2

For a project I'm currently trying to get some heart-related data (ppg) from a sensor (Polar OH1) via Bluetooth le. The service, which the manufacturer of the sensor uses is not documented very well. Now, when reading the characteristic value of the service, I get a huge amount of byte data:

'''\r\xb1\x1aQ\xb4x\xa3C\x83\xdcv\xd3Q\x12\xbdJ\x7f\x82\xbf\x06\x91s\x07\xb7,\xb4\xd5\xa59\xf1\xf8\x8e\xabeF@2\xe0\x10\xcb{\xe5\xfd\x8dC\x10f\x8ca\xe6\x98\xb2\xf9I\xaa\xb7\xff\xe3\xab\x13'\x03J\xd4\xb5*/...'''

Unfortunately, decoding this data with either utf-8, utf-16 (le,be) or utf-32 does not work. How can I find out how to decode this cryptic mess ? Since it is my first time working with Bluetooth Le I'm really stuck.

Im using Python3 on Linux (Ubuntu).

Best regards

nepho5
  • 31
  • 2
  • Did you see [https://github.com/polarofficial/accesslink-example-python](https://github.com/polarofficial/accesslink-example-python)? – wwii Nov 05 '20 at 19:23

2 Answers2

1

With BLE data in a characteristic, there are typically multiple fields within the one characteristic. For example, the official Heart Rate measurement characteristic can be 8 octets long and have fields for the flags, HRM Value, Energy Expended and RR-interval all in the one characteristic.

If it is using the Bluetooth standard for Heart Rate measurement then the characteristic UUID will be 00002A37-0000-1000-8000-00805F9B34FB. Official UUID's are often written as shortened to 16-bit values, so for this it would be 0x2A37.

You can read about the values in 16-bit UUID Numbers Document . Another useful document is the GATT Specification Supplement that specifies how values are represented in official Characteristics.

These documents are of little/no help if the manufacturer has used a custom characteristic. A custom characteristic is represented by a UUID value not in the range of 0000xxxx-0000-1000-8000-00805F9B34FB

To explore the data, using a generic Bluetooth Low Energy scanning and exploration tool such as nRF Connect is often helpful

The binary values are often easier to understand in Python if split into a list where each item represents an octet. For example:

>>> data = b'\r\xb1\x1aQ\xb4x\xa3C\x83\xdcv\xd3Q\x12\xbdJ\x7f\x82\xbf\x06\x91s\x07\xb7'
>>> list(data)
[13, 177, 26, 81, 180, 120, 163, 67, 131, 220, 118, 211, 81, 18, 189, 74, 127, 130, 191, 6, 145, 115, 7, 183]
>>> [f'{i:02x}' for i in data]
['0d', 'b1', '1a', '51', 'b4', '78', 'a3', '43', '83', 'dc', '76', 'd3', '51', '12', 'bd', '4a', '7f', '82', 'bf', '06', '91', '73', '07', 'b7']

The other thing to be aware of is that when converting between octets and integers the int type has the methods from_bytes and to_bytes. For example, if we know a value is of type sint16, it is signed and take 2 octets. The other thing to note is that BLE data is typically in little endian format.

>>> int.from_bytes([0x82, 0xbf], byteorder='little', signed=True)
-16510
>>> int(-16510).to_bytes(2, byteorder='little', signed=True)
b'\x82\xbf'
>>> int.from_bytes(b'\x82\xbf', byteorder='little', signed=True)
-16510
ukBaz
  • 6,985
  • 2
  • 8
  • 31
-2

try use cp1250 encode. i think your byte data is not compatible, you should tidy up first

b'\xe5\xfd\x8dC\x10f\x8ca\xe6'.decode('cp1250')
Zeta
  • 46
  • 7