ubluetooth — 蓝牙

该模块为板上的蓝牙控制器提供接口。目前,这支持中央、外设、广播和观察者角色的低功耗蓝牙 (BLE),以及 GATT 服务器和客户端以及 L2CAP 面向连接的通道。一个设备可以同时以多个角色运行。某些端口支持配对(和绑定)。

This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types.

备注

该模块仍在开发中,其类、函数、方法和常量可能会发生变化。

BLE类

构造函数

class ubluetooth.BLE

返回单例 BLE 对象。

配置

BLE.active([active, ]/)

可选择更改 BLE 无线电的活动状态,并返回当前状态。

在使用此类上的任何其他方法之前,必须使无线电处于活动状态

BLE.config('param', /)
BLE.config(*, param=value, ...)

获取或设置 BLE 接口的配置值。要获得一个值,参数名称应该被引用为一个字符串,并且一次只查询一个参数。要设置值,请使用关键字语法,并且一次可以设置一个或多个参数。

当前支持的值是:

  • 'mac' : 当前使用的地址,取决于当前地址模式。这将返回一个元组。(addr_type, addr) .

    gatts_write 有关地址类型的详细信息,请参阅。

    这只能在接口当前处于活动状态时查询。

  • 'addr_mode': 设置地址模式。值可以是:

    • 0x00 - PUBLIC - 使用控制器的公共地址。

    • 0x01 - RANDOM - 使用生成的静态地址。

    • 0x02 - RPA - 使用可解析的私有地址。

    • 0x03 - NRPA - 使用不可解析的私有地址。

    默认情况下,如果可用,接口模式将使用 PUBLIC 地址,否则将使用 RANDOM 地址。

  • 'gap_name' :获取/设置服务0x1800使用的GAP设备名称,特征0x2a00。这可以随时设置并多次更改。

  • 'rxbuf' : 获取/设置用于存储传入事件的内部缓冲区的大小(以字节为单位)。该缓冲区对整个 BLE 驱动程序是全局的,因此处理所有事件的传入数据,包括所有特征。增加此值可以更好地处理突发传入数据(例如扫描结果)和接收更大特征值的能力。

  • 'mtu' : 获取/设置将在 ATT MTU 交换期间使用的 MTU。生成的 MTU 将是该 MTU 和远程设备的 MTU 中的最小值。ATT MTU 交换不会自动发生(除非远程设备启动它),必须手动启动 gattc_exchange_mtu 。使用该 _IRQ_MTU_EXCHANGED 事件来发现给定连接的 MTU。

事件处理

BLE.irq(handler, /)

为来自 BLE 堆栈的事件注册回调。的处理程序采用两个参数,event``(这将在下面的代码中的一个)和``data (其是值的特定事件元组)。

注:作为一种优化,以防止不必要的配发, addr, adv_data, char_data, notify_datauuid 在元组的条目是只读的指向 ubluetooth 内部ringbuffer memoryview实例,仅仅是IRQ处理函数的调用期间有效。如果您的程序需要保存这些值之一以在 IRQ 处理程序返回后访问(例如通过将其保存在类实例或全局变量中),那么它需要获取数据的副本,通过使用 bytes(addr)bluetooth.UUID(uuid) ,像这样:

显示所有可能事件的句柄:

