High level Bluetooth Low Energy API and radio abstraction layer

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Wed Dec 02 12:57:28 2015 +0000
Revision:
1008:c27e0c6f1f38
Parent:
1006:76ae9bbf173f
Child:
1017:ccb8c0646e55
Synchronized with git rev 13bf70b6
Author: Rohit Grover
Release 2.1.5
=============

A minor release to separate the concept of minlen and len in
GattCharacteristic. Also contains some improvements to documentation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 978:7d8155c636b8 1 /* mbed Microcontroller Library
rgrover1 978:7d8155c636b8 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 978:7d8155c636b8 3 *
rgrover1 978:7d8155c636b8 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 978:7d8155c636b8 5 * you may not use this file except in compliance with the License.
rgrover1 978:7d8155c636b8 6 * You may obtain a copy of the License at
rgrover1 978:7d8155c636b8 7 *
rgrover1 978:7d8155c636b8 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 978:7d8155c636b8 9 *
rgrover1 978:7d8155c636b8 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 978:7d8155c636b8 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 978:7d8155c636b8 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 978:7d8155c636b8 13 * See the License for the specific language governing permissions and
rgrover1 978:7d8155c636b8 14 * limitations under the License.
rgrover1 978:7d8155c636b8 15 */
rgrover1 978:7d8155c636b8 16
rgrover1 978:7d8155c636b8 17 #ifndef SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
rgrover1 978:7d8155c636b8 18 #define SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
rgrover1 978:7d8155c636b8 19
rgrover1 993:4d62b7967c11 20 #warning ble/services/EddystoneConfigService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.
rgrover1 993:4d62b7967c11 21
rgrover1 978:7d8155c636b8 22 #include "mbed.h"
rgrover1 978:7d8155c636b8 23 #include "ble/BLE.h"
rgrover1 978:7d8155c636b8 24 #include "ble/services/EddystoneService.h"
rgrover1 978:7d8155c636b8 25
rgrover1 978:7d8155c636b8 26 #define UUID_URI_BEACON(FIRST, SECOND) { \
rgrover1 978:7d8155c636b8 27 0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba, \
rgrover1 978:7d8155c636b8 28 0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8, \
rgrover1 978:7d8155c636b8 29 }
rgrover1 978:7d8155c636b8 30
rgrover1 978:7d8155c636b8 31 static const uint8_t UUID_URI_BEACON_SERVICE[] = UUID_URI_BEACON(0x20, 0x80);
rgrover1 978:7d8155c636b8 32 static const uint8_t UUID_LOCK_STATE_CHAR[] = UUID_URI_BEACON(0x20, 0x81);
rgrover1 978:7d8155c636b8 33 static const uint8_t UUID_LOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x82);
rgrover1 978:7d8155c636b8 34 static const uint8_t UUID_UNLOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x83);
rgrover1 978:7d8155c636b8 35 static const uint8_t UUID_URI_DATA_CHAR[] = UUID_URI_BEACON(0x20, 0x84);
rgrover1 978:7d8155c636b8 36 static const uint8_t UUID_FLAGS_CHAR[] = UUID_URI_BEACON(0x20, 0x85);
rgrover1 978:7d8155c636b8 37 static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
rgrover1 978:7d8155c636b8 38 static const uint8_t UUID_TX_POWER_MODE_CHAR[] = UUID_URI_BEACON(0x20, 0x87);
rgrover1 978:7d8155c636b8 39 static const uint8_t UUID_BEACON_PERIOD_CHAR[] = UUID_URI_BEACON(0x20, 0x88);
rgrover1 978:7d8155c636b8 40 static const uint8_t UUID_RESET_CHAR[] = UUID_URI_BEACON(0x20, 0x89);
rgrover1 978:7d8155c636b8 41 extern const uint8_t BEACON_EDDYSTONE[2];
rgrover1 978:7d8155c636b8 42
rgrover1 978:7d8155c636b8 43 /**
rgrover1 978:7d8155c636b8 44 * @class EddystoneConfigService
rgrover1 1008:c27e0c6f1f38 45 * @brief Eddystone Configuration Service. Used to set URL, adjust power levels, and set flags.
rgrover1 978:7d8155c636b8 46 * See https://github.com/google/eddystone
rgrover1 978:7d8155c636b8 47 *
rgrover1 978:7d8155c636b8 48 */
rgrover1 978:7d8155c636b8 49 class EddystoneConfigService
rgrover1 978:7d8155c636b8 50 {
rgrover1 978:7d8155c636b8 51 public:
rgrover1 978:7d8155c636b8 52 /**
rgrover1 978:7d8155c636b8 53 * @brief Transmission Power Modes for UriBeacon
rgrover1 978:7d8155c636b8 54 */
rgrover1 978:7d8155c636b8 55 enum {
rgrover1 978:7d8155c636b8 56 TX_POWER_MODE_LOWEST,
rgrover1 978:7d8155c636b8 57 TX_POWER_MODE_LOW,
rgrover1 978:7d8155c636b8 58 TX_POWER_MODE_MEDIUM,
rgrover1 978:7d8155c636b8 59 TX_POWER_MODE_HIGH,
rgrover1 978:7d8155c636b8 60 NUM_POWER_MODES
rgrover1 978:7d8155c636b8 61 };
rgrover1 978:7d8155c636b8 62
rgrover1 978:7d8155c636b8 63 static const unsigned ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service.
rgrover1 1008:c27e0c6f1f38 64 static const unsigned SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets.
rgrover1 978:7d8155c636b8 65
rgrover1 1008:c27e0c6f1f38 66 typedef uint8_t Lock_t[16]; /* 128 bits. */
rgrover1 978:7d8155c636b8 67 typedef int8_t PowerLevels_t[NUM_POWER_MODES];
rgrover1 978:7d8155c636b8 68
rgrover1 1008:c27e0c6f1f38 69 // There are currently three subframes defined: URI, UID, and TLM.
rgrover1 978:7d8155c636b8 70 #define EDDYSTONE_MAX_FRAMETYPE 3
rgrover1 978:7d8155c636b8 71 static const unsigned URI_DATA_MAX = 18;
rgrover1 978:7d8155c636b8 72 typedef uint8_t UriData_t[URI_DATA_MAX];
rgrover1 978:7d8155c636b8 73
rgrover1 1008:c27e0c6f1f38 74 // UID Frame Type subfields.
rgrover1 978:7d8155c636b8 75 static const size_t UID_NAMESPACEID_SIZE = 10;
rgrover1 978:7d8155c636b8 76 typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
rgrover1 978:7d8155c636b8 77 static const size_t UID_INSTANCEID_SIZE = 6;
rgrover1 978:7d8155c636b8 78 typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
rgrover1 978:7d8155c636b8 79
rgrover1 1008:c27e0c6f1f38 80 // Eddystone Frame Type ID.
rgrover1 978:7d8155c636b8 81 static const uint8_t FRAME_TYPE_UID = 0x00;
rgrover1 978:7d8155c636b8 82 static const uint8_t FRAME_TYPE_URL = 0x10;
rgrover1 978:7d8155c636b8 83 static const uint8_t FRAME_TYPE_TLM = 0x20;
rgrover1 978:7d8155c636b8 84
rgrover1 1008:c27e0c6f1f38 85 static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14B.
rgrover1 1008:c27e0c6f1f38 86 static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes.
rgrover1 978:7d8155c636b8 87
rgrover1 978:7d8155c636b8 88 struct Params_t {
rgrover1 978:7d8155c636b8 89 // Config Data
rgrover1 1008:c27e0c6f1f38 90 bool isConfigured; // Flag for configuration being complete:
rgrover1 1008:c27e0c6f1f38 91 // True = configured, False = not configured. Reset at instantiation, used for external callbacks.
rgrover1 978:7d8155c636b8 92 uint8_t lockedState;
rgrover1 978:7d8155c636b8 93 Lock_t lock;
rgrover1 978:7d8155c636b8 94 uint8_t flags;
rgrover1 1008:c27e0c6f1f38 95 PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels.
rgrover1 1008:c27e0c6f1f38 96 uint8_t txPowerMode; // Firmware power levels used with setTxPower().
rgrover1 978:7d8155c636b8 97 uint16_t beaconPeriod;
rgrover1 978:7d8155c636b8 98 // TLM Frame Data
rgrover1 1008:c27e0c6f1f38 99 uint8_t tlmVersion; // Version of TLM packet.
rgrover1 978:7d8155c636b8 100 bool tlmEnabled;
rgrover1 1008:c27e0c6f1f38 101 float tlmBeaconPeriod; // How often to broadcat TLM frame, in seconds.
rgrover1 978:7d8155c636b8 102 // URI Frame Data
rgrover1 978:7d8155c636b8 103 uint8_t uriDataLength;
rgrover1 978:7d8155c636b8 104 UriData_t uriData;
rgrover1 978:7d8155c636b8 105 bool uriEnabled;
rgrover1 1008:c27e0c6f1f38 106 float uriBeaconPeriod; // How often to broadcast URIFrame, in seconds.
rgrover1 978:7d8155c636b8 107 // UID Frame Data
rgrover1 1008:c27e0c6f1f38 108 UIDNamespaceID_t uidNamespaceID; // UUID type, Namespace ID, 10B.
rgrover1 1008:c27e0c6f1f38 109 UIDInstanceID_t uidInstanceID; // UUID type, Instance ID, 6B.
rgrover1 978:7d8155c636b8 110 bool uidEnabled;
rgrover1 1008:c27e0c6f1f38 111 float uidBeaconPeriod; // How often to broadcast UID Frame, in seconds.
rgrover1 978:7d8155c636b8 112 };
rgrover1 978:7d8155c636b8 113
rgrover1 978:7d8155c636b8 114 /**
rgrover1 978:7d8155c636b8 115 * @param[ref] ble
rgrover1 978:7d8155c636b8 116 * BLEDevice object for the underlying controller.
rgrover1 978:7d8155c636b8 117 * @param[in/out] paramsIn
rgrover1 978:7d8155c636b8 118 * Reference to application-visible beacon state, loaded
rgrover1 978:7d8155c636b8 119 * from persistent storage at startup.
rgrover1 978:7d8155c636b8 120 * @param[in] defaultAdvPowerLevelsIn
rgrover1 1008:c27e0c6f1f38 121 * Default power-levels array; applies only if resetToDefaultsFlag is true.
rgrover1 978:7d8155c636b8 122 */
rgrover1 978:7d8155c636b8 123 EddystoneConfigService(BLEDevice &bleIn,
rgrover1 978:7d8155c636b8 124 Params_t &paramsIn,
rgrover1 978:7d8155c636b8 125 PowerLevels_t &defaultAdvPowerLevelsIn,
rgrover1 978:7d8155c636b8 126 PowerLevels_t &radioPowerLevelsIn) :
rgrover1 978:7d8155c636b8 127 ble(bleIn),
rgrover1 1008:c27e0c6f1f38 128 params(paramsIn), // Initialize URL data.
rgrover1 978:7d8155c636b8 129 defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
rgrover1 978:7d8155c636b8 130 radioPowerLevels(radioPowerLevelsIn),
rgrover1 978:7d8155c636b8 131 initSucceeded(false),
rgrover1 978:7d8155c636b8 132 resetFlag(),
rgrover1 1008:c27e0c6f1f38 133 defaultUidNamespaceID(), // Initialize UID data.
rgrover1 978:7d8155c636b8 134 defaultUidInstanceID(),
rgrover1 978:7d8155c636b8 135 defaultUidPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
rgrover1 978:7d8155c636b8 136 uidIsSet(false),
rgrover1 978:7d8155c636b8 137 defaultUriDataLength(),
rgrover1 978:7d8155c636b8 138 defaultUriData(),
rgrover1 978:7d8155c636b8 139 defaultUrlPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
rgrover1 978:7d8155c636b8 140 urlIsSet(false),
rgrover1 978:7d8155c636b8 141 tlmIsSet(false),
rgrover1 978:7d8155c636b8 142 lockedStateChar(UUID_LOCK_STATE_CHAR, &params.lockedState),
rgrover1 978:7d8155c636b8 143 lockChar(UUID_LOCK_CHAR, &params.lock),
rgrover1 978:7d8155c636b8 144 uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
rgrover1 978:7d8155c636b8 145 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
rgrover1 978:7d8155c636b8 146 unlockChar(UUID_UNLOCK_CHAR, &params.lock),
rgrover1 978:7d8155c636b8 147 flagsChar(UUID_FLAGS_CHAR, &params.flags),
rgrover1 978:7d8155c636b8 148 advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, &params.advPowerLevels),
rgrover1 978:7d8155c636b8 149 txPowerModeChar(UUID_TX_POWER_MODE_CHAR, &params.txPowerMode),
rgrover1 978:7d8155c636b8 150 beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, &params.beaconPeriod),
rgrover1 978:7d8155c636b8 151 resetChar(UUID_RESET_CHAR, &resetFlag) {
rgrover1 1008:c27e0c6f1f38 152 // Set Eddystone as not configured yet. Used to exit config before timeout if GATT services are written to.
rgrover1 978:7d8155c636b8 153 params.isConfigured = false;
rgrover1 978:7d8155c636b8 154
rgrover1 978:7d8155c636b8 155 lockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::lockAuthorizationCallback);
rgrover1 978:7d8155c636b8 156 unlockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::unlockAuthorizationCallback);
rgrover1 978:7d8155c636b8 157 uriDataChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::uriDataWriteAuthorizationCallback);
rgrover1 978:7d8155c636b8 158 flagsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
rgrover1 978:7d8155c636b8 159 advPowerLevelsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<PowerLevels_t>);
rgrover1 978:7d8155c636b8 160 txPowerModeChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::powerModeAuthorizationCallback);
rgrover1 978:7d8155c636b8 161 beaconPeriodChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint16_t>);
rgrover1 978:7d8155c636b8 162 resetChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
rgrover1 978:7d8155c636b8 163
rgrover1 978:7d8155c636b8 164 static GattCharacteristic *charTable[] = {
rgrover1 978:7d8155c636b8 165 &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
rgrover1 978:7d8155c636b8 166 &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
rgrover1 978:7d8155c636b8 167 };
rgrover1 978:7d8155c636b8 168
rgrover1 978:7d8155c636b8 169 GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
rgrover1 978:7d8155c636b8 170
rgrover1 978:7d8155c636b8 171 ble.addService(configService);
rgrover1 978:7d8155c636b8 172 ble.onDataWritten(this, &EddystoneConfigService::onDataWrittenCallback);
rgrover1 978:7d8155c636b8 173 }
rgrover1 978:7d8155c636b8 174
rgrover1 978:7d8155c636b8 175 /**
rgrover1 978:7d8155c636b8 176 * @brief Start EddystoneConfig advertising. This function should be called
rgrover1 978:7d8155c636b8 177 * after the EddystoneConfig constructor and after all the frames have been added.
rgrover1 978:7d8155c636b8 178 *
rgrover1 978:7d8155c636b8 179 * @paramsP[in] resetToDefaultsFlag
rgrover1 978:7d8155c636b8 180 * Applies to the state of the 'paramsIn' parameter.
rgrover1 978:7d8155c636b8 181 * If true, it indicates that paramsIn is potentially
rgrover1 978:7d8155c636b8 182 * un-initialized, and default values should be used
rgrover1 978:7d8155c636b8 183 * instead. Otherwise, paramsIn overrides the defaults.
rgrover1 978:7d8155c636b8 184 */
rgrover1 978:7d8155c636b8 185 void start(bool resetToDefaultsFlag){
rgrover1 978:7d8155c636b8 186 INFO("reset to defaults flag = %d", resetToDefaultsFlag);
rgrover1 978:7d8155c636b8 187 if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
rgrover1 978:7d8155c636b8 188 INFO("Reset to Defaults triggered");
rgrover1 978:7d8155c636b8 189 resetToDefaultsFlag = true;
rgrover1 978:7d8155c636b8 190 }
rgrover1 978:7d8155c636b8 191
rgrover1 978:7d8155c636b8 192 if (resetToDefaultsFlag) {
rgrover1 978:7d8155c636b8 193 resetToDefaults();
rgrover1 978:7d8155c636b8 194 } else {
rgrover1 978:7d8155c636b8 195 updateCharacteristicValues();
rgrover1 978:7d8155c636b8 196 }
rgrover1 978:7d8155c636b8 197
rgrover1 1008:c27e0c6f1f38 198 setupEddystoneConfigAdvertisements(); /* Set up advertising for the config service. */
rgrover1 978:7d8155c636b8 199 initSucceeded = true;
rgrover1 978:7d8155c636b8 200 }
rgrover1 978:7d8155c636b8 201
rgrover1 978:7d8155c636b8 202 /*
rgrover1 1008:c27e0c6f1f38 203 * Check if Eddystone initialized successfully.
rgrover1 978:7d8155c636b8 204 */
rgrover1 978:7d8155c636b8 205 bool initSuccessfully(void) const {
rgrover1 978:7d8155c636b8 206 return initSucceeded;
rgrover1 978:7d8155c636b8 207 }
rgrover1 978:7d8155c636b8 208
rgrover1 978:7d8155c636b8 209 /*
rgrover1 978:7d8155c636b8 210 * @brief Function to update the default values for the TLM frame. Only applied if Reset Defaults is applied.
rgrover1 978:7d8155c636b8 211 *
rgrover1 1008:c27e0c6f1f38 212 * @param[in] tlmVersionIn Version of the TLM frame being used.
rgrover1 1008:c27e0c6f1f38 213 * @param[in] advPeriodInMin How long between TLM frames being advertised, measured in minutes.
rgrover1 978:7d8155c636b8 214 *
rgrover1 978:7d8155c636b8 215 */
rgrover1 978:7d8155c636b8 216 void setDefaultTLMFrameData(uint8_t tlmVersionIn = 0, float advPeriodInSec = 60){
rgrover1 978:7d8155c636b8 217 DBG("Setting Default TLM Data, version = %d, advPeriodInMind= %f", tlmVersionIn, advPeriodInSec);
rgrover1 978:7d8155c636b8 218 defaultTlmVersion = tlmVersionIn;
rgrover1 978:7d8155c636b8 219 TlmBatteryVoltage = 0;
rgrover1 978:7d8155c636b8 220 TlmBeaconTemp = 0x8000;
rgrover1 978:7d8155c636b8 221 TlmPduCount = 0;
rgrover1 978:7d8155c636b8 222 TlmTimeSinceBoot = 0;
rgrover1 978:7d8155c636b8 223 defaultTlmAdvPeriod = advPeriodInSec;
rgrover1 1008:c27e0c6f1f38 224 tlmIsSet = true; // Flag to add this to Eddystone service when config is done.
rgrover1 978:7d8155c636b8 225 }
rgrover1 978:7d8155c636b8 226
rgrover1 978:7d8155c636b8 227 /*
rgrover1 978:7d8155c636b8 228 * @brief Function to update the default values for the URI frame. Only applied if Reset Defaults is applied.
rgrover1 978:7d8155c636b8 229 *
rgrover1 1008:c27e0c6f1f38 230 * @param[in] uriIn URL to advertise.
rgrover1 1008:c27e0c6f1f38 231 * @param[in] advPeriod How long to advertise the URL, measured in number of ADV frames.
rgrover1 978:7d8155c636b8 232 *
rgrover1 978:7d8155c636b8 233 */
rgrover1 978:7d8155c636b8 234 void setDefaultURIFrameData(const char *uriIn, float advPeriod = 1){
rgrover1 978:7d8155c636b8 235 DBG("Setting Default URI Data");
rgrover1 978:7d8155c636b8 236 // Set URL Frame
rgrover1 1008:c27e0c6f1f38 237 EddystoneService::encodeURL(uriIn, defaultUriData, defaultUriDataLength); // Encode URL to URL Formatting.
rgrover1 978:7d8155c636b8 238 if (defaultUriDataLength > URI_DATA_MAX) {
rgrover1 978:7d8155c636b8 239 return;
rgrover1 978:7d8155c636b8 240 }
rgrover1 978:7d8155c636b8 241 INFO("\t URI input = %s : %d", uriIn, defaultUriDataLength);
rgrover1 978:7d8155c636b8 242 INFO("\t default URI = %s : %d ", defaultUriData, defaultUriDataLength );
rgrover1 978:7d8155c636b8 243 defaultUriAdvPeriod = advPeriod;
rgrover1 1008:c27e0c6f1f38 244 urlIsSet = true; // Flag to add this to Eddystone service when config is done.
rgrover1 978:7d8155c636b8 245 }
rgrover1 978:7d8155c636b8 246
rgrover1 978:7d8155c636b8 247 /*
rgrover1 978:7d8155c636b8 248 * @brief Function to update the default values for the UID frame. Only applied if Reset Defaults is applied.
rgrover1 978:7d8155c636b8 249 *
rgrover1 1008:c27e0c6f1f38 250 * @param[in] namespaceID 10Byte Namespace ID.
rgrover1 1008:c27e0c6f1f38 251 * @param[in] instanceID 6Byte Instance ID.
rgrover1 1008:c27e0c6f1f38 252 * @param[in] advPeriod How long to advertise the URL, measured in the number of ADV frames.
rgrover1 978:7d8155c636b8 253 *
rgrover1 978:7d8155c636b8 254 */
rgrover1 978:7d8155c636b8 255 void setDefaultUIDFrameData(UIDNamespaceID_t *namespaceID, UIDInstanceID_t *instanceID, float advPeriod = 10){
rgrover1 978:7d8155c636b8 256 //Set UID frame
rgrover1 978:7d8155c636b8 257 DBG("Setting default UID Data");
rgrover1 978:7d8155c636b8 258 memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
rgrover1 978:7d8155c636b8 259 memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
rgrover1 978:7d8155c636b8 260 defaultUidAdvPeriod = advPeriod;
rgrover1 1008:c27e0c6f1f38 261 uidIsSet = true; // Flag to add this to Eddystone service when config is done.
rgrover1 978:7d8155c636b8 262 }
rgrover1 978:7d8155c636b8 263
rgrover1 1008:c27e0c6f1f38 264 /* Start out by advertising the config service for a limited time after
rgrover1 1008:c27e0c6f1f38 265 * startup, then switch to the normal non-connectible beacon functionality.
rgrover1 1008:c27e0c6f1f38 266 */
rgrover1 978:7d8155c636b8 267 void setupEddystoneConfigAdvertisements() {
rgrover1 978:7d8155c636b8 268 const char DEVICE_NAME[] = "eddystone Config";
rgrover1 978:7d8155c636b8 269
rgrover1 978:7d8155c636b8 270 ble.clearAdvertisingPayload();
rgrover1 978:7d8155c636b8 271
rgrover1 978:7d8155c636b8 272 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
rgrover1 978:7d8155c636b8 273
rgrover1 1008:c27e0c6f1f38 274 // UUID is in a different order in the ADV frame (!)
rgrover1 978:7d8155c636b8 275 uint8_t reversedServiceUUID[sizeof(UUID_URI_BEACON_SERVICE)];
rgrover1 978:7d8155c636b8 276 for (unsigned int i = 0; i < sizeof(UUID_URI_BEACON_SERVICE); i++) {
rgrover1 978:7d8155c636b8 277 reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
rgrover1 978:7d8155c636b8 278 }
rgrover1 978:7d8155c636b8 279 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
rgrover1 978:7d8155c636b8 280 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
rgrover1 978:7d8155c636b8 281 ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
rgrover1 978:7d8155c636b8 282 ble.accumulateScanResponse(
rgrover1 978:7d8155c636b8 283 GapAdvertisingData::TX_POWER_LEVEL,
rgrover1 978:7d8155c636b8 284 reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneConfigService::TX_POWER_MODE_LOW]),
rgrover1 978:7d8155c636b8 285 sizeof(uint8_t));
rgrover1 978:7d8155c636b8 286
rgrover1 978:7d8155c636b8 287 ble.setTxPower(radioPowerLevels[params.txPowerMode]);
rgrover1 978:7d8155c636b8 288 ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
rgrover1 978:7d8155c636b8 289 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
rgrover1 978:7d8155c636b8 290 ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
rgrover1 978:7d8155c636b8 291 }
rgrover1 978:7d8155c636b8 292
rgrover1 978:7d8155c636b8 293 /*
rgrover1 978:7d8155c636b8 294 * This function actually impliments the Eddystone Beacon service. It can be called with the help of the wrapper function
rgrover1 1008:c27e0c6f1f38 295 * to load saved config params, or it can be called explicitly to reset the Eddystone beacon to hardcoded values on each reset.
rgrover1 978:7d8155c636b8 296 *
rgrover1 978:7d8155c636b8 297 */
rgrover1 978:7d8155c636b8 298 void setupEddystoneAdvertisements() {
rgrover1 978:7d8155c636b8 299 DBG("Switching Config -> adv");
rgrover1 1008:c27e0c6f1f38 300 // Save params to storage.
rgrover1 978:7d8155c636b8 301 extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */
rgrover1 978:7d8155c636b8 302 saveURIBeaconConfigParams(&params);
rgrover1 978:7d8155c636b8 303 INFO("Saved Params to Memory.")
rgrover1 1008:c27e0c6f1f38 304 // Set up Eddystone Service.
rgrover1 978:7d8155c636b8 305 static EddystoneService eddyServ(ble, params.beaconPeriod, radioPowerLevels[params.txPowerMode]);
rgrover1 1008:c27e0c6f1f38 306 // Set configured frames (TLM, UID, URI and so on).
rgrover1 978:7d8155c636b8 307 if (params.tlmEnabled) {
rgrover1 978:7d8155c636b8 308 eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
rgrover1 978:7d8155c636b8 309 }
rgrover1 978:7d8155c636b8 310 if (params.uriEnabled) {
rgrover1 978:7d8155c636b8 311 eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
rgrover1 978:7d8155c636b8 312 }
rgrover1 978:7d8155c636b8 313 if (params.uidEnabled) {
rgrover1 978:7d8155c636b8 314 eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode],
rgrover1 978:7d8155c636b8 315 (uint8_t *)params.uidNamespaceID,
rgrover1 978:7d8155c636b8 316 (uint8_t *)params.uidInstanceID,
rgrover1 978:7d8155c636b8 317 params.uidBeaconPeriod);
rgrover1 978:7d8155c636b8 318 }
rgrover1 1008:c27e0c6f1f38 319 // Start advertising the Eddystone service.
rgrover1 978:7d8155c636b8 320 eddyServ.start();
rgrover1 978:7d8155c636b8 321 }
rgrover1 978:7d8155c636b8 322
rgrover1 978:7d8155c636b8 323 private:
rgrover1 978:7d8155c636b8 324 /*
rgrover1 978:7d8155c636b8 325 * This callback is invoked when a GATT client attempts to modify any of the
rgrover1 978:7d8155c636b8 326 * characteristics of this service. Attempts to do so are also applied to
rgrover1 978:7d8155c636b8 327 * the internal state of this service object.
rgrover1 978:7d8155c636b8 328 */
rgrover1 978:7d8155c636b8 329 void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
rgrover1 978:7d8155c636b8 330 uint16_t handle = writeParams->handle;
rgrover1 978:7d8155c636b8 331
rgrover1 978:7d8155c636b8 332 if (handle == lockChar.getValueHandle()) {
rgrover1 1008:c27e0c6f1f38 333 // Validated earlier.
rgrover1 978:7d8155c636b8 334 memcpy(params.lock, writeParams->data, sizeof(Lock_t));
rgrover1 1008:c27e0c6f1f38 335 // Set the state to be locked by the lock code (note: zeros are a valid lock).
rgrover1 978:7d8155c636b8 336 params.lockedState = true;
rgrover1 978:7d8155c636b8 337 INFO("Device Locked");
rgrover1 978:7d8155c636b8 338 } else if (handle == unlockChar.getValueHandle()) {
rgrover1 1008:c27e0c6f1f38 339 // Validated earlier.
rgrover1 978:7d8155c636b8 340 params.lockedState = false;
rgrover1 978:7d8155c636b8 341 INFO("Device Unlocked");
rgrover1 978:7d8155c636b8 342 } else if (handle == uriDataChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 343 params.uriDataLength = writeParams->len;
rgrover1 1008:c27e0c6f1f38 344 memset(params.uriData, 0x00, URI_DATA_MAX); // Clear URI string.
rgrover1 1008:c27e0c6f1f38 345 memcpy(params.uriData, writeParams->data, writeParams->len); // Set URI string.
rgrover1 978:7d8155c636b8 346 params.uriEnabled = true;
rgrover1 978:7d8155c636b8 347 INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
rgrover1 978:7d8155c636b8 348 } else if (handle == flagsChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 349 params.flags = *(writeParams->data);
rgrover1 978:7d8155c636b8 350 INFO("flagsChar = 0x%x", params.flags);
rgrover1 978:7d8155c636b8 351 } else if (handle == advPowerLevelsChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 352 memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 353 INFO("PowerLevelsChar = %4x", params.advPowerLevels);
rgrover1 978:7d8155c636b8 354 } else if (handle == txPowerModeChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 355 params.txPowerMode = *(writeParams->data);
rgrover1 978:7d8155c636b8 356 INFO("TxPowerModeChar = %d", params.txPowerMode);
rgrover1 978:7d8155c636b8 357 } else if (handle == beaconPeriodChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 358 params.beaconPeriod = *((uint16_t *)(writeParams->data));
rgrover1 978:7d8155c636b8 359 INFO("BeaconPeriod = %d", params.beaconPeriod);
rgrover1 978:7d8155c636b8 360
rgrover1 978:7d8155c636b8 361 /* Re-map beaconPeriod to within permissible bounds if necessary. */
rgrover1 978:7d8155c636b8 362 if (params.beaconPeriod != 0) {
rgrover1 978:7d8155c636b8 363 bool paramsUpdated = false;
rgrover1 978:7d8155c636b8 364 if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
rgrover1 978:7d8155c636b8 365 params.beaconPeriod = ble.getMinAdvertisingInterval();
rgrover1 978:7d8155c636b8 366 paramsUpdated = true;
rgrover1 978:7d8155c636b8 367 } else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
rgrover1 978:7d8155c636b8 368 params.beaconPeriod = ble.getMaxAdvertisingInterval();
rgrover1 978:7d8155c636b8 369 paramsUpdated = true;
rgrover1 978:7d8155c636b8 370 }
rgrover1 978:7d8155c636b8 371 if (paramsUpdated) {
rgrover1 978:7d8155c636b8 372 ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
rgrover1 978:7d8155c636b8 373 }
rgrover1 978:7d8155c636b8 374 }
rgrover1 978:7d8155c636b8 375 } else if (handle == resetChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 376 INFO("Reset triggered from Config Service, resetting to defaults");
rgrover1 978:7d8155c636b8 377 resetToDefaults();
rgrover1 978:7d8155c636b8 378 }
rgrover1 978:7d8155c636b8 379 updateCharacteristicValues();
rgrover1 1008:c27e0c6f1f38 380 params.isConfigured = true; // Some configuration data has been passed; on disconnect switch to advertising mode.
rgrover1 978:7d8155c636b8 381 }
rgrover1 978:7d8155c636b8 382
rgrover1 978:7d8155c636b8 383 /*
rgrover1 978:7d8155c636b8 384 * Reset the default values.
rgrover1 978:7d8155c636b8 385 */
rgrover1 978:7d8155c636b8 386 void resetToDefaults(void) {
rgrover1 978:7d8155c636b8 387 INFO("Resetting to defaults");
rgrover1 1008:c27e0c6f1f38 388 // General.
rgrover1 978:7d8155c636b8 389 params.lockedState = false;
rgrover1 978:7d8155c636b8 390 memset(params.lock, 0, sizeof(Lock_t));
rgrover1 978:7d8155c636b8 391 params.flags = 0x10;
rgrover1 978:7d8155c636b8 392 memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 393 params.txPowerMode = TX_POWER_MODE_LOW;
rgrover1 978:7d8155c636b8 394 params.beaconPeriod = (uint16_t) defaultUriAdvPeriod * 1000;
rgrover1 978:7d8155c636b8 395
rgrover1 1008:c27e0c6f1f38 396 // TLM Frame.
rgrover1 978:7d8155c636b8 397 params.tlmVersion = defaultTlmVersion;
rgrover1 978:7d8155c636b8 398 params.tlmBeaconPeriod = defaultTlmAdvPeriod;
rgrover1 978:7d8155c636b8 399 params.tlmEnabled = tlmIsSet;
rgrover1 978:7d8155c636b8 400
rgrover1 1008:c27e0c6f1f38 401 // URL Frame.
rgrover1 978:7d8155c636b8 402 memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
rgrover1 978:7d8155c636b8 403 params.uriDataLength = defaultUriDataLength;
rgrover1 978:7d8155c636b8 404 params.uriBeaconPeriod = defaultUriAdvPeriod;
rgrover1 978:7d8155c636b8 405 params.uriEnabled = urlIsSet;
rgrover1 978:7d8155c636b8 406
rgrover1 1008:c27e0c6f1f38 407 // UID Frame.
rgrover1 978:7d8155c636b8 408 memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
rgrover1 978:7d8155c636b8 409 memcpy(params.uidInstanceID, defaultUidInstanceID, UID_INSTANCEID_SIZE);
rgrover1 978:7d8155c636b8 410 params.uidBeaconPeriod = defaultUidAdvPeriod;
rgrover1 978:7d8155c636b8 411 params.uidEnabled = uidIsSet;
rgrover1 978:7d8155c636b8 412
rgrover1 978:7d8155c636b8 413 updateCharacteristicValues();
rgrover1 978:7d8155c636b8 414 }
rgrover1 978:7d8155c636b8 415
rgrover1 978:7d8155c636b8 416 /*
rgrover1 978:7d8155c636b8 417 * Internal helper function used to update the GATT database following any
rgrover1 978:7d8155c636b8 418 * change to the internal state of the service object.
rgrover1 978:7d8155c636b8 419 */
rgrover1 978:7d8155c636b8 420 void updateCharacteristicValues(void) {
rgrover1 978:7d8155c636b8 421 ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), &params.lockedState, 1);
rgrover1 978:7d8155c636b8 422 ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
rgrover1 978:7d8155c636b8 423 ble.updateCharacteristicValue(flagsChar.getValueHandle(), &params.flags, 1);
rgrover1 978:7d8155c636b8 424 ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
rgrover1 978:7d8155c636b8 425 reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
rgrover1 978:7d8155c636b8 426 ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), &params.txPowerMode, 1);
rgrover1 978:7d8155c636b8 427 ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
rgrover1 978:7d8155c636b8 428 reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 429 }
rgrover1 978:7d8155c636b8 430
rgrover1 978:7d8155c636b8 431 private:
rgrover1 978:7d8155c636b8 432 void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 433 if (params.lockedState) {
rgrover1 978:7d8155c636b8 434 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 435 } else if (authParams->len != sizeof(Lock_t)) {
rgrover1 978:7d8155c636b8 436 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 437 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 438 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 439 } else {
rgrover1 978:7d8155c636b8 440 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 441 }
rgrover1 978:7d8155c636b8 442 }
rgrover1 978:7d8155c636b8 443
rgrover1 978:7d8155c636b8 444 void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 445 if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) {
rgrover1 978:7d8155c636b8 446 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 447 } else if (authParams->len != sizeof(Lock_t)) {
rgrover1 978:7d8155c636b8 448 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 449 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 450 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 451 } else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
rgrover1 978:7d8155c636b8 452 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 453 } else {
rgrover1 978:7d8155c636b8 454 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 455 }
rgrover1 978:7d8155c636b8 456 }
rgrover1 978:7d8155c636b8 457
rgrover1 978:7d8155c636b8 458 void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 459 if (params.lockedState) {
rgrover1 978:7d8155c636b8 460 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 461 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 462 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 463 } else {
rgrover1 978:7d8155c636b8 464 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 465 }
rgrover1 978:7d8155c636b8 466 }
rgrover1 978:7d8155c636b8 467
rgrover1 978:7d8155c636b8 468 void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 469 if (params.lockedState) {
rgrover1 978:7d8155c636b8 470 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 471 } else if (authParams->len != sizeof(uint8_t)) {
rgrover1 978:7d8155c636b8 472 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 473 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 474 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 475 } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
rgrover1 978:7d8155c636b8 476 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
rgrover1 978:7d8155c636b8 477 } else {
rgrover1 978:7d8155c636b8 478 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 479 }
rgrover1 978:7d8155c636b8 480 }
rgrover1 978:7d8155c636b8 481
rgrover1 978:7d8155c636b8 482 template <typename T>
rgrover1 978:7d8155c636b8 483 void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 484 if (params.lockedState) {
rgrover1 978:7d8155c636b8 485 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 486 } else if (authParams->len != sizeof(T)) {
rgrover1 978:7d8155c636b8 487 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 488 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 489 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 490 } else {
rgrover1 978:7d8155c636b8 491 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 492 }
rgrover1 978:7d8155c636b8 493 }
rgrover1 978:7d8155c636b8 494
rgrover1 978:7d8155c636b8 495 BLEDevice &ble;
rgrover1 978:7d8155c636b8 496 Params_t &params;
rgrover1 978:7d8155c636b8 497 Ticker timeSinceBootTick;
rgrover1 978:7d8155c636b8 498 Timeout switchFrame;
rgrover1 1008:c27e0c6f1f38 499 // Default value that is restored on reset.
rgrover1 1008:c27e0c6f1f38 500 PowerLevels_t &defaultAdvPowerLevels; // This goes into the advertising frames (radio power measured at 1m from device).
rgrover1 1008:c27e0c6f1f38 501 PowerLevels_t &radioPowerLevels; // This configures the power levels of the radio.
rgrover1 978:7d8155c636b8 502 uint8_t lockedState;
rgrover1 978:7d8155c636b8 503 bool initSucceeded;
rgrover1 978:7d8155c636b8 504 uint8_t resetFlag;
rgrover1 978:7d8155c636b8 505 bool switchFlag;
rgrover1 978:7d8155c636b8 506
rgrover1 1008:c27e0c6f1f38 507 //UID default value that is restored on reset.
rgrover1 978:7d8155c636b8 508 UIDNamespaceID_t defaultUidNamespaceID;
rgrover1 978:7d8155c636b8 509 UIDInstanceID_t defaultUidInstanceID;
rgrover1 978:7d8155c636b8 510 float defaultUidAdvPeriod;
rgrover1 978:7d8155c636b8 511 int8_t defaultUidPower;
rgrover1 978:7d8155c636b8 512 uint16_t uidRFU;
rgrover1 978:7d8155c636b8 513 bool uidIsSet;
rgrover1 978:7d8155c636b8 514
rgrover1 1008:c27e0c6f1f38 515 //URI default value that is restored on reset.
rgrover1 978:7d8155c636b8 516 uint8_t defaultUriDataLength;
rgrover1 978:7d8155c636b8 517 UriData_t defaultUriData;
rgrover1 978:7d8155c636b8 518 int8_t defaultUrlPower;
rgrover1 978:7d8155c636b8 519 float defaultUriAdvPeriod;
rgrover1 978:7d8155c636b8 520 bool urlIsSet;
rgrover1 978:7d8155c636b8 521
rgrover1 1008:c27e0c6f1f38 522 //TLM default value that is restored on reset.
rgrover1 978:7d8155c636b8 523 uint8_t defaultTlmVersion;
rgrover1 978:7d8155c636b8 524 float defaultTlmAdvPeriod;
rgrover1 978:7d8155c636b8 525 volatile uint16_t TlmBatteryVoltage;
rgrover1 978:7d8155c636b8 526 volatile uint16_t TlmBeaconTemp;
rgrover1 978:7d8155c636b8 527 volatile uint32_t TlmPduCount;
rgrover1 978:7d8155c636b8 528 volatile uint32_t TlmTimeSinceBoot;
rgrover1 978:7d8155c636b8 529 bool tlmIsSet;
rgrover1 978:7d8155c636b8 530
rgrover1 978:7d8155c636b8 531 ReadOnlyGattCharacteristic<uint8_t> lockedStateChar;
rgrover1 978:7d8155c636b8 532 WriteOnlyGattCharacteristic<Lock_t> lockChar;
rgrover1 978:7d8155c636b8 533 GattCharacteristic uriDataChar;
rgrover1 978:7d8155c636b8 534 WriteOnlyGattCharacteristic<Lock_t> unlockChar;
rgrover1 978:7d8155c636b8 535 ReadWriteGattCharacteristic<uint8_t> flagsChar;
rgrover1 978:7d8155c636b8 536 ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
rgrover1 978:7d8155c636b8 537 ReadWriteGattCharacteristic<uint8_t> txPowerModeChar;
rgrover1 978:7d8155c636b8 538 ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
rgrover1 978:7d8155c636b8 539 WriteOnlyGattCharacteristic<uint8_t> resetChar;
rgrover1 978:7d8155c636b8 540 };
rgrover1 978:7d8155c636b8 541
rgrover1 978:7d8155c636b8 542 #endif // SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_