Python2.7+Bluez 5.61下dbus的InterfacesRemoved信号未触发问题咨询
Bluez 蓝牙设备离线检测与信号触发问题解答
1. InterfacesAdded/InterfacesRemoved 信号适用场景说明
- 这两个属于DBus ObjectManager的标准信号,仅当DBus对象的接口被新增/移除时才会触发,对应Bluez的逻辑为:
InterfacesAdded:仅当Bluez首次扫描到新设备,在DBus上创建对应的org.bluez.Device1接口对象时触发,同一个设备被重复扫描到不会重复触发InterfacesRemoved:仅当Bluez主动删除对应设备的DBus对象时才会触发,触发场景只有两类:一是主动调用适配器的RemoveDevice方法移除设备缓存;二是蓝牙适配器重启、Bluez服务重启清空所有设备缓存。
- 设备离开扫描范围变为不可探测时,Bluez默认不会删除对应设备的DBus缓存对象,所以不会触发
InterfacesRemoved信号,这是收不到该信号的核心原因。观察到PropertiesChanged信号正常是符合预期的,设备的RSSI、可连接状态、广播数据等属性变更时都会通过该信号通知。
2. 每收到蓝牙广播报文触发信号的实现方法
可以实现,需要修改Bluez的扫描配置关闭重复广播过滤:
- 调用对应蓝牙适配器
org.bluez.Adapter1接口的SetDiscoveryFilter方法,添加配置项DuplicateData = True,默认该参数为False,Bluez会自动过滤内容重复的广播报文,不会向上层通知,设为True后每收到一条广播报文都会向上层发送通知。 - 配置完成后,每次收到目标设备的广播都会触发对应设备的
PropertiesChanged信号(更新RSSI或广播数据属性),可以为每个设备单独维护一个超时定时器,每次收到该设备的信号就重置定时器,定时器超时即可判定设备处于不可探测状态。
现有信号注册代码无需修改,仅需要补充扫描过滤配置即可,参考配置代码示例:
# adapter_path为你的蓝牙适配器DBus路径,例如/org/bluez/hci0 adapter_obj = self.bus.get_object("org.bluez", adapter_path) adapter_iface = dbus.Interface(adapter_obj, "org.bluez.Adapter1") # 配置扫描过滤,按需添加其他参数,例如Transport指定为le表示仅扫描BLE设备 adapter_iface.SetDiscoveryFilter({ "DuplicateData": dbus.Boolean(True, variant_level=1), "Transport": dbus.String("le", variant_level=1) }) # 开启扫描 adapter_iface.StartDiscovery()
内容的提问来源于stack exchange,提问作者Antidot
相关产品推荐
相关产品推荐

