-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Fix for negative temp in Eddystone TLM; solving #7618 #7791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ddd6496
1f3a941
cc893d5
f677580
50e1c7e
3ee9d53
125cdee
96faa77
0980a21
a42a513
1f406c6
f638759
c9bf68d
aa5486b
a64613d
5529457
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,8 +14,6 @@ | |
#include <BLEEddystoneTLM.h> | ||
#include <BLEBeacon.h> | ||
|
||
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8)) | ||
|
||
int scanTime = 5; //In seconds | ||
BLEScan *pBLEScan; | ||
|
||
|
@@ -37,58 +35,66 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks | |
Serial.println(devUUID.toString().c_str()); | ||
Serial.println(""); | ||
} | ||
else | ||
|
||
if (advertisedDevice.haveManufacturerData() == true) | ||
{ | ||
if (advertisedDevice.haveManufacturerData() == true) | ||
{ | ||
std::string strManufacturerData = advertisedDevice.getManufacturerData(); | ||
std::string strManufacturerData = advertisedDevice.getManufacturerData(); | ||
|
||
uint8_t cManufacturerData[100]; | ||
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); | ||
uint8_t cManufacturerData[100]; | ||
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); | ||
|
||
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) | ||
{ | ||
Serial.println("Found an iBeacon!"); | ||
BLEBeacon oBeacon = BLEBeacon(); | ||
oBeacon.setData(strManufacturerData); | ||
Serial.printf("iBeacon Frame\n"); | ||
Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower()); | ||
} | ||
else | ||
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) | ||
{ | ||
Serial.println("Found an iBeacon!"); | ||
BLEBeacon oBeacon = BLEBeacon(); | ||
oBeacon.setData(strManufacturerData); | ||
Serial.printf("iBeacon Frame\n"); | ||
Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower()); | ||
} | ||
else | ||
{ | ||
Serial.println("Found another manufacturers beacon!"); | ||
Serial.printf("strManufacturerData: %d ", strManufacturerData.length()); | ||
for (int i = 0; i < strManufacturerData.length(); i++) | ||
{ | ||
Serial.println("Found another manufacturers beacon!"); | ||
Serial.printf("strManufacturerData: %d ", strManufacturerData.length()); | ||
for (int i = 0; i < strManufacturerData.length(); i++) | ||
{ | ||
Serial.printf("[%X]", cManufacturerData[i]); | ||
} | ||
Serial.printf("\n"); | ||
Serial.printf("[%X]", cManufacturerData[i]); | ||
} | ||
Serial.printf("\n"); | ||
} | ||
return; | ||
} | ||
|
||
uint8_t *payLoad = advertisedDevice.getPayload(); | ||
// search for Eddystone Service Data in the advertising payload | ||
// *payload shall point to eddystone data or to its end when not found | ||
const uint8_t serviceDataEddystone[3] = {0x16, 0xAA, 0xFE}; // it has Eddystone BLE UUID | ||
const size_t payLoadLen = advertisedDevice.getPayloadLength(); | ||
uint8_t *payLoadEnd = payLoad + payLoadLen - 1; // address of the end of payLoad space | ||
while (payLoad < payLoadEnd) { | ||
if (payLoad[1] == serviceDataEddystone[0] && payLoad[2] == serviceDataEddystone[1] && payLoad[3] == serviceDataEddystone[2]) { | ||
// found! | ||
payLoad += 4; | ||
break; | ||
} | ||
payLoad += *payLoad + 1; // payLoad[0] has the field Length | ||
} | ||
|
||
BLEUUID checkUrlUUID = (uint16_t)0xfeaa; | ||
|
||
if (advertisedDevice.getServiceUUID().equals(checkUrlUUID)) | ||
if (payLoad < payLoadEnd) // Eddystone Service Data and respective BLE UUID were found | ||
{ | ||
if (payLoad[11] == 0x10) | ||
if (*payLoad == 0x10) | ||
{ | ||
Serial.println("Found an EddystoneURL beacon!"); | ||
BLEEddystoneURL foundEddyURL = BLEEddystoneURL(); | ||
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! | ||
|
||
foundEddyURL.setData(eddyContent); | ||
uint8_t URLLen = *(payLoad - 4) - 3; // Get Field Length less 3 bytes (type and UUID) | ||
foundEddyURL.setData(std::string((char*)payLoad, URLLen)); | ||
std::string bareURL = foundEddyURL.getURL(); | ||
if (bareURL[0] == 0x00) | ||
{ | ||
size_t payLoadLen = advertisedDevice.getPayloadLength(); | ||
// dumps all bytes in advertising payload | ||
Serial.println("DATA-->"); | ||
uint8_t *payLoad = advertisedDevice.getPayload(); | ||
for (int idx = 0; idx < payLoadLen; idx++) | ||
{ | ||
Serial.printf("0x%08X ", payLoad[idx]); | ||
Serial.printf("0x%02X ", payLoad[idx]); | ||
} | ||
Serial.println("\nInvalid Data"); | ||
return; | ||
|
@@ -98,30 +104,19 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks | |
Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str()); | ||
Serial.printf("TX power %d\n", foundEddyURL.getPower()); | ||
Serial.println("\n"); | ||
} | ||
else if (payLoad[11] == 0x20) | ||
} | ||
else if (*payLoad == 0x20) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. I checked it with nRF APP and it is correct. The position is 22. |
||
Serial.println("Found an EddystoneTLM beacon!"); | ||
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM(); | ||
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just changed Line 106 to: |
||
|
||
eddyContent = "01234567890123"; | ||
|
||
for (int idx = 0; idx < 14; idx++) | ||
{ | ||
eddyContent[idx] = payLoad[idx + 11]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just changed Line 112 to: |
||
} | ||
|
||
foundEddyURL.setData(eddyContent); | ||
Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt()); | ||
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp()); | ||
int temp = (int)payLoad[16] + (int)(payLoad[15] << 8); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just changed Line 118 to: |
||
float calcTemp = temp / 256.0f; | ||
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp); | ||
Serial.printf("Reported advertise count: %d\n", foundEddyURL.getCount()); | ||
Serial.printf("Reported time since last reboot: %ds\n", foundEddyURL.getTime()); | ||
|
||
BLEEddystoneTLM eddystoneTLM; | ||
eddystoneTLM.setData(std::string((char*)payLoad, 14)); | ||
Serial.printf("Reported battery voltage: %dmV\n", eddystoneTLM.getVolt()); | ||
Serial.printf("Reported temperature: %.2f°C (raw data=0x%04X)\n", eddystoneTLM.getTemp(), eddystoneTLM.getRawTemp()); | ||
Serial.printf("Reported advertise count: %d\n", eddystoneTLM.getCount()); | ||
Serial.printf("Reported time since last reboot: %ds\n", eddystoneTLM.getTime()); | ||
Serial.println("\n"); | ||
Serial.print(foundEddyURL.toString().c_str()); | ||
Serial.print(eddystoneTLM.toString().c_str()); | ||
Serial.println("\n"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason for removing Lines 123 to 125? |
||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,6 @@ | |
#include "BLEEddystoneTLM.h" | ||
|
||
static const char LOG_TAG[] = "BLEEddystoneTLM"; | ||
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8)) | ||
#define ENDIAN_CHANGE_U32(x) ((((x)&0xFF000000)>>24) + (((x)&0x00FF0000)>>8)) + ((((x)&0xFF00)<<8) + (((x)&0xFF)<<24)) | ||
|
||
BLEEddystoneTLM::BLEEddystoneTLM() { | ||
beaconUUID = 0xFEAA; | ||
|
@@ -47,9 +45,13 @@ uint16_t BLEEddystoneTLM::getVolt() { | |
} // getVolt | ||
|
||
float BLEEddystoneTLM::getTemp() { | ||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; | ||
return EDDYSTONE_TEMP_U16_TO_FLOAT(m_eddystoneData.temp); | ||
} // getTemp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As said, this is a breaking change. I think it should stay the same: It should just use the new MACRO to convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion is to eliminate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be the final code: float BLEEddystoneTLM::getTemp() {
return EDDYSTONE_TEMP_U16_TO_FLOAT(m_eddystoneData.temp);
} // getTemp |
||
|
||
uint16_t BLEEddystoneTLM::getRawTemp() { | ||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp); | ||
} // getRawTemp | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As said, this is a breaking change. I think it should stay the same: It should just use the new MACRO to convert u16 to float, considering the signal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No need to use Please eliminate this method because it causes a breaking change to the API. |
||
uint32_t BLEEddystoneTLM::getCount() { | ||
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); | ||
} // getCount | ||
|
@@ -73,7 +75,7 @@ std::string BLEEddystoneTLM::toString() { | |
out += " mV\n"; | ||
|
||
out += "Temperature "; | ||
snprintf(val, sizeof(val), "%.2f", ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f); | ||
snprintf(val, sizeof(val), "%.2f", ((int16_t)ENDIAN_CHANGE_U16(m_eddystoneData.temp)) / 256.0f); | ||
out += val; | ||
out += " C\n"; | ||
|
||
|
@@ -110,6 +112,21 @@ std::string BLEEddystoneTLM::toString() { | |
|
||
/** | ||
* Set the raw data for the beacon record. | ||
* Example: | ||
* uint8_t *payLoad = advertisedDevice.getPayload(); | ||
* eddystoneTLM.setData(std::string((char*)payLoad+22, advertisedDevice.getPayloadLength() - 22)); | ||
* Note: the offset 22 works for current implementation of example BLE_EddystoneTLM Beacon.ino, however it is not static and will be reimplemented | ||
* Data frame: | ||
* | Field || Len | Type | UUID | EddyStone TLM | | ||
* | Offset || 0 | 1 | 2 | 4 | | ||
* | Len || 1 B | 1 B | 2 B | 14 B | | ||
* | Data || ?? | ?? | 0xAA | 0xFE | ??? | | ||
* | ||
* EddyStone TLM frame: | ||
* | Field || Type | Version | Batt mV | Beacon temp | Cnt since boot | Time since boot | | ||
* | Offset || 0 | 1 | 2 | 4 | 6 | 10 | | ||
* | Len || 1 B | 1 B | 2 B | 2 B | 4 B | 4 B | | ||
* | Data || 0x20 | ?? | ?? | ?? | ?? | ?? | | | | | | | | | | ||
*/ | ||
void BLEEddystoneTLM::setData(std::string data) { | ||
if (data.length() != sizeof(m_eddystoneData)) { | ||
|
@@ -132,7 +149,7 @@ void BLEEddystoneTLM::setVolt(uint16_t volt) { | |
} // setVolt | ||
|
||
void BLEEddystoneTLM::setTemp(float temp) { | ||
m_eddystoneData.temp = (uint16_t)temp; | ||
m_eddystoneData.temp = EDDYSTONE_TEMP_FLOAT_TO_U16(temp); | ||
} // setTemp | ||
|
||
void BLEEddystoneTLM::setCount(uint32_t advCount) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just changed Line 102 to:
else if (payLoad[22] == 0x20)
in order to make it work.