Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os-example-ble-EddystoneObserver by
Diff: source/main.cpp
- Revision:
- 33:d83bd71e5d82
- Parent:
- 29:083b9a2cb114
- Child:
- 34:b2d964ce740f
diff -r 1d55c70f6fa5 -r d83bd71e5d82 source/main.cpp
--- a/source/main.cpp Thu Jun 08 14:45:28 2017 +0100
+++ b/source/main.cpp Mon Jun 12 04:49:37 2017 +0000
@@ -17,106 +17,221 @@
#include <events/mbed_events.h>
#include "mbed.h"
#include "ble/BLE.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
+#include "ble/services/HeartRateService.h"
-static const int URI_MAX_LENGTH = 18; // Maximum size of service data in ADV packets
+
+//static const int URI_MAX_LENGTH = 18; // Maximum size of service data in ADV packets
static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
+static const char PEER_NAME[] = "HRM";
+static DiscoveredCharacteristic ledCharacteristic;
+static bool triggerLedCharacteristic;
DigitalOut led1(LED1, 1);
+ReadOnlyGattCharacteristic<uint32_t> readFrom(uuid, valuePtr,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
void periodicCallback(void)
{
led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
}
-void decodeURI(const uint8_t* uriData, const size_t uriLen)
-{
- const char *prefixes[] = {
- "http://www.",
- "https://www.",
- "http://",
- "https://",
- "urn:uuid:"
- };
- const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
- const char *suffixes[] = {
- ".com/",
- ".org/",
- ".edu/",
- ".net/",
- ".info/",
- ".biz/",
- ".gov/",
- ".com",
- ".org",
- ".edu",
- ".net",
- ".info",
- ".biz",
- ".gov"
- };
- const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
+//void decodeURI(const uint8_t* uriData, const size_t uriLen)
+//{
+// const char *prefixes[] = {
+// "http://www.",
+// "https://www.",
+// "http://",
+// "https://",
+// "urn:uuid:"
+// };
+// const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
+// const char *suffixes[] = {
+// ".com/",
+// ".org/",
+// ".edu/",
+// ".net/",
+// ".info/",
+// ".biz/",
+// ".gov/",
+// ".com",
+// ".org",
+// ".edu",
+// ".net",
+// ".info",
+// ".biz",
+// ".gov"
+// };
+// const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
+//
+// size_t index = 0;
+//
+// /* First byte is the URL Scheme. */
+// if (uriData[index] < NUM_PREFIXES) {
+// printf("%s", prefixes[uriData[index]]);
+// index++;
+// } else {
+// printf("URL Scheme was not encoded!");
+// return;
+// }
+//
+// /* From second byte onwards we can have a character or a suffix */
+// while(index < uriLen) {
+// if (uriData[index] < NUM_SUFFIXES) {
+// printf("%s", suffixes[uriData[index]]);
+// } else {
+// printf("%c", uriData[index]);
+// }
+// index++;
+// }
+//
+// printf("\n\r");
+//}
- size_t index = 0;
+void serviceDiscoveryCallback(const DiscoveredService *service) {
+ if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+ printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+ } else {
+ printf("S UUID-");
+ const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+ for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+ printf("%02x", longUUIDBytes[i]);
+ }
+ printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+ }
+}
- /* First byte is the URL Scheme. */
- if (uriData[index] < NUM_PREFIXES) {
- printf("%s", prefixes[uriData[index]]);
- index++;
- } else {
- printf("URL Scheme was not encoded!");
- return;
- }
+void updateLedCharacteristic(void) {
+ if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
+ ledCharacteristic.read();
+ }
+}
- /* From second byte onwards we can have a character or a suffix */
- while(index < uriLen) {
- if (uriData[index] < NUM_SUFFIXES) {
- printf("%s", suffixes[uriData[index]]);
- } else {
- printf("%c", uriData[index]);
- }
- index++;
- }
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
+ printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+ if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
+ ledCharacteristic = *characteristicP;
+ triggerLedCharacteristic = true;
+ }
+}
- printf("\n\r");
-}
+ void triggerToggledWrite(const GattReadCallbackParams *response) {
+ printf("triggerToggledWrite\n");
+ if (response->handle == ledCharacteristic.getValueHandle()) {
+ printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
+ for (unsigned index = 0; index < response->len; index++) {
+ printf("%c[%02x]", response->data[index], response->data[index]);
+ }
+ printf("\r\n");
+
+ uint8_t toggledValue = response->data[0] ^ 0x1;
+ ledCharacteristic.write(1, &toggledValue);
+ }
+ }
+
+
+ void triggerRead(const GattWriteCallbackParams *response) {
+ printf("triggerRead\n");
+ if (response->handle == ledCharacteristic.getValueHandle()) {
+ ledCharacteristic.read();
+ }
+ }
+
/*
* This function is called every time we scan an advertisement.
*/
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
{
- struct AdvertisingData_t {
- uint8_t length; /* doesn't include itself */
- GapAdvertisingData::DataType_t dataType;
- uint8_t data[1];
- } AdvDataPacket;
+// printf(
+// "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
+// params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
+// params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
+// );
+// struct AdvertisingData_t {
+// uint8_t length; /* doesn't include itself */
+// GapAdvertisingData::DataType_t dataType;
+// uint8_t data[1];
+// } AdvDataPacket;
+//
+// struct ApplicationData_t {
+// uint8_t applicationSpecificId[2];
+// uint8_t frameType;
+// uint8_t advPowerLevels;
+// uint8_t uriData[URI_MAX_LENGTH];
+// } AppDataPacket;
+//
+// const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE};
+// const uint8_t FRAME_TYPE_URL = 0x10;
+// const uint8_t APPLICATION_DATA_OFFSET = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData);
+//
+// AdvertisingData_t *pAdvData;
+// size_t index = 0;
+// while(index < params->advertisingDataLen) {
+// pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index];
+// if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) {
+// ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data;
+// if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) {
+// decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET);
+// break;
+// }
+// }
+// index += (pAdvData->length + 1);
+// }
- struct ApplicationData_t {
- uint8_t applicationSpecificId[2];
- uint8_t frameType;
- uint8_t advPowerLevels;
- uint8_t uriData[URI_MAX_LENGTH];
- } AppDataPacket;
+ for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
- const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE};
- const uint8_t FRAME_TYPE_URL = 0x10;
- const uint8_t APPLICATION_DATA_OFFSET = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData);
+ const uint8_t record_length = params->advertisingData[i];
+ if (record_length == 0) {
+ continue;
+ }
+ const uint8_t type = params->advertisingData[i + 1];
+ const uint8_t* value = params->advertisingData + i + 2;
+ const uint8_t value_length = record_length - 1;
+
+
+ if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
+ if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) {
+ printf(
+ "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
+ params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
+ params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
+ );
+ BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+ break;
+ }
+ }
+ i += record_length;
+ }
+}
- AdvertisingData_t *pAdvData;
- size_t index = 0;
- while(index < params->advertisingDataLen) {
- pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index];
- if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) {
- ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data;
- if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) {
- decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET);
- break;
- }
- }
- index += (pAdvData->length + 1);
- }
-}
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
+ printf("terminated SD for handle %u\r\n", connectionHandle);
+ if (triggerLedCharacteristic) {
+ triggerLedCharacteristic = false;
+ eventQueue.call(updateLedCharacteristic);
+ }
+}
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
+ printf("connectionCallback\n");
+ printf("params->role: %01x\n", params->role);
+ if (params->role == Gap::CENTRAL) {
+ printf("ROLE: CENTRAL\n");
+ BLE &ble = BLE::Instance();
+ ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+ ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, GattService::UUID_HEART_RATE_SERVICE, 0xa001);
+ }
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) {
+ printf("disconnected\r\n");
+ /* Start scanning and try to connect again */
+ BLE::Instance().gap().startScan(advertisementCallback);
+}
void onBleInitError(BLE &ble, ble_error_t error)
{
@@ -137,6 +252,9 @@
return;
}
+ ble.gap().onDisconnection(disconnectionCallback);
+ ble.gap().onConnection(connectionCallback);
+
ble.gap().setScanParams(1800 /* scan interval */, 1500 /* scan window */);
ble.gap().startScan(advertisementCallback);
}
