Skip to content
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

BLEEddystoneTLM wrong handling of temperature field of beacon data #3833

Closed
beegee-tokyo opened this issue Mar 19, 2020 · 5 comments
Closed

Comments

@beegee-tokyo
Copy link
Contributor

Hardware:

Board: ESP32 Dev Module
Core Installation version: 1.0.3
IDE name: Arduino IDE & Platform.io
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 7

Description:

@chegewara , can you confirm?
EddystoneTLM has a temperature value.
According to Google definition the format is 8.8 fixed-point notation. But in the BLEEddystoneTLM class the temperature is declared as float, and the two bytes of the temperature value is just interpreted as an float value which gives complete wrong values. I found one Eddystone TLM example, and there the setting the temperature values is done wrong as well. The wrong value can be seen in nRFConnect, where it shows impossible temperatures.

The correct conversion from float to 8.8 fixed-point and back is shown in Fixed Point Maths.

The correct conversion on the beacon side would be (as example read temperature from a DHT sensor)

float tempFloat = dht.getTemperature();
int temp = (int)(tempFloat * 256);
...
beacon_data[5] = (temp & 0xFF);					   // Beacon temperature
beacon_data[4] = (temp >> 8);					   //
...

And in BLEEddystoneTLM class the getTemp() function should be

float NimBLEEddystoneTLM::getTemp() {
	return ((((m_eddystoneData.temp) & 0xFF00) >> 8) + (((m_eddystoneData.temp) & 0xFF) << 8)) / 256.0f;
} // getTemp

Sketch: Modified BLE scanner example

#include <Arduino.h>

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#include "BLEEddystoneURL.h"
#include "BLEEddystoneTLM.h"
#include "BLEBeacon.h"

#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))

int scanTime = 5; //In seconds
BLEScan *pBLEScan;

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
    void onResult(BLEAdvertisedDevice advertisedDevice) {
	{
		if (advertisedDevice.haveName())
		{
			Serial.print("Device name: ");
			Serial.println(advertisedDevice.getName().c_str());
			Serial.println("");
		}

		if (advertisedDevicehaveServiceUUID())
		{
			BLEUUID devUUID = advertisedDevice.getServiceUUID();
			Serial.print("Found ServiceUUID: ");
			Serial.println(devUUID.toString().c_str());
			Serial.println("");
		}
		else
		{
			return;
		}

		uint8_t *payLoad = advertisedDevice.getPayload();

		BLEUUID checkUrlUUID = (uint16_t)0xfeaa;

		if (advertisedDevice.getServiceUUID().equals(checkUrlUUID))
		{
			if (payLoad[11] == 0x10)
			{
				// this part for Eddystone URL beacon
			}
			else if (payLoad[11] == 0x20)
			{
				Serial.println("Found an EddystoneTLM beacon!");
				BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();

				// Why The F*** is a std::string used here. THE ADVERTISED DATA IS BINARY AND CONTAINS NULL VALUES
				std::string eddyContent = "01234567890123";

				for (int idx = 0; idx < 14; idx++)
				{
					eddyContent[idx] = payLoad[idx + 11];
				}

				foundEddyURL.setData(eddyContent);
				Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
				Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
				// Correct calculation of temperature from 8.8 fixed-point
				int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
				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: %dms\n", foundEddyURL.getTime());
				Serial.println("\n");
			}
		}
	}
};

void setup()
{
	Serial.begin(115200);
	Serial.println("Scanning...");

	BLEDevice::init("");
	pBLEScan = BLEDevice::getScan(); //create new scan
	pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
	pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
	pBLEScan->setInterval(100);
	pBLEScan->setWindow(99); // less or equal setInterval value
}

void loop()
{
	// put your main code here, to run repeatedly:
	BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
	Serial.print("Devices found: ");
	Serial.println(foundDevices.getCount());
	Serial.println("Scan done!");
	pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
	delay(2000);
}

Debug Messages: Log output with both the incorrect calculated and correct calculated temperature.

Reported temperature from TLM class: 33309.00C
Reported temperature from data: 29.51C
@chegewara
Copy link
Contributor

chegewara commented Mar 19, 2020

Hi,
yes, i can confirm that EddystoneTLM should be 8.8 fixed-point notation.
Simplest way to get temp is:
((int16_t)value) / 256.0f
So, yes, you are correct.

@beegee-tokyo
Copy link
Contributor Author

Thanks for confirming. Not sure about the ((int16_t)value) / 256.0fbecause I got a little Endian / big Endian problem.

Will prepare a pull-request together with samples for EddystoneTLM, EddystoneURL and a beacon scanner.

@chegewara
Copy link
Contributor

Maybe you like this:
https://shop.strato.de/WebRoot/Store19/Shops/81396262/MediaGallery/Dokumente/Anleitungen/S1_Firmware_Interface_Instruction_Document_V102.pdf
Its instruction to eddystone TLM beacon and how data can be broadcasted in advertising.

@beegee-tokyo
Copy link
Contributor Author

Interesting, but it's not exactly EddystoneTLM format. Will check details tomorrow.

beegee-tokyo added a commit to beegee-tokyo/arduino-esp32 that referenced this issue Mar 20, 2020
Add Beacon scanner example to show usage of BLEEddystoneTLM class and  BLEEddystoneURL class     
Add EddystoneTLM beacon example    
Add EddystoneURL beacon example
@beegee-tokyo
Copy link
Contributor Author

Fixed with #3836

me-no-dev pushed a commit that referenced this issue Sep 30, 2020
* Fix issue #3833, data parsing of Eddystone TLM data frame    
Add Beacon scanner example to show usage of BLEEddystoneTLM class and  BLEEddystoneURL class     
Add EddystoneTLM beacon example    
Add EddystoneURL beacon example

* Fix buffer size for .toString()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants