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 10:29:33 2019 +0000
Revision:
3:6647d74cf212
Parent:
2:8d3f3f35f089
Child:
4:0b54e0395ac1
Tune application output and fix sporadic segfault

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 3:6647d74cf212 37 #define SENSORS_POLL_INTERVAL 3.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 3:6647d74cf212 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 SI7021::SI7021_status_t result = sens_hum_temp.SI7021_SoftReset();
screamer 1:cf0bd0446785 217 if (result == SI7021::SI7021_SUCCESS) {
screamer 1:cf0bd0446785 218 wait_ms(15);
screamer 1:cf0bd0446785 219 SI7021::SI7021_vector_data_t result_data;
screamer 3:6647d74cf212 220 result = sens_hum_temp.SI7021_Conf(SI7021::SI7021_RESOLUTION_RH_11_TEMP_11,
screamer 3:6647d74cf212 221 SI7021::SI7021_HTRE_DISABLED);
screamer 2:8d3f3f35f089 222 result = sens_hum_temp.SI7021_GetElectronicSerialNumber(&result_data);
screamer 2:8d3f3f35f089 223 result = sens_hum_temp.SI7021_GetFirmwareRevision(&result_data);
screamer 1:cf0bd0446785 224 printf("Si7021 Electronic Serial Number: %16x %16x, firmware rev %02x\n",
screamer 3:6647d74cf212 225 result_data.ElectronicSerialNumber_MSB,
screamer 3:6647d74cf212 226 result_data.ElectronicSerialNumber_LSB,
screamer 3:6647d74cf212 227 result_data.FirmwareRevision);
screamer 3:6647d74cf212 228 }
screamer 3:6647d74cf212 229
screamer 3:6647d74cf212 230 if (!sens_light.open()) {
screamer 3:6647d74cf212 231 printf("ERROR: Failed to initialize sensor Si1133\n");
screamer 1:cf0bd0446785 232 }
screamer 1:cf0bd0446785 233
screamer 2:8d3f3f35f089 234 if (!sens_aqs.init()) {
screamer 2:8d3f3f35f089 235 printf("ERROR: Failed to initialize sensor CCS811\n");
screamer 1:cf0bd0446785 236 } else {
screamer 2:8d3f3f35f089 237 if (!sens_aqs.mode(AMS_CCS811::SIXTY_SECOND)) {
screamer 2:8d3f3f35f089 238 printf("ERROR: Failed to set mode for sensor CCS811\n");
screamer 1:cf0bd0446785 239 }
screamer 2:8d3f3f35f089 240 // sens_aqs.enable_interupt(true);
screamer 2:8d3f3f35f089 241 }
screamer 3:6647d74cf212 242
screamer 2:8d3f3f35f089 243 if (!sens_imu.open()) {
screamer 2:8d3f3f35f089 244 printf("ERROR: Failed to initialize sensor ICM20648\n");
screamer 1:cf0bd0446785 245 }
screamer 1:cf0bd0446785 246 }
screamer 1:cf0bd0446785 247
screamer 1:cf0bd0446785 248 /**
screamer 1:cf0bd0446785 249 * Update sensors and report their values.
screamer 1:cf0bd0446785 250 * This function is called periodically.
screamer 1:cf0bd0446785 251 */
screamer 1:cf0bd0446785 252 void sensors_update() {
screamer 3:6647d74cf212 253 SI7021::SI7021_status_t sens_hum_temp_reading, humidity_reading, temp2_reading;
screamer 2:8d3f3f35f089 254 SI7021::SI7021_vector_data_t humidity_data, temp2_data;
screamer 1:cf0bd0446785 255
screamer 3:6647d74cf212 256 // BMP280 pressure and temperature (1)
screamer 3:6647d74cf212 257 float pressure_value = sens_press_temp.getPressure();
screamer 3:6647d74cf212 258 float temp1_value = sens_press_temp.getTemperature();
screamer 1:cf0bd0446785 259
screamer 3:6647d74cf212 260 // Si7021 humidity and temperature (2)
screamer 3:6647d74cf212 261 sens_hum_temp_reading = sens_hum_temp.SI7021_TriggerHumidity(SI7021::SI7021_NO_HOLD_MASTER_MODE);
screamer 3:6647d74cf212 262 if (sens_hum_temp_reading == SI7021::SI7021_SUCCESS) {
screamer 1:cf0bd0446785 263 wait_ms(30);
screamer 2:8d3f3f35f089 264 humidity_reading = sens_hum_temp.SI7021_ReadHumidity(&humidity_data);
screamer 2:8d3f3f35f089 265 temp2_reading = sens_hum_temp.SI7021_ReadTemperatureFromRH(&temp2_data);
screamer 2:8d3f3f35f089 266 sens_aqs.env_data(humidity_data.RelativeHumidity, temp2_data.Temperature);
screamer 1:cf0bd0446785 267 }
screamer 1:cf0bd0446785 268
screamer 2:8d3f3f35f089 269 // Si1133 light and UV index
screamer 2:8d3f3f35f089 270 float light_value, uv_index_value;
screamer 2:8d3f3f35f089 271 bool light_reading = sens_light.get_light_and_uv(&light_value, &uv_index_value);
screamer 2:8d3f3f35f089 272
screamer 2:8d3f3f35f089 273 // CCS811 air quality CO2 and TVoC
screamer 2:8d3f3f35f089 274 sens_aqs.has_new_data();
screamer 2:8d3f3f35f089 275 int co2_value = sens_aqs.co2_read();
screamer 2:8d3f3f35f089 276 int tvoc_value = sens_aqs.tvoc_read();
screamer 2:8d3f3f35f089 277
screamer 2:8d3f3f35f089 278 // Si7210 field and temperature (3)
screamer 2:8d3f3f35f089 279 sens_hall.measureOnce();
screamer 2:8d3f3f35f089 280 float field_value = sens_hall.getFieldStrength() / 1000, temp3_value = sens_hall.getTemperature() / 1000;
screamer 3:6647d74cf212 281
screamer 3:6647d74cf212 282 // ICM20648 accelerometer and gyroscope
screamer 2:8d3f3f35f089 283 float acc_x, acc_y, acc_z, gyr_x, gyr_y, gyr_z, temp4_value;
screamer 2:8d3f3f35f089 284 sens_imu.get_accelerometer(&acc_x, &acc_y, &acc_z);
screamer 2:8d3f3f35f089 285 sens_imu.get_gyroscope(&gyr_x, &gyr_y, &gyr_z);
screamer 2:8d3f3f35f089 286 sens_imu.get_temperature(&temp4_value);
screamer 1:cf0bd0446785 287
screamer 2:8d3f3f35f089 288 printf(" \n");
screamer 3:6647d74cf212 289 printf("BMP280 temp: %7.2f C, pressure: %7.2f [mbar] \n", temp1_value, pressure_value);
screamer 3:6647d74cf212 290 printf("Si7021 temp: %7.2f C, humidity: %7.2f %% \n", temp2_data.Temperature, humidity_data.RelativeHumidity);
screamer 3:6647d74cf212 291 printf("Si7210 temp: %7.2f C, field: %7.2f [mT] \n", temp3_value, field_value);
screamer 3:6647d74cf212 292 printf("Si1133 light: %7.2f lux, UV level: %7.2f \n", light_value, uv_index_value);
screamer 3:6647d74cf212 293 printf("CCS811 CO2: %7d ppm, VoC: %7d ppb \n", co2_value, tvoc_value);
screamer 3:6647d74cf212 294 printf("ICM20648 acc: %7.2f x, %6.2f y, %7.2f z [mg] \n", acc_x, acc_y, acc_z);
screamer 3:6647d74cf212 295 printf("ICM20648 gyro: %7.2f x, %6.2f y, %7.2f z [mdps] \n", gyr_x, gyr_y, gyr_z);
screamer 2:8d3f3f35f089 296
screamer 2:8d3f3f35f089 297 printf("\r\033[8A");
screamer 1:cf0bd0446785 298
screamer 1:cf0bd0446785 299 if (endpointInfo) {
screamer 1:cf0bd0446785 300 #ifdef SEND_ALL_SENSORS
screamer 3:6647d74cf212 301 res_pressure->set_value((float)pressure_value);
screamer 3:6647d74cf212 302 res_temperature1->set_value((float)temp1_value);
screamer 3:6647d74cf212 303
screamer 1:cf0bd0446785 304 if (humidity_reading == SI7021::SI7021_SUCCESS) {
screamer 3:6647d74cf212 305 res_humidity->set_value((float)humidity_data.RelativeHumidity);
screamer 1:cf0bd0446785 306 }
screamer 2:8d3f3f35f089 307 if (temp2_reading == SI7021::SI7021_SUCCESS) {
screamer 3:6647d74cf212 308 res_temperature2->set_value((float)temp2_data.Temperature);
screamer 2:8d3f3f35f089 309 }
screamer 2:8d3f3f35f089 310
screamer 3:6647d74cf212 311 res_field->set_value((float)field_value);
screamer 3:6647d74cf212 312 res_temperature3->set_value((float)temp3_value);
screamer 2:8d3f3f35f089 313
screamer 2:8d3f3f35f089 314 if (light_reading) {
screamer 3:6647d74cf212 315 res_light->set_value((float)light_value);
screamer 1:cf0bd0446785 316 }
screamer 2:8d3f3f35f089 317
screamer 2:8d3f3f35f089 318 res_co2->set_value(co2_value);
screamer 2:8d3f3f35f089 319 res_tvoc->set_value(tvoc_value);
screamer 2:8d3f3f35f089 320
screamer 3:6647d74cf212 321 res_accelerometer_x->set_value((float)acc_x);
screamer 3:6647d74cf212 322 res_accelerometer_y->set_value((float)acc_y);
screamer 3:6647d74cf212 323 res_accelerometer_z->set_value((float)acc_z);
screamer 3:6647d74cf212 324 res_gyroscope_x->set_value((float)gyr_x);
screamer 3:6647d74cf212 325 res_gyroscope_y->set_value((float)gyr_y);
screamer 3:6647d74cf212 326 res_gyroscope_z->set_value((float)gyr_z);
screamer 1:cf0bd0446785 327 #endif /* SEND_ALL_SENSORS */
screamer 1:cf0bd0446785 328 }
screamer 1:cf0bd0446785 329 }
screamer 1:cf0bd0446785 330
screamer 0:3853978178c0 331 int main() {
screamer 1:cf0bd0446785 332 printf("\nStarting Simple Pelion Device Management Client example\n");
screamer 1:cf0bd0446785 333
screamer 1:cf0bd0446785 334 int storage_status = fs.mount(&sd);
screamer 1:cf0bd0446785 335 if (storage_status != 0) {
screamer 1:cf0bd0446785 336 printf("Storage mounting failed.\n");
screamer 1:cf0bd0446785 337 }
screamer 1:cf0bd0446785 338
screamer 1:cf0bd0446785 339 #if USE_BUTTON == 1
screamer 0:3853978178c0 340 // If the User button is pressed ons start, then format storage.
screamer 1:cf0bd0446785 341 bool btn_pressed = (button.read() == MBED_CONF_APP_BUTTON_PRESSED_STATE);
screamer 1:cf0bd0446785 342 if (btn_pressed) {
screamer 1:cf0bd0446785 343 printf("User button is pushed on start...\n");
screamer 1:cf0bd0446785 344 }
screamer 1:cf0bd0446785 345 #else
screamer 1:cf0bd0446785 346 bool btn_pressed = FALSE;
screamer 1:cf0bd0446785 347 #endif /* USE_BUTTON */
screamer 1:cf0bd0446785 348
screamer 1:cf0bd0446785 349 if (storage_status || btn_pressed) {
screamer 1:cf0bd0446785 350 printf("Formatting the storage...\n");
screamer 1:cf0bd0446785 351 int storage_status = StorageHelper::format(&fs, &sd);
screamer 0:3853978178c0 352 if (storage_status != 0) {
screamer 0:3853978178c0 353 printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
screamer 0:3853978178c0 354 }
screamer 0:3853978178c0 355 } else {
screamer 0:3853978178c0 356 printf("You can hold the user button during boot to format the storage and change the device identity.\n");
screamer 0:3853978178c0 357 }
screamer 0:3853978178c0 358
screamer 0:3853978178c0 359 Nanostack::get_instance(); // ensure Nanostack is initialised
screamer 0:3853978178c0 360 ns_file_system_set_root_path("/fs/");
screamer 0:3853978178c0 361
screamer 1:cf0bd0446785 362 // Connect to the internet (DHCP is expected to be on)
screamer 1:cf0bd0446785 363 printf("Connecting to the network using 802.15.4...\n");
screamer 1:cf0bd0446785 364
screamer 1:cf0bd0446785 365 nsapi_error_t net_status = -1;
screamer 1:cf0bd0446785 366 for (int tries = 0; tries < 3; tries++) {
screamer 1:cf0bd0446785 367 net_status = net->connect();
screamer 1:cf0bd0446785 368 if (net_status == NSAPI_ERROR_OK) {
screamer 1:cf0bd0446785 369 break;
screamer 1:cf0bd0446785 370 } else {
screamer 1:cf0bd0446785 371 printf("Unable to connect to network. Retrying...\n");
screamer 1:cf0bd0446785 372 }
screamer 1:cf0bd0446785 373 }
screamer 1:cf0bd0446785 374
screamer 1:cf0bd0446785 375 if (net_status != NSAPI_ERROR_OK) {
screamer 1:cf0bd0446785 376 printf("ERROR: Connecting to the network failed (%d)!\n", net_status);
screamer 1:cf0bd0446785 377 return -1;
screamer 1:cf0bd0446785 378 }
screamer 1:cf0bd0446785 379
screamer 1:cf0bd0446785 380 printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
screamer 1:cf0bd0446785 381
screamer 1:cf0bd0446785 382 printf("Initializing Pelion Device Management Client...\n");
screamer 0:3853978178c0 383
screamer 0:3853978178c0 384 /* Initialize Simple Pelion DM Client */
screamer 0:3853978178c0 385 SimpleMbedCloudClient client(net, &sd, &fs);
screamer 1:cf0bd0446785 386 int client_status = client.init();
screamer 1:cf0bd0446785 387 if (client_status != 0) {
screamer 1:cf0bd0446785 388 printf("ERROR: Pelion Client initialization failed (%d)\n", client_status);
screamer 1:cf0bd0446785 389 return -1;
screamer 1:cf0bd0446785 390 }
screamer 0:3853978178c0 391
screamer 0:3853978178c0 392 /* Create resources */
screamer 3:6647d74cf212 393 res_led = client.create_resource("3201/0/5853", "LED blinking (R:G:B:cnt)");
screamer 1:cf0bd0446785 394 res_led->observable(false);
screamer 1:cf0bd0446785 395 res_led->set_value("0:0:0:0");
screamer 1:cf0bd0446785 396 res_led->attach_post_callback(blink_callback);
screamer 1:cf0bd0446785 397 res_led->methods(M2MMethod::POST);
screamer 0:3853978178c0 398
screamer 3:6647d74cf212 399 res_button = client.create_resource("3200/0/5501", "button_count");
screamer 1:cf0bd0446785 400 res_button->set_value(0);
screamer 1:cf0bd0446785 401 res_button->methods(M2MMethod::GET);
screamer 1:cf0bd0446785 402 res_button->observable(true);
screamer 1:cf0bd0446785 403 res_button->attach_notification_callback(button_callback);
screamer 0:3853978178c0 404
screamer 3:6647d74cf212 405 #ifdef SEND_ALL_SENSORS
screamer 2:8d3f3f35f089 406 // Sensor BMP280
screamer 2:8d3f3f35f089 407 res_pressure = client.create_resource("3323/0/5853", "Barometric pressure (hPa)");
screamer 2:8d3f3f35f089 408 res_pressure->set_value(0);
screamer 2:8d3f3f35f089 409 res_pressure->observable(true);
screamer 2:8d3f3f35f089 410 res_pressure->methods(M2MMethod::GET);
screamer 3:6647d74cf212 411
screamer 2:8d3f3f35f089 412 res_temperature1 = client.create_resource("3303/0/5853", "Temperature BMP280 (C)");
screamer 2:8d3f3f35f089 413 res_temperature1->set_value(0);
screamer 2:8d3f3f35f089 414 res_temperature1->observable(true);
screamer 2:8d3f3f35f089 415 res_temperature1->methods(M2MMethod::GET);
screamer 3:6647d74cf212 416
screamer 2:8d3f3f35f089 417 // Sensor Si7021
screamer 1:cf0bd0446785 418 res_humidity = client.create_resource("3304/0/5853", "Humidity (%)");
screamer 1:cf0bd0446785 419 res_humidity->set_value(0);
screamer 1:cf0bd0446785 420 res_humidity->observable(true);
screamer 1:cf0bd0446785 421 res_humidity->methods(M2MMethod::GET);
screamer 3:6647d74cf212 422
screamer 2:8d3f3f35f089 423 res_temperature2 = client.create_resource("3303/1/5853", "Temperature Si7021 (C)");
screamer 2:8d3f3f35f089 424 res_temperature2->set_value(0);
screamer 2:8d3f3f35f089 425 res_temperature2->observable(true);
screamer 3:6647d74cf212 426 res_temperature2->methods(M2MMethod::GET);
screamer 3:6647d74cf212 427
screamer 3:6647d74cf212 428 // Sensor Si7210
screamer 3:6647d74cf212 429 res_field = client.create_resource("33257/0/5853", "Magnetic Field (mT)");
screamer 2:8d3f3f35f089 430 res_field->set_value(0);
screamer 2:8d3f3f35f089 431 res_field->observable(true);
screamer 2:8d3f3f35f089 432 res_field->methods(M2MMethod::GET);
screamer 3:6647d74cf212 433
screamer 2:8d3f3f35f089 434 res_temperature3 = client.create_resource("3303/2/5853", "Temperature Si7210 (C)");
screamer 2:8d3f3f35f089 435 res_temperature3->set_value(0);
screamer 2:8d3f3f35f089 436 res_temperature3->observable(true);
screamer 2:8d3f3f35f089 437 res_temperature3->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 438
screamer 3:6647d74cf212 439 // Sensor Si1133
screamer 3:6647d74cf212 440 res_light = client.create_resource("3301/0/5853", "LightIntensity (LUX)");
screamer 3:6647d74cf212 441 res_light->set_value(0);
screamer 3:6647d74cf212 442 res_light->observable(true);
screamer 3:6647d74cf212 443 res_light->methods(M2MMethod::GET);
screamer 3:6647d74cf212 444
screamer 2:8d3f3f35f089 445 // Sensor CCS811
screamer 1:cf0bd0446785 446 res_co2 = client.create_resource("33255/0/5853", "CO2 (ppm)");
screamer 1:cf0bd0446785 447 res_co2->set_value(0);
screamer 1:cf0bd0446785 448 res_co2->observable(true);
screamer 1:cf0bd0446785 449 res_co2->methods(M2MMethod::GET);
screamer 0:3853978178c0 450
screamer 1:cf0bd0446785 451 res_tvoc = client.create_resource("33256/0/5853", "VOC (ppm)");
screamer 1:cf0bd0446785 452 res_tvoc->set_value(0);
screamer 1:cf0bd0446785 453 res_tvoc->observable(true);
screamer 1:cf0bd0446785 454 res_tvoc->methods(M2MMethod::GET);
screamer 3:6647d74cf212 455
screamer 2:8d3f3f35f089 456 // Sensor ICM20648
screamer 2:8d3f3f35f089 457 res_accelerometer_x = client.create_resource("3313/0/5702", "Accelerometer X");
screamer 2:8d3f3f35f089 458 res_accelerometer_x->set_value(0);
screamer 2:8d3f3f35f089 459 res_accelerometer_x->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 460 res_accelerometer_x->observable(true);
screamer 3:6647d74cf212 461
screamer 2:8d3f3f35f089 462 res_accelerometer_y = client.create_resource("3313/0/5703", "Accelerometer Y");
screamer 2:8d3f3f35f089 463 res_accelerometer_y->set_value(0);
screamer 2:8d3f3f35f089 464 res_accelerometer_y->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 465 res_accelerometer_y->observable(true);
screamer 3:6647d74cf212 466
screamer 2:8d3f3f35f089 467 res_accelerometer_z = client.create_resource("3313/0/5704", "Accelerometer Z");
screamer 2:8d3f3f35f089 468 res_accelerometer_z->set_value(0);
screamer 2:8d3f3f35f089 469 res_accelerometer_z->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 470 res_accelerometer_z->observable(true);
screamer 3:6647d74cf212 471
screamer 2:8d3f3f35f089 472 res_gyroscope_x = client.create_resource("3334/0/5702", "Gyroscope X");
screamer 2:8d3f3f35f089 473 res_gyroscope_x->set_value(0);
screamer 2:8d3f3f35f089 474 res_gyroscope_x->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 475 res_gyroscope_x->observable(true);
screamer 3:6647d74cf212 476
screamer 2:8d3f3f35f089 477 res_gyroscope_y = client.create_resource("3334/0/5703", "Gyroscope Y");
screamer 2:8d3f3f35f089 478 res_gyroscope_y->set_value(0);
screamer 2:8d3f3f35f089 479 res_gyroscope_y->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 480 res_gyroscope_y->observable(true);
screamer 3:6647d74cf212 481
screamer 2:8d3f3f35f089 482 res_gyroscope_z = client.create_resource("3334/0/5704", "Gyroscope Z");
screamer 2:8d3f3f35f089 483 res_gyroscope_z->set_value(0);
screamer 2:8d3f3f35f089 484 res_gyroscope_z->methods(M2MMethod::GET);
screamer 2:8d3f3f35f089 485 res_gyroscope_z->observable(true);
screamer 3:6647d74cf212 486
screamer 2:8d3f3f35f089 487 res_temperature4 = client.create_resource("3303/3/5853", "Temperature ICM20648 (C)");
screamer 2:8d3f3f35f089 488 res_temperature4->set_value(0);
screamer 2:8d3f3f35f089 489 res_temperature4->observable(true);
screamer 2:8d3f3f35f089 490 res_temperature4->methods(M2MMethod::GET);
screamer 1:cf0bd0446785 491 #endif /* SEND_ALL_SENSORS */
screamer 0:3853978178c0 492
screamer 1:cf0bd0446785 493 sensors_init();
screamer 1:cf0bd0446785 494
screamer 1:cf0bd0446785 495 // Callback that fires when registering is complete
screamer 1:cf0bd0446785 496 client.on_registered(&registered);
screamer 0:3853978178c0 497
screamer 0:3853978178c0 498 /* Register the device */
screamer 0:3853978178c0 499 client.register_and_connect();
screamer 0:3853978178c0 500
screamer 1:cf0bd0446785 501 button.fall(eventQueue.event(&button_press));
screamer 0:3853978178c0 502
screamer 1:cf0bd0446785 503 // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
screamer 1:cf0bd0446785 504 Ticker timer;
screamer 1:cf0bd0446785 505 timer.attach(eventQueue.event(&sensors_update), SENSORS_POLL_INTERVAL);
screamer 0:3853978178c0 506
screamer 0:3853978178c0 507 eventQueue.dispatch_forever();
screamer 1:cf0bd0446785 508 }