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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
EddystoneService.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 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_EDDYSTONEBEACON_H_ 00018 #define SERVICES_EDDYSTONEBEACON_H_ 00019 00020 #warning ble/services/EddystoneService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'. 00021 00022 #include "ble/BLE.h" 00023 #include "CircularBuffer.h" 00024 #include "Timer.h" 00025 #include "Ticker.h" 00026 #include "Timeout.h" 00027 00028 #if BLE_FEATURE_GATT_SERVER 00029 00030 static const uint8_t BEACON_EDDYSTONE[] = {0xAA, 0xFE}; 00031 00032 //Debug is disabled by default 00033 #if 0 00034 #define DBG(MSG, ...) printf("[EddyStone: DBG]" MSG " \t[%s,%d]\r\n", \ 00035 ## __VA_ARGS__, \ 00036 __FILE__, \ 00037 __LINE__); 00038 #define WARN(MSG, ...) printf("[EddyStone: WARN]" MSG " \t[%s,%d]\r\n", \ 00039 ## __VA_ARGS__, \ 00040 __FILE__, \ 00041 __LINE__); 00042 #define ERR(MSG, ...) printf("[EddyStone: ERR]" MSG " \t[%s,%d]\r\n", \ 00043 ## __VA_ARGS__, \ 00044 __FILE__, \ 00045 __LINE__); 00046 #else // if 0 00047 #define DBG(x, ...) //wait_us(10); 00048 #define WARN(x, ...) //wait_us(10); 00049 #define ERR(x, ...) 00050 #endif // if 0 00051 00052 #if 0 00053 #define INFO(x, ...) printf("[EddyStone: INFO]"x " \t[%s,%d]\r\n", \ 00054 ## __VA_ARGS__, \ 00055 __FILE__, \ 00056 __LINE__); 00057 #else // if 0 00058 #define INFO(x, ...) 00059 #endif // if 0 00060 00061 /** 00062 * @class Eddystone 00063 * @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags. 00064 * See https://github.com/google/eddystone 00065 * 00066 */ 00067 class EddystoneService 00068 { 00069 public: 00070 enum FrameTypes { 00071 NONE, 00072 url, 00073 uid, 00074 tlm 00075 }; 00076 00077 static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets 00078 00079 // There are currently 3 subframes defined, URI, UID, and TLM 00080 #define EDDYSTONE_MAX_FRAMETYPE 3 00081 void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t); 00082 static const int URI_DATA_MAX = 18; 00083 typedef uint8_t UriData_t[URI_DATA_MAX]; 00084 mbed::CircularBuffer<FrameTypes, EDDYSTONE_MAX_FRAMETYPE> overflow; 00085 00086 // UID Frame Type subfields 00087 static const int UID_NAMESPACEID_SIZE = 10; 00088 typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE]; 00089 static const int UID_INSTANCEID_SIZE = 6; 00090 typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE]; 00091 00092 // Eddystone Frame Type ID 00093 static const uint8_t FRAME_TYPE_UID = 0x00; 00094 static const uint8_t FRAME_TYPE_URL = 0x10; 00095 static const uint8_t FRAME_TYPE_TLM = 0x20; 00096 00097 static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes 00098 static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes 00099 00100 /** 00101 * Set Eddystone UID Frame information. 00102 * 00103 * @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB. 00104 * @param[in] namespaceID 10B namespace ID 00105 * @param[in] instanceID 6B instance ID 00106 * @param[in] uidAdvPeriodIn Advertising period of UID frames. 00107 * @param[in] RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference. 00108 */ 00109 void setUIDFrameData(int8_t power, 00110 UIDNamespaceID_t namespaceID, 00111 UIDInstanceID_t instanceID, 00112 float uidAdvPeriodIn, 00113 uint16_t RFU = 0x0000) { 00114 if (0.0f == uidAdvPeriodIn) { 00115 uidIsSet = false; 00116 return; 00117 } 00118 if (power > 20) { 00119 power = 20; 00120 } 00121 if (power < -100) { 00122 power = -100; 00123 } 00124 00125 defaultUidPower = power; 00126 memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE); 00127 memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE); 00128 uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesn't really matter yet. 00129 uidAdvPeriod = uidAdvPeriodIn; 00130 uidIsSet = true; // set toggle to advertise UID frames 00131 } 00132 00133 /* 00134 * Construct UID frame from private variables 00135 * @param[in/out] Data pointer to array to store constructed frame in 00136 * @param[in] maxSize number of bytes left in array, effectively how much empty space is available to write to 00137 * @return number of bytes used. negative number indicates error message. 00138 */ 00139 unsigned constructUIDFrame(uint8_t *Data, uint8_t maxSize) { 00140 unsigned index = 0; 00141 00142 Data[index++] = FRAME_TYPE_UID; // 1B Type 00143 00144 if (defaultUidPower > 20) { 00145 defaultUidPower = 20; // enforce range of vaild values. 00146 } 00147 if (defaultUidPower < -100) { 00148 defaultUidPower = -100; 00149 } 00150 Data[index++] = defaultUidPower; // 1B Power @ 0meter 00151 00152 DBG("UID NamespaceID = '0x"); 00153 for (size_t x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespace ID 00154 Data[index++] = defaultUidNamespaceID[x]; 00155 DBG("%x,", defaultUidNamespaceID[x]); 00156 } 00157 DBG("'\r\n"); 00158 00159 DBG("UID InstanceID = '0x"); 00160 for (size_t x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID 00161 Data[index++] = defaultUidInstanceID[x]; 00162 DBG("%x,", defaultUidInstanceID[x]); 00163 } 00164 DBG("'\r\n"); 00165 00166 if (0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore 00167 Data[index++] = (uint8_t)(uidRFU >> 0); 00168 Data[index++] = (uint8_t)(uidRFU >> 8); 00169 } 00170 DBG("construcUIDFrame %d, %d", maxSize, index); 00171 return index; 00172 } 00173 00174 /** 00175 * Set Eddystone URL Frame information. 00176 * @param[in] power TX Power in dB measured at 0 meters from the device. 00177 * @param[in] urlIn URL to encode 00178 * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods) 00179 * @return false on success, true on failure. 00180 */ 00181 bool setURLFrameData(int8_t power, const char *urlIn, float urlAdvPeriodIn) { 00182 if (0.0f == urlAdvPeriodIn) { 00183 urlIsSet = false; 00184 return false; 00185 } 00186 encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting 00187 if (defaultUriDataLength > URI_DATA_MAX) { 00188 return true; // error, URL is too big 00189 } 00190 defaultUrlPower = power; 00191 urlAdvPeriod = urlAdvPeriodIn; 00192 urlIsSet = true; 00193 return false; 00194 } 00195 00196 /** 00197 * Set Eddystone URL Frame information. 00198 * @param[in] power TX Power in dB measured at 0 meters from the device. 00199 * @param[in] encodedUrlIn Encoded URL 00200 * @param[in] encodedUrlInLength Length of the encoded URL 00201 * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods) 00202 * @return false on success, true on failure. 00203 */ 00204 bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, float urlAdvPeriodIn) { 00205 if (0.0f == urlAdvPeriodIn) { 00206 urlIsSet = false; 00207 return false; 00208 } 00209 memcpy(defaultUriData, encodedUrlIn, encodedUrlInLength); 00210 if (defaultUriDataLength > URI_DATA_MAX) { 00211 return true; // error, URL is too big 00212 } 00213 defaultUrlPower = power; 00214 defaultUriDataLength = encodedUrlInLength; 00215 urlAdvPeriod = urlAdvPeriodIn; 00216 urlIsSet = true; 00217 return false; 00218 } 00219 00220 /* 00221 * Construct URL frame from private variables 00222 * @param[in/out] Data pointer to array to store constructed frame in 00223 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to 00224 * @return number of bytes used. negative number indicates error message. 00225 */ 00226 int constructURLFrame(uint8_t *Data, uint8_t maxSize) { 00227 int index = 0; 00228 Data[index++] = FRAME_TYPE_URL; // 1B Type 00229 Data[index++] = defaultUrlPower; // 1B TX Power 00230 for (int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL 00231 Data[index++] = defaultUriData[x]; 00232 } 00233 DBG("constructURLFrame: %d, %d", maxSize, index); 00234 return index; 00235 } 00236 00237 /* 00238 * Set Eddystone TLM Frame information. 00239 * @param[in] Version of the TLM beacon data format 00240 * @param[in] advPeriod how often to advertise the TLM frame for (in minutes) 00241 * @param batteryVoltage in milivolts 00242 * @param beaconTemp in 8.8 floating point notation 00243 * 00244 */ 00245 void setTLMFrameData(uint8_t version = 0, 00246 float advPeriod = 60.0f, 00247 uint16_t batteryVoltage = 0, 00248 uint16_t beaconTemp = 0x8000, 00249 uint32_t pduCount = 0, 00250 uint32_t timeSinceBoot = 0) { 00251 if (0.0f == advPeriod) { 00252 tlmIsSet = false; 00253 return; 00254 } 00255 TlmVersion = version; 00256 TlmBatteryVoltage = batteryVoltage; 00257 TlmBeaconTemp = beaconTemp; 00258 TlmPduCount = pduCount; // reset 00259 TlmTimeSinceBoot = timeSinceBoot; // reset 00260 TlmAdvPeriod = advPeriod; 00261 tlmIsSet = true; // TLM Data has been enabled 00262 } 00263 00264 /* 00265 * Construct TLM frame from private variables 00266 * @param[in/out] Data pointer to array to store constructed frame in 00267 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to 00268 * @return number of bytes used. negative number indicates error message. 00269 */ 00270 int constructTLMFrame(uint8_t *Data, uint8_t maxSize) { 00271 uint32_t now = timeSinceBootTimer.read_ms(); 00272 TlmTimeSinceBoot += (now - lastBootTimerRead) / 100; 00273 lastBootTimerRead = now; 00274 00275 int index = 0; 00276 Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry 00277 Data[index++] = TlmVersion; // TLM Version Number 00278 Data[index++] = (uint8_t)(TlmBatteryVoltage >> 8); // Battery Voltage[0] 00279 Data[index++] = (uint8_t)(TlmBatteryVoltage >> 0); // Battery Voltage[1] 00280 Data[index++] = (uint8_t)(TlmBeaconTemp >> 8); // Beacon Temp[0] 00281 Data[index++] = (uint8_t)(TlmBeaconTemp >> 0); // Beacon Temp[1] 00282 Data[index++] = (uint8_t)(TlmPduCount >> 24); // PDU Count [0] 00283 Data[index++] = (uint8_t)(TlmPduCount >> 16); // PDU Count [1] 00284 Data[index++] = (uint8_t)(TlmPduCount >> 8); // PDU Count [2] 00285 Data[index++] = (uint8_t)(TlmPduCount >> 0); // PDU Count [3] 00286 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 24); // Time Since Boot [0] 00287 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 16); // Time Since Boot [1] 00288 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 8); // Time Since Boot [2] 00289 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 0); // Time Since Boot [3] 00290 DBG("constructURLFrame: %d, %d", maxSize, index); 00291 return index; 00292 } 00293 00294 /* 00295 * Update the TLM frame battery voltage value 00296 * @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV) 00297 * @return nothing 00298 */ 00299 void updateTlmBatteryVoltage(uint16_t voltagemv) { 00300 TlmBatteryVoltage = voltagemv; 00301 } 00302 00303 /* 00304 * Update the TLM frame beacon temperature 00305 * @param[in] temp Temperature of beacon (in 8.8fpn) 00306 * @return nothing 00307 */ 00308 void updateTlmBeaconTemp(uint16_t temp) { 00309 TlmBeaconTemp = temp; 00310 } 00311 00312 /* 00313 * Update the TLM frame PDU Count field 00314 * @param[in] pduCount Number of Advertisiting frames sent since powerup 00315 * @return nothing 00316 */ 00317 void updateTlmPduCount(uint32_t pduCount) { 00318 TlmPduCount = pduCount; 00319 } 00320 00321 /* 00322 * Update the TLM frame Time since boot in 0.1s incriments 00323 * @param[in] timeSinceBoot Time since boot in 0.1s incriments 00324 * @return nothing 00325 */ 00326 void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) { 00327 TlmTimeSinceBoot = timeSinceBoot; 00328 } 00329 00330 /* 00331 * Update advertising data 00332 * @return true on success, false on failure 00333 */ 00334 bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) { 00335 // Fields from the Service 00336 DBG("Updating AdvFrame: %d", serviceDataLen); 00337 00338 ble.clearAdvertisingPayload(); 00339 ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); 00340 ble.setAdvertisingInterval(100); 00341 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00342 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE)); 00343 ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen); 00344 00345 00346 return true; 00347 } 00348 00349 /* 00350 * State machine for switching out frames. 00351 * This function is called by the radioNotificationCallback when a frame needs to get swapped out. 00352 * This function exists because of time constraints in the radioNotificationCallback, so it is effectively 00353 * broken up into two functions. 00354 */ 00355 void swapOutFrames(FrameTypes frameType) { 00356 uint8_t serviceData[SERVICE_DATA_MAX]; 00357 unsigned serviceDataLen = 0; 00358 //hard code in the eddystone UUID 00359 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0]; 00360 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1]; 00361 00362 // if certain frames are not enabled, then skip them. Worst case TLM is always enabled 00363 switch (frameType) { 00364 case tlm: 00365 // TLM frame 00366 if (tlmIsSet) { 00367 DBG("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d", 00368 TlmVersion, 00369 TlmBatteryVoltage, 00370 TlmBeaconTemp, 00371 TlmPduCount, 00372 TlmTimeSinceBoot); 00373 serviceDataLen += constructTLMFrame(serviceData + serviceDataLen, 20); 00374 DBG("\t Swapping in TLM Frame: len=%d", serviceDataLen); 00375 updateAdvPacket(serviceData, serviceDataLen); 00376 } 00377 break; 00378 case url: 00379 // URL Frame 00380 if (urlIsSet) { 00381 DBG("Swapping in URL Frame: Power: %d", defaultUrlPower); 00382 serviceDataLen += constructURLFrame(serviceData + serviceDataLen, 20); 00383 DBG("\t Swapping in URL Frame: len=%d ", serviceDataLen); 00384 updateAdvPacket(serviceData, serviceDataLen); 00385 //switchFlag = false; 00386 } 00387 break; 00388 case uid: 00389 // UID Frame 00390 if (uidIsSet) { 00391 DBG("Swapping in UID Frame: Power: %d", defaultUidPower); 00392 serviceDataLen += constructUIDFrame(serviceData + serviceDataLen, 20); 00393 DBG("\t Swapping in UID Frame: len=%d", serviceDataLen); 00394 updateAdvPacket(serviceData, serviceDataLen); 00395 //switchFlag = false; 00396 } 00397 break; 00398 default: 00399 ERR("You have not initialized a Frame yet, please initialize one before starting a beacon"); 00400 ERR("uidIsSet = %d, urlIsSet = %d, tlmIsSet = %d", uidIsSet, urlIsSet, tlmIsSet); 00401 } 00402 } 00403 00404 /* 00405 * Callback to swap in URL frame 00406 */ 00407 void urlCallback(void) { 00408 DBG("urlCallback"); 00409 if (false == advLock) { 00410 advLock = true; 00411 DBG("advLock = url") 00412 frameIndex = url; 00413 swapOutFrames(frameIndex); 00414 ble.startAdvertising(); 00415 } else { 00416 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free 00417 INFO("URI(%d) cannot complete, %d is currently broadcasting", url, frameIndex); 00418 FrameTypes x = url; 00419 overflow.push(x); 00420 } 00421 } 00422 00423 /* 00424 * Callback to swap in UID frame 00425 */ 00426 void uidCallback(void) { 00427 DBG("uidCallback"); 00428 if (false == advLock) { 00429 advLock = true; 00430 DBG("advLock = uid") 00431 frameIndex = uid; 00432 swapOutFrames(frameIndex); 00433 ble.startAdvertising(); 00434 } else { 00435 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free 00436 INFO("UID(%d) cannot complete, %d is currently broadcasting", uid, frameIndex); 00437 FrameTypes x = uid; // have to do this to satisfy cont vs volatile keywords... sigh... 00438 overflow.push(x); 00439 } 00440 } 00441 00442 /* 00443 * Callback to swap in TLM frame 00444 */ 00445 void tlmCallback(void) { 00446 DBG("tlmCallback"); 00447 if (false == advLock) { 00448 // OK to broadcast 00449 advLock = true; 00450 DBG("advLock = tlm") 00451 frameIndex = tlm; 00452 swapOutFrames(frameIndex); 00453 ble.startAdvertising(); 00454 } else { 00455 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free 00456 INFO("TLM(%d) cannot complete, %d is currently broadcasting", tlm, frameIndex); 00457 FrameTypes x = tlm; 00458 overflow.push(x); 00459 } 00460 } 00461 00462 void stopAdvCallback(void) { 00463 if (overflow.empty()) { 00464 // if nothing left to transmit, stop 00465 ble.stopAdvertising(); 00466 advLock = false; // unlock lock 00467 } else { 00468 // transmit other packets at current time index 00469 FrameTypes x = NONE; 00470 overflow.pop(x); 00471 INFO("Re-Transmitting %d", x); 00472 swapOutFrames(x); 00473 } 00474 } 00475 00476 /* 00477 * Callback from onRadioNotification(), used to update the PDUCounter and process next state. 00478 */ 00479 #define EDDYSTONE_SWAPFRAME_DELAYMS 1 00480 void radioNotificationCallback(bool radioActive) { 00481 // Update PDUCount 00482 TlmPduCount++; 00483 // True just before an frame is sent, false just after a frame is sent 00484 if (radioActive) { 00485 // Do Nothing 00486 } else { 00487 // Packet has been sent, disable advertising 00488 stopAdv.attach_us(this, &EddystoneService::stopAdvCallback, 1); 00489 } 00490 } 00491 00492 /* 00493 * This function explicityly sets the parameters used by the Eddystone beacon. 00494 * this function should be used in leu of the config service. 00495 * 00496 * @param bleIn ble object used to broadcast eddystone information 00497 * @param beaconPeriodus is how often ble broadcasts are mde, in mili seconds 00498 * @param txPowerLevel sets the broadcasting power level. 00499 * 00500 */ 00501 EddystoneService(BLEDevice &bleIn, 00502 uint16_t beaconPeriodus = 100, 00503 uint8_t txPowerIn = 0) : 00504 ble(bleIn), 00505 advPeriodus(beaconPeriodus), 00506 txPower(txPowerIn), 00507 advLock(false), 00508 frameIndex(NONE) { 00509 } 00510 00511 /* 00512 * @breif this function starts eddystone advertising based on configured frames. 00513 */ 00514 void start(void) { 00515 // Initialize Frame transition, start with URL to pass eddystone validator app on first try 00516 if (urlIsSet) { 00517 frameIndex = url; 00518 urlTicker.attach(this, &EddystoneService::urlCallback, (float) advPeriodus / 1000.0f); 00519 DBG("attached urlCallback every %d seconds", urlAdvPeriod); 00520 } 00521 if (uidIsSet) { 00522 frameIndex = uid; 00523 uidTicker.attach(this, &EddystoneService::uidCallback, uidAdvPeriod); 00524 DBG("attached uidCallback every %d seconds", uidAdvPeriod); 00525 } 00526 if (tlmIsSet) { 00527 frameIndex = tlm; 00528 // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset 00529 updateTlmPduCount(0); 00530 updateTlmTimeSinceBoot(0); 00531 lastBootTimerRead = 0; 00532 timeSinceBootTimer.start(); 00533 tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod); 00534 DBG("attached tlmCallback every %d seconds", TlmAdvPeriod); 00535 } 00536 if (NONE == frameIndex) { 00537 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_BLE, MBED_ERROR_CODE_BLE_NO_FRAME_INITIALIZED), "No Frames were Initialized! Please initialize a frame before starting an eddystone beacon."); 00538 } 00539 //uidRFU = 0; 00540 00541 ble.setTxPower(txPower); 00542 ble.gap().onRadioNotification(this, &EddystoneService::radioNotificationCallback); 00543 } 00544 00545 private: 00546 00547 // Eddystone Variables 00548 BLEDevice &ble; 00549 uint16_t advPeriodus; 00550 uint8_t txPower; 00551 mbed::Timer timeSinceBootTimer; 00552 volatile uint32_t lastBootTimerRead; 00553 volatile bool advLock; 00554 volatile FrameTypes frameIndex; 00555 mbed::Timeout stopAdv; 00556 00557 00558 // URI Frame Variables 00559 uint8_t defaultUriDataLength; 00560 UriData_t defaultUriData; 00561 int8_t defaultUrlPower; 00562 bool urlIsSet; // flag that enables / disable URI Frames 00563 float urlAdvPeriod; // how long the url frame will be advertised for 00564 mbed::Ticker urlTicker; 00565 00566 // UID Frame Variables 00567 UIDNamespaceID_t defaultUidNamespaceID; 00568 UIDInstanceID_t defaultUidInstanceID; 00569 int8_t defaultUidPower; 00570 uint16_t uidRFU; 00571 bool uidIsSet; // flag that enables / disable UID Frames 00572 float uidAdvPeriod; // how long the uid frame will be advertised for 00573 mbed::Ticker uidTicker; 00574 00575 // TLM Frame Variables 00576 uint8_t TlmVersion; 00577 volatile uint16_t TlmBatteryVoltage; 00578 volatile uint16_t TlmBeaconTemp; 00579 volatile uint32_t TlmPduCount; 00580 volatile uint32_t TlmTimeSinceBoot; 00581 bool tlmIsSet; // flag that enables / disables TLM frames 00582 float TlmAdvPeriod; // number of minutes between adv frames 00583 mbed::Ticker tlmTicker; 00584 00585 public: 00586 /* 00587 * Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification). 00588 */ 00589 static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, uint8_t &sizeofURIDataOut) { 00590 DBG("Encode URL = %s", uriDataIn); 00591 const char *prefixes[] = { 00592 "http://www.", 00593 "https://www.", 00594 "http://", 00595 "https://", 00596 }; 00597 const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *); 00598 const char *suffixes[] = { 00599 ".com/", 00600 ".org/", 00601 ".edu/", 00602 ".net/", 00603 ".info/", 00604 ".biz/", 00605 ".gov/", 00606 ".com", 00607 ".org", 00608 ".edu", 00609 ".net", 00610 ".info", 00611 ".biz", 00612 ".gov" 00613 }; 00614 const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *); 00615 00616 sizeofURIDataOut = 0; 00617 memset(uriDataOut, 0, sizeof(UriData_t)); 00618 00619 if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) { 00620 return; 00621 } 00622 00623 /* 00624 * handle prefix 00625 */ 00626 for (unsigned i = 0; i < NUM_PREFIXES; i++) { 00627 size_t prefixLen = strlen(prefixes[i]); 00628 if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) { 00629 uriDataOut[sizeofURIDataOut++] = i; 00630 uriDataIn += prefixLen; 00631 break; 00632 } 00633 } 00634 00635 /* 00636 * handle suffixes 00637 */ 00638 while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) { 00639 /* check for suffix match */ 00640 unsigned i; 00641 for (i = 0; i < NUM_SUFFIXES; i++) { 00642 size_t suffixLen = strlen(suffixes[i]); 00643 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) { 00644 uriDataOut[sizeofURIDataOut++] = i; 00645 uriDataIn += suffixLen; 00646 break; /* from the for loop for checking against suffixes */ 00647 } 00648 } 00649 /* This is the default case where we've got an ordinary character which doesn't match a suffix. */ 00650 INFO("Encoding URI: No Suffix Found"); 00651 if (i == NUM_SUFFIXES) { 00652 uriDataOut[sizeofURIDataOut++] = *uriDataIn; 00653 ++uriDataIn; 00654 } 00655 } 00656 } 00657 }; 00658 00659 #endif // BLE_FEATURE_GATT_SERVER 00660 00661 #endif // SERVICES_EDDYSTONEBEACON_H_
Generated on Tue Jul 12 2022 13:54:18 by
1.7.2