You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

注意事项

  1. 确保BlueZ版本符合要求:部分接口(如BeaconManager1)需要较新的BlueZ版本,可通过bluetoothctl -v查看。
  2. 权限配置:运行脚本需要蓝牙操作权限,可通过sudo setcap cap_net_raw+ep /usr/bin/python3(根据你的Python路径调整)赋予权限,或用sudo运行。
  3. Nuki iBeacon格式:务必参考Nuki官方文档确认状态字节的准确偏移位置,不同型号可能有差异。

内容的提问来源于stack exchange,提问作者Josef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:05:11