2

Good afternoon,

First of all I apologize for asking questions in this thread but this is my first time writing on StackExchange. I am doing a university work where it is necessary through a Raspberry Pi to access information that is reported by a blueetooth sensor that has an IMU unit (with accelerometer, gyroscope and magnetometer).

Before starting to build code in python on the Raspberry Pi, I installed an Android application called nRF Connect that allows you to access information from blueetooth devices.

After successfully connecting to the Bluetooth device, I was able to access a number of bluetooth features, as can be seen from the figure below:

enter image description here

To access the values indicated by the gyroscope, accelerometer and magnetometer, it is necessary to send the byte array 0x01 via UUID 0xFF35:

enter image description here

After sending this byte 0x01 to UUID 0xFF35, the characteristic with UUID 0xFF38 immediately starts sending the required information. This value is constantly changing as it refers to the three sensors that are installed in the IMU unit. As can be seen by the red box in the figure below:

enter image description here

In the meantime I tried to create some python code on the Raspberry Pi in order to get the values reported by characteristic with UUID 0xFF38.

I checked the thread at the following link: BlueZ BTGATT-client.py WriteValue and tried to adapt the code to my situation.

The code I have at the moment is as follows:

import pydbus
import time
from gi.repository import GLib

dev_id = '20:C3:8F:D0:CF:10' bluez_service = 'org.bluez' adapter_path = '/org/bluez/hci0' device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}" uuid = '0000ff35-0000-1000-8000-00805f9b34fb' uuidnew= '0000ff38-0000-1000-8000-00805f9b34fb'

Setup DBus informaton for adapter and remote device

bus = pydbus.SystemBus() mngr = bus.get('org.bluez', '/') adapter = bus.get('org.bluez', adapter_path) device = bus.get('org.bluez', device_path)

Connect to device (needs to have already been paired via bluetoothctl)

device.Connect() #print(dir(adapter)) #print(dir(device))

def get_characteristic_path(dev_path, uuid): mng_objs = mngr.GetManagedObjects() for path in mng_objs: chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID') if path.startswith(dev_path) and chr_uuid == uuid: return path

#Read information from characteristic 0xFF35 char_path = get_characteristic_path(device._path, uuid) btn = bus.get(bluez_service, char_path) print(btn.ReadValue({}))

#Set the value 0x01, to activate the characteristic 0xFF38 in order to report the sensor values.

new_value = int(1).to_bytes(2, byteorder='little') btn.WriteValue(new_value, {})

#Read the values of characteristic 0xFF38 newCaract = get_characteristic_path(device._path, uuidnew) btnNew = bus.get(bluez_service, newCaract) print(btnNew.ReadValue({}))

If I run this code in the Thonny IDE (which comes installed on the Raspberry pi), I am confronted with the following message: enter image description here

Where line 43 is precisely the statement:

print(btnNew.ReadValue({}))

Essentially the following instructions, wrote the byte 0x01 to characteristic 0xFF35:

new_value = int(1).to_bytes(2, byteorder='little')
btn.WriteValue(new_value, {}), 

However when analyzing the error message there seems to be no synchronism that allows the Raspberry Pi to read the values sent by characteristic 0xFF38.

On the other hand, if I run this code a second time the following output appears:

enter image description here

As you can see, the characteristic 0xFF35, reports the value 1, meaning that in fact byte 0x01 was written to this characteristic.

-Given this error message, I ask what might be the most appropriate procedure for reading the values reported by characteristic 0xFF38?

Thank you very much for your attention

[UPDATE]

Good afternoon,

Regarding the nRF Connect application, I confirm that I can do write at 0xFF35 and read from 0xFF38. In this case, I am writing 0x01 at characteristic 0xFF35 and automatically at 0xFF38 I see that the values reported by the IMU unit are being correctly received, as in the figure below:

enter image description here

On the other hand, I returned to the Rapberry Pi and did the following:

-In the Python code I added the following line of code:

btnNew.StartNotify()

Then I opened two terminals, in one of them I inserted the "bluetoothctl" command line, in another I inserted the "sudo btmon" command line.Then I pressed the Run button and got the following result: enter image description here

