Bleak 实战指南:用 Python 轻松玩转跨平台蓝牙低功耗设备 Bleak 实战指南用 Python 轻松玩转跨平台蓝牙低功耗设备【免费下载链接】bleakA cross platform Bluetooth Low Energy Client for Python using asyncio项目地址: https://gitcode.com/gh_mirrors/bl/bleak你是否遇到过这样的场景好不容易拿到一个支持蓝牙的心率带或温湿度传感器满心欢喜想写段 Python 读取数据结果发现——Windows 要用 WinRT APImacOS 要用 CoreBluetoothLinux 要对着 BlueZ 的 D-Bus 接口折腾三套代码几乎无法复用如果你正准备做物联网、可穿戴设备或智能家居开发这篇文章就是为你准备的。Bleak 是一个基于 asyncio 的跨平台 Python 蓝牙低功耗BLE客户端库它把不同操作系统底层的差异全部封装起来让你用一套几乎相同的代码在 Windows、macOS、Linux 甚至 Android 上都能连接和读写 BLE 设备。当连个蓝牙设备变成一场噩梦先说一个真实的故事。有位开发者想读取智能体脂秤的数据他的开发机是 Windows但部署环境是树莓派。他先照着网上教程用 WinRT 写通了 Windows 版又得给树莓派重写一套基于 BlueZ 的代码。这还不算完——两套代码的事件模型、回调方式、服务发现逻辑全都长得不一样他几乎等于把同一个功能写了两遍还得祈祷两边行为一致。这就是 BLE 开发最让人头疼的地方协议本身是统一的但每个操作系统都提供了截然不同的访问方式。Windows 走 WinRTmacOS 走 CoreBluetooth 的 Objective-C 桥接Linux 则要跟 BlueZ 的 D-Bus 打交道。作为普通开发者我们想做的只是读取传感器数值却被逼着成为三平台专家。而 Bleak 的出现就是要把这一层翻译工作彻底替你包办。先认识这位翻译官Bleak 是什么Bleak 的全称是Bluetooth Low Energy platform Agnostic Klient平台无关的蓝牙低功耗客户端从名字就能看出它的野心写一次处处运行。它本质上是一个 GATT 客户端库负责连接作为 GATT 服务端的 BLE 设备支持服务的读写、通知订阅和设备扫描。它的核心亮点可以用一张表说清楚特性说明跨平台支持 Windows 11、LinuxBlueZ ≥ 5.55、macOS10.15及 Android异步模型基于 asyncio天然适合高并发场景API 统一同一套代码在不同系统上行为一致生态完善官方提供大量示例文档详尽MIT 协议免费商用 换句话说Bleak 就像蓝牙世界的通用插座转换头不管插座长什么样插上去就能用。三个词扫盲GATT、UUID 与订阅在动手之前我们需要先弄懂 BLE 世界里的三个基础概念否则代码里的术语会让你一头雾水。GATT通用属性协议——你可以把 BLE 设备想象成一个文件柜。柜子里的每层抽屉叫服务Service抽屉里的每个文件夹叫特征Characteristic文件夹上的备注标签叫描述符Descriptor。数据就存放在特征里读写操作也都是围绕特征展开的。UUID——每个服务、特征都有一个全球唯一的身份证号。比如2A24这个 16 位短编号就是设备型号特征的官方编号。我们写代码时就是靠这些编号找到想读的数据。通知Notification——如果设备每秒钟都产生新数据比如心率让程序每隔一秒主动问一次显然又慢又浪费。更聪明的做法是订阅告诉设备有数据就推给我设备就会在你没睡觉的时候主动把数据送上门。这也是 BLE 能省电的关键设计。从零到一让电脑读懂你的第一个传感器概念清楚了我们来动真格。整个过程分三步安装 → 扫描 → 连接读取。第一步安装Bleak 的安装步骤非常简单一条命令即可$ pip install bleak如果你用的是 iOS 的 Pythonista 环境则改为$ pip install bleak[pythonista]⚠️ 注意千万别把你的脚本命名为bleak.py否则 Python 会把它误认为库本身直接报循环导入错误。第二步扫描附近的设备装上之后先用一个小脚本看看周围有哪些 BLE 设备在广播自己import asyncio from bleak import BleakScanner async def main(): devices await BleakScanner.discover(timeout5.0) for d in devices: print(d) asyncio.run(main())这段代码做了什么BleakScanner.discover()会扫描 5 秒并返回所有可见设备每个设备对象里包含地址、名称等信息。asyncio.run(main())是 asyncio 程序的固定入口整个程序只调用这一次。第三步连接并读取数据扫描到设备后就可以连接并读取它的型号信息了。这里用最常见的设备型号特征UUID 为2A24做演示import asyncio from bleak import BleakClient address 24:71:89:cc:09:05 # 换成你扫描到的设备地址 MODEL_NBR_UUID 2A24 # 设备型号特征的官方 UUID async def main(address): async with BleakClient(address) as client: model_number await client.read_gatt_char(MODEL_NBR_UUID) print(fModel Number: {model_number.decode()}) asyncio.run(main(address))这段代码里最关键的是async with BleakClient(address) as client它会在进入代码块时自动连接设备离开时自动断开你完全不用手动管理连接的生命周期。read_gatt_char()按 UUID 读取特征值返回的是字节串所以用.decode()转成字符串打印。跑起来之后你会看到类似Model Number: CC2650的输出——恭喜你的 Python 程序已经成功和物理世界的蓝牙设备对上话了让数据主动送上门玩转通知与回调读一次数据只是入门。真正让 BLE 变得强大的是订阅通知。想象一下心率带每秒钟都要推送数据如果每次都用请求-响应模式效率和电量都会很难看。下面这段代码演示如何订阅一个特征的通知import asyncio from bleak import BleakClient, BleakScanner # 通知回调设备每次推送数据这里就会被调用 def notification_handler(characteristic, data: bytearray): print(f{characteristic.description}: {data}) async def main(): device await BleakScanner.find_device_by_name(MyDevice) async with BleakClient(device) as client: await client.start_notify(00002A37-0000-1000-8000-00805F9B34FB, notification_handler) await asyncio.sleep(10) # 订阅后保持 10 秒接收 await client.stop_notify(00002A37-0000-1000-8000-00805F9B34FB) asyncio.run(main())这段代码做了什么start_notify()告诉设备开始推送notification_handler就是接收推送的回调函数——设备每推一次数据Python 就自动打印一次期间你的程序可以继续干别的事。这正是 asyncio 的优雅之处异步不会阻塞主流程就像餐厅服务员同时接待多桌客人哪桌有需要就应哪桌。进阶玩法并发连接与 UART 透传学会基本读写后Bleak 还能帮你做更有意思的事。同时连接多个设备。假设你想同时监听两个传感器的数据用asyncio.gather就能并发处理。项目官方示例examples/two_devices.py展示了完整做法核心思路是先扫描再连接把扫描返回的BLEDevice对象直接传给BleakClient能减少连接失败的概率并用asyncio.Lock避免两台设备同时建立连接时互相干扰。UART 透传。很多单片机如 Arduino、MicroPython 设备通过 Nordic 的 UART 服务实现双向通信——你打字发过去设备回传结果。examples/uart_service.py就是一个蓝牙串口终端从键盘读取一行写入 UART 的 RX 特征再把设备通过 TX 特征推回来的数据打印出来。这个模式非常适合做调试工具或遥控器类应用。避坑指南新手最容易踩的五个坑下面这些坑几乎每个 Bleak 新手都会至少踩一次。我们用错误 vs 正确的方式直观看清差别。坑 1多次调用asyncio.run()❌ 错误做法每个函数各自包一层asyncio.run()看似能用实则共用的事件循环被反复关闭重建迟早崩溃。✅ 正确做法只调用一次asyncio.run()把所有异步逻辑放进一个async def main()里。坑 2把脚本命名为bleak.py❌ 错误做法文件名和库名撞车报错cannot import name BleakClient from partially initialized module bleak。✅ 正确做法换个名字比如my_sensor_app.py。坑 3macOS 上程序崩溃或扫不到设备在 macOS 上应用必须获得蓝牙权限。如果程序崩溃并报SIGABRT多半是系统隐私设置里没给运行 Python 的终端应用授权。在系统偏好设置 → 安全性与隐私 → 隐私 → 蓝牙中勾选对应应用即可坑 4树莓派上连接时好时坏树莓派内置的 Wi-Fi 和蓝牙共用天线无线干扰会导致Not connected或偶尔丢失广播包。可以临时关掉 Wi-Fi 验证sudo rfkill block wlan如果问题消失说明是干扰所致换一个 USB 蓝牙适配器即可。坑 5改了设备固件读到的却是旧服务操作系统会缓存 BLE 设备的服务结构。开发外设时若频繁增删服务Linux 上需要先移除设备缓存bluetoothctl -- remove XX:XX:XX:XX:XX:XXBlueZ 5.62 之前还需手动删除/var/lib/bluetooth/YY:YY:YY:YY:YY:YY/cache/下的对应缓存文件。从这出发去哪里继续深挖Bleak 的生态非常完整读完这篇文章后你可以顺着这些路径继续探索官方示例examples/目录下有扫描、通知、多设备、UART 透传等十几个可直接运行的例子examples/service_explorer.py能帮你把设备上所有服务、特征、描述符完整打印出来是熟悉任意设备的万能钥匙。文档docs/目录涵盖安装、各平台后端说明和故障排查遇到问题先翻docs/troubleshooting.rst往往比搜遍全网更有效。源码如果好奇底层实现bleak/backends/下按平台分目录存放了各系统的适配代码读一读你会对跨平台抽象有更深的理解。如果你还在为怎么写一套代码、跑遍所有平台而头疼不妨现在就把 Bleak 装进你的环境跑通上面那个读型号的小程序。当你第一次看到 Python 打印出传感器返回的数据时那种机器听懂了你的话的成就感就是进入蓝牙低功耗世界最好的入场券。【免费下载链接】bleakA cross platform Bluetooth Low Energy Client for Python using asyncio项目地址: https://gitcode.com/gh_mirrors/bl/bleak创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考