Added an EddystoneURLConfigService in addition to UriBeaconConfigService. Updated README and converted comments that used UriBeacon to EddystoneURL in the EddystoneService.h

Dependents:   mbed_EddystoneURL_Beacon_ssci mbed_EddystoneURL_Beacon_ssci mbed_EddystoneURL_Beacon_ssci

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EddystoneService.h Source File

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 
00023 static const uint8_t BEACON_EDDYSTONE[] = {0xAA, 0xFE};
00024 
00025 //Debug is disabled by default
00026 #if 0
00027 #define DBG(x, ...)  printf("[EddyStone: DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
00028 #define WARN(x, ...) printf("[EddyStone: WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
00029 #define ERR(x, ...)  printf("[EddyStone: ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
00030 #else
00031 #define DBG(x, ...) //wait_us(10);
00032 #define WARN(x, ...) //wait_us(10);
00033 #define ERR(x, ...)
00034 #endif
00035 
00036 #if 0
00037 #define INFO(x, ...)  printf("[EddyStone: INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
00038 #else
00039 #define INFO(x, ...)
00040 #endif
00041 
00042 /**
00043 * @class Eddystone
00044 * @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags.
00045 * See https://github.com/google/eddystone
00046 *
00047 */
00048 class EddystoneService
00049 {
00050 public:
00051     /**
00052      * @brief Transmission Power Modes for Eddystone-URL Beacon
00053      */
00054 
00055     static const int ADVERTISING_INTERVAL_MSEC = 1000;  // Advertising interval for config service.
00056     static const int SERVICE_DATA_MAX = 31;             // Maximum size of service data in ADV packets
00057 
00058     // There are currently 3 subframes defined, URI, UID, and TLM
00059 #define EDDYSTONE_MAX_FRAMETYPE 3
00060     void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
00061     uint8_t frameIndex;
00062     static const int URI_DATA_MAX = 18;
00063     typedef uint8_t  UriData_t[URI_DATA_MAX];
00064 
00065     // UID Frame Type subfields
00066     static const int UID_NAMESPACEID_SIZE = 10;
00067     typedef uint8_t  UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
00068     static const int UID_INSTANCEID_SIZE = 6;
00069     typedef uint8_t  UIDInstanceID_t[UID_INSTANCEID_SIZE];
00070 
00071     // Eddystone Frame Type ID
00072     static const uint8_t FRAME_TYPE_UID = 0x00;
00073     static const uint8_t FRAME_TYPE_URL = 0x10;
00074     static const uint8_t FRAME_TYPE_TLM = 0x20;
00075 
00076     static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
00077     static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
00078 
00079     /*
00080     *  Set Eddystone UID Frame information.
00081     *  @param[in] power   TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB.
00082     *  @param namespaceID 10B namespace ID
00083     *  @param instanceID  6B instance ID
00084     *  @param RFU         2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
00085     *
00086     */
00087     void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, uint16_t RFU = 0x0000) {
00088         if(power > 20) {
00089             power = 20;
00090         }
00091         if(power < -100) {
00092             power = -100;
00093         }
00094         defaultUidPower = power;
00095         memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
00096         memcpy(defaultUidInstanceID,  instanceID,  UID_INSTANCEID_SIZE);
00097         uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesnt really matter yet.
00098         return;
00099     }
00100 
00101     /*
00102     *  Construct UID frame from private variables
00103     *  @param[in/out] Data pointer to array to store constructed frame in
00104     *  @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
00105     *  @return number of bytes used. negative number indicates error message.
00106     */
00107     int constructUIDFrame(uint8_t * Data, uint8_t maxSize) {
00108 
00109         int index = 0;
00110         Data[index++] = FRAME_TYPE_UID;                     // 1B  Type
00111         if(defaultUidPower > 20) {
00112             defaultUidPower = 20;   // enforce range of vaild values.
00113         }
00114         if(defaultUidPower < -100) {
00115             defaultUidPower = -100;
00116         }
00117         Data[index++] = defaultUidPower;                    // 1B  Power @ 0meter
00118         for(int x = 0; x < UID_NAMESPACEID_SIZE; x++) {     // 10B Namespce ID
00119             Data[index++] = defaultUidNamespaceID[x];
00120         }
00121         for(int x = 0; x< UID_INSTANCEID_SIZE; x++) {       // 6B  Instance ID
00122             Data[index++] = defaultUidInstanceID[x];
00123         }
00124         if(0 != uidRFU) {                                // 2B RFU, include if non-zero, otherwise ignore
00125             Data[index++] = (uint8_t)(uidRFU >> 0);
00126             Data[index++] = (uint8_t)(uidRFU >> 8);
00127         }
00128         DBG("construcUIDFrame %d, %d",maxSize,index);
00129         return index;
00130     }
00131 
00132     /*
00133     *  Set Eddystone URL Frame information.
00134     *  @param[in] power   TX Power in dB measured at 0 meters from the device.
00135     *  @param url         URL to encode
00136     *  @return            false on success, true on failure.
00137     */
00138     bool setURLFrameData(int8_t power, const char * url) {
00139         defaultUrlPower = power;
00140         encodeURL(url, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
00141         if (defaultUriDataLength > URI_DATA_MAX) {
00142             return true; // error, URL is too big
00143         }
00144         return false;
00145     }
00146 
00147     /*
00148     *  Construct URL frame from private variables
00149     *  @param[in/out] Data pointer to array to store constructed frame in
00150     *  @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
00151     *  @return number of bytes used. negative number indicates error message.
00152     */
00153     int constructURLFrame(uint8_t * Data, uint8_t maxSize) {
00154         int index = 0;
00155         Data[index++] = FRAME_TYPE_URL;                     // 1B  Type
00156         Data[index++] = defaultUrlPower;                    // 1B  TX Power
00157         for(int x = 0; x < defaultUriDataLength; x++) {     // 18B of URL Prefix + encoded URL
00158             Data[index++] = defaultUriData[x];
00159         }
00160         DBG("constructURLFrame: %d, %d",maxSize,index);
00161         return index;
00162     }
00163 
00164     /*
00165     *  Set Eddystone TLM Frame information.
00166     *  @param[in] Version    of the TLM beacon data format
00167     *  @param batteryVoltage in milivolts
00168     *  @param beaconTemp     in 8.8 floating point notation
00169     *
00170     */
00171     void setTLMFrameData(uint8_t version, uint16_t batteryVoltage, uint16_t beaconTemp, uint32_t pduCount = 0, uint32_t timeSinceBoot = 0) {
00172         TlmVersion = version;
00173         TlmBatteryVoltage = batteryVoltage;
00174         TlmBeaconTemp = beaconTemp;
00175         TlmPduCount = pduCount; // reset
00176         TlmTimeSinceBoot = timeSinceBoot; // reset
00177         return;
00178     }
00179 
00180     /*
00181     *  Construct TLM frame from private variables
00182     *  @param[in/out] Data pointer to array to store constructed frame in
00183     *  @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
00184     *  @return number of bytes used. negative number indicates error message.
00185     */
00186     int constructTLMFrame(uint8_t * Data, uint8_t maxSize) {
00187         int index = 0;
00188         Data[index++] = FRAME_TYPE_TLM;                    // Eddystone frame type = Telemetry
00189         Data[index++] = TlmVersion;                        // TLM Version Number
00190         Data[index++] = (uint8_t)(TlmBatteryVoltage>>8);   // Battery Voltage[0]
00191         Data[index++] = (uint8_t)(TlmBatteryVoltage>>0);   // Battery Voltage[1]
00192         Data[index++] = (uint8_t)(TlmBeaconTemp>>8);       // Beacon Temp[0]
00193         Data[index++] = (uint8_t)(TlmBeaconTemp>>0);       // Beacon Temp[1]
00194         Data[index++] = (uint8_t)(TlmPduCount>>24);         // PDU Count [0]
00195         Data[index++] = (uint8_t)(TlmPduCount>>16);         // PDU Count [1]
00196         Data[index++] = (uint8_t)(TlmPduCount>>8);        // PDU Count [2]
00197         Data[index++] = (uint8_t)(TlmPduCount>>0);        // PDU Count [3]
00198         Data[index++] = (uint8_t)(TlmTimeSinceBoot>>24);    // Time Since Boot [0]
00199         Data[index++] = (uint8_t)(TlmTimeSinceBoot>>16);    // Time Since Boot [1]
00200         Data[index++] = (uint8_t)(TlmTimeSinceBoot>>8);   // Time Since Boot [2]
00201         Data[index++] = (uint8_t)(TlmTimeSinceBoot>>0);   // Time Since Boot [3]
00202         DBG("constructURLFrame: %d, %d",maxSize,index);
00203         return index;
00204     }
00205 
00206     /*
00207     *  Update the TLM frame battery voltage value
00208     *  @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV)
00209     *  @return nothing
00210     */
00211     void updateTlmBatteryVoltage(uint16_t voltagemv) {
00212         TlmBatteryVoltage = voltagemv;
00213         return;
00214     }
00215 
00216     /*
00217     *  Update the TLM frame beacon temperature
00218     *  @param[in] temp Temperature of beacon (in 8.8fpn)
00219     *  @return nothing
00220     */
00221     void updateTlmBeaconTemp(uint16_t temp) {
00222         TlmBeaconTemp = temp;
00223         return;
00224     }
00225 
00226     /*
00227     *  Update the TLM frame PDU Count field
00228     *  @param[in] pduCount Number of Advertisiting frames sent since powerup
00229     *  @return nothing
00230     */
00231     void updateTlmPduCount(uint32_t pduCount) {
00232         TlmPduCount = pduCount;
00233         return;
00234     }
00235 
00236     /*
00237     *  Update the TLM frame Time since boot in 0.1s incriments
00238     *  @param[in] timeSinceBoot Time since boot in 0.1s incriments
00239     *  @return nothing
00240     */
00241     void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) {
00242         TlmTimeSinceBoot = timeSinceBoot;
00243         return;
00244     }
00245 
00246     /*
00247     *  callback function, called every 0.1s, incriments the TimeSinceBoot field in the TLM frame
00248     *  @return nothing
00249     */
00250     void tsbCallback(void) {
00251         TlmTimeSinceBoot++;
00252     }
00253 
00254     /*
00255     * Update advertising data
00256     * @return true on success, false on failure
00257     */
00258     bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) {
00259         // Fields from the Service
00260         DBG("Updating AdvFrame: %d", serviceDataLen);
00261 //        printf("\r\n");
00262 //        for(int x = 0; x<serviceDataLen; x++) {
00263 //            printf("%2.2x:",serviceData[x]);
00264 //        }
00265 //        printf("\r\n");
00266         ble.clearAdvertisingPayload();
00267         ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00268         ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE));
00269         ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
00270 
00271         return true;
00272     }
00273 
00274     /*
00275     *   State machine for switching out frames.
00276     *   This function is called by the radioNotificationCallback when a frame needs to get swapped out.
00277     *   This function exists because of time constraints in the radioNotificationCallback, so it is effectively
00278     *   broken up into two functions.
00279     */
00280     void swapOutFrames(void) {
00281         uint8_t serviceData[SERVICE_DATA_MAX];
00282         unsigned serviceDataLen = 0;
00283         //hard code in the eddystone UUID
00284         serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
00285         serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
00286 
00287         // if certain frames are not enabled, then skip them. Worst case TLM is always enabled
00288         switch(frameIndex) {
00289             case 1:
00290                 // URL Frame
00291                 if(urlIsSet) {
00292                     INFO("Swapping in URL Frame: Power: %d",defaultUrlPower);
00293                     serviceDataLen += constructURLFrame(serviceData+serviceDataLen,20);
00294                     DBG("\t Swapping in URL Frame: len=%d ",serviceDataLen);
00295                     updateAdvPacket(serviceData,serviceDataLen);
00296                     switchFlag = false;
00297                     frameIndex++;
00298                     break;
00299                 }
00300             case 2:
00301                 // UID Frame
00302                 if(uidIsSet) {
00303                     INFO("Swapping in UID Frame: Power: %d",defaultUidPower);
00304                     serviceDataLen += constructUIDFrame(serviceData+serviceDataLen,20);
00305                     DBG("\t Swapping in UID Frame: len=%d",serviceDataLen);
00306                     updateAdvPacket(serviceData,serviceDataLen);
00307                     switchFlag = false;
00308                     frameIndex++;
00309                     break;
00310                 }
00311             default:
00312                 // TLM frame
00313                 INFO("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d",TlmVersion, TlmBatteryVoltage, TlmBeaconTemp, TlmPduCount, TlmTimeSinceBoot);
00314                 serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,20);
00315                 DBG("\t Swapping in TLM Frame: len=%d",serviceDataLen);
00316                 updateAdvPacket(serviceData,serviceDataLen);
00317                 frameIndex++;
00318                 break;
00319         }
00320     }
00321 
00322     /*
00323     *  Callback from onRadioNotification(), used to update the PDUCounter and process next state.
00324     */
00325 #define EDDYSTONE_SWAPFRAME_DELAYMS 1
00326     void radioNotificationCallback(bool radioActive) {
00327         //DBG("RadioNotificationCallback : %d, %d, %d, %d",radioActive,frameIndex,TlmPduCount,TlmTimeSinceBoot);
00328         // Update PDUCount
00329         TlmPduCount++;
00330         frameIndex = frameIndex % EDDYSTONE_MAX_FRAMETYPE;
00331 
00332 
00333         // True just before an frame is sent, fale just after a frame is sent
00334         if(radioActive) {
00335             // Do Nothing
00336         } else {
00337             // state machine to control which packet is being sent
00338             switch(frameIndex) {
00339                 case 0: // TLM Frame
00340                     switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
00341                     switchFlag = true;
00342                     break;
00343                 case 1: // URL Frame
00344                     // switch out packets
00345                     if(switchFlag) {
00346                         switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
00347                         switchFlag = false;
00348                     } else {
00349                         if((TlmPduCount % 10) == 0) { // every 10 adv packets switch the frame
00350                             switchFlag = true;
00351                         }
00352                     }
00353                     break;
00354                 case 2: // UIDFrame
00355                     // switch out packets
00356                     if(switchFlag ) {
00357                         switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
00358                         switchFlag = false;
00359                     } else {
00360                         if((TlmPduCount % 10) == 0) { // every 10 adv packets switch the frame
00361                             switchFlag = true;
00362                         }
00363                     }
00364                     break;
00365             }
00366         }
00367 
00368         return;
00369     }
00370 
00371     /*
00372     *   This function explicityly sets the parameters used by the Eddystone beacon.
00373     *   this function should be used in leu of the config service.
00374     *
00375     *   @param bleIn ble object used to broadcast eddystone information
00376     *   @oaram beaconPeriodus is how often ble broadcasts are mde, in mili seconds
00377     *   @param txPowerLevel sets the broadcasting power level.
00378     *   @param uidNamespaceID 10Byte Namespace UUID
00379     *   @param uidInstanceID  6Byte  Instance UUID
00380     *   @param url shortened URL to broadcast (pass in as a string)
00381     *   @param urlLen length of shortened url
00382     *   @param tlmVersion version of telemetry data field to use (default to 0x00)
00383     *
00384     */
00385     EddystoneService(BLEDevice       &bleIn,
00386               uint16_t        beaconPeriodus = 100,
00387               uint8_t         txPowerLevel = 0,
00388               uint8_t *       uidNamespaceID = NULL,
00389               uint8_t *       uidInstanceID = NULL,
00390               const char *    url = NULL,
00391               uint8_t         urlLen = 0,
00392               uint8_t         tlmVersion = 0) :
00393               ble(bleIn)
00394     { 
00395         uint8_t serviceData[SERVICE_DATA_MAX];
00396         unsigned serviceDataLen = 0;
00397         ERR("This function is not fully implemented yet, dont use it!!");
00398         // Check optional frames, set their 'isSet' flags appropriately
00399         if((uidNamespaceID != NULL) & (uidInstanceID != NULL)) {
00400             uidIsSet = true;
00401             setUIDFrameData(txPowerLevel,uidNamespaceID, uidInstanceID);
00402         } else {
00403             uidIsSet = false;
00404         }
00405         if(url != NULL) {
00406             urlIsSet = true;
00407             setURLFrameData(txPowerLevel,url);
00408         } else {
00409             uidIsSet = false;
00410         }
00411         // Default TLM frame to version 0x00, start all values at zero to be spec compliant.
00412         setTLMFrameData(tlmVersion, 0x00,0x00);
00413 
00414         // Initialize Frame transition
00415         frameIndex = 0;
00416         uidRFU = 0;
00417         switchFlag = true;
00418 
00419         /* Reinitialize the BLE stack. This will clear away the existing services and advertising state. */
00420         ble.shutdown();
00421         ble.init();
00422         ble.setTxPower(txPowerLevel);
00423         ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
00424         ble.setAdvertisingInterval(beaconPeriodus);
00425 
00426         // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset
00427         updateTlmPduCount(0);
00428         updateTlmTimeSinceBoot(0);
00429 
00430         // Construct TLM Frame in initial advertising.
00431         serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
00432         serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
00433         serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,SERVICE_DATA_MAX);
00434 
00435         updateAdvPacket(serviceData, serviceDataLen);
00436         ble.gap().startAdvertising();
00437         ble.gap().onRadioNotification(this,&EddystoneService::radioNotificationCallback);
00438         timeSinceBootTick.attach(this,&EddystoneService::tsbCallback,0.1); // incriment the TimeSinceBoot ticker every 0.1s
00439 
00440     }
00441 
00442 private:
00443 
00444 
00445     BLEDevice           &ble;
00446     Ticker              timeSinceBootTick;
00447     Timeout             switchFrame;
00448 // Default value that is restored on reset
00449     size_t              defaultUriDataLength;
00450     UriData_t           defaultUriData;
00451     UIDNamespaceID_t    defaultUidNamespaceID;
00452     UIDInstanceID_t     defaultUidInstanceID;
00453     int8_t              defaultUidPower;
00454     int8_t              defaultUrlPower;
00455     uint16_t            uidRFU;
00456     bool                uidIsSet;
00457     bool                urlIsSet;
00458     bool switchFlag;
00459 
00460 // Private Variables for Telemetry Data
00461     uint8_t                      TlmVersion;
00462     volatile uint16_t            TlmBatteryVoltage;
00463     volatile uint16_t            TlmBeaconTemp;
00464     volatile uint32_t            TlmPduCount;
00465     volatile uint32_t            TlmTimeSinceBoot;
00466 
00467 public:
00468     /*
00469      *  Encode a human-readable URI into the binary format defined by Eddystone-URL spec (https://github.com/google/eddystone/tree/master/eddystone-url).
00470      */
00471     static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, size_t &sizeofURIDataOut) {
00472         const char *prefixes[] = {
00473             "http://www.",
00474             "https://www.",
00475             "http://",
00476             "https://",
00477         };
00478         const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
00479         const char *suffixes[] = {
00480             ".com/",
00481             ".org/",
00482             ".edu/",
00483             ".net/",
00484             ".info/",
00485             ".biz/",
00486             ".gov/",
00487             ".com",
00488             ".org",
00489             ".edu",
00490             ".net",
00491             ".info",
00492             ".biz",
00493             ".gov"
00494         };
00495         const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
00496 
00497         sizeofURIDataOut = 0;
00498         memset(uriDataOut, 0, sizeof(UriData_t));
00499 
00500         if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
00501             return;
00502         }
00503 
00504         /*
00505          * handle prefix
00506          */
00507         for (unsigned i = 0; i < NUM_PREFIXES; i++) {
00508             size_t prefixLen = strlen(prefixes[i]);
00509             if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
00510                 uriDataOut[sizeofURIDataOut++]  = i;
00511                 uriDataIn                      += prefixLen;
00512                 break;
00513             }
00514         }
00515 
00516         /*
00517          * handle suffixes
00518          */
00519         while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
00520             /* check for suffix match */
00521             unsigned i;
00522             for (i = 0; i < NUM_SUFFIXES; i++) {
00523                 size_t suffixLen = strlen(suffixes[i]);
00524                 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
00525                     uriDataOut[sizeofURIDataOut++]  = i;
00526                     uriDataIn                      += suffixLen;
00527                     break; /* from the for loop for checking against suffixes */
00528                 }
00529             }
00530             /* This is the default case where we've got an ordinary character which doesn't match a suffix. */
00531             if (i == NUM_SUFFIXES) {
00532                 uriDataOut[sizeofURIDataOut++] = *uriDataIn;
00533                 ++uriDataIn;
00534             }
00535         }
00536     }
00537 };
00538 
00539 #endif  // SERVICES_EDDYSTONEBEACON_H_