Python+dasbus检测配对Nuki智能锁iBeacon广播的问题求助
可行方案汇总
方案1:监听已配对设备的PropertiesChanged信号
已配对设备的广播属性更新(包括iBeacon数据变化)会触发org.bluez.Device1接口的PropertiesChanged信号,这是最直接的方式。你可以针对目标Nuki锁的设备路径,订阅这个信号并解析更新的广播数据。
代码示例
from dasbus.connection import SystemMessageBus from dasbus.loop import EventLoop # 初始化系统D-Bus连接 bus = SystemMessageBus() # 替换为你的Nuki锁的设备路径(可通过配对流程获取) NUKI_DEVICE_PATH = "/org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF" # 获取Device1接口代理 device_proxy = bus.get_proxy( "org.bluez", NUKI_DEVICE_PATH, "org.bluez.Device1" ) # 保存上次检测到的锁状态 last_lock_state = None def handle_device_props_changed(interface, changed_props, invalidated_props): global last_lock_state # 只处理Device1接口的属性变更 if interface != "org.bluez.Device1": return # 检查制造商数据(iBeacon由苹果制造商ID 0x004C标识) if "ManufacturerData" in changed_props: manufacturer_data = changed_props["ManufacturerData"] if 0x004C in manufacturer_data: # 解析Nuki iBeacon中的状态字节(位置需参考Nuki官方文档) nuki_beacon_data = manufacturer_data[0x004C] current_state = nuki_beacon_data[10] # 示例位置,替换为实际偏移 if current_state != last_lock_state: print(f"锁状态变更:{current_state}") # 这里调用获取锁详细状态的逻辑 last_lock_state = current_state # 连接信号回调 device_proxy.PropertiesChanged.connect(handle_device_props_changed) # 启动事件循环 loop = EventLoop() loop.run()
方案2:定期主动扫描并解析iBeacon数据
如果信号监听的方式不稳定,你可以主动发起周期性扫描,过滤目标设备的广播数据并对比状态。这种方式兼容性更强,不需要依赖设备的信号触发。
代码示例
from dasbus.connection import SystemMessageBus from dasbus.loop import EventLoop import time bus = SystemMessageBus() ADAPTER_PATH = "/org/bluez/hci0" NUKI_MAC = "AA:BB:CC:DD:EE:FF" # 你的Nuki锁MAC地址 last_lock_state = None # 获取蓝牙适配器代理 adapter_proxy = bus.get_proxy("org.bluez", ADAPTER_PATH, "org.bluez.Adapter1") # 获取ObjectManager代理用于枚举设备 object_manager = bus.get_proxy("org.bluez", "/", "org.freedesktop.DBus.ObjectManager") def scan_nuki_beacon(): global last_lock_state try: # 启动扫描 adapter_proxy.StartDiscovery() # 扫描持续3秒(可根据需求调整) time.sleep(3) # 获取当前所有已发现的设备 managed_objects = object_manager.GetManagedObjects() for path, interfaces in managed_objects.items(): if "org.bluez.Device1" not in interfaces: continue device_props = interfaces["org.bluez.Device1"] # 过滤目标Nuki设备 if device_props["Address"] != NUKI_MAC: continue # 解析iBeacon数据 if "ManufacturerData" in device_props: manufacturer_data = device_props["ManufacturerData"] if 0x004C in manufacturer_data: nuki_beacon_data = manufacturer_data[0x004C] current_state = nuki_beacon_data[10] # 替换为实际偏移 if current_state != last_lock_state: print(f"检测到状态变更,请求锁详细状态...") # 调用锁状态查询逻辑 last_lock_state = current_state finally: # 务必停止扫描,避免持续耗电 adapter_proxy.StopDiscovery() # 初始化事件循环,每隔30秒扫描一次 loop = EventLoop() loop.add_timeout(30, scan_nuki_beacon) # 先执行一次初始扫描 scan_nuki_beacon() loop.run()
方案3:利用BlueZ的BeaconManager1接口(需BlueZ版本支持)
如果你的系统BlueZ版本足够新(建议5.50+),可以使用专门的org.bluez.BeaconManager1接口来监听iBeacon的更新,无需手动解析广播数据。
代码示例
from dasbus.connection import SystemMessageBus from dasbus.loop import EventLoop bus = SystemMessageBus() # 替换为你的蓝牙适配器路径 ADAPTER_PATH = "/org/bluez/hci0" # Nuki锁的iBeacon UUID(需参考官方文档) NUKI_BEACON_UUID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # 获取BeaconManager代理 beacon_manager = bus.get_proxy("org.bluez", ADAPTER_PATH, "org.bluez.BeaconManager1") def handle_beacon_updated(beacon_path): # 获取Beacon接口代理 beacon_proxy = bus.get_proxy("org.bluez", beacon_path, "org.bluez.Beacon1") beacon_props = beacon_proxy.GetAll("org.bluez.Beacon1") # 解析状态字节 manufacturer_data = beacon_props["ManufacturerData"] current_state = manufacturer_data[0x004C][10] # 替换为实际偏移 print(f"iBeacon状态更新:{current_state}") # 启动对目标UUID的iBeacon监听 beacon_manager.StartMonitoring(NUKI_BEACON_UUID) # 监听Beacon接口的属性变更信号 object_manager = bus.get_proxy("org.bluez", "/", "org.freedesktop.DBus.ObjectManager") def handle_interfaces_added(path, interfaces): if "org.bluez.Beacon1" in interfaces: beacon_proxy = bus.get_proxy("org.bluez", path, "org.bluez.Beacon1") beacon_proxy.PropertiesChanged.connect(lambda i,c,iv: handle_beacon_updated(path)) object_manager.InterfacesAdded.connect(handle_interfaces_added) loop = EventLoop() loop.run()
注意事项
- 确保BlueZ版本符合要求:部分接口(如
BeaconManager1)需要较新的BlueZ版本,可通过bluetoothctl -v查看。 - 权限配置:运行脚本需要蓝牙操作权限,可通过
sudo setcap cap_net_raw+ep /usr/bin/python3(根据你的Python路径调整)赋予权限,或用sudo运行。 - Nuki iBeacon格式:务必参考Nuki官方文档确认状态字节的准确偏移位置,不同型号可能有差异。
内容的提问来源于stack exchange,提问作者Josef
相关产品推荐
相关产品推荐

