BLE EddystoneObserver example

This example is a fork of the following mbed-os example:

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneObserver/

Please read the documentation in this page.

Committer:
Vincent Coubard
Date:
Tue Jul 26 14:38:37 2016 +0100
Revision:
0:932f719b42d5
Child:
1:d839eae15f56
Update example at tag mbed-os-5.0.1-rc1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 0:932f719b42d5 1 /* mbed Microcontroller Library
Vincent Coubard 0:932f719b42d5 2 * Copyright (c) 2006-2013 ARM Limited
Vincent Coubard 0:932f719b42d5 3 *
Vincent Coubard 0:932f719b42d5 4 * Licensed under the Apache License, Version 2.0 (the "License");
Vincent Coubard 0:932f719b42d5 5 * you may not use this file except in compliance with the License.
Vincent Coubard 0:932f719b42d5 6 * You may obtain a copy of the License at
Vincent Coubard 0:932f719b42d5 7 *
Vincent Coubard 0:932f719b42d5 8 * http://www.apache.org/licenses/LICENSE-2.0
Vincent Coubard 0:932f719b42d5 9 *
Vincent Coubard 0:932f719b42d5 10 * Unless required by applicable law or agreed to in writing, software
Vincent Coubard 0:932f719b42d5 11 * distributed under the License is distributed on an "AS IS" BASIS,
Vincent Coubard 0:932f719b42d5 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Vincent Coubard 0:932f719b42d5 13 * See the License for the specific language governing permissions and
Vincent Coubard 0:932f719b42d5 14 * limitations under the License.
Vincent Coubard 0:932f719b42d5 15 */
Vincent Coubard 0:932f719b42d5 16
Vincent Coubard 0:932f719b42d5 17 #include <mbed-events/events.h>
Vincent Coubard 0:932f719b42d5 18 #include "mbed.h"
Vincent Coubard 0:932f719b42d5 19 #include "ble/BLE.h"
Vincent Coubard 0:932f719b42d5 20
Vincent Coubard 0:932f719b42d5 21 static const int URI_MAX_LENGTH = 18; // Maximum size of service data in ADV packets
Vincent Coubard 0:932f719b42d5 22
Vincent Coubard 0:932f719b42d5 23 static EventQueue eventQueue(
Vincent Coubard 0:932f719b42d5 24 /* event count */ 16 * /* event size */ 32
Vincent Coubard 0:932f719b42d5 25 );
Vincent Coubard 0:932f719b42d5 26
Vincent Coubard 0:932f719b42d5 27 DigitalOut led1(LED1, 1);
Vincent Coubard 0:932f719b42d5 28
Vincent Coubard 0:932f719b42d5 29 void periodicCallback(void)
Vincent Coubard 0:932f719b42d5 30 {
Vincent Coubard 0:932f719b42d5 31 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
Vincent Coubard 0:932f719b42d5 32 }
Vincent Coubard 0:932f719b42d5 33
Vincent Coubard 0:932f719b42d5 34 void decodeURI(const uint8_t* uriData, const size_t uriLen)
Vincent Coubard 0:932f719b42d5 35 {
Vincent Coubard 0:932f719b42d5 36 const char *prefixes[] = {
Vincent Coubard 0:932f719b42d5 37 "http://www.",
Vincent Coubard 0:932f719b42d5 38 "https://www.",
Vincent Coubard 0:932f719b42d5 39 "http://",
Vincent Coubard 0:932f719b42d5 40 "https://",
Vincent Coubard 0:932f719b42d5 41 "urn:uuid:"
Vincent Coubard 0:932f719b42d5 42 };
Vincent Coubard 0:932f719b42d5 43 const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
Vincent Coubard 0:932f719b42d5 44 const char *suffixes[] = {
Vincent Coubard 0:932f719b42d5 45 ".com/",
Vincent Coubard 0:932f719b42d5 46 ".org/",
Vincent Coubard 0:932f719b42d5 47 ".edu/",
Vincent Coubard 0:932f719b42d5 48 ".net/",
Vincent Coubard 0:932f719b42d5 49 ".info/",
Vincent Coubard 0:932f719b42d5 50 ".biz/",
Vincent Coubard 0:932f719b42d5 51 ".gov/",
Vincent Coubard 0:932f719b42d5 52 ".com",
Vincent Coubard 0:932f719b42d5 53 ".org",
Vincent Coubard 0:932f719b42d5 54 ".edu",
Vincent Coubard 0:932f719b42d5 55 ".net",
Vincent Coubard 0:932f719b42d5 56 ".info",
Vincent Coubard 0:932f719b42d5 57 ".biz",
Vincent Coubard 0:932f719b42d5 58 ".gov"
Vincent Coubard 0:932f719b42d5 59 };
Vincent Coubard 0:932f719b42d5 60 const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
Vincent Coubard 0:932f719b42d5 61
Vincent Coubard 0:932f719b42d5 62 size_t index = 0;
Vincent Coubard 0:932f719b42d5 63
Vincent Coubard 0:932f719b42d5 64 /* First byte is the URL Scheme. */
Vincent Coubard 0:932f719b42d5 65 if (uriData[index] < NUM_PREFIXES) {
Vincent Coubard 0:932f719b42d5 66 printf("%s", prefixes[uriData[index]]);
Vincent Coubard 0:932f719b42d5 67 index++;
Vincent Coubard 0:932f719b42d5 68 } else {
Vincent Coubard 0:932f719b42d5 69 printf("URL Scheme was not encoded!");
Vincent Coubard 0:932f719b42d5 70 return;
Vincent Coubard 0:932f719b42d5 71 }
Vincent Coubard 0:932f719b42d5 72
Vincent Coubard 0:932f719b42d5 73 /* From second byte onwards we can have a character or a suffix */
Vincent Coubard 0:932f719b42d5 74 while(index < uriLen) {
Vincent Coubard 0:932f719b42d5 75 if (uriData[index] < NUM_SUFFIXES) {
Vincent Coubard 0:932f719b42d5 76 printf("%s", suffixes[uriData[index]]);
Vincent Coubard 0:932f719b42d5 77 } else {
Vincent Coubard 0:932f719b42d5 78 printf("%c", uriData[index]);
Vincent Coubard 0:932f719b42d5 79 }
Vincent Coubard 0:932f719b42d5 80 index++;
Vincent Coubard 0:932f719b42d5 81 }
Vincent Coubard 0:932f719b42d5 82
Vincent Coubard 0:932f719b42d5 83 printf("\n\r");
Vincent Coubard 0:932f719b42d5 84 }
Vincent Coubard 0:932f719b42d5 85
Vincent Coubard 0:932f719b42d5 86 /*
Vincent Coubard 0:932f719b42d5 87 * This function is called every time we scan an advertisement.
Vincent Coubard 0:932f719b42d5 88 */
Vincent Coubard 0:932f719b42d5 89 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
Vincent Coubard 0:932f719b42d5 90 {
Vincent Coubard 0:932f719b42d5 91 struct AdvertisingData_t {
Vincent Coubard 0:932f719b42d5 92 uint8_t length; /* doesn't include itself */
Vincent Coubard 0:932f719b42d5 93 GapAdvertisingData::DataType_t dataType;
Vincent Coubard 0:932f719b42d5 94 uint8_t data[0];
Vincent Coubard 0:932f719b42d5 95 } AdvDataPacket;
Vincent Coubard 0:932f719b42d5 96
Vincent Coubard 0:932f719b42d5 97 struct ApplicationData_t {
Vincent Coubard 0:932f719b42d5 98 uint8_t applicationSpecificId[2];
Vincent Coubard 0:932f719b42d5 99 uint8_t frameType;
Vincent Coubard 0:932f719b42d5 100 uint8_t advPowerLevels;
Vincent Coubard 0:932f719b42d5 101 uint8_t uriData[URI_MAX_LENGTH];
Vincent Coubard 0:932f719b42d5 102 } AppDataPacket;
Vincent Coubard 0:932f719b42d5 103
Vincent Coubard 0:932f719b42d5 104 const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE};
Vincent Coubard 0:932f719b42d5 105 const uint8_t FRAME_TYPE_URL = 0x10;
Vincent Coubard 0:932f719b42d5 106 const uint8_t APPLICATION_DATA_OFFSET = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData);
Vincent Coubard 0:932f719b42d5 107
Vincent Coubard 0:932f719b42d5 108 AdvertisingData_t *pAdvData;
Vincent Coubard 0:932f719b42d5 109 size_t index = 0;
Vincent Coubard 0:932f719b42d5 110 while(index < params->advertisingDataLen) {
Vincent Coubard 0:932f719b42d5 111 pAdvData = (AdvertisingData_t *)&params->advertisingData[index];
Vincent Coubard 0:932f719b42d5 112 if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) {
Vincent Coubard 0:932f719b42d5 113 ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data;
Vincent Coubard 0:932f719b42d5 114 if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) {
Vincent Coubard 0:932f719b42d5 115 decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET);
Vincent Coubard 0:932f719b42d5 116 break;
Vincent Coubard 0:932f719b42d5 117 }
Vincent Coubard 0:932f719b42d5 118 }
Vincent Coubard 0:932f719b42d5 119 index += (pAdvData->length + 1);
Vincent Coubard 0:932f719b42d5 120 }
Vincent Coubard 0:932f719b42d5 121 }
Vincent Coubard 0:932f719b42d5 122
Vincent Coubard 0:932f719b42d5 123 void onBleInitError(BLE &ble, ble_error_t error)
Vincent Coubard 0:932f719b42d5 124 {
Vincent Coubard 0:932f719b42d5 125 /* Initialization error handling should go here */
Vincent Coubard 0:932f719b42d5 126 }
Vincent Coubard 0:932f719b42d5 127
Vincent Coubard 0:932f719b42d5 128 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
Vincent Coubard 0:932f719b42d5 129 {
Vincent Coubard 0:932f719b42d5 130 BLE& ble = params->ble;
Vincent Coubard 0:932f719b42d5 131 ble_error_t error = params->error;
Vincent Coubard 0:932f719b42d5 132
Vincent Coubard 0:932f719b42d5 133 if (error != BLE_ERROR_NONE) {
Vincent Coubard 0:932f719b42d5 134 onBleInitError(ble, error);
Vincent Coubard 0:932f719b42d5 135 return;
Vincent Coubard 0:932f719b42d5 136 }
Vincent Coubard 0:932f719b42d5 137
Vincent Coubard 0:932f719b42d5 138 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
Vincent Coubard 0:932f719b42d5 139 return;
Vincent Coubard 0:932f719b42d5 140 }
Vincent Coubard 0:932f719b42d5 141
Vincent Coubard 0:932f719b42d5 142 ble.gap().setScanParams(1800 /* scan interval */, 1500 /* scan window */);
Vincent Coubard 0:932f719b42d5 143 ble.gap().startScan(advertisementCallback);
Vincent Coubard 0:932f719b42d5 144 }
Vincent Coubard 0:932f719b42d5 145
Vincent Coubard 0:932f719b42d5 146 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
Vincent Coubard 0:932f719b42d5 147 BLE &ble = BLE::Instance();
Vincent Coubard 0:932f719b42d5 148 eventQueue.post(Callback<void()>(&ble, &BLE::processEvents));
Vincent Coubard 0:932f719b42d5 149 }
Vincent Coubard 0:932f719b42d5 150
Vincent Coubard 0:932f719b42d5 151 int main()
Vincent Coubard 0:932f719b42d5 152 {
Vincent Coubard 0:932f719b42d5 153 eventQueue.post_every(periodicCallback, 500);
Vincent Coubard 0:932f719b42d5 154
Vincent Coubard 0:932f719b42d5 155 BLE &ble = BLE::Instance();
Vincent Coubard 0:932f719b42d5 156 ble.onEventsToProcess(scheduleBleEventsProcessing);
Vincent Coubard 0:932f719b42d5 157 ble.init(bleInitComplete);
Vincent Coubard 0:932f719b42d5 158
Vincent Coubard 0:932f719b42d5 159 while (true) {
Vincent Coubard 0:932f719b42d5 160 eventQueue.dispatch();
Vincent Coubard 0:932f719b42d5 161 }
Vincent Coubard 0:932f719b42d5 162
Vincent Coubard 0:932f719b42d5 163 return 0;
Vincent Coubard 0:932f719b42d5 164 }