Recent Changes - Search:
ECG Home

GitHub

People

Publications

Calendar

Projects

Fall 2017

Older Courses

Spring 2017

Fall 2016

Spring 2016

Fall 2015

Spring 2015

Fall 2014

Spring 2014

Fall 2013

Spring 2013

Fall 2012

Spring 2012

Fall 2011

Spring 2011

Fall 2010

Spring 2010

Fall 2009

Spring 2009

Fall 2008

Spring 2008

Fall 2007

HOWTOs

edit SideBar

more docs: Attach:DanielGabriel-iSENSE-Dashboard-docs.pdf

Dashboard

In this section I will describe in general how each part of the Dashboard works and how each part of the Dashboard interacts with each other part. For specifics, please refer to the Java class files. The files are either documented or are fairly straightforward. With this documentation and the documentation in the code, one should be able to fully understand how the Dashboard works.

First of all, major Dashboard classes all fall directly within the iSENSE/dashboard directory. Other utility classes, which have sufficient documentation in code, can be found in the subdirectories. The Dashboard has six main classes which are organized as follows.

The Model is the main wrapper for the Dashboard. It instantiates each of the other classes and begins program execution. However, as an embedded applet, the AppletBooter class acts as a wrapper around the Model. The DispatchThread pulls in data from the sensors and distributes them to the Controller and the View. The View takes that data and displays it for the user. If the user has hit the record button, the Controller will take that data and pass it to the TransmitThread to send to the server. The diagram below illustrates the relationship between these major classes.

The classes described above are on the userís computer. The Server may be a different machine. The sensors are physical devices attached to the userís computer via USB, for example. As you can see, data are brought in from the sensors to the DispatchThread. From there, the View and Controller each get a copy of the data and if the Dashboard is recording, data are given to the TransmitThread to be sent to the Server.



Now I will discuss how each of these major classes works in more detail. First, the AppletBooter class extends the Applet class. As an Applet, it begins execution by calling the init() method. This method then pulls in the cookie data from the userís browser and creates a new token based on that information. It then gives that token to the Model for later use.

As an Applet, the Model is created when the setCookieData() method is called. The Model creates the Controller, DispatchThread, and the View when it is constructed. At that point, the Model does not do work until the user continues program flow through the View. For example, when the main Dashboard window is created, the DispatchThread is started and the TransmitThread is both created and started.

The Controller keeps track of the internal representation of the data collected by the user. It holds an instance of Client, a list of experiments, a list of fields, and the most recently read in values, among other things. This class has a variety of methods which are used during execution. For more information on those, please see the in code documentation. When the Controller is set to record, it will give the current data it has collected to the TransmitThread to be sent to the Server.

The TransmitThread is a Java Thread that makes use of synchronized methods to ensure data are not lost. It will attempt to send the collected data to the Server as quickly as possible. When it cannot send all the data points it has collected, it will send them in groups of one hundred. The synchronized keywords used in the definition of the addData() and chopList() methods act as a semaphore to control access to the access to the StampedValueList that is the collection data. The DispatchThread has two main responsibilities. The first is that it discovers all available sensors and adds them to a list of available sensors. It does this when it is created, at the creation of the Model class. Its second responsibility is to take in readings from the sensors and relay that information to the Controller and the View. After it calls the getReading() method of each sensor, the DispatchThread calls the Modelís updateData() methods. This instructs the Controller and View to ask the DispatchThread to visit them (per the Visitor Pattern).

The View is the graphical user interface to the Dashboard. The class View itself instantiates the other classes found in iSENSE/dashboard/gui and provides methods to switch between them. Although more information can be found in the in code documentation, an example is the switchToMainWindow() method. This method will hide the wizard and will create a new instance of the main DashboardWindow. It will then start the two threads used in execution.

Serial-Dashboard Interaction



