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

树莓派4使用bluepy连接JK BMS设备失败,求排查原因

树莓派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.py
    
  • BLE地址类型不匹配
    部分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 up
    
  • bluepy版本兼容性问题
    尝试更新bluepy到最新稳定版本:

    pip3 install --upgrade bluepy
    

内容的提问来源于stack exchange,提问作者Døner M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:20:50