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