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@13:c5f3a7d8764a, 2016-10-24 (annotated)
- Committer:
- mbed_official
- Date:
- Mon Oct 24 11:15:22 2016 +0100
- Revision:
- 13:c5f3a7d8764a
- Parent:
- 12:5e1ef2515c70
- Child:
- 29:083b9a2cb114
Merge pull request #32 from ARMmbed/oob
Sync with mbed OS 5.2 OOB repo
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble
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 | 3:b1e385adea43 | 23 | static EventQueue eventQueue( |
mbed_official | 3:b1e385adea43 | 24 | /* event count */ 16 * /* event size */ 32 |
mbed_official | 3:b1e385adea43 | 25 | ); |
mbed_official | 3:b1e385adea43 | 26 | |
mbed_official | 3:b1e385adea43 | 27 | DigitalOut led1(LED1, 1); |
mbed_official | 3:b1e385adea43 | 28 | |
mbed_official | 3:b1e385adea43 | 29 | void periodicCallback(void) |
mbed_official | 3:b1e385adea43 | 30 | { |
mbed_official | 3:b1e385adea43 | 31 | led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ |
mbed_official | 3:b1e385adea43 | 32 | } |
mbed_official | 3:b1e385adea43 | 33 | |
mbed_official | 3:b1e385adea43 | 34 | void decodeURI(const uint8_t* uriData, const size_t uriLen) |
mbed_official | 3:b1e385adea43 | 35 | { |
mbed_official | 3:b1e385adea43 | 36 | const char *prefixes[] = { |
mbed_official | 3:b1e385adea43 | 37 | "http://www.", |
mbed_official | 3:b1e385adea43 | 38 | "https://www.", |
mbed_official | 3:b1e385adea43 | 39 | "http://", |
mbed_official | 3:b1e385adea43 | 40 | "https://", |
mbed_official | 3:b1e385adea43 | 41 | "urn:uuid:" |
mbed_official | 3:b1e385adea43 | 42 | }; |
mbed_official | 3:b1e385adea43 | 43 | const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *); |
mbed_official | 3:b1e385adea43 | 44 | const char *suffixes[] = { |
mbed_official | 3:b1e385adea43 | 45 | ".com/", |
mbed_official | 3:b1e385adea43 | 46 | ".org/", |
mbed_official | 3:b1e385adea43 | 47 | ".edu/", |
mbed_official | 3:b1e385adea43 | 48 | ".net/", |
mbed_official | 3:b1e385adea43 | 49 | ".info/", |
mbed_official | 3:b1e385adea43 | 50 | ".biz/", |
mbed_official | 3:b1e385adea43 | 51 | ".gov/", |
mbed_official | 3:b1e385adea43 | 52 | ".com", |
mbed_official | 3:b1e385adea43 | 53 | ".org", |
mbed_official | 3:b1e385adea43 | 54 | ".edu", |
mbed_official | 3:b1e385adea43 | 55 | ".net", |
mbed_official | 3:b1e385adea43 | 56 | ".info", |
mbed_official | 3:b1e385adea43 | 57 | ".biz", |
mbed_official | 3:b1e385adea43 | 58 | ".gov" |
mbed_official | 3:b1e385adea43 | 59 | }; |
mbed_official | 3:b1e385adea43 | 60 | const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *); |
mbed_official | 3:b1e385adea43 | 61 | |
mbed_official | 3:b1e385adea43 | 62 | size_t index = 0; |
mbed_official | 3:b1e385adea43 | 63 | |
mbed_official | 3:b1e385adea43 | 64 | /* First byte is the URL Scheme. */ |
mbed_official | 3:b1e385adea43 | 65 | if (uriData[index] < NUM_PREFIXES) { |
mbed_official | 3:b1e385adea43 | 66 | printf("%s", prefixes[uriData[index]]); |
mbed_official | 3:b1e385adea43 | 67 | index++; |
mbed_official | 3:b1e385adea43 | 68 | } else { |
mbed_official | 3:b1e385adea43 | 69 | printf("URL Scheme was not encoded!"); |
mbed_official | 3:b1e385adea43 | 70 | return; |
mbed_official | 3:b1e385adea43 | 71 | } |
mbed_official | 3:b1e385adea43 | 72 | |
mbed_official | 3:b1e385adea43 | 73 | /* From second byte onwards we can have a character or a suffix */ |
mbed_official | 3:b1e385adea43 | 74 | while(index < uriLen) { |
mbed_official | 3:b1e385adea43 | 75 | if (uriData[index] < NUM_SUFFIXES) { |
mbed_official | 3:b1e385adea43 | 76 | printf("%s", suffixes[uriData[index]]); |
mbed_official | 3:b1e385adea43 | 77 | } else { |
mbed_official | 3:b1e385adea43 | 78 | printf("%c", uriData[index]); |
mbed_official | 3:b1e385adea43 | 79 | } |
mbed_official | 3:b1e385adea43 | 80 | index++; |
mbed_official | 3:b1e385adea43 | 81 | } |
mbed_official | 3:b1e385adea43 | 82 | |
mbed_official | 3:b1e385adea43 | 83 | printf("\n\r"); |
mbed_official | 3:b1e385adea43 | 84 | } |
mbed_official | 3:b1e385adea43 | 85 | |
mbed_official | 3:b1e385adea43 | 86 | /* |
mbed_official | 3:b1e385adea43 | 87 | * This function is called every time we scan an advertisement. |
mbed_official | 3:b1e385adea43 | 88 | */ |
mbed_official | 3:b1e385adea43 | 89 | void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) |
mbed_official | 3:b1e385adea43 | 90 | { |
mbed_official | 3:b1e385adea43 | 91 | struct AdvertisingData_t { |
mbed_official | 3:b1e385adea43 | 92 | uint8_t length; /* doesn't include itself */ |
mbed_official | 3:b1e385adea43 | 93 | GapAdvertisingData::DataType_t dataType; |
mbed_official | 12:5e1ef2515c70 | 94 | uint8_t data[1]; |
mbed_official | 3:b1e385adea43 | 95 | } AdvDataPacket; |
mbed_official | 3:b1e385adea43 | 96 | |
mbed_official | 3:b1e385adea43 | 97 | struct ApplicationData_t { |
mbed_official | 3:b1e385adea43 | 98 | uint8_t applicationSpecificId[2]; |
mbed_official | 3:b1e385adea43 | 99 | uint8_t frameType; |
mbed_official | 3:b1e385adea43 | 100 | uint8_t advPowerLevels; |
mbed_official | 3:b1e385adea43 | 101 | uint8_t uriData[URI_MAX_LENGTH]; |
mbed_official | 3:b1e385adea43 | 102 | } AppDataPacket; |
mbed_official | 3:b1e385adea43 | 103 | |
mbed_official | 3:b1e385adea43 | 104 | const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE}; |
mbed_official | 3:b1e385adea43 | 105 | const uint8_t FRAME_TYPE_URL = 0x10; |
mbed_official | 3:b1e385adea43 | 106 | const uint8_t APPLICATION_DATA_OFFSET = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData); |
mbed_official | 3:b1e385adea43 | 107 | |
mbed_official | 3:b1e385adea43 | 108 | AdvertisingData_t *pAdvData; |
mbed_official | 3:b1e385adea43 | 109 | size_t index = 0; |
mbed_official | 3:b1e385adea43 | 110 | while(index < params->advertisingDataLen) { |
mbed_official | 3:b1e385adea43 | 111 | pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index]; |
mbed_official | 3:b1e385adea43 | 112 | if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) { |
mbed_official | 3:b1e385adea43 | 113 | ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data; |
mbed_official | 3:b1e385adea43 | 114 | if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) { |
mbed_official | 3:b1e385adea43 | 115 | decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET); |
mbed_official | 3:b1e385adea43 | 116 | break; |
mbed_official | 3:b1e385adea43 | 117 | } |
mbed_official | 3:b1e385adea43 | 118 | } |
mbed_official | 3:b1e385adea43 | 119 | index += (pAdvData->length + 1); |
mbed_official | 3:b1e385adea43 | 120 | } |
mbed_official | 3:b1e385adea43 | 121 | } |
mbed_official | 3:b1e385adea43 | 122 | |
mbed_official | 3:b1e385adea43 | 123 | void onBleInitError(BLE &ble, ble_error_t error) |
mbed_official | 3:b1e385adea43 | 124 | { |
mbed_official | 3:b1e385adea43 | 125 | /* Initialization error handling should go here */ |
mbed_official | 3:b1e385adea43 | 126 | } |
mbed_official | 3:b1e385adea43 | 127 | |
mbed_official | 3:b1e385adea43 | 128 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
mbed_official | 3:b1e385adea43 | 129 | { |
mbed_official | 3:b1e385adea43 | 130 | BLE& ble = params->ble; |
mbed_official | 3:b1e385adea43 | 131 | ble_error_t error = params->error; |
mbed_official | 3:b1e385adea43 | 132 | |
mbed_official | 3:b1e385adea43 | 133 | if (error != BLE_ERROR_NONE) { |
mbed_official | 3:b1e385adea43 | 134 | onBleInitError(ble, error); |
mbed_official | 3:b1e385adea43 | 135 | return; |
mbed_official | 3:b1e385adea43 | 136 | } |
mbed_official | 3:b1e385adea43 | 137 | |
mbed_official | 3:b1e385adea43 | 138 | if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
mbed_official | 3:b1e385adea43 | 139 | return; |
mbed_official | 3:b1e385adea43 | 140 | } |
mbed_official | 3:b1e385adea43 | 141 | |
mbed_official | 3:b1e385adea43 | 142 | ble.gap().setScanParams(1800 /* scan interval */, 1500 /* scan window */); |
mbed_official | 3:b1e385adea43 | 143 | ble.gap().startScan(advertisementCallback); |
mbed_official | 3:b1e385adea43 | 144 | } |
mbed_official | 3:b1e385adea43 | 145 | |
mbed_official | 3:b1e385adea43 | 146 | void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { |
mbed_official | 3:b1e385adea43 | 147 | BLE &ble = BLE::Instance(); |
mbed_official | 13:c5f3a7d8764a | 148 | eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); |
mbed_official | 3:b1e385adea43 | 149 | } |
mbed_official | 3:b1e385adea43 | 150 | |
mbed_official | 3:b1e385adea43 | 151 | int main() |
mbed_official | 3:b1e385adea43 | 152 | { |
mbed_official | 13:c5f3a7d8764a | 153 | eventQueue.call_every(500, periodicCallback); |
mbed_official | 3:b1e385adea43 | 154 | |
mbed_official | 3:b1e385adea43 | 155 | BLE &ble = BLE::Instance(); |
mbed_official | 3:b1e385adea43 | 156 | ble.onEventsToProcess(scheduleBleEventsProcessing); |
mbed_official | 3:b1e385adea43 | 157 | ble.init(bleInitComplete); |
mbed_official | 3:b1e385adea43 | 158 | |
mbed_official | 13:c5f3a7d8764a | 159 | eventQueue.dispatch_forever(); |
mbed_official | 3:b1e385adea43 | 160 | |
mbed_official | 3:b1e385adea43 | 161 | return 0; |
mbed_official | 3:b1e385adea43 | 162 | } |