ubluepy --- Bluetooth LE 外设与中心设备¶
ubluepy 模块是随 MicroPython nRF 移植版附带的旧版 Bluetooth LE API。它大致模仿了 Linux 上的 bluepy Python 库,并直接构建于 Nordic SoftDevice 之上 --- 没有可移植的后端,因此该模块仅在 Nordic 目标平台上可用(在 OpenMV 的产品线中即 Arduino Nano 33 BLE Sense)。较新的 bluetooth / aioble API 在本构建中未启用,因此 ubluepy 是驱动片上无线电的唯一方式。
可用的功能集取决于固件所烧录的 SoftDevice:
s140(Nano 33 BLE Sense)--- 同时支持外设和中心(扫描器)角色。这正是 OpenMV 固件所附带的版本。
s132 --- 同时支持外设和中心。
s110 --- 仅支持外设;扫描器 / 连接相关方法被编译排除。
外设示例¶
作为 Bluetooth LE 外设进行广播,提供单个环境感知服务,并在每次写入其客户端特征配置描述符(CCCD)时通知一个温度特征:
from ubluepy import Service, Characteristic, UUID, Peripheral, constants
from machine import LED
notif_enabled = False
def event_handler(event_id, handle, data):
global notif_enabled
if event_id == constants.EVT_GAP_CONNECTED:
LED("LED_GREEN").on()
elif event_id == constants.EVT_GAP_DISCONNECTED:
LED("LED_GREEN").off()
periph.advertise(device_name="Nano 33", services=[svc])
elif event_id == constants.EVT_GATTS_WRITE:
notif_enabled = bool(data[0])
svc = Service(UUID("181A")) # Environmental Sensing
char = Characteristic(UUID("2A6E"),
props=Characteristic.PROP_NOTIFY | Characteristic.PROP_READ,
attrs=Characteristic.ATTR_CCCD)
svc.addCharacteristic(char)
periph = Peripheral()
periph.addService(svc)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33", services=[svc])
中心设备示例¶
扫描附近的广播设备 100 ms,并解码每个 ScanEntry 的广播数据:
from ubluepy import Scanner, constants
s = Scanner()
for entry in s.scan(100):
print(entry.addr(), entry.rssi(), "dBm")
for ad_type, name, value in entry.getScanData():
print(" ", ad_type, name, bytes(value))
模块内容¶
类¶
- class ubluepy.UUID(value)¶
构造一个 16 位或 128 位的 Bluetooth UUID。
value可为以下之一:
int--- 一个 16 位数值 UUID(UUID(0x180A))。6 字符的
"0xXXXX"字符串 --- 一个 16 位 UUID,例如UUID("0x181A")。36 字符的
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"字符串 --- 一个完整的 128 位 UUID。其中厂商专用部分会在构造时注册到 SoftDevice。另一个
UUID实例 --- 执行复制。
其他任何长度都会引发
ValueError("Invalid UUID string length")。
- class ubluepy.Service(uuid: UUID, type: int = Service.PRIMARY)¶
定义一个 GATT 服务,当其被添加到
Peripheral时将注册到 SoftDevice。uuid一个
UUID实例。传入非 UUID 对象会引发ValueError。typeService.PRIMARY(默认)或Service.SECONDARY之一。其他值会引发ValueError。
- addCharacteristic(characteristic: Characteristic) None¶
向服务注册一个
Characteristic。该特征的 GATT 句柄在此调用期间被分配。
- getCharacteristic(uuid: UUID) Characteristic | None¶
按 UUID 查找先前已添加的
Characteristic。返回该特征实例,若未找到匹配项则返回None。
- class ubluepy.Characteristic(uuid: UUID, *, props: int = PROP_READ | PROP_WRITE, attrs: int = 0)¶
定义一个 GATT 特征。在父级
Peripheral开始广播之前,使用Service.addCharacteristic()将其添加到Service中。uuid一个
UUID实例。props(仅限关键字)由一个或多个
Characteristic.PROP_*值组成的位掩码,用于描述该特征支持哪些操作。attrs(仅限关键字)附加 GATT 属性的位掩码。使用
Characteristic.ATTR_CCCD来附加一个客户端特征配置描述符 --- 这是使PROP_NOTIFY/PROP_INDICATE特征正常工作所必需的。
- class ubluepy.Descriptor(uuid: UUID)¶
用于表示 GATT 描述符的桩类。当前实现仅存储 UUID 且不暴露任何方法 --- 提供它是为了与本模块未来版本保持前向兼容。
- class ubluepy.Peripheral¶
本地 Bluetooth LE 设备。同一个类用于外设和中心两种角色;角色由你调用的方法选定(
advertise()选择外设,connect()选择中心)。- getServices() list¶
返回当前注册到此
Peripheral的服务列表。
- advertise(*, device_name: str | None = None, services: list | None = None, data: bytes | None = None, connectable: bool = True) None¶
以外设角色开始广播。
device_name在 GAP 负载中广播的完整本地名称。
services要广播的
Service实例列表。每个服务的 UUID 都会被包含在广播中。data可选的原始广播负载(
bytes/bytearray),追加到自动生成的头部之后。可用于厂商专用或信标负载,例如 Eddystone。connectable当为
True(默认)时,作为可连接设备进行广播,并注册 GAP / GATTS 事件处理程序,使得已配置的setConnectionHandler()回调在连接、断开连接以及 CCCD 写入时触发。当为False时,作为信标进行广播 --- 不附加任何处理程序,且该设备无法被连接。
- setConnectionHandler(func) None¶
注册一个在 GAP 和 GATTS 事件上被调用的回调。该回调以
func(event_id, conn_handle, data)形式调用,其中event_id是constants.EVT_GAP_CONNECTED、constants.EVT_GAP_DISCONNECTED或constants.EVT_GATTS_WRITE值之一,conn_handle是 SoftDevice 连接句柄(对于 GATTS 写入则为属性句柄),data是以bytearray形式表示的原始事件负载(连接 / 断开连接时为None)。
- withDelegate(delegate: DefaultDelegate) None¶
附加一个
DefaultDelegate实例以接收已解码的 GATT 事件。
- connect(addr, *, addr_type: int = constants.ADDR_TYPE_PUBLIC) None¶
仅限中心角色。 连接到具有给定地址的对端,并同步发现其主服务和特征。在连接建立且发现完成之前会阻塞;发现的服务随后可通过
getServices()获取。addr对端地址,为 17 字符的
"xx:xx:xx:xx:xx:xx"字符串(例如取自ScanEntry.addr())。addr_type(仅限关键字)constants.ADDR_TYPE_PUBLIC(默认)或constants.ADDR_TYPE_RANDOM_STATIC之一。
- class ubluepy.Scanner¶
用于发现附近广播设备的 GAP 观察者。仅当固件针对支持中心功能的 SoftDevice(s132 / s140)构建时可用。
- class ubluepy.ScanEntry¶
由
Scanner.scan()捕获的单个广播报告。实例由扫描器返回 --- 没有公共构造函数。- addr_type() int¶
返回对端地址类型(
constants.ADDR_TYPE_PUBLIC或constants.ADDR_TYPE_RANDOM_STATIC)。
- getScanData() list¶
将广播负载解码为
(ad_type, description, value)元组的列表。ad_type是数值型 AD 类型字节(参见constants.ad_types),description是匹配常量名称的字符串(若类型未知则为None),value是以bytearray形式表示的 AD 记录主体。
- class ubluepy.DefaultDelegate¶
传递给
Peripheral.withDelegate()的对象的基类。对其进行子类化并重写handleConnection()/handleNotification()以响应 GATT 事件。
常量¶
模块的 constants 属性是一个命名空间,包含 GAP/GATT 事件标识符、地址类型值以及嵌套的 ad_types 命名空间。
- constants.EVT_GATTS_WRITE: int¶
用于写入本地 GATT 属性(包括启用/禁用通知的 CCCD 写入)的
Peripheral连接处理程序event_id值(80)。
- constants.ad_types: type¶
来自 Bluetooth Core Specification Supplement 的广播数据 AD 类型常量命名空间。每个名称映射到相应的 1 字节 AD 类型:
名称
值
AD_TYPE_FLAGS0x01AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE0x02AD_TYPE_16BIT_SERVICE_UUID_COMPLETE0x03AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE0x04AD_TYPE_32BIT_SERVICE_UUID_COMPLETE0x05AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE0x06AD_TYPE_128BIT_SERVICE_UUID_COMPLETE0x07AD_TYPE_SHORT_LOCAL_NAME0x08AD_TYPE_COMPLETE_LOCAL_NAME0x09AD_TYPE_TX_POWER_LEVEL0x0AAD_TYPE_CLASS_OF_DEVICE0x0DAD_TYPE_SIMPLE_PAIRING_HASH_C0x0EAD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R0x0FAD_TYPE_SECURITY_MANAGER_TK_VALUE0x10AD_TYPE_SECURITY_MANAGER_OOB_FLAGS0x11AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE0x12AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT0x14AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT0x15AD_TYPE_SERVICE_DATA0x16AD_TYPE_PUBLIC_TARGET_ADDRESS0x17AD_TYPE_RANDOM_TARGET_ADDRESS0x18AD_TYPE_APPEARANCE0x19AD_TYPE_ADVERTISING_INTERVAL0x1AAD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS0x1BAD_TYPE_LE_ROLE0x1CAD_TYPE_SIMPLE_PAIRING_HASH_C2560x1DAD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R2560x1EAD_TYPE_SERVICE_DATA_32BIT_UUID0x20AD_TYPE_SERVICE_DATA_128BIT_UUID0x21AD_TYPE_URI0x24AD_TYPE_3D_INFORMATION_DATA0x3DAD_TYPE_MANUFACTURER_SPECIFIC_DATA0xFF