Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EddystoneConfigService.h Source File

EddystoneConfigService.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
00018 #define SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
00019 
00020 #warning ble/services/EddystoneConfigService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.
00021 
00022 #if BLE_FEATURE_GATT_SERVER
00023 
00024 #include "ble/BLE.h"
00025 #include "ble/services/EddystoneService.h"
00026 #include "Timer.h"
00027 #include "Ticker.h"
00028 
00029 #define UUID_URI_BEACON(FIRST, SECOND) {                         \
00030         0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba,       \
00031         0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8,          \
00032 }
00033 
00034 static const uint8_t UUID_URI_BEACON_SERVICE[]    = UUID_URI_BEACON(0x20, 0x80);
00035 static const uint8_t UUID_LOCK_STATE_CHAR[]       = UUID_URI_BEACON(0x20, 0x81);
00036 static const uint8_t UUID_LOCK_CHAR[]             = UUID_URI_BEACON(0x20, 0x82);
00037 static const uint8_t UUID_UNLOCK_CHAR[]           = UUID_URI_BEACON(0x20, 0x83);
00038 static const uint8_t UUID_URI_DATA_CHAR[]         = UUID_URI_BEACON(0x20, 0x84);
00039 static const uint8_t UUID_FLAGS_CHAR[]            = UUID_URI_BEACON(0x20, 0x85);
00040 static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
00041 static const uint8_t UUID_TX_POWER_MODE_CHAR[]    = UUID_URI_BEACON(0x20, 0x87);
00042 static const uint8_t UUID_BEACON_PERIOD_CHAR[]    = UUID_URI_BEACON(0x20, 0x88);
00043 static const uint8_t UUID_RESET_CHAR[]            = UUID_URI_BEACON(0x20, 0x89);
00044 extern const uint8_t BEACON_EDDYSTONE[2];
00045 
00046 /**
00047 * @class EddystoneConfigService
00048 * @brief Eddystone Configuration Service. Used to set URL, adjust power levels, and set flags.
00049 * See https://github.com/google/eddystone
00050 *
00051 */
00052 class EddystoneConfigService
00053 {
00054 public:
00055     /**
00056      * @brief Transmission Power Modes for UriBeacon
00057      */
00058     enum {
00059         TX_POWER_MODE_LOWEST,
00060         TX_POWER_MODE_LOW,
00061         TX_POWER_MODE_MEDIUM,
00062         TX_POWER_MODE_HIGH,
00063         NUM_POWER_MODES
00064     };
00065 
00066     static const unsigned ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service.
00067     static const unsigned SERVICE_DATA_MAX          = 31;   // Maximum size of service data in ADV packets.
00068 
00069     typedef uint8_t Lock_t[16];                             /* 128 bits. */
00070     typedef int8_t PowerLevels_t[NUM_POWER_MODES];
00071 
00072     // There are currently three subframes defined: URI, UID, and TLM.
00073 #define EDDYSTONE_MAX_FRAMETYPE 3
00074     static const unsigned URI_DATA_MAX = 18;
00075     typedef uint8_t UriData_t[URI_DATA_MAX];
00076 
00077     // UID Frame Type subfields.
00078     static const size_t UID_NAMESPACEID_SIZE = 10;
00079     typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
00080     static const size_t UID_INSTANCEID_SIZE = 6;
00081     typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
00082 
00083     // Eddystone Frame Type ID.
00084     static const uint8_t FRAME_TYPE_UID = 0x00;
00085     static const uint8_t FRAME_TYPE_URL = 0x10;
00086     static const uint8_t FRAME_TYPE_TLM = 0x20;
00087 
00088     static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14B.
00089     static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes.
00090 
00091     struct Params_t {
00092         // Config Data
00093         bool             isConfigured; // Flag for configuration being complete:
00094                                        //   True = configured, False = not configured. Reset at instantiation, used for external callbacks.
00095         uint8_t          lockedState;
00096         Lock_t           lock;
00097         uint8_t          flags;
00098         PowerLevels_t    advPowerLevels;  // Current value of AdvertisedPowerLevels.
00099         uint8_t          txPowerMode;     // Firmware power levels used with setTxPower().
00100         uint16_t         beaconPeriod;
00101         // TLM Frame Data
00102         uint8_t          tlmVersion;      // Version of TLM packet.
00103         bool             tlmEnabled;
00104         float            tlmBeaconPeriod; // How often to broadcat TLM frame, in seconds.
00105         // URI Frame Data
00106         uint8_t          uriDataLength;
00107         UriData_t        uriData;
00108         bool             uriEnabled;
00109         float            uriBeaconPeriod; // How often to broadcast URIFrame, in seconds.
00110         // UID Frame Data
00111         UIDNamespaceID_t uidNamespaceID;  // UUID type, Namespace ID, 10B.
00112         UIDInstanceID_t  uidInstanceID;   // UUID type, Instance ID, 6B.
00113         bool             uidEnabled;
00114         float            uidBeaconPeriod; // How often to broadcast UID Frame, in seconds.
00115     };
00116 
00117     /**
00118      * @param[in]    bleIn
00119      *                    BLEDevice object for the underlying controller.
00120      * @param[in,out] paramsIn
00121      *                    Reference to application-visible beacon state, loaded
00122      *                    from persistent storage at startup.
00123      * @param[in]     defaultAdvPowerLevelsIn
00124      *                    Default power-levels array; applies only if resetToDefaultsFlag is true.
00125      *
00126      * @param[in]     radioPowerLevelsIn
00127      *                    Transmission power-levels to use in TX.
00128      */
00129     EddystoneConfigService (BLEDevice     &bleIn,
00130                            Params_t      &paramsIn,
00131                            PowerLevels_t &defaultAdvPowerLevelsIn,
00132                            PowerLevels_t &radioPowerLevelsIn) :
00133         ble(bleIn),
00134         params(paramsIn),       // Initialize URL data.
00135         defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
00136         radioPowerLevels(radioPowerLevelsIn),
00137         initSucceeded(false),
00138         resetFlag(),
00139         defaultUidNamespaceID(), // Initialize UID data.
00140         defaultUidInstanceID(),
00141         defaultUidPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
00142         uidIsSet(false),
00143         defaultUriDataLength(),
00144         defaultUriData(),
00145         defaultUrlPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
00146         urlIsSet(false),
00147         tlmIsSet(false),
00148         lockedStateChar(UUID_LOCK_STATE_CHAR, &params.lockedState),
00149         lockChar(UUID_LOCK_CHAR, &params.lock),
00150         uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
00151                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
00152         unlockChar(UUID_UNLOCK_CHAR, &params.lock),
00153         flagsChar(UUID_FLAGS_CHAR, &params.flags),
00154         advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, &params.advPowerLevels),
00155         txPowerModeChar(UUID_TX_POWER_MODE_CHAR, &params.txPowerMode),
00156         beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, &params.beaconPeriod),
00157         resetChar(UUID_RESET_CHAR, &resetFlag) {
00158         // Set Eddystone as not configured yet. Used to exit config before timeout if GATT services are written to.
00159         params.isConfigured = false;
00160 
00161         lockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::lockAuthorizationCallback);
00162         unlockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::unlockAuthorizationCallback);
00163         uriDataChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::uriDataWriteAuthorizationCallback);
00164         flagsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
00165         advPowerLevelsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<PowerLevels_t>);
00166         txPowerModeChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::powerModeAuthorizationCallback);
00167         beaconPeriodChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint16_t>);
00168         resetChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
00169 
00170         static GattCharacteristic *charTable[] = {
00171             &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
00172             &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
00173         };
00174 
00175         GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00176 
00177         ble.addService(configService);
00178         ble.onDataWritten(this, &EddystoneConfigService::onDataWrittenCallback);
00179     }
00180 
00181     /**
00182      * @brief Start EddystoneConfig advertising. This function should be called
00183      * after the EddystoneConfig constructor and after all the frames have been added.
00184      *
00185      * @param[in]   resetToDefaultsFlag
00186      *                    Applies to the state of the 'paramsIn' parameter.
00187      *                    If true, it indicates that paramsIn is potentially
00188      *                    un-initialized, and default values should be used
00189      *                    instead. Otherwise, paramsIn overrides the defaults.
00190      */
00191     void start(bool resetToDefaultsFlag){
00192         INFO("reset to defaults flag = %d", resetToDefaultsFlag);
00193         if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
00194             INFO("Reset to Defaults triggered");
00195             resetToDefaultsFlag = true;
00196         }
00197 
00198         if (resetToDefaultsFlag) {
00199             resetToDefaults();
00200         } else {
00201             updateCharacteristicValues();
00202         }
00203 
00204         setupEddystoneConfigAdvertisements(); /* Set up advertising for the config service. */
00205         initSucceeded = true;
00206     }
00207 
00208     /*
00209     * Check if Eddystone initialized successfully.
00210     */
00211     bool initSuccessfully(void) const {
00212         return initSucceeded;
00213     }
00214 
00215     /*
00216     * @brief Function to update the default values for the TLM frame. Only applied if Reset Defaults is applied.
00217     *
00218     * @param[in] tlmVersionIn     Version of the TLM frame being used.
00219     * @param[in] advPeriodInMin How long between TLM frames being advertised, measured in minutes.
00220     *
00221     */
00222     void setDefaultTLMFrameData(uint8_t tlmVersionIn = 0, float advPeriodInSec = 60){
00223         DBG("Setting Default TLM Data, version = %d, advPeriodInMind= %f", tlmVersionIn, advPeriodInSec);
00224         defaultTlmVersion   = tlmVersionIn;
00225         TlmBatteryVoltage   = 0;
00226         TlmBeaconTemp       = 0x8000;
00227         TlmPduCount         = 0;
00228         TlmTimeSinceBoot    = 0;
00229         defaultTlmAdvPeriod = advPeriodInSec;
00230         tlmIsSet            = true; // Flag to add this to Eddystone service when config is done.
00231     }
00232 
00233     /*
00234     * @brief Function to update the default values for the URI frame. Only applied if Reset Defaults is applied.
00235     *
00236     * @param[in] uriIn      URL to advertise.
00237     * @param[in] advPeriod  How long to advertise the URL, measured in number of ADV frames.
00238     *
00239     */
00240     void setDefaultURIFrameData(const char *uriIn, float advPeriod = 1){
00241         DBG("Setting Default URI Data");
00242         // Set URL Frame
00243         EddystoneService::encodeURL(uriIn, defaultUriData, defaultUriDataLength);   // Encode URL to URL Formatting.
00244         if (defaultUriDataLength > URI_DATA_MAX) {
00245             return;
00246         }
00247         INFO("\t  URI input = %s : %d", uriIn, defaultUriDataLength);
00248         INFO("\t default URI = %s : %d ", defaultUriData, defaultUriDataLength );
00249         defaultUriAdvPeriod = advPeriod;
00250         urlIsSet            = true; // Flag to add this to Eddystone service when config is done.
00251     }
00252 
00253     /*
00254     * @brief Function to update the default values for the UID frame. Only applied if Reset Defaults is applied.
00255     *
00256     * @param[in] namespaceID 10Byte Namespace ID.
00257     * @param[in] instanceID  6Byte Instance ID.
00258     * @param[in] advPeriod   How long to advertise the URL, measured in the number of ADV frames.
00259     *
00260     */
00261     void setDefaultUIDFrameData(UIDNamespaceID_t *namespaceID, UIDInstanceID_t *instanceID, float advPeriod = 10){
00262         //Set UID frame
00263         DBG("Setting default UID Data");
00264         memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
00265         memcpy(defaultUidInstanceID,  instanceID,  UID_INSTANCEID_SIZE);
00266         defaultUidAdvPeriod = advPeriod;
00267         uidIsSet            = true; // Flag to add this to Eddystone service when config is done.
00268     }
00269 
00270     /* Start out by advertising the config service for a limited time after
00271      * startup, then switch to the normal non-connectible beacon functionality.
00272      */
00273     void setupEddystoneConfigAdvertisements() {
00274         const char DEVICE_NAME[] = "eddystone Config";
00275 
00276         ble.clearAdvertisingPayload();
00277 
00278         ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00279 
00280         // UUID is in a different order in the ADV frame (!)
00281         uint8_t reversedServiceUUID[sizeof(UUID_URI_BEACON_SERVICE)];
00282         for (unsigned int i = 0; i < sizeof(UUID_URI_BEACON_SERVICE); i++) {
00283             reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
00284         }
00285         ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
00286         ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
00287         ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
00288         ble.accumulateScanResponse(
00289             GapAdvertisingData::TX_POWER_LEVEL,
00290             reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneConfigService::TX_POWER_MODE_LOW]),
00291             sizeof(uint8_t));
00292 
00293         ble.setTxPower(radioPowerLevels[params.txPowerMode]);
00294         ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
00295         ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00296         ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
00297     }
00298 
00299     /*
00300     *   This function actually impliments the Eddystone Beacon service. It can be called with the help of the wrapper function
00301     *   to load saved config params, or it can be called explicitly to reset the Eddystone beacon to hardcoded values on each reset.
00302     *
00303     */
00304     void setupEddystoneAdvertisements() {
00305         DBG("Switching Config -> adv");
00306         // Save params to storage.
00307         extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */
00308         saveURIBeaconConfigParams(&params);
00309         INFO("Saved Params to Memory.")
00310         // Set up Eddystone Service.
00311         static EddystoneService eddyServ(ble, params.beaconPeriod, radioPowerLevels[params.txPowerMode]);
00312         // Set configured frames (TLM, UID, URI and so on).
00313         if (params.tlmEnabled) {
00314             eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
00315         }
00316         if (params.uriEnabled) {
00317             eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
00318         }
00319         if (params.uidEnabled) {
00320             eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode],
00321                                      (uint8_t *)params.uidNamespaceID,
00322                                      (uint8_t *)params.uidInstanceID,
00323                                      params.uidBeaconPeriod);
00324         }
00325         // Start advertising the Eddystone service.
00326         eddyServ.start();
00327     }
00328 
00329 private:
00330     /*
00331      * This callback is invoked when a GATT client attempts to modify any of the
00332      * characteristics of this service. Attempts to do so are also applied to
00333      * the internal state of this service object.
00334      */
00335     void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
00336         uint16_t handle = writeParams->handle;
00337 
00338         if (handle == lockChar.getValueHandle()) {
00339             // Validated earlier.
00340             memcpy(params.lock, writeParams->data, sizeof(Lock_t));
00341             // Set the state to be locked by the lock code (note: zeros are a valid lock).
00342             params.lockedState = true;
00343             INFO("Device Locked");
00344         } else if (handle == unlockChar.getValueHandle()) {
00345             // Validated earlier.
00346             params.lockedState = false;
00347             INFO("Device Unlocked");
00348         } else if (handle == uriDataChar.getValueHandle()) {
00349             params.uriDataLength = writeParams->len;
00350             memset(params.uriData, 0x00, URI_DATA_MAX);                      // Clear URI string.
00351             memcpy(params.uriData, writeParams->data, writeParams->len); // Set URI string.
00352             params.uriEnabled = true;
00353             INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
00354         } else if (handle == flagsChar.getValueHandle()) {
00355             params.flags = *(writeParams->data);
00356             INFO("flagsChar = 0x%x", params.flags);
00357         } else if (handle == advPowerLevelsChar.getValueHandle()) {
00358             memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
00359             INFO("PowerLevelsChar = %4x", params.advPowerLevels);
00360         } else if (handle == txPowerModeChar.getValueHandle()) {
00361             params.txPowerMode = *(writeParams->data);
00362             INFO("TxPowerModeChar = %d", params.txPowerMode);
00363         } else if (handle == beaconPeriodChar.getValueHandle()) {
00364             params.beaconPeriod = *((uint16_t *)(writeParams->data));
00365             INFO("BeaconPeriod = %d", params.beaconPeriod);
00366 
00367             /* Re-map beaconPeriod to within permissible bounds if necessary. */
00368             if (params.beaconPeriod != 0) {
00369                 bool paramsUpdated = false;
00370                 if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
00371                     params.beaconPeriod = ble.getMinAdvertisingInterval();
00372                     paramsUpdated       = true;
00373                 } else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
00374                     params.beaconPeriod = ble.getMaxAdvertisingInterval();
00375                     paramsUpdated       = true;
00376                 }
00377                 if (paramsUpdated) {
00378                     ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
00379                 }
00380             }
00381         } else if (handle == resetChar.getValueHandle()) {
00382             INFO("Reset triggered from Config Service, resetting to defaults");
00383             resetToDefaults();
00384         }
00385         updateCharacteristicValues();
00386         params.isConfigured = true; // Some configuration data has been passed; on disconnect switch to advertising mode.
00387     }
00388 
00389     /*
00390      * Reset the default values.
00391      */
00392     void resetToDefaults(void) {
00393         INFO("Resetting to defaults");
00394         // General.
00395         params.lockedState = false;
00396         memset(params.lock, 0, sizeof(Lock_t));
00397         params.flags = 0x10;
00398         memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
00399         params.txPowerMode  = TX_POWER_MODE_LOW;
00400         params.beaconPeriod = (uint16_t) defaultUriAdvPeriod * 1000;
00401 
00402         // TLM Frame.
00403         params.tlmVersion      = defaultTlmVersion;
00404         params.tlmBeaconPeriod = defaultTlmAdvPeriod;
00405         params.tlmEnabled      = tlmIsSet;
00406 
00407         // URL Frame.
00408         memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
00409         params.uriDataLength   = defaultUriDataLength;
00410         params.uriBeaconPeriod = defaultUriAdvPeriod;
00411         params.uriEnabled      = urlIsSet;
00412 
00413         // UID Frame.
00414         memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
00415         memcpy(params.uidInstanceID,  defaultUidInstanceID,  UID_INSTANCEID_SIZE);
00416         params.uidBeaconPeriod = defaultUidAdvPeriod;
00417         params.uidEnabled      = uidIsSet;
00418 
00419         updateCharacteristicValues();
00420     }
00421 
00422     /*
00423      * Internal helper function used to update the GATT database following any
00424      * change to the internal state of the service object.
00425      */
00426     void updateCharacteristicValues(void) {
00427         ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), &params.lockedState, 1);
00428         ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
00429         ble.updateCharacteristicValue(flagsChar.getValueHandle(), &params.flags, 1);
00430         ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
00431                                       reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
00432         ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), &params.txPowerMode, 1);
00433         ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
00434                                       reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
00435     }
00436 
00437 private:
00438     void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00439         if (params.lockedState) {
00440             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00441         } else if (authParams->len != sizeof(Lock_t)) {
00442             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00443         } else if (authParams->offset != 0) {
00444             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00445         } else {
00446             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00447         }
00448     }
00449 
00450     void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00451         if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) {
00452             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00453         } else if (authParams->len != sizeof(Lock_t)) {
00454             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00455         } else if (authParams->offset != 0) {
00456             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00457         } else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
00458             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00459         } else {
00460             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00461         }
00462     }
00463 
00464     void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00465         if (params.lockedState) {
00466             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00467         } else if (authParams->offset != 0) {
00468             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00469         } else {
00470             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00471         }
00472     }
00473 
00474     void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00475         if (params.lockedState) {
00476             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00477         } else if (authParams->len != sizeof(uint8_t)) {
00478             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00479         } else if (authParams->offset != 0) {
00480             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00481         } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
00482             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
00483         } else {
00484             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00485         }
00486     }
00487 
00488     template <typename T>
00489     void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00490         if (params.lockedState) {
00491             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00492         } else if (authParams->len != sizeof(T)) {
00493             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00494         } else if (authParams->offset != 0) {
00495             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00496         } else {
00497             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00498         }
00499     }
00500 
00501     BLEDevice                                  &ble;
00502     Params_t                                   &params;
00503     mbed::Ticker                               timeSinceBootTick;
00504     mbed::Timeout                              switchFrame;
00505     // Default value that is restored on reset.
00506     PowerLevels_t                              &defaultAdvPowerLevels; // This goes into the advertising frames (radio power measured at 1m from device).
00507     PowerLevels_t                              &radioPowerLevels;      // This configures the power levels of the radio.
00508     uint8_t                                    lockedState;
00509     bool                                       initSucceeded;
00510     uint8_t                                    resetFlag;
00511     bool                                       switchFlag;
00512 
00513     //UID default value that is restored on reset.
00514     UIDNamespaceID_t                           defaultUidNamespaceID;
00515     UIDInstanceID_t                            defaultUidInstanceID;
00516     float                                      defaultUidAdvPeriod;
00517     int8_t                                     defaultUidPower;
00518     uint16_t                                   uidRFU;
00519     bool                                       uidIsSet;
00520 
00521     //URI default value that is restored on reset.
00522     uint8_t                                    defaultUriDataLength;
00523     UriData_t                                  defaultUriData;
00524     int8_t                                     defaultUrlPower;
00525     float                                      defaultUriAdvPeriod;
00526     bool                                       urlIsSet;
00527 
00528     //TLM default value that is restored on reset.
00529     uint8_t                                    defaultTlmVersion;
00530     float                                      defaultTlmAdvPeriod;
00531     volatile uint16_t                          TlmBatteryVoltage;
00532     volatile uint16_t                          TlmBeaconTemp;
00533     volatile uint32_t                          TlmPduCount;
00534     volatile uint32_t                          TlmTimeSinceBoot;
00535     bool                                       tlmIsSet;
00536 
00537     ReadOnlyGattCharacteristic<uint8_t>         lockedStateChar;
00538     WriteOnlyGattCharacteristic<Lock_t>         lockChar;
00539     GattCharacteristic                         uriDataChar;
00540     WriteOnlyGattCharacteristic<Lock_t>         unlockChar;
00541     ReadWriteGattCharacteristic<uint8_t>        flagsChar;
00542     ReadWriteGattCharacteristic<PowerLevels_t>  advPowerLevelsChar;
00543     ReadWriteGattCharacteristic<uint8_t>        txPowerModeChar;
00544     ReadWriteGattCharacteristic<uint16_t>       beaconPeriodChar;
00545     WriteOnlyGattCharacteristic<uint8_t>        resetChar;
00546 };
00547 
00548 #endif // BLE_FEATURE_GATT_SERVER
00549 
00550 #endif  // SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_