Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: microbit-dal microbit-dal microbit-ble-open microbit-dal ... more
Fork of BLE_API by
Diff: services/URIBeaconConfigService.h
- Revision:
- 287:cca148e535b1
- Parent:
- 286:898ff71b9502
- Child:
- 300:d9a39f759a6a
diff -r 898ff71b9502 -r cca148e535b1 services/URIBeaconConfigService.h
--- a/services/URIBeaconConfigService.h Fri Feb 13 16:37:42 2015 +0000
+++ b/services/URIBeaconConfigService.h Fri Feb 13 16:37:42 2015 +0000
@@ -14,280 +14,282 @@
* limitations under the License.
*/
-#ifndef __BLE_URI_BEACON_CONFIG_SERVICE_H__
-#define __BLE_URI_BEACON_CONFIG_SERVICE_H__
+#ifndef SERVICES_URIBEACONCONFIGSERVICE_H_
+#define SERVICES_URIBEACONCONFIGSERVICE_H_
-#include "BLEDevice.h"
-
-#define URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(FIRST, SECOND) { \
+#define UUID_URI_BEACON(FIRST, SECOND) { \
0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba, \
0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8, \
}
-static const uint8_t URIBeacon2ControlServiceUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x80);
-static const uint8_t lockedStateCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x81);
-static const uint8_t lockCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x82);
-static const uint8_t unlockCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x83);
-static const uint8_t uriDataCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x84);
-static const uint8_t flagsCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x85);
-static const uint8_t txPowerLevelsCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x86);
-static const uint8_t txPowerModeCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x87);
-static const uint8_t beaconPeriodCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x88);
-static const uint8_t resetCharUUID[] = URI_BEACON_CONFIG_UUID_INITIALIZER_LIST(0x20, 0x89);
+
+static const uint8_t UUID_URI_BEACON_SERVICE[] = UUID_URI_BEACON(0x20, 0x80);
+static const uint8_t UUID_LOCK_STATE_CHAR[] = UUID_URI_BEACON(0x20, 0x81);
+static const uint8_t UUID_LOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x82);
+static const uint8_t UUID_UNLOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x83);
+static const uint8_t UUID_URI_DATA_CHAR[] = UUID_URI_BEACON(0x20, 0x84);
+static const uint8_t UUID_FLAGS_CHAR[] = UUID_URI_BEACON(0x20, 0x85);
+static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
+static const uint8_t UUID_TX_POWER_MODE_CHAR[] = UUID_URI_BEACON(0x20, 0x87);
+static const uint8_t UUID_BEACON_PERIOD_CHAR[] = UUID_URI_BEACON(0x20, 0x88);
+static const uint8_t UUID_RESET_CHAR[] = UUID_URI_BEACON(0x20, 0x89);
+static const uint8_t BEACON_UUID[] = {0xD8, 0xFE};
/**
* @class URIBeaconConfigService
* @brief UriBeacon Configuration Service. Can be used to set URL, adjust power levels, and set flags.
+* See http://uribeacon.org
+*
*/
class URIBeaconConfigService {
-public:
+ public:
/**
- * @enum TXPowerModes_t
* @brief Transmission Power Modes for UriBeacon
*/
- enum TXPowerModes_t {
- TX_POWER_MODE_LOWEST = 0, /*!< Lowest TX power mode */
- TX_POWER_MODE_LOW = 1, /*!< Low TX power mode */
- TX_POWER_MODE_MEDIUM = 2, /*!< Medium TX power mode */
- TX_POWER_MODE_HIGH = 3, /*!< High TX power mode */
- NUM_POWER_MODES /*!< Number of Power Modes defined */
+ static const uint8_t TX_POWER_MODE_LOWEST = 0; /*!< Lowest TX power mode */
+ static const uint8_t TX_POWER_MODE_LOW = 1; /*!< Low TX power mode */
+ static const uint8_t TX_POWER_MODE_MEDIUM = 2; /*!< Medium TX power mode */
+ static const uint8_t TX_POWER_MODE_HIGH = 3; /*!< High TX power mode */
+ static const unsigned int NUM_POWER_MODES = 4; /*!< Number of Power Modes defined */
+
+
+ typedef uint8_t Lock_t[16]; /* 128 bits */
+ typedef int8_t PowerLevels_t[NUM_POWER_MODES];
+
+ static const int URI_DATA_MAX = 18;
+ typedef uint8_t UriData_t[URI_DATA_MAX];
+
+ struct Params_t {
+ Lock_t lock;
+ uint8_t uriDataLength;
+ UriData_t uriData;
+ uint8_t flags;
+ // Current value of AdvertisedPowerLevels
+ PowerLevels_t advPowerLevels;
+ // Firmware power levels used with setTxPower()
+ uint8_t txPowerMode;
+ uint16_t beaconPeriod;
};
- static const size_t SIZEOF_LOCK_BITS = 16; /* uint128 */
- typedef uint8_t LockBits_t[SIZEOF_LOCK_BITS];
/**
- * @param[ref] ble
- * BLEDevice object for the underlying controller.
- * @param[in] uridata
- * URI as a null-terminated string.
- * @param[in] flagsIn
- * UriBeacon Flags.
- * @param[in] powerLevels[]
- * Table of UriBeacon Tx Power Levels in dBm.
- * @param[in] powerMode
- * Currently effective power mode.
- * @param[in] beaconPeriodIn
- * The period in milliseconds that a UriBeacon packet is
- * transmitted. A value of zero disables UriBeacon
- * transmissions.
+ * @param[ref] ble
+ * BLEDevice object for the underlying controller.
+ * @param[in/out] paramsIn
+ * Reference to application-visible beacon state, loaded
+ * from persistent storage at startup.
+ * @param[in] resetToDefaultsFlag
+ * reset params state to the defaults.
+ * @param[in] defaultUriDataIn
+ * Default encoded URIData; applies only if the resetToDefaultsFlag is true.
+ * @param[in] defaultUriDataLengthIn
+ * Length of the default encoded URIData (from above); applies only if the resetToDefaultsFlag is true.
+ * @param[in] defaultAdvPowerLevelsIn
+ * Default power-levels array; applies only if the resetToDefaultsFlag is true.
*/
- URIBeaconConfigService(BLEDevice &bleIn,
- const char *uriDataIn,
- uint8_t flagsIn = 0,
- const int8_t powerLevelsIn[NUM_POWER_MODES] = NULL,
- TXPowerModes_t powerModeIn = TX_POWER_MODE_LOW,
- uint16_t beaconPeriodIn = 1000) :
+ URIBeaconConfigService(BLEDevice &bleIn,
+ Params_t ¶msIn,
+ bool resetToDefaultsFlag,
+ UriData_t &defaultUriDataIn,
+ int defaultUriDataLengthIn,
+ PowerLevels_t &defaultAdvPowerLevelsIn) :
ble(bleIn),
- payloadIndex(0),
- serviceDataPayload(),
+ params(paramsIn),
+ defaultUriDataLength(defaultUriDataLengthIn),
+ defaultUriData(defaultUriDataIn),
+ defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
initSucceeded(false),
- lockedState(false),
- lockBits(),
- uriDataLength(0),
- uriData(),
- flags(flagsIn),
- powerLevels(),
- beaconPeriod(beaconPeriodIn),
- lockedStateChar(lockedStateCharUUID, &lockedState),
- lockChar(lockCharUUID, lockBits),
- unlockChar(unlockCharUUID, lockBits),
- uriDataChar(uriDataCharUUID, uriData),
- flagsChar(flagsCharUUID, &flags),
- txPowerLevelsChar(txPowerLevelsCharUUID, powerLevels),
- txPowerModeChar(txPowerModeCharUUID, &txPowerMode),
- beaconPeriodChar(beaconPeriodCharUUID, &beaconPeriod),
- resetChar(resetCharUUID, &resetFlag)
- {
- if ((uriDataIn == NULL) || ((uriDataLength = strlen(uriDataIn)) == 0) || (uriDataLength > MAX_SIZE_URI_DATA_CHAR_VALUE)) {
+ lockedStateChar(UUID_LOCK_STATE_CHAR, &lockedState),
+ lockChar(UUID_LOCK_CHAR, ¶ms.lock),
+ uriDataChar(UUID_URI_DATA_CHAR, params.uriData, URI_DATA_MAX, params.uriDataLength,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
+ unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock),
+ flagsChar(UUID_FLAGS_CHAR, ¶ms.flags),
+ advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels),
+ txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode),
+ beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod),
+ resetChar(UUID_RESET_CHAR, &resetFlag) {
+ if (defaultUriDataLengthIn > URI_DATA_MAX) {
return;
}
- strcpy(reinterpret_cast<char *>(uriData), uriDataIn);
- if (powerLevelsIn != NULL) {
- memcpy(powerLevels, powerLevelsIn, sizeof(powerLevels));
- updateTxPowerLevelsCharacteristic();
+ if (params.uriDataLength > URI_DATA_MAX) {
+ resetToDefaultsFlag = true;
}
- configureGAP();
+ lockedState = isLocked();
- // enable the following for debugging the state of the lock
- // lockedStateChar.setReadAuthorizationCallback(this, &URIBeaconConfigService::lockedStateAuthorizationCallback);
+ if (resetToDefaultsFlag) {
+ resetToDefaults();
+ } else {
+ updateCharacteristicValues();
+ }
lockChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::lockAuthorizationCallback);
unlockChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::unlockAuthorizationCallback);
uriDataChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::uriDataWriteAuthorizationCallback);
flagsChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::flagsAuthorizationCallback);
- txPowerLevelsChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::denyGATTWritesIfLocked);
- txPowerModeChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::powerModeAuthorizationCallback);
+ advPowerLevelsChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::denyGATTWritesIfLocked);
+ txPowerModeChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::denyGATTWritesIfLocked);
beaconPeriodChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::denyGATTWritesIfLocked);
resetChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::denyGATTWritesIfLocked);
- GattCharacteristic *charTable[] = {&lockedStateChar,
- &lockChar,
- &unlockChar,
- &uriDataChar,
- &flagsChar,
- &txPowerLevelsChar,
- &beaconPeriodChar,
- &resetChar};
- GattService beaconControlService(URIBeacon2ControlServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
- ble.addService(beaconControlService);
+ static GattCharacteristic *charTable[] = {
+ &lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
+ &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
+ };
- ble.onDataWritten(this, &URIBeaconConfigService::onDataWritten);
+ GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+ ble.addService(configService);
+ ble.onDataWritten(this, &URIBeaconConfigService::onDataWrittenCallback);
+
+ initSucceeded = true;
}
bool configuredSuccessfully(void) const {
return initSucceeded;
}
- /**
- * Please note that the following public APIs are offered to allow modifying
- * the service programmatically. It is also possible to do so over BLE GATT
- * transactions.
- */
-public:
- /**
- * Update flags of the URIBeacon dynamically.
- *
- * @param[in] flagsIn
- * @verbatim
- * ### UriBeacon Flags
- * Bit | Description
- * :---- | :----------
- * 0 | Invisible Hint
- * 1..7 | Reserved for future use. Must be zero.
- * @endverbatim
- * The `Invisible Hint` flag is a command for the user-agent that tells
- * it not to access or display the UriBeacon. This is a guideline only,
- * and is not a blocking method. User agents may, with user approval,
- * display invisible beacons.
- */
- void setFlags(uint8_t flagsIn) {
- flags = flagsIn;
- configureGAP();
- updateFlagsCharacteristic();
+
+ private:
+ // True if the lock bits are non-zero
+ bool isLocked() {
+ Lock_t testLock;
+ memset(testLock, 0, sizeof(Lock_t));
+ return memcmp(params.lock, testLock, sizeof(Lock_t));
}
- /**
- * @brief Update the txPowerLevels table.
- *
- * @param[in] powerLevelsIn
- * Array of power levels
- */
- void setTxPowerLevels(const int8_t powerLevelsIn[NUM_POWER_MODES]) {
- memcpy(powerLevels, powerLevelsIn, sizeof(powerLevels));
- configureGAP();
- updateTxPowerLevelsCharacteristic();
- }
-
- /**
- * @brief Set the effective power mode from one of the values in the powerLevels tables.
- *
- * @param[in] mode
- * Set the TX Power Mode.
+ /*
+ * This callback is invoked when a GATT client attempts to modify any of the
+ * characteristics of this service. Attempts to do so are also applied to
+ * the internal state of this service object.
*/
- void setTxPowerMode(TXPowerModes_t mode) {
- txPowerMode = mode;
- configureGAP();
- updateTxPowerModeCharacteristic();
- }
+ void onDataWrittenCallback(const GattCharacteristicWriteCBParams *writeParams) {
+ uint16_t handle = writeParams->charHandle;
- /**
- * The period in milliseconds that a UriBeacon packet is transmitted.
- *
- * @note A value of zero disables UriBeacon transmissions.
- *
- * @param beaconPeriodIn
- * Beacon advertising period in milliseconds
- */
- void setBeaconPeriod(uint16_t beaconPeriodIn) {
- beaconPeriod = beaconPeriodIn;
- configureGAP();
- updateBeaconPeriodCharacteristic();
- }
-
-protected:
- void updateLockBits(const LockBits_t lockBitsIn) {
- static const uint8_t allZeroes[SIZEOF_LOCK_BITS] = {0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0};
-
- memcpy(lockBits, lockBitsIn, SIZEOF_LOCK_BITS);
- if (memcmp(lockBits, allZeroes, SIZEOF_LOCK_BITS)) {
- lockedState = true;
+ if (handle == lockChar.getValueHandle()) {
+ // Validated earlier
+ memcpy(params.lock, writeParams->data, sizeof(Lock_t));
+ // use isLocked() in case bits are being set to all 0's
+ lockedState = isLocked();
+ } else if (handle == unlockChar.getValueHandle()) {
+ // Validated earlier
+ memset(params.lock, 0, sizeof(Lock_t));
+ lockedState = false;
+ } else if (handle == uriDataChar.getValueHandle()) {
+ params.uriDataLength = writeParams->len;
+ memcpy(params.uriData, writeParams->data, params.uriDataLength);
+ } else if (handle == flagsChar.getValueHandle()) {
+ params.flags = *(writeParams->data);
+ } else if (handle == advPowerLevelsChar.getValueHandle()) {
+ memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
+ } else if (handle == txPowerModeChar.getValueHandle()) {
+ params.txPowerMode = *(writeParams->data);
+ } else if (handle == beaconPeriodChar.getValueHandle()) {
+ params.beaconPeriod = *((uint16_t *)(writeParams->data));
+ } else if (handle == resetChar.getValueHandle()) {
+ resetToDefaults();
}
}
- void copyLockBitsInto(LockBits_t lockBitsOut) const {
- memcpy(lockBitsOut, lockBits, SIZEOF_LOCK_BITS);
- }
-
- void resetLockBits(void) {
- lockedState = false;
- memset(lockBits, 0, SIZEOF_LOCK_BITS);
- storage_saveLockBits();
- }
-
- /**
- * APIs around making lockBits persistent.
- */
-private:
- /**
- * Have we previously saved lockedBits? Once set, this state is expected to persist.
- * @return true if we've previously saved locked bits.
- */
- virtual bool storage_haveSavedLockBits() const {
- /* Expecting to be overridden. Left empty to allow the default URIBeacon to be instantiated if persistence isn't required. */
- return false;
- }
-
- /**
- * Save the current value of lockBits into persistent storage; this value is then retrievable by lockLockBits() until a subsequent call to saveLockBits().
+ /*
+ * Reset the default values.
*/
- virtual void storage_saveLockBits() {
- /* Expecting to be overridden. Left empty to allow the default URIBeacon to be instantiated if persistence isn't required. */
- }
-
- /**
- * Retrieve the saved lockBits from persistent storage and update the class member 'lockBits'.
- */
- virtual void storage_loadLockBits() {
- /* Expecting to be overridden. Left empty to allow the default URIBeacon to be instantiated if persistence isn't required. */
- }
-
-private:
- /*
- * Setup the advertisement payload and GAP settings.
- */
- void configureGAP(void) {
- const uint8_t BEACON_UUID[] = {0xD8, 0xFE};
-
- payloadIndex = 0;
- serviceDataPayload[payloadIndex++] = BEACON_UUID[0];
- serviceDataPayload[payloadIndex++] = BEACON_UUID[1];
- serviceDataPayload[payloadIndex++] = flags;
- serviceDataPayload[payloadIndex++] = powerLevels[txPowerMode];
-
- const char *urlData = reinterpret_cast<char *>(uriData);
- size_t sizeofURLData = uriDataLength;
- size_t encodedBytes = encodeURISchemePrefix(urlData, sizeofURLData) + encodeURI(urlData, sizeofURLData);
-
- ble.clearAdvertisingPayload();
- ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_UUID, sizeof(BEACON_UUID));
- ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceDataPayload, encodedBytes + 4);
-
- ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(beaconPeriod));
- ble.setTxPower(powerLevels[txPowerMode]);
+ void resetToDefaults(void) {
+ lockedState = false;
+ memset(params.lock, 0, sizeof(Lock_t));
+ memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
+ params.uriDataLength = defaultUriDataLength;
+ params.flags = 0;
+ memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
+ params.txPowerMode = TX_POWER_MODE_LOW;
+ params.beaconPeriod = 1000;
+ updateCharacteristicValues();
}
/*
- * Encode the URI Prefix to a single byte if possible.
+ * Internal helper function used to update the GATT database following any
+ * change to the internal state of the service object.
*/
- size_t encodeURISchemePrefix(const char *&urldata, size_t &sizeofURLData) {
- if (!sizeofURLData) {
- return 0;
+ void updateCharacteristicValues(void) {
+ ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), &lockedState, 1);
+ ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
+ ble.updateCharacteristicValue(flagsChar.getValueHandle(), ¶ms.flags, 1);
+ ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
+ reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t));
+ ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1);
+ ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
+ reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
+ }
+
+ private:
+ void lockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
+ authParams->authorizationReply = (authParams->len == sizeof(Lock_t)) && !lockedState;
+ }
+
+
+ void unlockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
+ if (!lockedState || (authParams->len == sizeof(Lock_t) && (memcmp(authParams->data, params.lock, sizeof(Lock_t)) == 0))) {
+ authParams->authorizationReply = true;
+ } else {
+ authParams->authorizationReply = false;
+ }
+ }
+
+ void uriDataWriteAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
+ if (lockedState || (authParams->offset != 0) || (authParams->len > URI_DATA_MAX)) {
+ authParams->authorizationReply = false;
+ }
+ }
+
+ void flagsAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
+ if (lockedState || authParams->len != 1) {
+ authParams->authorizationReply = false;
+ }
+ }
+
+ void denyGATTWritesIfLocked(GattCharacteristicWriteAuthCBParams *authParams) {
+ if (lockedState) {
+ authParams->authorizationReply = false;
+ }
+ }
+
+ BLEDevice &ble;
+ Params_t ¶ms;
+ // Default value that is restored on reset
+ uint16_t defaultUriDataLength;
+ UriData_t &defaultUriData;
+ // Default value that is restored on reset
+ PowerLevels_t &defaultAdvPowerLevels;
+ uint8_t lockedState;
+ bool initSucceeded;
+ uint8_t resetFlag;
+
+ ReadOnlyGattCharacteristic<uint8_t> lockedStateChar;
+ WriteOnlyGattCharacteristic<Lock_t> lockChar;
+ GattCharacteristic uriDataChar;
+ WriteOnlyGattCharacteristic<Lock_t> unlockChar;
+ ReadWriteGattCharacteristic<uint8_t> flagsChar;
+ ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
+ ReadWriteGattCharacteristic<uint8_t> txPowerModeChar;
+ ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
+ WriteOnlyGattCharacteristic<uint8_t> resetChar;
+
+ public:
+ /*
+ * Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
+ */
+ static void encodeURI(const char *uriDataIn, UriData_t uriDataOut, size_t &sizeofURIDataOut) {
+ sizeofURIDataOut = 0;
+ memset(uriDataOut, 0, sizeof(UriData_t));
+
+ if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
+ return;
}
- /* These are the URI Prefixes that can be abbreviated.*/
+ /*
+ * handle prefix
+ */
const char *prefixes[] = {
"http://www.",
"https://www.",
@@ -295,29 +297,19 @@
"https://",
"urn:uuid:"
};
-
- size_t encodedBytes = 0;
- const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
+ const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
for (unsigned i = 0; i < NUM_PREFIXES; i++) {
size_t prefixLen = strlen(prefixes[i]);
- if (strncmp(urldata, prefixes[i], prefixLen) == 0) {
- serviceDataPayload[payloadIndex++] = i;
- encodedBytes = 1;
-
- urldata += prefixLen;
- sizeofURLData -= prefixLen;
+ if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
+ uriDataOut[sizeofURIDataOut++] = i;
+ uriDataIn += prefixLen;
break;
}
}
- return encodedBytes;
- }
-
- /*
- * Encode the URI Suffix to a single byte if possible.
- */
- size_t encodeURI(const char *urldata, size_t sizeofURLData) {
- /* These are the URI suffixes that can be abbreviated. */
+ /*
+ * handle suffixes
+ */
const char *suffixes[] = {
".com/",
".org/",
@@ -335,212 +327,28 @@
".gov"
};
const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
-
- size_t encodedBytes = 0;
- while (sizeofURLData && (payloadIndex < MAX_SIZEOF_SERVICE_DATA_PAYLOAD)) {
+ while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
/* check for suffix match */
unsigned i;
for (i = 0; i < NUM_SUFFIXES; i++) {
size_t suffixLen = strlen(suffixes[i]);
- if ((suffixLen == 0) || (sizeofURLData < suffixLen)) {
+ if (suffixLen == 0) {
continue;
}
- if (strncmp(urldata, suffixes[i], suffixLen) == 0) {
- serviceDataPayload[payloadIndex++] = i;
- ++encodedBytes;
- urldata += suffixLen;
- sizeofURLData -= suffixLen;
+ if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
+ uriDataOut[sizeofURIDataOut++] = i;
+ uriDataIn += suffixLen;
break; /* from the for loop for checking against suffixes */
}
}
/* This is the default case where we've got an ordinary character which doesn't match a suffix. */
if (i == NUM_SUFFIXES) {
- serviceDataPayload[payloadIndex++] = *urldata;
- ++encodedBytes;
- ++urldata;
- --sizeofURLData;
+ uriDataOut[sizeofURIDataOut++] = *uriDataIn;
+ ++uriDataIn;
}
}
- if (sizeofURLData == 0) {
- initSucceeded = true;
- }
-
- return encodedBytes;
}
-
- /*
- * This callback is invoked when a GATT client attempts to modify any of the
- * characteristics of this service. Attempts to do so are also applied to
- * the internal state of this service object.
- */
- void onDataWritten(const GattCharacteristicWriteCBParams *params) {
- uint16_t handle = params->charHandle;
- if (handle == lockChar.getValueHandle()) {
- updateLockBits(params->data);
- storage_saveLockBits();
- } else if (handle == unlockChar.getValueHandle()) {
- memset(lockBits, 0, SIZEOF_LOCK_BITS);
- lockedState = false;
- storage_saveLockBits();
- } else if (handle == uriDataChar.getValueHandle()) {
- uriDataLength = params->len;
- memcpy(uriData, params->data, uriDataLength);
- } else if (handle == flagsChar.getValueHandle()) {
- flags = *(params->data);
- } else if (handle == txPowerLevelsChar.getValueHandle()) {
- memcpy(powerLevels, params->data, NUM_POWER_MODES * sizeof(int8_t));
- } else if (handle == txPowerModeChar.getValueHandle()) {
- txPowerMode = *reinterpret_cast<const TXPowerModes_t *>(params->data);
- } else if (handle == beaconPeriodChar.getValueHandle()) {
- beaconPeriod = *((uint16_t *)(params->data));
- } else if (handle == resetChar.getValueHandle()) {
- resetDefaults();
- }
- configureGAP();
- ble.setAdvertisingPayload();
- }
-
- /*
- * Reset the default values.
- */
- void resetDefaults(void) {
- uriDataLength = 0;
- memset(uriData, 0, MAX_SIZE_URI_DATA_CHAR_VALUE);
- flags = 0;
- memset(powerLevels, 0, sizeof(powerLevels));
- txPowerMode = TX_POWER_MODE_LOW;
- beaconPeriod = 0;
- resetLockBits();
-
- updateGATT();
- }
-
- /*
- * Internal helper function used to update the GATT database following any
- * change to the internal state of the service object.
- */
- void updateGATT(void) {
- updateLockedStateCharacteristic();
- updateURIDataCharacteristic();
- updateFlagsCharacteristic();
- updateBeaconPeriodCharacteristic();
- updateTxPowerLevelsCharacteristic();
- updateTxPowerModeCharacteristic();
- }
-
- void updateLockedStateCharacteristic(void) {
- ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), reinterpret_cast<uint8_t *>(&lockedState), sizeof(lockedState));
- }
-
- void updateURIDataCharacteristic(void) {
- ble.updateCharacteristicValue(uriDataChar.getValueHandle(), uriData, uriDataLength);
- }
-
- void updateFlagsCharacteristic(void) {
- ble.updateCharacteristicValue(flagsChar.getValueHandle(), &flags, 1 /* size */);
- }
-
- void updateBeaconPeriodCharacteristic(void) {
- ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(&beaconPeriod), sizeof(uint16_t));
- }
-
- void updateTxPowerModeCharacteristic(void) {
- ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), reinterpret_cast<uint8_t *>(&txPowerMode), sizeof(uint8_t));
- }
-
- void updateTxPowerLevelsCharacteristic(void) {
- ble.updateCharacteristicValue(txPowerLevelsChar.getValueHandle(), reinterpret_cast<uint8_t *>(powerLevels), NUM_POWER_MODES * sizeof(int8_t));
- }
-
-private:
- // enable the following for debugging the state of the lock
- // void lockedStateAuthorizationCallback(GattCharacteristicReadAuthCBParams *params) {
- // printf("read authorization callback: lockedState is %u\r\n", lockedState);
- // params->authorizationReply = true;
- // }
-
- void lockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *params) {
- params->authorizationReply = !lockedState;
- }
-
- void unlockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *params) {
- if (lockedState && (memcmp(params->data, lockBits, SIZEOF_LOCK_BITS) == 0)) {
- params->authorizationReply = true;
- } else {
- params->authorizationReply = false;
- }
- }
-
- void uriDataWriteAuthorizationCallback(GattCharacteristicWriteAuthCBParams *params) {
- if (lockedState || (params->offset != 0) || (params->len > MAX_SIZE_URI_DATA_CHAR_VALUE)) {
- params->authorizationReply = false;
- }
- }
-
- void flagsAuthorizationCallback(GattCharacteristicWriteAuthCBParams *params) {
- if (lockedState || ((*(params->data) & 0xFE) != 0)) {
- params->authorizationReply = false;
- }
- }
-
- void powerModeAuthorizationCallback(GattCharacteristicWriteAuthCBParams *params) {
- if (lockedState || (*(params->data) >= NUM_POWER_MODES)) {
- params->authorizationReply = false;
- }
- }
-
- void denyGATTWritesIfLocked(GattCharacteristicWriteAuthCBParams *params) {
- if (lockedState) {
- params->authorizationReply = false;
- }
- }
-
-private:
- /**
- * For debugging only. Print Hex representation of ServiceDataPayload to the console.
- */
- // void dumpEncodedSeviceData() const {
- // printf("encoded: '");
- // for (unsigned i = 0; i < payloadIndex; i++) {
- // printf(" %02x", serviceDataPayload[i]);
- // }
- // printf("'\r\n");
- // }
-
-private:
- static const size_t MAX_SIZEOF_SERVICE_DATA_PAYLOAD = 22; /* Uri Data must be between 0 and 18 bytes in length; and
- * together with the 4-byte header, the service data must
- * fit within 22 bytes. */
- static const size_t MAX_SIZE_URI_DATA_CHAR_VALUE = 48; /* This is chosen arbitrarily. It should be large enough
- * to hold any reasonable uncompressed URI. */
-private:
- BLEDevice &ble;
-
- size_t payloadIndex;
- uint8_t serviceDataPayload[MAX_SIZEOF_SERVICE_DATA_PAYLOAD];
- bool initSucceeded;
-
- bool lockedState;
- uint8_t lockBits[SIZEOF_LOCK_BITS];
-
- uint16_t uriDataLength;
- uint8_t uriData[MAX_SIZE_URI_DATA_CHAR_VALUE];
- uint8_t flags;
- int8_t powerLevels[NUM_POWER_MODES];
- TXPowerModes_t txPowerMode;
- uint16_t beaconPeriod;
- bool resetFlag;
-
- ReadOnlyGattCharacteristic<bool> lockedStateChar;
- WriteOnlyArrayGattCharacteristic<uint8_t, SIZEOF_LOCK_BITS> lockChar;
- WriteOnlyArrayGattCharacteristic<uint8_t, SIZEOF_LOCK_BITS> unlockChar;
- ReadWriteArrayGattCharacteristic<uint8_t, MAX_SIZE_URI_DATA_CHAR_VALUE> uriDataChar;
- ReadWriteGattCharacteristic<uint8_t> flagsChar;
- ReadWriteArrayGattCharacteristic<int8_t, NUM_POWER_MODES> txPowerLevelsChar;
- ReadWriteGattCharacteristic<TXPowerModes_t> txPowerModeChar;
- ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
- WriteOnlyGattCharacteristic<bool> resetChar;
};
-#endif /* #ifndef __BLE_URI_BEACON_CONFIG_SERVICE_H__*/
\ No newline at end of file
+#endif // SERVICES_URIBEACONCONFIGSERVICE_H_
\ No newline at end of file
