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

树莓派GATT Server向Android GATT Client传数据时代码报错求解

问题解决:bluepy中Service无addCharacteristic方法的错误

错误原因

bluepy的btle.Service类没有提供addCharacteristic或add_Characteristic方法,它通过内置的characteristics列表来管理下属特征。你之前的代码误用了不存在的方法,导致AttributeError。

修正方案

核心修改

将自定义Service类中的self.addCharacteristic(MyCharacteristic(self))替换为:

self.characteristics.append(MyCharacteristic(self))

完整修正代码

from bluepy.btle import Peripheral, UUID, DefaultDelegate, Characteristic, Service
import struct
import time
import uuid

# 定义服务和特征的UUID
SERVICE_UUID = uuid.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
CHARACTERISTIC_UUID = uuid.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")

# 回调处理类:处理来自Android设备的通知
class MyDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        print("收到Android设备数据:", data)

# 自定义特征类:实现读、写逻辑
class MyCharacteristic(Characteristic):
    def __init__(self, service):
        # 配置特征属性:支持读、写、通知
        Characteristic.__init__(self, CHARACTERISTIC_UUID, 
                               Characteristic.PROP_READ | Characteristic.PROP_WRITE | Characteristic.PROP_NOTIFY,
                               service)
        self.data = b"Hello, Android!"  # 初始数据

    def read(self):
        # 处理Android设备的读请求
        return self.data

    def write(self, value):
        # 处理Android设备的写请求
        self.data = value
        print("收到写入数据:", value)

# 自定义服务类
class MyService(Service):
    def __init__(self, peripheral):
        Service.__init__(self, peripheral, SERVICE_UUID, primary=True)
        # 将特征添加到服务的特征列表中
        self.characteristics.append(MyCharacteristic(self))

# 主程序逻辑
if __name__ == "__main__":
    # 创建GATT Server实例
    peripheral = Peripheral()
    peripheral.setDelegate(MyDelegate())  # 绑定回调处理

    # 注册自定义服务
    service = MyService(peripheral)
    peripheral.setServices([service])

    # 构造广播数据:携带128位服务UUID,让Android设备能扫描到
    AD_TYPE_128_BIT_UUID = 0x07
    adv_data = struct.pack("BB", AD_TYPE_128_BIT_UUID, 16) + SERVICE_UUID.bytes_le
    peripheral.setAdvertisingData(adv_data)
    peripheral.setAdvertisingInterval(1000)
    peripheral.startAdvertising()

    print("树莓派GATT Server已启动,等待Android设备连接...")

    try:
        target_char = peripheral.getCharacteristics(uuid=CHARACTERISTIC_UUID)[0]
        while True:
            # 等待通知,超时1秒
            if peripheral.waitForNotifications(1.0):
                continue
            # 可选:定时推送分析后的数据到Android设备
            # target_char.write(b"分析结果: " + str(time.time()).encode())
            time.sleep(1)
    except KeyboardInterrupt:
        print("停止服务")
        peripheral.stopAdvertising()
        peripheral.disconnect()

其他关键修改说明

  1. 移除重复Peripheral实例:原代码中创建了两个Peripheral对象,导致广播配置和服务注册分离,现在统一为一个实例。
  2. 规范特征属性配置:使用bluepy内置的Characteristic.PROP_*常量定义特征权限,比字符串列表更符合API规范。
  3. 修复广播数据:使用0x07类型(128位UUID)构造广播数据,确保Android设备能识别自定义服务。
  4. 绑定Delegate:将回调类绑定到Peripheral,才能处理来自Android设备的通知。
  5. 调整数据推送逻辑:将数据写入代码放到循环中(注释部分),模拟定时推送分析结果,避免原代码中永远无法执行的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:32:35