Depicted above is how the serial port interfaces and the crickets interact with the dashboard. To begin, when the dashboard is instantiated it will first create an instance of CRKComm, which it will then use as an argument to SPIís constructor. The purpose of passing the instance of CRKComm is so that SPI can use CRKCommís low-level serial methods in order to establish and maintain a connection to a Cricket via a serial port. When SPI is created it will obtain a listing of all the available serial port on the userís computer. Next, the cricket auto-detection is performed. The auto-detection iterates through the list of available serial ports searching for a path and port that contains a particular substring with which the USB IR-Transceivers are typically associated with. Once such a port is found, it is opened and the CRKCommís enableCrickets method is invoked in hopes of establishing a connection with a Cricket. If the enableCrickets fails, then no Cricket was found. The opened serial port is then closed and the next port is opened. If a Cricket responds to the enableCrickets call, then the method returns successfully and the current serial port is used for communication to that particular cricket.

Following a successful Cricket auto-detection, the DispatchThread then creates six CricketSensors. The CricketSensor class implements the Sensor interface. The CricketSensor takes the instance of CRKComm as well as a sensor ID as parameters. Based on which sensor ID is passed to the constructor, the Cricket is then programmed with the appropriate pre-complied byte sequence which will return a value from the desired sensor. Interestingly enough, the byte sequences for sensors A and B vastly differ from the byte sequences for sensors C through F. The following is example byte code that is used to acquire values from sensors A and C, respectively.

Byte-code sequence for sensors A and B:
55	;select sensor A
67	;send value via fast send 
0	;end program

Byte-code sequence for sensors C through F:
0x02 0x01 0x12    	; push $112 onto stack
0x3D              	; bsend
0x01 0x00         	; push 0 (sensorc) onto stack
0x3E              	; bsr.  this will get high byte of
          	  	; sensor value and leave it on stack
0x02 0x01 0x00    	; push 256 onto stack
0x19             	; multiply high byte to make it a high byte
0x01 0x00         	; send dummy arg of 0 to get low byte
0x3E              	; bsr it. low byte of sensor value is on stack
0x17              	; add them -- that's the answer.
0x43             	; send
0x00              	; end of code

Also, note that each of these procedures are stored in the Cricketís external EEPROM in the 4080 bytes of user data ranging from 0x000 to 0xFEF. They are also stored in a manner that prevents them from being overwritten by each other. In addition to program the devices, the CricketSensor class is also responsible for running the downloaded procedures. The procedures downloaded to a Cricket when the DispatchThread is created remain in the Cricketís memory until they have been overwritten with other data. Therefore, the procedures are only loaded onto the cricket each time the Dashboard initializes in case the Cricket has been used for something else in the meantime. Lastly, the CricketSensor class is responsible for providing string descriptions of the sensors.

Next, the CricketTemperatureSensor class, like the CricketSensor class, implements the Sensor interface. The purpose of this class is to provide cricket temperature sensor readings in degrees Celsius as opposed to the raw cricket reading. When sensors are bound to the data streams in the Wizard, if a sensor measures temperature and is on a Cricket, this class is instantiated. Since the class implements the Sensor class, it must implement at least all the methods that the Sensor class provides. More importantly, the getReading method is implemented where instead of returning the raw cricket reading, it returns the correctly calibrated reading. Furthermore, the calibrated reading is determined by plugging the raw cricket value into the following equation,

Degrees Celsius = 0.00142 * raw_value ^ 2 Ė 0.696 * raw_value + 88.5. (This formula was developed by John R. Morgan for Prof. Alex Ballantine, July 2005.)

Finally, the DispatchThread enters the run method where it collects data from sensors. The method iterates through a list of sensors according to user selected sample rate and interrogates the sensor for a reading. This is where all the abstraction becomes important. The DispatchThread can simply ask for a sensor reading regardless of what kind of sensor it may be requesting from. The request will traverse the various layers of abstraction and invoke the proper method such that accurate data is returned to the DispatchThread whereby it is then sent to the Controller and View in order to be sent off to the server containing the database and to be updated in the dashboard GUI, respectively.

Edit - History - Print - Recent Changes - Search
Page last modified on May 20, 2008, at 09:06 PM