Looking at the last image, we see that the "Data" field under the "Handle": 0x0024", is constantly changing.

When I give the sensor a few shakes, I notice that some of the "Data" fields change.

Considering this situation, at the Python code level, did I proceed correctly to access the value indicated by 0xFF38? Is any adjustment necessary?

Thank you for your attention

[UPDATE-2]

import pydbus
import time
from gi.repository import GLib

dev_id = '20:C3:8F:D0:CF:10' bluez_service = 'org.bluez' adapter_path = '/org/bluez/hci0' device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}" uuid = '0000ff35-0000-1000-8000-00805f9b34fb' uuidnew= '0000ff38-0000-1000-8000-00805f9b34fb'

Setup DBus informaton for adapter and remote device

bus = pydbus.SystemBus() mngr = bus.get('org.bluez', '/') adapter = bus.get('org.bluez', adapter_path) device = bus.get('org.bluez', device_path)

Connect to device (needs to have already been paired via bluetoothctl)

device.Connect() #print(dir(adapter)) #print(dir(device))

def get_characteristic_path(dev_path, uuid): mng_objs = mngr.GetManagedObjects() for path in mng_objs: chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID') if path.startswith(dev_path) and chr_uuid == uuid: return path

#Read information from characteristic 0xFF35 char_path = get_characteristic_path(device._path, uuid) btn = bus.get(bluez_service, char_path) print(btn.ReadValue({}))

#Set the value 0x01, to activate the characteristic 0xFF38 in order to report the sensor values. new_value = int(1).to_bytes(2, byteorder='little') btn.WriteValue(new_value, {})

#Read the values of characteristic 0xFF38 newCaract = get_characteristic_path(device._path, uuidnew) btnNew = bus.get(bluez_service, newCaract)

Enable eventloop for notifications

def temp_handler(iface, prop_changed, prop_removed): """Notify event handler for temperature""" if 'Value' in prop_changed: print(f"Temp value: {as_int(prop_changed['Value'])} \u00B0C")

mainloop = GLib.MainLoop() btnNew.onPropertiesChanged = temp_handler btnNew.StartNotify() try: mainloop.run() except KeyboardInterrupt: mainloop.quit() btnNew.StopNotify() device.Disconnect()

jf_PT
  • 21
  • 3

1 Answers1

2

gatttool is one of the tools that has been deprecated by the BlueZ project. If you are following a tutorial that uses those tools then you should be careful that the tutorial isn't incompatible with your system.

You might be seeing the error messages you are getting because gatttool bypasses the Bluetooth daemon running on your system causing there to be some kind of conflict.

You should be able to test your device is working using bluetoothctl. Using blutoothctl will help identify if the issue is with your system or with the code as bluetoothctl uses the same API to talk to the Bluetooth daemon as your Python code.

As you want to read and write to two different UUIDs it is often easier to have two instances of bluetoothctl running in different terminals to save you switching between the two characteristics.

In the first terminal start bluetothctl, connect, and turn on notifications for 0XFF38 characteristic:

connect 20:C3:8F:D0:CF:10
gatt.select-attribute 0000ff38-0000-1000-8000-00805f9b34fb
gatt.notify on

In the second terminal the bluetoothctl instance should already show that it is connected to your device. Select the other characteristic and write 0x01 to it as you did in nRF Connect:

gatt.select-attribute 0000ff35-0000-1000-8000-00805f9b34fb
gatt.write 0x01

In the first bluetoothctl that is monitoring 0xff38 you should see the IMU data start to appear.

Doing this test with bluetoothctl will help identify if it is an issue with your system or your Python code.


As a side note I would comment that your BLE device is using UUIDs in the value range reserved for officially adopted Characteristics (0000????-0000-1000-8000-00805F9B34FB). More information at: https://www.novelbits.io/uuid-for-custom-services-and-characteristics/ and in the 16-bit UUIDs document. Not a problem for your experiments at university but an issue if it is taken further.

ukBaz
  • 1,548
  • 1
  • 7
  • 23