You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于bluepy获取BLE设备指定NOTIFY特征值失败问题求助

BLE设备Notify特征数据接收异常问题(Raspberry Pi 4 + Ubuntu + bluepy)

问题背景

在搭载Ubuntu系统的Raspberry Pi 4上使用bluepy库开发Python程序,目标是连接指定BLE设备,获取特征00001011-1212-efde-1523-785feabcd123(handle:15)的Notify值。通过bluepy扫描得到设备的服务与特征信息如下:

Service UUID: 00001800-0000-1000-8000-00805f9b34fb
     -> Characteristic UUID: 00002a00-0000-1000-8000-00805f9b34fb
        Characteristic handle: 3
        Characteristic properties: READ 
        Value: b''
     -> Characteristic UUID: 00002a01-0000-1000-8000-00805f9b34fb
        Characteristic handle: 5
        Characteristic properties: READ 
        Value: b'\x00\x00'
     -> Characteristic UUID: 00002a04-0000-1000-8000-00805f9b34fb
        Characteristic handle: 7
        Characteristic properties: READ 
        Value: b'\xff\xff\xff\xff\x00\x00\xff\xff'
Service UUID: 00001801-0000-1000-8000-00805f9b34fb
     -> Characteristic UUID: 00002a05-0000-1000-8000-00805f9b34fb
        Characteristic handle: 10
        Characteristic properties: INDICATE 
Service UUID: 00001523-1212-efde-1523-785feabcd123
     -> Characteristic UUID: 00001027-1212-efde-1523-785feabcd123
        Characteristic handle: 13
        Characteristic properties: READ WRITE 
     -> Characteristic UUID: 00001011-1212-efde-1523-785feabcd123
        Characteristic handle: 15
        Characteristic properties: NOTIFY 
Service UUID: 0000180d-0000-1000-8000-00805f9b34fb
     -> Characteristic UUID: 00002a37-0000-1000-8000-00805f9b34fb
        Characteristic handle: 19
        Characteristic properties: NOTIFY 

已确认指令通过peripheral.writeCharacteristic送达设备,且BLE Scanner连接时能看到目标特征的Notify值更新,但代码仅能收到handle:19的特征数据,无法获取handle:15的Notify值。当前使用的代码如下:

def threadWrite(characteristic, peripheral):
    # is the Characteristic UUID: 00001027-1212-efde-1523-785feabcd123
    characteristic.write(b"reset\n")
    time.sleep(1)
    characteristic.write(b"read ppg 4\n")
    time.sleep(1)

    peripheral.setDelegate(classes.MyDelegate())
    svc = peripheral.getServiceByUUID("00001523-1212-efde-1523-785feabcd123")
    ch = svc.getCharacteristics("00001011-1212-efde-1523-785feabcd123")[0]
    ch_cccd = ch.getDescriptors(forUUID=0x2902)[0]
    ch_cccd.write(b"\0x1\x00")

    characteristic.write(b"read ppg 5\n")

    while True:
        if peripheral.waitForNotifications(1.0):
            # handleNotification() was called
            continue
        print("Waiting...")

# different module
class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        btle.DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        print ("Notification received: handle =", cHandle, "; Raw data =", binascii.b2a_hex(data))

问题分析与解决方案

1. CCCD写入格式错误

你写入客户端特征配置描述符(CCCD)的字节序列b"\0x1\x00"是错误的:

  • 正确启用Notify的字节序应为小端模式的b"\x01\x00"(对应数值0x0001)
  • 原代码中的\0x1是无效转义,实际会被解析为两个独立字符:\0(空字符)和x1,导致CCCD设置失败,目标特征的Notify功能未被真正启用。

2. 优化Delegate设置与订阅顺序

建议先设置Delegate再进行CCCD写入,确保回调能正确捕获所有通知;同时添加withResponse=True参数,确保CCCD写入操作被设备确认。

修正后的代码

import time
import binascii
from bluepy import btle

def threadWrite(characteristic, peripheral):
    # 先设置Delegate,确保通知回调就绪
    peripheral.setDelegate(classes.MyDelegate())
    
    # 发送初始化指令
    characteristic.write(b"reset\n")
    time.sleep(1)
    characteristic.write(b"read ppg 4\n")
    time.sleep(1)

    # 获取目标Notify特征及对应的CCCD
    svc = peripheral.getServiceByUUID("00001523-1212-efde-1523-785feabcd123")
    ch = svc.getCharacteristics("00001011-1212-efde-1523-785feabcd123")[0]
    ch_cccd = ch.getDescriptors(forUUID=0x2902)[0]
    
    # 写入正确的CCCD值启用Notify,添加withResponse确保写入成功
    ch_cccd.write(b"\x01\x00", withResponse=True)
    
    # 可选:验证CCCD设置结果
    # print("CCCD value after write:", ch_cccd.read())

    characteristic.write(b"read ppg 5\n")

    while True:
        if peripheral.waitForNotifications(1.0):
            continue
        print("Waiting...")

# 另一个模块中的Delegate类
class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        super().__init__()

    def handleNotification(self, cHandle, data):
        print(f"Notification received: handle = {cHandle}; Raw data = {binascii.b2a_hex(data)}")

额外验证步骤

  • 写入CCCD后,可通过ch_cccd.read()读取其值,确认结果为b'\x01\x00',说明Notify已成功启用。
  • 如果仍能收到handle:19的特征数据,可尝试禁用该特征的Notify:找到对应特征的CCCD,写入b"\x00\x00"即可关闭其通知功能。

内容的提问来源于stack exchange,提问作者Tommaso Ceredi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 06:45:37