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