Difference between revisions of "Smart environment PRO"

From AMTech WikiDocs
Jump to: navigation, search
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
=== Smart environment PRO ===
 
=== Smart environment PRO ===
*Supports the following sensors
+
*id Gases_PRO 19
 +
*Bridge waspmote following sensors read to  to IoT DAP
 +
#Device Temperature      IN_TEMP
 +
#Battery level          BAT
 +
#Acceleromete X,Y,Z      ACC
 +
#Chlorine                GP_CL2
 +
#Carbon Monoxide        GP_CO
 +
#Ethylene Oxide          GP_ETO
 +
#Hydrogen                GP_H2
 +
#Hydrogen Sulphide      GP_H2S
 +
#Hydrogen Chloride      GP_HCL
 +
#Hydrogen Cyanide        GP_HCN
 +
#Ammonia                GP_NH3
 +
#Nitrogen Monoxide      GP_NO
 +
#Nitrogen                GP_NO2
 +
#Oxygen                  GP_O2
 +
#Phospine                GP_PH3
 +
#Sulfur                  GP_SO2
 +
#Methane                GP_CH4
 +
#Ozone                  GP_O3
 +
#Carbon Dioxide          GP_CO2
 +
#Temperature Celsius    GP_TC
 +
#Temperature Fahrenheit  GP_TF
 +
#Humidity                GP_HUM
 +
#Pressure                GP_PRES
 +
* Edge Intelligence
 +
**[[Smoothing_observations|Smoothing observations]]
 +
