如何在Ubuntu 20.04上使用BlueZ 5和5.4内核发送打包的广告包

问题描述

在以前的Ubuntu内核和发行版中,可以使用hci套接字接口发送31个字节的任意集合作为广告信标,但在ubuntu 20.04中,不推荐使用hci蓝牙工具,因为他们正在使用的套接字API。

目标是让N个设备以5 Hz的速率相互广播31个字节的传感器数据,并让N个设备从其他设备读取数据包。

不推荐使用hci套接字API,替换为DBus BlueZ API和Management BlueZ API。 DBus API是受限制的,并且似乎最多只允许25个字节。管理API似乎更强大,并且似乎可以在Ubuntu 18.04 / 4.15内核上运行(尽管即使在扫描和切换之间每100毫秒进行一次广告发布时,扫描似乎也只能偶尔接收广告,而使用hci api却是坚如磐石) ,但是在Ubuntu 20.04 / 5.4内核上,会出现各种问题。

  • 似乎仍可以使用hci套接字API,但是即使运行类似hcitool lescan的结果也会导致btmonCommand disallowed。我相信这可能是由于启用了LE Extended Advertising,但我还没有弄清楚如何禁用它。

  • 使用DBus API(或bluetoothctl)仍然受到限制,并且不允许充分使用31个字节(甚至30个字节+长度)

  • 在设置广告数据后不久,使用Management API会导致Advertising Timeout,我认为可能是由于启用了LE Extended Advertising。即使我在数据包中明确设置了超时,该问题仍然存在。

例如,运行

btmgmt add-adv -c -d 1E000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D 1

以固定的MAC发送广告数据包,其中广告数据的长度为:31有效载荷:0-30导致btmon输出

  < HCI Command:... (0x08|0x0036) plen 25  #631 [hci0] 5676.358401
        Handle: 0x01
        Properties: 0x0013
          Connectable
          Scannable
          Use legacy advertising PDUs: ADV_IND
        Min advertising interval: 1280.000 msec (0x0800)
        Max advertising interval: 1280.000 msec (0x0800)
        Channel map: 37,38,39 (0x07)
        Own address type: Public (0x00)
        Peer address type: Public (0x00)
        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
        Filter policy: Allow Scan Request from Any,Allow Connect Request from Any (0x00)
        TX power: 127 dbm (0x7f)
        Primary PHY: LE 1M (0x01)
        Secondary max skip: 0x00
        Secondary PHY: LE 1M (0x01)
        SID: 0x00
        Scan request notifications: disabled (0x00)
> HCI Event: Command Co.. (0x0e) plen 5  #632 [hci0] 5676.359321
      LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
        Status: Success (0x00)
        TX power (selected): 7 dbm (0x07)
< HCI Command: L.. (0x08|0x0039) plen 6  #633 [hci0] 5676.359410
        Extended advertising: Enabled (0x01)
        Number of sets: 1 (0x01)
        Entry 0
          Handle: 0x01
          Duration: 2000 ms (0xc8)
          Max ext adv events: 0
> HCI Event: Command Co.. (0x0e) plen 4  #634 [hci0] 5676.361330
      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
        Status: Success (0x00)
@ MGMT Event: Com.. (0x0001) plen 4  {0x0003} [hci0] 5676.361372
      Add Advertising (0x003e) plen 1
        Status: Success (0x00)
        Instance: 1
> HCI Event: LE Meta Ev.. (0x3e) plen 6  #635 [hci0] 5676.362333
      LE Advertising Set Terminated (0x12)
        Status: Advertising Timeout (0x3c)
        Handle: 1
        Connection handle: 65535
        Number of completed extended advertising events: 0

是否有很好的方法可以重新创建使用hci套接字可用的功能,还是禁用扩展广告以使hci套接字再次工作的方法

解决方法

Jos Ryke的这张图片可能有助于解释发生了什么。在这31个字节中,总是使用3个来设置广告标记。

BT 4.0 advertising packet

现在使用-g-l命令行开关设置btmgmt的源代码。使用常规的可发现模式无限期地投放广告。

static void add_adv_usage(void)
{
    bt_shell_usage();
    print("Options:\n"
        "\t -u,--uuid <uuid>         Service UUID\n"
        "\t -d,--adv-data <data>     Advertising Data bytes\n"
        "\t -s,--scan-rsp <data>     Scan Response Data bytes\n"
        "\t -t,--timeout <timeout>   Timeout in seconds\n"
        "\t -D,--duration <duration> Duration in seconds\n"
        "\t -P,--phy <phy>           Phy type,Specify 1M/2M/CODED\n"
        "\t -c,--connectable         \"connectable\" flag\n"
        "\t -g,--general-discov      \"general-discoverable\" flag\n"
        "\t -l,--limited-discov      \"limited-discoverable\" flag\n"
        "\t -n,--scan-rsp-local-name \"local-name\" flag\n"
        "\t -a,--scan-rsp-appearance \"appearance\" flag\n"
        "\t -m,--managed-flags       \"managed-flags\" flag\n"
        "\t -p,--tx-power            \"tx-power\" flag\n"
        "e.g.:\n"
        "\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
}

其他28个字节必须以一个声明长度的字节和声明所声明长度的其余data type个字节所描述的字节开头。 使用-d的{​​{1}}选项设置的是这28个字节。

如果28个字节不足,那么人们常用的解决方法是将数据分割成多个广告或使用扫描响应数据包。

Core Specification中有关广告数据格式的详细信息,其中将btmgmt定义为:

包含广告PDU的数据包。参见[第6卷] B部分,第2.3.1节

更多数据是部分:

蓝牙核心规范5.2版|第3卷,C部分| 11广告和扫描响应数据格式

其中有ADV_NONCONN_IND数据包类型的示例:

Advertising Packet

以flags数据类型开头。