使用 pydbus 捕获所有 BLE 广告电报

问题描述 投票:0回答:1

我有业务合作伙伴提供的加速度传感器,触发时每秒发送大约 20 个 BLE 广告。 我安装了 Bluez 5.66 并且正在运行一个 pydbus 应用程序,该应用程序源自这篇文章 主动 BLE 扫描 (BlueZ) - DBus 问题

顺便说一句,感谢@uKbaz 以及他关于该主题的所有教程。

import argparse
from gi.repository import GLib
from pydbus import SystemBus
import datetime

DEVICE_INTERFACE = 'org.bluez.Device1'

remove_list = set()

def stop_scan():
    """Stop device discovery and quit event loop"""
    adapter.StopDiscovery()
    mainloop.quit()

def on_iface_added(owner, path, iface, signal, interfaces_and_properties):
    """
    Event handler for D-Bus interface added.
    Test to see if it is a new Bluetooth device
    """
    iface_path, iface_props = interfaces_and_properties
    if DEVICE_INTERFACE in iface_props:
        on_device_found(iface_path, iface_props[DEVICE_INTERFACE])

def on_properties_changed(owner, path, iface, signal, interfaces_and_properties):
    """
    Event handler for D-Bus interface properties changed.
    Manufacturing data or Service Data change
    """
    iface_path, iface_props, leftover = interfaces_and_properties
    if DEVICE_INTERFACE in interfaces_and_properties:
        on_device_found(path, iface_props)

def on_device_found(device_path, device_props):
    """
    Handle new Bluetooth device being discover.
    If it is a beacon of type iBeacon, Eddystone, AltBeacon
    then process it
    """
    address = device_props.get('Address')
    
    address_type = device_props.get('AddressType')
    name = device_props.get('Name')
    alias = device_props.get('Alias')
    paired = device_props.get('Paired')
    trusted = device_props.get('Trusted')
    rssi = device_props.get('RSSI')
    service_data = device_props.get('ServiceData')
    manufacturer_data = device_props.get('ManufacturerData')
    
    if address == 'D7:6F:3F:5E:F4:BF' or "D7_6F_3F_5E_F4_BF" in device_path:
    
        print(str(datetime.datetime.now()) + " MAC: " + str(address) + 
              " RSSI:" + str(rssi) + " MData:" + str(manufacturer_data))
        adapter.RemoveDevice(device_path)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--duration', type=int, default=0,
                        help='Duration of scan [0 for continuous]')
    args = parser.parse_args()
    bus = SystemBus()
    adapter = bus.get('org.bluez', '/org/bluez/hci0')
    #adapter = bus.get('org.bluez', '/org/bluez/hci1')
    bus.subscribe(iface='org.freedesktop.DBus.ObjectManager',
                  signal='InterfacesAdded',
                  signal_fired=on_iface_added)
    
    # bus.subscribe(iface='org.freedesktop.DBus.Properties',
    #               signal='PropertiesChanged',
    #               signal_fired=on_properties_changed)

    mainloop = GLib.MainLoop()

    if args.duration > 0:
        GLib.timeout_add_seconds(args.duration, stop_scan)
    adapter.SetDiscoveryFilter({'DuplicateData': GLib.Variant.new_boolean(True), 
                                "Transport":GLib.Variant.new_string("le")})
    
    adapter.StartDiscovery()

    try:
        print('\n\tUse CTRL-C to stop discovery\n')
        mainloop.run()
    except KeyboardInterrupt:
        stop_scan()

应用程序正在扫描新设备。 如果发现新设备,它会抓取相关数据并将该设备从适配器的设备列表中删除,以便可以再次发现它。 一般来说,该应用程序可以运行,但我每 9-12 秒只看到一个广告,这太少了。

这是最新的输出,分为时间戳、RSSI、MAC 和制造数据。 第一个字节是校验和,后面跟着一个 ID 字节(始终为 108 (0x6C))和一个类型字节(在我的情况下始终为 5 (0x05))。 接下来的四个字节非常有趣,因为它们代表自启动以来发送的广告计数。正如人们所看到的,我在两次发现之间丢失了大约 180..220 封电报。

2023-12-14 12:29:43.101505 MAC: D7:6F:3F:5E:F4:BF RSSI:-42 MData:{22272: [4, 108, 5, 0, 0, 135, 40, 255, 6, 91, 219, 250, 26, 113, 63, 208, 95, 198, 254, 145, 167, 63, 252, 8, 61, 44, 64]}
2023-12-14 12:29:52.786266 MAC: D7:6F:3F:5E:F4:BF RSSI:-50 MData:{62720: [172, 108, 5, 0, 0, 135, 228, 6, 244, 242, 147, 225, 202, 207, 177, 231, 113, 8, 69, 128, 139, 156, 1, 191, 159, 180, 64]}
2023-12-14 12:30:03.416085 MAC: D7:6F:3F:5E:F4:BF RSSI:-54 MData:{46336: [155, 108, 5, 0, 0, 136, 178, 23, 254, 79, 104, 76, 238, 62, 128, 39, 134, 13, 60, 204, 68, 50, 229, 175, 192, 148, 64]}
2023-12-14 12:30:15.044914 MAC: D7:6F:3F:5E:F4:BF RSSI:-46 MData:{19712: [183, 108, 5, 0, 0, 137, 148, 255, 78, 78, 84, 9, 52, 187, 96, 8, 222, 234, 64, 19, 115, 152, 0, 13, 222, 72, 64]}
2023-12-14 12:30:25.915247 MAC: D7:6F:3F:5E:F4:BF RSSI:-42 MData:{57856: [63, 108, 5, 0, 0, 138, 104, 43, 102, 106, 174, 150, 40, 251, 252, 20, 128, 245, 178, 191, 247, 116, 194, 65, 222, 208, 64]}
2023-12-14 12:30:47.678187 MAC: D7:6F:3F:5E:F4:BF RSSI:-42 MData:{21504: [48, 108, 5, 0, 0, 140, 15, 0, 192, 220, 0, 5, 2, 47, 240, 20, 7, 190, 191, 160, 55, 8, 1, 127, 107, 188, 64]}
2023-12-14 12:30:58.415692 MAC: D7:6F:3F:5E:F4:BF RSSI:-52 MData:{43776: [37, 108, 5, 0, 0, 140, 223, 62, 128, 238, 232, 244, 19, 191, 227, 192, 28, 214, 77, 16, 223, 152, 46, 2, 78, 168, 64]}
2023-12-14 12:31:20.841068 MAC: D7:6F:3F:5E:F4:BF RSSI:-50 MData:{36352: [96, 108, 5, 0, 0, 142, 148, 210, 191, 112, 95, 76, 253, 1, 205, 91, 240, 1, 53, 160, 8, 13, 214, 63, 192, 76, 64]}

