Scott Jenson / Mbed 2 deprecated BLE_EddystoneBeaconConfigService_Button

Dependencies:   BLE_API_EddystoneConfigService_2 mbed nRF51822

Fork of BLE_EddystoneBeaconConfigService_3 by URIBeacon

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_EDDYSTONEBEACONCONFIGSERVICE_H_
00018 #define SERVICES_EDDYSTONEBEACONCONFIGSERVICE_H_
00019 
00020 #include "mbed.h"
00021 #include "ble/BLE.h"
00022 #include "ble/services/EddystoneService.h"
00023 
00024 #define EDDYSTONE_NUM_UID_FRAMES 10
00025 #define EDDYSTONE_NUM_URL_FRAMES 50
00026 
00027 
00028 #define UUID_URI_BEACON(FIRST, SECOND) {                         \
00029         0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba,       \
00030         0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8,          \
00031 }
00032 
00033 static const uint8_t UUID_URI_BEACON_SERVICE[]    = UUID_URI_BEACON(0x20, 0x80);
00034 static const uint8_t UUID_LOCK_STATE_CHAR[]       = UUID_URI_BEACON(0x20, 0x81);
00035 static const uint8_t UUID_LOCK_CHAR[]             = UUID_URI_BEACON(0x20, 0x82);
00036 static const uint8_t UUID_UNLOCK_CHAR[]           = UUID_URI_BEACON(0x20, 0x83);
00037 static const uint8_t UUID_URI_DATA_CHAR[]         = UUID_URI_BEACON(0x20, 0x84);
00038 static const uint8_t UUID_FLAGS_CHAR[]            = UUID_URI_BEACON(0x20, 0x85);
00039 static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
00040 static const uint8_t UUID_TX_POWER_MODE_CHAR[]    = UUID_URI_BEACON(0x20, 0x87);
00041 static const uint8_t UUID_BEACON_PERIOD_CHAR[]    = UUID_URI_BEACON(0x20, 0x88);
00042 static const uint8_t UUID_RESET_CHAR[]            = UUID_URI_BEACON(0x20, 0x89);
00043 extern const uint8_t       BEACON_EDDYSTONE[2];
00044 
00045 /**
00046 * @class EddystoneConfigService
00047 * @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags.
00048 * See https://github.com/google/eddystone
00049 *
00050 */
00051 class EddystoneConfigService
00052 {
00053 public:    
00054     /**
00055      * @brief Transmission Power Modes for UriBeacon
00056      */
00057     static const uint8_t TX_POWER_MODE_LOWEST = 0; /*!< Lowest TX power mode */
00058     static const uint8_t TX_POWER_MODE_LOW     = 1; /*!< Low TX power mode */
00059     static const uint8_t TX_POWER_MODE_MEDIUM  = 2; /*!< Medium TX power mode */
00060     static const uint8_t TX_POWER_MODE_HIGH    = 3; /*!< High TX power mode */
00061     static const unsigned NUM_POWER_MODES      = 4; /*!< Number of Power Modes defined */
00062 
00063     static const int ADVERTISING_INTERVAL_MSEC = 1000;  // Advertising interval for config service.
00064     static const int SERVICE_DATA_MAX = 31;             // Maximum size of service data in ADV packets
00065 
00066     typedef uint8_t Lock_t[16];               /* 128 bits */
00067     typedef int8_t PowerLevels_t[NUM_POWER_MODES ];
00068 
00069     // There are currently 3 subframes defined, URI, UID, and TLM
00070 #define EDDYSTONE_MAX_FRAMETYPE 3
00071     void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
00072     uint8_t frameIndex;
00073     static const int URI_DATA_MAX = 18;
00074     typedef uint8_t  UriData_t[URI_DATA_MAX];
00075 
00076     // UID Frame Type subfields
00077     static const int UID_NAMESPACEID_SIZE = 10;
00078     typedef uint8_t  UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
00079     static const int UID_INSTANCEID_SIZE = 6;
00080     typedef uint8_t  UIDInstanceID_t[UID_INSTANCEID_SIZE];
00081 
00082     // Eddystone Frame Type ID
00083     static const uint8_t FRAME_TYPE_UID = 0x00;
00084     static const uint8_t FRAME_TYPE_URL = 0x10;
00085     static const uint8_t FRAME_TYPE_TLM = 0x20;
00086 
00087     static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
00088     static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
00089 
00090     struct Params_t {
00091         // Config Data
00092         bool          isConfigured;  // Flag for configuration being complete, True = configured, false = not configured. Reset at instantiation, used for external callbacks. 
00093         bool          deepSleep;     // Flag set so device boots into deep sleep, button press turns on beacon
00094         uint8_t       lockedState;
00095         Lock_t        lock;
00096         uint8_t       flags;
00097         PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels
00098         uint8_t       txPowerMode;    // Firmware power levels used with setTxPower()
00099         uint16_t      beaconPeriod;
00100         // TLM Frame Data
00101         uint8_t       tlmVersion;     // version of TLM packet
00102         bool          tlmEnabled;
00103         float       tlmBeaconPeriod; // how often to broadcat TLM frame, in S
00104         // URI Frame Data
00105         uint8_t       uriDataLength;
00106         UriData_t     uriData;
00107         bool          uriEnabled;
00108         float       uriBeaconPeriod; // how often to broadcast URIFrame, in S
00109         // UID Frame Data
00110         UIDNamespaceID_t uidNamespaceID; // UUID type, Namespace ID, 10B
00111         UIDInstanceID_t  uidInstanceID;  // UUID type, Instance ID,  6B
00112         bool          uidEnabled;
00113         float       uidBeaconPeriod;   // how often to broadcast UID Frame, in S
00114     };
00115 
00116     /**
00117      * @param[ref]    ble
00118      *                    BLEDevice object for the underlying controller.
00119      * @param[in/out] paramsIn
00120      *                    Reference to application-visible beacon state, loaded
00121      *                    from persistent storage at startup.
00122      * @param[in]     defaultAdvPowerLevelsIn
00123      *                    Default power-levels array; applies only if the resetToDefaultsFlag is true.
00124      */
00125     EddystoneConfigService (BLEDevice     &bleIn,
00126                            Params_t      &paramsIn,
00127                            PowerLevels_t &defaultAdvPowerLevelsIn,
00128                            PowerLevels_t &radioPowerLevelsIn) :
00129         ble(bleIn),
00130         params(paramsIn),       // Initialize URL Data
00131         defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
00132         radioPowerLevels(radioPowerLevelsIn),
00133         initSucceeded(false),
00134         resetFlag(),
00135         defaultUidNamespaceID(), // Initialize UID Data
00136         defaultUidInstanceID(),
00137         defaultUidPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
00138         uidIsSet(false),
00139         defaultUriDataLength(),
00140         defaultUriData(),
00141         defaultUrlPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
00142         urlIsSet(false),
00143         tlmIsSet(false),
00144         lockedStateChar(UUID_LOCK_STATE_CHAR, &params.lockedState),
00145         lockChar(UUID_LOCK_CHAR, &params.lock),
00146         uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
00147                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
00148         unlockChar(UUID_UNLOCK_CHAR, &params.lock),
00149         flagsChar(UUID_FLAGS_CHAR, &params.flags),
00150         advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, &params.advPowerLevels),
00151         txPowerModeChar(UUID_TX_POWER_MODE_CHAR, &params.txPowerMode),
00152         beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, &params.beaconPeriod),
00153         resetChar(UUID_RESET_CHAR, &resetFlag) 
00154         {
00155         // set eddystone as not configured yet. Used to exit config before timeout if GATT services are written to.
00156         params.isConfigured = false;
00157     }
00158     
00159     /*
00160     * @breif Start EddystoneConfig advertising. This function should be called after the EddystoneConfig constructor and after all the frames have been added. 
00161     * @paramsP[in]   resetToDefaultsFlag
00162      *                    Applies to the state of the 'paramsIn' parameter.
00163      *                    If true, it indicates that paramsIn is potentially
00164      *                    un-initialized, and default values should be used
00165      *                    instead. Otherwise, paramsIn overrides the defaults.
00166     * 
00167     */
00168     void start(bool resetToDefaultsFlag){
00169         INFO("reset to defaults flag = %d", resetToDefaultsFlag);
00170         if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
00171             INFO("Reset to Defaults triggered");
00172             resetToDefaultsFlag = true;
00173         }
00174 
00175         lockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::lockAuthorizationCallback);
00176         unlockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::unlockAuthorizationCallback);
00177         uriDataChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::uriDataWriteAuthorizationCallback);
00178         flagsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
00179         advPowerLevelsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<PowerLevels_t>);
00180         txPowerModeChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::powerModeAuthorizationCallback);
00181         beaconPeriodChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint16_t>);
00182         resetChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
00183 
00184         static GattCharacteristic *charTable[] = {
00185             &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
00186             &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
00187         };
00188 
00189         GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00190 
00191         ble.addService(configService);
00192         if (resetToDefaultsFlag) {
00193             resetToDefaults();
00194         } else {
00195             updateCharacteristicValues();
00196         }
00197         
00198         ble.onDataWritten(this, &EddystoneConfigService::onDataWrittenCallback);
00199 
00200         setupEddystoneConfigAdvertisements(); /* Setup advertising for the configService. */
00201 
00202         initSucceeded = true;
00203     }
00204 
00205     /*
00206     * Check if eddystone initialized successfully
00207     */
00208     bool initSuccessfully(void) const {
00209         return initSucceeded;
00210     }
00211     
00212     /*
00213     * @breif Function to update the default values for the TLM frame. Only applied if Reset Defaults is applied. 
00214     *
00215     * @param[in] tlmVersionIn     Version of the TLM frame being used
00216     * @param[in] advPeriodInMin how long between TLM frames being advertised, this is measured in minutes.
00217     *
00218     */
00219     void setDefaultTLMFrameData(uint8_t tlmVersionIn = 0, float advPeriodInSec = 60){
00220         DBG("Setting Default TLM Data, version = %d, advPeriodInMind= %f",tlmVersionIn,advPeriodInSec);
00221         defaultTlmVersion = tlmVersionIn;
00222         TlmBatteryVoltage = 0;
00223         TlmBeaconTemp = 0;
00224         TlmPduCount = 0;
00225         TlmTimeSinceBoot = 0;
00226         defaultTlmAdvPeriod = advPeriodInSec;
00227         tlmIsSet = true; // flag to add this to eddystone service when config is done
00228     
00229     }
00230     
00231     /*
00232     * @breif Function to update the default values for the URI frame. Only applied if Reset Defaults is applied. 
00233     *
00234     * @param[in] uriIn      url to advertise
00235     * @param[in] advPeriod  how long to advertise the url for, measured in number of ADV frames.
00236     *
00237     */
00238     void setDefaultURIFrameData(const char * uriIn, float  advPeriod = 1){
00239         DBG("Setting Default URI Data");
00240         // Set URL Frame
00241           EddystoneService::encodeURL(uriIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
00242         if (defaultUriDataLength > URI_DATA_MAX) {
00243             return;
00244         }
00245         //memcpy(defaultUriData,uriIn,URI_DATA_MAX);
00246         //defaultUriDataLength = strlen(uriIn);
00247         INFO("\t default URI = %s : %d", uriIn, defaultUriDataLength);
00248 //              defaultUriData = (UriData_t *)uriIn;
00249         defaultUriAdvPeriod = advPeriod;
00250         urlIsSet = true; // flag to add this to eddystone service when config is done
00251     }
00252     
00253     /*
00254     * @breif 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 for, 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 configService for a limited time after
00271      * startup; and switch to the normal non-connectible beacon functionality
00272      * afterwards. */
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 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(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(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         // Setup Eddystone Service 
00311         static EddystoneService eddyServ(ble,params.beaconPeriod,radioPowerLevels[params.txPowerMode]);
00312         // Set configured frames (TLM,UID,URI...etc)
00313         if(params.tlmEnabled){
00314             eddyServ.setTLMFrameData(params.tlmVersion,params.tlmBeaconPeriod);
00315         }
00316         if(params.uriEnabled){
00317             eddyServ.setURLFrameData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriBeaconPeriod);
00318         }
00319         if(params.uidEnabled){
00320             eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode], (uint8_t *) params.uidNamespaceID, (uint8_t *) params.uidInstanceID, params.uidBeaconPeriod);
00321         }        
00322         // Start Advertising the eddystone service. 
00323         eddyServ.start(); 
00324     }
00325 
00326 private:
00327 
00328     /*
00329      * This callback is invoked when a GATT client attempts to modify any of the
00330      * characteristics of this service. Attempts to do so are also applied to
00331      * the internal state of this service object.
00332      */
00333     void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
00334         uint16_t handle = writeParams->handle;
00335 
00336         if (handle == lockChar.getValueHandle()) {
00337             // Validated earlier
00338             memcpy(params.lock, writeParams->data, sizeof(Lock_t));
00339             // Set the state to be locked by the lock code (note: zeros are a valid lock)
00340             params.lockedState = true;
00341             INFO("Device Locked");
00342         } else if (handle == unlockChar.getValueHandle()) {
00343             // Validated earlier
00344             params.lockedState = false;
00345             INFO("Device Unlocked");
00346         } else if (handle == uriDataChar.getValueHandle()) {
00347             params.uriDataLength = writeParams->len;
00348             memset(params.uriData,0x00,URI_DATA_MAX); // clear URI string
00349             memcpy(params.uriData, writeParams->data, params.uriDataLength); // set URI string
00350             params.uriEnabled = true;
00351             INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
00352         } else if (handle == flagsChar.getValueHandle()) {
00353             params.flags = *(writeParams->data);
00354             INFO("flagsChar = 0x%x",params.flags);
00355         } else if (handle == advPowerLevelsChar.getValueHandle()) {
00356             memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
00357             INFO("PowerLevelsChar = %4x",params.advPowerLevels);
00358         } else if (handle == txPowerModeChar.getValueHandle()) {
00359             params.txPowerMode = *(writeParams->data);
00360             INFO("TxPowerModeChar = %d",params.txPowerMode);
00361         } else if (handle == beaconPeriodChar.getValueHandle()) {
00362             params.beaconPeriod = *((uint16_t *)(writeParams->data));
00363             INFO("BeaconPeriod = %d",params.beaconPeriod);
00364 
00365             /* Re-map beaconPeriod to within permissible bounds if necessary. */
00366             if (params.beaconPeriod != 0) {
00367                 bool paramsUpdated = false;
00368                 if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
00369                     params.beaconPeriod = ble.getMinAdvertisingInterval();
00370                     paramsUpdated = true;
00371                 } else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
00372                     params.beaconPeriod = ble.getMaxAdvertisingInterval();
00373                     paramsUpdated = true;
00374                 }
00375                 if (paramsUpdated) {
00376                     ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(&params.beaconPeriod), sizeof(uint16_t));
00377                 }
00378             }
00379         } else if (handle == resetChar.getValueHandle()) {
00380             INFO("Reset triggered from Config Service, resetting to defaults");
00381             resetToDefaults();
00382         }
00383         updateCharacteristicValues();
00384         params.isConfigured = true; // some configuration data has been passed, on disconnect switch to advertising mode.
00385     }
00386 
00387     /*
00388      * Reset the default values.
00389      */
00390     void resetToDefaults(void) {
00391         INFO("Resetting to defaults");
00392         // General
00393         params.lockedState      = false;
00394         params.deepSleep        = true; // boot into deepSleep
00395         memset(params.lock, 0, sizeof(Lock_t));
00396         params.flags            = 0x10;
00397         memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
00398         params.txPowerMode      = TX_POWER_MODE_LOW ;
00399         params.beaconPeriod     = 1000;
00400         
00401         // TLM Frame
00402         params.tlmVersion = defaultTlmVersion;
00403         params.tlmBeaconPeriod = defaultTlmAdvPeriod;
00404         params.tlmEnabled = tlmIsSet;
00405         
00406         // URL Frame
00407         memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
00408         params.uriDataLength    = defaultUriDataLength;
00409         params.uriBeaconPeriod  = defaultUriAdvPeriod;
00410         params.uriEnabled = urlIsSet;
00411         
00412         // UID Frame
00413         memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
00414         memcpy(params.uidInstanceID,  defaultUidInstanceID,  UID_INSTANCEID_SIZE);
00415         params.uidBeaconPeriod = defaultUidAdvPeriod;
00416         params.uidEnabled = uidIsSet;
00417         
00418         updateCharacteristicValues();
00419     }
00420 
00421     /*
00422      * Internal helper function used to update the GATT database following any
00423      * change to the internal state of the service object.
00424      */
00425     void updateCharacteristicValues(void) {
00426         ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), &params.lockedState, 1);
00427         ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength); // TODO: this isnt updating the initial URI in config mode, need to figure out why.
00428         INFO("updateCharacteristicValues - URI, %s : %d",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 
00451     void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00452         if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) {
00453             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00454         } else if (authParams->len != sizeof(Lock_t)) {
00455             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00456         } else if (authParams->offset != 0) {
00457             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00458         } else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
00459             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00460         } else {
00461             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00462         }
00463     }
00464 
00465     void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00466         if (params.lockedState) {
00467             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00468         } else if (authParams->offset != 0) {
00469             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00470         } else {
00471             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00472         }
00473     }
00474 
00475     void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00476         if (params.lockedState) {
00477             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00478         } else if (authParams->len != sizeof(uint8_t)) {
00479             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00480         } else if (authParams->offset != 0) {
00481             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00482         } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES ) {
00483             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
00484         } else {
00485             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00486         }
00487     }
00488 
00489     template <typename T>
00490     void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
00491         if (params.lockedState) {
00492             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
00493         } else if (authParams->len != sizeof(T)) {
00494             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
00495         } else if (authParams->offset != 0) {
00496             authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
00497         } else {
00498             authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
00499         }
00500     }
00501 
00502     BLEDevice           &ble;
00503     Params_t            &params;
00504     Ticker              timeSinceBootTick;
00505     Timeout             switchFrame;
00506 // Default value that is restored on reset
00507     PowerLevels_t       &defaultAdvPowerLevels; // this goes into the advertising frames (radio power measured at 1m from device)
00508     PowerLevels_t       &radioPowerLevels;   // this configures the power levels of the radio
00509     uint8_t             lockedState;
00510     bool                initSucceeded;
00511     uint8_t             resetFlag;
00512     bool                switchFlag;
00513 
00514 //UID Default value that is restored on reset
00515     UIDNamespaceID_t    defaultUidNamespaceID;
00516     UIDInstanceID_t     defaultUidInstanceID;
00517     float               defaultUidAdvPeriod;
00518     int8_t              defaultUidPower;
00519     uint16_t            uidRFU;
00520     bool                uidIsSet;
00521 
00522 //URI  Default value that is restored on reset
00523     uint8_t             defaultUriDataLength;
00524     UriData_t           defaultUriData;
00525     int8_t              defaultUrlPower;
00526     float               defaultUriAdvPeriod;
00527     bool                urlIsSet;
00528 
00529 //TLM  Default value that is restored on reset
00530     uint8_t             defaultTlmVersion;
00531     float               defaultTlmAdvPeriod;
00532     volatile uint16_t   TlmBatteryVoltage;
00533     volatile uint16_t   TlmBeaconTemp;
00534     volatile uint32_t   TlmPduCount;
00535     volatile uint32_t   TlmTimeSinceBoot;
00536     bool                tlmIsSet;
00537 
00538     ReadOnlyGattCharacteristic<uint8_t>        lockedStateChar;
00539     WriteOnlyGattCharacteristic<Lock_t>        lockChar;
00540     GattCharacteristic                         uriDataChar;
00541     WriteOnlyGattCharacteristic<Lock_t>        unlockChar;
00542     ReadWriteGattCharacteristic<uint8_t>       flagsChar;
00543     ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
00544     ReadWriteGattCharacteristic<uint8_t>       txPowerModeChar;
00545     ReadWriteGattCharacteristic<uint16_t>      beaconPeriodChar;
00546     WriteOnlyGattCharacteristic<uint8_t>       resetChar;
00547 
00548 };
00549 
00550 #endif  // SERVICES_EDDYSTONEBEACONCONFIGSERVICE_H_