* Placeholders (See [[Sensor%27s_network#Placeholders_substitution|Placeholders]])
 +
** #{waspmoteName} waspmote model name
 +
** #{waspmoteId} waspmote model numeric unique identifier
 +
** #{blePeripheralUuid} ble unique id identifier
  
Bridge Bluetooth the following sensors read to  to IoT DAP /amtech/linkeddata/types/composite/entity/BLEbeaconsScanner /amtech/linkeddata/types/composite/observation/waspmoteSmartEnvironment
+
* Produced observations (see /amtech/linkeddata/types/composite/observation)
 +
** /amtech/linkeddata/types/composite/observation/waspmoteSmartEnvironment
  
* Edge Intelligence
+
*[https://www.arduino.cc/en/tutorial/sketch Arduino sketch] for Smart environment PRO configure with following sensors
** Smoothing for new, broadcast and lost tag
+
**SENSOR_ACC ,SENSOR_BAT, SENSOR_IN_TEMP , SENSOR_GP_TC, SENSOR_GP_HUM, SENSOR_GP_PRES, SENSOR_GP_CH4, SENSOR_GP_NO2, SENSOR_GP_O2, SENSOR_GP_CO
** [https://en.wikipedia.org/wiki/IBeacon iBeacon] and [https://github.com/google/eddystone/blob/master/protocol-specification.md Eddystone] protocols
+
<syntaxhighlight lang="c">
 +
/*
 +
*  ------Waspmote starting program------
 +
*
 +
*  Explanation: Send basic parameters through the corresponding
 +
*  XBee module.
 +
*  For other communication modules please use on line code generator.
 +
*
 +
*  Copyright (C) 2015 Libelium Comunicaciones Distribuidas S.L.
 +
*  http://www.libelium.com
 +
*
 +
*  This program is free software: you can redistribute it and/or modify
 +
*  it under the terms of the GNU General Public License as published by
 +
*  the Free Software Foundation, either version 3 of the License, or
 +
*  (at your option) any later version.
 +
*
 +
*  This program is distributed in the hope that it will be useful,
 +
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
 +
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +
*  GNU General Public License for more details.
 +
*
 +
*  You should have received a copy of the GNU General Public License
 +
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
*/
  
 +
// Include libraries
 +
#include <WaspFrame.h>
 +
#include <WaspBLE.h>
 +
#include <WaspSensorGas_Pro.h>
 +
// Define the Waspmote default ID
 +
char deviceName[] = "WBLE";
 +
// Variable to store advertisement data
 +
uint8_t advData[31];
 +
char sv[32];
 +
// Define the authentication key
 +
char key_access[] = "LIBELIUM";
 +
uint8_t flag =0;
  
 +
Gas O2(SOCKET_A);
 +
Gas CH4(SOCKET_B);
 +
Gas NO2(SOCKET_C);
 +
Gas CO(SOCKET_F);
  
* Placeholders (See [[Sensor%27s_network#Placeholders_substitution|Placeholders]])
+
float o2_concentration;
{waspmoteName: libeliumSensors.getModelName(head.waspmoteId),
+
float ch4_concentration;
                      waspmoteId : head.waspmoteId,
+
float no2_concentration;
                      blePeripheralUuid : head.blePeripheralUuid};
+
float co_concentration;
 +
float temperature;
 +
float humidity;
 +
float pressure;
  
 +
uint16_t aux = 0;
 +
uint8_t msgNumber = 0;
  
 +
#define AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xff;
 +
#define Gases_PRO 19
 +
#define LIBELIUM_BLEID 0x88;
 +
//#define TOTAL_SENSORS 10;
 +
//#define SENSORS_MSG  5
  
** #{waspmoteName} waspmote model name
+
void showValue(float val, char *sensorName, int pos){
** #{waspmoteId} waspmote model numeric unique identifier
+
      memset(sv, 0x00, sizeof(sv));
** #{blePeripheralUuid} waspmote model numeric unique identifier
+
      dtostrf(val,1,2,sv);
 +
      USB.printf("%s Valor = %s  pos %d\n", sensorName, sv, pos);
 +
 
 +
}
  
 +
void showACCValues( int x, int y, int z, int pos ){
 +
    sprintf(sv, "%d,%d,%d",x, y, z );
 +
    USB.printf("SENSOR_ACC Valor = %s  pos %d\n", sv, pos);
 +
}
 +
 +
 +
/*
 +
* AD_TYPE_MANUFACTURER_SPECIFIC_DATA (1) LIBELIUM_BLEID (1) Gases_PRO (1) TOTAL_SENSORS (1) SENSORS_MSG (1)
 +
* SENSOR_ACC (1 + 6)  SENSOR_BAT (1 + 1), SENSOR_IN_TEMP (1 + 4) , SENSOR_GP_TC (1 + 4 ) SENSOR_GP_HUM ( 1+ 4) [29]
 +
*/
 +
#define MSGADDITIONAL_SIZE 29;
 +
int buildAdditionalSensors()
 +
{
 +
  int ms = 0;  ;
 +
  memset(advData,  0x00, sizeof(advData));
 +
  advData[ms++]= MSGADDITIONAL_SIZE;
 +
  advData[ms++]= AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
 +
  advData[ms++] = LIBELIUM_BLEID;
 +
  advData[ms++] = Gases_PRO;
 +
  //byte result = (byte)(number1 | (number2 << 4));
 +
  advData[ms++] = (uint8_t)(10 | (5 <<4));
 +
  advData[ms++] = msgNumber++;
 +
  showValue(msgNumber, "msgNumber", ms);
 +
  //1 SENSOR_ACC
 +
  advData[ms++] = SENSOR_ACC;
 +
  int x = ACC.getX();
 +
  int y = ACC.getY();
 +
  int z = ACC.getZ();
 +
  memcpy( &advData[ms], &x, sizeof(int) );
 +
  ms += sizeof(int);
 +
  memcpy( &advData[ms], &y, sizeof(int) );
 +
  ms += sizeof(int);
 +
  memcpy( &advData[ms], &z, sizeof(int) );
 +
  ms += sizeof(int);
 +
  showACCValues(x,y,z, ms);
 +
  //2S ENSOR_BAT
 +
  advData[ms++] = SENSOR_BAT;
 +
  uint8_t vuint =  PWR.getBatteryLevel();
 +
  memcpy( &advData[ms], &vuint, sizeof(uint8_t) );
 +
  ms += sizeof(uint8_t);
 +
  showValue(vuint, "SENSOR_BAT", ms);
 +
  //3 SENSOR_IN_TEMP
 +
  advData[ms++] = SENSOR_IN_TEMP;
 +
  float vfloat = RTC.getTemperature();
 +
  memcpy( &advData[ms], &vfloat, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(vfloat, "SENSOR_IN_TEMP", ms);
 +
  //4 SENSOR_GP_TC
 +
  advData[ms++] = SENSOR_GP_TC;
 +
  memcpy( &advData[ms], &temperature, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(temperature, "SENSOR_GP_TC", ms);
 +
  //5 SENSOR_GP_HUM
 +
  advData[ms++] = SENSOR_GP_HUM;
 +
  memcpy( &advData[ms], &humidity, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(humidity, "SENSOR_GP_HUM", ms);
 +
  return ms;
 +
}
 +
 +
 +
/*
 +
* LIBELIUM_BLEID (1) Gases_PRO (1) TOTAL_SENSORS (1) SENSORS_MSG (1) SENSOR_GP_PRES ( 1+ 4) SENSOR_GP_CH4 ( 1+ 4) SENSOR_GP_NO2 ( 1+ 4) SENSOR_GP_O2 ( 1+ 4) SENSOR_GP_CO ( 1+ 4) [30]
 +
*/
 +
#define MSGSENSORS_SIZE 30
 +
int buildSensors()
 +
{
 +
  int ms = 0;  ;
 +
  memset(advData,  0x00, sizeof(advData));
 +
  advData[ms++]= MSGSENSORS_SIZE;
 +
  advData[ms++]= AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
 +
  advData[ms++] = LIBELIUM_BLEID;
 +
  advData[ms++] = Gases_PRO;
 +
  advData[ms++] = (uint8_t)(10 | (5 <<4));
 +
  advData[ms++] = msgNumber++;
 +
  showValue(msgNumber, "msgNumber", ms);
 +
  //1 SENSOR_GP_PRES
 +
  advData[ms++] = SENSOR_GP_PRES;
 +
  memcpy( &advData[ms], &pressure, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(pressure, "SENSOR_GP_PRES", ms);
 +
  //2 SENSOR_GP_CH4
 +
  advData[ms++] = SENSOR_GP_CH4;
 +
  memcpy( &advData[ms], &ch4_concentration, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(ch4_concentration, "SENSOR_GP_CH4", ms);
 +
  //3 SENSOR_GP_NO2
 +
  advData[ms++] = SENSOR_GP_NO2;
 +
  memcpy( &advData[ms], &no2_concentration, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(no2_concentration, "SENSOR_GP_NO2", ms);
 +
  //4 SENSOR_GP_O2
 +
  advData[ms++] = SENSOR_GP_O2;
 +
  memcpy( &advData[ms], &o2_concentration, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(o2_concentration, "SENSOR_GP_O2", ms);
 +
  //5 SENSOR_GP_CO
 +
  advData[ms++] = SENSOR_GP_CO;
 +
  memcpy( &advData[ms], &co_concentration, sizeof(float) );
 +
  ms += sizeof(float);
 +
  showValue(co_concentration, "SENSOR_GP_CO", ms);
 +
  return ms;
 +
}
 +
 +
void print_hex_memory(void *mem, int len) {
 +
  int i;
 +
  USB.printf("Len %d ==>", len);
 +
  unsigned char *p = (unsigned char *)mem;
 +
  for (i=0;i<len;i++) {
 +
    USB.printf("0x%02x ", p[i]);
 +
    if ((i%16==0) && i)
 +
      USB.printf("\n");
 +
  }
 +
  USB.printf("\n");
 +
}
 +
 +
 +
void setup()
 +
{
 +
  ///////////////////////////////////////
 +
  // Boards ON      ////////////////////
 +
  ///////////////////////////////////////
 +
  PWR.setSensorPower(SENS_3V3, SENS_ON);
 +
 
 +
  /////////////////////////////////
 +
  // 2. Store key access in EEPROM
 +
  /////////////////////////////////
 +
  Utils.setAuthKey(key_access);
 +
 +
  /////////////////////////////////
 +
  // 3. Set up RTC and ACC
 +
  /////////////////////////////////
 +
  delay(500);
 +
 +
  /////////////////////////////////
 +
  // 8. Print module information
 +
  /////////////////////////////////   
 +
  USB.println(F("\nStarting program by default"));
 +
 +
  USB.println(F("BLE module is plugged on socket 0:"));
 +
 +
  USB.println(F("  Configuration:"));
 +
 
 +
  RTC.ON();
 +
  ACC.ON();
 +
 +
  O2.ON();
 +
  CH4.ON();
 +
  NO2.ON();
 +
  CO.ON();
 +
 
 +
  PWR.deepSleep("00:00:00:03", RTC_OFFSET, RTC_ALM1_MODE1, ALL_ON);
 +
 +
  /////////////////////////////////
 +
  // 5. LEDs management
 +
  ///////////////////////////////// 
 +
  Utils.setLED(LED0, LED_OFF);
 +
  Utils.setLED(LED1, LED_OFF);
 +
  for (int i = 0 ; i < 4 ; i++)
 +
  {
 +
    Utils.blinkLEDs(100);
 +
  }
 +
 
 +
  // 0. Turn BLE module ON
 +
  BLE.ON(SOCKET0);
 +
 +
 +
  // Write the local attribute containing the device name
 +
  flag = BLE.writeLocalAttribute(3, deviceName);
 +
 +
  if (flag == 0)
 +
  {   
 +
    USB.println("Name written");
 +
  }
 +
  else
 +
  {
 +
    USB.print("Error writing. flag =");
 +
    USB.println(flag, DEC);
 +
  }
 +
 
 +
 +
  // 2. Print MAC address
 +
  USB.print("BLE MAC is: ");
 +
  USB.println(BLE.getOwnMac());
 +
  BLE.setConnectableMode(BLE_GAP_UNDIRECTED_CONNECTABLE);
 +
 
 +
  // 1.8 Wake up again to allow receiving new commands.
 +
  //aux = BLE.wakeUp();
 +
  //BLE.sleep();
 +
  USB.println(F("==============================="));
 +
}
 +
 +
void loop()
 +
{
 +
  USB.println(F("==========start loop====================="));
 +
  // set Green LED
 +
  Utils.setLED(LED1,LED_ON);
 +
  //read sensors 
 +
  o2_concentration = O2.getConc();
 +
  ch4_concentration = CH4.getConc();
 +
  no2_concentration = NO2.getConc();
 +
  co_concentration = CO.getConc();
 +
  temperature = O2.getTemp(1);
 +
  humidity = O2.getHumidity();
 +
  pressure = O2.getPressure();
 +
 
 +
  int len;
 
   
 
   
 +
 
 +
  for (int i = 0 ; i < 2; i++)
 +
  {
 +
      if (msgNumber==0xff)
 +
      {
 +
        msgNumber= 0;
 +
      }
 +
     
 +
      aux = BLE.wakeUp();
 +
      /* NOTE 1: after turning BLE module ON, the default state
 +
      is non discoverable.
 +
      */
 +
      /* NOTE 2: If you are currently advertising, then any changes
 +
      on the advertisement data will not take effect until you
 +
      stop and re-start advertising again.
 +
      */
 +
      // 1.1 Make device no discoverable to stop advertisement.
 +
      aux = BLE.setDiscoverableMode(BLE_GAP_NON_DISCOVERABLE);
 +
      USB.println(F("\tA - Stop advertisements"));
 +
     
 +
      // 1.2 Set advertisement interval of 100 ms and three channels
 +
      /* NOTE 3: intervals are specified in units of 625 uS
 +
      Example: 1000 ms / 0.625 = 1600
 +
      */
 +
      aux = BLE.setAdvParameters(1600, 1600, 7);
 +
      USB.println(F("\tB - Setting advertisement interval"));
 +
     
 +
      if(i== 0){
 +
        //Additional sensors
 +
        len = buildAdditionalSensors();
 +
      }else{
 +
        // 1.3 Set Advertisement with sensor read value.
 +
        len =  buildSensors();
 +
      } 
 +
      BLE.setAdvData(BLE_GAP_ADVERTISEMENT, advData, len);
 +
      //BLE.setAdvData(BLE_GAP_SCAN_RESPONSE, advData, len);
 +
     
 +
      USB.print(F("Advertisement = "));
 +
      USB.println(F("\tC - Setting advertisements data to: "));
 +
      print_hex_memory(&advData, len);
 +
     
 +
      // 1.4 Set discoverable mode to user data to start advertising
 +
      // with custom data
 +
      aux = BLE.setDiscoverableMode(BLE_GAP_USER_DATA);
 +
      USB.println(F("\tD - Start advertisements"));
 +
     
 +
      // 1.5 Go to sleep and but remain advertising to save power.
 +
      BLE.sleep();
 +
      delay(1000); 
 +
  }
 +
 
 +
 
 +
  USB.println(F("============end loop==================="));
  
* Produced observations (see /amtech/linkeddata/types/composite/observation)
+
  //PWR.deepSleep("00:00:00:30", RTC_OFFSET, RTC_ALM1_MODE1, ALL_OFF);
** /amtech/linkeddata/types/composite/observation/waspmoteSmartEnvironment
+
  //delay(1000);
 +
}
 +
</syntaxhighlight>

Latest revision as of 14:12, 2 February 2018

Smart environment PRO

  • id Gases_PRO 19
  • Bridge waspmote following sensors read to to IoT DAP
  1. Device Temperature IN_TEMP
  2. Battery level BAT
  3. Acceleromete X,Y,Z ACC
  4. Chlorine GP_CL2
  5. Carbon Monoxide GP_CO
  6. Ethylene Oxide GP_ETO
  7. Hydrogen GP_H2
  8. Hydrogen Sulphide GP_H2S
  9. Hydrogen Chloride GP_HCL
  10. Hydrogen Cyanide GP_HCN
  11. Ammonia GP_NH3
  12. Nitrogen Monoxide GP_NO
  13. Nitrogen GP_NO2
  14. Oxygen GP_O2
  15. Phospine GP_PH3
  16. Sulfur GP_SO2
  17. Methane GP_CH4
  18. Ozone GP_O3
  19. Carbon Dioxide GP_CO2
  20. Temperature Celsius GP_TC
  21. Temperature Fahrenheit GP_TF
  22. Humidity GP_HUM
  23. Pressure GP_PRES
  • Edge Intelligence
  • Placeholders (See Placeholders)
    • #{waspmoteName} waspmote model name
    • #{waspmoteId} waspmote model numeric unique identifier
    • #{blePeripheralUuid} ble unique id identifier
  • Produced observations (see /amtech/linkeddata/types/composite/observation)
    • /amtech/linkeddata/types/composite/observation/waspmoteSmartEnvironment
  • Arduino sketch for Smart environment PRO configure with following sensors
    • SENSOR_ACC ,SENSOR_BAT, SENSOR_IN_TEMP , SENSOR_GP_TC, SENSOR_GP_HUM, SENSOR_GP_PRES, SENSOR_GP_CH4, SENSOR_GP_NO2, SENSOR_GP_O2, SENSOR_GP_CO
/*
 *  ------Waspmote starting program------
 *
 *  Explanation: Send basic parameters through the corresponding 
 *  XBee module.
 *  For other communication modules please use on line code generator.
 *
 *  Copyright (C) 2015 Libelium Comunicaciones Distribuidas S.L.
 *  http://www.libelium.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// Include libraries
#include <WaspFrame.h>
#include <WaspBLE.h>
#include <WaspSensorGas_Pro.h>
// Define the Waspmote default ID
char deviceName[] = "WBLE";
// Variable to store advertisement data
uint8_t advData[31];
char sv[32];
// Define the authentication key
char key_access[] = "LIBELIUM";
uint8_t flag =0;

Gas O2(SOCKET_A);
Gas CH4(SOCKET_B);
Gas NO2(SOCKET_C);
Gas CO(SOCKET_F);

float o2_concentration;
float ch4_concentration;
float no2_concentration;
float co_concentration;
float temperature;
float humidity;
float pressure;

uint16_t aux = 0;
uint8_t msgNumber = 0;

#define AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xff;
#define Gases_PRO 19
#define LIBELIUM_BLEID 0x88;
//#define TOTAL_SENSORS 10;
//#define SENSORS_MSG  5

void showValue(float val, char *sensorName, int pos){
      memset(sv, 0x00, sizeof(sv));
      dtostrf(val,1,2,sv);
      USB.printf("%s Valor = %s   pos %d\n", sensorName, sv, pos);
  
}

void showACCValues( int x, int y, int z, int pos ){
    sprintf(sv, "%d,%d,%d",x, y, z );
    USB.printf("SENSOR_ACC Valor = %s   pos %d\n", sv, pos);
}


/*
 * AD_TYPE_MANUFACTURER_SPECIFIC_DATA (1) LIBELIUM_BLEID (1) Gases_PRO (1) TOTAL_SENSORS (1) SENSORS_MSG (1) 
 * SENSOR_ACC (1 + 6)  SENSOR_BAT (1 + 1), SENSOR_IN_TEMP (1 + 4) , SENSOR_GP_TC (1 + 4 ) SENSOR_GP_HUM ( 1+ 4) [29]
 */
 #define MSGADDITIONAL_SIZE 29; 
int buildAdditionalSensors()
{
  int ms = 0;  ; 
  memset(advData,  0x00, sizeof(advData));
  advData[ms++]= MSGADDITIONAL_SIZE;
  advData[ms++]= AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
  advData[ms++] = LIBELIUM_BLEID;
  advData[ms++] = Gases_PRO;
  //byte result = (byte)(number1 | (number2 << 4));
  advData[ms++] = (uint8_t)(10 | (5 <<4));
  advData[ms++] = msgNumber++;
  showValue(msgNumber, "msgNumber", ms);
  //1 SENSOR_ACC
  advData[ms++] = SENSOR_ACC;
  int x = ACC.getX();
  int y = ACC.getY();
  int z = ACC.getZ();
  memcpy( &advData[ms], &x, sizeof(int) );
  ms += sizeof(int);
  memcpy( &advData[ms], &y, sizeof(int) );
  ms += sizeof(int);
  memcpy( &advData[ms], &z, sizeof(int) );
  ms += sizeof(int);
  showACCValues(x,y,z, ms);
  //2S ENSOR_BAT
  advData[ms++] = SENSOR_BAT;
  uint8_t vuint =  PWR.getBatteryLevel();
  memcpy( &advData[ms], &vuint, sizeof(uint8_t) );
  ms += sizeof(uint8_t);
  showValue(vuint, "SENSOR_BAT", ms);
  //3 SENSOR_IN_TEMP
  advData[ms++] = SENSOR_IN_TEMP;
  float vfloat = RTC.getTemperature();
  memcpy( &advData[ms], &vfloat, sizeof(float) );
  ms += sizeof(float);
  showValue(vfloat, "SENSOR_IN_TEMP", ms);
  //4 SENSOR_GP_TC
  advData[ms++] = SENSOR_GP_TC;
  memcpy( &advData[ms], &temperature, sizeof(float) );
  ms += sizeof(float);
  showValue(temperature, "SENSOR_GP_TC", ms);
  //5 SENSOR_GP_HUM
  advData[ms++] = SENSOR_GP_HUM;
  memcpy( &advData[ms], &humidity, sizeof(float) );
  ms += sizeof(float);
  showValue(humidity, "SENSOR_GP_HUM", ms);
  return ms;
}


/*
 * LIBELIUM_BLEID (1) Gases_PRO (1) TOTAL_SENSORS (1) SENSORS_MSG (1) SENSOR_GP_PRES ( 1+ 4) SENSOR_GP_CH4 ( 1+ 4) SENSOR_GP_NO2 ( 1+ 4) SENSOR_GP_O2 ( 1+ 4) SENSOR_GP_CO ( 1+ 4) [30]
 */
 #define MSGSENSORS_SIZE 30
int buildSensors()
{
  int ms = 0;  ; 
  memset(advData,  0x00, sizeof(advData));
  advData[ms++]= MSGSENSORS_SIZE;
  advData[ms++]= AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
  advData[ms++] = LIBELIUM_BLEID;
  advData[ms++] = Gases_PRO;
  advData[ms++] = (uint8_t)(10 | (5 <<4));
  advData[ms++] = msgNumber++;
  showValue(msgNumber, "msgNumber", ms);
  //1 SENSOR_GP_PRES
  advData[ms++] = SENSOR_GP_PRES;
  memcpy( &advData[ms], &pressure, sizeof(float) );
  ms += sizeof(float);
  showValue(pressure, "SENSOR_GP_PRES", ms);
  //2 SENSOR_GP_CH4
  advData[ms++] = SENSOR_GP_CH4;
  memcpy( &advData[ms], &ch4_concentration, sizeof(float) );
  ms += sizeof(float);
  showValue(ch4_concentration, "SENSOR_GP_CH4", ms);
  //3 SENSOR_GP_NO2
  advData[ms++] = SENSOR_GP_NO2;
  memcpy( &advData[ms], &no2_concentration, sizeof(float) );
  ms += sizeof(float);
  showValue(no2_concentration, "SENSOR_GP_NO2", ms);
  //4 SENSOR_GP_O2
  advData[ms++] = SENSOR_GP_O2;
  memcpy( &advData[ms], &o2_concentration, sizeof(float) );
  ms += sizeof(float);
  showValue(o2_concentration, "SENSOR_GP_O2", ms);
  //5 SENSOR_GP_CO
  advData[ms++] = SENSOR_GP_CO;
  memcpy( &advData[ms], &co_concentration, sizeof(float) );
  ms += sizeof(float);
  showValue(co_concentration, "SENSOR_GP_CO", ms);
  return ms;
}

void print_hex_memory(void *mem, int len) {
  int i;
  USB.printf("Len %d ==>", len);
  unsigned char *p = (unsigned char *)mem;
  for (i=0;i<len;i++) {
    USB.printf("0x%02x ", p[i]);
    if ((i%16==0) && i)
      USB.printf("\n");
  }
  USB.printf("\n");
}


void setup()
{
  ///////////////////////////////////////
  // Boards ON       ////////////////////
  ///////////////////////////////////////
  PWR.setSensorPower(SENS_3V3, SENS_ON); 
  
  /////////////////////////////////
  // 2. Store key access in EEPROM
  /////////////////////////////////
  Utils.setAuthKey(key_access);

  /////////////////////////////////
  // 3. Set up RTC and ACC
  /////////////////////////////////
  delay(500);

  /////////////////////////////////
  // 8. Print module information
  /////////////////////////////////     
  USB.println(F("\nStarting program by default"));

  USB.println(F("BLE module is plugged on socket 0:"));

  USB.println(F("   Configuration:"));
  
  RTC.ON();
  ACC.ON();

  O2.ON();
  CH4.ON();
  NO2.ON();
  CO.ON();
  
  PWR.deepSleep("00:00:00:03", RTC_OFFSET, RTC_ALM1_MODE1, ALL_ON);

  /////////////////////////////////
  // 5. LEDs management 
  /////////////////////////////////  
  Utils.setLED(LED0, LED_OFF);
  Utils.setLED(LED1, LED_OFF);
  for (int i = 0 ; i < 4 ; i++)
  {
    Utils.blinkLEDs(100);
  }
  
  // 0. Turn BLE module ON
  BLE.ON(SOCKET0);


  // Write the local attribute containing the device name
  flag = BLE.writeLocalAttribute(3, deviceName);

  if (flag == 0)
  {    
    USB.println("Name written");
  }
  else
  {
    USB.print("Error writing. flag =");
    USB.println(flag, DEC);
  }
  

  // 2. Print MAC address
  USB.print("BLE MAC is: ");
  USB.println(BLE.getOwnMac()); 
  BLE.setConnectableMode(BLE_GAP_UNDIRECTED_CONNECTABLE);
  
  // 1.8 Wake up again to allow receiving new commands.
  //aux = BLE.wakeUp();
  //BLE.sleep();
  USB.println(F("==============================="));
}

void loop()
{
  USB.println(F("==========start loop====================="));
  // set Green LED
  Utils.setLED(LED1,LED_ON);
  //read sensors  
  o2_concentration = O2.getConc();
  ch4_concentration = CH4.getConc();
  no2_concentration = NO2.getConc();
  co_concentration = CO.getConc();
  temperature = O2.getTemp(1);
  humidity = O2.getHumidity();
  pressure = O2.getPressure();
  
  int len;
 
  
  for (int i = 0 ; i < 2; i++)
  {
      if (msgNumber==0xff)
      { 
        msgNumber= 0;
      }
      
      aux = BLE.wakeUp();
      /* NOTE 1: after turning BLE module ON, the default state 
       is non discoverable.
      */
       /* NOTE 2: If you are currently advertising, then any changes 
       on the advertisement data will not take effect until you 
       stop and re-start advertising again.
       */
      // 1.1 Make device no discoverable to stop advertisement.
      aux = BLE.setDiscoverableMode(BLE_GAP_NON_DISCOVERABLE);
      USB.println(F("\tA - Stop advertisements"));
      
      // 1.2 Set advertisement interval of 100 ms and three channels
      /* NOTE 3: intervals are specified in units of 625 uS
       Example: 1000 ms / 0.625 = 1600
       */
      aux = BLE.setAdvParameters(1600, 1600, 7);
      USB.println(F("\tB - Setting advertisement interval"));
      
      if(i== 0){
        //Additional sensors
        len = buildAdditionalSensors(); 
      }else{
        // 1.3 Set Advertisement with sensor read value.
        len =  buildSensors();
      }   
      BLE.setAdvData(BLE_GAP_ADVERTISEMENT, advData, len);
      //BLE.setAdvData(BLE_GAP_SCAN_RESPONSE, advData, len);
      
      USB.print(F("Advertisement = "));
      USB.println(F("\tC - Setting advertisements data to: "));
      print_hex_memory(&advData, len);
      
      // 1.4 Set discoverable mode to user data to start advertising 
      // with custom data
      aux = BLE.setDiscoverableMode(BLE_GAP_USER_DATA);
      USB.println(F("\tD - Start advertisements"));
      
      // 1.5 Go to sleep and but remain advertising to save power.
       BLE.sleep();
       delay(1000);   
  }
  
   
  USB.println(F("============end loop==================="));

  //PWR.deepSleep("00:00:00:30", RTC_OFFSET, RTC_ALM1_MODE1, ALL_OFF);
  //delay(1000);
}