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