An mbed BLE-to-Cloud Gateway using Nucleo-F429ZI+X-Nucleo-IDB05A1 or Nucleo-L476RG+X-Nucleo-IDB05A1+X-Nucleo-IDW01M1.

Information

Nucleo- F429ZI configuration requires two hardware patches:

  1. on Nucleo-F429ZI open SB121 and close SB122
  2. on X-Nucleo-IDB05A1 move R4 to R6

The BLE client searches for and connects to a MotEnv node.

Committer:
nikapov
Date:
Thu Oct 12 17:28:58 2017 +0200
Revision:
1:d9c0c4889bd2
Parent:
0:c7083010ae49
Child:
3:39c8d17bed52
Update easy-connect to support IDW01M1 Wi-Fi.
Add BLE Client code and environmental data support.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nikapov 0:c7083010ae49 1 /*
nikapov 0:c7083010ae49 2 * Copyright (c) 2015, 2016 ARM Limited. All rights reserved.
nikapov 0:c7083010ae49 3 * SPDX-License-Identifier: Apache-2.0
nikapov 0:c7083010ae49 4 * Licensed under the Apache License, Version 2.0 (the License); you may
nikapov 0:c7083010ae49 5 * not use this file except in compliance with the License.
nikapov 0:c7083010ae49 6 * You may obtain a copy of the License at
nikapov 0:c7083010ae49 7 *
nikapov 0:c7083010ae49 8 * http://www.apache.org/licenses/LICENSE-2.0
nikapov 0:c7083010ae49 9 *
nikapov 0:c7083010ae49 10 * Unless required by applicable law or agreed to in writing, software
nikapov 0:c7083010ae49 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
nikapov 0:c7083010ae49 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nikapov 0:c7083010ae49 13 * See the License for the specific language governing permissions and
nikapov 0:c7083010ae49 14 * limitations under the License.
nikapov 0:c7083010ae49 15 */
nikapov 0:c7083010ae49 16 #define __STDC_FORMAT_MACROS
nikapov 0:c7083010ae49 17 #include <inttypes.h>
nikapov 0:c7083010ae49 18 #include "simpleclient.h"
nikapov 0:c7083010ae49 19 #include <string>
nikapov 0:c7083010ae49 20 #include <sstream>
nikapov 0:c7083010ae49 21 #include <vector>
nikapov 0:c7083010ae49 22 #include "mbed-trace/mbed_trace.h"
nikapov 0:c7083010ae49 23 #include "mbedtls/entropy_poll.h"
nikapov 1:d9c0c4889bd2 24 #include "ble\BLE.h"
nikapov 1:d9c0c4889bd2 25 #include "ble\DiscoveredCharacteristic.h"
nikapov 1:d9c0c4889bd2 26 #include "ble\DiscoveredService.h"
nikapov 1:d9c0c4889bd2 27
nikapov 0:c7083010ae49 28
nikapov 0:c7083010ae49 29 #include "security.h"
nikapov 0:c7083010ae49 30
nikapov 0:c7083010ae49 31 #include "mbed.h"
nikapov 0:c7083010ae49 32
nikapov 0:c7083010ae49 33 // easy-connect compliancy, it has 2 sets of wifi pins we have only one
nikapov 0:c7083010ae49 34 #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX
nikapov 0:c7083010ae49 35 #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX
nikapov 1:d9c0c4889bd2 36 #define MBED_CFG_SPWF01SA_TX MBED_CONF_APP_WIFI_TX
nikapov 1:d9c0c4889bd2 37 #define MBED_CFG_SPWF01SA_RX MBED_CONF_APP_WIFI_RX
nikapov 0:c7083010ae49 38 #include "easy-connect/easy-connect.h"
nikapov 0:c7083010ae49 39
nikapov 0:c7083010ae49 40 #ifdef TARGET_STM
nikapov 0:c7083010ae49 41 #define RED_LED (LED3)
nikapov 0:c7083010ae49 42 #define GREEN_LED (LED1)
nikapov 0:c7083010ae49 43 #define BLUE_LED (LED2)
nikapov 0:c7083010ae49 44 #define LED_ON (1)
nikapov 0:c7083010ae49 45 #else // !TARGET_STM
nikapov 0:c7083010ae49 46 #define RED_LED (LED1)
nikapov 0:c7083010ae49 47 #define GREEN_LED (LED2)
nikapov 0:c7083010ae49 48 #define BLUE_LED (LED3)
nikapov 0:c7083010ae49 49 #define LED_ON (0)
nikapov 0:c7083010ae49 50 #endif // !TARGET_STM
nikapov 0:c7083010ae49 51 #define LED_OFF (!LED_ON)
nikapov 0:c7083010ae49 52
nikapov 0:c7083010ae49 53 // Status indication
nikapov 0:c7083010ae49 54 DigitalOut red_led(RED_LED);
nikapov 0:c7083010ae49 55 DigitalOut green_led(GREEN_LED);
nikapov 0:c7083010ae49 56 DigitalOut blue_led(BLUE_LED);
nikapov 0:c7083010ae49 57
nikapov 1:d9c0c4889bd2 58
nikapov 1:d9c0c4889bd2 59 /************************************************************BLE Stuff from here *********************************/
nikapov 1:d9c0c4889bd2 60
nikapov 1:d9c0c4889bd2 61 BLE &ble = BLE::Instance();
nikapov 1:d9c0c4889bd2 62 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
nikapov 1:d9c0c4889bd2 63 Thread BLE_thread;
nikapov 1:d9c0c4889bd2 64 static bool triggerEnvCharacteristic;
nikapov 1:d9c0c4889bd2 65 static bool envDataAvailable = false;
nikapov 1:d9c0c4889bd2 66 static DiscoveredCharacteristic envCharacteristic;
nikapov 1:d9c0c4889bd2 67 uint16_t payload_length = 0;
nikapov 1:d9c0c4889bd2 68 uint8_t dataforClient[12];
nikapov 1:d9c0c4889bd2 69
nikapov 1:d9c0c4889bd2 70 void BLEConnect(BLEProtocol::AddressBytes_t address) {
nikapov 1:d9c0c4889bd2 71 BLE::Instance().gap().connect(address, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
nikapov 1:d9c0c4889bd2 72 }
nikapov 1:d9c0c4889bd2 73
nikapov 1:d9c0c4889bd2 74
nikapov 1:d9c0c4889bd2 75 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
nikapov 1:d9c0c4889bd2 76 // parse the advertising payload, looking for data type MANUFACTURER_SPECIFIC_DATA
nikapov 1:d9c0c4889bd2 77 // The advertising payload is a collection of key/value records where
nikapov 1:d9c0c4889bd2 78 // byte 0: length of the record excluding this byte
nikapov 1:d9c0c4889bd2 79 // byte 1: The key, it is the type of the data
nikapov 1:d9c0c4889bd2 80 // byte [2..N] The value. N is equal to byte0 - 1
nikapov 1:d9c0c4889bd2 81
nikapov 1:d9c0c4889bd2 82 //printf("Starting advertisementCallback...\r\n");
nikapov 1:d9c0c4889bd2 83
nikapov 1:d9c0c4889bd2 84 for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
nikapov 1:d9c0c4889bd2 85
nikapov 1:d9c0c4889bd2 86 const uint8_t record_length = params->advertisingData[i];
nikapov 1:d9c0c4889bd2 87 if (record_length == 0) {
nikapov 1:d9c0c4889bd2 88 continue;
nikapov 1:d9c0c4889bd2 89 }
nikapov 1:d9c0c4889bd2 90 const uint8_t type = params->advertisingData[i + 1];
nikapov 1:d9c0c4889bd2 91 const uint8_t* value = params->advertisingData + i + 2;
nikapov 1:d9c0c4889bd2 92 const uint8_t value_length = record_length - 1;
nikapov 1:d9c0c4889bd2 93
nikapov 1:d9c0c4889bd2 94 if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
nikapov 1:d9c0c4889bd2 95 char devName[16];
nikapov 1:d9c0c4889bd2 96 int strLength = value_length > 15 ? 15 : value_length;
nikapov 1:d9c0c4889bd2 97 memcpy (devName, value, strLength);
nikapov 1:d9c0c4889bd2 98 devName[strLength] = '\0';
nikapov 1:d9c0c4889bd2 99 printf("Found a device with name: %s\n\r", devName);
nikapov 1:d9c0c4889bd2 100
nikapov 1:d9c0c4889bd2 101 if (memcmp(value, "BlueMbedOS", value_length) == 0) {
nikapov 1:d9c0c4889bd2 102 printf("Found an mbed device node\n");
nikapov 1:d9c0c4889bd2 103 BLEProtocol::AddressBytes_t devAddress;
nikapov 1:d9c0c4889bd2 104 memcpy (devAddress, params->peerAddr,BLEProtocol::ADDR_LEN);
nikapov 1:d9c0c4889bd2 105 eventQueue.call(BLEConnect,devAddress);
nikapov 1:d9c0c4889bd2 106 break;
nikapov 1:d9c0c4889bd2 107 }
nikapov 1:d9c0c4889bd2 108 }
nikapov 1:d9c0c4889bd2 109 /*
nikapov 1:d9c0c4889bd2 110 if(type == GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA) {
nikapov 1:d9c0c4889bd2 111 printf("length: %d - mask: 0x%x\n\r", value_length, *((uint32_t*)(value+2)));
nikapov 1:d9c0c4889bd2 112 if (((value_length == 6) || (value_length == 12)) && (*((uint32_t*)(value+2)) & 0x00001C00) == 0x00001C00) {
nikapov 1:d9c0c4889bd2 113 printf("Found an ST device with environmental data\n");
nikapov 1:d9c0c4889bd2 114 //BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
nikapov 1:d9c0c4889bd2 115 BLEProtocol::AddressBytes_t devAddress;
nikapov 1:d9c0c4889bd2 116 memcpy (devAddress, params->peerAddr,BLEProtocol::ADDR_LEN);
nikapov 1:d9c0c4889bd2 117 eventQueue.call(BLEConnect,devAddress);
nikapov 1:d9c0c4889bd2 118 break;
nikapov 1:d9c0c4889bd2 119 }
nikapov 1:d9c0c4889bd2 120 }
nikapov 1:d9c0c4889bd2 121 */
nikapov 1:d9c0c4889bd2 122 i += record_length;
nikapov 1:d9c0c4889bd2 123 }
nikapov 1:d9c0c4889bd2 124 }
nikapov 1:d9c0c4889bd2 125
nikapov 1:d9c0c4889bd2 126 void serviceDiscoveryCallback(const DiscoveredService *service) {
nikapov 1:d9c0c4889bd2 127
nikapov 1:d9c0c4889bd2 128 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
nikapov 1:d9c0c4889bd2 129 printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
nikapov 1:d9c0c4889bd2 130 } else {
nikapov 1:d9c0c4889bd2 131 printf("S UUID-");
nikapov 1:d9c0c4889bd2 132 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
nikapov 1:d9c0c4889bd2 133 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
nikapov 1:d9c0c4889bd2 134 printf("%02x", longUUIDBytes[i]);
nikapov 1:d9c0c4889bd2 135 }
nikapov 1:d9c0c4889bd2 136 printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
nikapov 1:d9c0c4889bd2 137 }
nikapov 1:d9c0c4889bd2 138 }
nikapov 1:d9c0c4889bd2 139
nikapov 1:d9c0c4889bd2 140 //read data from BLE
nikapov 1:d9c0c4889bd2 141 void updateEnvCharacteristic(void) {
nikapov 1:d9c0c4889bd2 142 if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
nikapov 1:d9c0c4889bd2 143 //printf("Reading environmental data\n\n");
nikapov 1:d9c0c4889bd2 144 envCharacteristic.read();
nikapov 1:d9c0c4889bd2 145 envDataAvailable = true;
nikapov 1:d9c0c4889bd2 146 } else {
nikapov 1:d9c0c4889bd2 147 envDataAvailable = false;
nikapov 1:d9c0c4889bd2 148 }
nikapov 1:d9c0c4889bd2 149
nikapov 1:d9c0c4889bd2 150 }
nikapov 1:d9c0c4889bd2 151
nikapov 1:d9c0c4889bd2 152
nikapov 1:d9c0c4889bd2 153 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
nikapov 1:d9c0c4889bd2 154 /*
nikapov 1:d9c0c4889bd2 155 printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
nikapov 1:d9c0c4889bd2 156 if (characteristicP->getUUID().getShortUUID() == 0xA001) { /* !ALERT! Alter this filter to suit your device. */
nikapov 1:d9c0c4889bd2 157 /* optCharacteristic = *characteristicP;
nikapov 1:d9c0c4889bd2 158 triggerLedCharacteristic = true;
nikapov 1:d9c0c4889bd2 159 }*/
nikapov 1:d9c0c4889bd2 160 printf("Found environmental data\n");
nikapov 1:d9c0c4889bd2 161 envCharacteristic = *characteristicP;
nikapov 1:d9c0c4889bd2 162 triggerEnvCharacteristic = true;
nikapov 0:c7083010ae49 163 }
nikapov 0:c7083010ae49 164
nikapov 1:d9c0c4889bd2 165 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
nikapov 1:d9c0c4889bd2 166
nikapov 1:d9c0c4889bd2 167 //printf("terminated SD for handle %u\r\n", connectionHandle);
nikapov 1:d9c0c4889bd2 168
nikapov 1:d9c0c4889bd2 169 if (triggerEnvCharacteristic) {
nikapov 1:d9c0c4889bd2 170 triggerEnvCharacteristic = false;
nikapov 1:d9c0c4889bd2 171 eventQueue.call(updateEnvCharacteristic);
nikapov 1:d9c0c4889bd2 172 }
nikapov 1:d9c0c4889bd2 173 }
nikapov 1:d9c0c4889bd2 174
nikapov 1:d9c0c4889bd2 175 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
nikapov 1:d9c0c4889bd2 176 printf("Connected to ST Node now...\r\n");
nikapov 1:d9c0c4889bd2 177 if (params->role == Gap::CENTRAL) {
nikapov 1:d9c0c4889bd2 178 BLE &ble = BLE::Instance();
nikapov 1:d9c0c4889bd2 179 ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
nikapov 1:d9c0c4889bd2 180 const char *servUUIDString = "00000000-0001-11e1-9ab4-0002a5d5c51b";
nikapov 1:d9c0c4889bd2 181 UUID servUUID(servUUIDString);
nikapov 1:d9c0c4889bd2 182 const char *charUUIDString = "001c0000-0001-11e1-ac36-0002a5d5c51b";
nikapov 1:d9c0c4889bd2 183 UUID charUUID(charUUIDString);
nikapov 1:d9c0c4889bd2 184 ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, servUUID, charUUID);
nikapov 1:d9c0c4889bd2 185 }
nikapov 1:d9c0c4889bd2 186 }
nikapov 1:d9c0c4889bd2 187
nikapov 1:d9c0c4889bd2 188
nikapov 1:d9c0c4889bd2 189 void triggerRead(const GattReadCallbackParams *response) {
nikapov 1:d9c0c4889bd2 190
nikapov 1:d9c0c4889bd2 191 if (response->handle == envCharacteristic.getValueHandle()) {
nikapov 1:d9c0c4889bd2 192 payload_length = response-> len;
nikapov 1:d9c0c4889bd2 193 for(int i=0; i< response-> len; i++) {
nikapov 1:d9c0c4889bd2 194 // printf("%02x", response->data[i]);
nikapov 1:d9c0c4889bd2 195 dataforClient[i] = response -> data[i];
nikapov 1:d9c0c4889bd2 196 // printf("%d", dataforClient[i]);
nikapov 1:d9c0c4889bd2 197 }
nikapov 1:d9c0c4889bd2 198
nikapov 1:d9c0c4889bd2 199 //printf("Temperature: %f\r\n", (uint32_t)((dataforClient[9]<<8) | dataforClient[8])/10.0);
nikapov 1:d9c0c4889bd2 200 //printf("Humidity: %f\r\n", (uint32_t)((dataforClient[7]<<8) | dataforClient[6])/10.0);
nikapov 1:d9c0c4889bd2 201 //printf("Pressure: %f\r\n\r\n\r\n", (uint32_t)((dataforClient[5]<<24) |(dataforClient[4]<<16) |(dataforClient[3]<<8) | dataforClient[2])/100.0);
nikapov 1:d9c0c4889bd2 202
nikapov 1:d9c0c4889bd2 203 eventQueue.call(updateEnvCharacteristic); // triggering BLE data read again
nikapov 1:d9c0c4889bd2 204 }
nikapov 1:d9c0c4889bd2 205 }
nikapov 1:d9c0c4889bd2 206
nikapov 1:d9c0c4889bd2 207 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) {
nikapov 1:d9c0c4889bd2 208 printf("Got disconnected from the device!\r\n");
nikapov 1:d9c0c4889bd2 209 /* Start scanning and try to connect again */
nikapov 1:d9c0c4889bd2 210 BLE::Instance().gap().startScan(advertisementCallback);
nikapov 1:d9c0c4889bd2 211 }
nikapov 1:d9c0c4889bd2 212
nikapov 1:d9c0c4889bd2 213 void onBleInitError(BLE &ble, ble_error_t error)
nikapov 1:d9c0c4889bd2 214 {
nikapov 1:d9c0c4889bd2 215 /* Initialization error handling should go here */
nikapov 1:d9c0c4889bd2 216 printf("BLE Error = %u\r\n", error);
nikapov 1:d9c0c4889bd2 217 }
nikapov 1:d9c0c4889bd2 218
nikapov 1:d9c0c4889bd2 219 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
nikapov 1:d9c0c4889bd2 220 {
nikapov 1:d9c0c4889bd2 221 //printf("I'm inside BLE init\r\n");
nikapov 1:d9c0c4889bd2 222 BLE& ble = params->ble;
nikapov 1:d9c0c4889bd2 223 ble_error_t error = params->error;
nikapov 1:d9c0c4889bd2 224 ble_error_t error1 = params->error;
nikapov 1:d9c0c4889bd2 225
nikapov 1:d9c0c4889bd2 226 if (error != BLE_ERROR_NONE) {
nikapov 1:d9c0c4889bd2 227 /* In case of error, forward the error handling to onBleInitError */
nikapov 1:d9c0c4889bd2 228 onBleInitError(ble, error);
nikapov 1:d9c0c4889bd2 229 return;
nikapov 1:d9c0c4889bd2 230 }
nikapov 1:d9c0c4889bd2 231
nikapov 1:d9c0c4889bd2 232 /* Ensure that it is the default instance of BLE */
nikapov 1:d9c0c4889bd2 233 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
nikapov 1:d9c0c4889bd2 234 printf("Not the default instance\r\n");
nikapov 1:d9c0c4889bd2 235 return;
nikapov 1:d9c0c4889bd2 236 }
nikapov 1:d9c0c4889bd2 237
nikapov 1:d9c0c4889bd2 238 ble.gap().onDisconnection(disconnectionCallback);
nikapov 1:d9c0c4889bd2 239 ble.gap().onConnection(connectionCallback);
nikapov 1:d9c0c4889bd2 240
nikapov 1:d9c0c4889bd2 241 // On reading data, call triggerRead function.
nikapov 1:d9c0c4889bd2 242 ble.gattClient().onDataRead(triggerRead);
nikapov 1:d9c0c4889bd2 243
nikapov 1:d9c0c4889bd2 244 // scan interval: 400ms and scan window: 400ms.
nikapov 1:d9c0c4889bd2 245 // Every 400ms the device will scan for 400ms
nikapov 1:d9c0c4889bd2 246 // This means that the device will scan continuously.
nikapov 1:d9c0c4889bd2 247 ble.gap().setScanParams(400, 400);
nikapov 1:d9c0c4889bd2 248 error = ble.gap().startScan(advertisementCallback);
nikapov 1:d9c0c4889bd2 249 if (error) {
nikapov 1:d9c0c4889bd2 250 printf("BLE Error startScan = %u\r\n", error);
nikapov 1:d9c0c4889bd2 251 }
nikapov 1:d9c0c4889bd2 252
nikapov 1:d9c0c4889bd2 253 }
nikapov 1:d9c0c4889bd2 254
nikapov 1:d9c0c4889bd2 255 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
nikapov 1:d9c0c4889bd2 256 BLE &ble = BLE::Instance();
nikapov 1:d9c0c4889bd2 257 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
nikapov 1:d9c0c4889bd2 258 }
nikapov 1:d9c0c4889bd2 259
nikapov 1:d9c0c4889bd2 260 //BLE thread init and further calls to other BLE methods.
nikapov 1:d9c0c4889bd2 261 void BLE_thread_init(void){
nikapov 1:d9c0c4889bd2 262 //printf("I'm inside BLE thread.....\r\n");
nikapov 1:d9c0c4889bd2 263
nikapov 1:d9c0c4889bd2 264 //Schedule events before starting the thread since there might be some missed events while scanning / pairing.
nikapov 1:d9c0c4889bd2 265 ble.onEventsToProcess(scheduleBleEventsProcessing);
nikapov 1:d9c0c4889bd2 266 ble.init(bleInitComplete);
nikapov 1:d9c0c4889bd2 267 //Loop forever the BLE thread
nikapov 1:d9c0c4889bd2 268 eventQueue.dispatch_forever();
nikapov 1:d9c0c4889bd2 269 }
nikapov 1:d9c0c4889bd2 270
nikapov 1:d9c0c4889bd2 271 /************************************************************BLE Stuff to here *********************************/
nikapov 1:d9c0c4889bd2 272
nikapov 0:c7083010ae49 273 // These are example resource values for the Device Object
nikapov 0:c7083010ae49 274 struct MbedClientDevice device = {
nikapov 0:c7083010ae49 275 "Manufacturer_String", // Manufacturer
nikapov 0:c7083010ae49 276 "Type_String", // Type
nikapov 0:c7083010ae49 277 "ModelNumber_String", // ModelNumber
nikapov 0:c7083010ae49 278 "SerialNumber_String" // SerialNumber
nikapov 0:c7083010ae49 279 };
nikapov 0:c7083010ae49 280
nikapov 0:c7083010ae49 281 // Instantiate the class which implements LWM2M Client API (from simpleclient.h)
nikapov 0:c7083010ae49 282 MbedClient mbed_client(device);
nikapov 0:c7083010ae49 283
nikapov 0:c7083010ae49 284
nikapov 1:d9c0c4889bd2 285 class EnvResource {
nikapov 1:d9c0c4889bd2 286 public:
nikapov 1:d9c0c4889bd2 287 EnvResource() {
nikapov 1:d9c0c4889bd2 288
nikapov 1:d9c0c4889bd2 289 temp_object = M2MInterfaceFactory::create_object("3303");
nikapov 1:d9c0c4889bd2 290 temp_inst = temp_object->create_object_instance();
nikapov 1:d9c0c4889bd2 291 temp_res = temp_inst->create_dynamic_resource("5700", "Temperature",
nikapov 1:d9c0c4889bd2 292 M2MResourceInstance::FLOAT, true); // observable
nikapov 1:d9c0c4889bd2 293 // we can only read this value
nikapov 1:d9c0c4889bd2 294 temp_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 1:d9c0c4889bd2 295 temp_res->set_value((uint8_t*)"20.0", 4);
nikapov 1:d9c0c4889bd2 296
nikapov 1:d9c0c4889bd2 297 hum_object = M2MInterfaceFactory::create_object("3304");
nikapov 1:d9c0c4889bd2 298 hum_inst = hum_object->create_object_instance();
nikapov 1:d9c0c4889bd2 299 hum_res = hum_inst->create_dynamic_resource("5700", "Humidity",
nikapov 1:d9c0c4889bd2 300 M2MResourceInstance::FLOAT, true); // observable
nikapov 1:d9c0c4889bd2 301 // we can only read this value
nikapov 1:d9c0c4889bd2 302 hum_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 1:d9c0c4889bd2 303 hum_res->set_value((uint8_t*)"50.0", 4);
nikapov 1:d9c0c4889bd2 304
nikapov 1:d9c0c4889bd2 305 press_object = M2MInterfaceFactory::create_object("3300");
nikapov 1:d9c0c4889bd2 306 press_inst = press_object->create_object_instance();
nikapov 1:d9c0c4889bd2 307 press_res = press_inst->create_dynamic_resource("5700", "Pressure",
nikapov 1:d9c0c4889bd2 308 M2MResourceInstance::FLOAT, true); // observable
nikapov 1:d9c0c4889bd2 309 // we can only read this value
nikapov 1:d9c0c4889bd2 310 press_res->set_operation(M2MBase::GET_ALLOWED);
nikapov 1:d9c0c4889bd2 311 press_res->set_value((uint8_t*)"1000", 4);
nikapov 1:d9c0c4889bd2 312
nikapov 1:d9c0c4889bd2 313 timer_res = press_inst->create_dynamic_resource("5603", "PollingPeriodMs", // one polling time for all env values, associated to humidity
nikapov 1:d9c0c4889bd2 314 M2MResourceInstance::INTEGER, false); // not observable
nikapov 1:d9c0c4889bd2 315 // we can read/wr this value
nikapov 1:d9c0c4889bd2 316 timer_res->set_operation(M2MBase::GET_PUT_ALLOWED);
nikapov 1:d9c0c4889bd2 317 timer_res->set_value((uint8_t*)"1000",4); // default 1s polling
nikapov 1:d9c0c4889bd2 318
nikapov 1:d9c0c4889bd2 319 }
nikapov 1:d9c0c4889bd2 320
nikapov 1:d9c0c4889bd2 321 M2MObject* get_temp_object() {
nikapov 1:d9c0c4889bd2 322 return temp_object;
nikapov 1:d9c0c4889bd2 323 }
nikapov 1:d9c0c4889bd2 324
nikapov 1:d9c0c4889bd2 325 M2MObject* get_hum_object() {
nikapov 1:d9c0c4889bd2 326 return hum_object;
nikapov 1:d9c0c4889bd2 327 }
nikapov 1:d9c0c4889bd2 328
nikapov 1:d9c0c4889bd2 329 M2MObject* get_press_object() {
nikapov 1:d9c0c4889bd2 330 return press_object;
nikapov 1:d9c0c4889bd2 331 }
nikapov 1:d9c0c4889bd2 332
nikapov 1:d9c0c4889bd2 333 int get_polling_period() {
nikapov 1:d9c0c4889bd2 334 return timer_res->get_value_int();
nikapov 1:d9c0c4889bd2 335 }
nikapov 0:c7083010ae49 336
nikapov 1:d9c0c4889bd2 337 void update_resources() {
nikapov 1:d9c0c4889bd2 338 float temp;
nikapov 1:d9c0c4889bd2 339 float hum;
nikapov 1:d9c0c4889bd2 340 float press;
nikapov 1:d9c0c4889bd2 341
nikapov 1:d9c0c4889bd2 342 if (!envDataAvailable) {
nikapov 1:d9c0c4889bd2 343 return;
nikapov 1:d9c0c4889bd2 344 }
nikapov 1:d9c0c4889bd2 345
nikapov 1:d9c0c4889bd2 346 temp = (uint32_t)((dataforClient[9]<<8) | dataforClient[8])/10.0;
nikapov 1:d9c0c4889bd2 347 hum = ((dataforClient[7]<<8) | dataforClient[6])/10.0;
nikapov 1:d9c0c4889bd2 348 press = (uint32_t)((dataforClient[5]<<24) |(dataforClient[4]<<16) |(dataforClient[3]<<8) | dataforClient[2])/100.0;
nikapov 1:d9c0c4889bd2 349
nikapov 1:d9c0c4889bd2 350 stringstream ss_temp;
nikapov 1:d9c0c4889bd2 351 ss_temp << temp;
nikapov 1:d9c0c4889bd2 352 std::string stringified = ss_temp.str();
nikapov 1:d9c0c4889bd2 353 temp_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 1:d9c0c4889bd2 354
nikapov 1:d9c0c4889bd2 355 stringstream ss_hum;
nikapov 1:d9c0c4889bd2 356 ss_hum << hum;
nikapov 1:d9c0c4889bd2 357 stringified = ss_hum.str();
nikapov 1:d9c0c4889bd2 358 hum_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 1:d9c0c4889bd2 359
nikapov 1:d9c0c4889bd2 360 stringstream ss_press;
nikapov 1:d9c0c4889bd2 361 ss_press << press;
nikapov 1:d9c0c4889bd2 362 stringified = ss_press.str();
nikapov 1:d9c0c4889bd2 363 press_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
nikapov 1:d9c0c4889bd2 364
nikapov 1:d9c0c4889bd2 365 }
nikapov 1:d9c0c4889bd2 366
nikapov 1:d9c0c4889bd2 367 private:
nikapov 1:d9c0c4889bd2 368
nikapov 1:d9c0c4889bd2 369 M2MObject* temp_object;
nikapov 1:d9c0c4889bd2 370 M2MObjectInstance* temp_inst;
nikapov 1:d9c0c4889bd2 371 M2MResource* temp_res;
nikapov 1:d9c0c4889bd2 372
nikapov 1:d9c0c4889bd2 373 M2MObject* hum_object;
nikapov 1:d9c0c4889bd2 374 M2MObjectInstance* hum_inst;
nikapov 1:d9c0c4889bd2 375 M2MResource* hum_res;
nikapov 1:d9c0c4889bd2 376
nikapov 1:d9c0c4889bd2 377 M2MObject* press_object;
nikapov 1:d9c0c4889bd2 378 M2MObjectInstance* press_inst;
nikapov 1:d9c0c4889bd2 379 M2MResource* press_res;
nikapov 1:d9c0c4889bd2 380
nikapov 1:d9c0c4889bd2 381 M2MResource* timer_res;
nikapov 1:d9c0c4889bd2 382
nikapov 0:c7083010ae49 383 };
nikapov 0:c7083010ae49 384
nikapov 0:c7083010ae49 385
nikapov 0:c7083010ae49 386 osThreadId mainThread;
nikapov 0:c7083010ae49 387
nikapov 0:c7083010ae49 388 // Entry point to the program
nikapov 0:c7083010ae49 389 int main() {
nikapov 0:c7083010ae49 390
nikapov 0:c7083010ae49 391 unsigned int seed;
nikapov 0:c7083010ae49 392 size_t len;
nikapov 0:c7083010ae49 393
nikapov 0:c7083010ae49 394 #ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
nikapov 0:c7083010ae49 395 // Used to randomize source port
nikapov 0:c7083010ae49 396 mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len);
nikapov 0:c7083010ae49 397
nikapov 0:c7083010ae49 398 #elif defined MBEDTLS_TEST_NULL_ENTROPY
nikapov 0:c7083010ae49 399
nikapov 0:c7083010ae49 400 #warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware."
nikapov 0:c7083010ae49 401 // Used to randomize source port
nikapov 0:c7083010ae49 402 mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len);
nikapov 0:c7083010ae49 403
nikapov 0:c7083010ae49 404 #else
nikapov 0:c7083010ae49 405
nikapov 0:c7083010ae49 406 #error "This hardware does not have entropy, endpoint will not register to Connector.\
nikapov 0:c7083010ae49 407 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:c7083010ae49 408 Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint."
nikapov 0:c7083010ae49 409
nikapov 0:c7083010ae49 410 #endif
nikapov 0:c7083010ae49 411
nikapov 0:c7083010ae49 412 srand(seed);
nikapov 0:c7083010ae49 413 red_led = LED_OFF;
nikapov 0:c7083010ae49 414 blue_led = LED_OFF;
nikapov 0:c7083010ae49 415
nikapov 0:c7083010ae49 416 // Keep track of the main thread
nikapov 0:c7083010ae49 417 mainThread = osThreadGetId();
nikapov 0:c7083010ae49 418
nikapov 0:c7083010ae49 419 printf("\nStarting mbed Client example\n");
nikapov 0:c7083010ae49 420
nikapov 1:d9c0c4889bd2 421 //mbed_trace_init();
nikapov 0:c7083010ae49 422
nikapov 0:c7083010ae49 423 NetworkInterface* network = easy_connect(true);
nikapov 0:c7083010ae49 424 if(network == NULL) {
nikapov 0:c7083010ae49 425 printf("\nConnection to Network Failed - exiting application...\n");
nikapov 0:c7083010ae49 426 return -1;
nikapov 0:c7083010ae49 427 }
nikapov 1:d9c0c4889bd2 428
nikapov 1:d9c0c4889bd2 429 // environmental data
nikapov 1:d9c0c4889bd2 430 EnvResource env_resource;
nikapov 1:d9c0c4889bd2 431
nikapov 0:c7083010ae49 432
nikapov 0:c7083010ae49 433 // Create endpoint interface to manage register and unregister
nikapov 0:c7083010ae49 434 mbed_client.create_interface(MBED_SERVER_ADDRESS, network);
nikapov 0:c7083010ae49 435
nikapov 0:c7083010ae49 436 // Create Objects of varying types, see simpleclient.h for more details on implementation.
nikapov 0:c7083010ae49 437 M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info
nikapov 0:c7083010ae49 438 M2MDevice* device_object = mbed_client.create_device_object(); // device resources object
nikapov 0:c7083010ae49 439
nikapov 0:c7083010ae49 440 // Create list of Objects to register
nikapov 0:c7083010ae49 441 M2MObjectList object_list;
nikapov 0:c7083010ae49 442
nikapov 0:c7083010ae49 443 // Add objects to list
nikapov 0:c7083010ae49 444 object_list.push_back(device_object);
nikapov 1:d9c0c4889bd2 445 object_list.push_back(env_resource.get_temp_object());
nikapov 1:d9c0c4889bd2 446 object_list.push_back(env_resource.get_hum_object());
nikapov 1:d9c0c4889bd2 447 object_list.push_back(env_resource.get_press_object());
nikapov 1:d9c0c4889bd2 448
nikapov 0:c7083010ae49 449 // Set endpoint registration object
nikapov 0:c7083010ae49 450 mbed_client.set_register_object(register_object);
nikapov 0:c7083010ae49 451
nikapov 0:c7083010ae49 452 // Register with mbed Device Connector
nikapov 0:c7083010ae49 453 mbed_client.test_register(register_object, object_list);
nikapov 0:c7083010ae49 454
nikapov 1:d9c0c4889bd2 455 // wait for registration and BLE data started flushing
nikapov 1:d9c0c4889bd2 456 while (!mbed_client.register_successful()) {
nikapov 1:d9c0c4889bd2 457 Thread::wait(500);
nikapov 1:d9c0c4889bd2 458 }
nikapov 1:d9c0c4889bd2 459
nikapov 1:d9c0c4889bd2 460 printf("\nNow starting BLE thread\n");
nikapov 1:d9c0c4889bd2 461 BLE_thread.start(BLE_thread_init);
nikapov 1:d9c0c4889bd2 462
nikapov 1:d9c0c4889bd2 463 while (!envDataAvailable) {
nikapov 1:d9c0c4889bd2 464 Thread::wait(500);
nikapov 1:d9c0c4889bd2 465 }
nikapov 1:d9c0c4889bd2 466
nikapov 1:d9c0c4889bd2 467 printf ("\nNow pushing data to the mbed device connector.\n");
nikapov 1:d9c0c4889bd2 468
nikapov 0:c7083010ae49 469 while (true) {
nikapov 1:d9c0c4889bd2 470
nikapov 1:d9c0c4889bd2 471 env_resource.update_resources();
nikapov 1:d9c0c4889bd2 472 int timer_val = env_resource.get_polling_period();
nikapov 1:d9c0c4889bd2 473 Thread::wait(timer_val);
nikapov 0:c7083010ae49 474 }
nikapov 0:c7083010ae49 475
nikapov 0:c7083010ae49 476 mbed_client.test_unregister();
nikapov 1:d9c0c4889bd2 477
nikapov 0:c7083010ae49 478 }