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