Pydbus 更多通知同时处理
Posted
技术标签:
【中文标题】Pydbus 更多通知同时处理【英文标题】:Pydbus more notifications same time handling 【发布时间】:2021-01-03 19:04:10 【问题描述】:我想使用 pydbus 通过通知接收来自 BLE 设备的传感器数据。 我正在使用带有主循环的 GLib 链接了我的部分代码:
def sensor1_handler(iface, prop_changed, prop_removed):
if 'Value' in prop_changed:
"""Handle values"""
def sensor2_handler(iface, prop_changed, prop_removed):
if 'Value' in prop_changed:
"""Handle values"""
sensor1=bus.get("org.bluez", "/org/bluez/hciX/dev_XX_XX_XX_XX_XX_XX/serviceYYYY/charYYYY")
sensor2=bus.get("org.bluez", "/org/bluez/hciX/dev_XX_XX_XX_XX_XX_XX/serviceYYYY/charYYYY")
sensor1.onPropertiesChanged = sensor1_handler
sensor2.onPropertiesChanged = sensor2_handler
sensor2.StartNotify()
sensor1.StartNotify()
当我想接收通知时,两个信号几乎同时到达,并且只有一个(第一个到达的通知)通知回调函数运行。
我该如何解决这个问题?我在考虑消息队列。
编辑:
sensor1 功能:
def sensor1_handler(iface, prop_changed, prop_removed):
if 'Value' in prop_changed:
temperatureLSB = prop_changed['Value'][1]
temperatureMSB = prop_changed['Value'][0]
humidityLSB = prop_changed['Value'][3]
humidityMSB = prop_changed['Value'][2]
temperature = temperatureLSB | (temperatureMSB << 8)
humidity = humidityLSB | (humidityMSB << 8)
print(-45+175*(temperature/(pow(2,16)-1)))
print(100*(humidity/(pow(2,16)-1)))
sensor2 功能:
def sensor2_handler(iface, prop_changed, prop_removed):
if 'Value' in prop_changed:
iaqLSB = prop_changed['Value'][1]
iaqMSB = prop_changed['Value'][0]
iaq = iaqLSB | (iaqMSB << 8)
print(iaq)
sensor2 数据在 sensor1 之前发送,因此 sensor2 数据首先到达。这两个数据来自同一个设备,我还没有添加其他设备。
【问题讨论】:
您对正在发生的事情的解释听起来并不完整。属性更改回调不会因为同时发生另一个属性更改而消失。你确定你的第一个回调处理程序没有阻塞吗? 我已经编辑了帖子。 我知道这不是您来这里的问题,但是使用int.from_bytes
可以更有效地完成从字节到整数的操作。 temperature = int.from_bytes(prop_changed['Value'][0:2], byteorder='little', signed=True)
不是问题 :) 它使我的代码更有效率,所以谢谢你问题是我不明白为什么不调用第二个回调函数以及为什么它没有延迟
@AndrewS,如果有人没有回复,我会在周末看看。关于为什么它不起作用,没有什么明显的想法。只是需要一点时间来创建一个试验来为自己证明这一点
【参考方案1】:
感谢大家的帮助!
经过多次尝试,我注意到问题出在我的服务器端。 两个传感器数据是从一台设备发送的,相差约 10 毫秒,消息发送不是通知模式,而是指示。
我以前没有注意到,因为我只发送了 1 个传感器数据,相差 2 秒,但是当我尝试几乎同时发送 2 条消息时出现了问题。
设置为Notification后,服务器可以快速发送消息(不需要确认)。
我知道这个错误最终不是由pydbus引起的,而是我的错。我希望如果有人发现类似的问题,他们应该检查发送者(服务器)端。
【讨论】:
【参考方案2】:不确定这是否有用,但我无法重现该问题。我有两个 BBC micro:bits 并且都订阅了来自 Button A 的通知。我一直在尽可能地同时捣碎按钮,并且两者都毫无问题地出现。
下面是我用于实验的代码。它比理想的示例略长,但我通过修改现有示例创建了它。它不需要太多修改即可在您的设备上运行并查看您是否有同样的问题。
from time import sleep
from gi.repository import GLib
import pydbus
bus = pydbus.SystemBus()
mngr = bus.get('org.bluez', '/')
DEV1 = 'DC:DB:16:6B:8C:5F'
DEV2 = 'DE:82:35:E7:43:BE'
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
class MyRemoteDevice:
CHAR_UUID = 'e95dda90-251d-470a-a062-fa1922dfa9a8'
def __init__(self, mac_addr):
device_path = f"/org/bluez/hci0/dev_mac_addr.replace(':', '_')"
self.device = bus.get('org.bluez', device_path)
# Placeholder for characteristic details
self.characteristic = None
def _get_gatt_details(self):
char_path = get_characteristic_path(self.device._path, MyRemoteDevice.CHAR_UUID)
self.characteristic = bus.get('org.bluez', char_path)
def connect(self):
self.device.Connect()
while not self.device.ServicesResolved:
sleep(0.25)
self._get_gatt_details()
def disconnect(self):
self.characteristic.StopNotify()
self.device.Disconnect()
def read(self):
return self.characteristic.ReadValue()
def write(self, new_value):
self.characteristic.WriteValue(new_value, )
def _notify_handler(self, iface, prop_changed, prop_removed):
value = prop_changed.get('Value', [])
if value:
print(f'self.device.Address is int.from_bytes(value, byteorder="little")')
def start_notify(self):
self.characteristic.onPropertiesChanged = self._notify_handler
self.characteristic.StartNotify()
my_first_dev = MyRemoteDevice(DEV1)
my_second_dev = MyRemoteDevice(DEV2)
my_first_dev.connect()
my_second_dev.connect()
print(my_first_dev.read())
print(my_second_dev.read())
my_first_dev.start_notify()
my_second_dev.start_notify()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
my_first_dev.disconnect()
my_second_dev.disconnect()
这是其中一次运行的示例输出。这对我来说似乎很可靠。
(venv) pi@raspberrypi:~/stack_overflow $ python two_notifications.py
[0]
[0]
DC:DB:16:6B:8C:5F is 1
DE:82:35:E7:43:BE is 1
DC:DB:16:6B:8C:5F is 2
DE:82:35:E7:43:BE is 2
DC:DB:16:6B:8C:5F is 0
DE:82:35:E7:43:BE is 0
DC:DB:16:6B:8C:5F is 1
DE:82:35:E7:43:BE is 1
DC:DB:16:6B:8C:5F is 0
DE:82:35:E7:43:BE is 0
DC:DB:16:6B:8C:5F is 1
DE:82:35:E7:43:BE is 1
DC:DB:16:6B:8C:5F is 2
DE:82:35:E7:43:BE is 2
DE:82:35:E7:43:BE is 0
DC:DB:16:6B:8C:5F is 0
DE:82:35:E7:43:BE is 1
DC:DB:16:6B:8C:5F is 1
DE:82:35:E7:43:BE is 2
DC:DB:16:6B:8C:5F is 2
DC:DB:16:6B:8C:5F is 0
DE:82:35:E7:43:BE is 0
完成的有点匆忙,如果有什么不清楚的地方请告诉我。
【讨论】:
以上是关于Pydbus 更多通知同时处理的主要内容,如果未能解决你的问题,请参考以下文章