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:
Thu Jul 28 23:29:23 2016 +0100
Revision:
2:6a3a66fd3889
Parent:
1:d839eae15f56
Child:
3:b1e385adea43
Sync with mbed-os-5.1.0-rc3

Who changed what in which revision?

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