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:
Fri Oct 20 19:04:58 2017 +0200
Revision:
4:d5f5559b48f7
Parent:
3:39c8d17bed52
Add support to Nucleo_F429ZI and ethernet.

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