Successfully reported this slideshow.

AirSensEUR: AirQuality monitoring open framework technical presentation

5

Share

1 of 154
1 of 154

AirSensEUR: AirQuality monitoring open framework technical presentation

5

Share

Download to read offline

AirSensEUR is an open framework focused on air quality monitoring using low cost sensors. The project started on 2014 from a group of passionate researchers and engineers. The framework is composed by a set of electronic boards, firmware, and several software applications. The slides present the technical solutions adopted in the framework by entering on hardware and software related details. For more info, look at the project website www.airsenseur.org

AirSensEUR is an open framework focused on air quality monitoring using low cost sensors. The project started on 2014 from a group of passionate researchers and engineers. The framework is composed by a set of electronic boards, firmware, and several software applications. The slides present the technical solutions adopted in the framework by entering on hardware and software related details. For more info, look at the project website www.airsenseur.org

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

AirSensEUR: AirQuality monitoring open framework technical presentation

  1. 1. AirSenSeurAirSenSeur AirAir qualityquality monitoring open frameworkmonitoring open framework Technical presentationTechnical presentation Marco Signorini – Liberaintentio S.r.l.
  2. 2. January 2016 2 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  3. 3. January 2016 3 AirSensEUR System OverviewAirSensEUR System Overview  Composed by two different actors: “Shield” and “Host”  The Shield is targeted to interface to physical sensors  The Host is in charge of retrieve data from the shield, aggregate with time and positioning information, store locally and periodically push the overall samples to an external server  Shield and Host are linked together by a serial line  Hardware references and software sources released under public licences (www.airsenseur.org)
  4. 4. January 2016 4 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  5. 5. January 2016 5 Shield HardwareShield Hardware  ATMega328 with optiboot installed (Arduino UNO compatible)  Four independent Programmable Analog Front Ends (AFE) for two and three leads chemical sensors  Four 16bits high precision Analog to Digital converters  Four indepentent 4 channels 12bits high precision Digital to Analog converters for onboard reference signals synthesis  I2C digital temperature, pressure and humidity sensors  Opto-coupled USB interface for optional PC connection  Low noise linear power supply regulators onboard
  6. 6. January 2016 6 Shield HardwareShield Hardware AFE A/D D/As AFE A/D D/As AFE A/D D/As AFE A/D D/As Chemical sensors analog front end and data acquisition blocks ATMega328 uController T and %RH Pressure I2C sensor board Local Power Supply and level shifters Chemical Sensors Power Supply +6V DC TTL serial To host Arduino USB2Serial adapter connector Vin- Vad Vafe Vout
  7. 7. January 2016 7 Shield Hardware (single channel)Shield Hardware (single channel) I2C Programmable AFE (current to voltage conversion) Analog to Digital conversion through SPI I2C Digital to Analog Generates voltage references Compatibility with multiple sensor brands
  8. 8. January 2016 8 Shield Hardware (AFE)Shield Hardware (AFE)  Texas Instruments LMP91000 Configurable Potentiostat  Connected via I2C  Generates a voltage proportional to the chemical sensor cell current  Fully programmable (bias, internal zero reference, load, gain)  Supports internal or external voltage references (Vafe)
  9. 9. January 2016 9 Shield Hardware (ADC)Shield Hardware (ADC)  Texas Instruments ADC161S626 16bit, 50 to 250kSPS  Connected via SPI  External voltage reference (Vad) range of +0.5V to 5V  True differential input: allows to inject external zero reference (Vn-)
  10. 10. January 2016 10 Shield Hardware (DAC)Shield Hardware (DAC)  Analog Devices AD5694R quad channels 12bit DAC  Connected via I2C  Very low drift (2ppm/C) internal voltage reference  Selectable gain for 0 to 2.5V or 0 to 5V full scale output  Used to generate references for − Analog Front End (Vafe) − Analog to Digital negative reference (Vn-) − Analog to Digital full scale reference (Va)
  11. 11. January 2016 11 Shield Hardware (THP and supply)Shield Hardware (THP and supply) Factory calibrated I2C Humidity and Temperature sensor Factory calibrated I2C Pressure sensor Linear 5V regulator
  12. 12. January 2016 12 Shield Hardware (THP and supply)Shield Hardware (THP and supply)  TecnoSens UR100CD Temperature and Humidity sensor − Calibration factory parameters stored into embedded EEPROM − Connected via I2C  Bosh BMP180 Pressure sensor − Fully calibrated MEMS sensor − Connected via I2C  Linear Voltage regulator − Provides 5V from 6-10V external power supply
  13. 13. January 2016 13 Shield Hardware (ATMega328)Shield Hardware (ATMega328) ATMega 328 Running at 16MHz Arduino(tm) USB2Serial connector onboard Programmable LED onboard
  14. 14. January 2016 14 Shield Hardware (ATMega328)Shield Hardware (ATMega328)  Connected to ADC via SPI and four dedicated chip select lines  Connected to AFE via I2C  Connected to DAC via I2C and four dedicated gain selection lines  Connected to THP sensors via I2C  Serial line shared with external programmer and host  Programmable LED on digital line (shared)  Optional external serial RAM via SPI and shared chip select line
  15. 15. January 2016 15 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  16. 16. January 2016 16 Shield FirmwareShield Firmware  Arduino IDE 1.6.5 compatible  Implemented mainly in C++  .INO file wrapper for C++ root object instance  Initializes peripherals and sensors  Handles serial communication protocol  Samples sensors  Performs filtering and average calculations  Generates timestamps for outgoing samples
  17. 17. January 2016 17 Shield Firmware (Data Flow)Shield Firmware (Data Flow) IIR IIR Decimation Filter Averager Sampler Period (Fs) Coefficient Coefficient Ratio Length Buffer Timer Timestamp LastSample Sensor Fs Fs Fs Fs/Ratio Fs/(Ratio*Length)
  18. 18. January 2016 18 Shield Firmware (.INO wrapper)Shield Firmware (.INO wrapper)  Is the main entry point for the Arduino framework  Two functions: init and loop  References two external C functions where all the magic is performed by C++ code. “_impl” functions are implemented in ChemSensorBoardImpl.cpp extern void setup_impl(); extern void loop_impl(); void setup() { setup_impl(); } void loop() { loop_impl(); }
  19. 19. January 2016 19 Shield Firmware (setup_impl)Shield Firmware (setup_impl)  Initializes the hardware and the software data structures  Initializes the timer and registers a callback void setup_impl() { // Initialize the heartbeat pin pinMode(HBLEDPIN, OUTPUT); digitalWrite(HBLEDPIN, LOW); hbTimer = 0; // Initialize the serial line Serial.begin(9600); // Instantiate the main objects sensorBoard = new SensorsArray(); commProtocol = new CommProtocol(sensorBoard); // Initialize the timer at 10ms Timer1.initialize(10000); Timer1.attachInterrupt(timerInterrupt); }
  20. 20. January 2016 20 Shield Firmware (loop_impl)Shield Firmware (loop_impl)  Calls the main sensorBoard loop, handles heartbeat and the serial line void loop_impl() { // Propagate to the sensor array bool newSample = sensorBoard->loop(); // Heartbeat led if (newSample && (hbTimer == 0)) { hbTimer = HBLED_NEWSAMPLE_TMR; } // Handle the serial line if (Serial.available()) { unsigned char val = Serial.read(); commProtocol->onDataReceived(val); } }
  21. 21. January 2016 21 Shield Firmware (timer callback)Shield Firmware (timer callback)  Propagate timing callback to the main objects, handles the heartbeat LED void timerInterrupt() { if (sensorBoard) { sensorBoard->timerTick(); } if (commProtocol) { commProtocol->timerTick(); } // Heartbeat led if (hbTimer != 0) { hbTimer--; digitalWrite(HBLEDPIN, HIGH); } else { digitalWrite(HBLEDPIN, LOW); } }
  22. 22. January 2016 22 Shield Firmware (global objects)Shield Firmware (global objects)  Two global objects are instantiated in the setup_impl function: SensorsArray* sensorBoard; CommProtocol* commProtocol; SensorsArray is the main entry point for all sensors management and samples retrieval. It's implemented in SensorsArray.cpp file CommProtocol is responsible for handling serial data communications with the host. It's implemented in CommProtocol.cpp file. It receives a SensorArray reference so it's able to interact with it.
  23. 23. January 2016 23 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)  OnDataReceived handles the communications with the Host  timerTick should be called periodically to properly handle protocol timeouts  Valid commands are wrapped by a specific private callback class CommProtocol { public: CommProtocol(SensorsArray *sensors); void timerTick(); void onDataReceived(unsigned char pivotChar); private: void reset(); void processBuffer(); static bool sampleEnable(...); static bool sampleDisable(...);
  24. 24. January 2016 24 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) typedef struct _commandinfo { unsigned char commandID; unsigned char parNum; bool (*handler)(CommProtocol* context, unsigned char cmdOffset); } commandinfo; private: static const commandinfo validCommands[];  Each valid command is associated to a callback function and the number of expected parameters  A list of valid commands is statically defined and stored in the FLASH memory
  25. 25. January 2016 25 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) typedef enum _rxstatus { RX_IDLE, RX_HEADER_FOUND } rxstatus; private: unsigned char buffer[COMMPROTOCOL_BUFFER_LENGTH]; unsigned char offset; rxstatus rxStatus;  The internal state machine is based on two possible statues: “waiting for a valid header” and “header found” (i.e. Idle or running)  Incoming data are stored on a RAM buffer at the “offset” position. Offset is changed on each incoming data
  26. 26. January 2016 26 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) void CommProtocol::onDataReceived(unsigned char pivotChar) { switch (rxStatus) { case RX_IDLE: { // Searching for an header ... } break; case RX_HEADER_FOUND: { // Searching for a trailer if(pivotChar == COMMPROTOCOL_TRAILER) { ProcessBuffer(); ... } break; } }  onDataReceived is responsible for data framing and processing
  27. 27. January 2016 27 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) void CommProtocol::processBuffer() { // .. we expect the command ID, validate it ... // Execute the action typedef bool (*fpointer)(CommProtocol* context, unsigned char cmdOffset); fpointer handler = &(validCommands[offsetId].handler); if (valid && handler != 0) { valid = (*handler)(this, offsetId); } // Signal an invalid/fault condition if (!valid) { strcpy_P((char*)buffer, commProtocolErrorString); } // Send back the result Serial.print((char*)buffer);  ProcessBuffer calls the proper callback and send back results
  28. 28. January 2016 28 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) bool CommProtocol::setSampleDecimation(CommProtocol* context, unsigned char cmdOffset) { unsigned char channel = context->getParameter(0); unsigned char decimation = context->getParameter(1); if (context->sensorsArray- >setSampleDecimation(channel, decimation)) { return context->renderOKAnswer(cmdOffset, channel); } return false; }  Command handler example: no dynamic answer to the host
  29. 29. January 2016 29 Shield Firmware (CommProtocol)Shield Firmware (CommProtocol) bool CommProtocol::getSampleDecimation(CommProtocol* context, unsigned char cmdOffset) { unsigned char channel = context->getParameter(0); unsigned char decimation; if (!context->sensorsArray->getSampleDecimation(channel, &decimation)) { return false; } context->buffer[0] = COMMPROTOCOL_HEADER; context->buffer[1] = validCommands[cmdOffset].commandID; context->buffer[2] = 0; context->writeValue(channel, false); context->writeValue(decimation, true); return true; }  Command handler example: dynamic result sent to the host
  30. 30. January 2016 30 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)  Is the “container” of all sensor implementation objects and related data averagers and FIRs  Provides a type-unaware interface for all sensor channels  Orchestrates the sampling process for all sensors through a pair of functions: loop and timerTick.
  31. 31. January 2016 31 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray) class SensorsArray { ... private: static const LMP91000 AFEList[NUM_OF_CHEM_SENSORS]; static const ADC16S626 ADCList[NUM_OF_CHEM_SENSORS]; static const AD5694R DACList[NUM_OF_CHEM_SENSORS]; static UR100CD ur100cd; static SFE_BMP180 bmp180; static DitherTool ditherTool; Sampler* samplers[NUM_OF_TOTAL_SENSORS]; SamplesAverager* averagers[NUM_OF_TOTAL_SENSORS]; ... };  Sensors implementations are statically defined and allocated in FLASH area, when possible
  32. 32. January 2016 32 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray) class SensorsArray { ... public: unsigned char setSamplePrescaler(...); bool getSamplePrescaler(...); unsigned char setSamplePostscaler(...); bool getSamplePostscaler(...); bool getLastSample(...); bool writeDACRegisters(...); bool readDACRegisters(...); ... };  Provides type-unaware interface for all sensor channels
  33. 33. January 2016 33 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray) class SensorsArray { public: SensorsArray(); virtual ~SensorsArray(); Public: bool timerTick(); bool loop(); ... };  Implements the entry point functions to be called periodically by the main loop and timer
  34. 34. January 2016 34 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)  The constructor is responsible for: − Initialize the internal coefficients for the pressure sensor − Initialize the samplers and averagers arrays − Allocate and initialize the sampler units − Allocate the data averagers − Link averagers with the dithering tool − Initialize DACs − Load preset stored on the EEPROM
  35. 35. January 2016 35 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)  The timerTick function propagates the event to all samplers  Samplers with unread samples shall return true; false otherwise bool SensorsArray::timerTick() { bool result = false; // Loop on each sensor samplers for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { result |= samplers[n]->sampleTick(); } } // Increase the internal timestamp timestamp++; return result; }
  36. 36. January 2016 36 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)  The timerTick function propagates the event to all samplers  Samplers with unread samples shall return true; false otherwise bool SensorsArray::loop() { ... bool result = false; for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { if (samplers[n]->sampleLoop()) { // A new sample is ready to be averaged result |= averagers[n]- >collectSample(samplers[n]->getLastSample(), timestamp); }; } } return result; }
  37. 37. January 2016 37 Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)  The loop function propagates the event to all samplers. When a new sample is available, it propagates to the proper averager. bool SensorsArray::loop() { // If sampling is disabled, skip this function if (!samplingEnabled) return false; // Otherwise loop on each sensor sampler and averager bool result = false; for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { if (samplers[n]->sampleLoop()) { // A new sample is ready to be averaged result|=averagers[n]->collectSample(samplers[n]->get LastSample(), timestamp); }; } } return result; }
  38. 38. January 2016 38 Shield Firmware (Sampler)Shield Firmware (Sampler)  Sampler is an abstract class and is the base class for other specialized sampler units  Implements common sampler funcionalities: prescaler, IIR and decimation filter.  It contains a reference to a singleton DitherTool used by IIR to reduce the data DC offset introduced by rouding math  Two functions needs to be implemented by specialized classes: − sampleTick() − sampleLoop()
  39. 39. January 2016 39 Shield Firmware (Samplers hierarchy)Shield Firmware (Samplers hierarchy) SamplerSampler ChemSensorSamplerChemSensorSampler HumSensorSamplerHumSensorSampler PressSensorSamplerPressSensorSampler TempSensorSamplerTempSensorSampler
  40. 40. January 2016 40 Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)  Two functions needs to be implemented by specialized classes: − sampleTick() − SampleLoop()  Specialized classes dialogate with the hardware through a set of objects providing low level hardware abstraction. Those objects are allocated by the SensorsArray constructor and linked to the specialized object at construction time.
  41. 41. January 2016 41 Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)  The sampleTick function defines the sampling time by comparing an internal counter to a prescaler value.  Time for sampling is signalled by setting the “go” variable to true bool ChemSensorSampler::sampleTick() { if (timer == prescaler) { // It's time for a new sample timer = 0; go = true; return true; } timer++; return false; }
  42. 42. January 2016 42 Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)  The sampleLoop function reads a new sample from the sensor (sensor.getSample) then calls the onReadSample function.  The sampleLoop is responsible for applying IIR and decimation filters bool ChemSensorSampler::sampleLoop() { // Take the new sample if (go) { onReadSample(sensor.getSample()); go = false; // Filter with two cascade single pole IIRs applyIIRFilter(IIR1); applyIIRFilter(IIR2); // Apply the decimation filter return applyDecimationFilter(); } return false; }
  43. 43. January 2016 43 Shield Firmware (Sampler)Shield Firmware (Sampler)  The applyIIRFilter calculates the IIR filter from samples stored on workSample.  The result is stored on workSample. This allows multiple calls of the same function when multiple poles are required void Sampler::applyIIRFilter(unsigned char iiRID) { unsigned char *denom = iIRDenum + iiRID; // The filter is disabled if denominator == 0 if (*denom == 0) return; double* S = iIRAccumulator + iiRID; // S(n) = S(n-1) + 1/den * (I(n) - S(n-1)) *S = *S + ((double)workSample - *S)/(*denom); workSample = (unsigned short)(ditherTool->applyDithering(*S)); }
  44. 44. January 2016 44 Shield Firmware (Sampler)Shield Firmware (Sampler)  The applyDecimationFilter skips samples based on the decimation parameter.  It returns true each “decimation” samples so the calling procedure could evaluate it. bool Sampler::applyDecimationFilter() { if (decimationTimer == decimation) { decimationTimer = 0; lastSample = workSample; } else { decimationTimer++; } return ((decimationTimer == 0) || (blankTimer != 0)); }
  45. 45. January 2016 45 Shield Firmware (SamplesAverager)Shield Firmware (SamplesAverager)  Implements the last filter in the chain: average  Historical samples are stored in a dynamically allocated array so it's possible to change the buffer's deep at runtime  Averaged results are released at 1/buffersize rate  Fast implementation. The most important funcion is collectSample  Dithering is used to prevent DC insertion due to round floats and limited C toolchain float support
  46. 46. January 2016 46 Shield Firmware (SamplesAverager)Shield Firmware (SamplesAverager)  The collectSample function uses an accumulator to count the average  The oldest sample is removed by the accumulator and the newest is added  The result is divided by buffer size and dithered bool SamplesAverager::collectSample(unsigned short sample, unsigned long _timestamp) { ... accumulator = accumulator - dataBuffer[sampleOffset]; accumulator = accumulator + sample; dataBuffer[sampleOffset] = sample; sampleOffset++; lastAverageSample=ditherTool->applyDithering(accumulator/bSize); }
  47. 47. January 2016 47 Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)  Samplers and SensorsArray use specific class drivers to dialogate with hardware  Driver classes hide the low level details for handshaking I/O lines and connecting onboard peripherals  Driver classes increase software modularity and code reuse  Driver classes implementation details are strictly based on target devices datasheet
  48. 48. January 2016 48 Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)  Several driver classes are provided in the firmware. Each class targets a specific device. LMP91000LMP91000 ADC16S626ADC16S626 AD5694RAD5694R UR100CDUR100CD SFE_BMP180SFE_BMP180
  49. 49. January 2016 49 Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)  Driver classes are mainly statically allocated by the SensorsArray class and passed to Samplers via constructors const LMP91000 SensorsArray::AFEList[NUM_OF_CHEM_SENSORS] = ... const ADC16S626 SensorsArray::ADCList[NUM_OF_CHEM_SENSORS] = ... const AD5694R SensorsArray::DACList[NUM_OF_CHEM_SENSORS] = ... UR100CD SensorsArray::ur100cd = UR100CD(); SFE_BMP180 SensorsArray::bmp180 = SFE_BMP180(); SensorsArray::SensorsArray() { // Initialize the sampler units samplers[CHEMSEN1]= new ChemSensorSampler(ADCList[CHEMSEN1]); samplers[CHEMSEN2]= new ChemSensorSampler(ADCList[CHEMSEN2]); ... samplers[TEMPSEN] = new TempSensorSampler(ur100cd); samplers[PRESSEN1] = new PressSensorSampler(bmp180); ...
  50. 50. January 2016 50 Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)  A simple driver class example is provided by ADC16S626 A/D converter connected to the microcontroller via an SPI and a chip select line class ADC16S626 { public: ADC16S626(const unsigned char csPin); virtual ~ADC16S626(); unsigned short getSample() const; private: unsigned short toLinear(unsigned short twoComplSample) const; private: const unsigned char m_csPin; };
  51. 51. January 2016 51 Shield Firmware (Driver Classes)Shield Firmware (Driver Classes) unsigned short ADC16S626::getSample() const { byte inByteHigh, inByteMid, inByteLow; digitalWrite(m_csPin, LOW); inByteHigh = SPI.transfer(0x00); inByteMid = SPI.transfer(0x00); inByteLow = SPI.transfer(0x00); digitalWrite(m_csPin, HIGH); unsigned short result = ((inByteLow >> 6) & 0x03); result |= (((unsigned short)inByteMid) << 2); result |= (((unsigned short)inByteHigh) << 10); result = toLinear(result); return result; }
  52. 52. January 2016 52 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  53. 53. January 2016 53 Java Panel ApplicationJava Panel Application  Targeted to run on an PC connected to the AirSensEUR Shield via RS232 to USB opto-coupled interface  Developed for debug purposes but elected by usage as main console for initial AirSensEUR set-up and configuration tool  Java based: runs on any PC and/or MAC with installed JRE (Java Runtime Environment)  NetBeans project files available  It's not perfect... a lot of improvements should be done... so think to it as a working progress project
  54. 54. January 2016 54 Java Panel ApplicationJava Panel Application  Depends on jna and purejavacomm libraries. They provides direct access to the USB/serial line interface from the JVM  Depends on AirSensEURLib project, mainly for .comm and .exceptions packages shared with other AirSensEUR Host applications (see later)
  55. 55. January 2016 55 Java Panel Application (Communcation Layer)Java Panel Application (Communcation Layer)  ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield  ChemSensorCommHandler implements ChemSensorBoard with the help of SerialPortHelper and CommProtocolHelper classes ChemSensorBoardChemSensorBoard ChemSensorCommHandle r ChemSensorCommHandle r CommProtocolHelperCommProtocolHelper SerialPortHelperSerialPortHelper AirSensEURLib
  56. 56. January 2016 56 AirSensEURLib (SerialPortHelper)AirSensEURLib (SerialPortHelper)  The SerialPortHelper class provides a connection layer between purejavacomm library and AirSensEUR applications  Is used to enumerate available serial interfaces  Is used to open/close a known serial interface and to read/write characters from/to it  It implements the SerialPortEventListener.serialEvent defined in the purejavacomm library. This is called each time the serial line receives data from the AirSensEUR Shield  It defines a SerialReceiverParser.onDataReceived callback interface. This should be implemented by data consumers.
  57. 57. January 2016 57 AirSensEURLib (SerialPortHelper)AirSensEURLib (SerialPortHelper) public static interface SerialReceiverParser { void onDataReceived(InputStream inputStream); } private class SerialReceiverListener implements SerialPortEventListener { @Override public void serialEvent(SerialPortEvent event) { if(event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { if (inputStream.available() != 0) { rxDataParser.onDataReceived(inputStream); } } } }
  58. 58. January 2016 58 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  The CommProtocolHelper class implements the protocol engine for connecting to the AirSensEUR Shield via a list of logical DataMessage(s)  Defines the DataMessage class used to encapsulate high level commands sent and received by the overlying application  Translates DataMessage instances to/from data stream to be sent/received via serial line  The CommProtocolHelper encapsulates low level AirSensEUR Shield protocol details providing high level function calls for the Java applications
  59. 59. January 2016 59 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  Three set of methods are provided: − “render” methods − “eval” methods − “data list” methods
  60. 60. January 2016 60 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  “render” methods are used by the application to “send” commands to the AirSensEUR Shield void renderSamplerPrescaler(int channelId, int prescaler); void renderSamplerPrescalerRead(int channelId); public void renderSensorInquiry(int channelId); public void renderGetLastSample(int channelId); public void renderStartSample() public void renderStopSample()
  61. 61. January 2016 61 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  “eval” methods are used by the application to “receive and parse” answers coming from the AirSensEUR Shield.  “eval” methods automatically detect contents present on received DataMessage and return “null” for a not matching condition. This allows for multiple safe and distributed evaluations of the same DataMessage. Integer evalPrescalerInquiry(DataMessage rxMessage, int channel) Integer evalDecimationInquiry(DataMessage rxMessage, int channel) String evalSensorInquiry(DataMessage rxMessage, int channel) List<Integer> evalLastSampleInquiry(DataMessage rxMessage, int channel)
  62. 62. January 2016 62 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  “data list” methods are used to access to internal messaging datastructure in order to push/pop commands/answers public synchronized void clearCurrentCommandList() public synchronized List<DataMessage> getSafeCurrentCommandList() public synchronized DataMessage getNextRxDataMessage()
  63. 63. January 2016 63 AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)  The conversion between incoming data from AirSensEUR Shield and DataList items is performed by the function onRxDataReceived  This function should be called by the SerialPortHelper::SerialReceiverParser implementor // This is the main rx state machine. It aggregates all incoming // data and populates the fromBoard list as a FIFO buffer // containing all the received messages synchronized public boolean onRxCharReceived(byte value)
  64. 64. January 2016 64 AirSensEURLib (ChemSensorBoard)AirSensEURLib (ChemSensorBoard)  ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield public interface ChemSensorBoard { public void connectToBoard(CommPortIdentifier serialPort); public void disConnectFromBoard(); public void writeBufferToBoard(); public List<CommProtocolHelper.DataMessage> getCurrentBuffer(); }
  65. 65. January 2016 65 Java Panel ApplicationJava Panel Application (ChemSensorCommHandler)(ChemSensorCommHandler)  ChemSensorCommHandler implements the ChemSensorBoard interface  It contains a SerialPortHelper instance to perform actions through the serial port  It implements the SerialPortHelper.SerialReceiverParser interface by calling the CommProtocolHelper.onRxCharReceived when needed  Allows to the Java application to access to DataMessage Lists and to flush pending commands through the serial line
  66. 66. January 2016 66 Java Panel Application (Dialogs and Panels)Java Panel Application (Dialogs and Panels)  The Java Panel application is implemented using the Swing GUI framework  Swing defines a set of graphical objects targeted to design portable graphic user applications  Graphical objects are grouped in Panels  Panels are grouped together to form Dialogs  AirSensEUR Java Panel Application defines a common class for sensor properties Dialogs. This is the SensorSetupDialog
  67. 67. January 2016 67 Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)  Provides a common interface for all setup dialogs  The interface contains all methods needed to dialogate with the AirSensEUR Shield through the CommProtocolHelper public class SensorSetupDialog extends javax.swing.JDialog { public SensorSetupDialog(java.awt.Frame parent, boolean modal) { super(parent, modal); } public void storeToBoard() { } public void readFromBoard() { } public void evaluateRxMessage(CommProtocolHelper.DataMessage msg) { } }
  68. 68. January 2016 68 Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)  storeToBoard is called by the application asking the setup dialog to dump their current settings to the CommProtocolHelper buffers (in order to be sent to the AirSensEUR Shield)  readFromBuffer is called by the application asking the setup dialog to fill the CommProtocolHelper with query commands for AirSensEUR Shield parameters retrieval  evaluateRxMessage is called by the application each time a new DataMessage has been received back by the AirSensEUR Shield. The dialog may use the coming DataMessage for update their panels status
  69. 69. January 2016 69 Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)  Two setup dialogs are derived from the SensorSetupDialog: − ChemSensorSetupDialog − GenericSensorSetupDialog
  70. 70. January 2016 70 Java Panel ApplicationJava Panel Application (ChemSensorSetupDialog)(ChemSensorSetupDialog) LMP9100PanelLMP9100Panel AD5694RPanelAD5694RPanel IIRAndAvgPanelIIRAndAvgPanel
  71. 71. January 2016 71 Java Panel ApplicationJava Panel Application (GenericSensorSetupDialog)(GenericSensorSetupDialog) IIRAndAvgPanelIIRAndAvgPanel  Each Dialog propagates to their panels the storeToBoard, readFromBoard, evaluateRxMessage events  Each panel is responsible for dump or updating their proper specific settings through a set of DataMessage
  72. 72. January 2016 72 Java Panel Application (setupPanel example)Java Panel Application (setupPanel example)  The simplest panel is the IIRAndAvgPanel
  73. 73. January 2016 73 Java Panel Application (Setup Panels)Java Panel Application (Setup Panels) IIRAndAvgPanelIIRAndAvgPanel  Items in the panel are implemented by a set of Swing widgets  Widget options are defined in Data Models  Data Models associate a “label” to be shown to the user with a “value” to be sento to the AirSensEUR Shield registers and viceversa
  74. 74. January 2016 74 Java Panel Application (Data Models)Java Panel Application (Data Models)  Two common typologies are needed: − Slider and Register Data Models
  75. 75. January 2016 75 Java Panel Application (SampleLogger)Java Panel Application (SampleLogger)  SampleLogger is a Swing JPanel derived class providing basic abastraction interface for entities able to manage set of samples  Defines the DataProcessing interface targeted to evaluate incoming samples through a set of mathematical expressions  Implements the DataProcessing interface by providing a standard two complements translation to be applied to AirSensEUR Shield four chemical channels data  Implements the common procedures needed to extract and detect new samples based on associated timestamp  Implements the readFromBoard and evaluateRxMessage common to all derived sample loggers
  76. 76. January 2016 76 Java Panel Application (SampleLogger)Java Panel Application (SampleLogger)  Two SampleLogger derived classes: − LineGraphSampleLoggerPanel − TextBasedSampleLoggerPanel
  77. 77. January 2016 77 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  78. 78. January 2016 78 Host HardwareHost Hardware  ARM9@400MHz based, 256MB RAM, running Debian Linux from a micro SD card  LiFePO4 Battery and/or USB/Wall adapter operated, with battery parameters available to the CPU through I2C  USB/wall power plugs protected by overvoltage and polarity reversal  Four independent step-up power supply, supervised by the CPU  Onboard USB sockets for WiFi and GPRS dongles  Onboard low power GPS module with 1PPS signal feed back to the CPU and optional high gain external antenna
  79. 79. January 2016 79 Host HardwareHost Hardware  I2C connected front panel with 8 programmable LEDs and 8 programmable pusbuttons  Expansion socket providing access to not yet used onboard peripherals (note: 3v3 operating only) like: − SPI − I2C − Low res A/D converter lines − Low res PWM lines
  80. 80. January 2016 80 Host HardwareHost Hardware Step up Power Supply 5V@1A LiFePO4 Battery ARM9 based module GPS moduleFront Panel Step up Power Supply 7V@300mA and level shifters Battery Manager +5VDC@3A SerialUSB Step up Power Supply 5V@1A Step up Power Supply 5V@1A Unregulated 3v3 line 5V line WiFi Dongle GPRS Dongle AirSensEUR Shield I2C USB
  81. 81. January 2016 81 Host Hardware (Battery Manager)Host Hardware (Battery Manager) LTC4156 I2C programmable LiFePO4 battery manager LTC2942 I2C Fuel Gauge Engine Active overvoltage and reverse polarity protection
  82. 82. January 2016 82 Host Hardware (Battery Manager)Host Hardware (Battery Manager)  Built as external module for easy replacement when targeting different battery techologies  Based on Linear Technology LTC4156 dual input, high efficient, I2C programmable LiFePO4 battery manager single chip solution  Inputs are protected from overvoltage and polarity reversal  Independent, programmable current limiters for USB and wall adapter lines  Instant-on operation with low battery; operation without battery installed is allowed  Embeds a Linear Technology LTC2942 I2C programmable fuel gauge with charge counter and voltage converter
  83. 83. January 2016 83 Host Hardware (Main Power Supply)Host Hardware (Main Power Supply) MAX8815 step up converter 5V up to 1A Power on and shutdown signals controlled by a PIC12 microcontroller
  84. 84. January 2016 84 Host Hardware (Main Power Supply)Host Hardware (Main Power Supply)  5V up to 1A are generated by a dedicated Maxim MAX8815A step up converter, independently by battery charge status  A PIC12F1571 microcontroller generates the proper power on/shutdown signals (wake and shutdown) based on user request on the Power On pushbutton  Shutdown signal is propagated to the CPU thus allowing a graceful Linux power off  Standard PIC brown out circuit detects low battery status and shuts down the system
  85. 85. January 2016 85 Host Hardware (Shield connection)Host Hardware (Shield connection) TTL to 3v3 bidirectional translators CPU controlled 7V@300mA Step Up Power supply
  86. 86. January 2016 86 Host Hardware (Main Power Supply)Host Hardware (Main Power Supply)  A Philips dual channels IC translator interfaces the TTL based serial line coming from the AirSensEUR Shield into a 3v3 lines and viceversa  The AirSensEUR Shield power supply is generated by the Host through a Microchip MCP1661 step up converter.  MCP1661 generates 7V with 300mA max current starting from the unregulated battery voltage.  An active switch, composed by Q3 and Q4, is used to completely shut off the 7V generation if required by the CPU
  87. 87. January 2016 87 Host Hardware (Dongles connection)Host Hardware (Dongles connection) USB host connectors For USB WiFi and GPRS MAX8815 step up converter 5V max 1A Control line from the CPU module
  88. 88. January 2016 88 Host Hardware (Dongles connection)Host Hardware (Dongles connection)  Two 5V up to 1A rails are generated by two dedicated Maxim MAX8815A step up converter, independently by battery charge status  Compatible to USB specifications (max 500mA for USB 1 and 2 and up to 900mA for USB3)  Step up converters can be turned on/off by a dedicated GPIO line in the CPU module
  89. 89. January 2016 89 Host Hardware (Front Panel)Host Hardware (Front Panel) PORTB used as input MCP23017 I2C 16 I/O programmable lines PORTA used as output
  90. 90. January 2016 90 Host Hardware (Front panel)Host Hardware (Front panel)  Based on Microchip MCP23017 I2C 16 bit programmable I/O expander  Supported by Linux driver kernels as a standard GPIO and LED devices  Two available input/output ports used, respectively, for LEDs and pushbuttons  The front panel implements other spare pushbuttons, like PowerOn and Reset, and 3DFix LED, via custom lines
  91. 91. January 2016 91 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  92. 92. January 2016 92 Host Linux CustomizationHost Linux Customization  The AirSensEUR Host runs a small Debian Linux distribution  Targeted to Debian Wheezy with kernel 4.2.6 for armel architecture  The AirSensEUR Host is an embedded system... no BIOS installed  To properly boot Linux, a suitable bootloader is needed. This is an open source bootloader provided by Atmel Corporation  Kernel and bootloader should be patched to target to the CPU module and to AirSensEUR framework  A 115200bps 8N1 serial debug port is available for reading boot logs and interact with a bare ASCII shell
  93. 93. January 2016 93 Host Linux Customization (Boot process)Host Linux Customization (Boot process) Three actors are involved: CPU, bootloader and Linux Kernel  The CPU scans for a well known places in order to find a “signed” binary acting as bootloader  The CPU loads the bootloader binary into an onchip RAM memory and starts running the bootloader  The bootloader initializes the onchip peripherals (timers, memory interface and so on) then loads the kernel image, from a well defined location, into the external RAM  The bootloader loads the kernel configuration image file from a well defined location  The bootloader uncompress the Linux kernel then starts run it
  94. 94. January 2016 94 Host Linux Customization (Boot process)Host Linux Customization (Boot process)  The kernel parses the binary configuration image and initializes the drivers embedded into the kernel image  The kernel “mounts” an external filesystem where other drivers are availables as “modules”  The kernel locates all the available driver modules, loads and configure them based on the binary configuration image details  The kernel starts the application services  The kernel runs the user defined initialization script
  95. 95. January 2016 95 Host Linux Customization (Boot process)Host Linux Customization (Boot process)  CPU: AT91SAM9G25 made by Atmel Corporation  CPU module: AriettaG25 made by Acme Systems Srl  Bootloader: at91bootstrap-3.7 (patched) compiled as boot.bin  Kernel: Linux kernel 4.2.6 (patched) − Kernel Image: zImage − Kernel binary configuration file tree: acme-arietta.dtb  Linux filesystem: Debian Wheezy generated with Multistrap  Kernel modules: located on /lib/modules/4.2.6+  User defined initialization script: bash script located at /etc/rc.local
  96. 96. January 2016 96 Host Linux Customization (CPU Boot process)Host Linux Customization (CPU Boot process)  AT91SAMG25 is not a “simple” CPU: is a SystemOnChip (SOC)  It embeds an ARM CPU core AND a lot of peripherals like: MMU, MMC, Timers, I/O, ADC, PWM, I2C, SPI, USB, Watchdog, and many other  It provides a very small ROM where a very basic program is stored and is run by the CPU at power on  The CPU scans a set of well known peripherals (USB, SPI, GPIO and MMC) in order to find a predefined byte pattern signature identifying a suitable bootloader.  AirSensEUR Host provides this bootloader in a boot.bin file located in the first partition of the microSD card. This partition should be formatted with a valid FAT16 filesystem
  97. 97. January 2016 97 Host Linux Customization (Bootloader)Host Linux Customization (Bootloader)  At91boostrap code is an open source bootloader provided by Atmel Corporation  It's targeted to a set of SOC made by Atmel and should be patched to target the AriettaG25 module  The bootloader initializes the basic peripherals (timer, watchdog, MMU) in order to allow access to the external RAM memory  The bootloader loads kernel and configuration images from the first partition of the microSD card, formatted with FAT filesystem, by pointing to the files zImage and acme-arietta.dtb  The bootloader deflates the Linux kernel image and jumps to the first kernel opcode
  98. 98. January 2016 98 Host Linux Customization (Kernel boot)Host Linux Customization (Kernel boot)  AirSensEUR Host runs a patched version of the Linux kernel 4.2.6  Patches are related to some missing/mismatching drivers (the battery manager IC, the I2C expander in the front panel and some minor changes in the CPU module)  The kernel parses the binary tree configuration file then starts configuring and executing the drivers found in the uncompressed zImage file  The kernel “mounts” the second partition found in the microSD where an EXT4 filesystem is populated with dynamically compiled driver modules  The kernel loads and configure the external driver modules
  99. 99. January 2016 99 Host Linux Customization (DTS and DTB)Host Linux Customization (DTS and DTB)  The Linux kernel is widely adopted in platform with different architecture, peripherals and options  When running on a PC, a set of enumeration and discovery systems have been provided. This is not true for an embedded system  The solution is to provide a standard configuration file where all configuration details are specified. This is performed by the Device Tree ASCII readable configuration file source (DTS) ASCII readable configuration file source (DTS) Binary parsable configuration file (DTB) Binary parsable configuration file (DTB)DTS CompilerDTS Compiler
  100. 100. January 2016 100 Host Linux Customization (DTS and DTB)Host Linux Customization (DTS and DTB)  The DTS is a “tree” where the hardware relationships and parameters are defined  Bus controllers are linked with bus connected devices  Bus connected devices are logically added to low level services and so on
  101. 101. January 2016 101 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  102. 102. January 2016 102 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  103. 103. January 2016 103 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  104. 104. January 2016 104 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  105. 105. January 2016 105 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  106. 106. January 2016 106 Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)
  107. 107. January 2016 107 Host Linux CustomizationHost Linux Customization (Hardware Abstraction)(Hardware Abstraction)  The Linux Kernel provides an “easy” way to map hardware subsystems into files descriptors.  AirSensEUR Host uses this feature to statically map I/O, serial lines, I2C subsystems into a well known set of file descriptors  High level applications and bash scripts can use those files to access to the hardware “like if” they're interacting with a file  That's one of the sucess keys of the Linux kernel! echo 1 > /sys/class/leds/led_1/brightness echo "Hello" > /dev/ttyS1 echo “ATDT123456” > /dev/ttyUSB2
  108. 108. January 2016 108 Host Linux CustomizationHost Linux Customization (Hardware Abstraction)(Hardware Abstraction) Subsystem Driver File Path Direct GPIO atmel-gpio /sys/class/gpio Direct GPIO leds-gpio /sys/class/leds I2C LEDs leds-gpio (gpio virtualized by gpio-mcp23s08 driver) /sys/class/leds Direct pushbuttons gpio-keys ./sys/class/input/event0 I2C pushbuttons gpo-keys-polled (gpio virtualized by gio-mcp23s08 driver) /sys/class/input/event1 I2C Battery manager ltc4156_charger /sys/class/power- supply/ltc4156-charger-0 I2C Battery Fuel Gauge ltc2941-battery-gauge /sys/class/power- supply/ltc2943-0  Step up converters, GPS power supply and PPS signals are treated as GPIO lines
  109. 109. January 2016 109 Host Linux Customization (rootfs)Host Linux Customization (rootfs)  The Linux kernel is only part of the game.  AirSensEUR Host applications runs over a Linux Debian Wheezy distribution  A Wheezy distribution can be easily obtained though Multistrap  Multistap allows defining a set of application packages to be included in the target file system, thus simplifying the Debian customization process  The target file system should be copied into the microSD second partition, formatted with an EXT4 filesystem, together with the AirSensEUR Host application binaries and shell scripts
  110. 110. January 2016 110 Host Linux Customization (middleware)Host Linux Customization (middleware)  Small programs running in background  Provides elementary functions needed to interface the hardware with high level applications  To be compiled from sources and copied on the target rootfs  Eventmonitor  rpi_gpio_ntp
  111. 111. January 2016 111 Host Linux Customization (Eventmonitor)Host Linux Customization (Eventmonitor)  Small C custom program for AirSensEUR Host  Listen to incoming pushbuttons event and executes the appropriate batch script  Batch script should be located into /etc/eventmonitor folder, should be named “hadler_xx” where xx is the event number associated to the pushbutton. Script should be marked as executable
  112. 112. January 2016 112 Host Linux Customization (rp_gpio_ntp)Host Linux Customization (rp_gpio_ntp)  Written by Folkert van Heusden and released under GPLv2  Works together with an NTP server running on the same platform  Analyzes a GPIO line where a PPS signal is connected and transfer information to the NTP server  Useful to implement a local precise NTP server when no network connectivity is present but GPS information is available
  113. 113. January 2016 113 Host Linux Customization (NTP Service)Host Linux Customization (NTP Service)  NTPd https://www.eecis.udel.edu/~mills/ntp/html/ntpd.html  Synchronizes the local real time clock with a set of sources  Sources can be defined via a configuration script  Contacts external NTP server when data network is ready  Interact with GPS local services when available
  114. 114. January 2016 114 Host Linux Customization (GPS Service)Host Linux Customization (GPS Service)  GPSd http://www.catb.org/gpsd/  Monitors the AirSensEUR Host GPS module connected through a serial line  Publishes JSON data through a local TCP socket on port 2947  Provides an abstraction layer between GPS module brands and protocols  Provides access to GPS data to multiple processes  Interacts with a local NTP server for (second based) precise local timestamp synchronization with GPS information
  115. 115. January 2016 115 Host Linux Customization (Hostapd)Host Linux Customization (Hostapd)  Hostapd is a user space daemon for access point and authentication servers (https://w1.fi/hostapd/)  It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and more  Licenced under the terms of BSD license. Implementred by Jouni Malinen  AirSensEUR Host requires Hostapd to provide a WiFi access point connection through a WiFi USB dongle.
  116. 116. January 2016 116 Host Linux Customization (WvDial)Host Linux Customization (WvDial)  WvDial https://github.com/wlach/wvdial  Is a command line ppp dialer  Easy to configure and use  Can be run by external batch scripts  AirSensEUR Host requires WvDial to handle GPRS ppp connections via a GPRS USB dongle
  117. 117. January 2016 117 Host Linux Customization (Lighttpd)Host Linux Customization (Lighttpd)  Lighttpd https://www.lighttpd.net/  Small footprint, efficient HTTP server  Easy to configure  Can provide CGI and integrate with interpreted languages, like PHP  AirSensEUR Host requires Lighttpd to provide a Web Console Management for easy setup and control
  118. 118. January 2016 118 Host Linux Customization (Many others)Host Linux Customization (Many others)  Many others services and middle layer applications are required by the AirSensEUR Host to properly operate  Some examples are: − Shell − Cron − Network tools − SSH Server − Java Runtime Environment − …  The whole services are downloaded and installed by Multistrap
  119. 119. January 2016 119 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  120. 120. January 2016 120 AirSensEUR Host ApplicationsAirSensEUR Host Applications Two categories BASH ScriptsBASH Scripts Java ApplicationsJava Applications
  121. 121. January 2016 121 Host Applications (Bash scripts)Host Applications (Bash scripts)  Mainly for very high level, very common, system related actions − Start/stop processes and services − Check processes and service status − Handle network interfaces − Handle LEDs and step up converter status  Fast and easy to implement and maintain  Mainly located in /usr/local/airsenseur
  122. 122. January 2016 122 Host Applications (Java Applications)Host Applications (Java Applications)  Targeted to data management  Connect to the AirSensEUR Shield and other data sources  Store collected data in a local sqlite database  Perform data transfer to external servers  Can benefit from the pletora of freely available and tested Java libraries  Developing Java is fast and the debug can be performed remotely through a TCP connection
  123. 123. January 2016 123 Host Applications (Java Applications)Host Applications (Java Applications) Three main Actors: Data Aggregator Data PushHost
  124. 124. January 2016 124 Host Applications (Java Applications)Host Applications (Java Applications) Data Aggregator Sqlite FileGPS Info AirSesEUR Shield GPSd Host/dev/ttyS1 /dev/ttyS2 JSONRPC TCP 8000 JSON TCP 2947
  125. 125. January 2016 125 Host Applications (Java Applications)Host Applications (Java Applications) Sqlite File Data Push JSON, XML, ...
  126. 126. January 2016 126 Host Applications (AirSensEURHost)Host Applications (AirSensEURHost)  Depends on jna and purejavacomm libraries. They provides direct access to the USB/serial line interface from the JVM  Depends on json rpc and jackson libraries  Depends on expr-master libraries providing mathematical expression evaluation  Depends on AirSensEURLib project, mainly for .comm, .json, .persisters and .exceptions packages
  127. 127. January 2016 127 AirSensEURHost (Communcation Layer)AirSensEURHost (Communcation Layer)  ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield  ChemSensorHostCommHandl er implements ChemSensorBoard with the help of SerialPortHelper and CommProtocolHelper classes ChemSensorBoardChemSensorBoard ChemSensorHostCommHandlerChemSensorHostCommHandler CommProtocolHelperCommProtocolHelper SerialPortHelperSerialPortHelper AirSensEURLib
  128. 128. January 2016 128 AirSensEURHostAirSensEURHost (ChemSensorHostCommHandler)(ChemSensorHostCommHandler)  ChemSensorHostCommHandler implements the ChemSensorBoard interface  It contains a SerialPortHelper instance to perform actions through the serial port  It implements the SerialPortHelper.SerialReceiverParser interface by calling the CommProtocolHelper.onRxCharReceived when needed  Defines a ChemSensorMessageHandler.onNewPacketReady callback function used to signal new valid packets received from the AirSensEUR Shield  It automatically connects and re-connects to the serial line if errors where detected on the received data
  129. 129. January 2016 129 AirSensEURHost (ChemSensorHost)AirSensEURHost (ChemSensorHost)  ChemSensorHost implements the ChemSensorMessageHandler interface and extends the Timer functionality  It periodically asks for new samples availability to the AirSensEUR Shield  Each sample received by the AirSensEUR Shield is evaluated and stored on a local buffer (implemented by the CollectedData internal class)  The collected data list contents is extracted by the ChemSensorServiceImpl class (explained later)
  130. 130. January 2016 130 AirSensEURHost (JSONServer)AirSensEURHost (JSONServer)  JSONServer is a wrapper class used to instantiate a JSON RPC server by mean of the jsonrpc4j library  Available procedures are defined by the ChemSensorService interface located on the AirSensEURLib library
  131. 131. January 2016 131 AirSensEURHost (ChemSensorServiceImpl)AirSensEURHost (ChemSensorServiceImpl)  ChemSensorService interface is implemented by ChemSensorServiceImpl class  Each method is called by the JSONServer engine  Data are sent back to the client through containers defined in AirSensEURLib library
  132. 132. January 2016 132 AirSensEURLib (SampleData)AirSensEURLib (SampleData)
  133. 133. January 2016 133 Host Applications (ASDataAggregator)Host Applications (ASDataAggregator)  Depends on json rpc and jackson libraries  Depends on sqlite4java and gpsd4java libraries  Depends on AirSensEURLib project, mainly for .comm, .json, .persisters and .exceptions packages  Depends on AirSensEURSqlLib project, where SQL helpers and containers are shared with other host applications
  134. 134. January 2016 134 AirSensEURDataAggregatorAirSensEURDataAggregator  AirSensEURDataAggregator aggregates information coming from multiple sources and store all together in a local sqlite database  Acts as a JSON client for the GPSd daemon  Acts ad a JSON client for the AirSensEURHost application  Uses local clock to timestamp all information inserted in the database  All aggregated information are stored as a single entry in the database table and, for convenience, on a .csv local file
  135. 135. January 2016 135 ASDataAggregator (ASDataAggregatorEngine)ASDataAggregator (ASDataAggregatorEngine)  AirSensEURDataAggregatorEngine.task() implements the whole actions. It's periodically called by the main routine EndEnd StartStart GPSDataCollector.poll()GPSDataCollector.poll() ChemSensorClient.getLastSampleChemSensorClient.getLastSample SamplePersisterFile.addSample()SamplePersisterFile.addSample() SamplePersisterSQL.addSample()SamplePersisterSQL.addSample()
  136. 136. January 2016 136 ASDataAggregator (GPSDataCollector)ASDataAggregator (GPSDataCollector)  GPSDataCollector is a wrapper class for the GPSEndpoint provided by the gpsd4java library  It connects to the GPSd server and retrieves JSON data  GPS information are temporarily stored to be used by the aggregator engine when required
  137. 137. January 2016 137 AirSensEURLib (ChemSensorClient)AirSensEURLib (ChemSensorClient)  ChemSensorClient is a wrapper for a ChemSensorService proxy implementation  Any call to a function by instances of ChemSensorClient generates an RPC to the server through a socket connection  RPC results are returned as a plain java object  Remote Procedure Calls details are completely hidden to calling methods
  138. 138. January 2016 138 AirSensEURLib (ChemSensorClient)AirSensEURLib (ChemSensorClient)
  139. 139. January 2016 139 AirSensEURLib (SampleData)AirSensEURLib (SampleData)
  140. 140. January 2016 140 AirSensEURLib (SamplesPersister)AirSensEURLib (SamplesPersister)  SamplesPersister is a public interface defining a set of functions common to an abstract entity providing persistance of sample datasets (SampleDataContainer)
  141. 141. January 2016 141 AirSensEURLib (SamplePersisterFile)AirSensEURLib (SamplePersisterFile)  SamplePersisterFile implements a SamplePersister interface by providing a comma separated values file persistence
  142. 142. January 2016 142 AirSensEURSqlLib (SamplePersisterSQL)AirSensEURSqlLib (SamplePersisterSQL)  SamplePersisterSQL implements a SamplePersister interface by providing persistence through sqlite database
  143. 143. January 2016 143 Host Applications (AirSensEURDataPush)Host Applications (AirSensEURDataPush)  Depends on sqlite4java, httpclient and jackson libraries  Depends on AirSensEURLib project, mainly for .comm, .json, .persisters and .exceptions packages  Depends on AirSensEURSqlLib project, where SQL helpers and containers are shared with other host applications  Depends on AirSensEURSOSDbLib project where 52North SOS RPCs are implemented  Depends on AirSensEURInfluxDBLib project where INFLUX DB helpers are implemented
  144. 144. January 2016 144 AirSensEURDataPushAirSensEURDataPush  AirSensEURDataPush reads information stored on a local sqlite database and pushes uncommitted data to a remote data server  It can push data to two remote data server types: − 52North SOS server (JSON InsertObservations API) − INFLUX DB
  145. 145. January 2016 145 AirSensEURDataPushAirSensEURDataPush In 52North SOS working mode: − For each sensor channel:  Ask for the last valid sample data timestamp  Retrieve a chunk of data from the local database with timestamp greater than the last found timestamp  Populate an InsertObservation by filling a multiple set of Observations  Generate an HTTP POST with the JSON(ized) InsertObservation pointing to the remote server  Repeat until no more samples are available in local database
  146. 146. January 2016 146 AirSensEURDataPushAirSensEURDataPush In INFLUX DB working mode: − Retrieve, from a local history database file, the timestamp for the last valid commit operation − Retrieve, from the local samples database, a chunk of data with timestamp greater than the last found timestamp − Populate a SampleDataSerie with collected information − Generate an HTTP POST with the JSON(ized) SampleDataSerie pointing to the remote server − Update the local history database with last updated timestamp − Repeat until no more samples are available in the local database
  147. 147. January 2016 147 AirSensEURDataPushAirSensEURDataPush Data Push History persister SQL persisterSample persister Configuration engine
  148. 148. January 2016 148 AirSensEURDataPush (HistoryPersister)AirSensEURDataPush (HistoryPersister)  Used to retrieve the timestamp of a last valid data committed to the server  HistoryPersisterSQL generates a local sqlite file and uses it as a persistance medium  HistorySOSDB executes a GetDataAvailability RPC on SOS server
  149. 149. January 2016 149 AirSensEURDataPush (SamplesPersister)AirSensEURDataPush (SamplesPersister)  SamplePersisterInfluxDB persists data through a set of HTTP JSON post compatible with Influx DBs  SamplePersisterSOSDB generates a set of InsertObservation calls. Each InsertObservation is filled by several Observation(s) in order to increase the network efficiency. Required containers are defined in the .dao package in AirSensEUDSOSDbLib project
  150. 150. January 2016 150 Java Host Application configurationJava Host Application configuration  Configuration is handled by a private Configuration class implemented in all Java Host Applications  Configuration is read from .properties file. Valid tokens and possible values are defined in the Configuration class  configuration.properties files are located at /usr/local/etc and are specified by the shell startup scripts with the following rules Application Configuration File AirSensEURHost sensor.properties AirSensEURDataAggregator aggregator.properties AirSensEURDataPush (SOSDb) datapushsosdb.properties AirSensEURDataPush (InfluxDb) influxpush.properties
  151. 151. January 2016 151 AgendaAgenda  System Overview  AirSensEUR Shield Hardware  AirSensEUR Shield Firmware  The Java Panel Application  AirSensEUR Host Hardware  AirSensEUR Host Linux Customization  AirSensEUR Host Applications  AirSensEUR Web Management Console
  152. 152. January 2016 152 Web Management ConsoleWeb Management Console  Feedback on AirSensEUR Host activities status  Simple configuration of main working parameters  Wi-Fi reachable
  153. 153. January 2016 153 Web Management ConsoleWeb Management Console Server Side Browser Side HTTP Ajax JSON
  154. 154. January 2016 154 Web Management ConsoleWeb Management Console  Client side developed with ReactJs and styled with Bootstrap  Client-Server data exchange in JSON format  Server side developed with small PHP scripts targeting a single function each one  PHP scripts interacting with BASH for configuration files generation, start/stop processes  Live data retrieved by PHP scripts through JSON calls to AirSensEURHost application and sent back to the client  Data Push scheduling through custom cron file PHP editors

×