i have some problems by understanding the flag field in Bluetooth characteristics.
For example the heart rate measurement characteristic:
And its flags:
According to my understanding, the first part of the value must contain the flags. For example 0x06 for:
The second part of the value is then byte(Heartrate).
In Python i fill the value like this:
value = []
value.append(dbus.Byte(0x06))
value.append(dbus.Byte(randint(90, 130)))
The whole thing also works perfectly. When I connect to the server with the app nRF connect I get all the info perfectly displayed with all the info.
Now about my problem:
I tried to implement the Weight Measurement Characteristic.
I want Weight in kg, BMI and height. So for my understanding i have to fill flag field with 0x08 for 00001000.
In Python it will look like this:
value = []
value.append(dbus.Byte(0x08))
value.append(dbus.Byte(randint(1, 13))) #weight
value.append(dbus.Byte(randint(1, 25))) #BMI
value.append(dbus.Byte(randint(1, 25))) #height
Now i get in nRF Connect App the message Invalid Data Syntax.
My Questions are:
Thank you very very much for your help!
I'm using bluez5.63/test/example-gatt-server.py for my Server!
The usual way to build the value for a characteristic is to use the Python struct
library to pack that values into bytes.
The values sent in the characteristics are always bytes which can only represent integers. So to turn the height
value to an integer it is saying that for every increment of 1
on the field value, the hight value goes up by 0.001
. This means the decimal point needs to move 3 places to the right on the height value sent. So to send a height value of 0.001
you will actually send a value of 1
. This means your messurment needs to be multiplied by value * 10**3
or if you prefer value / 0.001
.
For weight it is similar but in addition to moving the decimal point you also have to change the value. This can be value / 0.005
or value * (1 / 5) * 10 ** 3
An example of how the python code might look:
import struct
weight_char = struct.Struct('<BHHH')
def pack_flags(units, timestamp, user_id, bmi_height):
flags = 0
for idx, _flag in enumerate((units, timestamp, user_id, bmi_height)):
flags |= _flag << idx
return flags
flags = pack_flags(False, False, False, True)
weight = 42.4 # example weight in KG
height = 1.49 # Height in meters
bmi = 20.1
value = weight_char.pack(flags,
int(weight * 0.2 * 10**3),
int(bmi * 10**1),
int(height * 10**3))
print(f"Value to send: {value.hex()}")
Which gives the output of:
Value to send: 082021c900d205