nkolban / esp32-snippets

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

Multiple UUIDs' service data #791

Open marcoaltomonte opened 5 years ago

marcoaltomonte commented 5 years ago

I am trying to get data from a Xiaomi Temperature Humidity sensor: its payload is composed by a 0x95fe 2bytes service data, followed by a name record, followed by a 0xff 2 bytes service data. BLEAdvertisedDevice::parseAdvertisement parses the first 0x95fe service data but then it overwrites it with the 0xffff one. It would be great if the code can expose multiple getters.

chegewara commented 5 years ago

Hi, is it possible to paste whole advertising raw data or screenshot from nRF connect?

marcoaltomonte commented 5 years ago

This is the raw data I took yesterday to debug: 020106151695FE5020AA018A8979D8A8654C0D1004ED00BF0109094D4A5F48545F563105030F180A180916FFFFCFC1AFBE987D

If I understood the code correctly, I think it is devided into: 02.01.06 15.16.95FE.5020AA018A8979D8A8654C0D1004ED00BF01 09.09.4D4A5F48545F5631 05.03.0F180A18 09.16.FFFF.CFC1AFBE987D

Il giorno mar 22 gen 2019 alle ore 14:16 chegewara notifications@github.com ha scritto:

Hi, is it possible to paste whole advertising raw data or screenshot from nRF connect?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/791#issuecomment-456395326, or mute the thread https://github.com/notifications/unsubscribe-auth/ADAeSyYHtXlHPq8r3Pndcvy2wa04gcvyks5vFw8pgaJpZM4aMoNK .

marcoaltomonte commented 5 years ago

Maybe this can help: just the first ble packet is 51 bytes long. All the following packets are smaller (around 25 bytes): they do not include name advertizing (is it stripped by esp code?) nor the 0xffff uuid.

chegewara commented 5 years ago

Hi @marcoaltomonte Advertising data should not be striped by esp code. There is one weird thing i see in this advertising packet. You have twice 0x10(16). This is weird to me only because im not familiar with this kind of packet:

0x10 | «Device ID» | Device ID Profile v1.3 or later

0x10 | «Security Manager TK Value» | Bluetooth Core Specification:Vol. 3, Part C, sections 11.1.7 and 18.6 (v4.0)Core Specification Supplement, Part A, section 1.8

The problem is that 0x10 is not parsed by this library, it is just discarded and should be printed in logs as `"Unhandled type: adType: 0x10"

obart78 commented 5 years ago

I have the same device and issue: The Type in OPs dump is already hex 0x16 not 16d. This device advertises two services with different uuids. But the parser overwrites the 95fe uuid with the ffff one.

chegewara commented 5 years ago

Yes @obart78 i realized i made mistake in post some time later.

This is how code works in steps: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEAdvertisedDevice.cpp#L280 https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEAdvertisedDevice.cpp#L451 https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEAdvertisedDevice.cpp#L141

marcoaltomonte commented 5 years ago

I worked around this issue by parsing the payload myself.

guillier commented 5 years ago

Hi,

Using this patch from PR nkolban/ESP32_BLE_Arduino#24 I was able to work around this issue. I would be nice to see it integrated even if, as it is, it changes slightly the functions signatures. Though, using std::string BLEAdvertisedDevice::getServiceData(int i=0) and BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i=0) avoids breakage while solving the problem.

andreyxc commented 5 years ago

https://github.com/hannseman/homebridge-mi-hygrothermograph

Technical details

The plugin scans for Bluetooth Low Energy peripherals and check the broadcast advertisement packets. By only reading the advertisement packet there is no need to establish a connection to the peripheral. Inside each packet discovered we look for Service Data with a UUID of 0xfe95. If found we start trying to parse the actual Service Data to find the temperature and humidity.

By using a Bluetooth LE Sniffer it is possible to see that the peripheral advertises 3 different sized Service Data:

50:20:aa:01:be:64:ae:d0:a8:65:4c:0d:10:04:cc:00:8a:01 50:20:aa:01:ba:64:ae:d0:a8:65:4c:06:10:02:84:01 50:20:aa:01:c0:64:ae:d0:a8:65:4c:0a:10:01:5d Some bytes stay the same and some bytes change over time. By placing the peripheral in different temperated places it could be established that the last bytes contain the sensor data.

These were the observations:

In the first example the last two bytes 8a:01 contains the humidity data. 8a:01 as an little endian 16-bit integer is equal to 394 as in 39.4 % relative humidity. If we check the next two bytes cc:00 they equal to 204 as in 20.4 celsius. In the second example 84:01 equals to 388 as in 38.8 % relative humidity. No temperature could be found in this data, more on that later. In the shortest and third example 5d equals to 93 and this very much looks like the charge level on the battery in percent. If we start looking at the other bytes in order the next one looks like a length indicator for the following bytes with 04, 02 and 01 as values. The following two bytes almost always stays the same for each sized packet except for the 16 bytes sized data here they alterate between 06:10 and 04:10. After some investigation it is established that these bytes indicate what type of sensor data that will follow. 06:10 will have humidity data and 04:10 will have temperature data. 0d:10 indicate that both humidity and temperature data will follow and 0a:10 that battery data is to be expected.

andreyxc commented 5 years ago

I did not understand how to solve the problem ((