Python使用Bleak库无法读取BLE设备带indicate权限的特征值
核心原因
BLE GATT特征的不同权限是完全独立的,indicate权限不代表支持read操作:
- 带
read权限的特征:支持客户端(你的Python代码)主动向设备发起读请求,拉取当前值 - 仅带
indicate权限的特征:不支持主动读,只能由设备侧主动向客户端推送数据,且客户端收到推送后需要回复确认包,你收到的Protocol Error 0x02: Read Not Permitted错误就是设备明确拒绝了你的主动读请求。
你在手机BLE工具上能看到该特征的值,是因为手机工具自动注册了indicate的监听回调,接收设备主动推送的值再做展示,并非发起了主动读操作。
解决代码(基于Bleak)
你需要用start_notify方法注册indicate的回调函数来接收设备推送的值,而不是用read_gatt_char主动读取:
import sys import platform import asyncio import logging from bleak import BleakClient logger = logging.getLogger(__name__) # 替换为你要监听的indicate特征UUID,此处为Handle 2对应的00002a05 INDICATE_UUID = "00002a05-0000-1000-8000-00805f9b34fb" ADDRESS = ( "00:80:E1:26:C4:5E" if platform.system() != "Darwin" else "B9EA5233-37EF-4DD6-87A8-2A875E821C46" ) # indicate数据回调函数 def on_indicate(sender, data): print(f"收到indicate数据,来源:{sender},值:{data}") async def main(address): async with BleakClient(address) as client: # 注册indicate监听,Bleak会自动处理2902描述符配置和ACK回复逻辑 await client.start_notify(INDICATE_UUID, on_indicate) print("indicate监听已启动,等待设备推送数据...") # 保持连接不退出 while True: await asyncio.sleep(1) if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.run(main(sys.argv[1] if len(sys.argv) == 2 else ADDRESS))
注:Bleak的
start_notify方法同时支持notify和indicate类型的特征,不需要额外区分,底层会自动处理indicate要求的ACK回复逻辑,你只需要处理回调里收到的数据即可。
内容的提问来源于stack exchange,提问作者Rifet Gazdic
相关产品推荐
相关产品推荐

