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

Dependencies:   ICM20648 BMP280 Si1133 Si7210 AMS_CCS811_gas_sensor SI7021

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:
Wed Mar 27 19:05:42 2019 +0000
Revision:
7:c5ebecef1a84
Parent:
6:ec491c9aae8f
Remove unnecessary macros

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