Pelion Device Management example over 15.4 Thread for Thunderboard Sense 2 board

Dependencies:   ICM20648 BMP280 Si1133 Si7210 AMS_CCS811_gas_sensor SI7021

DEPRECATED

This example application is not maintained and not recommended. It uses an old version of Mbed OS, Pelion DM, and Arm toolchain. It doesn't work with Mbed Studio.

Please use: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-pelion/

This example is known to work great on the following platforms:

Follow the Quick-Start instructions: https://cloud.mbed.com/quick-start

Thunderboard Sense 2

Example functionality

This example showcases the following device functionality:

  • Read onboard sensors, and report them as Pelion LWM2M resources:
    • Barometric Pressure and Temperature (BMP280)
    • Relative Humidity and Temperature (Si7021)
    • Air quality - CO2 and tVOC (CCS811)
    • Light intensity and UV level (Si1133)
    • Hall effect and Temperature (Si7210)
    • Accelerometer and Gyroscope (ICM20648)
  • It also exposes the RGB LEDs for triggering flashes in a specific color
  • On user button click, increment Pelion LWM2M button resource.

/media/uploads/screamer/pelion_st_humidity_reading.png?v=2

15.4 Thread setup

This example program requires that a Thread Border Router is available. A Border Router is a network gateway between a wireless 6LoWPAN mesh network and a backhaul network. It controls and relays traffic between the two networks. In a typical setup, a 6LoWPAN border router is connected to another router in the backhaul network (over Ethernet or a serial line) which in turn forwards traffic to/from the internet or a private company LAN, for instance.

https://raw.githubusercontent.com/ARMmbed/nanostack-border-router/f8bf21aac12c9926afba252187e2adf2525bf1eb/images/br_role.png

Instructions how to set up a Thread Border Router

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/SiliconLabs/code/pelion-example-tbsense2

cd pelion-example-tbsense2

2. Install the CLOUD_SDK_API_KEY

mbed config -G CLOUD_SDK_API_KEY <PELION_DM_API_KEY>

For instructions on how to generate your API key, please see the documentation.

3. Initialize firmware credentials (done once per repository). You can use the following command:

mbed dm init -d "<your company name in Pelion DM>" --model-name "<product model identifier>" -q --force

If above command do not work for your Mbed CLI, please consider upgrading Mbed CLI to version 1.8.x or above.

4. Compile and program:

mbed compile -t <toolchain> -m TB_SENSE_2

(supported toolchains : GCC_ARM / ARM / IAR)

5. You can connect on a virtual terminal/COM port to the platform using:

mbed sterm -b 115200

This should give you an output similar to:

[BOOT] Mbed Bootloader
[BOOT] ARM: 00000000000000000000
[BOOT] OEM: 00000000000000000000
[BOOT] Layout: 0 90AC
[BOOT] Active firmware integrity check:
[BOOT] SHA256: 615A11A7F03B1F048573E2CB51D8C9A5DD4E6F17A7F8E79C4B64E3241FF78974
[BOOT] Version: 1553594998
[BOOT] Slot 0 is empty
[BOOT] Active firmware up-to-date
[BOOT] Application's start address: 0x10400
[BOOT] Application's jump address: 0x10FBD
[BOOT] Application's stack address: 0x20040000
[BOOT] Forwarding to application...


Starting Simple Pelion Device Management Client example
You can hold the user button during boot to format the storage and change the device identity.
Connecting to the network using 802.15.4...
Connected to the network successfully. IP address: 2001:****:****:****:****:****:****:73bc
Initializing Pelion Device Management Client...
Si7021 Electronic Serial Number:                0         15b5ffff, firmware rev 20
Registered to Pelion Device Management. Endpoint Name: 0169b91a********************01a0
                                                                 
BMP280 temp:     32.750 C,   pressure: 1030.750 [mbar]            
Si7021 temp:     27.529 C,   humidity:   24.842 %                 
Si7210 temp:     34.484 C,   field:      -0.076 [mT]              
Si1133 light:  1258.574 lux, UV level:    0.031                       
CCS811 CO2:           0 ppm, VoC:             0 ppb                   
ICM20648 acc:    -0.093 x,  -0.057 y,     0.969 z [mg]            
ICM20648 gyro:   -1.503 x,   0.122 y,    -0.771 z [mdps]          
    
