百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

MicroPython低阶蓝牙BLE接口(二)

bigegpt 2024-09-05 12:14 4 浏览

MicroPython中提供了ubluetooth模块作为蓝牙BLE(Bluetooth Low Energy)的操作接口,其主要提供了蓝牙控制器层面的操作, 匹配低阶蓝牙BLE协议,但未集成各种特定设备类型配置文件(Profile),仅提供基础实现模块以供高阶层抽象,故称作低阶蓝牙BLE接口。

在蓝牙BLE中,一个设备可能需要以多个角色进行工作。当前,其能够支持中心(Central)、外设(Peripheral)、广播者(Broadcaster)和观察者(Observer)角色,还能够支持GATT服务器、GATT客户端和L2CAP面向连接通道的工作模式。目前,仅有部分MicroPython移植版本能够支持配对和绑定操作。

注意:该模块仍在开发中,其涉及的类、函数、方法和常量定义均有可能发生变化。

GATT服务器

GATT服务器含有一系列经注册的服务。每项服务均可包含带有属性值的特性,特性还可以包含描述符,描述符也有自己的属性值。

这些属性值均存储在本地,能够通过服务注册时生成的“属性句柄”(handle)进行存取,亦可以供远程设备读取。另外,服务器还能在特定连接中将特性的属性值上报给所连接的客户端设备。

中心设备和外设设备均能够工作于服务器模式,然而,大部分情况下,外设设备工作于服务器模式更为常见。

特性(Characteristic)和描述符(Descriptor)默认具有最大20字节的长度,远程客户端写入的任何值会被截短到该长度。然而,任何本地的写入操作均可以增大该长度,所以,若需要某个特性能够被远程客户端以更大长度写入,可以在服务注册之后,使用gatts_write()首先进行一次大长度的写入操作,比如gatts_write(char_handle,bytes(100))。

BLE.gatts_register_services(services_definition, /)

配置服务器特定服务选项,该调用会替代掉现有选项值。

services_definition是一个服务列表,其中每项服务均是一个包含两个元素的元组,该元组由一个UUID和一个特性列表组成。每个特性是一个两元素或者三元素的元组,其中包含一个UUID,一个标志值,和一个可选的的描述符列表。而每个描述符又是一个两元素的元组,其包含一个UUID和一个标志值。

这些标志值是下面各种标志的位或组合,既可以设定特性或者描述符的行为,也可以设定所需的安全性和隐私性。

该函数的返回值是一个元组列表,其中每项服务对应一个元组,每个元组的元素均是其所对应特性和描述符的句柄。特性和描述符的句柄在同一元组中以其定义时的顺序排列。

下面示例中注册了两项服务(心率服务和Nordic UART透传服务):

HR_UUID=bluetooth.UUID(0x180D)
HR_CHAR=(bluetooth.UUID(0x2A37),bluetooth.FLAG_READ| luetooth.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()以进行相应操作。

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

特性和描述符可用标志如下:

from micropython import const
_FLAG_BROADCAST = const(0x0001)
_FLAG_READ = const(0x0002)
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
_FLAG_WRITE = const(0x0008)
_FLAG_NOTIFY = const(0x0010)
_FLAG_INDICATE = const(0x0020)
_FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040)
_FLAG_AUX_WRITE = const(0x0100)
_FLAG_READ_ENCRYPTED = const(0x0200)
_FLAG_READ_AUTHENTICATED = const(0x0400)
_FLAG_READ_AUTHORIZED = const(0x0800)
_FLAG_WRITE_ENCRYPTED = const(0x1000)
_FLAG_WRITE_AUTHENTICATED = const(0x2000)
_FLAG_WRITE_AUTHORIZED = const(0x4000)

若要使用上述常量定义,需要自行添加到你的Python代码中。

BLE.gatts_read(value_handle, /)

读取value_handle所指定的本地值,该值可能由gatts_write()本地写入,也可能由远程设备写入。

BLE.gatts_write(value_handle, data, /)

写入value_handle所指定的值,以供客户端读取。

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