def bt_irq(event, data):
    if event == _IRQ_CENTRAL_CONNECT:
        # A central has connected to this peripheral.
        conn_handle, addr_type, addr = data
    elif event == _IRQ_CENTRAL_DISCONNECT:
        # A central has disconnected from this peripheral.
        conn_handle, addr_type, addr = data
    elif event == _IRQ_GATTS_WRITE:
        # A client has written to this characteristic or descriptor.
        conn_handle, attr_handle = data
    elif event == _IRQ_GATTS_READ_REQUEST:
        # A client has issued a read. Note: this is a hard IRQ.
        # Return None to deny the read.
        # Note: This event is not supported on ESP32.
        conn_handle, attr_handle = data
    elif event == _IRQ_SCAN_RESULT:
        # A single scan result.
        addr_type, addr, adv_type, rssi, adv_data = data
    elif event == _IRQ_SCAN_DONE:
        # Scan duration finished or manually stopped.
        pass
    elif event == _IRQ_PERIPHERAL_CONNECT:
        # A successful gap_connect().
        conn_handle, addr_type, addr = data
    elif event == _IRQ_PERIPHERAL_DISCONNECT:
        # Connected peripheral has disconnected.
        conn_handle, addr_type, addr = data
    elif event == _IRQ_GATTC_SERVICE_RESULT:
        # Called for each service found by gattc_discover_services().
        conn_handle, start_handle, end_handle, uuid = data
    elif event == _IRQ_GATTC_SERVICE_DONE:
        # Called once service discovery is complete.
        # Note: Status will be zero on success, implementation-specific value otherwise.
        conn_handle, status = data
    elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
        # Called for each characteristic found by gattc_discover_services().
        conn_handle, def_handle, value_handle, properties, uuid = data
    elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
        # Called once service discovery is complete.
        # Note: Status will be zero on success, implementation-specific value otherwise.
        conn_handle, status = data
    elif event == _IRQ_GATTC_DESCRIPTOR_RESULT:
        # Called for each descriptor found by gattc_discover_descriptors().
        conn_handle, dsc_handle, uuid = data
    elif event == _IRQ_GATTC_DESCRIPTOR_DONE:
        # Called once service discovery is complete.
        # Note: Status will be zero on success, implementation-specific value otherwise.
        conn_handle, status = data
    elif event == _IRQ_GATTC_READ_RESULT:
        # A gattc_read() has completed.
        conn_handle, value_handle, char_data = data
    elif event == _IRQ_GATTC_READ_DONE:
        # A gattc_read() has completed.
        # Note: The value_handle will be zero on btstack (but present on NimBLE).
        # Note: Status will be zero on success, implementation-specific value otherwise.
        conn_handle, value_handle, status = data
    elif event == _IRQ_GATTC_WRITE_DONE:
        # A gattc_write() has completed.
        # Note: The value_handle will be zero on btstack (but present on NimBLE).
        # Note: Status will be zero on success, implementation-specific value otherwise.
        conn_handle, value_handle, status = data
    elif event == _IRQ_GATTC_NOTIFY:
        # A server has sent a notify request.
        conn_handle, value_handle, notify_data = data
    elif event == _IRQ_GATTC_INDICATE:
        # A server has sent an indicate request.
        conn_handle, value_handle, notify_data = data
    elif event == _IRQ_GATTS_INDICATE_DONE:
        # A client has acknowledged the indication.
        # Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise.
        conn_handle, value_handle, status = data
    elif event == _IRQ_MTU_EXCHANGED:
        # MTU exchange complete (either initiated by us or the remote device).
        conn_handle, mtu = data

事件代码是:

from micropython import const
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
_IRQ_GATTS_READ_REQUEST = const(4)
_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_DONE = const(6)
_IRQ_PERIPHERAL_CONNECT = const(7)
_IRQ_PERIPHERAL_DISCONNECT = const(8)
_IRQ_GATTC_SERVICE_RESULT = const(9)
_IRQ_GATTC_SERVICE_DONE = const(10)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
_IRQ_GATTC_DESCRIPTOR_DONE = const(14)
_IRQ_GATTC_READ_RESULT = const(15)
_IRQ_GATTC_READ_DONE = const(16)
_IRQ_GATTC_WRITE_DONE = const(17)
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)
_IRQ_GATTS_INDICATE_DONE = const(20)
_IRQ_MTU_EXCHANGED = const(21)

为了节省固件空间,这些常量不包含在 ubluetooth 模块中。将上面列表中您需要的那些添加到您的程序中。

广播员角色

BLE.gap_advertise(interval_us, adv_data=None, *, resp_data=None, connectable=True)

以指定的时间间隔(以微秒为单位)开始广告。此间隔将向下舍入到最接近的 625us。要停止广告,请将interval_us设置 为``None`` 。

adv_data和resp_data可以是任何实现缓冲协议的类型(例如``bytes`` , bytearray , str )。adv_data包含在所有广播中,并且resp_data被发送以响应主动扫描。

注意:如果adv_data(或resp_data)是``None``,则传递给前一个调用的数据 gap_advertise 将被重新使用。这允许广播公司仅使用 来恢复广告``gap_advertise(interval_us)`` 。要清除广告有效负载,请传递一个空值 bytes,即``b’’`` 。

观察者角色

BLE.gap_scan(duration_ms, interval_us=1280000, window_us=11250, active=False, /)

运行持续指定持续时间(以毫秒为单位)的扫描操作。

