Mbed OS Device Connector client pushing environmental sensor data via 6LowPan.

Dependencies:   X_NUCLEO_IKS01A2

Fork of mbed-os-example-client-Sensors_6LowPan by Nicola Capovilla

The application is derived from the official mbedOS client example (link) and has been tested using a X-NUCLEO-IDS01A4 SubGHz 6LowPan connectivity board and a X-NUCLEO-IKS01A2 (default) or a X-NUCLEO-IKS01A1 motion and environmental sensors expansion board connected to a ST NUCLEO-F429ZI platform.
The following steps should be performed to make the application work:

  • Register and login into ARM mbed Connector.
  • Replace the default and empty security.h file with the one associated with your account and provided by the Connector (Security Credentials menu).
  • In order to use X-NUCLEO-IKS01A1 instead of default X-NUCLEO-IKS01A2 comment out the IKS01A2 macro definition in main.cpp file.
  • Choose NUCLEO-F429ZI as a target either from online compiler or from CLI, compile and flash.
  • Setup and connect a NUCLEO-F429ZI + X-NUCLEO-IDS01A4 6LowPan border router as explained here
  • Open a serial terminal (params 115200N1) and wait that the client is connected to the mbed Connector via the border router.
  • As soon as the client is connected it will start acquiring and pushing the environmental (pressure, temperature and humidity) data to the cloud.

Note: environmental data are expressed using IPSO representation based on OMA LWM2M standard.

