Reputation: 1
I am writing a Linux application using the gattlib
library in python3 to send and receive user inputted data between a BlueSnap DB9 BLE
adapter and my Linux device. I have been able to successfully send a String
of data to the adapter from my device and seen the output on the adapter's terminal, but I am having issues receiving data from the adapter.
I am following this example for reading and writing data using the gattlib
library. I can write data using the write_cmd
and write_by_handle
functions but I am unable to read data or enable notifications with gattlib
using any of the read functions mentioned there. Notifications don't appear to be enabled when using gattlib because the on_notification function I overwrote doesn't print out the print statement I added there.
I have determined that the handles for writing and reading data are 0x0043
and 0x0046
, respectively. Here are the UUIDs for writing and reading that serialio provided to me: UUIDs.
When using bluetoothctl
, after selecting the characteristic, I am able to write data to the adapter. Only after enabling notifications on bluetoothctl
, only then am I able to read data as well. Once I disable notifications, attempting to read manually prints out all 0s instead of the data I want to read. What is the proper way to select a characteristic and enable notifications using gattlib
in python3?
UPDATE: I was able to get notifications enabled. I ran hcidump
on both bluetoothctl
and my python code and determined the handle I had used for enabling notifications was incorrect. The correct handle for enabling notifications is 0x0047
. Once I realized this mistake, I ran enable_notifications
using the correct handle and set both parameters to True
and was able to enable notifications and see incoming data on my device's terminal as I typed it on my adapter's terminal.
Upvotes: 0
Views: 1200
Reputation: 7994
Not using gattlib
but here is an example of using the Python3 D-Bus bindings and the GLib event loop to read, write and get notifications from GATT characteristics.
from time import sleep
import pydbus
from gi.repository import GLib
# Setup of device specific values
dev_id = 'DE:82:35:E7:43:BE'
adapter_path = '/org/bluez/hci0'
device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}"
temp_reading_uuid = 'e95d9250-251d-470a-a062-fa1922dfa9a8'
temp_period_uuid = 'e95d1b25-251d-470a-a062-fa1922dfa9a8'
# 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()
# wait for GATT services to be discovered
while not device.ServicesResolved:
sleep(0.5)
# Some helper functions
def get_characteristic_path(device_path, uuid):
"""Find DBus path for UUID on a device"""
mng_objs = mngr.GetManagedObjects()
for path in mng_objs:
chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
if path.startswith(device_path) and chr_uuid == uuid:
return path
def as_int(value):
"""Create integer from bytes"""
return int.from_bytes(value, byteorder='little')
# Get a couple of characteristics on the device we are connected to
temp_reading_path = get_characteristic_path(device._path, temp_reading_uuid)
temp_period_path = get_characteristic_path(device._path, temp_period_uuid)
temp = bus.get('org.bluez', temp_reading_path)
period = bus.get('org.bluez', temp_period_path)
# Read value of characteristics
print(temp.ReadValue({}))
# [0]
print(period.ReadValue({}))
# [232, 3]
print(as_int(period.ReadValue({})))
# 1000
# Write a new value to one of the characteristics
new_value = int(1500).to_bytes(2, byteorder='little')
period.WriteValue(new_value, {})
# 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()
temp.onPropertiesChanged = temp_handler
temp.StartNotify()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
temp.StopNotify()
device.Disconnect()
Upvotes: 1