The Eddystone Observer scans for Eddystone beacons that are running the Eddystone Service example (see there for general information about Eddystone beacons). It reads the advertising packets broadcast by these beacons, and prints a human-readable version of the advertised URLs to the serial console. he canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_EddystoneObserver

The Eddystone Observer scans for Eddystone beacons that are running the Eddystone Service example (see there for general information about Eddystone beacons). It reads the advertising packets broadcast by these beacons, and prints a human-readable version of the advertised URLs to the serial console.

Running the application

Requirements

General hardware information is in the main readme.

This sample requires two devices - one to broadcast the beacon and one to scan for the broadcast. If you have more devices, you can use them as extra beacons.

You need a terminal program to listen to the observer's output through a serial port. You can download one, for example:

  • Tera Term for Windows.
  • CoolTerm for Mac OS X.
  • GNU Screen for Linux.

Building instructions

Building with mbed CLI

If you'd like to use mbed CLI to build this, then you should refer to the main readme. The instructions here relate to using the developer.mbed.org Online Compiler

In order to build this example in the mbed Online Compiler, first import the example using the ‘Import’ button on the right hand side.

Next, select a platform to build for. This must either be a platform that supports BLE, for example the NRF51-DK, or one of the following:

List of platforms supporting Bluetooth Low Energy

Or you must also add a piece of hardware and the supporting library that includes a Bluetooth Low Energy driver for that hardware, for example the K64F or NUCLEO_F401RE with the X-NUCLEO-IDB04A1

Once you have selected your platform, compile the example and drag and drop the resulting binary onto your board.

For general instructions on using the mbed Online Compiler, please see the mbed Handbook

  • Build the Eddystone Observer application and install it on your board as explained in the building instructions. Leave the board connected to your computer.

Checking console output

To see the application's output:

  • Check which serial port your Eddystone Observer is connected to.
  • Run a terminal program with the correct serial port and the baud rate set to 9600. For example, to use GNU Screen, run: ``screen /dev/tty.usbmodem1412 9600``.
  • The Eddystone Observer should start printing URLs of nearby Eddystone beacons to the terminal.
Committer:
mbed_official
Date:
Fri Sep 08 14:45:27 2017 +0100
Revision:
42:092c08942a29
Parent:
29:083b9a2cb114
Merge pull request #102 from adbridge/master

Updating mbed-os to mbed-os-5.5.6
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Who changed what in which revision?

UserRevisionLine numberNew 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 *)&params->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 }