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.
Fork of BLE_API by
Diff: ble/services/EddystoneService.h
- Revision:
- 832:5dac246f8f02
- Parent:
- 830:a6ef72e0697a
- Child:
- 841:468a5863cacb
--- a/ble/services/EddystoneService.h Tue Sep 29 09:54:19 2015 +0100 +++ b/ble/services/EddystoneService.h Tue Sep 29 09:54:19 2015 +0100 @@ -24,20 +24,32 @@ //Debug is disabled by default #if 0 -#define DBG(x, ...) printf("[EddyStone: DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); -#define WARN(x, ...) printf("[EddyStone: WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); -#define ERR(x, ...) printf("[EddyStone: ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); -#else +#define DBG(MSG, ...) printf("[EddyStone: DBG]" MSG " \t[%s,%d]\r\n", \ + ## __VA_ARGS__, \ + __FILE__, \ + __LINE__); +#define WARN(MSG, ...) printf("[EddyStone: WARN]" MSG " \t[%s,%d]\r\n", \ + ## __VA_ARGS__, \ + __FILE__, \ + __LINE__); +#define ERR(MSG, ...) printf("[EddyStone: ERR]" MSG " \t[%s,%d]\r\n", \ + ## __VA_ARGS__, \ + __FILE__, \ + __LINE__); +#else // if 0 #define DBG(x, ...) //wait_us(10); #define WARN(x, ...) //wait_us(10); #define ERR(x, ...) -#endif +#endif // if 0 #if 0 -#define INFO(x, ...) printf("[EddyStone: INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); -#else +#define INFO(x, ...) printf("[EddyStone: INFO]"x " \t[%s,%d]\r\n", \ + ## __VA_ARGS__, \ + __FILE__, \ + __LINE__); +#else // if 0 #define INFO(x, ...) -#endif +#endif // if 0 /** * @class Eddystone @@ -62,7 +74,7 @@ void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t); static const int URI_DATA_MAX = 18; typedef uint8_t UriData_t[URI_DATA_MAX]; - CircularBuffer<FrameTypes,EDDYSTONE_MAX_FRAMETYPE> overflow; + CircularBuffer<FrameTypes, EDDYSTONE_MAX_FRAMETYPE> overflow; // UID Frame Type subfields static const int UID_NAMESPACEID_SIZE = 10; @@ -78,90 +90,98 @@ static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes - /* - * Set Eddystone UID Frame information. - * @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB. - * @param namespaceID 10B namespace ID - * @param instanceID 6B instance ID - * @param RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference. - * - */ - void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, uint32_t uidAdvPeriodIn, uint16_t RFU = 0x0000) { - if(0 == uidAdvPeriodIn){ + /** + * Set Eddystone UID Frame information. + * + * @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB. + * @param[in] namespaceID 10B namespace ID + * @param[in] instanceID 6B instance ID + * @param[in] RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference. + */ + void setUIDFrameData(int8_t power, + UIDNamespaceID_t namespaceID, + UIDInstanceID_t instanceID, + uint32_t uidAdvPeriodIn, + uint16_t RFU = 0x0000) { + if (0 == uidAdvPeriodIn) { uidIsSet = false; return; } - if(power > 20) { + if (power > 20) { power = 20; } - if(power < -100) { + if (power < -100) { power = -100; } + defaultUidPower = power; memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE); memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE); - uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesnt really matter yet. + uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesn't really matter yet. uidAdvPeriod = uidAdvPeriodIn; - uidIsSet = true; // set toggle to advertise UID frames - return; + uidIsSet = true; // set toggle to advertise UID frames } /* * Construct UID frame from private variables * @param[in/out] Data pointer to array to store constructed frame in - * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to + * @param[in] maxSize number of bytes left in array, effectively how much empty space is available to write to * @return number of bytes used. negative number indicates error message. */ - int constructUIDFrame(uint8_t * Data, uint8_t maxSize) { + unsigned constructUIDFrame(uint8_t *Data, uint8_t maxSize) { + unsigned index = 0; - int index = 0; Data[index++] = FRAME_TYPE_UID; // 1B Type - if(defaultUidPower > 20) { - defaultUidPower = 20; // enforce range of vaild values. + + if (defaultUidPower > 20) { + defaultUidPower = 20; // enforce range of vaild values. } - if(defaultUidPower < -100) { + if (defaultUidPower < -100) { defaultUidPower = -100; } Data[index++] = defaultUidPower; // 1B Power @ 0meter + DBG("UID NamespaceID = '0x"); - for(int x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespce ID + for (size_t x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespace ID Data[index++] = defaultUidNamespaceID[x]; - DBG("%x,",defaultUidNamespaceID[x]); + DBG("%x,", defaultUidNamespaceID[x]); } DBG("'\r\n"); - DBG("UID InstancdID = '0x"); - for(int x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID + + DBG("UID InstanceID = '0x"); + for (size_t x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID Data[index++] = defaultUidInstanceID[x]; - DBG("%x,",defaultUidInstanceID[x]); + DBG("%x,", defaultUidInstanceID[x]); } DBG("'\r\n"); - if(0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore + + if (0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore Data[index++] = (uint8_t)(uidRFU >> 0); Data[index++] = (uint8_t)(uidRFU >> 8); } - DBG("construcUIDFrame %d, %d",maxSize,index); + DBG("construcUIDFrame %d, %d", maxSize, index); return index; } - /* - * Set Eddystone URL Frame information. - * @param[in] power TX Power in dB measured at 0 meters from the device. - * @param url URL to encode - * @param urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods) - * @return false on success, true on failure. - */ - bool setURLFrameData(int8_t power, const char * urlIn, uint32_t urlAdvPeriodIn) { - if(0 == urlAdvPeriodIn){ + /** + * Set Eddystone URL Frame information. + * @param[in] power TX Power in dB measured at 0 meters from the device. + * @param[in] url URL to encode + * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods) + * @return false on success, true on failure. + */ + bool setURLFrameData(int8_t power, const char *urlIn, uint32_t urlAdvPeriodIn) { + if (0 == urlAdvPeriodIn) { urlIsSet = false; return false; } defaultUrlPower = power; encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting if (defaultUriDataLength > URI_DATA_MAX) { - return true; // error, URL is too big + return true; // error, URL is too big } urlAdvPeriod = urlAdvPeriodIn; - urlIsSet = true; + urlIsSet = true; return false; } @@ -171,14 +191,14 @@ * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to * @return number of bytes used. negative number indicates error message. */ - int constructURLFrame(uint8_t * Data, uint8_t maxSize) { + int constructURLFrame(uint8_t *Data, uint8_t maxSize) { int index = 0; Data[index++] = FRAME_TYPE_URL; // 1B Type Data[index++] = defaultUrlPower; // 1B TX Power - for(int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL + for (int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL Data[index++] = defaultUriData[x]; } - DBG("constructURLFrame: %d, %d",maxSize,index); + DBG("constructURLFrame: %d, %d", maxSize, index); return index; } @@ -190,19 +210,23 @@ * @param beaconTemp in 8.8 floating point notation * */ - void setTLMFrameData(uint8_t version = 0, uint32_t advPeriod = 60, uint16_t batteryVoltage = 0, uint16_t beaconTemp = 0, uint32_t pduCount = 0, uint32_t timeSinceBoot = 0) { - if(0 == advPeriod){ + void setTLMFrameData(uint8_t version = 0, + uint32_t advPeriod = 60, + uint16_t batteryVoltage = 0, + uint16_t beaconTemp = 0, + uint32_t pduCount = 0, + uint32_t timeSinceBoot = 0) { + if (0 == advPeriod) { tlmIsSet = false; return; } - TlmVersion = version; + TlmVersion = version; TlmBatteryVoltage = batteryVoltage; - TlmBeaconTemp = beaconTemp; - TlmPduCount = pduCount; // reset - TlmTimeSinceBoot = timeSinceBoot; // reset - TlmAdvPeriod = advPeriod; - tlmIsSet = true; // TLM Data has been enabled - return; + TlmBeaconTemp = beaconTemp; + TlmPduCount = pduCount; // reset + TlmTimeSinceBoot = timeSinceBoot; // reset + TlmAdvPeriod = advPeriod; + tlmIsSet = true; // TLM Data has been enabled } /* @@ -211,23 +235,23 @@ * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to * @return number of bytes used. negative number indicates error message. */ - int constructTLMFrame(uint8_t * Data, uint8_t maxSize) { + int constructTLMFrame(uint8_t *Data, uint8_t maxSize) { int index = 0; Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry Data[index++] = TlmVersion; // TLM Version Number - Data[index++] = (uint8_t)(TlmBatteryVoltage>>8); // Battery Voltage[0] - Data[index++] = (uint8_t)(TlmBatteryVoltage>>0); // Battery Voltage[1] - Data[index++] = (uint8_t)(TlmBeaconTemp>>8); // Beacon Temp[0] - Data[index++] = (uint8_t)(TlmBeaconTemp>>0); // Beacon Temp[1] - Data[index++] = (uint8_t)(TlmPduCount>>24); // PDU Count [0] - Data[index++] = (uint8_t)(TlmPduCount>>16); // PDU Count [1] - Data[index++] = (uint8_t)(TlmPduCount>>8); // PDU Count [2] - Data[index++] = (uint8_t)(TlmPduCount>>0); // PDU Count [3] - Data[index++] = (uint8_t)(TlmTimeSinceBoot>>24); // Time Since Boot [0] - Data[index++] = (uint8_t)(TlmTimeSinceBoot>>16); // Time Since Boot [1] - Data[index++] = (uint8_t)(TlmTimeSinceBoot>>8); // Time Since Boot [2] - Data[index++] = (uint8_t)(TlmTimeSinceBoot>>0); // Time Since Boot [3] - DBG("constructURLFrame: %d, %d",maxSize,index); + Data[index++] = (uint8_t)(TlmBatteryVoltage >> 8); // Battery Voltage[0] + Data[index++] = (uint8_t)(TlmBatteryVoltage >> 0); // Battery Voltage[1] + Data[index++] = (uint8_t)(TlmBeaconTemp >> 8); // Beacon Temp[0] + Data[index++] = (uint8_t)(TlmBeaconTemp >> 0); // Beacon Temp[1] + Data[index++] = (uint8_t)(TlmPduCount >> 24); // PDU Count [0] + Data[index++] = (uint8_t)(TlmPduCount >> 16); // PDU Count [1] + Data[index++] = (uint8_t)(TlmPduCount >> 8); // PDU Count [2] + Data[index++] = (uint8_t)(TlmPduCount >> 0); // PDU Count [3] + Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 24); // Time Since Boot [0] + Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 16); // Time Since Boot [1] + Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 8); // Time Since Boot [2] + Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 0); // Time Since Boot [3] + DBG("constructURLFrame: %d, %d", maxSize, index); return index; } @@ -238,7 +262,6 @@ */ void updateTlmBatteryVoltage(uint16_t voltagemv) { TlmBatteryVoltage = voltagemv; - return; } /* @@ -248,7 +271,6 @@ */ void updateTlmBeaconTemp(uint16_t temp) { TlmBeaconTemp = temp; - return; } /* @@ -258,7 +280,6 @@ */ void updateTlmPduCount(uint32_t pduCount) { TlmPduCount = pduCount; - return; } /* @@ -268,7 +289,6 @@ */ void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) { TlmTimeSinceBoot = timeSinceBoot; - return; } /* @@ -286,11 +306,7 @@ bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) { // Fields from the Service DBG("Updating AdvFrame: %d", serviceDataLen); -// printf("\r\n"); -// for(int x = 0; x<serviceDataLen; x++) { -// printf("%2.2x:",serviceData[x]); -// } -// printf("\r\n"); + ble.clearAdvertisingPayload(); ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); ble.setAdvertisingInterval(100); @@ -309,40 +325,45 @@ * broken up into two functions. */ void swapOutFrames(FrameTypes frameType) { - uint8_t serviceData[SERVICE_DATA_MAX]; + uint8_t serviceData[SERVICE_DATA_MAX]; unsigned serviceDataLen = 0; //hard code in the eddystone UUID serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0]; serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1]; // if certain frames are not enabled, then skip them. Worst case TLM is always enabled - switch(frameType) { + switch (frameType) { case tlm: // TLM frame - if(tlmIsSet) { - DBG("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d",TlmVersion, TlmBatteryVoltage, TlmBeaconTemp, TlmPduCount, TlmTimeSinceBoot); - serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,20); - DBG("\t Swapping in TLM Frame: len=%d",serviceDataLen); - updateAdvPacket(serviceData,serviceDataLen); + if (tlmIsSet) { + DBG("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d", + TlmVersion, + TlmBatteryVoltage, + TlmBeaconTemp, + TlmPduCount, + TlmTimeSinceBoot); + serviceDataLen += constructTLMFrame(serviceData + serviceDataLen, 20); + DBG("\t Swapping in TLM Frame: len=%d", serviceDataLen); + updateAdvPacket(serviceData, serviceDataLen); } break; case url: // URL Frame - if(urlIsSet) { - DBG("Swapping in URL Frame: Power: %d",defaultUrlPower); - serviceDataLen += constructURLFrame(serviceData+serviceDataLen,20); - DBG("\t Swapping in URL Frame: len=%d ",serviceDataLen); - updateAdvPacket(serviceData,serviceDataLen); + if (urlIsSet) { + DBG("Swapping in URL Frame: Power: %d", defaultUrlPower); + serviceDataLen += constructURLFrame(serviceData + serviceDataLen, 20); + DBG("\t Swapping in URL Frame: len=%d ", serviceDataLen); + updateAdvPacket(serviceData, serviceDataLen); //switchFlag = false; } break; case uid: // UID Frame - if(uidIsSet) { - DBG("Swapping in UID Frame: Power: %d",defaultUidPower); - serviceDataLen += constructUIDFrame(serviceData+serviceDataLen,20); - DBG("\t Swapping in UID Frame: len=%d",serviceDataLen); - updateAdvPacket(serviceData,serviceDataLen); + if (uidIsSet) { + DBG("Swapping in UID Frame: Power: %d", defaultUidPower); + serviceDataLen += constructUIDFrame(serviceData + serviceDataLen, 20); + DBG("\t Swapping in UID Frame: len=%d", serviceDataLen); + updateAdvPacket(serviceData, serviceDataLen); //switchFlag = false; } break; @@ -357,7 +378,7 @@ */ void urlCallback(void) { DBG("urlCallback"); - if( false == advLock) { + if (false == advLock) { advLock = true; DBG("advLock = url") frameIndex = url; @@ -365,11 +386,10 @@ ble.startAdvertising(); } else { // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free - INFO("URI(%d) cannot complete, %d is currently broadcasting",url, frameIndex); + INFO("URI(%d) cannot complete, %d is currently broadcasting", url, frameIndex); FrameTypes x = url; overflow.push(x); } - return; } /* @@ -377,7 +397,7 @@ */ void uidCallback(void) { DBG("uidCallback"); - if( false == advLock) { + if (false == advLock) { advLock = true; DBG("advLock = uid") frameIndex = uid; @@ -385,11 +405,10 @@ ble.startAdvertising(); } else { // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free - INFO("UID(%d) cannot complete, %d is currently broadcasting", uid,frameIndex); + INFO("UID(%d) cannot complete, %d is currently broadcasting", uid, frameIndex); FrameTypes x = uid; // have to do this to satisfy cont vs volatile keywords... sigh... overflow.push(x); } - return; } /* @@ -397,7 +416,7 @@ */ void tlmCallback(void) { DBG("tlmCallback"); - if( false == advLock) { + if (false == advLock) { // OK to broadcast advLock = true; DBG("advLock = tlm") @@ -406,15 +425,14 @@ ble.startAdvertising(); } else { // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free - INFO("TLM(%d) cannot complete, %d is currently broadcasting",tlm ,frameIndex); + INFO("TLM(%d) cannot complete, %d is currently broadcasting", tlm, frameIndex); FrameTypes x = tlm; overflow.push(x); } - return; } void stopAdvCallback(void) { - if(overflow.empty()) { + if (overflow.empty()) { // if nothing left to transmit, stop ble.stopAdvertising(); advLock = false; // unlock lock @@ -422,7 +440,7 @@ // transmit other packets at current time index FrameTypes x = NONE; overflow.pop(x); - INFO("Re-Transmitting %d",x); + INFO("Re-Transmitting %d", x); swapOutFrames(x); } } @@ -435,13 +453,12 @@ // Update PDUCount TlmPduCount++; // True just before an frame is sent, false just after a frame is sent - if(radioActive) { + if (radioActive) { // Do Nothing } else { // Packet has been sent, disable advertising stopAdv.attach_us(this, &EddystoneService::stopAdvCallback, 1); } - return; } /* @@ -453,15 +470,14 @@ * @param txPowerLevel sets the broadcasting power level. * */ - EddystoneService(BLEDevice &bleIn, - uint16_t beaconPeriodus = 100, - uint8_t txPowerIn = 0) : + EddystoneService(BLEDevice &bleIn, + uint16_t beaconPeriodus = 100, + uint8_t txPowerIn = 0) : ble(bleIn), advPeriodus(beaconPeriodus), txPower(txPowerIn), advLock(false), frameIndex(NONE) { - } /* @@ -479,25 +495,22 @@ uidTicker.attach(this, &EddystoneService::uidCallback, uidAdvPeriod); DBG("attached uidCallback every %d seconds", uidAdvPeriod); } - if(tlmIsSet) { + if (tlmIsSet) { frameIndex = tlm; // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset updateTlmPduCount(0); updateTlmTimeSinceBoot(0); - timeSinceBootTick.attach(this,&EddystoneService::tsbCallback,0.1); // incriment the TimeSinceBoot ticker every 0.1s + timeSinceBootTick.attach(this, &EddystoneService::tsbCallback, 0.1); // incriment the TimeSinceBoot ticker every 0.1s tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod); DBG("attached tlmCallback every %d seconds", TlmAdvPeriod); } - if(NONE == frameIndex) { + if (NONE == frameIndex) { error("No Frames were Initialized! Please initialize a frame before starting an eddystone beacon."); } //uidRFU = 0; - ble.setTxPower(txPower); -// ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); -// ble.setAdvertisingInterval(advPeriodus); -// ble.gap().startAdvertising(); - ble.gap().onRadioNotification(this,&EddystoneService::radioNotificationCallback); + ble.setTxPower(txPower); + ble.gap().onRadioNotification(this, &EddystoneService::radioNotificationCallback); } private: @@ -530,29 +543,29 @@ Ticker uidTicker; // TLM Frame Variables - uint8_t TlmVersion; - volatile uint16_t TlmBatteryVoltage; - volatile uint16_t TlmBeaconTemp; - volatile uint32_t TlmPduCount; - volatile uint32_t TlmTimeSinceBoot; - bool tlmIsSet; // flag that enables / disables TLM frames - uint32_t TlmAdvPeriod; // number of minutes between adv frames - Ticker tlmTicker; + uint8_t TlmVersion; + volatile uint16_t TlmBatteryVoltage; + volatile uint16_t TlmBeaconTemp; + volatile uint32_t TlmPduCount; + volatile uint32_t TlmTimeSinceBoot; + bool tlmIsSet; // flag that enables / disables TLM frames + uint32_t TlmAdvPeriod; // number of minutes between adv frames + Ticker tlmTicker; public: /* * Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification). */ static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, uint8_t &sizeofURIDataOut) { - DBG("Encode URL = %s",uriDataIn); - const char *prefixes[] = { + DBG("Encode URL = %s", uriDataIn); + const char *prefixes[] = { "http://www.", "https://www.", "http://", "https://", }; const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *); - const char *suffixes[] = { + const char *suffixes[] = { ".com/", ".org/", ".edu/",