17 #ifndef SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_    18 #define SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_    20 #warning ble/services/EddystoneConfigService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.    22 #if BLE_FEATURE_GATT_SERVER    25 #include "ble/services/EddystoneService.h"    29 #define UUID_URI_BEACON(FIRST, SECOND) {                         \    30         0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba,       \    31         0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8,          \    34 static const uint8_t UUID_URI_BEACON_SERVICE[]    = UUID_URI_BEACON(0x20, 0x80);
    35 static const uint8_t UUID_LOCK_STATE_CHAR[]       = UUID_URI_BEACON(0x20, 0x81);
    36 static const uint8_t UUID_LOCK_CHAR[]             = UUID_URI_BEACON(0x20, 0x82);
    37 static const uint8_t UUID_UNLOCK_CHAR[]           = UUID_URI_BEACON(0x20, 0x83);
    38 static const uint8_t UUID_URI_DATA_CHAR[]         = UUID_URI_BEACON(0x20, 0x84);
    39 static const uint8_t UUID_FLAGS_CHAR[]            = UUID_URI_BEACON(0x20, 0x85);
    40 static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
    41 static const uint8_t UUID_TX_POWER_MODE_CHAR[]    = UUID_URI_BEACON(0x20, 0x87);
    42 static const uint8_t UUID_BEACON_PERIOD_CHAR[]    = UUID_URI_BEACON(0x20, 0x88);
    43 static const uint8_t UUID_RESET_CHAR[]            = UUID_URI_BEACON(0x20, 0x89);
    44 extern const uint8_t BEACON_EDDYSTONE[2];
    66     static const unsigned ADVERTISING_INTERVAL_MSEC = 1000; 
    67     static const unsigned SERVICE_DATA_MAX          = 31;   
    69     typedef uint8_t Lock_t[16];                             
    70     typedef int8_t PowerLevels_t[NUM_POWER_MODES];
    73 #define EDDYSTONE_MAX_FRAMETYPE 3    74     static const unsigned URI_DATA_MAX = 18;
    75     typedef uint8_t UriData_t[URI_DATA_MAX];
    78     static const size_t UID_NAMESPACEID_SIZE = 10;
    79     typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
    80     static const size_t UID_INSTANCEID_SIZE = 6;
    81     typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
    84     static const uint8_t FRAME_TYPE_UID = 0x00;
    85     static const uint8_t FRAME_TYPE_URL = 0x10;
    86     static const uint8_t FRAME_TYPE_TLM = 0x20;
    88     static const uint8_t FRAME_SIZE_TLM = 14; 
    89     static const uint8_t FRAME_SIZE_UID = 20; 
    98         PowerLevels_t    advPowerLevels;  
   100         uint16_t         beaconPeriod;
   104         float            tlmBeaconPeriod; 
   106         uint8_t          uriDataLength;
   109         float            uriBeaconPeriod; 
   111         UIDNamespaceID_t uidNamespaceID;  
   112         UIDInstanceID_t  uidInstanceID;   
   114         float            uidBeaconPeriod; 
   131                            PowerLevels_t &defaultAdvPowerLevelsIn,
   132                            PowerLevels_t &radioPowerLevelsIn) :
   135         defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
   136         radioPowerLevels(radioPowerLevelsIn),
   137         initSucceeded(false),
   139         defaultUidNamespaceID(), 
   140         defaultUidInstanceID(),
   141         defaultUidPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
   143         defaultUriDataLength(),
   145         defaultUrlPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
   148         lockedStateChar(UUID_LOCK_STATE_CHAR, ¶ms.lockedState),
   149         lockChar(UUID_LOCK_CHAR, ¶ms.lock),
   150         uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
   152         unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock),
   153         flagsChar(UUID_FLAGS_CHAR, ¶ms.flags),
   154         advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels),
   155         txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode),
   156         beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod),
   157         resetChar(UUID_RESET_CHAR, &resetFlag) {
   159         params.isConfigured = 
false;
   161         lockChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::lockAuthorizationCallback);
   162         unlockChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::unlockAuthorizationCallback);
   163         uriDataChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::uriDataWriteAuthorizationCallback);
   164         flagsChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
   165         advPowerLevelsChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::basicAuthorizationCallback<PowerLevels_t>);
   166         txPowerModeChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::powerModeAuthorizationCallback);
   167         beaconPeriodChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::basicAuthorizationCallback<uint16_t>);
   168         resetChar.setWriteAuthorizationCallback(
this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
   171             &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
   172             &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
   177         ble.addService(configService);
   178         ble.onDataWritten(
this, &EddystoneConfigService::onDataWrittenCallback);
   191     void start(
bool resetToDefaultsFlag){
   192         INFO(
"reset to defaults flag = %d", resetToDefaultsFlag);
   193         if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
   194             INFO(
"Reset to Defaults triggered");
   195             resetToDefaultsFlag = 
true;
   198         if (resetToDefaultsFlag) {
   201             updateCharacteristicValues();
   204         setupEddystoneConfigAdvertisements(); 
   205         initSucceeded = 
true;
   211     bool initSuccessfully(
void)
 const {
   212         return initSucceeded;
   222     void setDefaultTLMFrameData(uint8_t tlmVersionIn = 0, 
float advPeriodInSec = 60){
   223         DBG(
"Setting Default TLM Data, version = %d, advPeriodInMind= %f", tlmVersionIn, advPeriodInSec);
   224         defaultTlmVersion   = tlmVersionIn;
   225         TlmBatteryVoltage   = 0;
   226         TlmBeaconTemp       = 0x8000;
   228         TlmTimeSinceBoot    = 0;
   229         defaultTlmAdvPeriod = advPeriodInSec;
   240     void setDefaultURIFrameData(
const char *uriIn, 
float advPeriod = 1){
   241         DBG(
"Setting Default URI Data");
   243         EddystoneService::encodeURL(uriIn, defaultUriData, defaultUriDataLength);   
   244         if (defaultUriDataLength > URI_DATA_MAX) {
   247         INFO(
"\t  URI input = %s : %d", uriIn, defaultUriDataLength);
   248         INFO(
"\t default URI = %s : %d ", defaultUriData, defaultUriDataLength );
   249         defaultUriAdvPeriod = advPeriod;
   261     void setDefaultUIDFrameData(UIDNamespaceID_t *namespaceID, UIDInstanceID_t *instanceID, 
float advPeriod = 10){
   263         DBG(
"Setting default UID Data");
   264         memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
   265         memcpy(defaultUidInstanceID,  instanceID,  UID_INSTANCEID_SIZE);
   266         defaultUidAdvPeriod = advPeriod;
   273     void setupEddystoneConfigAdvertisements() {
   274         const char DEVICE_NAME[] = 
"eddystone Config";
   276         ble.clearAdvertisingPayload();
   281         uint8_t reversedServiceUUID[
sizeof(UUID_URI_BEACON_SERVICE)];
   282         for (
unsigned int i = 0; i < 
sizeof(UUID_URI_BEACON_SERVICE); i++) {
   283             reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[
sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
   288         ble.accumulateScanResponse(
   290             reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneConfigService::TX_POWER_MODE_LOW]),
   293         ble.setTxPower(radioPowerLevels[params.txPowerMode]);
   294         ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
   296         ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
   304     void setupEddystoneAdvertisements() {
   305         DBG(
"Switching Config -> adv");
   307         extern void saveURIBeaconConfigParams(
const Params_t *paramsP); 
   308         saveURIBeaconConfigParams(¶ms);
   309         INFO(
"Saved Params to Memory.")
   311         static EddystoneService eddyServ(
ble, params.beaconPeriod, radioPowerLevels[params.txPowerMode]);
   313         if (params.tlmEnabled) {
   314             eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
   316         if (params.uriEnabled) {
   317             eddyServ.
setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (
const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
   319         if (params.uidEnabled) {
   321                                      (uint8_t *)params.uidNamespaceID,
   322                                      (uint8_t *)params.uidInstanceID,
   323                                      params.uidBeaconPeriod);
   336         uint16_t handle = writeParams->
handle;
   338         if (handle == lockChar.getValueHandle()) {
   340             memcpy(params.lock, writeParams->
data, 
sizeof(Lock_t));
   342             params.lockedState = 
true;
   343             INFO(
"Device Locked");
   344         } 
else if (handle == unlockChar.getValueHandle()) {
   346             params.lockedState = 
false;
   347             INFO(
"Device Unlocked");
   348         } 
else if (handle == uriDataChar.getValueHandle()) {
   349             params.uriDataLength = writeParams->
len;
   350             memset(params.uriData, 0x00, URI_DATA_MAX);                      
   351             memcpy(params.uriData, writeParams->
data, writeParams->
len); 
   352             params.uriEnabled = 
true;
   353             INFO(
"URI = %s, URILen = %d", writeParams->
data, writeParams->
len);
   354         } 
else if (handle == flagsChar.getValueHandle()) {
   355             params.flags = *(writeParams->
data);
   356             INFO(
"flagsChar = 0x%x", params.flags);
   357         } 
else if (handle == advPowerLevelsChar.getValueHandle()) {
   358             memcpy(params.advPowerLevels, writeParams->
data, 
sizeof(PowerLevels_t));
   359             INFO(
"PowerLevelsChar = %4x", params.advPowerLevels);
   360         } 
else if (handle == txPowerModeChar.getValueHandle()) {
   361             params.txPowerMode = *(writeParams->
data);
   362             INFO(
"TxPowerModeChar = %d", params.txPowerMode);
   363         } 
else if (handle == beaconPeriodChar.getValueHandle()) {
   364             params.beaconPeriod = *((uint16_t *)(writeParams->
data));
   365             INFO(
"BeaconPeriod = %d", params.beaconPeriod);
   368             if (params.beaconPeriod != 0) {
   369                 bool paramsUpdated = 
false;
   370                 if (params.beaconPeriod < 
ble.getMinAdvertisingInterval()) {
   371                     params.beaconPeriod = 
ble.getMinAdvertisingInterval();
   372                     paramsUpdated       = 
true;
   373                 } 
else if (params.beaconPeriod > 
ble.getMaxAdvertisingInterval()) {
   374                     params.beaconPeriod = 
ble.getMaxAdvertisingInterval();
   375                     paramsUpdated       = 
true;
   378                     ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), 
reinterpret_cast<uint8_t *
>(¶ms.beaconPeriod), 
sizeof(uint16_t));
   381         } 
else if (handle == resetChar.getValueHandle()) {
   382             INFO(
"Reset triggered from Config Service, resetting to defaults");
   385         updateCharacteristicValues();
   386         params.isConfigured = 
true; 
   392     void resetToDefaults(
void) {
   393         INFO(
"Resetting to defaults");
   395         params.lockedState = 
false;
   396         memset(params.lock, 0, 
sizeof(Lock_t));
   398         memcpy(params.advPowerLevels, defaultAdvPowerLevels, 
sizeof(PowerLevels_t));
   399         params.txPowerMode  = TX_POWER_MODE_LOW;
   400         params.beaconPeriod = (uint16_t) defaultUriAdvPeriod * 1000;
   403         params.tlmVersion      = defaultTlmVersion;
   404         params.tlmBeaconPeriod = defaultTlmAdvPeriod;
   405         params.tlmEnabled      = tlmIsSet;
   408         memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
   409         params.uriDataLength   = defaultUriDataLength;
   410         params.uriBeaconPeriod = defaultUriAdvPeriod;
   411         params.uriEnabled      = urlIsSet;
   414         memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
   415         memcpy(params.uidInstanceID,  defaultUidInstanceID,  UID_INSTANCEID_SIZE);
   416         params.uidBeaconPeriod = defaultUidAdvPeriod;
   417         params.uidEnabled      = uidIsSet;
   419         updateCharacteristicValues();
   426     void updateCharacteristicValues(
void) {
   427         ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), ¶ms.lockedState, 1);
   428         ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
   429         ble.updateCharacteristicValue(flagsChar.getValueHandle(), ¶ms.flags, 1);
   430         ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
   431                                       reinterpret_cast<uint8_t *
>(¶ms.beaconPeriod), 
sizeof(uint16_t));
   432         ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1);
   433         ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
   434                                       reinterpret_cast<uint8_t *
>(params.advPowerLevels), 
sizeof(PowerLevels_t));
   439         if (params.lockedState) {
   441         } 
else if (authParams->
len != 
sizeof(Lock_t)) {
   443         } 
else if (authParams->
offset != 0) {
   451         if ((!params.lockedState) && (authParams->
len == 
sizeof(Lock_t))) {
   453         } 
else if (authParams->
len != 
sizeof(Lock_t)) {
   455         } 
else if (authParams->
offset != 0) {
   457         } 
else if (memcmp(authParams->
data, params.lock, 
sizeof(Lock_t)) != 0) {
   465         if (params.lockedState) {
   467         } 
else if (authParams->
offset != 0) {
   475         if (params.lockedState) {
   477         } 
else if (authParams->
len != 
sizeof(uint8_t)) {
   479         } 
else if (authParams->
offset != 0) {
   481         } 
else if (*((uint8_t *)authParams->
data) >= NUM_POWER_MODES) {
   488     template <
typename T>
   490         if (params.lockedState) {
   492         } 
else if (authParams->
len != 
sizeof(T)) {
   494         } 
else if (authParams->
offset != 0) {
   506     PowerLevels_t                              &defaultAdvPowerLevels; 
   507     PowerLevels_t                              &radioPowerLevels;      
   514     UIDNamespaceID_t                           defaultUidNamespaceID;
   515     UIDInstanceID_t                            defaultUidInstanceID;
   516     float                                      defaultUidAdvPeriod;
   517     int8_t                                     defaultUidPower;
   522     uint8_t                                    defaultUriDataLength;
   523     UriData_t                                  defaultUriData;
   524     int8_t                                     defaultUrlPower;
   525     float                                      defaultUriAdvPeriod;
   529     uint8_t                                    defaultTlmVersion;
   530     float                                      defaultTlmAdvPeriod;
   531     volatile uint16_t                          TlmBatteryVoltage;
   532     volatile uint16_t                          TlmBeaconTemp;
   533     volatile uint32_t                          TlmPduCount;
   534     volatile uint32_t                          TlmTimeSinceBoot;
   548 #endif // BLE_FEATURE_GATT_SERVER   550 #endif  // SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_ 
GattAuthCallbackReply_t authorizationReply
Authorization result. 
const uint8_t * data
Incoming data. 
const uint8_t * data
Pointer to the data to write. 
Abstract away BLE-capable radio transceivers or SOCs. 
GATT write authorization request event. 
Peripheral device is discoverable at any moment. 
Complete list of 128-bit Service IDs. 
ATT Error: Write not permitted. 
ATT Error: The specified offset was past the end of the attribute. 
GATT Write event definition. 
uint16_t len
Length (in bytes) of the data to write. 
Peripheral device is LE only and does not support Bluetooth Enhanced DataRate. 
EddystoneConfigService(BLEDevice &bleIn, Params_t ¶msIn, PowerLevels_t &defaultAdvPowerLevelsIn, PowerLevels_t &radioPowerLevelsIn)
Representation of a GattServer characteristic. 
void start(bool resetToDefaultsFlag)
Start EddystoneConfig advertising. 
uint16_t offset
Offset for the write operation. 
uint16_t len
Length of the incoming data. 
GattAttribute::Handle_t handle
Handle of the attribute to which the write operation applies. 
A Ticker is used to call a function at a recurring interval. 
Eddystone Configuration Service. 
Representation of a GattServer service. 
Device is connectable, scannable and doesn't expect connection from a specific peer. 
bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, float urlAdvPeriodIn)
Set Eddystone URL Frame information. 
Entry namespace for all BLE API definitions. 
ATT Error: Invalid value size. 
void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, float uidAdvPeriodIn, uint16_t RFU=0x0000)
Set Eddystone UID Frame information. 
ATT Error: Used in ATT as "insufficient authorization". 
A Timeout is used to call a function at a point in the future.