17 #ifndef SERVICES_URIBEACONCONFIGSERVICE_H_    18 #define SERVICES_URIBEACONCONFIGSERVICE_H_    21 #include "ble/pal/Deprecated.h"    23 #ifdef YOTTA_CFG_MBED_OS    24 #include "mbed-drivers/mbed.h"    29 #if BLE_FEATURE_GATT_SERVER    30 #if BLE_ROLE_BROADCASTER    32 BLE_DEPRECATED_API_USE_BEGIN()
    34 extern const uint8_t UUID_URI_BEACON_SERVICE[
UUID::LENGTH_OF_LONG_UUID];
    35 extern const uint8_t UUID_LOCK_STATE_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    36 extern const uint8_t UUID_LOCK_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    37 extern const uint8_t UUID_UNLOCK_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    38 extern const uint8_t UUID_URI_DATA_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    39 extern const uint8_t UUID_FLAGS_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    40 extern const uint8_t UUID_ADV_POWER_LEVELS_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    41 extern const uint8_t UUID_TX_POWER_MODE_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    42 extern const uint8_t UUID_BEACON_PERIOD_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    43 extern const uint8_t UUID_RESET_CHAR[
UUID::LENGTH_OF_LONG_UUID];
    45 extern const uint8_t BEACON_UUID[sizeof(
UUID::ShortUUIDBytes_t)];
    56     "This service is deprecated, and no replacement is currently available."
    63     static const uint8_t TX_POWER_MODE_LOWEST = 0; 
    64     static const uint8_t TX_POWER_MODE_LOW    = 1; 
    65     static const uint8_t TX_POWER_MODE_MEDIUM = 2; 
    66     static const uint8_t TX_POWER_MODE_HIGH   = 3; 
    67     static const unsigned NUM_POWER_MODES     = 4; 
    69     static const int ADVERTISING_INTERVAL_MSEC = 1000;  
    70     static const int SERVICE_DATA_MAX = 31;             
    72     typedef uint8_t Lock_t[16];               
    73     typedef int8_t PowerLevels_t[NUM_POWER_MODES];
    75     static const int URI_DATA_MAX = 18;
    76     typedef uint8_t  UriData_t[URI_DATA_MAX];
    80         uint8_t       uriDataLength;
    83         PowerLevels_t advPowerLevels; 
    85         uint16_t      beaconPeriod;
   108         "This service is deprecated, and no replacement is currently available."   110     URIBeaconConfigService(
BLE          &bleIn,
   112                            bool          resetToDefaultsFlag,
   113                            const 
char   *defaultURIDataIn,
   114                            PowerLevels_t &defaultAdvPowerLevelsIn) :
   117         defaultUriDataLength(),
   119         defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
   120         initSucceeded(false),
   122         lockedStateChar(UUID_LOCK_STATE_CHAR, &lockedState),
   123         lockChar(UUID_LOCK_CHAR, ¶ms.lock),
   124         uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
   126         unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock),
   127         flagsChar(UUID_FLAGS_CHAR, ¶ms.flags),
   128         advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels),
   129         txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode),
   130         beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod),
   131         resetChar(UUID_RESET_CHAR, &resetFlag) {
   133         encodeURI(defaultURIDataIn, defaultUriData, defaultUriDataLength);
   134         if (defaultUriDataLength > URI_DATA_MAX) {
   138         if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
   139             resetToDefaultsFlag = 
true;
   141         if (resetToDefaultsFlag) {
   144             updateCharacteristicValues();
   147         lockedState = isLocked();
   149         lockChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::lockAuthorizationCallback);
   150         unlockChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::unlockAuthorizationCallback);
   151         uriDataChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::uriDataWriteAuthorizationCallback);
   152         flagsChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::basicAuthorizationCallback<uint8_t>);
   153         advPowerLevelsChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::basicAuthorizationCallback<PowerLevels_t>);
   154         txPowerModeChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::powerModeAuthorizationCallback);
   155         beaconPeriodChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::basicAuthorizationCallback<uint16_t>);
   156         resetChar.setWriteAuthorizationCallback(
this, &URIBeaconConfigService::basicAuthorizationCallback<uint8_t>);
   159             &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
   160             &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
   165         ble.addService(configService);
   166         ble.onDataWritten(
this, &URIBeaconConfigService::onDataWrittenCallback);
   168         setupURIBeaconConfigAdvertisements(); 
   170         initSucceeded = 