Committer:
screamer
Date:
Fri Mar 22 00:58:50 2019 +0000
Revision:
0:3853978178c0
Child:
1:cf0bd0446785
Initial commit based on @stevew817 demo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:3853978178c0 1 // Includes and declarations for Pelion DM Client to work
screamer 0:3853978178c0 2 #include "simple-mbed-cloud-client.h"
screamer 0:3853978178c0 3 #include "BlockDevice.h"
screamer 0:3853978178c0 4 #include "LittleFileSystem.h"
screamer 0:3853978178c0 5 #include "NetworkInterface.h"
screamer 0:3853978178c0 6 #include "mbed_trace.h"
screamer 0:3853978178c0 7 #include "Nanostack.h"
screamer 0:3853978178c0 8 #include "ns_file_system.h"
screamer 0:3853978178c0 9
screamer 0:3853978178c0 10 #define TRACE_GROUP "APP"
screamer 0:3853978178c0 11
screamer 0:3853978178c0 12 // Thunderboard Sense 2 connects over 802.15.4 by default. Since the mesh
screamer 0:3853978178c0 13 // stack is a bit iffy, we'll register a 'network down' handler to act as
screamer 0:3853978178c0 14 // a kind of watchdog for the Pelion DM Client.
screamer 0:3853978178c0 15 NetworkInterface *net = NetworkInterface::get_default_instance();
screamer 0:3853978178c0 16
screamer 0:3853978178c0 17 // Thunderboard Sense 2 has a 1M external flash, which is being shared
screamer 0:3853978178c0 18 // between upgrade storage and LittleFS. LittleFS is instantiated at the
screamer 0:3853978178c0 19 // start of storage, until the start address for upgrade storage.
screamer 0:3853978178c0 20 // Currently, this split is at 256/768 for FS/upgrade.
screamer 0:3853978178c0 21 BlockDevice* bd = BlockDevice::get_default_instance();
screamer 0:3853978178c0 22 SlicingBlockDevice sd(bd, 0, MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS);
screamer 0:3853978178c0 23 LittleFileSystem fs("fs", &sd);
screamer 0:3853978178c0 24
screamer 0:3853978178c0 25 // An event queue is a very useful structure to debounce information between
screamer 0:3853978178c0 26 // contexts (e.g. ISR and normal threads)
screamer 0:3853978178c0 27 // This is great because things such as network operations are illegal in ISR,
screamer 0:3853978178c0 28 // so updating a resource in a button's fall() function is not allowed.
screamer 0:3853978178c0 29 EventQueue eventQueue;
screamer 0:3853978178c0 30
screamer 0:3853978178c0 31 DigitalIn rst_btn(BTN0);
screamer 0:3853978178c0 32
screamer 0:3853978178c0 33 //------------------------------------------------------------------------------
screamer 0:3853978178c0 34 // Includes and declarations for our sensor array
screamer 0:3853978178c0 35 #include "BMP280.h"
screamer 0:3853978178c0 36 #include "Si1133.h"
screamer 0:3853978178c0 37 #include "SI7021.h"
screamer 0:3853978178c0 38 #include "AMS_CCS811.h"
screamer 0:3853978178c0 39
screamer 0:3853978178c0 40 // Define measurement intervals in seconds
screamer 0:3853978178c0 41 #define LIGHT_MEASURING_INTERVAL (600)
screamer 0:3853978178c0 42 #define RHT_MEASURING_INTERVAL (600)
screamer 0:3853978178c0 43 #define BAROMETER_MEASURING_INTERVAL (600)
screamer 0:3853978178c0 44 #define AQ_AVERAGING_SAMPLES (10)
screamer 0:3853978178c0 45
screamer 0:3853978178c0 46 /* Turn on power supply to ENV sensor suite */
screamer 0:3853978178c0 47 DigitalOut env_en(PF9, 1);
screamer 0:3853978178c0 48 /* Turn on power to CCS811 sensor */
screamer 0:3853978178c0 49 DigitalOut ccs_en(PF14, 1);
screamer 0:3853978178c0 50
screamer 0:3853978178c0 51 BMP280 barometer(PC4, PC5);
screamer 0:3853978178c0 52 Si1133 light_sensor(PC4, PC5);
screamer 0:3853978178c0 53 SI7021 rht_sensor(PC4, PC5, SI7021::SI7021_ADDRESS, 400000);
screamer 0:3853978178c0 54
screamer 0:3853978178c0 55 InterruptIn ccs_int(PF13);
screamer 0:3853978178c0 56 I2C ccs_i2c(PB6, PB7);
screamer 0:3853978178c0 57 AMS_CCS811 aqs(&ccs_i2c, PF15);
screamer 0:3853978178c0 58
screamer 0:3853978178c0 59 // When called, will trigger a light sensor measurement and update the resources
screamer 0:3853978178c0 60 void measure_lux(MbedCloudClientResource *light_var, MbedCloudClientResource *uv_var) {
screamer 0:3853978178c0 61 float light_level, uv_index;
screamer 0:3853978178c0 62 bool result = light_sensor.get_light_and_uv(&light_level, &uv_index);
screamer 0:3853978178c0 63 if (result) {
screamer 0:3853978178c0 64 if (light_var) light_var->set_value(light_level);
screamer 0:3853978178c0 65 if (uv_var) uv_var->set_value(uv_index);
screamer 0:3853978178c0 66 } else {
screamer 0:3853978178c0 67 tr_warn("Could not take measurement from lux sensor");
screamer 0:3853978178c0 68 }
screamer 0:3853978178c0 69 }
screamer 0:3853978178c0 70
screamer 0:3853978178c0 71 // When called, will trigger an RHT measurement and update the resources
screamer 0:3853978178c0 72 void measure_rht(MbedCloudClientResource *temperature, MbedCloudClientResource *humidity) {
screamer 0:3853978178c0 73 SI7021::SI7021_status_t result = rht_sensor.SI7021_TriggerHumidity( SI7021::SI7021_NO_HOLD_MASTER_MODE );
screamer 0:3853978178c0 74 if (result == SI7021::SI7021_SUCCESS) {
screamer 0:3853978178c0 75 wait_ms(30);
screamer 0:3853978178c0 76 SI7021::SI7021_vector_data_t result_data;
screamer 0:3853978178c0 77 result = rht_sensor.SI7021_ReadHumidity( &result_data );
screamer 0:3853978178c0 78 if (result == SI7021::SI7021_SUCCESS) {
screamer 0:3853978178c0 79 if (humidity) humidity->set_value(result_data.RelativeHumidity);
screamer 0:3853978178c0 80 } else {
screamer 0:3853978178c0 81 tr_warn("Could not get humidity from RHT sensor");
screamer 0:3853978178c0 82 }
screamer 0:3853978178c0 83 result = rht_sensor.SI7021_ReadTemperatureFromRH( &result_data );
screamer 0:3853978178c0 84 if (result == SI7021::SI7021_SUCCESS) {
screamer 0:3853978178c0 85 if (temperature) temperature->set_value(result_data.Temperature);
screamer 0:3853978178c0 86 } else {
screamer 0:3853978178c0 87 tr_warn("Could not get temperature from RHT sensor");
screamer 0:3853978178c0 88 }
screamer 0:3853978178c0 89
screamer 0:3853978178c0 90 aqs.env_data(result_data.RelativeHumidity, result_data.Temperature);
screamer 0:3853978178c0 91 } else {
screamer 0:3853978178c0 92 tr_warn("Could not take measurement from RHT sensor");
screamer 0:3853978178c0 93 }
screamer 0:3853978178c0 94 }
screamer 0:3853978178c0 95
screamer 0:3853978178c0 96 // When called, will trigger a barometer measurement and update the resources
screamer 0:3853978178c0 97 void measure_baro(MbedCloudClientResource *pressure) {
screamer 0:3853978178c0 98 float result = barometer.getPressure();
screamer 0:3853978178c0 99 if (result > 0) {
screamer 0:3853978178c0 100 if (pressure) pressure->set_value(result);
screamer 0:3853978178c0 101 } else {
screamer 0:3853978178c0 102 tr_warn("Could not take measurement from barometric sensor");
screamer 0:3853978178c0 103 }
screamer 0:3853978178c0 104 }
screamer 0:3853978178c0 105
screamer 0:3853978178c0 106 // When called, will read out the CCS811 measurement
screamer 0:3853978178c0 107 void measure_airquality(MbedCloudClientResource *eco2, MbedCloudClientResource *tvoc) {
screamer 0:3853978178c0 108 static uint32_t co2_buf[AQ_AVERAGING_SAMPLES] = {0};
screamer 0:3853978178c0 109 static uint32_t voc_buf[AQ_AVERAGING_SAMPLES] = {0};
screamer 0:3853978178c0 110 static size_t num_samples = 0;
screamer 0:3853978178c0 111 static bool started = false;
screamer 0:3853978178c0 112
screamer 0:3853978178c0 113 aqs.has_new_data();
screamer 0:3853978178c0 114 co2_buf[num_samples] = aqs.co2_read();
screamer 0:3853978178c0 115 voc_buf[num_samples] = aqs.tvoc_read();
screamer 0:3853978178c0 116
screamer 0:3853978178c0 117 if ((num_samples == 0) && started) {
screamer 0:3853978178c0 118 int co2 = 0, voc = 0;
screamer 0:3853978178c0 119 for (size_t i = 0; i < AQ_AVERAGING_SAMPLES; i++) {
screamer 0:3853978178c0 120 co2 += co2_buf[i];
screamer 0:3853978178c0 121 voc += voc_buf[i];
screamer 0:3853978178c0 122 }
screamer 0:3853978178c0 123
screamer 0:3853978178c0 124 co2 = co2 / AQ_AVERAGING_SAMPLES;
screamer 0:3853978178c0 125 voc = voc / AQ_AVERAGING_SAMPLES;
screamer 0:3853978178c0 126
screamer 0:3853978178c0 127 if (eco2) eco2->set_value(co2);
screamer 0:3853978178c0 128 if (tvoc) tvoc->set_value(voc);
screamer 0:3853978178c0 129 }
screamer 0:3853978178c0 130
screamer 0:3853978178c0 131 started = true;
screamer 0:3853978178c0 132 num_samples = (num_samples + 1) % AQ_AVERAGING_SAMPLES;
screamer 0:3853978178c0 133 }
screamer 0:3853978178c0 134
screamer 0:3853978178c0 135 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
screamer 0:3853978178c0 136 static int num_count = 0;
screamer 0:3853978178c0 137 static int event = 0;
screamer 0:3853978178c0 138
screamer 0:3853978178c0 139 static DigitalOut led_ch_red(PD11, 1);
screamer 0:3853978178c0 140 static DigitalOut led_ch_green(PD12, 1);
screamer 0:3853978178c0 141 static DigitalOut led_ch_blue(PD13, 1);
screamer 0:3853978178c0 142
screamer 0:3853978178c0 143 static DigitalOut led_com_0(PI0, 0);
screamer 0:3853978178c0 144 static DigitalOut led_com_1(PI1, 0);
screamer 0:3853978178c0 145 static DigitalOut led_com_2(PI2, 0);
screamer 0:3853978178c0 146 static DigitalOut led_com_3(PI3, 0);
screamer 0:3853978178c0 147
screamer 0:3853978178c0 148 static DigitalOut led_rgb_en(PJ14, 0);
screamer 0:3853978178c0 149
screamer 0:3853978178c0 150 if (buffer != NULL) {
screamer 0:3853978178c0 151 tr_info("POST received. POST data: %s\n", buffer);
screamer 0:3853978178c0 152
screamer 0:3853978178c0 153 if (event > 0) {
screamer 0:3853978178c0 154 tr_info("Not blinking since previous blink still in progress\n");
screamer 0:3853978178c0 155 return;
screamer 0:3853978178c0 156 }
screamer 0:3853978178c0 157 num_count = 0;
screamer 0:3853978178c0 158 for (size_t i = 0, num_arg = 0; i < 20 || buffer[i] == 0; i++) {
screamer 0:3853978178c0 159 if (buffer[i] == ':') {
screamer 0:3853978178c0 160 num_arg++;
screamer 0:3853978178c0 161 continue;
screamer 0:3853978178c0 162 }
screamer 0:3853978178c0 163
screamer 0:3853978178c0 164 if (buffer[i] >= '0' && buffer[i] <= '9') {
screamer 0:3853978178c0 165 switch (num_arg) {
screamer 0:3853978178c0 166 case 0:
screamer 0:3853978178c0 167 if (buffer[i] == '1') {
screamer 0:3853978178c0 168 led_ch_red = 1;
screamer 0:3853978178c0 169 } else {
screamer 0:3853978178c0 170 led_ch_red = 0;
screamer 0:3853978178c0 171 }
screamer 0:3853978178c0 172 break;
screamer 0:3853978178c0 173 case 1:
screamer 0:3853978178c0 174 if (buffer[i] == '1') {
screamer 0:3853978178c0 175 led_ch_green = 1;
screamer 0:3853978178c0 176 } else {
screamer 0:3853978178c0 177 led_ch_green = 0;
screamer 0:3853978178c0 178 }
screamer 0:3853978178c0 179 break;
screamer 0:3853978178c0 180 case 2:
screamer 0:3853978178c0 181 if (buffer[i] == '1') {
screamer 0:3853978178c0 182 led_ch_blue = 1;
screamer 0:3853978178c0 183 } else {
screamer 0:3853978178c0 184 led_ch_blue = 0;
screamer 0:3853978178c0 185 }
screamer 0:3853978178c0 186 break;
screamer 0:3853978178c0 187 case 3:
screamer 0:3853978178c0 188 num_count = ((buffer[i] - 0x30) * 2) - 1;
screamer 0:3853978178c0 189 tr_info("blinking %d\n", num_count);
screamer 0:3853978178c0 190 break;
screamer 0:3853978178c0 191 default:
screamer 0:3853978178c0 192 break;
screamer 0:3853978178c0 193 }
screamer 0:3853978178c0 194 } else {
screamer 0:3853978178c0 195 //garbage...
screamer 0:3853978178c0 196 continue;
screamer 0:3853978178c0 197 }
screamer 0:3853978178c0 198 if (num_count > 0) {
screamer 0:3853978178c0 199 break;
screamer 0:3853978178c0 200 }
screamer 0:3853978178c0 201 }
screamer 0:3853978178c0 202
screamer 0:3853978178c0 203 if (num_count > 0) {
screamer 0:3853978178c0 204 led_rgb_en = 1;
screamer 0:3853978178c0 205 led_com_0 = 1;
screamer 0:3853978178c0 206 led_com_1 = 1;
screamer 0:3853978178c0 207 event = eventQueue.call_in(1000, blink_callback, resource, (const uint8_t *)NULL, 0);
screamer 0:3853978178c0 208 if (event == 0) {
screamer 0:3853978178c0 209 led_rgb_en = 0;
screamer 0:3853978178c0 210 num_count = 0;
screamer 0:3853978178c0 211 }
screamer 0:3853978178c0 212 }
screamer 0:3853978178c0 213 } else {
screamer 0:3853978178c0 214 tr_info("blink cb\n");
screamer 0:3853978178c0 215 num_count--;
screamer 0:3853978178c0 216 led_com_0 = (num_count & 1);
screamer 0:3853978178c0 217 led_com_1 = (num_count & 1);
screamer 0:3853978178c0 218
screamer 0:3853978178c0 219 if (num_count == 0) {
screamer 0:3853978178c0 220 led_rgb_en = 0;
screamer 0:3853978178c0 221 event = 0;
screamer 0:3853978178c0 222 } else {
screamer 0:3853978178c0 223 event = eventQueue.call_in(1000, blink_callback, resource, (const uint8_t *)NULL, 0);
screamer 0:3853978178c0 224 if (event == 0) {
screamer 0:3853978178c0 225 led_rgb_en = 0;
screamer 0:3853978178c0 226 num_count = 0;
screamer 0:3853978178c0 227 }
screamer 0:3853978178c0 228 }
screamer 0:3853978178c0 229 }
screamer 0:3853978178c0 230 }
screamer 0:3853978178c0 231
screamer 0:3853978178c0 232 int main() {
screamer 0:3853978178c0 233 // If the User button is pressed ons start, then format storage.
screamer 0:3853978178c0 234 if (rst_btn == 0) {
screamer 0:3853978178c0 235 printf("User button is pushed on start. Formatting the storage...\n");
screamer 0:3853978178c0 236 int storage_status = bd->erase(0, bd->size());
screamer 0:3853978178c0 237 if (storage_status != 0) {
screamer 0:3853978178c0 238 printf("ERROR: Failed to erase the storage (%d).\n", storage_status);
screamer 0:3853978178c0 239 }
screamer 0:3853978178c0 240 storage_status = StorageHelper::format(&fs, &sd);
screamer 0:3853978178c0 241 if (storage_status != 0) {
screamer 0:3853978178c0 242 printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
screamer 0:3853978178c0 243 }
screamer 0:3853978178c0 244 } else {
screamer 0:3853978178c0 245 printf("You can hold the user button during boot to format the storage and change the device identity.\n");
screamer 0:3853978178c0 246 }
screamer 0:3853978178c0 247
screamer 0:3853978178c0 248 Nanostack::get_instance(); // ensure Nanostack is initialised
screamer 0:3853978178c0 249 ns_file_system_set_root_path("/fs/");
screamer 0:3853978178c0 250
screamer 0:3853978178c0 251 /* Initialize connectivity */
screamer 0:3853978178c0 252 net->connect();
screamer 0:3853978178c0 253
screamer 0:3853978178c0 254 /* Initialize Simple Pelion DM Client */
screamer 0:3853978178c0 255 SimpleMbedCloudClient client(net, &sd, &fs);
screamer 0:3853978178c0 256 client.init();
screamer 0:3853978178c0 257
screamer 0:3853978178c0 258 /* Create resources */
screamer 0:3853978178c0 259
screamer 0:3853978178c0 260 /* Thunderboard Sense 2 has *A LOT* of sensors. This demo app will expose:
screamer 0:3853978178c0 261 * * Temperature
screamer 0:3853978178c0 262 * * Relative Humidity
screamer 0:3853978178c0 263 * * CO2
screamer 0:3853978178c0 264 * * tVOC
screamer 0:3853978178c0 265 * * light intensity (lux)
screamer 0:3853978178c0 266 * * barometric pressure
screamer 0:3853978178c0 267 * It also exposes the RGB LEDs for triggering flashes in a specific color
screamer 0:3853978178c0 268 */
screamer 0:3853978178c0 269 MbedCloudClientResource *variable;
screamer 0:3853978178c0 270 variable = client.create_resource("3201/0/5853", "LED blinking (R:G:B:cnt)");
screamer 0:3853978178c0 271 variable->observable(false);
screamer 0:3853978178c0 272 variable->set_value("0:0:0:0");
screamer 0:3853978178c0 273 variable->attach_post_callback(blink_callback);
screamer 0:3853978178c0 274 variable->methods(M2MMethod::POST);
screamer 0:3853978178c0 275
screamer 0:3853978178c0 276 MbedCloudClientResource *lux_res;
screamer 0:3853978178c0 277 lux_res = client.create_resource("3301/0/5853", "LightIntensity (lux)");
screamer 0:3853978178c0 278 lux_res->observable(true);
screamer 0:3853978178c0 279 lux_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 280
screamer 0:3853978178c0 281 MbedCloudClientResource *baro_res;
screamer 0:3853978178c0 282 baro_res = client.create_resource("3323/0/5853", "Barometric pressure (hPa)");
screamer 0:3853978178c0 283 baro_res->observable(true);
screamer 0:3853978178c0 284 baro_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 285
screamer 0:3853978178c0 286 MbedCloudClientResource *temperature_res;
screamer 0:3853978178c0 287 temperature_res = client.create_resource("3303/0/5853", "Temperature (C)");
screamer 0:3853978178c0 288 temperature_res->observable(true);
screamer 0:3853978178c0 289 temperature_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 290
screamer 0:3853978178c0 291 MbedCloudClientResource *humidity_res;
screamer 0:3853978178c0 292 humidity_res = client.create_resource("3304/0/5853", "Humidity (%)");
screamer 0:3853978178c0 293 humidity_res->observable(true);
screamer 0:3853978178c0 294 humidity_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 295
screamer 0:3853978178c0 296 MbedCloudClientResource *co2_res;
screamer 0:3853978178c0 297 co2_res = client.create_resource("33255/0/5853", "CO2 (ppm)");
screamer 0:3853978178c0 298 co2_res->observable(true);
screamer 0:3853978178c0 299 co2_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 300
screamer 0:3853978178c0 301 MbedCloudClientResource *voc_res;
screamer 0:3853978178c0 302 voc_res = client.create_resource("33256/0/5853", "VOC (ppm)");
screamer 0:3853978178c0 303 voc_res->observable(true);
screamer 0:3853978178c0 304 voc_res->methods(M2MMethod::GET);
screamer 0:3853978178c0 305
screamer 0:3853978178c0 306 /* Register the device */
screamer 0:3853978178c0 307 client.register_and_connect();
screamer 0:3853978178c0 308
screamer 0:3853978178c0 309 /* Set up measurements */
screamer 0:3853978178c0 310 barometer.initialize();
screamer 0:3853978178c0 311 eventQueue.call_every(BAROMETER_MEASURING_INTERVAL * 1000,
screamer 0:3853978178c0 312 measure_baro, baro_res);
screamer 0:3853978178c0 313 measure_baro(baro_res);
screamer 0:3853978178c0 314
screamer 0:3853978178c0 315 if (light_sensor.open()) {
screamer 0:3853978178c0 316 measure_lux(lux_res, (MbedCloudClientResource *)NULL);
screamer 0:3853978178c0 317 eventQueue.call_every(LIGHT_MEASURING_INTERVAL * 1000,
screamer 0:3853978178c0 318 measure_lux, lux_res,
screamer 0:3853978178c0 319 (MbedCloudClientResource *)NULL);
screamer 0:3853978178c0 320 } else {
screamer 0:3853978178c0 321 tr_err("Disabling Si1133 because we can't find it on the bus");
screamer 0:3853978178c0 322 }
screamer 0:3853978178c0 323
screamer 0:3853978178c0 324 SI7021::SI7021_status_t result = rht_sensor.SI7021_SoftReset();
screamer 0:3853978178c0 325 if (result == SI7021::SI7021_SUCCESS) {
screamer 0:3853978178c0 326 wait_ms ( 15 );
screamer 0:3853978178c0 327 SI7021::SI7021_vector_data_t result_data;
screamer 0:3853978178c0 328 result = rht_sensor.SI7021_Conf(SI7021::SI7021_RESOLUTION_RH_11_TEMP_11,
screamer 0:3853978178c0 329 SI7021::SI7021_HTRE_DISABLED);
screamer 0:3853978178c0 330 result = rht_sensor.SI7021_GetElectronicSerialNumber(&result_data);
screamer 0:3853978178c0 331 result = rht_sensor.SI7021_GetFirmwareRevision(&result_data);
screamer 0:3853978178c0 332 tr_info("Si7021 Electronic Serial Number: %16x %16x\n",
screamer 0:3853978178c0 333 result_data.ElectronicSerialNumber_MSB,
screamer 0:3853978178c0 334 result_data.ElectronicSerialNumber_LSB);
screamer 0:3853978178c0 335 tr_info("Firmware Revision: %02x\r\n", result_data.FirmwareRevision);
screamer 0:3853978178c0 336
screamer 0:3853978178c0 337 measure_rht(temperature_res, humidity_res);
screamer 0:3853978178c0 338 eventQueue.call_every(RHT_MEASURING_INTERVAL * 1000,
screamer 0:3853978178c0 339 measure_rht, temperature_res, humidity_res);
screamer 0:3853978178c0 340 }
screamer 0:3853978178c0 341
screamer 0:3853978178c0 342 /* Initialize air quality sensor */
screamer 0:3853978178c0 343 if(!aqs.init()) {
screamer 0:3853978178c0 344 tr_err("Failed CCS811 init\r\n");
screamer 0:3853978178c0 345 } else {
screamer 0:3853978178c0 346 if(!aqs.mode(AMS_CCS811::SIXTY_SECOND)) {
screamer 0:3853978178c0 347 tr_err("Failed to set CCS811 mode\r\n");
screamer 0:3853978178c0 348 }
screamer 0:3853978178c0 349 ccs_int.fall(eventQueue.event(measure_airquality, co2_res, voc_res));
screamer 0:3853978178c0 350 aqs.enable_interupt(true);
screamer 0:3853978178c0 351 }
screamer 0:3853978178c0 352
screamer 0:3853978178c0 353 eventQueue.dispatch_forever();
screamer 0:3853978178c0 354 }