mbedOS client example, modified to push X-Nucleo-IKS01A1/2 Environmental Sensor data to mbed Cloud Connector.

Dependencies:   X_NUCLEO_IKS01A1 X_NUCLEO_IKS01A2

The application is derived from the official mbedOS client example (link) and has been tested using 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-IKS02A1 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.
  • Connect the board to your ethernet network, open a serial terminal (params 115200N1) and wait that the client is connected to the mbed Connector.
  • Press user button to start acquiring and pushing the environmental (pressure, temperature and humidity) data.

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

Committer:
nikapov
Date:
Wed Apr 26 18:23:56 2017 +0200
Revision:
0:003e60a0deb8
First version.
Original repository: https://github.com/ARMmbed/mbed-os-example-client
Version hash: 629b972f41109fd1b54bb755ea454d736a50069b

Who changed what in which revision?

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