
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 and run the Eddystone beacon on one or more other devices.
- 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.
Revision 0:932f719b42d5, committed 2016-07-26
- Comitter:
- Vincent Coubard
- Date:
- Tue Jul 26 14:38:37 2016 +0100
- Child:
- 1:d839eae15f56
- Commit message:
- Update example at tag mbed-os-5.0.1-rc1
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.mbed Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,1 @@ +ROOT=.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.mbedignore Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,4 @@ +mbed-os/features/net/* +mbed-os/uvisor-mbed-lib/* +mbed-os/frameworks/* +mbed-os/features/mbedtls/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-events.lib Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-events.git#c621d7f80bb282ab1814e727f9c4f81a8538bf6f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,1 @@ +https://github.com/mbedmicro/mbed#5fea6e69ec1aec4c56852f2e959002dc815eb480
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,13 @@ +{ + "target_overrides": { + "K64F": { + "target.features_add": ["BLE"], + "target.extra_labels_add": ["ST_BLUENRG"], + "target.macros_add": ["IDB0XA1_D13_PATCH"] + }, + "NUCLEO_F401RE": { + "target.features_add": ["BLE"], + "target.extra_labels_add": ["ST_BLUENRG"] + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/module.json Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,16 @@ +{ + "name": "ble-eddystoneobserver", + "version": "0.0.1", + "description": "BLE EddystoneObserver example, building with yotta", + "licenses": [ + { + "url": "https://spdx.org/licenses/Apache-2.0", + "type": "Apache-2.0" + } + ], + "dependencies": { + "ble": "^2.0.0" + }, + "targetDependencies": {}, + "bin": "./source" +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readme.md Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,35 @@ +The Eddystone Observer scans for Eddystone beacons that are running the [Eddystone Service example](https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_EddystoneService) (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](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md). + +This sample requires two devices - one to [broadcast the beacon](https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_EddystoneService) 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 instructions for all samples are in the [main readme](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md). + +1. Build and run the [Eddystone beacon](https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_EddystoneService) on one or more other devices. + +1. 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: + +1. Check which serial port your Eddystone Observer is connected to. + +1. 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``. + +1. The Eddystone Observer should start printing URLs of nearby Eddystone beacons to the terminal.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shields/TARGET_ST_BLUENRG.lib Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/ble-x-nucleo-idb0xa1#947ff7cf03846721ec9970f16d373390cbf71f39
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main.cpp Tue Jul 26 14:38:37 2016 +0100 @@ -0,0 +1,164 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <mbed-events/events.h> +#include "mbed.h" +#include "ble/BLE.h" + +static const int URI_MAX_LENGTH = 18; // Maximum size of service data in ADV packets + +static EventQueue eventQueue( + /* event count */ 16 * /* event size */ 32 +); + +DigitalOut led1(LED1, 1); + +void periodicCallback(void) +{ + led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ +} + +void decodeURI(const uint8_t* uriData, const size_t uriLen) +{ + const char *prefixes[] = { + "http://www.", + "https://www.", + "http://", + "https://", + "urn:uuid:" + }; + const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *); + const char *suffixes[] = { + ".com/", + ".org/", + ".edu/", + ".net/", + ".info/", + ".biz/", + ".gov/", + ".com", + ".org", + ".edu", + ".net", + ".info", + ".biz", + ".gov" + }; + const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *); + + size_t index = 0; + + /* First byte is the URL Scheme. */ + if (uriData[index] < NUM_PREFIXES) { + printf("%s", prefixes[uriData[index]]); + index++; + } else { + printf("URL Scheme was not encoded!"); + return; + } + + /* From second byte onwards we can have a character or a suffix */ + while(index < uriLen) { + if (uriData[index] < NUM_SUFFIXES) { + printf("%s", suffixes[uriData[index]]); + } else { + printf("%c", uriData[index]); + } + index++; + } + + printf("\n\r"); +} + +/* + * This function is called every time we scan an advertisement. + */ +void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) +{ + struct AdvertisingData_t { + uint8_t length; /* doesn't include itself */ + GapAdvertisingData::DataType_t dataType; + uint8_t data[0]; + } AdvDataPacket; + + struct ApplicationData_t { + uint8_t applicationSpecificId[2]; + uint8_t frameType; + uint8_t advPowerLevels; + uint8_t uriData[URI_MAX_LENGTH]; + } AppDataPacket; + + const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE}; + const uint8_t FRAME_TYPE_URL = 0x10; + const uint8_t APPLICATION_DATA_OFFSET = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData); + + AdvertisingData_t *pAdvData; + size_t index = 0; + while(index < params->advertisingDataLen) { + pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index]; + if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) { + ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data; + if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) { + decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET); + break; + } + } + index += (pAdvData->length + 1); + } +} + +void onBleInitError(BLE &ble, ble_error_t error) +{ + /* Initialization error handling should go here */ +} + +void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) +{ + BLE& ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { + onBleInitError(ble, error); + return; + } + + if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { + return; + } + + ble.gap().setScanParams(1800 /* scan interval */, 1500 /* scan window */); + ble.gap().startScan(advertisementCallback); +} + +void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { + BLE &ble = BLE::Instance(); + eventQueue.post(Callback<void()>(&ble, &BLE::processEvents)); +} + +int main() +{ + eventQueue.post_every(periodicCallback, 500); + + BLE &ble = BLE::Instance(); + ble.onEventsToProcess(scheduleBleEventsProcessing); + ble.init(bleInitComplete); + + while (true) { + eventQueue.dispatch(); + } + + return 0; +}