要无限期扫描,请将duration_ms设置为 0

要停止扫描,请将duration_ms设置为 None

使用interval_us和window_us可选择配置占空比。扫描器将每interval_us微秒运行window_us 微秒,总共持续duration_ms毫秒。默认间隔和窗口分别为 1.28 秒和 11.25 毫秒(后台扫描)。

对于每个扫描结果, _IRQ_SCAN_RESULT 将引发事件,并带有事件数据。 (addr_type, addr, adv_type, rssi, adv_data)

addr_type 值表示公共或随机地址:
  • 0x00 - PUBLIC 公共

  • 0x01 - RANDOM (静态、RPA 或 NRPA,类型在地址本身中编码)

adv_type 值对应于蓝牙规范:

  • 0x00 - ADV_IND - 可连接和可扫描的无向广告

  • 0x01 - ADV_DIRECT_IND - 可连接的定向广告

  • 0x02 - ADV_SCAN_IND - 可扫描的无向广告

  • 0x03 - ADV_NONCONN_IND - 不可连接的无向广告

  • 0x04 - SCAN_RSP - 扫描响应

active True 如果要在结果中接收扫描响应,可以设置。

当扫描停止时(由于持续时间完成或明确停止),_IRQ_SCAN_DONE 将引发该事件。

核心角色

中央设备可以使用观察者角色(参见 参考资料 gap_scan )或已知地址连接到它发现的外围设备。

BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, /)

连接到外围设备。

gap_scan 有关地址类型的详细信息,请参阅 gap_scan

成功后,_IRQ_PERIPHERAL_CONNECT 将引发该事件。

外围角色

外围设备应发送可连接的广告(请参阅 参考资料 gap_advertise)。它通常充当 GATT 服务器,首先使用 gatts_register_services .

当中心连接时,_IRQ_CENTRAL_CONNECT 将引发该事件。

中心和外围角色

BLE.gap_disconnect(conn_handle, /)

断开指定的连接句柄。这可以是已连接到该设备的中央设备(如果作为外围设备),也可以是之前由该设备连接的外围设备(如果作为中央设备)。

成功时, 将引发 _IRQ_PERIPHERAL_DISCONNECT or _IRQ_CENTRAL_DISCONNECT 事件。

如果连接句柄未连接,返回 False 否则返回 True

通用属性配置文件规范服务

GATT 服务器有一组注册服务。每个服务可能包含特性,每个特性都有一个值。特征还可以包含描述符,描述符本身具有值。

这些值存储在本地,并由服务注册期间生成的“值句柄”访问。它们也可以从远程客户端设备读取或写入。此外,服务器可以通过连接句柄向连接的客户端“通知”特征。

处于中央或外围角色的设备可以充当 GATT 服务器,但在大多数情况下,外围设备充当服务器的情况更为常见。

特征和描述符的默认最大大小为 20 字节。客户写给他们的任何东西都将被截断到这个长度。但是,任何本地写入都会增加最大大小,因此如果您希望允许从客户端对给定特性进行更大的写入,请 gatts_write 在注册后使用 。例如 。 gatts_write(char_handle, bytes(100)) .

BLE.gatts_register_services(services_definition, /)

使用指定的服务配置服务器,替换任何现有服务。

services_definition是列表服务,其中每个服务是包含UUID和列表的两个元素的元组的特性。

每个特性都是一个包含 UUID、标志值和可选的描述符列表的二或三元素元组 。

每个描述符都是一个包含 UUID 和标志 值的两元素元组。

flags 是一个下列值得二进制或组合 ubluetooth.FLAG_READ, ubluetooth.FLAG_WRITEubluetooth.FLAG_NOTIFY

返回值是一个元组列表(每个服务一个元素)(每个元素是一个值句柄)。特征和描述符句柄按照定义的顺序平展为同一个元组。

以下示例注册了两个服务(Heart Rate 和 Nordic UART):

HR_UUID = bluetooth.UUID(0x180D)
HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
HR_SERVICE = (HR_UUID, (HR_CHAR,),)
UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,)
UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),)
SERVICES = (HR_SERVICE, UART_SERVICE,)
( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES)

这三个值手柄(hr, tx, rx )可与使用 gatts_read, gatts_write, gatts_notify, 和 gatts_indicate

注意:在注册服务之前必须停止广播。

BLE.gatts_read(value_handle, /)

