The eddystone config service allows you to configure the eddystone frame data over BLE for a set period of time and then starts an eddystone beacon. This example defaults to 30 seconds of config time.

Dependencies:   BLE_API mbed nRF51822 X_NUCLEO_IDB0XA1

Fork of BLE_EddystoneBeaconConfigServiceRelease by Austin Blackstone

This is the eddystone config service. This code starts up and for a user configured time period (default 30 seconds) will advertise the configuration service.

The configuration service allows for modifying various frames of the eddystone specification.

For more details on the Configuration Service please see : https://github.com/google/eddystone/blob/master/eddystone-url/docs/config-service-spec.md

Committer:
andresag
Date:
Tue Nov 24 10:04:38 2015 +0000
Revision:
3:d0f3e00cbfdf
Update example to use new Eddystone implementation NOT included in ble/services.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andresag 3:d0f3e00cbfdf 1 /* mbed Microcontroller Library
andresag 3:d0f3e00cbfdf 2 * Copyright (c) 2006-2015 ARM Limited
andresag 3:d0f3e00cbfdf 3 *
andresag 3:d0f3e00cbfdf 4 * Licensed under the Apache License, Version 2.0 (the "License");
andresag 3:d0f3e00cbfdf 5 * you may not use this file except in compliance with the License.
andresag 3:d0f3e00cbfdf 6 * You may obtain a copy of the License at
andresag 3:d0f3e00cbfdf 7 *
andresag 3:d0f3e00cbfdf 8 * http://www.apache.org/licenses/LICENSE-2.0
andresag 3:d0f3e00cbfdf 9 *
andresag 3:d0f3e00cbfdf 10 * Unless required by applicable law or agreed to in writing, software
andresag 3:d0f3e00cbfdf 11 * distributed under the License is distributed on an "AS IS" BASIS,
andresag 3:d0f3e00cbfdf 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
andresag 3:d0f3e00cbfdf 13 * See the License for the specific language governing permissions and
andresag 3:d0f3e00cbfdf 14 * limitations under the License.
andresag 3:d0f3e00cbfdf 15 */
andresag 3:d0f3e00cbfdf 16
andresag 3:d0f3e00cbfdf 17 #ifndef __EDDYSTONESERVICE_H__
andresag 3:d0f3e00cbfdf 18 #define __EDDYSTONESERVICE_H__
andresag 3:d0f3e00cbfdf 19
andresag 3:d0f3e00cbfdf 20 #include "ble/BLE.h"
andresag 3:d0f3e00cbfdf 21 #include "EddystoneTypes.h"
andresag 3:d0f3e00cbfdf 22 #include "URLFrame.h"
andresag 3:d0f3e00cbfdf 23 #include "UIDFrame.h"
andresag 3:d0f3e00cbfdf 24 #include "TLMFrame.h"
andresag 3:d0f3e00cbfdf 25 #include <string.h>
andresag 3:d0f3e00cbfdf 26 #ifdef YOTTA_CFG_MBED_OS
andresag 3:d0f3e00cbfdf 27 #include "mbed-drivers/mbed.h"
andresag 3:d0f3e00cbfdf 28 #else
andresag 3:d0f3e00cbfdf 29 #include "mbed.h"
andresag 3:d0f3e00cbfdf 30 #endif
andresag 3:d0f3e00cbfdf 31
andresag 3:d0f3e00cbfdf 32 class EddystoneService
andresag 3:d0f3e00cbfdf 33 {
andresag 3:d0f3e00cbfdf 34 public:
andresag 3:d0f3e00cbfdf 35 static const uint16_t TOTAL_CHARACTERISTICS = 9;
andresag 3:d0f3e00cbfdf 36
andresag 3:d0f3e00cbfdf 37 static const uint32_t DEFAULT_CONFIG_PERIOD_MSEC = 1000;
andresag 3:d0f3e00cbfdf 38 static const uint16_t DEFAULT_BEACON_PERIOD_MSEC = 1000;
andresag 3:d0f3e00cbfdf 39
andresag 3:d0f3e00cbfdf 40 /* Operation modes of the EddystoneService:
andresag 3:d0f3e00cbfdf 41 * NONE: EddystoneService has been initialised but no memory has been
andresag 3:d0f3e00cbfdf 42 * dynamically allocated. Additionally, no services are running
andresag 3:d0f3e00cbfdf 43 * nothing is being advertised.
andresag 3:d0f3e00cbfdf 44 * CONFIG: EddystoneService has been initialised, the configuration
andresag 3:d0f3e00cbfdf 45 * service started and memory has been allocated for BLE
andresag 3:d0f3e00cbfdf 46 * characteristics. Memory consumption peaks during CONFIG
andresag 3:d0f3e00cbfdf 47 * mode.
andresag 3:d0f3e00cbfdf 48 * BEACON: Eddystone service is running as a beacon advertising URL,
andresag 3:d0f3e00cbfdf 49 * UID and/or TLM frames depending on how it is configured.
andresag 3:d0f3e00cbfdf 50 * Note: The main app can change the mode of EddystoneService at any point
andresag 3:d0f3e00cbfdf 51 * of time by calling startConfigService() or startBeaconService().
andresag 3:d0f3e00cbfdf 52 * Resources from the previous mode will be freed. It is currently NOT
andresag 3:d0f3e00cbfdf 53 * possible to force EddystoneService back into MODE_NONE.
andresag 3:d0f3e00cbfdf 54 */
andresag 3:d0f3e00cbfdf 55 enum OperationModes {
andresag 3:d0f3e00cbfdf 56 EDDYSTONE_MODE_NONE,
andresag 3:d0f3e00cbfdf 57 EDDYSTONE_MODE_CONFIG,
andresag 3:d0f3e00cbfdf 58 EDDYSTONE_MODE_BEACON
andresag 3:d0f3e00cbfdf 59 };
andresag 3:d0f3e00cbfdf 60
andresag 3:d0f3e00cbfdf 61 struct EddystoneParams_t {
andresag 3:d0f3e00cbfdf 62 bool lockState;
andresag 3:d0f3e00cbfdf 63 Lock_t lock;
andresag 3:d0f3e00cbfdf 64 Lock_t unlock;
andresag 3:d0f3e00cbfdf 65 uint8_t flags;
andresag 3:d0f3e00cbfdf 66 PowerLevels_t advPowerLevels;
andresag 3:d0f3e00cbfdf 67 uint8_t txPowerMode;
andresag 3:d0f3e00cbfdf 68 uint16_t beaconPeriod;
andresag 3:d0f3e00cbfdf 69 uint8_t tlmVersion;
andresag 3:d0f3e00cbfdf 70 uint8_t urlDataLength;
andresag 3:d0f3e00cbfdf 71 UrlData_t urlData;
andresag 3:d0f3e00cbfdf 72 UIDNamespaceID_t uidNamespaceID;
andresag 3:d0f3e00cbfdf 73 UIDInstanceID_t uidInstanceID;
andresag 3:d0f3e00cbfdf 74 };
andresag 3:d0f3e00cbfdf 75
andresag 3:d0f3e00cbfdf 76 enum EddystoneError_t {
andresag 3:d0f3e00cbfdf 77 EDDYSTONE_ERROR_NONE,
andresag 3:d0f3e00cbfdf 78 EDDYSTONE_ERROR_INVALID_BEACON_PERIOD,
andresag 3:d0f3e00cbfdf 79 EDDYSTONE_ERROR_INVALID_CONSEC_FRAMES,
andresag 3:d0f3e00cbfdf 80 EDDYSTONE_ERROR_INVALID_ADVERTISING_INTERVAL
andresag 3:d0f3e00cbfdf 81 };
andresag 3:d0f3e00cbfdf 82
andresag 3:d0f3e00cbfdf 83 enum FrameType {
andresag 3:d0f3e00cbfdf 84 EDDYSTONE_FRAME_URL,
andresag 3:d0f3e00cbfdf 85 EDDYSTONE_FRAME_UID,
andresag 3:d0f3e00cbfdf 86 EDDYSTONE_FRAME_TLM,
andresag 3:d0f3e00cbfdf 87 NUM_EDDYSTONE_FRAMES
andresag 3:d0f3e00cbfdf 88 };
andresag 3:d0f3e00cbfdf 89
andresag 3:d0f3e00cbfdf 90 /* Initialise the EddystoneService using parameters from persistent storage */
andresag 3:d0f3e00cbfdf 91 EddystoneService(BLE &bleIn,
andresag 3:d0f3e00cbfdf 92 EddystoneParams_t &paramsIn,
andresag 3:d0f3e00cbfdf 93 const PowerLevels_t &advPowerLevelsIn,
andresag 3:d0f3e00cbfdf 94 const PowerLevels_t &radioPowerLevelsIn,
andresag 3:d0f3e00cbfdf 95 uint32_t advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);
andresag 3:d0f3e00cbfdf 96
andresag 3:d0f3e00cbfdf 97 /* When using this constructor we need to call setURLData,
andresag 3:d0f3e00cbfdf 98 * setTMLData and setUIDData to initialise values manually
andresag 3:d0f3e00cbfdf 99 */
andresag 3:d0f3e00cbfdf 100 EddystoneService(BLE &bleIn,
andresag 3:d0f3e00cbfdf 101 const PowerLevels_t &advPowerLevelsIn,
andresag 3:d0f3e00cbfdf 102 const PowerLevels_t &radioPowerLevelsIn,
andresag 3:d0f3e00cbfdf 103 uint32_t advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);
andresag 3:d0f3e00cbfdf 104
andresag 3:d0f3e00cbfdf 105 /* Setup callback to update BatteryVoltage in TLM frame */
andresag 3:d0f3e00cbfdf 106 void onTLMBatteryVoltageUpdate(TlmUpdateCallback_t tlmBatteryVoltageCallbackIn);
andresag 3:d0f3e00cbfdf 107
andresag 3:d0f3e00cbfdf 108 /* Setup callback to update BeaconTemperature in TLM frame */
andresag 3:d0f3e00cbfdf 109 void onTLMBeaconTemperatureUpdate(TlmUpdateCallback_t tlmBeaconTemperatureCallbackIn);
andresag 3:d0f3e00cbfdf 110
andresag 3:d0f3e00cbfdf 111 void setTLMData(uint8_t tlmVersionIn = 0);
andresag 3:d0f3e00cbfdf 112
andresag 3:d0f3e00cbfdf 113 void setURLData(const char *urlDataIn);
andresag 3:d0f3e00cbfdf 114
andresag 3:d0f3e00cbfdf 115 void setUIDData(const UIDNamespaceID_t *uidNamespaceIDIn, const UIDInstanceID_t *uidInstanceIDIn);
andresag 3:d0f3e00cbfdf 116
andresag 3:d0f3e00cbfdf 117 EddystoneError_t startConfigService(void);
andresag 3:d0f3e00cbfdf 118
andresag 3:d0f3e00cbfdf 119 EddystoneError_t startBeaconService(uint16_t consecUrlFramesIn = 2, uint16_t consecUidFramesIn = 2, uint16_t consecTlmFramesIn = 2);
andresag 3:d0f3e00cbfdf 120
andresag 3:d0f3e00cbfdf 121 /* It is not the responsibility of the Eddystone implementation to store
andresag 3:d0f3e00cbfdf 122 * the configured parameters in persistent storage since this is
andresag 3:d0f3e00cbfdf 123 * platform-specific. So we provide this function that returns the
andresag 3:d0f3e00cbfdf 124 * configured values that need to be stored and the main application
andresag 3:d0f3e00cbfdf 125 * takes care of storing them.
andresag 3:d0f3e00cbfdf 126 */
andresag 3:d0f3e00cbfdf 127 void getEddystoneParams(EddystoneParams_t *params);
andresag 3:d0f3e00cbfdf 128
andresag 3:d0f3e00cbfdf 129 private:
andresag 3:d0f3e00cbfdf 130 /* Helper function used only once during constructing the object to avoid
andresag 3:d0f3e00cbfdf 131 * duplicated code.
andresag 3:d0f3e00cbfdf 132 */
andresag 3:d0f3e00cbfdf 133 void eddystoneConstructorHelper(const PowerLevels_t &advPowerLevelsIn,
andresag 3:d0f3e00cbfdf 134 const PowerLevels_t &radioPowerLevelsIn,
andresag 3:d0f3e00cbfdf 135 uint32_t advConfigIntervalIn);
andresag 3:d0f3e00cbfdf 136
andresag 3:d0f3e00cbfdf 137 /* When changing modes, we shutdown and init the BLE instance, so
andresag 3:d0f3e00cbfdf 138 * this is needed to complete the initialisation task.
andresag 3:d0f3e00cbfdf 139 */
andresag 3:d0f3e00cbfdf 140 void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext);
andresag 3:d0f3e00cbfdf 141
andresag 3:d0f3e00cbfdf 142 void swapAdvertisedFrame(void);
andresag 3:d0f3e00cbfdf 143
andresag 3:d0f3e00cbfdf 144 void updateAdvertisementPacket(const uint8_t* rawFrame, size_t rawFrameLength);
andresag 3:d0f3e00cbfdf 145
andresag 3:d0f3e00cbfdf 146 /* Helper function that calls user-defined functions to update Battery Voltage and Temperature (if available),
andresag 3:d0f3e00cbfdf 147 * then updates the raw frame data and finally updates the actual advertised packet. This operation must be
andresag 3:d0f3e00cbfdf 148 * done fairly often because the TLM frame TimeSinceBoot must have a 0.1 secs resolution according to the
andresag 3:d0f3e00cbfdf 149 * Eddystone specification.
andresag 3:d0f3e00cbfdf 150 */
andresag 3:d0f3e00cbfdf 151 void updateRawTLMFrame(void);
andresag 3:d0f3e00cbfdf 152
andresag 3:d0f3e00cbfdf 153 void setupBeaconService(void);
andresag 3:d0f3e00cbfdf 154
andresag 3:d0f3e00cbfdf 155 void setupConfigService(void);
andresag 3:d0f3e00cbfdf 156
andresag 3:d0f3e00cbfdf 157 void freeConfigCharacteristics(void);
andresag 3:d0f3e00cbfdf 158
andresag 3:d0f3e00cbfdf 159 void freeBeaconFrames(void);
andresag 3:d0f3e00cbfdf 160
andresag 3:d0f3e00cbfdf 161 void radioNotificationCallback(bool radioActive);
andresag 3:d0f3e00cbfdf 162
andresag 3:d0f3e00cbfdf 163 /*
andresag 3:d0f3e00cbfdf 164 * Internal helper function used to update the GATT database following any
andresag 3:d0f3e00cbfdf 165 * change to the internal state of the service object.
andresag 3:d0f3e00cbfdf 166 */
andresag 3:d0f3e00cbfdf 167 void updateCharacteristicValues(void);
andresag 3:d0f3e00cbfdf 168
andresag 3:d0f3e00cbfdf 169 void setupEddystoneConfigAdvertisements(void);
andresag 3:d0f3e00cbfdf 170
andresag 3:d0f3e00cbfdf 171 void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
andresag 3:d0f3e00cbfdf 172
andresag 3:d0f3e00cbfdf 173 void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
andresag 3:d0f3e00cbfdf 174
andresag 3:d0f3e00cbfdf 175 void urlDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
andresag 3:d0f3e00cbfdf 176
andresag 3:d0f3e00cbfdf 177 void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
andresag 3:d0f3e00cbfdf 178
andresag 3:d0f3e00cbfdf 179 template <typename T>
andresag 3:d0f3e00cbfdf 180 void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
andresag 3:d0f3e00cbfdf 181
andresag 3:d0f3e00cbfdf 182 /*
andresag 3:d0f3e00cbfdf 183 * This callback is invoked when a GATT client attempts to modify any of the
andresag 3:d0f3e00cbfdf 184 * characteristics of this service. Attempts to do so are also applied to
andresag 3:d0f3e00cbfdf 185 * the internal state of this service object.
andresag 3:d0f3e00cbfdf 186 */
andresag 3:d0f3e00cbfdf 187 void onDataWrittenCallback(const GattWriteCallbackParams *writeParams);
andresag 3:d0f3e00cbfdf 188
andresag 3:d0f3e00cbfdf 189 uint16_t correctAdvertisementPeriod(uint16_t beaconPeriodIn) const;
andresag 3:d0f3e00cbfdf 190
andresag 3:d0f3e00cbfdf 191 BLE &ble;
andresag 3:d0f3e00cbfdf 192 uint32_t advConfigInterval;
andresag 3:d0f3e00cbfdf 193 uint8_t operationMode;
andresag 3:d0f3e00cbfdf 194
andresag 3:d0f3e00cbfdf 195 URLFrame urlFrame;
andresag 3:d0f3e00cbfdf 196 UIDFrame uidFrame;
andresag 3:d0f3e00cbfdf 197 TLMFrame tlmFrame;
andresag 3:d0f3e00cbfdf 198
andresag 3:d0f3e00cbfdf 199 PowerLevels_t radioPowerLevels;
andresag 3:d0f3e00cbfdf 200 PowerLevels_t advPowerLevels;
andresag 3:d0f3e00cbfdf 201 bool lockState;
andresag 3:d0f3e00cbfdf 202 bool resetFlag;
andresag 3:d0f3e00cbfdf 203 Lock_t lock;
andresag 3:d0f3e00cbfdf 204 Lock_t unlock;
andresag 3:d0f3e00cbfdf 205 uint8_t flags;
andresag 3:d0f3e00cbfdf 206 uint8_t txPowerMode;
andresag 3:d0f3e00cbfdf 207 uint16_t beaconPeriod;
andresag 3:d0f3e00cbfdf 208
andresag 3:d0f3e00cbfdf 209 ReadOnlyGattCharacteristic<bool> *lockStateChar;
andresag 3:d0f3e00cbfdf 210 WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)> *lockChar;
andresag 3:d0f3e00cbfdf 211 WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)> *unlockChar;
andresag 3:d0f3e00cbfdf 212 GattCharacteristic *urlDataChar;
andresag 3:d0f3e00cbfdf 213 ReadWriteGattCharacteristic<uint8_t> *flagsChar;
andresag 3:d0f3e00cbfdf 214 ReadWriteArrayGattCharacteristic<int8_t, sizeof(PowerLevels_t)> *advPowerLevelsChar;
andresag 3:d0f3e00cbfdf 215 ReadWriteGattCharacteristic<uint8_t> *txPowerModeChar;
andresag 3:d0f3e00cbfdf 216 ReadWriteGattCharacteristic<uint16_t> *beaconPeriodChar;
andresag 3:d0f3e00cbfdf 217 WriteOnlyGattCharacteristic<bool> *resetChar;
andresag 3:d0f3e00cbfdf 218
andresag 3:d0f3e00cbfdf 219 uint8_t *rawUrlFrame;
andresag 3:d0f3e00cbfdf 220 uint8_t *rawUidFrame;
andresag 3:d0f3e00cbfdf 221 uint8_t *rawTlmFrame;
andresag 3:d0f3e00cbfdf 222
andresag 3:d0f3e00cbfdf 223 uint16_t consecFrames[NUM_EDDYSTONE_FRAMES];
andresag 3:d0f3e00cbfdf 224 uint16_t currentConsecFrames[NUM_EDDYSTONE_FRAMES];
andresag 3:d0f3e00cbfdf 225 uint8_t currentAdvertisedFrame;
andresag 3:d0f3e00cbfdf 226
andresag 3:d0f3e00cbfdf 227 TlmUpdateCallback_t tlmBatteryVoltageCallback;
andresag 3:d0f3e00cbfdf 228 TlmUpdateCallback_t tlmBeaconTemperatureCallback;
andresag 3:d0f3e00cbfdf 229
andresag 3:d0f3e00cbfdf 230 Timer timeSinceBootTimer;
andresag 3:d0f3e00cbfdf 231 #ifndef YOTTA_CFG_MBED_OS
andresag 3:d0f3e00cbfdf 232 Timeout swapAdvertisedFrameTimeout;
andresag 3:d0f3e00cbfdf 233 #endif
andresag 3:d0f3e00cbfdf 234
andresag 3:d0f3e00cbfdf 235 GattCharacteristic *charTable[TOTAL_CHARACTERISTICS];
andresag 3:d0f3e00cbfdf 236 };
andresag 3:d0f3e00cbfdf 237
andresag 3:d0f3e00cbfdf 238 #endif /* __EDDYSTONESERVICE_H__ */