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