首先,我认为扫描窗口和/或间隔可能需要调整,但它们都设置为 11,250 毫秒,这应该会导致连续扫描。 我想测试的一件事是将扫描类型更改为被动,这也许可以加速发现过程,但我在 bluez 文档中找不到任何函数来设置它。 https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc

在这里您可以看到与应用程序并行运行的 btmon 的启动日志:

= Note: Linux version 4.19.94 (aarch64)                                          
= Note: Bluetooth subsystem version 2.22                                         
= New Index: E8:48:B8:C8:20:00 (Primary,USB,hci1)                                
= Open Index: E8:48:B8:C8:20:00                                                  
= Index Info: E8:48:B8:C8:20:00 (Realtek Semiconductor Corporation)              
= New Index: 08:BF:B8:53:93:6F (Primary,USB,hci0)                                
= Open Index: 08:BF:B8:53:93:6F                                                  
= Index Info: 08:BF:B8:53:93:6F (Realtek Semiconductor Corporation)              
@ MGMT Open: bluetoothd (privileged) version 1.14                                
@ MGMT Command: Start Discovery (0x0023) plen 1                                  
        Address type: 0x07
          BR/EDR
          LE Public
          LE Random
< HCI Command: LE Set Random Address (0x08|0x0005) plen 6                        
        Address: 34:7A:C0:B9:B5:80 (Non-Resolvable)
> HCI Event: Command Complete (0x0e) plen 4                                      
      LE Set Random Address (0x08|0x0005) ncmd 2
        Status: Success (0x00)
< HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 8              
        Own address type: Random (0x01)
        Filter policy: Accept all advertisement (0x00)
        PHYs: 0x01
        Entry 0: LE 1M
          Type: Active (0x01)
          Interval: 11.250 msec (0x0012)
          Window: 11.250 msec (0x0012)
> HCI Event: Command Complete (0x0e) plen 4                                      
      LE Set Extended Scan Parameters (0x08|0x0041) ncmd 2
        Status: Success (0x00)
< HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6                  
        Extended scan: Enabled (0x01)
        Filter duplicates: Enabled (0x01)
        Duration: 0 msec (0x0000)
        Period: 0.00 sec (0x0000)
> HCI Event: Command Complete (0x0e) plen 4                                      
      LE Set Extended Scan Enable (0x08|0x0042) ncmd 2
        Status: Success (0x00)
@ MGMT Event: Command Complete (0x0001) plen 4                                   
      Start Discovery (0x0023) plen 1
        Status: Success (0x00)
        Address type: 0x07
          BR/EDR
          LE Public
          LE Random
@ MGMT Event: Discovering (0x0013) plen 2                                        
        Address type: 0x07
          BR/EDR
          LE Public
          LE Random
        Discovery: Enabled (0x01)

我还尝试在找到设备后保留设备,并仅检查 PropertyChanges,只要发现制造商或服务数据(如果我正确解释文档),就会触发 PropertyChanges。但这也没有帮助。 https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/org.bluez.Adapter.rst

:bool DuplicateData (Default true):

        Disables duplicate detection of advertisement data.

        When enabled PropertiesChanged signals will be generated for
        either ManufacturerData and ServiceData everytime they are
        discovered.

这可能是硬件问题吗? 我已连接两个 BT 加密狗,但仅使用第一个。 一款加密狗来自 TP Link,一款来自华硕,但两者都使用 Realtek 芯片组 RTL8761B。

你们中有人对如何捕获更多电报有进一步的了解吗? 我知道不可能捕获所有这些,但也许 80-90% 就完美了。

非常感谢你!

python-3.x bluetooth bluetooth-lowenergy dbus bluez
1个回答
0
投票

好吧,首先,我不认为你可以使用 Bluez 获得所有广告。但你可以靠近……

这样做:

  • 只订阅PropertiesChanged信号,忽略InterfaceAdded。也不要执行RemoveDevice...
  • 向 SetDiscoveryFilter 添加 RSSI 参数,值为 -100
  • DuplicateData 必须具有值 True...但您已经拥有了。

如果执行上述操作,每秒至少应该收到几个事件。

© www.soinside.com 2019 - 2024. All rights reserved.