向已连接的客户端发送上报请求。如果data参数不为None,其会作为上报请求的负载发向客户端,Value_handle指定的本地值并不会被改变。而如果data为None,当前本地值将会被发送过去。(本地值需经由gatts_write()设置过)

BLE.gatts_indicate(conn_handle, value_handle, /)

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

注意,该调用不支持发送自定义值,其总是发送value_handle指定的本地值(本地址需经由gatts_write()设置过)。作为确认(无论失败还是超时),_IRQ_GATTS_INDICATE_DONE事件会被触发。

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

以字节为单位设置特定值的内部缓冲区大小。该缓冲区会限制远程写入请求的最大长度,默认为20字节。

若将append参数设为True将使得所有远程的写入操作均以添加,而不是替代,的形式更新当前值。该方式最多能够接受len参数所指定长度的字节数。当调用gatts_read()时,该值会在读取后被清空。此特性对于实现一些类似Nodic UART透传服务十分有效。

GATT客户端

GATT客户端能够发现和读/写远程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=0无确认写入(默认模式):该写入操作会被发送到远程服务器上,但是没有确认回复,也没有事件会被触发;
  • mode=1带确认写入:该模式下,要求远程服务器在收到数据后发送回复确认。

如果从远程服务器接收到回复,_IRQ_GATTC_WRITE_DONE事件会被触发。

BLE.gattc_exchange_mtu(conn_handle, /)

发起和已连接服务器的MTU(MTU:Maximum transmission unit,指在一个协议数据单元中能够传输的最大数据量)交换协商过程。其中,MTU值需首先使用BLE.config(mtu=value)设定完毕。MTU交换完成后,_IRQ_MTU_EXCHANGE事件会被触发。

注意:MTU交换通常由中心设备发起。当中心设备使用BlueKitchen协议栈时,不支持远程外设发起MTU交换,而对于NimBLE协议栈,中心设备和外设设备均可以发起该交换过程。

L2CAP(Logical Link Control and Adaptation Protocol)面向连接通道

该功能特性允许两个蓝牙BLE设备进行类似socket形式的数据交换。一旦设备通过通用存取规范GAP(Generic Access Profile)建立连接以后,任何一方设备均能够通过数字协议服务复用器PSM(Protocol/Service Multiplexer)监听另一方的连接。

注意:该功能特性目前仅在STM32平台和Unix平台上的NimBLE协议栈中得以支持(ESP32平台不支持)。在某一时间内,只能有一路L2CAP通道处于激活状态(例如,不能在监听的同时进行连接)。

多个L2CAP通道可以建立在同一CID(通道ID)上,活动L2CAP通道可以用连接句柄唯一标识。

面向连接通道具有内置的基于信任的流控机制。不像ATT(Attribute protocol),设备间需要协商一个共享的MTU(Maximum transmission unit),面向连接通道中的监听方设备设置了独立的MTU以限制其用l2cap_recvinto()接收到但还未消费完的最大数据量,连接方设备也设置了独立的MTU以限制其发送给远程设备的最大数据量。

BLE.l2cap_listen(psm, mtu, /)

开始在特定psm上监听可能的L2CAP通道请求,本地MTU设定为mtu参数所指定值。

当远程设备发起连接后,_IRQ_L2CAP_ACCEPT事件会被触发,在该事件响应函数中,可以通过返回非零整数而拒绝该连接请求。一旦接受了该连接请求,_IRQ_L2CAP_CONNECT事件会被触发,可以在该事件的响应函数中获取CID(通道ID)、本地和远程的MTU。

注意:当前时刻不允许停止监听。

BLE.l2cap_connect(conn_handle, psm, mtu, /)

在给定psm上连接处于监听态的设备,本地MTU通过mtu参数进行设置。

连接成功后,_IRQ_L2CAP_CONNECT事件会被触发,可以在该事件的响应函数中获取CID(通道ID)、本地和远程的MTU。连接失败时,会触发带有非零状态值的_IRQ_L2CAP_DISCONNECT事件。