读取此句柄的本地值(已由 gatts_write 远程客户端写入或由远程客户端写入 )。

BLE.gatts_write(value_handle, data, /)

写入此句柄的本地值,客户端可以读取该值。

BLE.gatts_notify(conn_handle, value_handle, data=None, /)

向连接的客户端发送通知请求。

如果data不是``None`` ,则该值将作为通知的一部分发送给客户端。本地值不会被修改。

否则,如果data是``None`` ,则将发送当前本地值(使用 设置:meth:gatts_write ) 。

BLE.gatts_indicate(conn_handle, value_handle, /)

向连接的客户端发送指示请求。

注意: 这当前不支持发送自定义值,它将始终发送当前本地值(如设置 gatts_write)。

在确认(或失败,例如超时)时, _IRQ_GATTS_INDICATE_DONE 将引发该 事件。

BLE.gatts_set_buffer(value_handle, len, append=False, /)

以字节为单位设置值的内部缓冲区大小。这将限制可以接收的最大可能写入。默认值为 20。

设置append 为 True 将使所有远程写入附加到当前值,而不是替换当前值。在大多数LEN字节可以用这种方式进行缓冲。当您使用 时 gatts_read,读取后该值将被清除。在实现类似 Nordic UART 服务之类的功能时,此功能很有用。

通用属性配置文件规范客户端

GATT 客户端可以发现和读取/写入远程 GATT 服务器上的特性。

中央角色设备充当 GATT 客户端更为常见,但是外围设备也可以充当客户端,以发现有关已连接到它的中央角色的信息(例如,从设备信息服务)。

BLE.gattc_discover_services(conn_handle, uuid=None, /)

查询已连接服务器的服务。

(可选)指定服务uuid以仅查询该服务。

对于发现的每个服务, _IRQ_GATTC_SERVICE_RESULT 将引发事件,然后是 _IRQ_GATTC_SERVICE_DONE 完成。

BLE.gattc_discover_characteristics(conn_handle, start_handle, end_handle, uuid=None, /)

查询连接的服务器以获取指定范围内的特征。

(可选)指定一个特征uuid以仅查询该特征。

您可以使用 start_handle=1 , end_handle=0xffff 在任何服务中搜索特征。

对于发现的每个特征,_IRQ_GATTC_CHARACTERISTIC_RESULT 将引发事件,然后是``_IRQ_GATTC_CHARACTERISTIC_DONE`` 完成。

BLE.gattc_discover_descriptors(conn_handle, start_handle, end_handle, /)

向连接的服务器查询指定范围内的描述符。

对于发现的每个描述符, _IRQ_GATTC_DESCRIPTOR_RESULT 将引发事件,然后 _IRQ_GATTC_DESCRIPTOR_DONE 在完成时引发。

BLE.gattc_read(conn_handle, value_handle, /)

为指定的特征或描述符句柄向连接的服务器发出远程读取。

当值可用时,_IRQ_GATTC_READ_RESULT 将引发该事件。此外, _IRQ_GATTC_READ_DONE 将提高。

BLE.gattc_write(conn_handle, value_handle, data, mode=0, /)

为指定的特征或描述符句柄向连接的服务器发出远程写入。

参数mode指定写入行为,当前支持的值为:

  • (默认)是无响应写入:写入将发送到远程服务器,但不会返回确认,也不会引发任何事件。

  • mode=1 是 write-with-response:请求远程服务器发送它收到数据的响应/确认。

如果收到来自远程服务器的响应, 则将引发该 事件。

BLE.gattc_exchange_mtu(conn_handle, /)

使用首选 MTU 集启动与连接的服务器的 MTU 交换 BLE.config(mtu=value)

_IRQ_MTU_EXCHANGED 当 MTU 交换完成时将引发该事件。

注意: MTU 交换通常由中央发起。在中心角色中使用 BlueKitchen 堆栈时,它不支持启动 MTU 交换的远程外围设备。NimBLE 适用于这两个角色。

UUID类

构造函数

class ubluetooth.UUID(value, /)

创建具有指定值的 UUID 实例。

该值可以是:

  • 一个 16 位整数。例如 0x2908

  • 一个 128 位的 UUID 字符串。例如 '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'

常量

ubluetooth.FLAG_READ
ubluetooth.FLAG_WRITE
ubluetooth.FLAG_NOTIFY