Committer:
nikapov
Date:
Thu Jan 25 18:00:04 2018 +0100
Revision:
0:694e888fd1b5
First release.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nikapov 0:694e888fd1b5 1 /*
nikapov 0:694e888fd1b5 2 * Copyright (c) 2015, 2016 ARM Limited. All rights reserved.
nikapov 0:694e888fd1b5 3 * SPDX-License-Identifier: Apache-2.0
nikapov 0:694e888fd1b5 4 * Licensed under the Apache License, Version 2.0 (the License); you may
nikapov 0:694e888fd1b5 5 * not use this file except in compliance with the License.
nikapov 0:694e888fd1b5 6 * You may obtain a copy of the License at
nikapov 0:694e888fd1b5 7 *
nikapov 0:694e888fd1b5 8 * http://www.apache.org/licenses/LICENSE-2.0
nikapov 0:694e888fd1b5 9 *
nikapov 0:694e888fd1b5 10 * Unless required by applicable law or agreed to in writing, software
nikapov 0:694e888fd1b5 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
nikapov 0:694e888fd1b5 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nikapov 0:694e888fd1b5 13 * See the License for the specific language governing permissions and
nikapov 0:694e888fd1b5 14 * limitations under the License.
nikapov 0:694e888fd1b5 15 */
nikapov 0:694e888fd1b5 16
nikapov 0:694e888fd1b5 17 /*
nikapov 0:694e888fd1b5 18 * Modified by STMicroelectronics to support X-NUCLEO-IKS01A1/2 environmental
nikapov 0:694e888fd1b5 19 * sensors on top of Nucleo-F429ZI/Nucleo-L476RG.
nikapov 0:694e888fd1b5 20 */
nikapov 0:694e888fd1b5 21
nikapov 0:694e888fd1b5 22
nikapov 0:694e888fd1b5 23 #define __STDC_FORMAT_MACROS
nikapov 0:694e888fd1b5 24 #include <inttypes.h>
nikapov 0:694e888fd1b5 25 #include "simpleclient.h"
nikapov 0:694e888fd1b5 26 #include <string>
nikapov 0:694e888fd1b5 27 #include <sstream>
nikapov 0:694e888fd1b5 28 #include <vector>
nikapov 0:694e888fd1b5 29 #include "mbed-trace/mbed_trace.h"
nikapov 0:694e888fd1b5 30 #include "mbedtls/entropy_poll.h"
nikapov 0:694e888fd1b5 31
nikapov 0:694e888fd1b5 32 #include "security.h"
nikapov 0:694e888fd1b5 33
nikapov 0:694e888fd1b5 34 #include "mbed.h"
nikapov 0:694e888fd1b5 35
nikapov 0:694e888fd1b5 36 // easy-connect compliancy, it has 2 sets of wifi pins we have only one
nikapov 0:694e888fd1b5 37 #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX
nikapov 0:694e888fd1b5 38 #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX
nikapov 0:694e888fd1b5 39 #include "easy-connect/easy-connect.h"
nikapov 0:694e888fd1b5 40
nikapov 0:694e888fd1b5 41 #ifdef TARGET_STM
nikapov 0:694e888fd1b5 42 #define RED_LED (LED3)
nikapov 0:694e888fd1b5 43 #define GREEN_LED (LED1)
nikapov 0:694e888fd1b5 44 #define BLUE_LED (LED2)
nikapov 0:694e888fd1b5 45 #define LED_ON (1)
nikapov 0:694e888fd1b5 46 #else // !TARGET_STM
nikapov 0:694e888fd1b5 47 #define RED_LED (LED1)
nikapov 0:694e888fd1b5 48 #define GREEN_LED (LED2)
nikapov 0:694e888fd1b5 49 #define BLUE_LED (LED3)
nikapov 0:694e888fd1b5 50 #define LED_ON (0)
nikapov 0:694e888fd1b5 51 #endif // !TARGET_STM
nikapov 0:694e888fd1b5 52 #define LED_OFF (!LED_ON)
nikapov 0:694e888fd1b5 53
nikapov 0:694e888fd1b5 54 // Status indication
nikapov 0:694e888fd1b5 55 DigitalOut red_led(RED_LED);
nikapov 0:694e888fd1b5 56 DigitalOut green_led(GREEN_LED);
nikapov 0:694e888fd1b5 57 DigitalOut blue_led(BLUE_LED);
nikapov 0:694e888fd1b5 58
nikapov 0:694e888fd1b5 59 Ticker status_ticker;
nikapov 0:694e888fd1b5 60 void blinky() {
nikapov 0:694e888fd1b5 61 green_led = !green_led;
nikapov 0:694e888fd1b5 62 }
nikapov 0:694e888fd1b5 63
nikapov 0:694e888fd1b5 64 // These are example resource values for the Device Object
nikapov 0:694e888fd1b5 65 struct MbedClientDevice device = {
nikapov 0:694e888fd1b5 66 "Manufacturer_String", // Manufacturer
nikapov 0:694e888fd1b5 67 "Type_String", // Type
nikapov 0:694e888fd1b5 68 "ModelNumber_String", // ModelNumber
nikapov 0:694e888fd1b5 69 "SerialNumber_String" // SerialNumber
nikapov 0:694e888fd1b5 70 };
nikapov 0:694e888fd1b5 71
nikapov 0:694e888fd1b5 72 // Instantiate the class which implements LWM2M Client API (from simpleclient.h)
nikapov 0:694e888fd1b5 73 MbedClient mbed_client(device);
nikapov 0:694e888fd1b5 74
nikapov 0:694e888fd1b5 75
nikapov 0:694e888fd1b5 76 // In case of K64F board , there is button resource available
nikapov 0:694e888fd1b5 77 // to change resource value and unregister
nikapov 0:694e888fd1b5 78 #ifdef TARGET_K64F
nikapov 0:694e888fd1b5 79 // Set up Hardware interrupt button.
nikapov 0:694e888fd1b5 80 InterruptIn obs_button(SW2);
nikapov 0:694e888fd1b5 81 InterruptIn unreg_button(SW3);
nikapov 0:694e888fd1b5 82 #else
nikapov 0:694e888fd1b5 83 //In non K64F boards , set up a timer to simulate updating resource,
nikapov 0:694e888fd1b5 84 // there is no functionality to unregister.
nikapov 0:694e888fd1b5 85 Ticker timer;
nikapov 0:694e888fd1b5 86 #endif
nikapov 0:694e888fd1b5 87
nikapov 0:694e888fd1b5 88 /*
nikapov 0:694e888fd1b5 89 * Arguments for running "blink" in it's own thread.
nikapov 0:694e888fd1b5 90 */
nikapov 0:694e888fd1b5 91 class BlinkArgs {
nikapov 0:694e888fd1b5 92 public:
nikapov 0:694e888fd1b5 93 BlinkArgs() {
nikapov 0:694e888fd1b5 94 clear();
nikapov 0:694e888fd1b5 95 }
nikapov 0:694e888fd1b5 96 void clear() {
nikapov 0:694e888fd1b5 97 position = 0;
nikapov 0:694e888fd1b5 98 blink_pattern.clear();
nikapov 0:694e888fd1b5 99 }
nikapov 0:694e888fd1b5 100 uint16_t position;
nikapov 0:694e888fd1b5 101 std::vector<uint32_t> blink_pattern;
nikapov 0:694e888fd1b5 102 };
nikapov 0:694e888fd1b5 103
nikapov 0:694e888fd1b5 104 /*
nikapov 0:694e888fd1b5 105 * The Led contains one property (pattern) and a function (blink).
nikapov 0:694e888fd1b5 106 * When the function blink is executed, the pattern is read, and the LED
nikapov 0:694e888fd1b5 107 * will blink based on the pattern.
nikapov 0:694e888fd1b5 108 */
nikapov 0:694e888fd1b5 109 class LedResource {
nikapov 0:694e888fd1b5 110 public:
nikapov 0:694e888fd1b5 111 LedResource() {
nikapov 0:694e888fd1b5 112 // create ObjectID with metadata tag of '3201', which is 'digital output'
nikapov 0:694e888fd1b5 113 led_object = M2MInterfaceFactory::create_object("3201");
nikapov 0:694e888fd1b5 114 M2MObjectInstance* led_inst = led_object->create_object_instance();
nikapov 0:694e888fd1b5 115
nikapov 0:694e888fd1b5 116 // 5853 = Multi-state output
nikapov 0:694e888fd1b5 117 M2MResource* pattern_res = led_inst->create_dynamic_resource("5853", "Pattern",
nikapov 0:694e888fd1b5 118 M2MResourceInstance::STRING, false);
nikapov 0:694e888fd1b5 119 // read and write
nikapov 0:694e888fd1b5 120 pattern_res->set_operation(M2MBase::GET_PUT_ALLOWED);
nikapov 0:694e888fd1b5 121 // set initial pattern (toggle every 200ms. 7 toggles in total)
nikapov 0:694e888fd1b5 122 pattern_res->set_value((const uint8_t*)"500:500:500:500:500:500:500", 27);
nikapov 0:694e888fd1b5 123
nikapov 0:694e888fd1b5 124 // there's not really an execute LWM2M ID that matches... hmm...
nikapov 0:694e888fd1b5 125 M2MResource* led_res = led_inst->create_dynamic_resource("5850", "Blink",
nikapov 0:694e888fd1b5 126 M2MResourceInstance::OPAQUE, false);
nikapov 0:694e888fd1b5 127 // we allow executing a function here...
nikapov 0:694e888fd1b5 128 led_res->set_operation(M2MBase::POST_ALLOWED);
nikapov 0:694e888fd1b5 129 // when a POST comes in, we want to execute the led_execute_callback
nikapov 0:694e888fd1b5 130 led_res->set_execute_function(execute_callback(this, &LedResource::blink));
nikapov 0:694e888fd1b5 131 // Completion of execute function can take a time, that's why delayed response is used
nikapov 0:694e888fd1b5 132 led_res->set_delayed_response(true);
nikapov 0:694e888fd1b5 133 blink_args = new BlinkArgs();
nikapov 0:694e888fd1b5 134
nikapov 0:694e888fd1b5 135 // betzw: Start blinky thread
nikapov 0:694e888fd1b5 136 blinky_thread.start(callback(this, &LedResource::do_blink)); // betzw - NOTE: threads can only be started once!
nikapov 0:694e888fd1b5 137 }
nikapov 0:694e888fd1b5 138
nikapov 0:694e888fd1b5 139 ~LedResource() {
nikapov 0:694e888fd1b5 140 delete blink_args;
nikapov 0:694e888fd1b5 141 }
nikapov 0:694e888fd1b5 142
nikapov 0:694e888fd1b5 143 M2MObject* get_object() {
nikapov 0:694e888fd1b5 144 return led_object;
nikapov 0:694e888fd1b5 145 }
nikapov 0:694e888fd1b5 146
nikapov 0:694e888fd1b5 147 void blink(void *argument) {
nikapov 0:694e888fd1b5 148 // read the value of 'Pattern'
nikapov 0:694e888fd1b5 149 status_ticker.detach();
nikapov 0:694e888fd1b5 150 green_led = LED_OFF;
nikapov 0:694e888fd1b5 151
nikapov 0:694e888fd1b5 152 M2MObjectInstance* inst = led_object->object_instance();
nikapov 0:694e888fd1b5 153 M2MResource* res = inst->resource("5853");
nikapov 0:694e888fd1b5 154 // Clear previous blink data
nikapov 0:694e888fd1b5 155 blink_args->clear();
nikapov 0:694e888fd1b5 156
nikapov 0:694e888fd1b5 157 // values in mbed Client are all buffers, and we need a vector of int's
nikapov 0:694e888fd1b5 158 uint8_t* buffIn = NULL;
nikapov 0:694e888fd1b5 159 uint32_t sizeIn;
nikapov 0:694e888fd1b5 160 res->get_value(buffIn, sizeIn);
nikapov 0:694e888fd1b5 161
nikapov 0:694e888fd1b5 162 // turn the buffer into a string, and initialize a vector<int> on the heap
nikapov 0:694e888fd1b5 163 std::string s((char*)buffIn, sizeIn);
nikapov 0:694e888fd1b5 164 free(buffIn);
nikapov 0:694e888fd1b5 165 printf("led_execute_callback pattern=%s\n", s.c_str());
nikapov 0:694e888fd1b5 166
nikapov 0:694e888fd1b5 167 // our pattern is something like 500:200:500, so parse that
nikapov 0:694e888fd1b5 168 std::size_t found = s.find_first_of(":");
nikapov 0:694e888fd1b5 169 while (found!=std::string::npos) {
nikapov 0:694e888fd1b5 170 blink_args->blink_pattern.push_back(atoi((const char*)s.substr(0,found).c_str()));
nikapov 0:694e888fd1b5 171 s = s.substr(found+1);
nikapov 0:694e888fd1b5 172 found=s.find_first_of(":");
nikapov 0:694e888fd1b5 173 if(found == std::string::npos) {
nikapov 0:694e888fd1b5 174 blink_args->blink_pattern.push_back(atoi((const char*)s.c_str()));
nikapov 0:694e888fd1b5 175 }
nikapov 0:694e888fd1b5 176 }
nikapov 0:694e888fd1b5 177 // check if POST contains payload
nikapov 0:694e888fd1b5 178 if (argument) {
nikapov 0:694e888fd1b5 179 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
nikapov 0:694e888fd1b5 180 String object_name = param->get_argument_object_name();
nikapov 0:694e888fd1b5 181 uint16_t object_instance_id = param->get_argument_object_instance_id();
nikapov 0:694e888fd1b5 182 String resource_name = param->get_argument_resource_name();
nikapov 0:694e888fd1b5 183 int payload_length = param->get_argument_value_length();
nikapov 0:694e888fd1b5 184 uint8_t* payload = param->get_argument_value();
nikapov 0:694e888fd1b5 185 printf("Resource: %s/%d/%s executed\n", object_name.c_str(), object_instance_id, resource_name.c_str());
nikapov 0:694e888fd1b5 186 printf("Payload: %.*s\n", payload_length, payload);
nikapov 0:694e888fd1b5 187 }
nikapov 0:694e888fd1b5 188 // do_blink is called with the vector, and starting at -1
nikapov 0:694e888fd1b5 189 // blinky_thread.start(callback(this, &LedResource::do_blink)); // betzw - NOTE: threads can only be started once!
nikapov 0:694e888fd1b5 190 blinky_thread.signal_set(1);
nikapov 0:694e888fd1b5 191 }
nikapov 0:694e888fd1b5 192
nikapov 0:694e888fd1b5 193 private:
nikapov 0:694e888fd1b5 194 M2MObject* led_object;
nikapov 0:694e888fd1b5 195 Thread blinky_thread;
nikapov 0:694e888fd1b5 196 BlinkArgs *blink_args;
nikapov 0:694e888fd1b5 197 void do_blink() {
nikapov 0:694e888fd1b5 198 blinky_thread.signal_wait(0);
nikapov 0:694e888fd1b5 199 for (;;) {
nikapov 0:694e888fd1b5 200 // blink the LED
nikapov 0:694e888fd1b5 201 red_led = !red_led;
nikapov 0:694e888fd1b5 202 // up the position, if we reached the end of the vector
nikapov 0:694e888fd1b5 203 if (blink_args->position >= blink_args->blink_pattern.size()) {
nikapov 0:694e888fd1b5 204 // send delayed response after blink is done
nikapov 0:694e888fd1b5 205 M2MObjectInstance* inst = led_object->object_instance();
nikapov 0:694e888fd1b5 206 M2MResource* led_res = inst->resource("5850");
nikapov 0:694e888fd1b5 207 led_res->send_delayed_post_response();
nikapov 0:694e888fd1b5 208 red_led = LED_OFF;
nikapov 0:694e888fd1b5 209 status_ticker.attach_us(blinky, 250000);
nikapov 0:694e888fd1b5 210 // betzw - WAS: return;
nikapov 0:694e888fd1b5 211 blinky_thread.signal_wait(0);
nikapov 0:694e888fd1b5 212 continue;
nikapov 0:694e888fd1b5 213 }
nikapov 0:694e888fd1b5 214 // Wait requested time, then continue processing the blink pattern from next position.
nikapov 0:694e888fd1b5 215 Thread::wait(blink_args->blink_pattern.at(blink_args->position));
nikapov 0:694e888fd1b5 216 blink_args->position++;
nikapov 0:694e888fd1b5 217 }
nikapov 0:694e888fd1b5 218 }
nikapov 0:694e888fd1b5 219 };
nikapov 0:694e888fd1b5 220
nikapov 0:694e888fd1b5 221 /*
nikapov 0:694e888fd1b5 222 * The button contains one property (click count).
nikapov 0:694e888fd1b5 223 * When `handle_button_click` is executed, the counter updates.
nikapov 0:694e888fd1b5 224 */
nikapov 0:694e888fd1b5 225 class ButtonResource {
nikapov 0:694e888fd1b5 226 public:
nikapov 0:694e888fd1b5 227 ButtonResource(): counter(0) {
nikapov 0:694e888fd1b5 228 // create ObjectID with metadata tag of '3200', which is 'digital input'
nikapov 0:694e888fd1b5 229 btn_object = M2MInterfaceFactory::create_object("3200");
nikapov 0:694e888fd1b5 230 M2MObjectInstance* btn_inst = btn_object->create_object_instance();
nikapov 0:694e888fd1b5 231 // create resource with ID '5501', which is digital input counter
nikapov 0:694e888fd1b5 232 M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button",
nikapov 0:694e888fd1b5 233 M2MResourceInstance::INTEGER, true /* observable */);
nikapov 0:694e888fd1b5 234 // we can read this value
nikapov 0:694e888fd1b5 235 btn_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 0:694e888fd1b5 236 // set initial value (all values in mbed Client are buffers)
nikapov 0:694e888fd1b5 237 // to be able to read this data easily in the Connector console, we'll use a string
nikapov 0:694e888fd1b5 238 btn_res->set_value((uint8_t*)"0", 1);
nikapov 0:694e888fd1b5 239 }
nikapov 0:694e888fd1b5 240
nikapov 0:694e888fd1b5 241 ~ButtonResource() {
nikapov 0:694e888fd1b5 242 }
nikapov 0:694e888fd1b5 243
nikapov 0:694e888fd1b5 244 M2MObject* get_object() {
nikapov 0:694e888fd1b5 245 return btn_object;
nikapov 0:694e888fd1b5 246 }
nikapov 0:694e888fd1b5 247
nikapov 0:694e888fd1b5 248 /*
nikapov 0:694e888fd1b5 249 * When you press the button, we read the current value of the click counter
nikapov 0:694e888fd1b5 250 * from mbed Device Connector, then up the value with one.
nikapov 0:694e888fd1b5 251 */
nikapov 0:694e888fd1b5 252 void handle_button_click() {
nikapov 0:694e888fd1b5 253 if (mbed_client.register_successful()) {
nikapov 0:694e888fd1b5 254 M2MObjectInstance* inst = btn_object->object_instance();
nikapov 0:694e888fd1b5 255 M2MResource* res = inst->resource("5501");
nikapov 0:694e888fd1b5 256
nikapov 0:694e888fd1b5 257 // up counter
nikapov 0:694e888fd1b5 258 counter++;
nikapov 0:694e888fd1b5 259 #if defined(TARGET_K64F) || defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_L476RG)
nikapov 0:694e888fd1b5 260 printf("handle_button_click, new value of counter is %d\r\n", counter);
nikapov 0:694e888fd1b5 261 #else
nikapov 0:694e888fd1b5 262 printf("simulate button_click, new value of counter is %d\n", counter);
nikapov 0:694e888fd1b5 263 #endif
nikapov 0:694e888fd1b5 264 // serialize the value of counter as a string, and tell connector
nikapov 0:694e888fd1b5 265 char buffer[20];
nikapov 0:694e888fd1b5 266 int size = sprintf(buffer,"%d",counter);
nikapov 0:694e888fd1b5 267 res->set_value((uint8_t*)buffer, size);
nikapov 0:694e888fd1b5 268 } else {
nikapov 0:694e888fd1b5 269 printf("simulate button_click, device not registered\n");
nikapov 0:694e888fd1b5 270 }
nikapov 0:694e888fd1b5 271 }
nikapov 0:694e888fd1b5 272
nikapov 0:694e888fd1b5 273 private:
nikapov 0:694e888fd1b5 274 M2MObject* btn_object;
nikapov 0:694e888fd1b5 275 uint16_t counter;
nikapov 0:694e888fd1b5 276 };
nikapov 0:694e888fd1b5 277
nikapov 0:694e888fd1b5 278 class BigPayloadResource {
nikapov 0:694e888fd1b5 279 public:
nikapov 0:694e888fd1b5 280 BigPayloadResource() {
nikapov 0:694e888fd1b5 281 big_payload = M2MInterfaceFactory::create_object("1000");
nikapov 0:694e888fd1b5 282 M2MObjectInstance* payload_inst = big_payload->create_object_instance();
nikapov 0:694e888fd1b5 283 M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData",
nikapov 0:694e888fd1b5 284 M2MResourceInstance::STRING, true /* observable */);
nikapov 0:694e888fd1b5 285 payload_res->set_operation(M2MBase::GET_PUT_ALLOWED);
nikapov 0:694e888fd1b5 286 payload_res->set_value((uint8_t*)"0", 1);
nikapov 0:694e888fd1b5 287 payload_res->set_incoming_block_message_callback(
nikapov 0:694e888fd1b5 288 incoming_block_message_callback(this, &BigPayloadResource::block_message_received));
nikapov 0:694e888fd1b5 289 payload_res->set_outgoing_block_message_callback(
nikapov 0:694e888fd1b5 290 outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested));
nikapov 0:694e888fd1b5 291 }
nikapov 0:694e888fd1b5 292
nikapov 0:694e888fd1b5 293 M2MObject* get_object() {
nikapov 0:694e888fd1b5 294 return big_payload;
nikapov 0:694e888fd1b5 295 }
nikapov 0:694e888fd1b5 296
nikapov 0:694e888fd1b5 297 void block_message_received(M2MBlockMessage *argument) {
nikapov 0:694e888fd1b5 298 if (argument) {
nikapov 0:694e888fd1b5 299 if (M2MBlockMessage::ErrorNone == argument->error_code()) {
nikapov 0:694e888fd1b5 300 if (argument->is_last_block()) {
nikapov 0:694e888fd1b5 301 printf("Last block received\n");
nikapov 0:694e888fd1b5 302 }
nikapov 0:694e888fd1b5 303 printf("Block number: %d\n", argument->block_number());
nikapov 0:694e888fd1b5 304 // First block received
nikapov 0:694e888fd1b5 305 if (argument->block_number() == 0) {
nikapov 0:694e888fd1b5 306 // Store block
nikapov 0:694e888fd1b5 307 // More blocks coming
nikapov 0:694e888fd1b5 308 } else {
nikapov 0:694e888fd1b5 309 // Store blocks
nikapov 0:694e888fd1b5 310 }
nikapov 0:694e888fd1b5 311 } else {
nikapov 0:694e888fd1b5 312 printf("Error when receiving block message! - EntityTooLarge\n");
nikapov 0:694e888fd1b5 313 }
nikapov 0:694e888fd1b5 314 printf("Total message size: %" PRIu32 "\n", argument->total_message_size());
nikapov 0:694e888fd1b5 315 }
nikapov 0:694e888fd1b5 316 }
nikapov 0:694e888fd1b5 317
nikapov 0:694e888fd1b5 318 void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) {
nikapov 0:694e888fd1b5 319 printf("GET request received for resource: %s\n", resource.c_str());
nikapov 0:694e888fd1b5 320 // Copy data and length to coap response
nikapov 0:694e888fd1b5 321 }
nikapov 0:694e888fd1b5 322
nikapov 0:694e888fd1b5 323 private:
nikapov 0:694e888fd1b5 324 M2MObject* big_payload;
nikapov 0:694e888fd1b5 325 };
nikapov 0:694e888fd1b5 326
nikapov 0:694e888fd1b5 327 /* STMicroelectronics IKS01A1/2 code - BEGIN */
nikapov 0:694e888fd1b5 328
nikapov 0:694e888fd1b5 329 #define IKS01A2 // comment out for IKS01A1
nikapov 0:694e888fd1b5 330
nikapov 0:694e888fd1b5 331 #ifdef IKS01A2
nikapov 0:694e888fd1b5 332 #define __ARCHDEP__TYPES // fix to a typedef redefinition with LWIP stack
nikapov 0:694e888fd1b5 333 typedef unsigned char u8_t;
nikapov 0:694e888fd1b5 334 typedef unsigned short int u16_t;
nikapov 0:694e888fd1b5 335 //typedef unsigned int u32_t; // conflictiong definition
nikapov 0:694e888fd1b5 336 typedef int i32_t;
nikapov 0:694e888fd1b5 337 typedef short int i16_t;
nikapov 0:694e888fd1b5 338 typedef signed char i8_t;
nikapov 0:694e888fd1b5 339 #include "XNucleoIKS01A2.h"
nikapov 0:694e888fd1b5 340 #else
nikapov 0:694e888fd1b5 341 #include "XNucleoIKS01A1.h"
nikapov 0:694e888fd1b5 342 #endif
nikapov 0:694e888fd1b5 343
nikapov 0:694e888fd1b5 344 #define SENSOR_OK 0
nikapov 0:694e888fd1b5 345 #define DEFAULT_ENV_POLLING_PERIOD_MS 5000 // default polling time
nikapov 0:694e888fd1b5 346
nikapov 0:694e888fd1b5 347 class EnvResource {
nikapov 0:694e888fd1b5 348 public:
nikapov 0:694e888fd1b5 349 EnvResource() {
nikapov 0:694e888fd1b5 350 #ifdef IKS01A2
nikapov 0:694e888fd1b5 351 p_mems_expansion_board = XNucleoIKS01A2::instance(IKS01A2_PIN_I2C_SDA,IKS01A2_PIN_I2C_SCL);
nikapov 0:694e888fd1b5 352 #else
nikapov 0:694e888fd1b5 353 p_mems_expansion_board = XNucleoIKS01A1::instance(IKS01A1_PIN_I2C_SDA,IKS01A1_PIN_I2C_SCL);
nikapov 0:694e888fd1b5 354 #endif
nikapov 0:694e888fd1b5 355
nikapov 0:694e888fd1b5 356 temp_object = M2MInterfaceFactory::create_object("3303");
nikapov 0:694e888fd1b5 357 temp_inst = temp_object->create_object_instance();
nikapov 0:694e888fd1b5 358 temp_res = temp_inst->create_dynamic_resource("5700", "Temperature",
nikapov 0:694e888fd1b5 359 M2MResourceInstance::FLOAT, true); // observable
nikapov 0:694e888fd1b5 360 // we can only read this value
nikapov 0:694e888fd1b5 361 temp_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 0:694e888fd1b5 362 temp_res->set_value((uint8_t*)"20.0", 4);
nikapov 0:694e888fd1b5 363
nikapov 0:694e888fd1b5 364 hum_object = M2MInterfaceFactory::create_object("3304");
nikapov 0:694e888fd1b5 365 hum_inst = hum_object->create_object_instance();
nikapov 0:694e888fd1b5 366 hum_res = hum_inst->create_dynamic_resource("5700", "Humidity",
nikapov 0:694e888fd1b5 367 M2MResourceInstance::FLOAT, true); // observable
nikapov 0:694e888fd1b5 368 // we can only read this value
nikapov 0:694e888fd1b5 369 hum_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 0:694e888fd1b5 370 hum_res->set_value((uint8_t*)"50.0", 4);
nikapov 0:694e888fd1b5 371
nikapov 0:694e888fd1b5 372 #ifdef IKS01A2 // need to explicitly enable the sensor with IKS01A2
nikapov 0:694e888fd1b5 373 HTS221Sensor *hum_temp = p_mems_expansion_board->ht_sensor;
nikapov 0:694e888fd1b5 374 hum_temp->enable();
nikapov 0:694e888fd1b5 375 #endif
nikapov 0:694e888fd1b5 376
nikapov 0:694e888fd1b5 377 press_object = M2MInterfaceFactory::create_object("3300");
nikapov 0:694e888fd1b5 378 press_inst = press_object->create_object_instance();
nikapov 0:694e888fd1b5 379 press_res = press_inst->create_dynamic_resource("5700", "Pressure",
nikapov 0:694e888fd1b5 380 M2MResourceInstance::FLOAT, true); // observable
nikapov 0:694e888fd1b5 381 // we can only read this value
nikapov 0:694e888fd1b5 382 press_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 0:694e888fd1b5 383 press_res->set_value((uint8_t*)"5000", 4);
nikapov 0:694e888fd1b5 384
nikapov 0:694e888fd1b5 385 #ifdef IKS01A2 // need to explicitly enable the sensor with IKS01A2
nikapov 0:694e888fd1b5 386 LPS22HBSensor *press_temp = p_mems_expansion_board->pt_sensor;
nikapov 0:694e888fd1b5 387 press_temp->enable();
nikapov 0:694e888fd1b5 388 #endif
nikapov 0:694e888fd1b5 389
nikapov 0:694e888fd1b5 390 timer_res = press_inst->create_dynamic_resource("5603", "PollingPeriodMs", // one polling time for all env values, associated to humidity
nikapov 0:694e888fd1b5 391 M2MResourceInstance::INTEGER, false); // not observable
nikapov 0:694e888fd1b5 392 // we can read/wr this value
nikapov 0:694e888fd1b5 393 timer_res->set_operation(M2MBase::GET_PUT_ALLOWED);
nikapov 0:694e888fd1b5 394 timer_res->set_value((uint8_t*)"1000",4); // default 1s polling
nikapov 0:694e888fd1b5 395
nikapov 0:694e888fd1b5 396 }
nikapov 0:694e888fd1b5 397
nikapov 0:694e888fd1b5 398 M2MObject* get_temp_object() {
nikapov 0:694e888fd1b5 399 return temp_object;
nikapov 0:694e888fd1b5 400 }
nikapov 0:694e888fd1b5 401
nikapov 0:694e888fd1b5 402 M2MObject* get_hum_object() {
nikapov 0:694e888fd1b5 403 return hum_object;
nikapov 0:694e888fd1b5 404 }
nikapov 0:694e888fd1b5 405
nikapov 0:694e888fd1b5 406 M2MObject* get_press_object() {
nikapov 0:694e888fd1b5 407 return press_object;
nikapov 0:694e888fd1b5 408 }
nikapov 0:694e888fd1b5 409
nikapov 0:694e888fd1b5 410 int get_polling_period() {
nikapov 0:694e888fd1b5 411 return timer_res->get_value_int();
nikapov 0:694e888fd1b5 412 }
nikapov 0:694e888fd1b5 413
nikapov 0:694e888fd1b5 414 void update_resources() {
nikapov 0:694e888fd1b5 415 float temp;
nikapov 0:694e888fd1b5 416 float hum;
nikapov 0:694e888fd1b5 417 float press;
nikapov 0:694e888fd1b5 418 int err;
nikapov 0:694e888fd1b5 419
nikapov 0:694e888fd1b5 420 err = p_mems_expansion_board->ht_sensor->get_temperature(&temp);
nikapov 0:694e888fd1b5 421 if ( err != SENSOR_OK) {
nikapov 0:694e888fd1b5 422 printf ("= * ERROR %d get_temperature\n\r", err);
nikapov 0:694e888fd1b5 423 temp = 20.0;
nikapov 0:694e888fd1b5 424 red_led = 1;
nikapov 0:694e888fd1b5 425 } else {
nikapov 0:694e888fd1b5 426 printf ("Temp C: %f\n\r", temp);
nikapov 0:694e888fd1b5 427 red_led = 0;
nikapov 0:694e888fd1b5 428 }
nikapov 0:694e888fd1b5 429
nikapov 0:694e888fd1b5 430 err = p_mems_expansion_board->ht_sensor->get_humidity(&hum);
nikapov 0:694e888fd1b5 431 if ( err != SENSOR_OK) {
nikapov 0:694e888fd1b5 432 printf ("= * ERROR %d get_humidity\n\r", err);
nikapov 0:694e888fd1b5 433 hum= 50.0;
nikapov 0:694e888fd1b5 434 red_led = 1;
nikapov 0:694e888fd1b5 435 } else {
nikapov 0:694e888fd1b5 436 printf ("Humidity %: %f\n\r", hum);
nikapov 0:694e888fd1b5 437 red_led = 0;
nikapov 0:694e888fd1b5 438 }
nikapov 0:694e888fd1b5 439
nikapov 0:694e888fd1b5 440 err = p_mems_expansion_board->pt_sensor->get_pressure(&press);
nikapov 0:694e888fd1b5 441 if ( err != SENSOR_OK) {
nikapov 0:694e888fd1b5 442 printf ("= * ERROR %d get_pressure\n\r", err);
nikapov 0:694e888fd1b5 443 red_led = 1;
nikapov 0:694e888fd1b5 444 return;
nikapov 0:694e888fd1b5 445 } else {
nikapov 0:694e888fd1b5 446 printf ("Pressure mBar: %f\n\r", press);
nikapov 0:694e888fd1b5 447 red_led = 0;
nikapov 0:694e888fd1b5 448 }
nikapov 0:694e888fd1b5 449
nikapov 0:694e888fd1b5 450 stringstream ss_temp;
nikapov 0:694e888fd1b5 451 ss_temp << temp;
nikapov 0:694e888fd1b5 452 std::string stringified = ss_temp.str();
nikapov 0:694e888fd1b5 453 temp_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 0:694e888fd1b5 454
nikapov 0:694e888fd1b5 455 stringstream ss_hum;
nikapov 0:694e888fd1b5 456 ss_hum << hum;
nikapov 0:694e888fd1b5 457 stringified = ss_hum.str();
nikapov 0:694e888fd1b5 458 hum_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 0:694e888fd1b5 459
nikapov 0:694e888fd1b5 460 stringstream ss_press;
nikapov 0:694e888fd1b5 461 ss_press << press;
nikapov 0:694e888fd1b5 462 stringified = ss_press.str();
nikapov 0:694e888fd1b5 463 press_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 0:694e888fd1b5 464 }
nikapov 0:694e888fd1b5 465
nikapov 0:694e888fd1b5 466 private:
nikapov 0:694e888fd1b5 467
nikapov 0:694e888fd1b5 468 M2MObject* temp_object;
nikapov 0:694e888fd1b5 469 M2MObjectInstance* temp_inst;
nikapov 0:694e888fd1b5 470 M2MResource* temp_res;
nikapov 0:694e888fd1b5 471
nikapov 0:694e888fd1b5 472 M2MObject* hum_object;
nikapov 0:694e888fd1b5 473 M2MObjectInstance* hum_inst;
nikapov 0:694e888fd1b5 474 M2MResource* hum_res;
nikapov 0:694e888fd1b5 475
nikapov 0:694e888fd1b5 476 M2MObject* press_object;
nikapov 0:694e888fd1b5 477 M2MObjectInstance* press_inst;
nikapov 0:694e888fd1b5 478 M2MResource* press_res;
nikapov 0:694e888fd1b5 479
nikapov 0:694e888fd1b5 480 M2MResource* timer_res;
nikapov 0:694e888fd1b5 481
nikapov 0:694e888fd1b5 482 #ifdef IKS01A2
nikapov 0:694e888fd1b5 483 XNucleoIKS01A2 *p_mems_expansion_board;
nikapov 0:694e888fd1b5 484 #else
nikapov 0:694e888fd1b5 485 XNucleoIKS01A1 *p_mems_expansion_board;
nikapov 0:694e888fd1b5 486 #endif
nikapov 0:694e888fd1b5 487
nikapov 0:694e888fd1b5 488 };
nikapov 0:694e888fd1b5 489
nikapov 0:694e888fd1b5 490
nikapov 0:694e888fd1b5 491 /* STMicroelectronics IKS01A1/2 code - END */
nikapov 0:694e888fd1b5 492
nikapov 0:694e888fd1b5 493 // Network interaction must be performed outside of interrupt context
nikapov 0:694e888fd1b5 494 Semaphore updates(0);
nikapov 0:694e888fd1b5 495 volatile bool registered = false;
nikapov 0:694e888fd1b5 496 volatile bool clicked = false;
nikapov 0:694e888fd1b5 497 osThreadId mainThread;
nikapov 0:694e888fd1b5 498
nikapov 0:694e888fd1b5 499 void unregister() {
nikapov 0:694e888fd1b5 500 registered = false;
nikapov 0:694e888fd1b5 501 blue_led = 0;
nikapov 0:694e888fd1b5 502 updates.release();
nikapov 0:694e888fd1b5 503 }
nikapov 0:694e888fd1b5 504
nikapov 0:694e888fd1b5 505 void button_clicked() {
nikapov 0:694e888fd1b5 506 clicked = true;
nikapov 0:694e888fd1b5 507 }
nikapov 0:694e888fd1b5 508
nikapov 0:694e888fd1b5 509 // debug printf function
nikapov 0:694e888fd1b5 510 void trace_printer(const char* str) {
nikapov 0:694e888fd1b5 511 printf("%s\r\n", str);
nikapov 0:694e888fd1b5 512 }
nikapov 0:694e888fd1b5 513
nikapov 0:694e888fd1b5 514 // Entry point to the program
nikapov 0:694e888fd1b5 515 int main() {
nikapov 0:694e888fd1b5 516
nikapov 0:694e888fd1b5 517 unsigned int seed;
nikapov 0:694e888fd1b5 518 size_t len;
nikapov 0:694e888fd1b5 519
nikapov 0:694e888fd1b5 520 #ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
nikapov 0:694e888fd1b5 521 // Used to randomize source port
nikapov 0:694e888fd1b5 522 mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len);
nikapov 0:694e888fd1b5 523
nikapov 0:694e888fd1b5 524 #elif defined MBEDTLS_TEST_NULL_ENTROPY
nikapov 0:694e888fd1b5 525
nikapov 0:694e888fd1b5 526 #warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware."
nikapov 0:694e888fd1b5 527 // Used to randomize source port
nikapov 0:694e888fd1b5 528 mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len);
nikapov 0:694e888fd1b5 529
nikapov 0:694e888fd1b5 530 #else
nikapov 0:694e888fd1b5 531
nikapov 0:694e888fd1b5 532 #error "This hardware does not have entropy, endpoint will not register to Connector.\
nikapov 0:694e888fd1b5 533 You need to enable NULL ENTROPY for your application, but if this configuration change is made then no security is offered by mbed TLS.\
nikapov 0:694e888fd1b5 534 Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint."
nikapov 0:694e888fd1b5 535
nikapov 0:694e888fd1b5 536 #endif
nikapov 0:694e888fd1b5 537
nikapov 0:694e888fd1b5 538 srand(seed);
nikapov 0:694e888fd1b5 539 red_led = LED_OFF;
nikapov 0:694e888fd1b5 540 blue_led = LED_OFF;
nikapov 0:694e888fd1b5 541
nikapov 0:694e888fd1b5 542 status_ticker.attach_us(blinky, 250000);
nikapov 0:694e888fd1b5 543 // Keep track of the main thread
nikapov 0:694e888fd1b5 544 mainThread = osThreadGetId();
nikapov 0:694e888fd1b5 545
nikapov 0:694e888fd1b5 546 printf("\nStarting mbed Client example\n");
nikapov 0:694e888fd1b5 547
nikapov 0:694e888fd1b5 548 mbed_trace_init();
nikapov 0:694e888fd1b5 549 mbed_trace_print_function_set(trace_printer);
nikapov 0:694e888fd1b5 550 mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN);
nikapov 0:694e888fd1b5 551
nikapov 0:694e888fd1b5 552 NetworkInterface* network = easy_connect(true);
nikapov 0:694e888fd1b5 553 if(network == NULL) {
nikapov 0:694e888fd1b5 554 printf("\nConnection to Network Failed - exiting application...\n");
nikapov 0:694e888fd1b5 555 return -1;
nikapov 0:694e888fd1b5 556 }
nikapov 0:694e888fd1b5 557
nikapov 0:694e888fd1b5 558 // we create our button and LED resources
nikapov 0:694e888fd1b5 559 ButtonResource button_resource;
nikapov 0:694e888fd1b5 560 LedResource led_resource;
nikapov 0:694e888fd1b5 561 BigPayloadResource big_payload_resource;
nikapov 0:694e888fd1b5 562
nikapov 0:694e888fd1b5 563 // STMicroelectronics IKS01A1/2
nikapov 0:694e888fd1b5 564 EnvResource env_resource;
nikapov 0:694e888fd1b5 565
nikapov 0:694e888fd1b5 566
nikapov 0:694e888fd1b5 567 #ifdef TARGET_K64F
nikapov 0:694e888fd1b5 568 // On press of SW3 button on K64F board, example application
nikapov 0:694e888fd1b5 569 // will call unregister API towards mbed Device Connector
nikapov 0:694e888fd1b5 570 //unreg_button.fall(&mbed_client,&MbedClient::test_unregister);
nikapov 0:694e888fd1b5 571 unreg_button.fall(&unregister);
nikapov 0:694e888fd1b5 572
nikapov 0:694e888fd1b5 573 // Observation Button (SW2) press will send update of endpoint resource values to connector
nikapov 0:694e888fd1b5 574 obs_button.fall(&button_clicked);
nikapov 0:694e888fd1b5 575 #elif defined(TARGET_NUCLEO_F429ZI) || defined (TARGET_NUCLEO_L476RG)
nikapov 0:694e888fd1b5 576 InterruptIn user_button(USER_BUTTON);
nikapov 0:694e888fd1b5 577 user_button.fall(&button_clicked);
nikapov 0:694e888fd1b5 578 #else
nikapov 0:694e888fd1b5 579 // Send update of endpoint resource values to connector every 15 seconds periodically
nikapov 0:694e888fd1b5 580 timer.attach(&button_clicked, 15.0);
nikapov 0:694e888fd1b5 581 #endif
nikapov 0:694e888fd1b5 582
nikapov 0:694e888fd1b5 583 // Create endpoint interface to manage register and unregister
nikapov 0:694e888fd1b5 584 mbed_client.create_interface(MBED_SERVER_ADDRESS, network);
nikapov 0:694e888fd1b5 585
nikapov 0:694e888fd1b5 586 // Create Objects of varying types, see simpleclient.h for more details on implementation.
nikapov 0:694e888fd1b5 587 M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info
nikapov 0:694e888fd1b5 588 M2MDevice* device_object = mbed_client.create_device_object(); // device resources object
nikapov 0:694e888fd1b5 589
nikapov 0:694e888fd1b5 590 // Create list of Objects to register
nikapov 0:694e888fd1b5 591 M2MObjectList object_list;
nikapov 0:694e888fd1b5 592
nikapov 0:694e888fd1b5 593 // Add objects to list
nikapov 0:694e888fd1b5 594 object_list.push_back(device_object);
nikapov 0:694e888fd1b5 595 object_list.push_back(button_resource.get_object());
nikapov 0:694e888fd1b5 596 object_list.push_back(led_resource.get_object());
nikapov 0:694e888fd1b5 597 object_list.push_back(big_payload_resource.get_object());
nikapov 0:694e888fd1b5 598
nikapov 0:694e888fd1b5 599 // STMicroelectronics IKS01A1/2
nikapov 0:694e888fd1b5 600 object_list.push_back(env_resource.get_temp_object());
nikapov 0:694e888fd1b5 601 object_list.push_back(env_resource.get_hum_object());
nikapov 0:694e888fd1b5 602 object_list.push_back(env_resource.get_press_object());
nikapov 0:694e888fd1b5 603
nikapov 0:694e888fd1b5 604 // Set endpoint registration object
nikapov 0:694e888fd1b5 605 mbed_client.set_register_object(register_object);
nikapov 0:694e888fd1b5 606
nikapov 0:694e888fd1b5 607 // Register with mbed Device Connector
nikapov 0:694e888fd1b5 608 mbed_client.test_register(register_object, object_list);
nikapov 0:694e888fd1b5 609
nikapov 0:694e888fd1b5 610
nikapov 0:694e888fd1b5 611 // STMicroelectronics IKS01A1/2
nikapov 0:694e888fd1b5 612 // wait for registration before getting data
nikapov 0:694e888fd1b5 613 while (!mbed_client.register_successful()) {
nikapov 0:694e888fd1b5 614 Thread::wait(500);
nikapov 0:694e888fd1b5 615 }
nikapov 0:694e888fd1b5 616 registered = true;
nikapov 0:694e888fd1b5 617 blue_led = 1;
nikapov 0:694e888fd1b5 618 printf ("\r\nRegistered! Now getting sensor data\r\n\n");
nikapov 0:694e888fd1b5 619
nikapov 0:694e888fd1b5 620 while (true) {
nikapov 0:694e888fd1b5 621
nikapov 0:694e888fd1b5 622 int timer_val = env_resource.get_polling_period();
nikapov 0:694e888fd1b5 623 env_resource.update_resources();
nikapov 0:694e888fd1b5 624
nikapov 0:694e888fd1b5 625 if(clicked) {
nikapov 0:694e888fd1b5 626 clicked = false;
nikapov 0:694e888fd1b5 627 button_resource.handle_button_click();
nikapov 0:694e888fd1b5 628 }
nikapov 0:694e888fd1b5 629 Thread::wait(timer_val);
nikapov 0:694e888fd1b5 630 }
nikapov 0:694e888fd1b5 631
nikapov 0:694e888fd1b5 632 mbed_client.test_unregister();
nikapov 0:694e888fd1b5 633 status_ticker.detach();
nikapov 0:694e888fd1b5 634 }