High level Bluetooth Low Energy API and radio abstraction layer

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Thu Dec 10 09:15:02 2015 +0000
Revision:
1022:306c409f6c09
Parent:
1019:575852ad31a2
Child:
1023:a072b59caddb
Synchronized with git rev ea69dba5
Author: Marcus Chang
Reversed internal representation of long UUID in the UUID class to little endian to be consistent with the short UUID.

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 1022:306c409f6c09 26 #define UUID_URI_BEACON(FIRST, SECOND) { \
rgrover1 1022:306c409f6c09 27 0xd8, 0x81, 0xc9, 0x1a, 0xb9, 0x99, 0x96, 0xab, \
rgrover1 1022:306c409f6c09 28 0xba, 0x40, 0x86, 0x87, SECOND, FIRST, 0x0c, 0xee \
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 1019:575852ad31a2 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 1019:575852ad31a2 64 static const unsigned SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets.
rgrover1 978:7d8155c636b8 65
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 85 static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14B.
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 90 bool isConfigured; // Flag for configuration being complete:
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 95 PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels.
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 99 uint8_t tlmVersion; // Version of TLM packet.
rgrover1 978:7d8155c636b8 100 bool tlmEnabled;
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 106 float uriBeaconPeriod; // How often to broadcast URIFrame, in seconds.
rgrover1 978:7d8155c636b8 107 // UID Frame Data
rgrover1 1019:575852ad31a2 108 UIDNamespaceID_t uidNamespaceID; // UUID type, Namespace ID, 10B.
rgrover1 1019:575852ad31a2 109 UIDInstanceID_t uidInstanceID; // UUID type, Instance ID, 6B.
rgrover1 978:7d8155c636b8 110 bool uidEnabled;
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 212 * @param[in] tlmVersionIn Version of the TLM frame being used.
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 230 * @param[in] uriIn URL to advertise.
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 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 1019:575852ad31a2 250 * @param[in] namespaceID 10Byte Namespace ID.
rgrover1 1019:575852ad31a2 251 * @param[in] instanceID 6Byte Instance ID.
rgrover1 1019:575852ad31a2 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 1019:575852ad31a2 261 uidIsSet = true; // Flag to add this to Eddystone service when config is done.
rgrover1 978:7d8155c636b8 262 }
rgrover1 978:7d8155c636b8 263
rgrover1 1019:575852ad31a2 264 /* Start out by advertising the config service for a limited time after
rgrover1 1019:575852ad31a2 265 * startup, then switch to the normal non-connectible beacon functionality.
rgrover1 1019:575852ad31a2 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 1022:306c409f6c09 274 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, UUID_URI_BEACON_SERVICE, sizeof(UUID_URI_BEACON_SERVICE));
rgrover1 978:7d8155c636b8 275 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
rgrover1 978:7d8155c636b8 276 ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
rgrover1 978:7d8155c636b8 277 ble.accumulateScanResponse(
rgrover1 978:7d8155c636b8 278 GapAdvertisingData::TX_POWER_LEVEL,
rgrover1 978:7d8155c636b8 279 reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneConfigService::TX_POWER_MODE_LOW]),
rgrover1 978:7d8155c636b8 280 sizeof(uint8_t));
rgrover1 978:7d8155c636b8 281
rgrover1 978:7d8155c636b8 282 ble.setTxPower(radioPowerLevels[params.txPowerMode]);
rgrover1 978:7d8155c636b8 283 ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
rgrover1 978:7d8155c636b8 284 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
rgrover1 978:7d8155c636b8 285 ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
rgrover1 978:7d8155c636b8 286 }
rgrover1 978:7d8155c636b8 287
rgrover1 978:7d8155c636b8 288 /*
rgrover1 978:7d8155c636b8 289 * This function actually impliments the Eddystone Beacon service. It can be called with the help of the wrapper function
rgrover1 1019:575852ad31a2 290 * 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 291 *
rgrover1 978:7d8155c636b8 292 */
rgrover1 978:7d8155c636b8 293 void setupEddystoneAdvertisements() {
rgrover1 978:7d8155c636b8 294 DBG("Switching Config -> adv");
rgrover1 1019:575852ad31a2 295 // Save params to storage.
rgrover1 978:7d8155c636b8 296 extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */
rgrover1 978:7d8155c636b8 297 saveURIBeaconConfigParams(&params);
rgrover1 978:7d8155c636b8 298 INFO("Saved Params to Memory.")
rgrover1 1019:575852ad31a2 299 // Set up Eddystone Service.
rgrover1 978:7d8155c636b8 300 static EddystoneService eddyServ(ble, params.beaconPeriod, radioPowerLevels[params.txPowerMode]);
rgrover1 1019:575852ad31a2 301 // Set configured frames (TLM, UID, URI and so on).
rgrover1 978:7d8155c636b8 302 if (params.tlmEnabled) {
rgrover1 978:7d8155c636b8 303 eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
rgrover1 978:7d8155c636b8 304 }
rgrover1 978:7d8155c636b8 305 if (params.uriEnabled) {
rgrover1 978:7d8155c636b8 306 eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
rgrover1 978:7d8155c636b8 307 }
rgrover1 978:7d8155c636b8 308 if (params.uidEnabled) {
rgrover1 978:7d8155c636b8 309 eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode],
rgrover1 978:7d8155c636b8 310 (uint8_t *)params.uidNamespaceID,
rgrover1 978:7d8155c636b8 311 (uint8_t *)params.uidInstanceID,
rgrover1 978:7d8155c636b8 312 params.uidBeaconPeriod);
rgrover1 978:7d8155c636b8 313 }
rgrover1 1019:575852ad31a2 314 // Start advertising the Eddystone service.
rgrover1 978:7d8155c636b8 315 eddyServ.start();
rgrover1 978:7d8155c636b8 316 }
rgrover1 978:7d8155c636b8 317
rgrover1 978:7d8155c636b8 318 private:
rgrover1 978:7d8155c636b8 319 /*
rgrover1 978:7d8155c636b8 320 * This callback is invoked when a GATT client attempts to modify any of the
rgrover1 978:7d8155c636b8 321 * characteristics of this service. Attempts to do so are also applied to
rgrover1 978:7d8155c636b8 322 * the internal state of this service object.
rgrover1 978:7d8155c636b8 323 */
rgrover1 978:7d8155c636b8 324 void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
rgrover1 978:7d8155c636b8 325 uint16_t handle = writeParams->handle;
rgrover1 978:7d8155c636b8 326
rgrover1 978:7d8155c636b8 327 if (handle == lockChar.getValueHandle()) {
rgrover1 1019:575852ad31a2 328 // Validated earlier.
rgrover1 978:7d8155c636b8 329 memcpy(params.lock, writeParams->data, sizeof(Lock_t));
rgrover1 1019:575852ad31a2 330 // Set the state to be locked by the lock code (note: zeros are a valid lock).
rgrover1 978:7d8155c636b8 331 params.lockedState = true;
rgrover1 978:7d8155c636b8 332 INFO("Device Locked");
rgrover1 978:7d8155c636b8 333 } else if (handle == unlockChar.getValueHandle()) {
rgrover1 1019:575852ad31a2 334 // Validated earlier.
rgrover1 978:7d8155c636b8 335 params.lockedState = false;
rgrover1 978:7d8155c636b8 336 INFO("Device Unlocked");
rgrover1 978:7d8155c636b8 337 } else if (handle == uriDataChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 338 params.uriDataLength = writeParams->len;
rgrover1 1019:575852ad31a2 339 memset(params.uriData, 0x00, URI_DATA_MAX); // Clear URI string.
rgrover1 1019:575852ad31a2 340 memcpy(params.uriData, writeParams->data, writeParams->len); // Set URI string.
rgrover1 978:7d8155c636b8 341 params.uriEnabled = true;
rgrover1 978:7d8155c636b8 342 INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
rgrover1 978:7d8155c636b8 343 } else if (handle == flagsChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 344 params.flags = *(writeParams->data);
rgrover1 978:7d8155c636b8 345 INFO("flagsChar = 0x%x", params.flags);
rgrover1 978:7d8155c636b8 346 } else if (handle == advPowerLevelsChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 347 memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 348 INFO("PowerLevelsChar = %4x", params.advPowerLevels);
rgrover1 978:7d8155c636b8 349 } else if (handle == txPowerModeChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 350 params.txPowerMode = *(writeParams->data);
rgrover1 978:7d8155c636b8 351 INFO("TxPowerModeChar = %d", params.txPowerMode);
rgrover1 978:7d8155c636b8 352 } else if (handle == beaconPeriodChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 353 params.beaconPeriod = *((uint16_t *)(writeParams->data));
rgrover1 978:7d8155c636b8 354 INFO("BeaconPeriod = %d", params.beaconPeriod);
rgrover1 978:7d8155c636b8 355
rgrover1 978:7d8155c636b8 356 /* Re-map beaconPeriod to within permissible bounds if necessary. */
rgrover1 978:7d8155c636b8 357 if (params.beaconPeriod != 0) {
rgrover1 978:7d8155c636b8 358 bool paramsUpdated = false;
rgrover1 978:7d8155c636b8 359 if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
rgrover1 978:7d8155c636b8 360 params.beaconPeriod = ble.getMinAdvertisingInterval();
rgrover1 978:7d8155c636b8 361 paramsUpdated = true;
rgrover1 978:7d8155c636b8 362 } else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
rgrover1 978:7d8155c636b8 363 params.beaconPeriod = ble.getMaxAdvertisingInterval();
rgrover1 978:7d8155c636b8 364 paramsUpdated = true;
rgrover1 978:7d8155c636b8 365 }
rgrover1 978:7d8155c636b8 366 if (paramsUpdated) {
rgrover1 978:7d8155c636b8 367 ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
rgrover1 978:7d8155c636b8 368 }
rgrover1 978:7d8155c636b8 369 }
rgrover1 978:7d8155c636b8 370 } else if (handle == resetChar.getValueHandle()) {
rgrover1 978:7d8155c636b8 371 INFO("Reset triggered from Config Service, resetting to defaults");
rgrover1 978:7d8155c636b8 372 resetToDefaults();
rgrover1 978:7d8155c636b8 373 }
rgrover1 978:7d8155c636b8 374 updateCharacteristicValues();
rgrover1 1019:575852ad31a2 375 params.isConfigured = true; // Some configuration data has been passed; on disconnect switch to advertising mode.
rgrover1 978:7d8155c636b8 376 }
rgrover1 978:7d8155c636b8 377
rgrover1 978:7d8155c636b8 378 /*
rgrover1 978:7d8155c636b8 379 * Reset the default values.
rgrover1 978:7d8155c636b8 380 */
rgrover1 978:7d8155c636b8 381 void resetToDefaults(void) {
rgrover1 978:7d8155c636b8 382 INFO("Resetting to defaults");
rgrover1 1019:575852ad31a2 383 // General.
rgrover1 978:7d8155c636b8 384 params.lockedState = false;
rgrover1 978:7d8155c636b8 385 memset(params.lock, 0, sizeof(Lock_t));
rgrover1 978:7d8155c636b8 386 params.flags = 0x10;
rgrover1 978:7d8155c636b8 387 memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 388 params.txPowerMode = TX_POWER_MODE_LOW;
rgrover1 978:7d8155c636b8 389 params.beaconPeriod = (uint16_t) defaultUriAdvPeriod * 1000;
rgrover1 978:7d8155c636b8 390
rgrover1 1019:575852ad31a2 391 // TLM Frame.
rgrover1 978:7d8155c636b8 392 params.tlmVersion = defaultTlmVersion;
rgrover1 978:7d8155c636b8 393 params.tlmBeaconPeriod = defaultTlmAdvPeriod;
rgrover1 978:7d8155c636b8 394 params.tlmEnabled = tlmIsSet;
rgrover1 978:7d8155c636b8 395
rgrover1 1019:575852ad31a2 396 // URL Frame.
rgrover1 978:7d8155c636b8 397 memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
rgrover1 978:7d8155c636b8 398 params.uriDataLength = defaultUriDataLength;
rgrover1 978:7d8155c636b8 399 params.uriBeaconPeriod = defaultUriAdvPeriod;
rgrover1 978:7d8155c636b8 400 params.uriEnabled = urlIsSet;
rgrover1 978:7d8155c636b8 401
rgrover1 1019:575852ad31a2 402 // UID Frame.
rgrover1 978:7d8155c636b8 403 memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
rgrover1 978:7d8155c636b8 404 memcpy(params.uidInstanceID, defaultUidInstanceID, UID_INSTANCEID_SIZE);
rgrover1 978:7d8155c636b8 405 params.uidBeaconPeriod = defaultUidAdvPeriod;
rgrover1 978:7d8155c636b8 406 params.uidEnabled = uidIsSet;
rgrover1 978:7d8155c636b8 407
rgrover1 978:7d8155c636b8 408 updateCharacteristicValues();
rgrover1 978:7d8155c636b8 409 }
rgrover1 978:7d8155c636b8 410
rgrover1 978:7d8155c636b8 411 /*
rgrover1 978:7d8155c636b8 412 * Internal helper function used to update the GATT database following any
rgrover1 978:7d8155c636b8 413 * change to the internal state of the service object.
rgrover1 978:7d8155c636b8 414 */
rgrover1 978:7d8155c636b8 415 void updateCharacteristicValues(void) {
rgrover1 978:7d8155c636b8 416 ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), &params.lockedState, 1);
rgrover1 978:7d8155c636b8 417 ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
rgrover1 978:7d8155c636b8 418 ble.updateCharacteristicValue(flagsChar.getValueHandle(), &params.flags, 1);
rgrover1 978:7d8155c636b8 419 ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
rgrover1 978:7d8155c636b8 420 reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
rgrover1 978:7d8155c636b8 421 ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), &params.txPowerMode, 1);
rgrover1 978:7d8155c636b8 422 ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
rgrover1 978:7d8155c636b8 423 reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
rgrover1 978:7d8155c636b8 424 }
rgrover1 978:7d8155c636b8 425
rgrover1 978:7d8155c636b8 426 private:
rgrover1 978:7d8155c636b8 427 void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 428 if (params.lockedState) {
rgrover1 978:7d8155c636b8 429 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 430 } else if (authParams->len != sizeof(Lock_t)) {
rgrover1 978:7d8155c636b8 431 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 432 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 433 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 434 } else {
rgrover1 978:7d8155c636b8 435 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 436 }
rgrover1 978:7d8155c636b8 437 }
rgrover1 978:7d8155c636b8 438
rgrover1 978:7d8155c636b8 439 void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 440 if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) {
rgrover1 978:7d8155c636b8 441 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 442 } else if (authParams->len != sizeof(Lock_t)) {
rgrover1 978:7d8155c636b8 443 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 444 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 445 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 446 } else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
rgrover1 978:7d8155c636b8 447 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 448 } else {
rgrover1 978:7d8155c636b8 449 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 450 }
rgrover1 978:7d8155c636b8 451 }
rgrover1 978:7d8155c636b8 452
rgrover1 978:7d8155c636b8 453 void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 454 if (params.lockedState) {
rgrover1 978:7d8155c636b8 455 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 456 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 457 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 458 } else {
rgrover1 978:7d8155c636b8 459 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 460 }
rgrover1 978:7d8155c636b8 461 }
rgrover1 978:7d8155c636b8 462
rgrover1 978:7d8155c636b8 463 void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 464 if (params.lockedState) {
rgrover1 978:7d8155c636b8 465 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 466 } else if (authParams->len != sizeof(uint8_t)) {
rgrover1 978:7d8155c636b8 467 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 468 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 469 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 470 } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
rgrover1 978:7d8155c636b8 471 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
rgrover1 978:7d8155c636b8 472 } else {
rgrover1 978:7d8155c636b8 473 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 474 }
rgrover1 978:7d8155c636b8 475 }
rgrover1 978:7d8155c636b8 476
rgrover1 978:7d8155c636b8 477 template <typename T>
rgrover1 978:7d8155c636b8 478 void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
rgrover1 978:7d8155c636b8 479 if (params.lockedState) {
rgrover1 978:7d8155c636b8 480 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
rgrover1 978:7d8155c636b8 481 } else if (authParams->len != sizeof(T)) {
rgrover1 978:7d8155c636b8 482 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
rgrover1 978:7d8155c636b8 483 } else if (authParams->offset != 0) {
rgrover1 978:7d8155c636b8 484 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
rgrover1 978:7d8155c636b8 485 } else {
rgrover1 978:7d8155c636b8 486 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
rgrover1 978:7d8155c636b8 487 }
rgrover1 978:7d8155c636b8 488 }
rgrover1 978:7d8155c636b8 489
rgrover1 978:7d8155c636b8 490 BLEDevice &ble;
rgrover1 978:7d8155c636b8 491 Params_t &params;
rgrover1 978:7d8155c636b8 492 Ticker timeSinceBootTick;
rgrover1 978:7d8155c636b8 493 Timeout switchFrame;
rgrover1 1019:575852ad31a2 494 // Default value that is restored on reset.
rgrover1 1019:575852ad31a2 495 PowerLevels_t &defaultAdvPowerLevels; // This goes into the advertising frames (radio power measured at 1m from device).
rgrover1 1019:575852ad31a2 496 PowerLevels_t &radioPowerLevels; // This configures the power levels of the radio.
rgrover1 978:7d8155c636b8 497 uint8_t lockedState;
rgrover1 978:7d8155c636b8 498 bool initSucceeded;
rgrover1 978:7d8155c636b8 499 uint8_t resetFlag;
rgrover1 978:7d8155c636b8 500 bool switchFlag;
rgrover1 978:7d8155c636b8 501
rgrover1 1019:575852ad31a2 502 //UID default value that is restored on reset.
rgrover1 978:7d8155c636b8 503 UIDNamespaceID_t defaultUidNamespaceID;
rgrover1 978:7d8155c636b8 504 UIDInstanceID_t defaultUidInstanceID;
rgrover1 978:7d8155c636b8 505 float defaultUidAdvPeriod;
rgrover1 978:7d8155c636b8 506 int8_t defaultUidPower;
rgrover1 978:7d8155c636b8 507 uint16_t uidRFU;
rgrover1 978:7d8155c636b8 508 bool uidIsSet;
rgrover1 978:7d8155c636b8 509
rgrover1 1019:575852ad31a2 510 //URI default value that is restored on reset.
rgrover1 978:7d8155c636b8 511 uint8_t defaultUriDataLength;
rgrover1 978:7d8155c636b8 512 UriData_t defaultUriData;
rgrover1 978:7d8155c636b8 513 int8_t defaultUrlPower;
rgrover1 978:7d8155c636b8 514 float defaultUriAdvPeriod;
rgrover1 978:7d8155c636b8 515 bool urlIsSet;
rgrover1 978:7d8155c636b8 516
rgrover1 1019:575852ad31a2 517 //TLM default value that is restored on reset.
rgrover1 978:7d8155c636b8 518 uint8_t defaultTlmVersion;
rgrover1 978:7d8155c636b8 519 float defaultTlmAdvPeriod;
rgrover1 978:7d8155c636b8 520 volatile uint16_t TlmBatteryVoltage;
rgrover1 978:7d8155c636b8 521 volatile uint16_t TlmBeaconTemp;
rgrover1 978:7d8155c636b8 522 volatile uint32_t TlmPduCount;
rgrover1 978:7d8155c636b8 523 volatile uint32_t TlmTimeSinceBoot;
rgrover1 978:7d8155c636b8 524 bool tlmIsSet;
rgrover1 978:7d8155c636b8 525
rgrover1 978:7d8155c636b8 526 ReadOnlyGattCharacteristic<uint8_t> lockedStateChar;
rgrover1 978:7d8155c636b8 527 WriteOnlyGattCharacteristic<Lock_t> lockChar;
rgrover1 978:7d8155c636b8 528 GattCharacteristic uriDataChar;
rgrover1 978:7d8155c636b8 529 WriteOnlyGattCharacteristic<Lock_t> unlockChar;
rgrover1 978:7d8155c636b8 530 ReadWriteGattCharacteristic<uint8_t> flagsChar;
rgrover1 978:7d8155c636b8 531 ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
rgrover1 978:7d8155c636b8 532 ReadWriteGattCharacteristic<uint8_t> txPowerModeChar;
rgrover1 978:7d8155c636b8 533 ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
rgrover1 978:7d8155c636b8 534 WriteOnlyGattCharacteristic<uint8_t> resetChar;
rgrover1 978:7d8155c636b8 535 };
rgrover1 978:7d8155c636b8 536
rgrover1 978:7d8155c636b8 537 #endif // SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_