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