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:
Tue Mar 26 00:14:14 2019 +0000
Revision:
2:8d3f3f35f089
Parent:
1:cf0bd0446785
Child:
3:6647d74cf212
Add support for Si7210 Hall sensor
Add support for ICM20648 6-axis sensor

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 1:cf0bd0446785 10 // Thunderboard Sense 2 connects over 802.15.4 by default. Since the mesh stack is a bit iffy.
screamer 1:cf0bd0446785 11 // We'll register a 'network down' handler to act as a kind of watchdog for the Pelion DM Client.
screamer 0:3853978178c0 12 NetworkInterface *net = NetworkInterface::get_default_instance();
screamer 0:3853978178c0 13
screamer 1:cf0bd0446785 14 // Thunderboard Sense 2 has a 1M external flash, which is being shared between upgrade storage and LittleFS.
screamer 1:cf0bd0446785 15 // LittleFS is instantiated at the start of storage, until the start address for upgrade storage.
screamer 0:3853978178c0 16 // Currently, this split is at 256/768 for FS/upgrade.
screamer 0:3853978178c0 17 BlockDevice* bd = BlockDevice::get_default_instance();
screamer 0:3853978178c0 18 SlicingBlockDevice sd(bd, 0, MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS);
screamer 0:3853978178c0 19 LittleFileSystem fs("fs", &sd);
screamer 0:3853978178c0 20
screamer 1:cf0bd0446785 21 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
screamer 1:cf0bd0446785 22 // This is great because things such as network operations are illegal in ISR, so updating a resource in a button's fall() function is not allowed.
screamer 0:3853978178c0 23 EventQueue eventQueue;
screamer 0:3853978178c0 24
screamer 1:cf0bd0446785 25 InterruptIn button(BTN0);
screamer 0:3853978178c0 26
screamer 0:3853978178c0 27 //------------------------------------------------------------------------------
screamer 0:3853978178c0 28 // Includes and declarations for our sensor array
screamer 0:3853978178c0 29 #include "BMP280.h"
screamer 0:3853978178c0 30 #include "Si1133.h"
screamer 0:3853978178c0 31 #include "SI7021.h"
screamer 2:8d3f3f35f089 32 #include "Si7210.h"
screamer 0:3853978178c0 33 #include "AMS_CCS811.h"
screamer 2:8d3f3f35f089 34 #include "ICM20648.h"
screamer 0:3853978178c0 35
screamer 0:3853978178c0 36 // Define measurement intervals in seconds
screamer 1:cf0bd0446785 37 #define SENSORS_POLL_INTERVAL 1.0
screamer 1:cf0bd0446785 38 #define SEND_ALL_SENSORS
screamer 0:3853978178c0 39
screamer 0:3853978178c0 40 /* Turn on power supply to ENV sensor suite */
screamer 0:3853978178c0 41 DigitalOut env_en(PF9, 1);
screamer 0:3853978178c0 42 /* Turn on power to CCS811 sensor */
screamer 0:3853978178c0 43 DigitalOut ccs_en(PF14, 1);
screamer 2:8d3f3f35f089 44 /* Turn on power to hall effect sensor */
screamer 2:8d3f3f35f089 45 DigitalOut hall_en(PB10, 1);
screamer 2:8d3f3f35f089 46 /* Turn on power to IMU */
screamer 2:8d3f3f35f089 47 DigitalOut imu_en(PF8, 1);
screamer 0:3853978178c0 48
screamer 2:8d3f3f35f089 49 I2C env_i2c(PC4, PC5);
screamer 2:8d3f3f35f089 50 BMP280 sens_press_temp(env_i2c);
screamer 2:8d3f3f35f089 51 Si1133 sens_light(PC4, PC5);
screamer 2:8d3f3f35f089 52 SI7021 sens_hum_temp(PC4, PC5, SI7021::SI7021_ADDRESS, 400000);
screamer 2:8d3f3f35f089 53 I2C hall_i2c(PB8, PB9);
screamer 2:8d3f3f35f089 54 silabs::Si7210 sens_hall(&hall_i2c);
screamer 0:3853978178c0 55 InterruptIn ccs_int(PF13);
screamer 0:3853978178c0 56 I2C ccs_i2c(PB6, PB7);
screamer 2:8d3f3f35f089 57 AMS_CCS811 sens_aqs(&ccs_i2c, PF15);
screamer 2:8d3f3f35f089 58 ICM20648 sens_imu(PC0, PC1, PC2, PC3, PF12);
screamer 0:3853978178c0 59
screamer 1:cf0bd0446785 60 // Declaring pointers for access to Pelion Client resources outside of main()
screamer 1:cf0bd0446785 61 MbedCloudClientResource *res_button;
screamer 1:cf0bd0446785 62 MbedCloudClientResource *res_led;
screamer 0:3853978178c0 63
screamer 1:cf0bd0446785 64 #ifdef SEND_ALL_SENSORS
screamer 1:cf0bd0446785 65 MbedCloudClientResource *res_light;
screamer 2:8d3f3f35f089 66 MbedCloudClientResource *res_pressure;
screamer 2:8d3f3f35f089 67 MbedCloudClientResource *res_temperature1;
screamer 1:cf0bd0446785 68 MbedCloudClientResource *res_humidity;
screamer 2:8d3f3f35f089 69 MbedCloudClientResource *res_temperature2;
screamer 1:cf0bd0446785 70 MbedCloudClientResource *res_co2;
screamer 1:cf0bd0446785 71 MbedCloudClientResource *res_tvoc;
screamer 2:8d3f3f35f089 72 MbedCloudClientResource *res_field;
screamer 2:8d3f3f35f089 73 MbedCloudClientResource *res_temperature3;
screamer 2:8d3f3f35f089 74 MbedCloudClientResource *res_accelerometer_x;
screamer 2:8d3f3f35f089 75 MbedCloudClientResource *res_accelerometer_y;
screamer 2:8d3f3f35f089 76 MbedCloudClientResource *res_accelerometer_z;
screamer 2:8d3f3f35f089 77 MbedCloudClientResource *res_gyroscope_x;
screamer 2:8d3f3f35f089 78 MbedCloudClientResource *res_gyroscope_y;
screamer 2:8d3f3f35f089 79 MbedCloudClientResource *res_gyroscope_z;
screamer 2:8d3f3f35f089 80 MbedCloudClientResource *res_temperature4;
screamer 1:cf0bd0446785 81 #endif /* SEND_ALL_SENSORS */
screamer 0:3853978178c0 82
screamer 1:cf0bd0446785 83 // When the device is registered, this variable will be used to access various useful information, like device ID etc.
screamer 1:cf0bd0446785 84 static const ConnectorClientEndpointInfo* endpointInfo;
screamer 0:3853978178c0 85
screamer 0:3853978178c0 86
screamer 0:3853978178c0 87 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
screamer 0:3853978178c0 88 static int num_count = 0;
screamer 0:3853978178c0 89 static int event = 0;
screamer 0:3853978178c0 90
screamer 0:3853978178c0 91 static DigitalOut led_ch_red(PD11, 1);
screamer 0:3853978178c0 92 static DigitalOut led_ch_green(PD12, 1);
screamer 0:3853978178c0 93 static DigitalOut led_ch_blue(PD13, 1);
screamer 0:3853978178c0 94
screamer 0:3853978178c0 95 static DigitalOut led_com_0(PI0, 0);
screamer 0:3853978178c0 96 static DigitalOut led_com_1(PI1, 0);
screamer 0:3853978178c0 97 static DigitalOut led_com_2(PI2, 0);
screamer 0:3853978178c0 98 static DigitalOut led_com_3(PI3, 0);
screamer 0:3853978178c0 99
screamer 0:3853978178c0 100 static DigitalOut led_rgb_en(PJ14, 0);
screamer 0:3853978178c0 101
screamer 0:3853978178c0 102 if (buffer != NULL) {
screamer 1:cf0bd0446785 103 printf("POST received. POST data: %s\n", buffer);
screamer 0:3853978178c0 104
screamer 0:3853978178c0 105 if (event > 0) {
screamer 1:cf0bd0446785 106 printf("Not blinking since previous blink still in progress\n");
screamer 0:3853978178c0 107 return;
screamer 0:3853978178c0 108 }
screamer 0:3853978178c0 109 num_count = 0;
screamer 0:3853978178c0 110 for (size_t i = 0, num_arg = 0; i < 20 || buffer[i] == 0; i++) {
screamer 0:3853978178c0 111 if (buffer[i] == ':') {
screamer 0:3853978178c0 112 num_arg++;
screamer 0:3853978178c0 113 continue;
screamer 0:3853978178c0 114 }
screamer 0:3853978178c0 115
screamer 0:3853978178c0 116 if (buffer[i] >= '0' && buffer[i] <= '9') {
screamer 0:3853978178c0 117 switch (num_arg) {
screamer 0:3853978178c0 118 case 0:
screamer 1:cf0bd0446785 119 if (buffer[i] == '1') {
screamer 1:cf0bd0446785 120 led_ch_red = 1;
screamer 1:cf0bd0446785 121 } else {
screamer 1:cf0bd0446785 122 led_ch_red = 0;
screamer 1:cf0bd0446785 123 }
screamer 1:cf0bd0446785 124 break;
screamer 0:3853978178c0 125 case 1:
screamer 1:cf0bd0446785 126 if (buffer[i] == '1') {
screamer 1:cf0bd0446785 127 led_ch_green = 1;
screamer 1:cf0bd0446785 128 } else {
screamer 1:cf0bd0446785 129 led_ch_green = 0;
screamer 1:cf0bd0446785 130 }
screamer 1:cf0bd0446785 131 break;
screamer 0:3853978178c0 132 case 2:
screamer 1:cf0bd0446785 133 if (buffer[i] == '1') {
screamer 1:cf0bd0446785 134 led_ch_blue = 1;
screamer 1:cf0bd0446785 135 } else {
screamer 1:cf0bd0446785 136 led_ch_blue = 0;
screamer 1:cf0bd0446785 137 }
screamer 1:cf0bd0446785 138 break;
screamer 0:3853978178c0 139 case 3:
screamer 1:cf0bd0446785 140 num_count = ((buffer[i] - 0x30) * 2) - 1;
screamer 1:cf0bd0446785 141 printf("blinking %d\n", num_count);
screamer 1:cf0bd0446785 142 break;
screamer 0:3853978178c0 143 default:
screamer 1:cf0bd0446785 144 break;
screamer 0:3853978178c0 145 }
screamer 0:3853978178c0 146 } else {
screamer 0:3853978178c0 147 //garbage...
screamer 0:3853978178c0 148 continue;
screamer 0:3853978178c0 149 }
screamer 0:3853978178c0 150 if (num_count > 0) {
screamer 0:3853978178c0 151 break;
screamer 0:3853978178c0 152 }
screamer 0:3853978178c0 153 }
screamer 0:3853978178c0 154
screamer 0:3853978178c0 155 if (num_count > 0) {
screamer 0:3853978178c0 156 led_rgb_en = 1;
screamer 0:3853978178c0 157 led_com_0 = 1;
screamer 0:3853978178c0 158 led_com_1 = 1;
screamer 0:3853978178c0 159 event = eventQueue.call_in(1000, blink_callback, resource, (const uint8_t *)NULL, 0);
screamer 0:3853978178c0 160 if (event == 0) {
screamer 0:3853978178c0 161 led_rgb_en = 0;
screamer 0:3853978178c0 162 num_count = 0;
screamer 0:3853978178c0 163 }
screamer 0:3853978178c0 164 }
screamer 0:3853978178c0 165 } else {
screamer 0:3853978178c0 166 num_count--;
screamer 0:3853978178c0 167 led_com_0 = (num_count & 1);
screamer 0:3853978178c0 168 led_com_1 = (num_count & 1);
screamer 0:3853978178c0 169
screamer 0:3853978178c0 170 if (num_count == 0) {
screamer 0:3853978178c0 171 led_rgb_en = 0;
screamer 0:3853978178c0 172 event = 0;
screamer 0:3853978178c0 173 } else {
screamer 0:3853978178c0 174 event = eventQueue.call_in(1000, blink_callback, resource, (const uint8_t *)NULL, 0);
screamer 0:3853978178c0 175 if (event == 0) {
screamer 0:3853978178c0 176 led_rgb_en = 0;
screamer 0:3853978178c0 177 num_count = 0;
screamer 0:3853978178c0 178 }
screamer 0:3853978178c0 179 }
screamer 0:3853978178c0 180 }
screamer 0:3853978178c0 181 }
screamer 0:3853978178c0 182
screamer 1:cf0bd0446785 183 /**
screamer 1:cf0bd0446785 184 * Button function triggered by the physical button press.
screamer 1:cf0bd0446785 185 */
screamer 1:cf0bd0446785 186 void button_press() {
screamer 1:cf0bd0446785 187 int v = res_button->get_value_int() + 1;
screamer 1:cf0bd0446785 188 res_button->set_value(v);
screamer 1:cf0bd0446785 189 printf("*** Button clicked %d times \n", v);
screamer 1:cf0bd0446785 190 }
screamer 1:cf0bd0446785 191
screamer 1:cf0bd0446785 192 /**
screamer 1:cf0bd0446785 193 * Notification callback handler
screamer 1:cf0bd0446785 194 * @param resource The resource that triggered the callback
screamer 1:cf0bd0446785 195 * @param status The delivery status of the notification
screamer 1:cf0bd0446785 196 */
screamer 1:cf0bd0446785 197 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
screamer 1:cf0bd0446785 198 printf("*** Button notification, status %s (%d) \n", MbedCloudClientResource::delivery_status_to_string(status), status);
screamer 1:cf0bd0446785 199 }
screamer 1:cf0bd0446785 200
screamer 1:cf0bd0446785 201 /**
screamer 1:cf0bd0446785 202 * Registration callback handler
screamer 1:cf0bd0446785 203 * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
screamer 1:cf0bd0446785 204 */
screamer 1:cf0bd0446785 205 void registered(const ConnectorClientEndpointInfo *endpoint) {
screamer 1:cf0bd0446785 206 printf("Registered to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
screamer 1:cf0bd0446785 207 endpointInfo = endpoint;
screamer 1:cf0bd0446785 208 }
screamer 1:cf0bd0446785 209
screamer 1:cf0bd0446785 210 /**
screamer 1:cf0bd0446785 211 * Initialize sensors
screamer 1:cf0bd0446785 212 */
screamer 1:cf0bd0446785 213 void sensors_init() {
screamer 2:8d3f3f35f089 214 sens_press_temp.initialize();
screamer 1:cf0bd0446785 215
screamer 2:8d3f3f35f089 216 if (!sens_light.open()) {
screamer 2:8d3f3f35f089 217 printf("ERROR: Failed to initialize sensor Si1133\n");
screamer 2:8d3f3f35f089 218 }
screamer 1:cf0bd0446785 219
screamer 2:8d3f3f35f089 220 SI7021::SI7021_status_t result = sens_hum_temp.SI7021_SoftReset();
screamer 1:cf0bd0446785 221 if (result == SI7021::SI7021_SUCCESS) {
screamer 1:cf0bd0446785 222 wait_ms(15);
screamer 1:cf0bd0446785 223 SI7021::SI7021_vector_data_t result_data;
screamer 2:8d3f3f35f089 224 result = sens_hum_temp.SI7021_Conf(SI7021::SI7021_RESOLUTION_RH_11_TEMP_11, SI7021::SI7021_HTRE_DISABLED);
screamer 2:8d3f3f35f089 225 result = sens_hum_temp.SI7021_GetElectronicSerialNumber(&result_data);
screamer 2:8d3f3f35f089 226 result = sens_hum_temp.SI7021_GetFirmwareRevision(&result_data);
screamer 1:cf0bd0446785 227 printf("Si7021 Electronic Serial Number: %16x %16x, firmware rev %02x\n",
screamer 2:8d3f3f35f089 228 result_data.ElectronicSerialNumber_MSB,
screamer 2:8d3f3f35f089 229 result_data.ElectronicSerialNumber_LSB,
screamer 2:8d3f3f35f089 230 result_data.FirmwareRevision);
screamer 1:cf0bd0446785 231 }
screamer 1:cf0bd0446785 232
screamer 2:8d3f3f35f089 233 if (!sens_aqs.init()) {
screamer 2:8d3f3f35f089 234 printf("ERROR: Failed to initialize sensor CCS811\n");
screamer 1:cf0bd0446785 235 } else {
screamer 2:8d3f3f35f089 236 if (!sens_aqs.mode(AMS_CCS811::SIXTY_SECOND)) {
screamer 2:8d3f3f35f089 237 printf("ERROR: Failed to set mode for sensor CCS811\n");
screamer 1:cf0bd0446785 238 }
screamer 2:8d3f3f35f089 239 // sens_aqs.enable_interupt(true);
screamer 2:8d3f3f35f089 240 }
screamer 2:8d3f3f35f089 241
screamer 2:8d3f3f35f089 242 if (!sens_imu.open()) {
screamer 2:8d3f3f35f089 243 printf("ERROR: Failed to initialize sensor ICM20648\n");
screamer 1:cf0bd0446785 244 }
screamer 1:cf0bd0446785 245 }
screamer 1:cf0bd0446785 246
screamer 1:cf0bd0446785 247 /**
screamer 1:cf0bd0446785 248 * Update sensors and report their values.
screamer 1:cf0bd0446785 249 * This function is called periodically.
screamer 1:cf0bd0446785 250 */
screamer 1:cf0bd0446785 251 void sensors_update() {
screamer 2:8d3f3f35f089 252 SI7021::SI7021_status_t rht_reading, humidity_reading, temp2_reading;
screamer 2:8d3f3f35f089 253 SI7021::SI7021_vector_data_t humidity_data, temp2_data;
screamer 1:cf0bd0446785 254
screamer 2:8d3f3f35f089 255 // BMP280 pressure and temperature (2)
screamer 2:8d3f3f35f089 256 float pressure_value = sens_press_temp.getPressure(), temp1_value = sens_press_temp.getPressure();
screamer 1:cf0bd0446785 257
screamer 2:8d3f3f35f089 258 // Si7021 humidity and temperature (1)
screamer 2:8d3f3f35f089 259 rht_reading = sens_hum_temp.SI7021_TriggerHumidity(SI7021::SI7021_NO_HOLD_MASTER_MODE);
screamer 1:cf0bd0446785 260 if (rht_reading == SI7021::SI7021_SUCCESS) {
screamer 1:cf0bd0446785 261 wait_ms(30);
screamer 2:8d3f3f35f089 262 humidity_reading = sens_hum_temp.SI7021_ReadHumidity(&humidity_data);
screamer 2:8d3f3f35f089 263 temp2_reading = sens_hum_temp.SI7021_ReadTemperatureFromRH(&temp2_data);
screamer 2:8d3f3f35f089 264 sens_aqs.env_data(humidity_data.RelativeHumidity, temp2_data.Temperature);
screamer 1:cf0bd0446785 265 }
screamer 1:cf0bd0446785 266
screamer 2:8d3f3f35f089 267 // Si1133 light and UV index
screamer 2:8d3f3f35f089 268 float light_value, uv_index_value;
screamer 2:8d3f3f35f089 269 bool light_reading = sens_light.get_light_and_uv(&light_value, &uv_index_value);
screamer 2:8d3f3f35f089 270
screamer 2:8d3f3f35f089 271 // CCS811 air quality CO2 and TVoC
screamer 2:8d3f3f35f089 272 sens_aqs.has_new_data();
screamer 2:8d3f3f35f089 273 int co2_value = sens_aqs.co2_read();
screamer 2:8d3f3f35f089 274 int tvoc_value = sens_aqs.tvoc_read();
screamer 2:8d3f3f35f089 275
screamer 2:8d3f3f35f089 276 // Si7210 field and temperature (3)
screamer 2:8d3f3f35f089 277 sens_hall.measureOnce();
screamer 2:8d3f3f35f089 278 float field_value = sens_hall.getFieldStrength() / 1000, temp3_value = sens_hall.getTemperature() / 1000;
screamer 1:cf0bd0446785 279
screamer 2:8d3f3f35f089 280 float acc_x, acc_y, acc_z, gyr_x, gyr_y, gyr_z, temp4_value;
screamer 2:8d3f3f35f089 281 sens_imu.get_accelerometer(&acc_x, &acc_y, &acc_z);
screamer 2:8d3f3f35f089 282 sens_imu.get_gyroscope(&gyr_x, &gyr_y, &gyr_z);
screamer 2:8d3f3f35f089 283 sens_imu.get_temperature(&temp4_value);
screamer 1:cf0bd0446785 284
screamer 2:8d3f3f35f089 285 printf(" \n");
screamer 2:8d3f3f35f089 286 printf("BMP280 temp: %7.2f C, pressure: %7.2f mbar \n", temp1_value, pressure_value);
screamer 2:8d3f3f35f089 287 printf("Si7021 temp: %7.2f C, humidity: %7.2f %% \n", temp2_data.Temperature, humidity_data.RelativeHumidity);
screamer 2:8d3f3f35f089 288 printf("Si7210 temp: %7.2f C, field: %7.2f mT \n", temp3_value, field_value);
screamer 2:8d3f3f35f089 289 printf("Si1133 light: %7.2f lux, UV level: %7.2f \n", light_value, uv_index_value);
screamer 2:8d3f3f35f089 290 printf("CCS811 CO2: %7d ppm, VoC: %7d ppb \n", co2_value, tvoc_value);
screamer 2:8d3f3f35f089 291 printf("ICM20648 acc: %7.2f x, %7.2f y, %7.2f z [mg] \n", acc_x, acc_y, acc_z);
screamer 2:8d3f3f35f089 292 printf("ICM20648 gyro: %7.2f x, %7.2f y, %7.2f z [mdps] \n", gyr_x, gyr_y, gyr_z);
screamer 2:8d3f3f35f089 293
screamer 2:8d3f3f35f089 294 printf("\r\033[8A");
screamer 1:cf0bd0446785 295
screamer 1:cf0bd0446785 296 if (endpointInfo) {
screamer 1:cf0bd0446785 297 #ifdef SEND_ALL_SENSORS
screamer 2:8d3f3f35f089 298 res_pressure->set_value(pressure_value);
screamer 2:8d3f3f35f089 299 res_temperature1->set_value(temp1_value);
screamer 2:8d3f3f35f089 300
screamer 1:cf0bd0446785 301 if (humidity_reading == SI7021::SI7021_SUCCESS) {
screamer 1:cf0bd0446785 302 res_humidity->set_value(humidity_data.RelativeHumidity);
screamer 1:cf0bd0446785 303 }
screamer 2:8d3f3f35f089 304 if (temp2_reading == SI7021::SI7021_SUCCESS) {
screamer 2:8d3f3f35f089 305 res_temperature2->set_value(temp2_data.Temperature);
screamer 2:8d3f3f35f089 306 }
screamer 2:8d3f3f35f089 307
screamer 2:8d3f3f35f089 308 res_field->set_value(field_value);
screamer 2:8d3f3f35f089 309 res_temperature3->set_value(temp3_value);
screamer 2:8d3f3f35f089 310
screamer 2:8d3f3f35f089 311 if (light_reading) {
screamer 2:8d3f3f35f089 312 res_light->set_value(light_value);
screamer 1:cf0bd0446785 313 }
screamer 2:8d3f3f35f089 314
screamer 2:8d3f3f35f089 315 res_co2->set_value(co2_value);
screamer 2:8d3f3f35f089 316 res_tvoc->set_value(tvoc_value);
screamer 2:8d3f3f35f089 317
screamer 2:8d3f3f35f089 318 res_accelerometer_x->set_value(acc_x);
screamer 2:8d3f3f35f089 319 res_accelerometer_y->set_value(acc_y);
screamer 2:8d3f3f35f089 320 res_accelerometer_z->set_value(acc_z);
screamer 2:8d3f3f35f089 321 res_gyroscope_x->set_value(gyr_x);
screamer 2:8d3f3f35f089 322 res_gyroscope_y->set_value(gyr_y);
screamer 2:8d3f3f35f089 323 res_gyroscope_z->set_value(gyr_z);
screamer 2:8d3f3f35f089 324
screamer 2:8d3f3f35f089 325 res_temperature4->set_value(temp4_value);
screamer 1:cf0bd0446785 326 #endif /* SEND_ALL_SENSORS */
screamer 1:cf0bd0446785 327 }
screamer 1:cf0bd0446785 328 }
screamer 1:cf0bd0446785 329
screamer 0:3853978178c0 330 int main() {
screamer 1:cf0bd0446785 331 printf("\nStarting Simple Pelion Device Management Client example\n");
screamer 1:cf0bd0446785 332
screamer 1:cf0bd0446785 333 int storage_status = fs.mount(&sd);
screamer 1:cf0bd0446785 334 if (storage_status != 0) {
screamer 1:cf0bd0446785 335 printf("Storage mounting failed.\n");
screamer 1:cf0bd0446785 336 }
screamer 1:cf0bd0446785 337
screamer 1:cf0bd0446785 338 #if USE_BUTTON == 1
screamer 0:3853978178c0 339 // If the User button is pressed ons start, then format storage.
screamer 1:cf0bd0446785 340 bool btn_pressed = (button.read() == MBED_CONF_APP_BUTTON_PRESSED_STATE);
screamer 1:cf0bd0446785 341 if (btn_pressed) {
screamer 1:cf0bd0446785 342 printf("User button is pushed on start...\n");
screamer 1:cf0bd0446785 343 }
screamer 1:cf0bd0446785 344 #else
screamer 1:cf0bd0446785 345 bool btn_pressed = FALSE;
screamer 1:cf0bd0446785 346 #endif /* USE_BUTTON */
screamer 1:cf0bd0446785 347
screamer 1:cf0bd0446785 348 if (storage_status || btn_pressed) {
screamer 1:cf0bd0446785 349 printf("Formatting the storage...\n");
screamer 1:cf0bd0446785 350 int storage_status = StorageHelper::format(&fs, &sd);
screamer 0:3853978178c0 351 if (storage_status != 0) {
screamer 0:3853978178c0 352 printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
screamer 0:3853978178c0 353 }
screamer 0:3853978178c0 354 } else {
screamer 0:3853978178c0 355 printf("You can hold the user button during boot to format the storage and change the device identity.\n");
screamer 0:3853978178c0 356 }
screamer 0:3853978178c0 357
screamer 0:3853978178c0 358 Nanostack::get_instance(); // ensure Nanostack is initialised
screamer 0:3853978178c0 359 ns_file_system_set_root_path("/fs/");
screamer 0:3853978178c0 360
screamer 1:cf0bd0446785 361 // Connect to the internet (DHCP is expected to be on)
screamer 1:cf0bd0446785 362 printf("Connecting to the network using 802.15.4...\n");
screamer 1:cf0bd0446785 363
screamer 1:cf0bd0446785 364 nsapi_error_t net_status = -1;
screamer 1:cf0bd0446785 365 for (int tries = 0; tries < 3; tries++) {
screamer 1:cf0bd0446785 366 net_status = net->connect();
screamer 1:cf0bd0446785 367 if (net_status == NSAPI_ERROR_OK) {
screamer 1:cf0bd0446785 368 break;
screamer 1:cf0bd0446785 369 } else {
screamer 1:cf0bd0446785 370 printf("Unable to connect to network. Retrying...\n");
screamer 1:cf0bd0446785 371 }
screamer 1:cf0bd0446785 372 }
screamer 1:cf0bd0446785 373
screamer 1:cf0bd0446785 374 if (net_status != NSAPI_ERROR_OK) {
screamer 1:cf0bd0446785 375 printf("ERROR: Connecting to the network failed (%d)!\n", net_status);
screamer 1:cf0bd0446785 376 return -1;
screamer 1:cf0bd0446785 377 }
screamer 1:cf0bd0446785 378
screamer 1:cf0bd0446785 379 printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
screamer 1:cf0bd0446785 380
screamer 1:cf0bd0446785 381 printf("Initializing Pelion Device Management Client...\n");
screamer 0:3853978178c0 382
screamer 0:3853978178c0 383 /* Initialize Simple Pelion DM Client */
screamer 0:3853978178c0 384 SimpleMbedCloudClient client(net, &sd, &fs);
screamer 1:cf0bd0446785 385 int client_status = client.init();
screamer 1:cf0bd0446785 386 if (client_status != 0) {
screamer 1:cf0bd0446785 387 printf("ERROR: Pelion Client initialization failed (%d)\n", client_status);
screamer 1:cf0bd0446785 388 return -1;
screamer 1:cf0bd0446785 389 }
screamer 0:3853978178c0 390
screamer 0:3853978178c0 391 /* Create resources */
screamer 2:8d3f3f35f089 392 res_led = client.create_resource("3201/0/5853", "LED blinking (R:G:B:count)");
screamer 1:cf0bd0446785 393 res_led->observable(false);
screamer 1:cf0bd0446785 394 res_led->set_value("0:0:0:0");
screamer 1:cf0bd0446785 395 res_led->attach_post_callback(blink_callback);
screamer 1:cf0bd0446785 396 res_led->methods(M2MMethod::POST);
screamer 0:3853978178c0 397
screamer 2:8d3f3f35f089 398 res_button = client.create_resource("3200/0/5501", "Button Click Count");
screamer 1:cf0bd0446785 399 res_button->set_value(0);
screamer 1:cf0bd0446785 400 res_button->methods(M2MMethod::GET);
screamer 1:cf0bd0446785 401 res_button->observable(true);
screamer 1:cf0bd0446785 402 res_button->attach_notification_callback(button_callback);
screamer 0:3853978178c0 403
screamer 1:cf0bd0446785 404 #ifdef SEND_ALL_SENSORS
screamer 2:8d3f3f35f089 405 res_light = client.create_resource("3301/0/5853", "LightIntensity (LUX)");
screamer 1:cf0bd0446785 406 res_light->set_value(0);
screamer 1:cf0bd0446785 407 res_light->observable(true);
screamer 1:cf0bd0446785 408 res_light->methods(M2MMethod::GET);
screamer 1:cf0bd0446785 409
screamer 2:8d3f3f35f089 410 // Sensor BMP280
screamer 2:8d3f3f35f089 411 res_pressure = client.create_resource("3323/0/5853", "Barometric pressure (hPa)");
screamer 2:8d3f3f35f089 412 res_pressure->set_value(0);
screamer 2:8d3f3f35f089 413 res_pressure->observable(true);
screamer 2:8d3f3f35f089 414 res_pressure->methods(M2MMethod::GET);
screamer 0:3853978178c0 415
screamer 2:8d3f3f35f089 416 res_temperature1 = client.create_resource("3303/0/5853", "Temperature BMP280 (C)");
screamer 2:8d3f3f35f089 417 res_temperature1->set_value(0);
screamer 2:8d3f3f35f089 418 res_temperature1->observable(true);
screamer 2:8d3f3f35f089 419 res_temperature1->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 420 res_temperature2->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 421
screamer 2:8d3f3f35f089 422 // Sensor Si7021
screamer 1:cf0bd0446785 423 res_humidity = client.create_resource("3304/0/5853", "Humidity (%)");
screamer 1:cf0bd0446785 424 res_humidity->set_value(0);
screamer 1:cf0bd0446785 425 res_humidity->observable(true);
screamer 1:cf0bd0446785 426 res_humidity->methods(M2MMethod::GET);
screamer 0:3853978178c0 427
screamer 2:8d3f3f35f089 428 res_temperature2 = client.create_resource("3303/1/5853", "Temperature Si7021 (C)");
screamer 2:8d3f3f35f089 429 res_temperature2->set_value(0);
screamer 2:8d3f3f35f089 430 res_temperature2->observable(true);
screamer 0:3853978178c0 431
screamer 2:8d3f3f35f089 432 // Sensor Si7210
screamer 2:8d3f3f35f089 433 res_field = client.create_resource("3304/0/5853", "Magnetic Field (mT)");
screamer 2:8d3f3f35f089 434 res_field->set_value(0);
screamer 2:8d3f3f35f089 435 res_field->observable(true);
screamer 2:8d3f3f35f089 436 res_field->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 437
screamer 2:8d3f3f35f089 438 res_temperature3 = client.create_resource("3303/2/5853", "Temperature Si7210 (C)");
screamer 2:8d3f3f35f089 439 res_temperature3->set_value(0);
screamer 2:8d3f3f35f089 440 res_temperature3->observable(true);
screamer 2:8d3f3f35f089 441 res_temperature3->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 442
screamer 2:8d3f3f35f089 443 // Sensor CCS811
screamer 1:cf0bd0446785 444 res_co2 = client.create_resource("33255/0/5853", "CO2 (ppm)");
screamer 1:cf0bd0446785 445 res_co2->set_value(0);
screamer 1:cf0bd0446785 446 res_co2->observable(true);
screamer 1:cf0bd0446785 447 res_co2->methods(M2MMethod::GET);
screamer 0:3853978178c0 448
screamer 1:cf0bd0446785 449 res_tvoc = client.create_resource("33256/0/5853", "VOC (ppm)");
screamer 1:cf0bd0446785 450 res_tvoc->set_value(0);
screamer 1:cf0bd0446785 451 res_tvoc->observable(true);
screamer 1:cf0bd0446785 452 res_tvoc->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 453
screamer 2:8d3f3f35f089 454 // Sensor ICM20648
screamer 2:8d3f3f35f089 455 res_accelerometer_x = client.create_resource("3313/0/5702", "Accelerometer X");
screamer 2:8d3f3f35f089 456 res_accelerometer_x->set_value(0);
screamer 2:8d3f3f35f089 457 res_accelerometer_x->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 458 res_accelerometer_x->observable(true);
screamer 2:8d3f3f35f089 459
screamer 2:8d3f3f35f089 460 res_accelerometer_y = client.create_resource("3313/0/5703", "Accelerometer Y");
screamer 2:8d3f3f35f089 461 res_accelerometer_y->set_value(0);
screamer 2:8d3f3f35f089 462 res_accelerometer_y->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 463 res_accelerometer_y->observable(true);
screamer 2:8d3f3f35f089 464
screamer 2:8d3f3f35f089 465 res_accelerometer_z = client.create_resource("3313/0/5704", "Accelerometer Z");
screamer 2:8d3f3f35f089 466 res_accelerometer_z->set_value(0);
screamer 2:8d3f3f35f089 467 res_accelerometer_z->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 468 res_accelerometer_z->observable(true);
screamer 2:8d3f3f35f089 469
screamer 2:8d3f3f35f089 470 res_gyroscope_x = client.create_resource("3334/0/5702", "Gyroscope X");
screamer 2:8d3f3f35f089 471 res_gyroscope_x->set_value(0);
screamer 2:8d3f3f35f089 472 res_gyroscope_x->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 473 res_gyroscope_x->observable(true);
screamer 2:8d3f3f35f089 474
screamer 2:8d3f3f35f089 475 res_gyroscope_y = client.create_resource("3334/0/5703", "Gyroscope Y");
screamer 2:8d3f3f35f089 476 res_gyroscope_y->set_value(0);
screamer 2:8d3f3f35f089 477 res_gyroscope_y->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 478 res_gyroscope_y->observable(true);
screamer 2:8d3f3f35f089 479
screamer 2:8d3f3f35f089 480 res_gyroscope_z = client.create_resource("3334/0/5704", "Gyroscope Z");
screamer 2:8d3f3f35f089 481 res_gyroscope_z->set_value(0);
screamer 2:8d3f3f35f089 482 res_gyroscope_z->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 483 res_gyroscope_z->observable(true);
screamer 2:8d3f3f35f089 484
screamer 2:8d3f3f35f089 485 res_temperature4 = client.create_resource("3303/3/5853", "Temperature ICM20648 (C)");
screamer 2:8d3f3f35f089 486 res_temperature4->set_value(0);
screamer 2:8d3f3f35f089 487 res_temperature4->observable(true);
screamer 2:8d3f3f35f089 488 res_temperature4->methods(M2MMethod::GET);
screamer 1:cf0bd0446785 489 #endif /* SEND_ALL_SENSORS */
screamer 0:3853978178c0 490
screamer 1:cf0bd0446785 491 sensors_init();
screamer 1:cf0bd0446785 492
screamer 1:cf0bd0446785 493 // Callback that fires when registering is complete
screamer 1:cf0bd0446785 494 client.on_registered(&registered);
screamer 0:3853978178c0 495
screamer 0:3853978178c0 496 /* Register the device */
screamer 0:3853978178c0 497 client.register_and_connect();
screamer 0:3853978178c0 498
screamer 1:cf0bd0446785 499 button.fall(eventQueue.event(&button_press));
screamer 0:3853978178c0 500
screamer 1:cf0bd0446785 501 // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
screamer 1:cf0bd0446785 502 Ticker timer;
screamer 1:cf0bd0446785 503 timer.attach(eventQueue.event(&sensors_update), SENSORS_POLL_INTERVAL);
screamer 0:3853978178c0 504
screamer 0:3853978178c0 505 eventQueue.dispatch_forever();
screamer 1:cf0bd0446785 506 }