树莓派4使用bluepy连接JK BMS设备失败,求排查原因
我尝试用以下基于bluepy库的Python代码,从树莓派4连接JK BMS设备:
from bluepy import btle import time import codecs import logging import bmsstate OUTGOING_HEADER = b'\xaa\x55\x90\xeb' INCOMING_HEADER = b'\x55\xaa\xeb\x90' MAX_COMMAND_TIMEOUT_SECONDS = 5 MAX_STATE_LIFE_SECCONDS = 5 COMMAND_REQ_EXTENDED_RECORD = 0x96 COMMAND_REQ_DEVICE_INFO = 0x97 COMMAND_REQ_CHARGE_SWITCH = 0x1d COMMAND_REQ_DISCHARGE_SWITCH = 0x1e RESPONSE_ACK = 0xc8 RESPONSE_EXTENDED_RECORD = 0x01 RESPONSE_CELL_DATA = 0x02 RESPONSE_DEVICE_INFO_RECORD = 0x03 class JkBMS(btle.DefaultDelegate): def __init__(self, bt_mac): btle.DefaultDelegate.__init__(self) self.bt_mac = bt_mac self.name = bt_mac self.connected = False def logDebug(self, text): logging.debug(f'JkBMS {self.name}: {text}') def logInfo(self, text): logging.info(f'JkBMS {self.name}: {text}') def logWarn(self, text): logging.warning(f'JkBMS {self.name}: {text}') def logError(self, text): logging.error(f'JkBMS {self.name}: {text}') def initialize(self): self.sendCommand(COMMAND_REQ_DEVICE_INFO) self.sendCommand(COMMAND_REQ_EXTENDED_RECORD) def connect(self): if self.connected: return self.incomingData = bytearray() self.device = btle.Peripheral(None) self.device.withDelegate(self) attempts = 0 conn = False while not conn: attempts += 1 if attempts > 2: self.logError(f'cannot connect to JK BMS at {self.bt_mac}') exit() try: self.device.connect(self.bt_mac) conn = True except Exception as err: self.logError(f'connection failed to {self.bt_mac}, re-try') print(f"Unexpected {err=}, {type(err)=}") time.sleep(1) continue JK_BMS_MAC3 = "C8:47:8C:E4:57:FB" jkbms3 = jkbms.JkBMS(JK_BMS_MAC3) jkbms3.initialize()
但代码执行时抛出异常,无法建立连接,错误信息如下:
ERROR:root:JkBMS C8:47:8C:E4:57:FB: connection failed to
C8:47:8C:E4:57:FB, re-try Unexpected err=BTLEDisconnectError('Failed
to connect to peripheral C8:47:8C:E4:57:FB, addr type: public',
{'rsp': ['stat'], 'state': ['disc'], 'mtu': [0], 'sec': ['low']}),
type(err)=<class 'bluepy.btle.BTLEDisconnectError'>
我确认设备MAC地址(C8:47:8C:E4:57:FB)正确,通过sudo hcitool lescan可扫描到该设备,且手机端能正常连接该设备,请问问题出在哪里?
问题排查与解决方案
代码逻辑错误:未先执行连接操作
代码直接调用initialize(),但该方法依赖已建立的BLE连接,且未提前调用connect()方法。同时最后一行的jkbms.JkBMS存在错误(类在当前模块定义,无需前缀),修正后的代码结尾应为:JK_BMS_MAC3 = "C8:47:8C:E4:57:FB" jkbms3 = JkBMS(JK_BMS_MAC3) jkbms3.connect() jkbms3.initialize()蓝牙权限不足
bluepy操作BLE设备需要root权限,运行代码时必须加上sudo:sudo python3 your_script_name.pyBLE地址类型不匹配
部分JK BMS设备使用随机地址类型而非默认的public类型,可尝试修改connect方法中的连接语句,指定地址类型:self.device.connect(self.bt_mac, addrType=btle.ADDR_TYPE_RANDOM)若不确定地址类型,可先用扫描代码确认:
from bluepy import btle scanner = btle.Scanner() devices = scanner.scan(10) for dev in devices: if dev.addr == "C8:47:8C:E4:57:FB": print(f"设备地址类型:{dev.addrType}")树莓派蓝牙适配器状态异常
重启蓝牙服务或重置蓝牙适配器:sudo systemctl restart bluetooth # 或者重置适配器 sudo hciconfig hci0 down sudo hciconfig hci0 upbluepy版本兼容性问题
尝试更新bluepy到最新稳定版本:pip3 install --upgrade bluepy
内容的提问来源于stack exchange,提问作者Døner M.

