This is an example of BLE GATT Client, which receives broadcast data from BLE_Server_BME280 ( a GATT server) , then transfers values up to mbed Device Connector (cloud).

Please refer details about BLEClient_mbedDevConn below. https://github.com/soramame21/BLEClient_mbedDevConn

The location of required BLE GATT server, BLE_Server_BME280, is at here. https://developer.mbed.org/users/edamame22/code/BLE_Server_BME280/

Committer:
Ren Boting
Date:
Tue Sep 05 11:56:13 2017 +0900
Revision:
2:b894b3508057
Parent:
1:8950e6a891df
Update all libraries and reform main.cpp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
edamame22 0:29983394c6b6 1 /*
edamame22 0:29983394c6b6 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
edamame22 0:29983394c6b6 3 * SPDX-License-Identifier: Apache-2.0
edamame22 0:29983394c6b6 4 * Licensed under the Apache License, Version 2.0 (the License); you may
edamame22 0:29983394c6b6 5 * not use this file except in compliance with the License.
edamame22 0:29983394c6b6 6 * You may obtain a copy of the License at
edamame22 0:29983394c6b6 7 *
edamame22 0:29983394c6b6 8 * http://www.apache.org/licenses/LICENSE-2.0
edamame22 0:29983394c6b6 9 *
edamame22 0:29983394c6b6 10 * Unless required by applicable law or agreed to in writing, software
edamame22 0:29983394c6b6 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
edamame22 0:29983394c6b6 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
edamame22 0:29983394c6b6 13 * See the License for the specific language governing permissions and
edamame22 0:29983394c6b6 14 * limitations under the License.
edamame22 0:29983394c6b6 15 */
edamame22 0:29983394c6b6 16
edamame22 0:29983394c6b6 17 #include "simpleclient.h"
edamame22 0:29983394c6b6 18 #include <string>
edamame22 0:29983394c6b6 19 #include <sstream>
edamame22 0:29983394c6b6 20 #include <vector>
edamame22 0:29983394c6b6 21 #include "mbed-trace/mbed_trace.h"
edamame22 0:29983394c6b6 22 #include "mbedtls/entropy_poll.h"
edamame22 0:29983394c6b6 23
edamame22 0:29983394c6b6 24 #include <events/mbed_events.h>
edamame22 0:29983394c6b6 25 #include <mbed.h>
edamame22 0:29983394c6b6 26 #include "ble/BLE.h"
edamame22 0:29983394c6b6 27 #include "ble/DiscoveredCharacteristic.h"
edamame22 0:29983394c6b6 28 #include "ble/DiscoveredService.h"
edamame22 0:29983394c6b6 29
edamame22 0:29983394c6b6 30 #include "security.h"
edamame22 0:29983394c6b6 31
Ren Boting 2:b894b3508057 32 //#include "mbed.h"
edamame22 0:29983394c6b6 33 #include "rtos.h"
edamame22 0:29983394c6b6 34
edamame22 0:29983394c6b6 35 #if MBED_CONF_APP_NETWORK_INTERFACE == WIFI
edamame22 0:29983394c6b6 36 #include "ESP8266Interface.h"
edamame22 0:29983394c6b6 37 ESP8266Interface esp(MBED_CONF_APP_WIFI_TX, MBED_CONF_APP_WIFI_RX);
edamame22 0:29983394c6b6 38 #elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET
edamame22 0:29983394c6b6 39 #include "EthernetInterface.h"
edamame22 0:29983394c6b6 40 EthernetInterface eth;
edamame22 0:29983394c6b6 41 #elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_LOWPAN_ND
edamame22 0:29983394c6b6 42 #define MESH
edamame22 0:29983394c6b6 43 #include "NanostackInterface.h"
edamame22 0:29983394c6b6 44 LoWPANNDInterface mesh;
edamame22 0:29983394c6b6 45 #elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_THREAD
edamame22 0:29983394c6b6 46 #define MESH
edamame22 0:29983394c6b6 47 #include "NanostackInterface.h"
edamame22 0:29983394c6b6 48 ThreadInterface mesh;
edamame22 0:29983394c6b6 49 #endif
edamame22 0:29983394c6b6 50
edamame22 0:29983394c6b6 51 #if defined(MESH)
edamame22 0:29983394c6b6 52 #if MBED_CONF_APP_MESH_RADIO_TYPE == ATMEL
edamame22 0:29983394c6b6 53 #include "NanostackRfPhyAtmel.h"
edamame22 0:29983394c6b6 54 NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS,
edamame22 0:29983394c6b6 55 ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL);
edamame22 0:29983394c6b6 56 #elif MBED_CONF_APP_MESH_RADIO_TYPE == MCR20
edamame22 0:29983394c6b6 57 #include "NanostackRfPhyMcr20a.h"
edamame22 0:29983394c6b6 58 NanostackRfPhyMcr20a rf_phy(MCR20A_SPI_MOSI, MCR20A_SPI_MISO, MCR20A_SPI_SCLK, MCR20A_SPI_CS, MCR20A_SPI_RST, MCR20A_SPI_IRQ);
edamame22 0:29983394c6b6 59 #endif //MBED_CONF_APP_RADIO_TYPE
edamame22 0:29983394c6b6 60 #endif //MESH
edamame22 0:29983394c6b6 61
edamame22 0:29983394c6b6 62 #ifndef MESH
edamame22 0:29983394c6b6 63 // This is address to mbed Device Connector
edamame22 0:29983394c6b6 64 #define MBED_SERVER_ADDRESS "coap://api.connector.mbed.com:5684"
edamame22 0:29983394c6b6 65 #else
edamame22 0:29983394c6b6 66 // This is address to mbed Device Connector
edamame22 0:29983394c6b6 67 #define MBED_SERVER_ADDRESS "coaps://[2607:f0d0:2601:52::20]:5684"
edamame22 0:29983394c6b6 68 #endif
edamame22 0:29983394c6b6 69
edamame22 0:29983394c6b6 70 Serial output(USBTX, USBRX);
edamame22 0:29983394c6b6 71
edamame22 0:29983394c6b6 72 // Status indication
edamame22 0:29983394c6b6 73 DigitalOut red_led(LED1);
edamame22 0:29983394c6b6 74 DigitalOut green_led(LED2);
edamame22 0:29983394c6b6 75 DigitalOut blue_led(LED3);
edamame22 0:29983394c6b6 76 Ticker status_ticker;
edamame22 0:29983394c6b6 77 // Ren, begin
edamame22 0:29983394c6b6 78 enum charType {
Ren Boting 2:b894b3508057 79 PRESSURE,
Ren Boting 2:b894b3508057 80 TEMPERATURE,
Ren Boting 2:b894b3508057 81 HUMIDITY
edamame22 0:29983394c6b6 82 };
edamame22 0:29983394c6b6 83 const char * dbg_CharType[HUMIDITY+1]={"Pressure","Temperature","Humidity"};
edamame22 0:29983394c6b6 84 const char * objName[HUMIDITY+1]={"3323","3303","3304"};
edamame22 0:29983394c6b6 85 static bool is_active[HUMIDITY+1];
edamame22 0:29983394c6b6 86 static float dataprint[HUMIDITY+1]={0,0,0};
edamame22 0:29983394c6b6 87 /*
edamame22 0:29983394c6b6 88 * The BME280 sensor contains 3 float properties.
edamame22 0:29983394c6b6 89 * Those are updated once BLE Gatt client read the values.
edamame22 0:29983394c6b6 90 */
edamame22 0:29983394c6b6 91 class BME280Resource {
edamame22 0:29983394c6b6 92 public:
edamame22 0:29983394c6b6 93 BME280Resource() {
Ren Boting 2:b894b3508057 94 // create Pressure object '3323'.
edamame22 0:29983394c6b6 95 for(int m=0; m<HUMIDITY+1; m++) {
Ren Boting 2:b894b3508057 96 M2MObjectInstance* tmp_inst;
edamame22 0:29983394c6b6 97 bme280[m] = M2MInterfaceFactory::create_object(objName[m]);
Ren Boting 2:b894b3508057 98 tmp_inst = bme280[m] ->create_object_instance();
Ren Boting 2:b894b3508057 99 tmp_res[m] = tmp_inst->create_dynamic_resource("5700", dbg_CharType[m],
edamame22 0:29983394c6b6 100 M2MResourceInstance::STRING, true /* observable */);
edamame22 0:29983394c6b6 101 tmp_res[m]->set_operation(M2MBase::GET_ALLOWED);
edamame22 0:29983394c6b6 102 tmp_res[m]->set_value((uint8_t*)"0.0", 3);
edamame22 0:29983394c6b6 103 }
edamame22 0:29983394c6b6 104 }
edamame22 0:29983394c6b6 105
edamame22 0:29983394c6b6 106 void set_bme280_value(float val, int h){
edamame22 0:29983394c6b6 107 char tmp_buf[50];
edamame22 0:29983394c6b6 108 int len;
edamame22 0:29983394c6b6 109 if (h<PRESSURE || h>HUMIDITY) {
edamame22 0:29983394c6b6 110 printf("data type h (input) is wrong!!");
edamame22 0:29983394c6b6 111 return;
edamame22 0:29983394c6b6 112 }
edamame22 0:29983394c6b6 113 if (h==HUMIDITY)
edamame22 0:29983394c6b6 114 len=sprintf(tmp_buf,"%0.2f%%",val);
edamame22 0:29983394c6b6 115 else if (h==PRESSURE)
edamame22 0:29983394c6b6 116 len=sprintf(tmp_buf,"%0.1f hPa",val);
edamame22 0:29983394c6b6 117 else
edamame22 0:29983394c6b6 118 len=sprintf(tmp_buf,"%0.2f degC",val);
edamame22 0:29983394c6b6 119
edamame22 0:29983394c6b6 120 tmp_res[h]->set_value((uint8_t*)tmp_buf, len);
edamame22 0:29983394c6b6 121 //printf("set_value(tmp_bug=%s\r\n", tmp_buf);
edamame22 0:29983394c6b6 122 }
edamame22 0:29983394c6b6 123
edamame22 0:29983394c6b6 124
edamame22 0:29983394c6b6 125 M2MObject* get_object(int idx) {
edamame22 0:29983394c6b6 126 if (idx<PRESSURE || idx>HUMIDITY) return NULL;
edamame22 0:29983394c6b6 127 return bme280[idx];
edamame22 0:29983394c6b6 128 }
edamame22 0:29983394c6b6 129 private:
edamame22 0:29983394c6b6 130 M2MObject* bme280[HUMIDITY+1];
Ren Boting 2:b894b3508057 131 // M2MObjectInstance* tmp_inst[HUMIDITY+1];
edamame22 0:29983394c6b6 132 M2MResource* tmp_res[HUMIDITY+1];
edamame22 0:29983394c6b6 133 };
edamame22 0:29983394c6b6 134
edamame22 0:29983394c6b6 135 static BME280Resource *demo1;
Ren Boting 2:b894b3508057 136 // end of BME280 resource definition
Ren Boting 2:b894b3508057 137
edamame22 0:29983394c6b6 138
edamame22 0:29983394c6b6 139 /************************************************************BLE Stuff from here *********************************/
edamame22 0:29983394c6b6 140 BLE &ble = BLE::Instance();
edamame22 0:29983394c6b6 141 static DiscoveredCharacteristic bme280Characteristic[HUMIDITY+1];
edamame22 0:29983394c6b6 142 static bool triggerLedCharacteristic;
edamame22 0:29983394c6b6 143 static const char PEER_NAME[] = "BME280";
edamame22 1:8950e6a891df 144
edamame22 0:29983394c6b6 145
edamame22 0:29983394c6b6 146 static EventQueue eventQueue(
edamame22 0:29983394c6b6 147 /* event count */ 16 * /* event size */ 32
edamame22 0:29983394c6b6 148 );
edamame22 0:29983394c6b6 149
edamame22 0:29983394c6b6 150 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
edamame22 0:29983394c6b6 151 // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME
edamame22 0:29983394c6b6 152 // The advertising payload is a collection of key/value records where
edamame22 0:29983394c6b6 153 // byte 0: length of the record excluding this byte
edamame22 0:29983394c6b6 154 // byte 1: The key, it is the type of the data
edamame22 0:29983394c6b6 155 // byte [2..N] The value. N is equal to byte0 - 1
edamame22 0:29983394c6b6 156
Ren Boting 2:b894b3508057 157 //printf("Starting advertisementCallback...\r\n");
edamame22 0:29983394c6b6 158 for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
edamame22 0:29983394c6b6 159
edamame22 0:29983394c6b6 160 const uint8_t record_length = params->advertisingData[i];
edamame22 0:29983394c6b6 161 if (record_length == 0) {
edamame22 0:29983394c6b6 162 continue;
edamame22 0:29983394c6b6 163 }
edamame22 0:29983394c6b6 164 const uint8_t type = params->advertisingData[i + 1];
edamame22 0:29983394c6b6 165 const uint8_t* value = params->advertisingData + i + 2;
edamame22 0:29983394c6b6 166 const uint8_t value_length = record_length - 1;
edamame22 0:29983394c6b6 167
edamame22 0:29983394c6b6 168 if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
edamame22 0:29983394c6b6 169 if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) {
edamame22 0:29983394c6b6 170 printf(
edamame22 0:29983394c6b6 171 "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
edamame22 0:29983394c6b6 172 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
edamame22 0:29983394c6b6 173 params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
edamame22 0:29983394c6b6 174 );
edamame22 0:29983394c6b6 175 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
edamame22 0:29983394c6b6 176 break;
edamame22 0:29983394c6b6 177 }
edamame22 0:29983394c6b6 178 }
edamame22 0:29983394c6b6 179 i += record_length;
edamame22 0:29983394c6b6 180 }
edamame22 0:29983394c6b6 181 }
edamame22 0:29983394c6b6 182
edamame22 0:29983394c6b6 183 void serviceDiscoveryCallback(const DiscoveredService *service) {
edamame22 0:29983394c6b6 184 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
edamame22 0:29983394c6b6 185 printf("S type short UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
edamame22 0:29983394c6b6 186 } else {
edamame22 0:29983394c6b6 187 printf("S type long UUID-");
edamame22 0:29983394c6b6 188 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
edamame22 0:29983394c6b6 189 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
edamame22 0:29983394c6b6 190 printf("%02x", longUUIDBytes[i]);
edamame22 0:29983394c6b6 191 }
edamame22 0:29983394c6b6 192 printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
edamame22 0:29983394c6b6 193 }
edamame22 0:29983394c6b6 194 }
edamame22 0:29983394c6b6 195
edamame22 0:29983394c6b6 196 /***
edamame22 0:29983394c6b6 197 This function called read() initially, following read() calls
edamame22 0:29983394c6b6 198 are repeated inside triggerRead function
edamame22 0:29983394c6b6 199 ***/
edamame22 0:29983394c6b6 200 void updateLedCharacteristic(void) {
edamame22 0:29983394c6b6 201 if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
edamame22 0:29983394c6b6 202 //printf("02 updateLedCharacteristic\n");
edamame22 0:29983394c6b6 203 for(int g=0; g<HUMIDITY+1; g++) {
edamame22 0:29983394c6b6 204 if (is_active[g]) bme280Characteristic[g].read();
edamame22 0:29983394c6b6 205 }
edamame22 0:29983394c6b6 206 }
edamame22 0:29983394c6b6 207 }
edamame22 0:29983394c6b6 208
edamame22 0:29983394c6b6 209
edamame22 0:29983394c6b6 210 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
edamame22 0:29983394c6b6 211 int tmp_uuid;
edamame22 0:29983394c6b6 212 tmp_uuid=characteristicP->getUUID().getShortUUID();
edamame22 0:29983394c6b6 213 printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
edamame22 0:29983394c6b6 214 if ((tmp_uuid < GattCharacteristic::UUID_PRESSURE_CHAR) ||
edamame22 0:29983394c6b6 215 (tmp_uuid > GattCharacteristic::UUID_HUMIDITY_CHAR)) return;
edamame22 0:29983394c6b6 216 triggerLedCharacteristic = true;
edamame22 0:29983394c6b6 217 if (tmp_uuid == GattCharacteristic::UUID_PRESSURE_CHAR) {
edamame22 0:29983394c6b6 218 bme280Characteristic[PRESSURE] = *characteristicP; is_active[PRESSURE] = true;
edamame22 0:29983394c6b6 219 printf(" is_active[PRESSURE] = true\r\n");
edamame22 0:29983394c6b6 220 }
edamame22 0:29983394c6b6 221 else if (tmp_uuid == GattCharacteristic::UUID_TEMPERATURE_CHAR) {
Ren Boting 2:b894b3508057 222 bme280Characteristic[TEMPERATURE] = *characteristicP; is_active[TEMPERATURE] = true;
Ren Boting 2:b894b3508057 223 printf(" is_active[TEMPERATURE] = true\r\n");
edamame22 0:29983394c6b6 224 } else {
edamame22 0:29983394c6b6 225 bme280Characteristic[HUMIDITY] = *characteristicP; is_active[HUMIDITY] = true;
edamame22 0:29983394c6b6 226 printf(" is_active[HUMIDITY] = true\r\n");
edamame22 0:29983394c6b6 227 }
edamame22 0:29983394c6b6 228 }
edamame22 0:29983394c6b6 229
edamame22 0:29983394c6b6 230 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
edamame22 0:29983394c6b6 231 printf("terminated SD for handle %u\r\n", connectionHandle);
edamame22 0:29983394c6b6 232 if (triggerLedCharacteristic) {
edamame22 0:29983394c6b6 233 triggerLedCharacteristic = false;
edamame22 0:29983394c6b6 234 eventQueue.call(updateLedCharacteristic);
edamame22 0:29983394c6b6 235 }
edamame22 0:29983394c6b6 236 }
edamame22 0:29983394c6b6 237
edamame22 0:29983394c6b6 238 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
edamame22 0:29983394c6b6 239 int ret;
edamame22 0:29983394c6b6 240 printf("Connected to BME280 now...\r\n");
edamame22 0:29983394c6b6 241 if (params->role == Gap::CENTRAL) {
edamame22 0:29983394c6b6 242 BLE &ble = BLE::Instance();
edamame22 0:29983394c6b6 243 ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
edamame22 0:29983394c6b6 244 // Ren, connect to ENVIRONMENT service
edamame22 0:29983394c6b6 245 ret=ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, GattService::UUID_ENVIRONMENTAL_SERVICE);
edamame22 0:29983394c6b6 246 printf("ble.gattClient().launchServiceDiscovery = %d\r\n", ret);
edamame22 0:29983394c6b6 247 }
edamame22 0:29983394c6b6 248 }
edamame22 0:29983394c6b6 249
edamame22 0:29983394c6b6 250 //ASHOK's triggerRead function
edamame22 0:29983394c6b6 251
edamame22 0:29983394c6b6 252 void triggerRead(const GattReadCallbackParams *response) {
edamame22 1:8950e6a891df 253 int k=0;
edamame22 1:8950e6a891df 254 uint8_t dataforClient[4] = {0,0,0,0};
edamame22 1:8950e6a891df 255 uint32_t final_dataforClient = 0;
edamame22 0:29983394c6b6 256 for(int j=0; j<HUMIDITY+1; j++) {
edamame22 0:29983394c6b6 257 if (is_active[j]) {
edamame22 0:29983394c6b6 258 if (response->handle == bme280Characteristic[j].getValueHandle()){
edamame22 1:8950e6a891df 259 if ( response-> len > 4) {
edamame22 1:8950e6a891df 260 printf("response-> len is wrong :%d, %s, skipping read", response-> len, dbg_CharType[j]);
edamame22 1:8950e6a891df 261 break;
edamame22 1:8950e6a891df 262 }
edamame22 0:29983394c6b6 263 for(int i=0; i< response-> len; i++) {
edamame22 0:29983394c6b6 264 dataforClient[i] = response -> data[i];
edamame22 0:29983394c6b6 265 }
edamame22 1:8950e6a891df 266 printf("%d B, ", response->len);
edamame22 0:29983394c6b6 267 //BLE packet contains 4 bytes of 8 bit int's each. Combine all of them to form a single 32-bit int.
edamame22 0:29983394c6b6 268 final_dataforClient = ((uint32_t)dataforClient[3]<<24) | (dataforClient[2]<<16) | (dataforClient[1] << 8) | (dataforClient[0]);
edamame22 0:29983394c6b6 269 //Ren debug
edamame22 0:29983394c6b6 270 dataprint[j] = ( j==PRESSURE)? (float) final_dataforClient/10 : (float) final_dataforClient/100;
edamame22 0:29983394c6b6 271 demo1->set_bme280_value(dataprint[j], j);
edamame22 0:29983394c6b6 272 if (j==HUMIDITY) {
edamame22 0:29983394c6b6 273 k=0; printf("%s = %0.2f%% ", dbg_CharType[j], dataprint[j]);
edamame22 0:29983394c6b6 274 } else
edamame22 0:29983394c6b6 275 {
edamame22 0:29983394c6b6 276 k=j+1;
edamame22 0:29983394c6b6 277 if(j==PRESSURE) printf("%s = %0.1f hPa ", dbg_CharType[j], dataprint[j]);
edamame22 0:29983394c6b6 278 else printf("%s = %0.2f degC ", dbg_CharType[j], dataprint[j]);
edamame22 0:29983394c6b6 279 }
edamame22 0:29983394c6b6 280 break;
edamame22 0:29983394c6b6 281 }
edamame22 0:29983394c6b6 282 }
edamame22 0:29983394c6b6 283 }
edamame22 0:29983394c6b6 284 printf("\r\n");
edamame22 0:29983394c6b6 285 bme280Characteristic[k].read();
edamame22 0:29983394c6b6 286 }
edamame22 0:29983394c6b6 287
edamame22 0:29983394c6b6 288 // BLE disconnected
edamame22 0:29983394c6b6 289 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) {
edamame22 0:29983394c6b6 290 printf("BLE disconnected\r\n");
edamame22 0:29983394c6b6 291 /* Start scanning and try to connect again */
edamame22 0:29983394c6b6 292 BLE::Instance().gap().startScan(advertisementCallback);
edamame22 0:29983394c6b6 293 }
edamame22 0:29983394c6b6 294
edamame22 0:29983394c6b6 295 void onBleInitError(BLE &ble, ble_error_t error)
edamame22 0:29983394c6b6 296 {
edamame22 0:29983394c6b6 297 /* Initialization error handling should go here */
edamame22 0:29983394c6b6 298 printf("BLE Error = %u\r\n", error);
edamame22 0:29983394c6b6 299 }
edamame22 0:29983394c6b6 300
edamame22 0:29983394c6b6 301 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
edamame22 0:29983394c6b6 302 {
edamame22 0:29983394c6b6 303 printf("I'm inside BLE init Complete\r\n");
edamame22 0:29983394c6b6 304 BLE& ble = params->ble;
edamame22 0:29983394c6b6 305 ble_error_t error = params->error;
edamame22 0:29983394c6b6 306
edamame22 0:29983394c6b6 307 if (error != BLE_ERROR_NONE) {
edamame22 0:29983394c6b6 308 /* In case of error, forward the error handling to onBleInitError */
edamame22 0:29983394c6b6 309 onBleInitError(ble, error);
edamame22 0:29983394c6b6 310 return;
edamame22 0:29983394c6b6 311 }
edamame22 0:29983394c6b6 312
edamame22 0:29983394c6b6 313 /* Ensure that it is the default instance of BLE */
edamame22 0:29983394c6b6 314 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
edamame22 0:29983394c6b6 315 printf("Not the default instance\r\n");
edamame22 0:29983394c6b6 316 return;
edamame22 0:29983394c6b6 317 }
edamame22 0:29983394c6b6 318
edamame22 0:29983394c6b6 319 // Ren, clear discovered Characteristic at beginning
edamame22 0:29983394c6b6 320 for(int i=0; i<HUMIDITY+1; i++) {
Ren Boting 2:b894b3508057 321 dataprint[i]=0.0; is_active[i]=false;
edamame22 0:29983394c6b6 322 }
edamame22 0:29983394c6b6 323
edamame22 0:29983394c6b6 324 ble.gap().onDisconnection(disconnectionCallback);
edamame22 0:29983394c6b6 325 ble.gap().onConnection(connectionCallback);
edamame22 0:29983394c6b6 326
edamame22 0:29983394c6b6 327 // On reading data, call triggerRead function.
edamame22 0:29983394c6b6 328 ble.gattClient().onDataRead(triggerRead);
edamame22 0:29983394c6b6 329
edamame22 0:29983394c6b6 330 // scan interval: 400ms and scan window: 400ms.
edamame22 0:29983394c6b6 331 // Every 400ms the device will scan for 400ms
edamame22 0:29983394c6b6 332 // This means that the device will scan continuously.
edamame22 0:29983394c6b6 333 ble.gap().setScanParams(400, 400);
edamame22 0:29983394c6b6 334 error = ble.gap().startScan(advertisementCallback);
edamame22 0:29983394c6b6 335 printf("BLE Error startScan = %u\r\n", error);
edamame22 0:29983394c6b6 336
edamame22 0:29983394c6b6 337 }
edamame22 0:29983394c6b6 338
edamame22 0:29983394c6b6 339 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
edamame22 0:29983394c6b6 340 BLE &ble = BLE::Instance();
edamame22 0:29983394c6b6 341 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
edamame22 0:29983394c6b6 342 }
edamame22 0:29983394c6b6 343
edamame22 0:29983394c6b6 344 /************************************************************BLE Stuff to here *********************************/
edamame22 0:29983394c6b6 345
edamame22 0:29983394c6b6 346 void blinky() {
edamame22 0:29983394c6b6 347 green_led = !green_led;
edamame22 0:29983394c6b6 348 }
edamame22 0:29983394c6b6 349
edamame22 0:29983394c6b6 350 // These are example resource values for the Device Object
edamame22 0:29983394c6b6 351 struct MbedClientDevice device = {
edamame22 0:29983394c6b6 352 "Manufacturer_String", // Manufacturer
edamame22 0:29983394c6b6 353 "Type_String", // Type
edamame22 0:29983394c6b6 354 "ModelNumber_String", // ModelNumber
edamame22 0:29983394c6b6 355 "SerialNumber_String" // SerialNumber
edamame22 0:29983394c6b6 356 };
edamame22 0:29983394c6b6 357
edamame22 0:29983394c6b6 358 // Instantiate the class which implements LWM2M Client API (from simpleclient.h)
edamame22 0:29983394c6b6 359 MbedClient mbed_client(device);
edamame22 0:29983394c6b6 360
edamame22 0:29983394c6b6 361 // Network interaction must be performed outside of interrupt context
edamame22 0:29983394c6b6 362 Semaphore updates(0);
edamame22 0:29983394c6b6 363 volatile bool registered = false;
edamame22 0:29983394c6b6 364 volatile bool clicked = false;
edamame22 0:29983394c6b6 365 osThreadId mainThread;
edamame22 0:29983394c6b6 366
Ren Boting 2:b894b3508057 367
edamame22 0:29983394c6b6 368 #ifdef TARGET_K64F
edamame22 0:29983394c6b6 369 // Set up Hardware interrupt button.
edamame22 0:29983394c6b6 370 InterruptIn obs_button(SW2);
edamame22 0:29983394c6b6 371 InterruptIn unreg_button(SW3);
edamame22 0:29983394c6b6 372 #else
edamame22 0:29983394c6b6 373 //In non K64F boards , set up a timer to simulate updating resource,
edamame22 0:29983394c6b6 374 // there is no functionality to unregister.
edamame22 0:29983394c6b6 375 Ticker timer;
edamame22 0:29983394c6b6 376 #endif
edamame22 0:29983394c6b6 377
edamame22 0:29983394c6b6 378 /*
edamame22 0:29983394c6b6 379 * The button contains one property (click count).
edamame22 0:29983394c6b6 380 * When `handle_button_click` is executed, the counter updates.
edamame22 0:29983394c6b6 381 */
edamame22 0:29983394c6b6 382 class ButtonResource {
edamame22 0:29983394c6b6 383 public:
edamame22 0:29983394c6b6 384 ButtonResource(): counter(0) {
edamame22 0:29983394c6b6 385 // create ObjectID with metadata tag of 'BTN_SW2', which is 'digital input'
edamame22 0:29983394c6b6 386 btn_object = M2MInterfaceFactory::create_object("BTN_SW2");
edamame22 0:29983394c6b6 387 M2MObjectInstance* btn_inst = btn_object->create_object_instance();
edamame22 0:29983394c6b6 388 // create resource with ID '5501', which is digital input counter
edamame22 0:29983394c6b6 389 M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button",
edamame22 0:29983394c6b6 390 M2MResourceInstance::INTEGER, true /* observable */);
edamame22 0:29983394c6b6 391 // we can read this value
edamame22 0:29983394c6b6 392 btn_res->set_operation(M2MBase::GET_ALLOWED);
edamame22 0:29983394c6b6 393 // set initial value (all values in mbed Client are buffers)
edamame22 0:29983394c6b6 394 // to be able to read this data easily in the Connector console, we'll use a string
edamame22 0:29983394c6b6 395 btn_res->set_value((uint8_t*)"0", 1);
edamame22 0:29983394c6b6 396 }
edamame22 0:29983394c6b6 397
edamame22 0:29983394c6b6 398 ~ButtonResource() {
edamame22 0:29983394c6b6 399 }
edamame22 0:29983394c6b6 400
edamame22 0:29983394c6b6 401 M2MObject* get_object() {
edamame22 0:29983394c6b6 402 return btn_object;
edamame22 0:29983394c6b6 403 }
edamame22 0:29983394c6b6 404
edamame22 0:29983394c6b6 405 /*
edamame22 0:29983394c6b6 406 * When you press the button, we read the current value of the click counter
edamame22 0:29983394c6b6 407 * from mbed Device Connector, then up the value with one.
edamame22 0:29983394c6b6 408 */
edamame22 0:29983394c6b6 409 void handle_button_click() {
edamame22 0:29983394c6b6 410 M2MObjectInstance* inst = btn_object->object_instance();
edamame22 0:29983394c6b6 411 M2MResource* res = inst->resource("5501");
edamame22 0:29983394c6b6 412
edamame22 0:29983394c6b6 413 // up counter
edamame22 0:29983394c6b6 414 counter++;
edamame22 0:29983394c6b6 415 printf("handle_button_click, new value of counter is %d\r\n", counter);
edamame22 0:29983394c6b6 416 // serialize the value of counter as a string, and tell connector
edamame22 0:29983394c6b6 417 char buffer[20];
edamame22 0:29983394c6b6 418 int size = sprintf(buffer,"%d",counter);
edamame22 0:29983394c6b6 419 res->set_value((uint8_t*)buffer, size);
edamame22 0:29983394c6b6 420 }
edamame22 0:29983394c6b6 421
edamame22 0:29983394c6b6 422 private:
edamame22 0:29983394c6b6 423 M2MObject* btn_object;
edamame22 0:29983394c6b6 424 uint16_t counter;
edamame22 0:29983394c6b6 425 };
edamame22 0:29983394c6b6 426
edamame22 0:29983394c6b6 427
edamame22 0:29983394c6b6 428 void unregister() {
edamame22 0:29983394c6b6 429 registered = false;
edamame22 0:29983394c6b6 430 updates.release();
edamame22 0:29983394c6b6 431 }
edamame22 0:29983394c6b6 432
edamame22 0:29983394c6b6 433 void button_clicked() {
edamame22 0:29983394c6b6 434 clicked = true;
edamame22 0:29983394c6b6 435 updates.release();
edamame22 0:29983394c6b6 436 }
edamame22 0:29983394c6b6 437
edamame22 0:29983394c6b6 438 // debug printf function
edamame22 0:29983394c6b6 439 void trace_printer(const char* str) {
edamame22 0:29983394c6b6 440 printf("%s\r\n", str);
edamame22 0:29983394c6b6 441 }
edamame22 0:29983394c6b6 442
edamame22 0:29983394c6b6 443 /****************************************************************More BLE Stuff from here****************/
edamame22 0:29983394c6b6 444 //BLE thread init and further calls to other BLE methods.
edamame22 0:29983394c6b6 445 void BLE_thread_init(void){
edamame22 0:29983394c6b6 446 printf("I'm inside BLE thread_init.....\r\n");
edamame22 0:29983394c6b6 447 eventQueue.call_every(500, blinky);
edamame22 0:29983394c6b6 448 //Schedule events before starting the thread since there might be some missed events while scanning / pairing.
edamame22 0:29983394c6b6 449 ble.onEventsToProcess(scheduleBleEventsProcessing);
edamame22 0:29983394c6b6 450 ble.init(bleInitComplete);
edamame22 0:29983394c6b6 451 //Loop forever the BLE thread
edamame22 0:29983394c6b6 452 eventQueue.dispatch_forever();
edamame22 0:29983394c6b6 453 }
edamame22 0:29983394c6b6 454
edamame22 0:29983394c6b6 455 /****************************************************************More BLE Stuff to here****************/
edamame22 0:29983394c6b6 456
edamame22 0:29983394c6b6 457 // Entry point to the program
edamame22 0:29983394c6b6 458 int main() {
edamame22 0:29983394c6b6 459
edamame22 0:29983394c6b6 460 unsigned int seed;
edamame22 0:29983394c6b6 461 size_t len;
edamame22 0:29983394c6b6 462
edamame22 0:29983394c6b6 463 //Create a new thread for BLE
edamame22 0:29983394c6b6 464 Thread BLE_thread;
edamame22 0:29983394c6b6 465
edamame22 0:29983394c6b6 466
edamame22 0:29983394c6b6 467 #ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
edamame22 0:29983394c6b6 468 // Used to randomize source port
edamame22 0:29983394c6b6 469 mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len);
edamame22 0:29983394c6b6 470
edamame22 0:29983394c6b6 471 #elif defined MBEDTLS_TEST_NULL_ENTROPY
edamame22 0:29983394c6b6 472
edamame22 0:29983394c6b6 473 #warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware."
edamame22 0:29983394c6b6 474 // Used to randomize source port
edamame22 0:29983394c6b6 475 mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len);
edamame22 0:29983394c6b6 476
edamame22 0:29983394c6b6 477 #else
edamame22 0:29983394c6b6 478
edamame22 0:29983394c6b6 479 #error "This hardware does not have entropy, endpoint will not register to Connector.\
edamame22 0:29983394c6b6 480 You need to enable NULL ENTROPY for your application, but if this configuration change is made then no security is offered by mbed TLS.\
edamame22 0:29983394c6b6 481 Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint."
edamame22 0:29983394c6b6 482
edamame22 0:29983394c6b6 483 #endif
edamame22 0:29983394c6b6 484
edamame22 0:29983394c6b6 485 srand(seed);
edamame22 0:29983394c6b6 486 red_led = 1;
edamame22 0:29983394c6b6 487 blue_led = 1;
edamame22 0:29983394c6b6 488 status_ticker.attach_us(blinky, 250000);
edamame22 0:29983394c6b6 489 // Keep track of the main thread
edamame22 0:29983394c6b6 490 mainThread = osThreadGetId();
edamame22 0:29983394c6b6 491
edamame22 0:29983394c6b6 492 // Sets the console baud-rate
edamame22 0:29983394c6b6 493 output.baud(9600);
edamame22 0:29983394c6b6 494
edamame22 0:29983394c6b6 495 output.printf("Starting mbed Client example...\r\n");
edamame22 0:29983394c6b6 496
edamame22 0:29983394c6b6 497 mbed_trace_init();
edamame22 0:29983394c6b6 498 mbed_trace_print_function_set(trace_printer);
edamame22 0:29983394c6b6 499 NetworkInterface *network_interface = 0;
edamame22 0:29983394c6b6 500 int connect_success = -1;
edamame22 0:29983394c6b6 501 #if MBED_CONF_APP_NETWORK_INTERFACE == WIFI
edamame22 0:29983394c6b6 502 output.printf("\n\rUsing WiFi \r\n");
edamame22 0:29983394c6b6 503 output.printf("\n\rConnecting to WiFi..\r\n");
edamame22 0:29983394c6b6 504 connect_success = esp.connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD);
edamame22 0:29983394c6b6 505 network_interface = &esp;
edamame22 0:29983394c6b6 506 #elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET
edamame22 0:29983394c6b6 507 output.printf("Using Ethernet\r\n");
edamame22 0:29983394c6b6 508 connect_success = eth.connect();
edamame22 0:29983394c6b6 509 network_interface = &eth;
edamame22 0:29983394c6b6 510 #endif
edamame22 0:29983394c6b6 511 #ifdef MESH
edamame22 0:29983394c6b6 512 output.printf("Using Mesh\r\n");
edamame22 0:29983394c6b6 513 output.printf("\n\rConnecting to Mesh..\r\n");
edamame22 0:29983394c6b6 514 mesh.initialize(&rf_phy);
edamame22 0:29983394c6b6 515 connect_success = mesh.connect();
edamame22 0:29983394c6b6 516 network_interface = &mesh;
edamame22 0:29983394c6b6 517 #endif
edamame22 0:29983394c6b6 518 if(connect_success == 0) {
edamame22 0:29983394c6b6 519 output.printf("\n\rConnected to Network successfully\r\n");
edamame22 0:29983394c6b6 520 } else {
edamame22 0:29983394c6b6 521 output.printf("\n\rConnection to Network Failed %d! Exiting application....\r\n", connect_success);
edamame22 0:29983394c6b6 522 return 0;
edamame22 0:29983394c6b6 523 }
edamame22 0:29983394c6b6 524 const char *ip_addr = network_interface->get_ip_address();
edamame22 0:29983394c6b6 525 if (ip_addr) {
edamame22 0:29983394c6b6 526 output.printf("IP address %s\r\n", ip_addr);
edamame22 0:29983394c6b6 527 } else {
edamame22 0:29983394c6b6 528 output.printf("No IP address\r\n");
edamame22 0:29983394c6b6 529 }
edamame22 0:29983394c6b6 530
edamame22 0:29983394c6b6 531 // create our button resources
edamame22 0:29983394c6b6 532 ButtonResource button_resource;
edamame22 0:29983394c6b6 533 #ifdef TARGET_K64F
edamame22 0:29983394c6b6 534 // On press of SW3 button on K64F board, example application
edamame22 0:29983394c6b6 535 // will call unregister API towards mbed Device Connector
edamame22 0:29983394c6b6 536 //unreg_button.fall(&mbed_client,&MbedClient::test_unregister);
edamame22 0:29983394c6b6 537 unreg_button.fall(&unregister);
edamame22 0:29983394c6b6 538
edamame22 0:29983394c6b6 539 // Observation Button (SW2) press will send update of endpoint resource values to connector
edamame22 0:29983394c6b6 540 obs_button.fall(&button_clicked);
edamame22 0:29983394c6b6 541 #else
edamame22 0:29983394c6b6 542 // Send update of endpoint resource values to connector every 5 seconds periodically
edamame22 0:29983394c6b6 543 timer.attach(&button_clicked, 5.0);
edamame22 0:29983394c6b6 544 #endif
edamame22 0:29983394c6b6 545
edamame22 0:29983394c6b6 546 // Create endpoint interface to manage register and unregister
edamame22 0:29983394c6b6 547 mbed_client.create_interface(MBED_SERVER_ADDRESS, network_interface);
edamame22 0:29983394c6b6 548
edamame22 0:29983394c6b6 549 // Create Objects of varying types, see simpleclient.h for more details on implementation.
edamame22 0:29983394c6b6 550 M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info
edamame22 0:29983394c6b6 551 M2MDevice* device_object = mbed_client.create_device_object(); // device resources object
edamame22 0:29983394c6b6 552
edamame22 0:29983394c6b6 553 // Create list of Objects to register
edamame22 0:29983394c6b6 554 M2MObjectList object_list;
edamame22 0:29983394c6b6 555
edamame22 0:29983394c6b6 556 // Add objects to list
edamame22 0:29983394c6b6 557 object_list.push_back(device_object);
edamame22 0:29983394c6b6 558 object_list.push_back(button_resource.get_object());
edamame22 0:29983394c6b6 559 // add bme280 data objects
edamame22 0:29983394c6b6 560 if (demo1==NULL) {
edamame22 0:29983394c6b6 561 // Create bme280 instance
edamame22 0:29983394c6b6 562 demo1=new BME280Resource();
edamame22 0:29983394c6b6 563 printf("created bme280 instance now!!\r\n");
edamame22 0:29983394c6b6 564 }
edamame22 0:29983394c6b6 565 object_list.push_back(demo1->get_object(PRESSURE));
edamame22 0:29983394c6b6 566 object_list.push_back(demo1->get_object(TEMPERATURE));
edamame22 0:29983394c6b6 567 object_list.push_back(demo1->get_object(HUMIDITY));
edamame22 0:29983394c6b6 568
edamame22 0:29983394c6b6 569 // Set endpoint registration object
edamame22 0:29983394c6b6 570 mbed_client.set_register_object(register_object);
edamame22 0:29983394c6b6 571
edamame22 0:29983394c6b6 572 // Register with mbed Device Connector
edamame22 0:29983394c6b6 573 mbed_client.test_register(register_object, object_list);
edamame22 0:29983394c6b6 574 registered = true;
edamame22 0:29983394c6b6 575
edamame22 0:29983394c6b6 576 //Start BLE thread after connection is established to device connector. Else, there is conflict.
edamame22 0:29983394c6b6 577 BLE_thread.start(BLE_thread_init);
edamame22 0:29983394c6b6 578 // waiting for completion of BLE_thread_init
edamame22 0:29983394c6b6 579 Thread::wait(2000);
Ren Boting 2:b894b3508057 580
edamame22 0:29983394c6b6 581 while (true) {
edamame22 0:29983394c6b6 582
Ren Boting 2:b894b3508057 583 printf("inside main for client\r\n");
edamame22 0:29983394c6b6 584 triggerLedCharacteristic = false;
edamame22 0:29983394c6b6 585
edamame22 0:29983394c6b6 586 updates.wait(25000);
edamame22 0:29983394c6b6 587 if(registered) {
edamame22 0:29983394c6b6 588 if(!clicked) {
edamame22 0:29983394c6b6 589 //printf("Inside registered ... clicked \r\n");
edamame22 0:29983394c6b6 590 mbed_client.test_update_register();
edamame22 0:29983394c6b6 591 }
edamame22 0:29983394c6b6 592 } else { // not registered, then stop;
edamame22 0:29983394c6b6 593 break;
edamame22 0:29983394c6b6 594 }
edamame22 0:29983394c6b6 595 if(clicked) {
edamame22 0:29983394c6b6 596 clicked = false;
edamame22 0:29983394c6b6 597 button_resource.handle_button_click();
edamame22 0:29983394c6b6 598 }
edamame22 0:29983394c6b6 599
edamame22 0:29983394c6b6 600 }
edamame22 0:29983394c6b6 601
edamame22 0:29983394c6b6 602 mbed_client.test_unregister();
edamame22 0:29983394c6b6 603 status_ticker.detach();
edamame22 0:29983394c6b6 604 }