Eddystone beacons broadcast a small amount of information, like URLs, to nearby BLE devices. The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_EddystoneService

Eddystone beacons broadcast a small amount of information, like URLs, to nearby BLE devices.

The Eddystone Beacon sample application runs in two stages:

  • On startup, the Configuration Service (which allows modification of the beacon runs for a user-defined period (default - 30 seconds).
  • When the Configuration Service period ends, the Eddystone Service broadcasts advertisement packets.

Running the application

Requirements

You should install the *Physical Web* application on your phone:

- Android version

- iOS version

Note: It is also possible to use a regular scanner to interract with your Eddystone beacon but it requires knowledge about BLE and Eddystone beacon specification out of the scope of this document.

Hardware requirements are in the main readme.

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-IDB05A1

List of components supporting Bluetooth Low Energy.

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

Working with nRF51-based 16K targets

Because of memory constraints, you can't use the SoftDevice 130 (S130) to build for nRF51-based 16K targets. If you are using these targets, then before building:

  1. Open the ``config.json`` file in this sample.
  2. Change ``soft device`` to ``S110``.
  3. Save.

You can now build for nRF51-based 16K targets.

Setting up the beacon

By default, the beacon directs to the url ``http://mbed.org``. You can change this to your own URL in two ways:

  • Manually edit the code in ``main.cpp`` in your copy of the sample.
  • Build and run the application's default code as explained in the building instructions. When the beacon starts up, the Configuration Service runs for 30 seconds (this is the default value; you can change it in ``main.cpp``). While the Configuration Service runs, you can use a BLE scanner on your phone to edit the values the service presents.

Checking for success

  • Build the application and install it on your board as explained in the building instructions.
  • Open the *Physical Web* application on your phone. It will start to search for nearby beacons.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneService/raw-file/4c8f8bf32a99/img/app_start.png

figure 1 Start of the *Physical Web* application version 0.1.856 on Android

  • When the beacon starts up, the Configuration Service runs for 30 seconds. During this time it is possible to change the URL advertised by the beacon. It is also important to note that during these 30 seconds, your device will not advertise any URL.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneService/raw-file/4c8f8bf32a99/img/open_configuration.png

figure 2 How to open the beacon configuration view using the *Physical Web* application version 0.1.856 on Android

  • Edit the URL advertised by your beacon.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneService/raw-file/4c8f8bf32a99/img/edit_url.png

figure 3 How to edit the URL advertised by your beacon using the *Physical Web* application version 0.1.856 on Android

  • Save the URL which will be advertised by your beacon.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneService/raw-file/4c8f8bf32a99/img/save_url.png

figure 4 How to save your beacon configuration and start advertising URL using the *Physical Web* application version 0.1.856 on Android.

  • Find your device; it should advertise the URL you have set.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-EddystoneService/raw-file/4c8f8bf32a99/img/result.png

figure 5 Display of URL advertised by your beacon using the *Physical Web* application version 0.1.856 on Android.

Note: You can use the Eddystone Observer sample instead of a phone application.

source/EddystoneService.h

Committer:
mbed_official
Date:
2017-09-08
Revision:
43:00b5f99e0a15
Parent:
12:b31d7c0f906c

File content as of revision 43:00b5f99e0a15:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 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.
 */

#ifndef __EDDYSTONESERVICE_H__
#define __EDDYSTONESERVICE_H__

#include <events/mbed_events.h>
#include "ble/BLE.h"
#include "EddystoneTypes.h"
#include "URLFrame.h"
#include "UIDFrame.h"
#include "TLMFrame.h"
#include <string.h>
#ifdef YOTTA_CFG_MBED_OS
    #include <mbed.h>
    #include "mbed-drivers/CircularBuffer.h"
#else
    #include "mbed.h"
    #include "CircularBuffer.h"
#endif

#ifndef YOTTA_CFG_EDDYSTONE_DEFAULT_URL_FRAME_INTERVAL
    #define YOTTA_CFG_EDDYSTONE_DEFAULT_URL_FRAME_INTERVAL 700
#endif

#ifndef YOTTA_CFG_EDDYSTONE_DEFAULT_UID_FRAME_INTERVAL
    #define YOTTA_CFG_EDDYSTONE_DEFAULT_UID_FRAME_INTERVAL 300
#endif

#ifndef YOTTA_CFG_EDDYSTONE_DEFAULT_TLM_FRAME_INTERVAL
    #define YOTTA_CFG_EDDYSTONE_DEFAULT_TLM_FRAME_INTERVAL 2000
#endif

#ifndef YOTTA_CFG_EDDYSTONE_DEFAULT_EDDYSTONE_URL_CONFIG_ADV_INTERVAL
    #define YOTTA_CFG_EDDYSTONE_DEFAULT_EDDYSTONE_URL_CONFIG_ADV_INTERVAL 1000
#endif

/**
 * This class implements the Eddystone-URL Config Service and the Eddystone
 * Protocol Specification as defined in the publicly available specification at
 * https://github.com/google/eddystone/blob/master/protocol-specification.md.
 */
class EddystoneService
{
public:
    /**
     * Total number of GATT Characteristics in the Eddystonei-URL Configuration
     * Service.
     */
    static const uint16_t TOTAL_CHARACTERISTICS = 9;

    /**
     * Default interval for advertising packets for the Eddystone-URL
     * Configuration Service.
     */
    static const uint32_t DEFAULT_CONFIG_PERIOD_MSEC    = YOTTA_CFG_EDDYSTONE_DEFAULT_EDDYSTONE_URL_CONFIG_ADV_INTERVAL;
    /**
     * Recommended interval for advertising packets containing Eddystone URL
     * frames.
     */
    static const uint16_t DEFAULT_URL_FRAME_PERIOD_MSEC = YOTTA_CFG_EDDYSTONE_DEFAULT_URL_FRAME_INTERVAL;
    /**
     * Recommended interval for advertising packets containing Eddystone UID
     * frames.
     */
    static const uint16_t DEFAULT_UID_FRAME_PERIOD_MSEC = YOTTA_CFG_EDDYSTONE_DEFAULT_UID_FRAME_INTERVAL;
    /**
     * Recommended interval for advertising packets containing Eddystone TLM
     * frames.
     */
    static const uint16_t DEFAULT_TLM_FRAME_PERIOD_MSEC = YOTTA_CFG_EDDYSTONE_DEFAULT_TLM_FRAME_INTERVAL;

    /**
     * Enumeration that defines the various operation modes of the
     * EddystoneService.
     *
     * @note The main app can change the mode of EddystoneService at any point
     *       of time by calling startConfigService() or startBeaconService().
     *       Resources from the previous mode will be freed.
     *
     * @note It is currently NOT possible to force EddystoneService back into
     *       EDDYSTONE_MODE_NONE.
     */
    enum OperationModes {
        /**
         * NONE: EddystoneService has been initialized but no memory has been
         * dynamically allocated. Additionally, no services are running
         * nothing is being advertised.
         */
        EDDYSTONE_MODE_NONE,
        /**
         * CONFIG: EddystoneService has been initialized, the configuration
         *         service started and memory has been allocated for BLE
         *         characteristics. Memory consumption peaks during CONFIG
         *         mode.
         */
        EDDYSTONE_MODE_CONFIG,
        /**
         * BEACON: Eddystone service is running as a beacon advertising URL,
         *         UID and/or TLM frames depending on how it is configured.
         */
        EDDYSTONE_MODE_BEACON
    };

    /**
     * Structure that encapsulates the Eddystone configuration parameters. This
     * structure is particularly useful when storing the parameters to
     * persistent storage.
     */
    struct EddystoneParams_t {
        /**
         * The value of the Eddystone-URL Configuration Service Lock State
         * characteristic.
         */
        bool             lockState;
        /**
         * The value of the Eddystone-URL Configuration Service Lock
         * characteristic that can be used to lock the beacon and set the
         * single-use lock-code.
         */
        Lock_t           lock;
        /**
         * The value of the Eddystone-URL Configuration Service Unlock
         * characteristic that can be used to unlock the beacon and clear the
         * single-use lock-code.
         */
        Lock_t           unlock;
        /**
         * The value of the Eddystone-URL Configuration Service Flags
         * characteristic. This value is currently fixed to 0x10.
         */
        uint8_t          flags;
        /**
         * The value of the Eddystone-URL Configuration Service Advertised TX
         * Power Levels characteristic that is an array of bytes whose values
         * are put into the advertising packets when in EDDYSTONE_BEACON_MODE.
         *
         * @note These are not the same values set internally into the radio tx
         *       power.
         */
        PowerLevels_t    advPowerLevels;
        /**
         * The value of the Eddystone-URL Configuration Service TX Power Mode
         * characteristic. This value is an index into the
         * EddystoneParams_t::advPowerLevels array.
         */
        uint8_t          txPowerMode;
        /**
         * The value of the Eddystone-URL Configuration Service Beacon Period
         * characteristic that is the interval (in milliseconds) of the
         * Eddystone-URL frames.
         *
         * @note A value of zero disables Eddystone-URL frame trasmissions.
         */
        uint16_t         urlFramePeriod;
        /**
         * The configured interval (in milliseconds) of the Eddystone-UID
         * frames.
         *
         * @note A value of zero disables Eddystone-UID frame transmissions.
         *
         * @note Currently it is only possible to modify this value by using
         *       the setUIDFrameAdvertisingInterval() API.
         */
        uint16_t         uidFramePeriod;
        /**
         * The configured interval (in milliseconds) of the Eddystone-TLM
         * frames.
         *
         * @note A value of zero disables Eddystone-TLM frame transmissions.
         *
         * @note Currently it is only possible to modify this value by using
         *       the setTLMFrameAdvertisingInterval() API.
         */
        uint16_t         tlmFramePeriod;
        /**
         * The configured version of the Eddystone-TLM frames.
         */
        uint8_t          tlmVersion;
        /**
         * The length of the encoded URL in EddystoneParams_t::urlData used
         * within Eddystone-URL frames.
         */
        uint8_t          urlDataLength;
        /**
         * The value of the Eddystone-URL Configuration Service URI Data
         * characteristic that contains an encoded URL as described in the
         * Eddystone Specification at
         * https://github.com/google/eddystone/blob/master/eddystone-url/README.md#eddystone-url-http-url-encoding.
         */
        UrlData_t        urlData;
        /**
         * The configured 10-byte namespace ID in Eddystone-UID frames that may
         * be used to group a particular set of beacons.
         */
        UIDNamespaceID_t uidNamespaceID;
        /**
         * The configured 6-byte instance ID that may be used to uniquely
         * identify individual devices in a group.
         */
        UIDInstanceID_t  uidInstanceID;
    };

    /**
     * Enumeration that defines the various error codes for EddystoneService.
     */
    enum EddystoneError_t {
        /**
         * No error occurred.
         */
        EDDYSTONE_ERROR_NONE,
        /**
         * The supplied advertising interval is invalid. The interval may be
         * too short/long for the type of advertising packets being broadcast.
         *
         * @note For the acceptable range of advertising interval refer to the
         *       following functions in mbed BLE API:
         *       - Gap::getMinNonConnectableAdvertisingInterval()
         *       - Gap::getMinAdvertisingInterval()
         *       - Gap::getMaxAdvertisingInterval()
         */
        EDDYSTONE_ERROR_INVALID_ADVERTISING_INTERVAL,
        /**
         * The result of executing a call when the the EddystoneService is in
         * the incorrect operation mode.
         */
        EDDYSTONE_ERROR_INVALID_STATE
    };

    /**
     * Enumeration that defines the available frame types within Eddystone
     * advertising packets.
     */
    enum FrameType {
        /**
         * The Eddystone-URL frame. Refer to
         * https://github.com/google/eddystone/tree/master/eddystone-url.
         */
        EDDYSTONE_FRAME_URL,
        /**
         * The Eddystone-URL frame. Refer to
         * https://github.com/google/eddystone/tree/master/eddystone-uid.
         */
        EDDYSTONE_FRAME_UID,
        /**
         * The Eddystone-URL frame. Refer to
         * https://github.com/google/eddystone/tree/master/eddystone-tlm.
         */
        EDDYSTONE_FRAME_TLM,
        /**
         * The total number Eddystone frame types.
         */
        NUM_EDDYSTONE_FRAMES
    };

    /**
     * The size of the advertising frame queue.
     *
     * @note [WARNING] If the advertising rate for any of the frames is higher
     *       than 100ms then frames will be dropped, this value must be
     *       increased.
     */
    static const uint16_t ADV_FRAME_QUEUE_SIZE = NUM_EDDYSTONE_FRAMES;


    /**
     * Constructor that Initializes the EddystoneService using parameters from
     * the supplied EddystoneParams_t. This constructor is particularly useful
     * for configuring the EddystoneService with parameters fetched from
     * persistent storage.
     *
     * @param[in] bleIn
     *              The BLE instance.
     * @param[in] paramIn
     *              The input Eddystone configuration parameters.
     * @param[in] radioPowerLevelsIn
     *              The value set internally into the radion tx power.
     * @param[in] advConfigIntervalIn
     *              The advertising interval for advertising packets of the
     *              Eddystone-URL Configuration Service.
     */
    EddystoneService(BLE                 &bleIn,
                     EddystoneParams_t   &paramsIn,
                     const PowerLevels_t &radioPowerLevelsIn,
                     events::EventQueue& eventQueue,
                     uint32_t            advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);

    /**
     * Constructor to initialize the EddystoneService to default values.
     *
     * @param[in] bleIn
     *              The BLE instance.
     * @param[in] advPowerLevelsIn
     *              The value of the Eddystone-URL Configuration Service TX
     *              Power Mode characteristic.
     * @param[in] radioPowerLevelsIn
     *              The value set internally into the radion tx power.
     * @param[in] advConfigIntervalIn
     *              The advertising interval for advertising packets of the
     *              Eddystone-URL Configuration Service.
     *
     * @note When using this constructor the setURLData(), setTMLData() and
     *       setUIDData() functions must be called to initialize
     *       EddystoneService manually.
     */
    EddystoneService(BLE                 &bleIn,
                     const PowerLevels_t &advPowerLevelsIn,
                     const PowerLevels_t &radioPowerLevelsIn,
                     EventQueue          &eventQueue,
                     uint32_t            advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);

    /**
     * Setup callback to update BatteryVoltage in Eddystone-TLM frames
     *
     * @param[in] tlmBatteryVoltageCallbackIn
     *              The callback being registered.
     */
    void onTLMBatteryVoltageUpdate(TlmUpdateCallback_t tlmBatteryVoltageCallbackIn);

    /**
     * Setup callback to update BeaconTemperature in Eddystone-TLM frames
     *
     * @param[in] tlmBeaconTemperatureCallbackIn
     *              The callback being registered.
     */
    void onTLMBeaconTemperatureUpdate(TlmUpdateCallback_t tlmBeaconTemperatureCallbackIn);

    /**
     * Set the Eddystone-TLM frame version. The other components of
     * Eddystone-TLM frames are updated just before the frame is broadcast
     * since information such as beacon temperature and time since boot changes
     * relatively quickly.
     *
     * @param[in] tlmVersionIn
     *              The Eddyston-TLM version to set.
     */
    void setTLMData(uint8_t tlmVersionIn = 0);

    /**
     * Set the Eddystone-URL frame URL data.
     *
     * @param[in] urlDataIn
     *              A pointer to the plain null terminated string representing
     *              a URL to be encoded.
     */
    void setURLData(const char *urlDataIn);

    /**
     * Set the Eddystone-UID namespace and instance IDs.
     *
     * @param[in] uidNamespaceIDIn
     *              The new Eddystone-UID namespace ID.
     * @param[in] uidInstanceIDIn
     *              The new Eddystone-UID instance ID.
     */
    void setUIDData(const UIDNamespaceID_t &uidNamespaceIDIn, const UIDInstanceID_t &uidInstanceIDIn);

    /**
     * Set the interval of the Eddystone-URL frames.
     *
     * @param[in] urlFrameIntervalIn
     *              The new frame interval in milliseconds. The default is
     *              DEFAULT_URL_FRAME_PERIOD_MSEC.
     *
     * @note A value of zero disables Eddystone-URL frame transmissions.
     */
    void setURLFrameAdvertisingInterval(uint16_t urlFrameIntervalIn = DEFAULT_URL_FRAME_PERIOD_MSEC);

    /**
     * Set the interval of the Eddystone-UID frames.
     *
     * @param[in] uidFrameIntervalIn
     *              The new frame interval in milliseconds. The default is
     *              DEFAULT_UID_FRAME_PERIOD_MSEC.
     *
     * @note A value of zero disables Eddystone-UID frame transmissions.
     */
    void setUIDFrameAdvertisingInterval(uint16_t uidFrameIntervalIn = DEFAULT_UID_FRAME_PERIOD_MSEC);

    /**
     * Set the interval for the Eddystone-TLM frames.
     *
     * @param[in] tlmFrameIntervalIn
     *              The new frame interval in milliseconds. The default is
     *              DEFAULT_TLM_FRAME_PERIOD_MSEC.
     *
     * @note A value of zero desables Eddystone-TLM frames.
     */
    void setTLMFrameAdvertisingInterval(uint16_t tlmFrameIntervalIn = DEFAULT_TLM_FRAME_PERIOD_MSEC);

    /**
     * Change the EddystoneService OperationMode to EDDYSTONE_MODE_CONFIG.
     *
     * @retval EDDYSTONE_ERROR_NONE if the operation succeeded.
     * @retval EDDYSONE_ERROR_INVALID_ADVERTISING_INTERVAL if the configured
     *         advertising interval is zero.
     *
     * @note If EddystoneService was previously in EDDYSTONE_MODE_BEACON, then
     *       the resources allocated to that mode of operation such as memory
     *       are freed and the BLE instance shutdown before the new operation
     *       mode is configured.
     */
    EddystoneError_t startConfigService(void);

    /**
     * Change the EddystoneService OperationMode to EDDYSTONE_MODE_BEACON.
     *
     * @retval EDDYSTONE_ERROR_NONE if the operation succeeded.
     * @retval EDDYSONE_ERROR_INVALID_ADVERTISING_INTERVAL if the configured
     *         advertising interval is zero.
     *
     * @note If EddystoneService was previously in EDDYSTONE_MODE_CONFIG, then
     *       the resources allocated to that mode of operation such as memory
     *       are freed and the BLE instance shutdown before the new operation
     *       mode is configured.
     */
    EddystoneError_t startBeaconService(void);

    /**
     * Change the EddystoneService OperationMode to EDDYSTONE_MODE_NONE.
     *
     * @retval EDDYSTONE_ERROR_NONE if the operation succeeded.
     * @retval EDDYSTONE_ERROR_INVALID_STATE if the state of the
     *         EddystoneService already is EDDYSTONE_MODE_NONE.
     *
     * @note If EddystoneService was previously in EDDYSTONE_MODE_CONFIG or
     *       EDDYSTONE_MODE_BEACON, then the resources allocated to that mode
     *       of operation such as memory are freed and the BLE instance
     *       shutdown before the new operation mode is configured.
     */
    EddystoneError_t stopCurrentService(void);

    /**
     * Set the Comple Local Name for the BLE device. This not only updates
     * the value of the Device Name Characteristic, it also updates the scan
     * response payload if the EddystoneService is currently in
     * EDDYSTONE_MODE_CONFIG.
     *
     * @param[in] deviceNameIn
     *              A pointer to a null terminated string containing the new
     *              device name.
     *
     * @return BLE_ERROR_NONE if the name was successfully set. Otherwise an
     *         appropriate error.
     *
     * @note EddystoneService does not make an internal copy of the string
     *       pointed to by @p deviceNameIn. Therefore, the user is responsible
     *       for ensuring that the string persists in memory as long as it is
     *       in use by the EddystoneService.
     *
     * @note The device name is not considered an Eddystone configuration
     *       parameter; therefore, it is not contained within the
     *       EddystoneParams_t structure and must be stored to persistent
     *       storage separately.
     */
    ble_error_t setCompleteDeviceName(const char *deviceNameIn);

    /**
     * Get the Eddystone Configuration parameters. This is particularly useful
     * for storing the configuration parameters in persistent storage.
     * It is not the responsibility of the Eddystone implementation to store
     * the configured parameters in persistent storage since this is
     * platform-specific.
     *
     * @param[out] params
     *              A reference to an EddystoneParams_t structure with the
     *              configured parameters of the EddystoneService.
     */
    void getEddystoneParams(EddystoneParams_t &params);

private:
    /**
     * Helper function used only once during construction of an
     * EddystoneService object to avoid duplicated code.
     *
     * @param[in] advPowerLevelsIn
     *              The value of the Eddystone-URL Configuration Service TX
     *              Power Mode characteristic.
     * @param[in] radioPowerLevelsIn
     *              The value set internally into the radion tx power.
     * @param[in] advConfigIntervalIn
     *              The advertising interval for advertising packets of the
     *              Eddystone-URL Configuration Service.
     */
    void eddystoneConstructorHelper(const PowerLevels_t &advPowerLevelsIn,
                                    const PowerLevels_t &radioPowerLevelsIn,
                                    uint32_t            advConfigIntervalIn);

    /**
     * Helper funtion that will be registered as an initialization complete
     * callback when BLE::shutdown() is called. This is necessary when changing
     * Eddystone OperationModes. Once the BLE initialization is complete, this
     * callback will initialize all the necessary resource to operate
     * Eddystone service in the selected mode.
     *
     * @param[in] initContext
     *              The context provided by BLE API when initialization
     *              completes.
     */
    void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext);

    /**
     * When in EDDYSTONE_MODE_BEACON this function is called to update the
     * advertising payload to contain the information related to the specified
     * FrameType.
     *
     * @param[in] frameType
     *              The frame to populate the advertising payload with.
     */
    void swapAdvertisedFrame(FrameType frameType);

    /**
     * Helper function that manages the BLE radio that is used to broadcast
     * advertising packets. To advertise frames at the configured intervals
     * the actual advertising interval of the BLE instance is set to the value
     * returned by Gap::getMaxAdvertisingInterval() from the BLE API. When a
     * frame needs to be advertised, the enqueueFrame() callbacks add the frame
     * type to the advFrameQueue and post a manageRadio() callback. When the
     * callback is executed, the frame is dequeued and advertised using the
     * radio (by updating the advertising payload). manageRadio() also posts a
     * callback to itself Gap::getMinNonConnectableAdvertisingInterval()
     * milliseconds later. In this callback, manageRadio() will advertise the
     * next frame in the queue, yet if there is none it calls
     * Gap::stopAdvertising() and does not post any further callbacks.
     */
    void manageRadio(void);

    /**
     * Regular callbacks posted at the rate of urlFramePeriod, uidFramePeriod
     * and tlmFramePeriod milliseconds enqueue frames to be advertised. If the
     * frame queue is currently empty, then this function directly calls
     * manageRadio() to broadcast the required FrameType.
     *
     * @param[in] frameType
     *              The FrameType to enqueue for broadcasting.
     */
    void enqueueFrame(FrameType frameType);

    /**
     * Helper function that updates the advertising payload when in
     * EDDYSTONE_MODE_BEACON to contain a new frame.
     *
     * @param[in] rawFrame
     *              The raw bytes of the frame to advertise.
     * @param[in] rawFrameLength
     *              The length in bytes of the array pointed to by @p rawFrame.
     */
    void updateAdvertisementPacket(const uint8_t* rawFrame, size_t rawFrameLength);

    /**
     * Helper function that updates the information in the Eddystone-TLM frames
     * Internally, this function executes the registered callbacks to update
     * beacon Battery Voltage and Temperature (if available). Furthermore, this
     * function updates the raw frame data. This operation must be done fairly
     * often because the Eddystone-TLM frame Time Since Boot must have a 0.1
     * seconds resolution according to the Eddystone specification.
     */
    void updateRawTLMFrame(void);

    /**
     * Initialize the resources required when switching to
     * EDDYSTONE_MODE_BEACON.
     */
    void setupBeaconService(void);

    /**
     * Initialize the resources required when switching to
     * EDDYSTONE_MODE_CONFIG. This includes the GATT services and
     * characteristics required by the Eddystone-URL Configuration Service.
     */
    void setupConfigService(void);

    /**
     * Free the resources acquired by a call to setupConfigService().
     */
    void freeConfigCharacteristics(void);

    /**
     * Free the resources acquired by a call to setupBeaconService() and
     * cancel all pending callbacks that operate the radio and frame queue.
     *
     * @note This call will not modify the current state of the BLE device.
     *       EddystoneService::stopBeaconService should only be called after
     *       a call to BLE::shutdown().
     */
    void stopBeaconService(void);

    /**
     * Helper function used to update the GATT database following any
     * change to the internal state of the service object.
     */
    void updateCharacteristicValues(void);

    /**
     * Setup the payload of advertising packets for Eddystone-URL Configuration
     * Service.
     */
    void setupEddystoneConfigAdvertisements(void);

    /**
     * Helper function to setup the payload of scan response packets for
     * Eddystone-URL Configuration Service.
     */
    void setupEddystoneConfigScanResponse(void);

    /**
     * Callback registered to the BLE API to authorize write operations to the
     * Eddystone-URL Configuration Service Lock characteristic.
     *
     * @param[in] authParams
     *              Write authentication information.
     */
    void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);

    /**
     * Callback registered to the BLE API to authorize write operations to the
     * Eddystone-URL Configuration Service Unlock characteristic.
     *
     * @param[in] authParams
     *              Write authentication information.
     */
    void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);

    /**
     * Callback registered to the BLE API to authorize write operations to the
     * Eddystone-URL Configuration Service URI Data characteristic.
     *
     * @param[in] authParams
     *              Write authentication information.
     */
    void urlDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams);

    void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams);

    /**
     * Callback registered to the BLE API to authorize write operations to the
     * following Eddystone-URL Configuration Service characteristics:
     * - Flags
     * - Beacon Period
     * - Reset
     *
     * @param[in] authParams
     *              Write authentication information.
     */
    template <typename T>
    void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams);

    /**
     * This callback is invoked when a GATT client attempts to modify any of the
     * characteristics of this service. Attempts to do so are also applied to
     * the internal state of this service object.
     *
     * @param[in] writeParams
     *              Information about the values that are being written.
     */
    void onDataWrittenCallback(const GattWriteCallbackParams *writeParams);

    /**
     * Correct the advertising interval for non-connectable packets.
     *
     * @param[in] beaconPeriodIn
     *              The input interval in milliseconds.
     *
     * @return The corrected interval in milliseconds.
     *
     * @note For the acceptable range of advertising interval refer to the
     *       following functions in mbed BLE API:
     *       - Gap::getMinNonConnectableAdvertisingInterval()
     *       - Gap::getMaxAdvertisingInterval()
     */
    uint16_t correctAdvertisementPeriod(uint16_t beaconPeriodIn) const;

    /**
     * BLE instance that EddystoneService will operate on.
     */
    BLE                                                             &ble;
    /**
     * The advertising interval for Eddystone-URL Config Service advertising
     * packets.
     */
    uint32_t                                                        advConfigInterval;
    /**
     * Current EddystoneServce operation mode.
     */
    uint8_t                                                         operationMode;

    /**
     * Encapsulation of a URL frame.
     */
    URLFrame                                                        urlFrame;
    /**
     * Encapsulation of a UID frame.
     */
    UIDFrame                                                        uidFrame;
    /**
     * Encapsulation of a TLM frame.
     */
    TLMFrame                                                        tlmFrame;

    /**
     * The value set internally into the radion tx power.
     */
    PowerLevels_t                                                   radioPowerLevels;
    /**
     * An array containing possible values for advertised tx power in Eddystone
     * frames. Also, the value of the Eddystone-URL Configuration Service
     * Advertised TX Power Levels characteristic.
     */
    PowerLevels_t                                                   advPowerLevels;
    /**
     * The value of the Eddystone-URL Configuration Service Lock State
     * characteristic.
     */
    bool                                                            lockState;
    /**
     * The value of the Eddystone-URL Configuration Service reset
     * characteristic.
     */
    bool                                                            resetFlag;
    /**
     * The value of the Eddystone-URL Configuration Service Lock
     * characteristic.
     */
    Lock_t                                                          lock;
    /**
     * The value of the Eddystone-URL Configuration Service Unlock
     * characteristic.
     */
    Lock_t                                                          unlock;
    /**
     * The value of the Eddystone-URL Configuration Service Flags
     * characteristic.
     */
    uint8_t                                                         flags;
    /**
     * The value of the Eddystone-URL Configuration Service TX Power Mode
     * characteristic.
     */
    uint8_t                                                         txPowerMode;
    /**
     * The value of the Eddystone-URL Configuration Service Beacon Period
     * characteristic. Also, the advertising interval (in milliseconds) of
     * Eddystone-URL frames.
     */
    uint16_t                                                        urlFramePeriod;
    /**
     * The advertising interval (in milliseconds) of Eddystone-UID frames.
     */
    uint16_t                                                        uidFramePeriod;
    /**
     * The advertising interval (in milliseconds) of Eddystone-TLM frames.
     */
    uint16_t                                                        tlmFramePeriod;

    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Lock State characteristic.
     */
    ReadOnlyGattCharacteristic<bool>                                *lockStateChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Lock characteristic.
     */
    WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>       *lockChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Unlock characteristic.
     */
    WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>       *unlockChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service URI Data characteristic.
     */
    GattCharacteristic                                              *urlDataChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Flags characteristic.
     */
    ReadWriteGattCharacteristic<uint8_t>                            *flagsChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Advertised TX Power Levels characteristic.
     */
    ReadWriteArrayGattCharacteristic<int8_t, sizeof(PowerLevels_t)> *advPowerLevelsChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service TX Power Mode characteristic.
     */
    ReadWriteGattCharacteristic<uint8_t>                            *txPowerModeChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Beacon Period characteristic.
     */
    ReadWriteGattCharacteristic<uint16_t>                           *beaconPeriodChar;
    /**
     * Pointer to the BLE API characteristic encapsulation for the Eddystone-URL
     * Configuration Service Reset characteristic.
     */
    WriteOnlyGattCharacteristic<bool>                               *resetChar;

    /**
     * Pointer to the raw bytes that will be used to populate Eddystone-URL
     * frames.
     */
    uint8_t                                                         *rawUrlFrame;
    /**
     * Pointer to the raw bytes that will be used to populate Eddystone-UID
     * frames.
     */
    uint8_t                                                         *rawUidFrame;
    /**
     * Pointer to the raw bytes that will be used to populate Eddystone-TLM
     * frames.
     */
    uint8_t                                                         *rawTlmFrame;

    /**
     * Circular buffer that represents of Eddystone frames to be advertised.
     */
    CircularBuffer<FrameType, ADV_FRAME_QUEUE_SIZE>                 advFrameQueue;

    /**
     * The registered callback to update the Eddystone-TLM frame Battery
     * Voltage.
     */
    TlmUpdateCallback_t                                             tlmBatteryVoltageCallback;
    /**
     * The registered callback to update the Eddystone-TLM frame Beacon
     * Temperature.
     */
    TlmUpdateCallback_t                                             tlmBeaconTemperatureCallback;

    /**
     * Timer that keeps track of the time since boot.
     */
    Timer                                                           timeSinceBootTimer;

    /**
     * Callback handle to keep track of periodic
     * enqueueFrame(EDDYSTONE_FRAME_UID) callbacks that populate the
     * advFrameQueue.
     */
    int                                                             uidFrameCallbackHandle;
    /**
     * Minar callback handle to keep track of periodic
     * enqueueFrame(EDDYSTONE_FRAME_URL) callbacks that populate the
     * advFrameQueue.
     */
    int                                                             urlFrameCallbackHandle;
    /**
     * Minar callback handle to keep track of periodic
     * enqueueFrame(EDDYSTONE_FRAME_TLM) callbacks that populate the
     * advFrameQueue.
     */
    int                                                             tlmFrameCallbackHandle;
    /**
     * Minar callback handle to keep track of manageRadio() callbacks.
     */
    int                                                             radioManagerCallbackHandle;

    /**
     * GattCharacteristic table used to populate the BLE ATT table in the
     * GATT Server.
     */
    GattCharacteristic                                              *charTable[TOTAL_CHARACTERISTICS];

    /**
     * Pointer to the device name currently being used.
     */
    const char                                                      *deviceName;

    /**
     * Event queue used to post callbacks s
     */
    EventQueue& eventQueue;
};

#endif  /* __EDDYSTONESERVICE_H__ */