0

我正在使用 python3 中的库编写一个 Linux 应用程序,以在适配器和我的 Linux 设备gattlib之间发送和接收用户输入的数据。BlueSnap DB9 BLE我已经能够String从我的设备成功地向适配器发送数据,并在适配器的终端上看到了输出,但是我在从适配器接收数据时遇到了问题。

我正在按照这个示例使用gattlib来读取和写入数据。write_cmd我可以使用and函数写入数据,write_by_handle但我无法gattlib使用此处提到的任何读取函数读取数据或启用通知。使用 gattlib 时似乎没有启用通知,因为我重写的 on_notification 函数没有打印出我在那里添加的打印语句。

我已经确定写入和读取数据的句柄分别是0x00430x0046。以下是 serialio 提供给我的用于写入和读取的 UUID:UUIDs

使用bluetoothctl时,选择特性后,我可以将数据写入适配器。只有在启用通知后bluetoothctl,我才能读取数据。一旦我禁用通知,尝试手动读取会打印出全 0,而不是我想要读取的数据。gattlib在 python3中选择特征和启用通知的正确方法是什么?

更新:我能够启用通知。我hcidump在这两个bluetoothctl和我的 python 代码上运行,并确定我用于启用通知的句柄不正确。启用通知的正确句柄是0x0047. 一旦我意识到这个错误,我enable_notifications使用正确的句柄运行并将两个参数设置为True,并且能够在我的设备终端上启用通知并查看传入数据,因为我在适配器的终端上键入它。

4

1 回答 1

1

不使用gattlib,但这里是使用 Python3 D-Bus 绑定和 GLib 事件循环来读取、写入和获取 GATT 特性的通知的示例。

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()
于 2021-08-04T19:55:06.047 回答