true;
   173     bool configuredSuccessfully(
void)
 const {
   174         return initSucceeded;
   180     void setupURIBeaconConfigAdvertisements()
   182         const char DEVICE_NAME[] = 
"mUriBeacon Config";
   184         ble.gap().clearAdvertisingPayload();
   189         uint8_t reversedServiceUUID[
sizeof(UUID_URI_BEACON_SERVICE)];
   190         for (
unsigned int i = 0; i < 
sizeof(UUID_URI_BEACON_SERVICE); i++) {
   191             reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[
sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
   200         ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
   201         ble.gap().setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
   207     void setupURIBeaconAdvertisements()
   214         unsigned beaconPeriod                                 = params.beaconPeriod;
   215         unsigned txPowerMode                                  = params.txPowerMode;
   216         unsigned uriDataLength                                = params.uriDataLength;
   217         URIBeaconConfigService::UriData_t &uriData            = params.uriData;
   218         URIBeaconConfigService::PowerLevels_t &advPowerLevels = params.advPowerLevels;
   219         uint8_t flags                                         = params.flags;
   221         extern void saveURIBeaconConfigParams(
const Params_t *paramsP); 
   222         saveURIBeaconConfigParams(¶ms);
   224         ble.gap().clearAdvertisingPayload();
   225         ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
   227         ble.gap().setAdvertisingInterval(beaconPeriod);
   231         uint8_t serviceData[SERVICE_DATA_MAX];
   232         unsigned serviceDataLen = 0;
   233         serviceData[serviceDataLen++] = BEACON_UUID[0];
   234         serviceData[serviceDataLen++] = BEACON_UUID[1];
   235         serviceData[serviceDataLen++] = flags;
   236         serviceData[serviceDataLen++] = advPowerLevels[txPowerMode];
   237         for (
unsigned j = 0; j < uriDataLength; j++) {
   238             serviceData[serviceDataLen++] = uriData[j];
   247         memset(testLock, 0, 
sizeof(Lock_t));
   248         return memcmp(params.lock, testLock, 
sizeof(Lock_t));
   257         uint16_t handle = writeParams->
handle;
   259         if (handle == lockChar.getValueHandle()) {
   261             memcpy(params.lock, writeParams->
data, 
sizeof(Lock_t));
   263             lockedState = isLocked();
   264         } 
else if (handle == unlockChar.getValueHandle()) {
   266             memset(params.lock, 0, 
sizeof(Lock_t));
   268         } 
else if (handle == uriDataChar.getValueHandle()) {
   269             params.uriDataLength = writeParams->
len;
   270             memcpy(params.uriData, writeParams->
data, params.uriDataLength);
   271         } 
else if (handle == flagsChar.getValueHandle()) {
   272             params.flags = *(writeParams->
data);
   273         } 
else if (handle == advPowerLevelsChar.getValueHandle()) {
   274             memcpy(params.advPowerLevels, writeParams->
data, 
sizeof(PowerLevels_t));
   275         } 
else if (handle == txPowerModeChar.getValueHandle()) {
   276             params.txPowerMode = *(writeParams->
data);
   277         } 
else if (handle == beaconPeriodChar.getValueHandle()) {
   278             params.beaconPeriod = *((uint16_t *)(writeParams->
data));
   281             if (params.beaconPeriod != 0) {
   282                 bool paramsUpdated = 
false;
   283                 if (params.beaconPeriod < 
ble.gap().getMinAdvertisingInterval()) {
   284                     params.beaconPeriod = 
ble.gap().getMinAdvertisingInterval();
   285                     paramsUpdated = 
true;
   286                 } 
else if (params.beaconPeriod > 
ble.gap().getMaxAdvertisingInterval()) {
   287                     params.beaconPeriod = 
ble.gap().getMaxAdvertisingInterval();
   288                     paramsUpdated = 
true;
   291                     ble.gattServer().write(beaconPeriodChar.getValueHandle(), 
reinterpret_cast<uint8_t *
>(¶ms.beaconPeriod), 
sizeof(uint16_t));
   294         } 
else if (handle == resetChar.getValueHandle()) {
   302     void resetToDefaults(
void) {
   304         memset(params.lock, 0, 
sizeof(Lock_t));
   305         memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
   306         params.uriDataLength    = defaultUriDataLength;
   308         memcpy(params.advPowerLevels, defaultAdvPowerLevels, 
sizeof(PowerLevels_t));
   309         params.txPowerMode      = TX_POWER_MODE_LOW;
   310         params.beaconPeriod     = 1000;
   311         updateCharacteristicValues();
   318     void updateCharacteristicValues(
void) {
   319         ble.gattServer().write(lockedStateChar.getValueHandle(), &lockedState, 1);
   320         ble.gattServer().write(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
   321         ble.gattServer().write(flagsChar.getValueHandle(), ¶ms.flags, 1);
   322         ble.gattServer().write(beaconPeriodChar.getValueHandle(),
   323                                       reinterpret_cast<uint8_t *
>(¶ms.beaconPeriod), 
sizeof(uint16_t));
   324         ble.gattServer().write(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1);
   325         ble.gattServer().write(advPowerLevelsChar.getValueHandle(),
   326                                       reinterpret_cast<uint8_t *
>(params.advPowerLevels), 
sizeof(PowerLevels_t));
   333         } 
else if (authParams->
len != 
sizeof(Lock_t)) {
   335         } 
else if (authParams->
offset != 0) {
   346         } 
else if (authParams->
len != 
sizeof(Lock_t)) {
   348         } 
else if (authParams->
offset != 0) {
   350         } 
else if (memcmp(authParams->
data, params.lock, 
sizeof(Lock_t)) != 0) {
   360         } 
else if (authParams->
offset != 0) {
   370         } 
else if (authParams->
len != 
sizeof(uint8_t)) {
   372         } 
else if (authParams->
offset != 0) {
   374         } 
else if (*((uint8_t *)authParams->
data) >= NUM_POWER_MODES) {
   381     template <
typename T>
   385         } 
else if (authParams->
len != 
sizeof(T)) {
   387         } 
else if (authParams->
offset != 0) {
   398     size_t        defaultUriDataLength;   
   399     UriData_t     defaultUriData;         
   400     PowerLevels_t &defaultAdvPowerLevels; 
   420     static void encodeURI(
const char *uriDataIn, UriData_t uriDataOut, 
size_t &sizeofURIDataOut) {
   421         const char *prefixes[] = {
   428         const size_t NUM_PREFIXES = 
sizeof(prefixes) / 
sizeof(
char *);
   429         const char *suffixes[] = {
   445         const size_t NUM_SUFFIXES = 
sizeof(suffixes) / 
sizeof(
char *);
   447         sizeofURIDataOut = 0;
   448         memset(uriDataOut, 0, 
sizeof(UriData_t));
   450         if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
   457         for (
unsigned i = 0; i < NUM_PREFIXES; i++) {
   458             size_t prefixLen = strlen(prefixes[i]);
   459             if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
   460                 uriDataOut[sizeofURIDataOut++]  = i;
   461                 uriDataIn                      += prefixLen;
   469         while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
   472             for (i = 0; i < NUM_SUFFIXES; i++) {
   473                 size_t suffixLen = strlen(suffixes[i]);
   474                 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
   475                     uriDataOut[sizeofURIDataOut++]  = i;
   476                     uriDataIn                      += suffixLen;
   481             if (i == NUM_SUFFIXES) {
   482                 uriDataOut[sizeofURIDataOut++] = *uriDataIn;
   489 BLE_DEPRECATED_API_USE_END()
   491 #endif // BLE_ROLE_BROADCASTER   492 #endif // BLE_FEATURE_GATT_SERVER   494 #endif  // SERVICES_URIBEACONCONFIGSERVICE_H_ 
GattAuthCallbackReply_t authorizationReply
Authorization result. 
const uint8_t * data
Incoming data. 
const uint8_t * data
Pointer to the data to write. 
static uint16_t MSEC_TO_ADVERTISEMENT_DURATION_UNITS(uint32_t durationInMillis)
Convert milliseconds to units of 0.625ms. 
Abstract away BLE-capable radio transceivers or SOCs. 
UriBeacon Configuration Service. 
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. 
Representation of a Universally Unique Identifier (UUID). 
Complete list of 16-bit Service IDs. 
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. 
Representation of a GattServer characteristic. 
Device is not connectable and not scannable. 
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. 
Representation of a GattServer service. 
Device is connectable, scannable and doesn't expect connection from a specific peer. 
Entry namespace for all BLE API definitions. 
ATT Error: Invalid value size. 
ATT Error: Used in ATT as "insufficient authorization". 
static const uint8_t TX_POWER_MODE_LOW