nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.33k stars 709 forks source link

How to read Eddystone TLM? #345

Open shahabmusic opened 6 years ago

shahabmusic commented 6 years ago

Is it possible to extract temperature values from an Eddystone TLM data?

I have a beacon that advertises the temperature and battery level. I can see these data using Android eddystone app and would like to see these data in esp32 in Arduino IDE too.

In one of the snippets I saw that you wait until you receive an Adv data type 0x16 and then you look for 0x1809 uuid and then you decode the temperature.

I tried to do the same thing in BLEAdvertisedDevice class. It find adv data type 0x16, however the esp32 does not find 0x1809 uuid.

This is my serial output.

`[D][BLEUtils.cpp:1067] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_SCAN_RESULT_EVT

[D][BLEUtils.cpp:1241] dumpGapEvent(): search_evt: ESP_GAP_SEARCH_INQ_RES_EVT, bda: cc:78:ab:8d:7d:76, dev_type: ESP_BT_DEVICE_TYPE_BLE, ble_addr_type: BLE_ADDR_TYPE_PUBLIC, ble_evt_type: ESP_BLE_EVT_CONN_ADV, rssi: -68, ble_adv: ??, flag: 4 ([BR/EDR Not Supported] ), num_resps: 1, adv_data_len: 25, scan_rsp_len: 0

[D][BLEAdvertisedDevice.cpp:487] setRSSI(): - setRSSI(): rssi: -68

[D][BLEAdvertisedDevice.cpp:298] parseAdvertisement(): Type: 0x01 (ESP_BLE_AD_TYPE_FLAG), length: 1, data: 04

[D][BLEAdvertisedDevice.cpp:298] parseAdvertisement(): Type: 0x03 (ESP_BLE_AD_TYPE_16SRV_CMPL), length: 2, data: aafe

[D][BLEAdvertisedDevice.cpp:516] setServiceUUID(): - addServiceUUID(): serviceUUID: 0000feaa-0000-1000-8000-00805f9b34fb

[D][BLEAdvertisedDevice.cpp:298] parseAdvertisement(): Type: 0x16 (ESP_BLE_AD_TYPE_SERVICE_DATA), length: 16, data: aafe20000b3714000080a09101443b20

`

Am I in the right path to get temperature readings? could anyone help please?

chegewara commented 6 years ago

This is your UUID 0000feaa-0000-1000-8000-00805f9b34fb. Also check this line [D][BLEAdvertisedDevice.cpp:298] parseAdvertisement(): Type: 0x03 (ESP_BLE_AD_TYPE_16SRV_CMPL), length: 2, data: aafe. This is your data packet aafe20000b3714000080a09101443b20 but you have to remember that bluetooth is using little endian. So you need to use 0xfeaa instead 0x1809

chegewara commented 6 years ago

But i think this data might be broken. This is nice info to read, first link i found with google: https://github.com/google/eddystone/blob/master/protocol-specification.md

chegewara commented 6 years ago

@shahabmusic You can check what raw data are used to advertise, i like to use nRF connect, and read from it what service UUID is used in advertising packet. If you have issue to read it you can paste here raw advertising packet or screenshot and we will try to help. Screenshot prefered like this one https://ibin.co/3lNX93QvWwn3.png

shahabmusic commented 6 years ago

here is screen shot of nRF

https://imagebin.ca/v/3nEK1J5YY3FS

chegewara commented 6 years ago

Ok, this is what i see:

PS is that true its been accessed over 8 million times?

shahabmusic commented 6 years ago

Thank you so much. Finally I could solve the puzzle after 3 weeks. So in my raw data: Type: 0x16 (ESP_BLE_AD_TYPE_SERVICE_DATA), length: 16, data: aafe20000b651b00008151d801667640 Temperature is 0x1b00. When I use a online hex to integer converter, I can convert b1 to 27 and 00 to 0 so temperature is 27.00 degrees. Now how can I do this conversion in C?

chegewara commented 6 years ago

Again, google is your friend. First link: https://stackoverflow.com/questions/1070497/c-convert-hex-string-to-signed-integer

I like this solution:

Andy Buchanan, as far as sticking to C++ goes, I liked yours, but I have a few mods: template <typename ElemT> struct HexTo { ElemT value; operator ElemT() const {return value;} friend std::istream& operator>>(std::istream& in, HexTo& out) { in >> std::hex >> out.value; return in; } };Used likeuint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");

or this: std::strtoul(<buffer>, <buffer_length>, <base>)

nkolban commented 6 years ago

Once you have the 14 bytes of TLM frame data, they can be decoded by mapping that data to the following structure:

struct tlm {
   uint8_t frameType;
   uint8_t version;
   uint16_t voltage;
   uint16_t temp;
   uint32_t pduCount;
   uint32_t timeCount;
}  __attribute__((packed));

see .... https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md#unencrypted-tlm-frame-specification

1technophile commented 6 years ago

Hello,

Seems the kind of work I have done with mi flora : https://1technophile.blogspot.fr/2017/11/mi-flora-integration-to-openmqttgateway.html

In this file : https://github.com/1technophile/OpenMQTTGateway/blob/master/ZgatewayBT.ino

you have methods to :

In particular take a look to process_miflora_data. Maybe not the most elegant way but works.

masdel123 commented 4 years ago

Thank you so much. Finally I could solve the puzzle after 3 weeks. So in my raw data: Type: 0x16 (ESP_BLE_AD_TYPE_SERVICE_DATA), length: 16, data: aafe20000b651b00008151d801667640 Temperature is 0x1b00. When I use a online hex to integer converter, I can convert b1 to 27 and 00 to 0 so temperature is 27.00 degrees. Now how can I do this conversion in C?

How could you solve this problem?Can you explain this? Because I have same issue about tlm-parsing to get battery value