SunTracker_BLE_Remote

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 X_NUCLEO_IKS01A1 mbed

Fork of SunTracker_BLE_Remote by ST Expansion SW Team

This application is the BLE Remote Control for the SunTracker demo application that you can find here.
Please refer to that page for further information.

Committer:
apalmieri
Date:
Fri Feb 19 15:32:04 2016 +0000
Revision:
2:c944cfe08e79
Parent:
1:e0f4bcce540c
Child:
3:b2bf47485f85
Sync w/ rev114 of mbed lib

Who changed what in which revision?

UserRevisionLine numberNew contents of line
apalmieri 2:c944cfe08e79 1 #if 0
apalmieri 0:2e972e7d3f64 2 /* mbed Microcontroller Library
apalmieri 0:2e972e7d3f64 3 * Copyright (c) 2006-2013 ARM Limited
apalmieri 0:2e972e7d3f64 4 *
apalmieri 0:2e972e7d3f64 5 * Licensed under the Apache License, Version 2.0 (the "License");
apalmieri 0:2e972e7d3f64 6 * you may not use this file except in compliance with the License.
apalmieri 0:2e972e7d3f64 7 * You may obtain a copy of the License at
apalmieri 0:2e972e7d3f64 8 *
apalmieri 0:2e972e7d3f64 9 * http://www.apache.org/licenses/LICENSE-2.0
apalmieri 0:2e972e7d3f64 10 *
apalmieri 0:2e972e7d3f64 11 * Unless required by applicable law or agreed to in writing, software
apalmieri 0:2e972e7d3f64 12 * distributed under the License is distributed on an "AS IS" BASIS,
apalmieri 0:2e972e7d3f64 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
apalmieri 0:2e972e7d3f64 14 * See the License for the specific language governing permissions and
apalmieri 0:2e972e7d3f64 15 * limitations under the License.
apalmieri 0:2e972e7d3f64 16 */
apalmieri 0:2e972e7d3f64 17
apalmieri 0:2e972e7d3f64 18 #include "mbed.h"
apalmieri 0:2e972e7d3f64 19 #include "ble/BLE.h"
apalmieri 0:2e972e7d3f64 20 #include "ble/DiscoveredCharacteristic.h"
apalmieri 0:2e972e7d3f64 21 #include "ble/DiscoveredService.h"
apalmieri 0:2e972e7d3f64 22
apalmieri 0:2e972e7d3f64 23 #define SCAN_INT 0x30 // 30 ms = 48 * 0.625 ms
apalmieri 0:2e972e7d3f64 24 #define SCAN_WIND 0x30 // 30 ms = 48 * 0.625 ms
apalmieri 0:2e972e7d3f64 25
apalmieri 0:2e972e7d3f64 26
apalmieri 0:2e972e7d3f64 27 const Gap::Address_t BLE_address_BE = {0xCC, 0x00, 0x00, 0xE1, 0x80, 0x02};
apalmieri 0:2e972e7d3f64 28 const Gap::Address_t BLE_peer_address_BE = {0xFD, 0x66, 0x05, 0x13, 0xBE, 0xBA};
apalmieri 0:2e972e7d3f64 29
apalmieri 0:2e972e7d3f64 30 DiscoveredCharacteristic ledCharacteristic;
apalmieri 0:2e972e7d3f64 31
apalmieri 0:2e972e7d3f64 32 uint8_t toggledValue = 0;
apalmieri 0:2e972e7d3f64 33 enum {
apalmieri 0:2e972e7d3f64 34 READ = 0,
apalmieri 0:2e972e7d3f64 35 WRITE,
apalmieri 0:2e972e7d3f64 36 IDLE
apalmieri 0:2e972e7d3f64 37 };
apalmieri 0:2e972e7d3f64 38 static volatile unsigned int triggerOp = IDLE;
apalmieri 0:2e972e7d3f64 39
apalmieri 0:2e972e7d3f64 40 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
apalmieri 0:2e972e7d3f64 41 {
apalmieri 0:2e972e7d3f64 42 (void)params;
apalmieri 0:2e972e7d3f64 43 printf("disconnected\n\r");
apalmieri 0:2e972e7d3f64 44 }
apalmieri 0:2e972e7d3f64 45
apalmieri 0:2e972e7d3f64 46 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
apalmieri 0:2e972e7d3f64 47 if (params->peerAddr[0] != BLE_peer_address_BE[0]) {
apalmieri 0:2e972e7d3f64 48 return;
apalmieri 0:2e972e7d3f64 49 }
apalmieri 0:2e972e7d3f64 50
apalmieri 0:2e972e7d3f64 51 printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
apalmieri 0:2e972e7d3f64 52 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
apalmieri 0:2e972e7d3f64 53 params->rssi, params->isScanResponse, params->type);
apalmieri 0:2e972e7d3f64 54
apalmieri 0:2e972e7d3f64 55 if(!params->isScanResponse) {
apalmieri 0:2e972e7d3f64 56 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_PUBLIC, NULL, NULL);
apalmieri 0:2e972e7d3f64 57 }
apalmieri 0:2e972e7d3f64 58 }
apalmieri 0:2e972e7d3f64 59
apalmieri 0:2e972e7d3f64 60 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
apalmieri 0:2e972e7d3f64 61 printf("terminated SD for handle %u\r\n", connectionHandle);
apalmieri 0:2e972e7d3f64 62 }
apalmieri 0:2e972e7d3f64 63
apalmieri 0:2e972e7d3f64 64 void serviceDiscoveryCallback(const DiscoveredService *service) {
apalmieri 0:2e972e7d3f64 65 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
apalmieri 0:2e972e7d3f64 66 printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
apalmieri 0:2e972e7d3f64 67 } else {
apalmieri 0:2e972e7d3f64 68 printf("S UUID-");
apalmieri 0:2e972e7d3f64 69 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
apalmieri 0:2e972e7d3f64 70 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
apalmieri 0:2e972e7d3f64 71 printf("%02X", longUUIDBytes[i]);
apalmieri 0:2e972e7d3f64 72 }
apalmieri 0:2e972e7d3f64 73 printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
apalmieri 0:2e972e7d3f64 74 }
apalmieri 0:2e972e7d3f64 75 }
apalmieri 0:2e972e7d3f64 76
apalmieri 0:2e972e7d3f64 77 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
apalmieri 0:2e972e7d3f64 78 //printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
apalmieri 0:2e972e7d3f64 79 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
apalmieri 0:2e972e7d3f64 80 //printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
apalmieri 0:2e972e7d3f64 81 ledCharacteristic = *characteristicP;
apalmieri 0:2e972e7d3f64 82 triggerOp = READ;
apalmieri 0:2e972e7d3f64 83 }
apalmieri 0:2e972e7d3f64 84 }
apalmieri 0:2e972e7d3f64 85
apalmieri 0:2e972e7d3f64 86 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
apalmieri 0:2e972e7d3f64 87 uint16_t LED_SERVICE_UUID = 0xA000;
apalmieri 0:2e972e7d3f64 88 uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xA001;
apalmieri 0:2e972e7d3f64 89
apalmieri 0:2e972e7d3f64 90 if (params->role == Gap::CENTRAL) {
apalmieri 0:2e972e7d3f64 91 BLE &ble = BLE::Instance();
apalmieri 0:2e972e7d3f64 92 ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
apalmieri 0:2e972e7d3f64 93 ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, LED_SERVICE_UUID, LED_STATE_CHARACTERISTIC_UUID);
apalmieri 0:2e972e7d3f64 94 }
apalmieri 0:2e972e7d3f64 95 }
apalmieri 0:2e972e7d3f64 96
apalmieri 0:2e972e7d3f64 97 void triggerToggledWrite(const GattReadCallbackParams *response) {
apalmieri 0:2e972e7d3f64 98 if (response->handle == ledCharacteristic.getValueHandle()) {
apalmieri 0:2e972e7d3f64 99 #if 0
apalmieri 0:2e972e7d3f64 100 printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
apalmieri 0:2e972e7d3f64 101 for (unsigned index = 0; index < response->len; index++) {
apalmieri 0:2e972e7d3f64 102 printf("%c[%02x]", response->data[index], response->data[index]);
apalmieri 0:2e972e7d3f64 103 }
apalmieri 0:2e972e7d3f64 104 printf("\r\n");
apalmieri 0:2e972e7d3f64 105 #endif
apalmieri 0:2e972e7d3f64 106
apalmieri 0:2e972e7d3f64 107 toggledValue = response->data[0] ^ 0x1;
apalmieri 0:2e972e7d3f64 108 triggerOp = WRITE;
apalmieri 0:2e972e7d3f64 109 }
apalmieri 0:2e972e7d3f64 110 }
apalmieri 0:2e972e7d3f64 111
apalmieri 0:2e972e7d3f64 112 void triggerRead(const GattWriteCallbackParams *response) {
apalmieri 0:2e972e7d3f64 113 if (response->handle == ledCharacteristic.getValueHandle()) {
apalmieri 0:2e972e7d3f64 114 triggerOp = READ;
apalmieri 0:2e972e7d3f64 115 }
apalmieri 0:2e972e7d3f64 116 }
apalmieri 0:2e972e7d3f64 117
apalmieri 0:2e972e7d3f64 118 /**
apalmieri 0:2e972e7d3f64 119 * This function is called when the ble initialization process has failled
apalmieri 0:2e972e7d3f64 120 */
apalmieri 0:2e972e7d3f64 121 void onBleInitError(BLE &ble, ble_error_t error)
apalmieri 0:2e972e7d3f64 122 {
apalmieri 0:2e972e7d3f64 123 /* Initialization error handling should go here */
apalmieri 0:2e972e7d3f64 124 }
apalmieri 0:2e972e7d3f64 125
apalmieri 0:2e972e7d3f64 126 /**
apalmieri 0:2e972e7d3f64 127 * Callback triggered when the ble initialization process has finished
apalmieri 0:2e972e7d3f64 128 */
apalmieri 0:2e972e7d3f64 129 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
apalmieri 0:2e972e7d3f64 130 {
apalmieri 0:2e972e7d3f64 131 BLE& ble = params->ble;
apalmieri 0:2e972e7d3f64 132 ble_error_t error = params->error;
apalmieri 0:2e972e7d3f64 133
apalmieri 0:2e972e7d3f64 134 if (error != BLE_ERROR_NONE) {
apalmieri 0:2e972e7d3f64 135 /* In case of error, forward the error handling to onBleInitError */
apalmieri 0:2e972e7d3f64 136 onBleInitError(ble, error);
apalmieri 0:2e972e7d3f64 137 return;
apalmieri 0:2e972e7d3f64 138 }
apalmieri 0:2e972e7d3f64 139
apalmieri 0:2e972e7d3f64 140 /* Ensure that it is the default instance of BLE */
apalmieri 0:2e972e7d3f64 141 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
apalmieri 0:2e972e7d3f64 142 return;
apalmieri 0:2e972e7d3f64 143 }
apalmieri 0:2e972e7d3f64 144
apalmieri 0:2e972e7d3f64 145 // Set BT Address
apalmieri 1:e0f4bcce540c 146 ble.gap().setAddress(BLEProtocol::AddressType::PUBLIC, BLE_address_BE);
apalmieri 0:2e972e7d3f64 147
apalmieri 0:2e972e7d3f64 148 ble.gap().onConnection(connectionCallback);
apalmieri 0:2e972e7d3f64 149 ble.onDisconnection(disconnectionCallback);
apalmieri 0:2e972e7d3f64 150
apalmieri 0:2e972e7d3f64 151 ble.gattClient().onDataRead(triggerToggledWrite);
apalmieri 0:2e972e7d3f64 152 ble.gattClient().onDataWrite(triggerRead);
apalmieri 0:2e972e7d3f64 153
apalmieri 0:2e972e7d3f64 154 ble.gap().setScanParams(SCAN_INT, SCAN_WIND);
apalmieri 0:2e972e7d3f64 155 ble.gap().startScan(advertisementCallback);
apalmieri 0:2e972e7d3f64 156
apalmieri 0:2e972e7d3f64 157 // infinite loop
apalmieri 0:2e972e7d3f64 158 while (1) {
apalmieri 0:2e972e7d3f64 159 if (!ble.gattClient().isServiceDiscoveryActive()) {
apalmieri 0:2e972e7d3f64 160 switch(triggerOp) {
apalmieri 0:2e972e7d3f64 161 case READ:
apalmieri 0:2e972e7d3f64 162 triggerOp = IDLE;
apalmieri 0:2e972e7d3f64 163 ledCharacteristic.read();
apalmieri 0:2e972e7d3f64 164 break;
apalmieri 0:2e972e7d3f64 165 case WRITE:
apalmieri 0:2e972e7d3f64 166 triggerOp = IDLE;
apalmieri 0:2e972e7d3f64 167 ledCharacteristic.write(1, &toggledValue);
apalmieri 0:2e972e7d3f64 168 break;
apalmieri 0:2e972e7d3f64 169 }
apalmieri 0:2e972e7d3f64 170 }
apalmieri 0:2e972e7d3f64 171 ble.waitForEvent();
apalmieri 0:2e972e7d3f64 172 }
apalmieri 0:2e972e7d3f64 173 }
apalmieri 0:2e972e7d3f64 174
apalmieri 0:2e972e7d3f64 175 int main(void)
apalmieri 0:2e972e7d3f64 176 {
apalmieri 0:2e972e7d3f64 177 BLE::Instance().init(bleInitComplete);
apalmieri 0:2e972e7d3f64 178 }
apalmieri 0:2e972e7d3f64 179
apalmieri 2:c944cfe08e79 180 #endif
apalmieri 2:c944cfe08e79 181
apalmieri 2:c944cfe08e79 182
apalmieri 2:c944cfe08e79 183
apalmieri 2:c944cfe08e79 184
apalmieri 2:c944cfe08e79 185
apalmieri 2:c944cfe08e79 186 /* mbed Microcontroller Library
apalmieri 2:c944cfe08e79 187 * Copyright (c) 2006-2015 ARM Limited
apalmieri 2:c944cfe08e79 188 *
apalmieri 2:c944cfe08e79 189 * Licensed under the Apache License, Version 2.0 (the "License");
apalmieri 2:c944cfe08e79 190 * you may not use this file except in compliance with the License.
apalmieri 2:c944cfe08e79 191 * You may obtain a copy of the License at
apalmieri 2:c944cfe08e79 192 *
apalmieri 2:c944cfe08e79 193 * http://www.apache.org/licenses/LICENSE-2.0
apalmieri 2:c944cfe08e79 194 *
apalmieri 2:c944cfe08e79 195 * Unless required by applicable law or agreed to in writing, software
apalmieri 2:c944cfe08e79 196 * distributed under the License is distributed on an "AS IS" BASIS,
apalmieri 2:c944cfe08e79 197 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
apalmieri 2:c944cfe08e79 198 * See the License for the specific language governing permissions and
apalmieri 2:c944cfe08e79 199 * limitations under the License.
apalmieri 2:c944cfe08e79 200 */
apalmieri 2:c944cfe08e79 201
apalmieri 2:c944cfe08e79 202 #include "mbed.h"
apalmieri 2:c944cfe08e79 203 #include "ble/Gap.h"
apalmieri 2:c944cfe08e79 204 #include "ble/BLE.h"
apalmieri 2:c944cfe08e79 205 #include "ble/DiscoveredCharacteristic.h"
apalmieri 2:c944cfe08e79 206 #include "ble/DiscoveredService.h"
apalmieri 2:c944cfe08e79 207 #include "ble/GapAdvertisingParams.h"
apalmieri 2:c944cfe08e79 208
apalmieri 2:c944cfe08e79 209
apalmieri 2:c944cfe08e79 210 #define PRINTF(...) printf(__VA_ARGS__)
apalmieri 2:c944cfe08e79 211
apalmieri 2:c944cfe08e79 212 BLE ble;
apalmieri 2:c944cfe08e79 213 DigitalOut led1(LED1);
apalmieri 2:c944cfe08e79 214
apalmieri 2:c944cfe08e79 215
apalmieri 2:c944cfe08e79 216 bool _connected = false;
apalmieri 2:c944cfe08e79 217
apalmieri 2:c944cfe08e79 218 DiscoveredCharacteristic hrmCharacteristic;
apalmieri 2:c944cfe08e79 219 static volatile bool triggerHrmCharacteristic = false;
apalmieri 2:c944cfe08e79 220 //PROTOTYPES
apalmieri 2:c944cfe08e79 221 void PrintScanResult(const Gap::AdvertisementCallbackParams_t *params);
apalmieri 2:c944cfe08e79 222 void periodicCallback(void);
apalmieri 2:c944cfe08e79 223 void connectToDevice(const Gap::Address_t peerAddr);
apalmieri 2:c944cfe08e79 224
apalmieri 2:c944cfe08e79 225 void serviceDiscoveryCallback(const DiscoveredService *service);
apalmieri 2:c944cfe08e79 226 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP);
apalmieri 2:c944cfe08e79 227 void discoveryTerminationCallback(Gap::Handle_t connectionHandle);
apalmieri 2:c944cfe08e79 228
apalmieri 2:c944cfe08e79 229
apalmieri 2:c944cfe08e79 230 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
apalmieri 2:c944cfe08e79 231 _connected = false;
apalmieri 2:c944cfe08e79 232 PRINTF("disconnected\r\n");
apalmieri 2:c944cfe08e79 233 }
apalmieri 2:c944cfe08e79 234
apalmieri 2:c944cfe08e79 235 void periodicCallback(void)
apalmieri 2:c944cfe08e79 236 {
apalmieri 2:c944cfe08e79 237 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
apalmieri 2:c944cfe08e79 238 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
apalmieri 2:c944cfe08e79 239 * heavy-weight sensor polling from the main thread. */
apalmieri 2:c944cfe08e79 240 triggerHrmCharacteristic = true;
apalmieri 2:c944cfe08e79 241 }
apalmieri 2:c944cfe08e79 242
apalmieri 2:c944cfe08e79 243 void PrintScanResult(const Gap::AdvertisementCallbackParams_t *params)
apalmieri 2:c944cfe08e79 244 {
apalmieri 2:c944cfe08e79 245 for(int8_t i = 5; i>=0; i--)
apalmieri 2:c944cfe08e79 246 {
apalmieri 2:c944cfe08e79 247 PRINTF("%02x",params->peerAddr[i] );
apalmieri 2:c944cfe08e79 248 if(i != 0)PRINTF("-");
apalmieri 2:c944cfe08e79 249 }
apalmieri 2:c944cfe08e79 250 PRINTF("\r\n");
apalmieri 2:c944cfe08e79 251
apalmieri 2:c944cfe08e79 252 PRINTF("RSSI: %d\r\n",params->rssi );
apalmieri 2:c944cfe08e79 253
apalmieri 2:c944cfe08e79 254 if(params->isScanResponse){
apalmieri 2:c944cfe08e79 255 PRINTF("isScanResponse=true\r\n");
apalmieri 2:c944cfe08e79 256 } else {
apalmieri 2:c944cfe08e79 257 PRINTF("isScanResponse=false\r\n");
apalmieri 2:c944cfe08e79 258 }
apalmieri 2:c944cfe08e79 259
apalmieri 2:c944cfe08e79 260 switch(params->type)
apalmieri 2:c944cfe08e79 261 {
apalmieri 2:c944cfe08e79 262 case GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED:
apalmieri 2:c944cfe08e79 263 PRINTF("ADV_CONNECTABLE_UNDIRECTED\r\n");
apalmieri 2:c944cfe08e79 264 break;
apalmieri 2:c944cfe08e79 265 case GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED:
apalmieri 2:c944cfe08e79 266 PRINTF("ADV_CONNECTABLE_DIRECTED\r\n");
apalmieri 2:c944cfe08e79 267 break;
apalmieri 2:c944cfe08e79 268 case GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED:
apalmieri 2:c944cfe08e79 269 PRINTF("ADV_SCANNABLE_UNDIRECTED\r\n");
apalmieri 2:c944cfe08e79 270 break;
apalmieri 2:c944cfe08e79 271 case GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED:
apalmieri 2:c944cfe08e79 272 PRINTF("ADV_NON_CONNECTABLE_UNDIRECTED\r\n");
apalmieri 2:c944cfe08e79 273 break;
apalmieri 2:c944cfe08e79 274
apalmieri 2:c944cfe08e79 275 }
apalmieri 2:c944cfe08e79 276
apalmieri 2:c944cfe08e79 277 PRINTF("advertisingDataLen: %d\r\n",params->advertisingDataLen );
apalmieri 2:c944cfe08e79 278
apalmieri 2:c944cfe08e79 279 PRINTF("advertisingData: ");
apalmieri 2:c944cfe08e79 280 for(int i=0; i < params->advertisingDataLen; i++)
apalmieri 2:c944cfe08e79 281 {
apalmieri 2:c944cfe08e79 282 PRINTF("%02x",params->advertisingData[i]);
apalmieri 2:c944cfe08e79 283 if(i != params->advertisingDataLen - 1)PRINTF("-");
apalmieri 2:c944cfe08e79 284 }
apalmieri 2:c944cfe08e79 285 PRINTF("\r\n");
apalmieri 2:c944cfe08e79 286 }
apalmieri 2:c944cfe08e79 287
apalmieri 2:c944cfe08e79 288
apalmieri 2:c944cfe08e79 289 void scanResultReceived(const Gap::AdvertisementCallbackParams_t *params)
apalmieri 2:c944cfe08e79 290 {
apalmieri 2:c944cfe08e79 291 PRINTF("\r\nscanResultReceived\r\n");
apalmieri 2:c944cfe08e79 292
apalmieri 2:c944cfe08e79 293 //print advertsing values
apalmieri 2:c944cfe08e79 294 PrintScanResult(params);
apalmieri 2:c944cfe08e79 295
apalmieri 2:c944cfe08e79 296 PRINTF("scan result ... try connect\r\n");
apalmieri 2:c944cfe08e79 297 connectToDevice(params->peerAddr);
apalmieri 2:c944cfe08e79 298 }
apalmieri 2:c944cfe08e79 299
apalmieri 2:c944cfe08e79 300 void connectToDevice(const Gap::Address_t peerAddr)
apalmieri 2:c944cfe08e79 301 {
apalmieri 2:c944cfe08e79 302 ble_error_t ret = ble.gap().connect(peerAddr, Gap::ADDR_TYPE_PUBLIC, NULL, NULL);
apalmieri 2:c944cfe08e79 303
apalmieri 2:c944cfe08e79 304 if(ret == BLE_ERROR_NONE) {
apalmieri 2:c944cfe08e79 305 PRINTF("SUCCESS: connect\r\n");
apalmieri 2:c944cfe08e79 306 } else {
apalmieri 2:c944cfe08e79 307 PRINTF("ERROR : connect\r\n");
apalmieri 2:c944cfe08e79 308 }
apalmieri 2:c944cfe08e79 309 }
apalmieri 2:c944cfe08e79 310
apalmieri 2:c944cfe08e79 311 void serviceDiscoveryCallback(const DiscoveredService *service) {
apalmieri 2:c944cfe08e79 312 PRINTF("Service discovery callback\r\n");
apalmieri 2:c944cfe08e79 313
apalmieri 2:c944cfe08e79 314 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
apalmieri 2:c944cfe08e79 315 PRINTF("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
apalmieri 2:c944cfe08e79 316 } else {
apalmieri 2:c944cfe08e79 317 printf("S UUID-");
apalmieri 2:c944cfe08e79 318 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
apalmieri 2:c944cfe08e79 319 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
apalmieri 2:c944cfe08e79 320 printf("%02x", longUUIDBytes[i]);
apalmieri 2:c944cfe08e79 321 }
apalmieri 2:c944cfe08e79 322 PRINTF(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
apalmieri 2:c944cfe08e79 323 }
apalmieri 2:c944cfe08e79 324 }
apalmieri 2:c944cfe08e79 325
apalmieri 2:c944cfe08e79 326 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
apalmieri 2:c944cfe08e79 327 PRINTF("Characteristic discovery callback\r\n");
apalmieri 2:c944cfe08e79 328
apalmieri 2:c944cfe08e79 329 PRINTF(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
apalmieri 2:c944cfe08e79 330 //TODO: use hear rate characteristic
apalmieri 2:c944cfe08e79 331 if (characteristicP->getUUID().getShortUUID() == 0x2A00) {
apalmieri 2:c944cfe08e79 332 hrmCharacteristic = *characteristicP;
apalmieri 2:c944cfe08e79 333 triggerHrmCharacteristic = true;
apalmieri 2:c944cfe08e79 334 PRINTF("device name characteristic found\r\n");
apalmieri 2:c944cfe08e79 335 }
apalmieri 2:c944cfe08e79 336 }
apalmieri 2:c944cfe08e79 337
apalmieri 2:c944cfe08e79 338 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
apalmieri 2:c944cfe08e79 339 PRINTF("terminated SD for handle %u\r\n", connectionHandle);
apalmieri 2:c944cfe08e79 340 }
apalmieri 2:c944cfe08e79 341
apalmieri 2:c944cfe08e79 342 void timeoutCallback(Gap::TimeoutSource_t param) {
apalmieri 2:c944cfe08e79 343
apalmieri 2:c944cfe08e79 344 switch(param)
apalmieri 2:c944cfe08e79 345 {
apalmieri 2:c944cfe08e79 346 case Gap::TIMEOUT_SRC_ADVERTISING:
apalmieri 2:c944cfe08e79 347 PRINTF("Timeout: Advertising\r\n");
apalmieri 2:c944cfe08e79 348 break;
apalmieri 2:c944cfe08e79 349 case Gap::TIMEOUT_SRC_SECURITY_REQUEST:
apalmieri 2:c944cfe08e79 350 PRINTF("Timeout: Security access\r\n");
apalmieri 2:c944cfe08e79 351 break;
apalmieri 2:c944cfe08e79 352 case Gap::TIMEOUT_SRC_SCAN:
apalmieri 2:c944cfe08e79 353 PRINTF("Timeout: Scan\r\n");
apalmieri 2:c944cfe08e79 354 break;
apalmieri 2:c944cfe08e79 355 case Gap::TIMEOUT_SRC_CONN:
apalmieri 2:c944cfe08e79 356 PRINTF("Timeout: Conn\r\n");
apalmieri 2:c944cfe08e79 357 break;
apalmieri 2:c944cfe08e79 358 }
apalmieri 2:c944cfe08e79 359 }
apalmieri 2:c944cfe08e79 360
apalmieri 2:c944cfe08e79 361 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
apalmieri 2:c944cfe08e79 362 if (params->role == Gap::CENTRAL) {
apalmieri 2:c944cfe08e79 363 PRINTF("Launch service discovery\r\n");
apalmieri 2:c944cfe08e79 364 //TODO: use heart rate service
apalmieri 2:c944cfe08e79 365 ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
apalmieri 2:c944cfe08e79 366 ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, 0x1800, 0x2A00);
apalmieri 2:c944cfe08e79 367 _connected = true;
apalmieri 2:c944cfe08e79 368 // ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, GattService::UUID_HEART_RATE_SERVICE, GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR); //BLE_UUID_UNKNOWN
apalmieri 2:c944cfe08e79 369 }
apalmieri 2:c944cfe08e79 370 else {
apalmieri 2:c944cfe08e79 371 PRINTF("No central role\r\n");
apalmieri 2:c944cfe08e79 372 }
apalmieri 2:c944cfe08e79 373 }
apalmieri 2:c944cfe08e79 374
apalmieri 2:c944cfe08e79 375
apalmieri 2:c944cfe08e79 376 void readCallback(const GattReadCallbackParams *response)
apalmieri 2:c944cfe08e79 377 {
apalmieri 2:c944cfe08e79 378 PRINTF("readCallback\r\n");
apalmieri 2:c944cfe08e79 379
apalmieri 2:c944cfe08e79 380 if (response->handle == hrmCharacteristic.getValueHandle()) {
apalmieri 2:c944cfe08e79 381 PRINTF("readCallback: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
apalmieri 2:c944cfe08e79 382 for (unsigned index = 0; index < response->len; index++) {
apalmieri 2:c944cfe08e79 383 PRINTF("%c[%02x]", response->data[index], response->data[index]);
apalmieri 2:c944cfe08e79 384 }
apalmieri 2:c944cfe08e79 385 PRINTF("\r\n");
apalmieri 2:c944cfe08e79 386 }
apalmieri 2:c944cfe08e79 387 }
apalmieri 2:c944cfe08e79 388
apalmieri 2:c944cfe08e79 389 /**
apalmieri 2:c944cfe08e79 390 * This function is called when the ble initialization process has failled
apalmieri 2:c944cfe08e79 391 */
apalmieri 2:c944cfe08e79 392 void onBleInitError(BLE &ble, ble_error_t error)
apalmieri 2:c944cfe08e79 393 {
apalmieri 2:c944cfe08e79 394 PRINTF("BLE init error");
apalmieri 2:c944cfe08e79 395 }
apalmieri 2:c944cfe08e79 396
apalmieri 2:c944cfe08e79 397 /**
apalmieri 2:c944cfe08e79 398 * Callback triggered when the ble initialization process has finished
apalmieri 2:c944cfe08e79 399 */
apalmieri 2:c944cfe08e79 400 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
apalmieri 2:c944cfe08e79 401 {
apalmieri 2:c944cfe08e79 402
apalmieri 2:c944cfe08e79 403 PRINTF("init complete\r\n");
apalmieri 2:c944cfe08e79 404
apalmieri 2:c944cfe08e79 405 BLE& ble = params->ble;
apalmieri 2:c944cfe08e79 406 ble_error_t error = params->error;
apalmieri 2:c944cfe08e79 407
apalmieri 2:c944cfe08e79 408 if (error != BLE_ERROR_NONE) {
apalmieri 2:c944cfe08e79 409 /* In case of error, forward the error handling to onBleInitError */
apalmieri 2:c944cfe08e79 410 PRINTF("Error init\r\n");
apalmieri 2:c944cfe08e79 411 onBleInitError(ble, error);
apalmieri 2:c944cfe08e79 412 return;
apalmieri 2:c944cfe08e79 413 }
apalmieri 2:c944cfe08e79 414
apalmieri 2:c944cfe08e79 415 /* Ensure that it is the default instance of BLE */
apalmieri 2:c944cfe08e79 416 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
apalmieri 2:c944cfe08e79 417 PRINTF("Error default instance\r\n");
apalmieri 2:c944cfe08e79 418 return;
apalmieri 2:c944cfe08e79 419 }
apalmieri 2:c944cfe08e79 420
apalmieri 2:c944cfe08e79 421 ble.onTimeout(timeoutCallback);
apalmieri 2:c944cfe08e79 422 ble.onConnection(connectionCallback);
apalmieri 2:c944cfe08e79 423 ble.onDisconnection(disconnectionCallback);
apalmieri 2:c944cfe08e79 424 ble.gattClient().onDataRead(readCallback);
apalmieri 2:c944cfe08e79 425
apalmieri 2:c944cfe08e79 426 ble.gap().setScanParams(300, 300);
apalmieri 2:c944cfe08e79 427 ble.gap().startScan(scanResultReceived);
apalmieri 2:c944cfe08e79 428 PRINTF("scan started...\r\n");
apalmieri 2:c944cfe08e79 429
apalmieri 2:c944cfe08e79 430
apalmieri 2:c944cfe08e79 431 // infinite loop
apalmieri 2:c944cfe08e79 432 while (1) {
apalmieri 2:c944cfe08e79 433 // check for trigger from periodicCallback()
apalmieri 2:c944cfe08e79 434 if (triggerHrmCharacteristic && !ble.gattClient().isServiceDiscoveryActive() && _connected) {
apalmieri 2:c944cfe08e79 435
apalmieri 2:c944cfe08e79 436 triggerHrmCharacteristic = false;
apalmieri 2:c944cfe08e79 437 PRINTF("START READ\r\n");
apalmieri 2:c944cfe08e79 438 hrmCharacteristic.read();
apalmieri 2:c944cfe08e79 439
apalmieri 2:c944cfe08e79 440 } else {
apalmieri 2:c944cfe08e79 441 ble.waitForEvent(); // low power wait for event
apalmieri 2:c944cfe08e79 442 }
apalmieri 2:c944cfe08e79 443 }
apalmieri 2:c944cfe08e79 444
apalmieri 2:c944cfe08e79 445
apalmieri 2:c944cfe08e79 446
apalmieri 2:c944cfe08e79 447
apalmieri 2:c944cfe08e79 448 }
apalmieri 2:c944cfe08e79 449
apalmieri 2:c944cfe08e79 450 int main(void)
apalmieri 2:c944cfe08e79 451 {
apalmieri 2:c944cfe08e79 452 PRINTF("started...\r\n");
apalmieri 2:c944cfe08e79 453
apalmieri 2:c944cfe08e79 454 led1 = 1;
apalmieri 2:c944cfe08e79 455 Ticker ticker;
apalmieri 2:c944cfe08e79 456 ticker.attach(periodicCallback, 1); // blink LED every second
apalmieri 2:c944cfe08e79 457
apalmieri 2:c944cfe08e79 458 _connected = false;
apalmieri 2:c944cfe08e79 459
apalmieri 2:c944cfe08e79 460 PRINTF("start init...\r\n");
apalmieri 2:c944cfe08e79 461
apalmieri 2:c944cfe08e79 462 ble.init(bleInitComplete);
apalmieri 2:c944cfe08e79 463 }