BLE.l2cap_disconnect(conn_handle, cid, /)

断开conn_handle和cid所指定的已激活的L2CAP通道。

BLE.l2cap_send(conn_handle, cid, buf, /)

在conn_handle和cid所指定的L2CAP通道上发送buf中内容。buf所指定的缓冲区长度不能大于远程设备的MTU,也不能大于两倍的本地MTU。

如果该通道当前已经“阻塞”,该函数会返回False,此时,直到_IRQ_L2CAP_SEND_READY事件被触发,l2cap_send函数不应该被再次调用。(该事件通常在远程设备接收并已经处理了数据之后被会触发)

BLE.l2cap_recvinto(conn_handle, cid, buf, /)

从conn_handle和cid所指定通道上接收数据并存储到buf参数所指定的缓冲区(该buf参数必须是有缓冲意义的数据类型,比如bytearray或者memoryview)。

该函数返回从通道中读取到的字节数。如果buf参数为None,仅返回其中可用的字节数。

注意:在接收到_IRQ_L2CAP_RECV事件后,应用程序应该持续调用l2cap_recvinto()直到接收缓冲区中没有数据(例如,已接收了远程设备所支持的MTU长度数据)。

直到接收方接收缓冲区为空,该通道上的远程设备不应该再次发送数据。

配对和绑定

配对允许设备双方通过交换秘钥而对连接进行加密和授权。可选的,配对时可进行配对秘钥认证(passkey authentication)以进行中间人攻击防护(MITM protection)。

绑定是将秘钥存储到非易失性存储器的过程。在进行绑定时,设备能够基于其所存储的IRK(identity resolving key)解析另一设备的RPA(resolvable private address)。为支持绑定,应用必须实现_IRQ_GET_SECRET事件和_IRQ_SET_SECRET事件的响应函数。

注意:该功能特性目前仅在STM32平台和Unix平台上的NimBLE协议栈上得以支持。(ESP32上不支持)

BLE.gap_pair(conn_handle, /)

发起和远程设备的配对过程。

在调用该函数之前,需确保io,mitm,le_secure和bond配置选项已通过config()进行过正确设置。配对成功后,_IRQ_ENCRYPTION_UPDATE事件会被触发。

BLE.gap_passkey(conn_handle, action, passkey, /)

用于响应特定于conn_handle和action的_IRQ_PASSKEY_ACTION事件。

配对秘钥passkey为一个数字值,设备I/O能力不同则对应的action不同,passkey亦不同:(1) 当action为_PASSKEY_ACTION_INPUT时,应用程序应该弹出输入界面以便用户输入远程设备上的passkey;(2) 当action为_PASSKEY_ACTION_DISPLAY时,应用程序应该生成一个随机的六位passkey并展示给用户;(3) 当action为_PASSKEY_ACTION_NUMERIC_COMPARISON时,应用程序应该显示_IRQ_PASSKEY_ACTION事件所提供的passkey,然后,要么返回0以代表取消配对,要么返回1以代表接受配对。

class UUID

class ubluetooth.UUID(value, /)

用特定值生成UUID实例。该值可以为如下之一:

  1. 十六位整数,比如0x2908;
  2. 128位UUID字符串,比如 '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'

注:点关注,不迷路,关注公众号: eeemaker小王子 获取更多内容及pdf完整版本

相关推荐

或者这些Joplin插件也可以帮助你的笔记应用再一次强大

写在前面距离上次分享《搭建私有全平台多端同步笔记,群晖NAS自建JoplinServer服务》已过去一段时间,大家是否开始使用起来了呢?如果你和我一样已经使用过Joplin有一段时间了,那或许你也会...

Three.JS教程4 threejs中的辅助类

一、辅助类简介Three.js提供了一些辅助类(Helpers)以帮助我们更容易地调试、可视化场景中的元素。ArrowHelepr:创建箭头辅助器;AxisHelper:创建坐标轴辅助器;BoxH...

第2章 还记得点、线、面吗(二)(第二章还能敲钟吗)

glbgltf模型(webvrmodel)-gltf模型下载定制,glb模型下载定制,三维项目电商网站在线三维展示,usdz格式,vr模型网,网页VR模型下载,三维模型下载,webgl网页模型下载我...

如何检查Linux系统硬件信息?从CPU到显卡,一网打尽!

你可能会问:“我为什么要关心硬件信息?”答案很简单:硬件是Linux系统的根基,了解它可以帮你解决很多实际问题。比如:性能调优:知道CPU核心数和内存大小,才能更好地调整程序运行参数。故障排查:系统卡...

SpriteJS:图形库造轮子的那些事儿

从2017年到2020年,我花了大约4年的时间,从零到一,实现了一个可切换WebGL和Canvas2D渲染的,跨平台支持浏览器、SSR、小程序,基于DOM结构和支持响应式的,高...

平时积累的FPGA知识点(6)(fpga经典应用100例)

平时在FPGA群聊等积累的FPGA知识点,第六期:1万兆网接口,发三十万包,会出现掉几包的情况,为什么?原因:没做时钟约束,万兆网接口的实现,本质上都是高速serdes,用IP的话,IP会自带约束。...

芯片逻辑调度框架设计 都需要那些那些软件工具

设计芯片逻辑调度框架通常需要使用以下软件工具:1.逻辑设计工具:例如Vivado、Quartus、SynopsysDesignCompiler等,用于设计和实现逻辑电路。2.仿真工具:例如Mo...

ZYNQ与DSP之间EMIF16通信(正点原子领航者zynq之fpga开发指南v3)

本文主要介绍说明XQ6657Z35-EVM高速数据处理评估板ZYNQ与DSP之间EMIF16通信的功能、使用步骤以及各个例程的运行效果。[基于TIKeyStone架构C6000系列TMS320C6...

好课推荐:从零开始大战FPGA(从零开始的冒险4399)

从零开始大战FPGA引子:本课程为“从零开始大战FPGA”系列课程的基础篇。课程通俗易懂、逻辑性强、示例丰富,课程中尤其强调在设计过程中对“时序”和“逻辑”的把控,以及硬件描述语言与硬件电路相对应的“...

业界第一个真正意义上开源100 Gbps NIC Corundum介绍

来源:内容由「网络交换FPGA」编译自「FCCM2020」,谢谢。FCCM2020在5月4日开始线上举行,对外免费。我们有幸聆听了其中一个有关100G开源NIC的介绍,我们对该文章进行了翻译,并对其中...

高层次综合:解锁FPGA广阔应用的最后一块拼图

我们为什么需要高层次综合高层次综合(High-levelSynthesis)简称HLS,指的是将高层次语言描述的逻辑结构,自动转换成低抽象级语言描述的电路模型的过程。所谓的高层次语言,包括C、C++...

Xilinx文档编号及其内容索引(部分)

Xilinx文档的数量非常多。即使全职从事FPGA相关工作,没有几年时间不可能对器件特性、应用、注意事项等等有较为全面的了解。本文记录了我自使用Xilinx系列FPGA以来或精读、或翻阅、或查询过的文...

Xilinx Vivado联合Modelsim软件仿真

引言:Xilinx公司Vivado开发软件自带仿真工具,可以实现一般性能的FPGA软件仿真测试,其测试执行效率以及性能都不如第三方专用仿真软件Modelsim强。本文我们介绍下如何进行Vivado20...

体育动画直播是怎么做出来的?从数据到虚拟赛场的科技魔法!

你是否见过这样的比赛直播?没有真实球员,却能看梅西带球突破?足球比赛变成动画版,但数据100%真实?电竞比赛用虚拟形象直播,选手操作实时同步?这就是体育动画直播——一种融合实时数据、游戏引擎和AI的...

Dialogue between CPC and political parties of neighboring countries held in Beijing

BEIJING,May26(Xinhua)--TheCommunistPartyofChina(CPC)inDialoguewithPoliticalPartiesof...