Skip to content

jkbms not work on my bluetooth bms . can not read cell_info #557

@z1713299460

Description

@z1713299460

Model: JK-BD6A24S20P Hardware Version: V19A Software Version: V19.13

**I tried capturing the HCI log on my Android phone.
After test i realized the BMS communication process works like this:

To get cell_info It must have to send 3 command,Three commands must be sent. Not one can be omitted.

First start notify:**

    char_uuid =  "0000ffe1-0000-1000-8000-00805f9b34fb"
    characteristic = service.getCharacteristics(char_uuid)[0]
    # 启用通知
    notify_handle = characteristic.getHandle() + 1
    device.writeCharacteristic(notify_handle, b"\x01\x00", withResponse=True)

Second send a 0x97 command:

    print("发送电池信息命令(0x97)...")
    command_97 = bytearray(20)
    command_97[0:4] = [0xAA, 0x55, 0x90, 0xEB]  # 头部
    command_97[4] = 0x97  # 命令字节
    command_97[5] = 0x00  # 长度字节
    command_97[6:10] = [0x00, 0x00, 0x00, 0x00]  # 值
    command_97[10:19] = [0x00] * 9  # 填充
    command_97[19] = sum(command_97[0:19]) & 0xFF  # CRC
    send_jkbms_command(device, command_97)
    time.sleep(1)

Third send a 0x96 command,Normally, sending this command should allow you to read the cell_info which start with 55 AA EB 90 02. BUT actually NO,this command can only read hardware software version same as 0x97 and settings info.

    print("发送电池信息命令(0x96)...")
    command_96 = bytearray(20)
    command_96[0:4] = [0xAA, 0x55, 0x90, 0xEB]  # 头部
    command_96[4] = 0x96  # 命令字节
    command_96[5] = 0x00  # 长度字节
    command_96[6:10] = [0x00, 0x00, 0x00, 0x00]  # 值
    command_96[10:19] = [0x00] * 9  # 填充
    command_96[19] = sum(command_96[0:19]) & 0xFF  # CRC
    send_jkbms_command(device, command_96)

Fourth the crucial step:send a Mysterious command
start_command = bytes.fromhex("aa5590eb6c0000000000000000000000000000e6")
send_jkbms_command(device, start_command)

After ALL Three command send,we finally receive the cell_info which start with 55 AA EB 90 02.

i paste my full test code here,hope this help someone:

#!/usr/bin/env python3
import time
import datetime
from bluepy.btle import Peripheral, DefaultDelegate

class JKBMSCallback(DefaultDelegate):
def init(self, filename):
DefaultDelegate.init(self)
self.filename = filename
self.data_buffer = b""
self.frame_count = 0
self.at_count = 0
self.state = "WAITING_FOR_AT"

def handleNotification(self, cHandle, data):
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
    
    # 打印原始数据
    hex_data = ' '.join([f'{b:02X}' for b in data])
    print(f"[{timestamp}] Handle: {cHandle:04X}, Data ({len(data)} bytes): {hex_data}")
    
    # 保存到文件
    with open(self.filename, 'a', encoding='utf-8') as f:
        f.write(f"[{timestamp}] Handle: {cHandle:04X}, Data ({len(data)} bytes): {hex_data}\n")
    
    # 累积数据用于可能的后续分析
    self.data_buffer += data
    
    # 检测AT响应 (41 54 0D 0A)
    if data == b'\x41\x54\x0D\x0A':
        self.at_count += 1
        print(f"--- 收到第 {self.at_count} 次 AT 响应 ---")
    
    # 检测帧头,开始新的帧
    if len(data) >= 4 and data[0:4] == b'\x55\xAA\xEB\x90':
        self.frame_count += 1
        frame_type = data[4] if len(data) > 4 else "unknown"
        print(f"--- 检测到帧头,第 {self.frame_count} 帧,类型: 0x{frame_type:02X} ---")
    
    if len(self.data_buffer) > 1000:  # 限制缓冲区大小
        self.data_buffer = self.data_buffer[-1000:]

def send_jkbms_command(device, command_bytes):
"""
发送命令到JK BMS设备

Args:
    device: 已连接的设备对象
    command_bytes: 命令字节数组
"""
try:
    # 获取服务和特征
    service_uuid = "0000ffe0-0000-1000-8000-00805f9b34fb"
    service = device.getServiceByUUID(service_uuid)
    
    char_uuid = "0000ffe1-0000-1000-8000-00805f9b34fb"
    characteristic = service.getCharacteristics(char_uuid)[0]
    
    # 发送命令
    print(f"发送命令: {' '.join([f'{b:02X}' for b in command_bytes])}")
    characteristic.write(command_bytes, withResponse=True)
    print("命令发送完成")
    
except Exception as e:
    print(f"发送命令时发生错误: {e}")

def read_jkbms_data(mac_address, output_file="jkbms_data.txt"):
"""
读取JK BMS的蓝牙数据

Args:
    mac_address: BMS设备的MAC地址
    output_file: 输出文件名
"""

print(f"尝试连接JK BMS设备: {mac_address}")
print(f"数据将保存到: {output_file}")
print("按Ctrl+C停止读取\n")

# 清空或创建输出文件
with open(output_file, 'w', encoding='utf-8') as f:
    f.write(f"JK BMS数据记录 - 开始时间: {datetime.datetime.now()}\n")
    f.write(f"设备MAC: {mac_address}\n")
    f.write("=" * 50 + "\n")

try:
    # 连接设备
    device = Peripheral(mac_address)
    
    # 设置回调处理
    callback = JKBMSCallback(output_file)
    device.setDelegate(callback)
    
    # 获取服务
    service_uuid = "0000ffe0-0000-1000-8000-00805f9b34fb"
    service = device.getServiceByUUID(service_uuid)
    
    # 获取特征
    char_uuid = "0000ffe1-0000-1000-8000-00805f9b34fb"
    characteristic = service.getCharacteristics(char_uuid)[0]
    
    # 启用通知
    notify_handle = characteristic.getHandle() + 1
    device.writeCharacteristic(notify_handle, b"\x01\x00", withResponse=True)
    
    print("连接成功!")
    
    # 第一步:发送0x97命令
    print("发送电池信息命令(0x97)...")
    command_97 = bytearray(20)
    command_97[0:4] = [0xAA, 0x55, 0x90, 0xEB]  # 头部
    command_97[4] = 0x97  # 命令字节
    command_97[5] = 0x00  # 长度字节
    command_97[6:10] = [0x00, 0x00, 0x00, 0x00]  # 值
    command_97[10:19] = [0x00] * 9  # 填充
    command_97[19] = sum(command_97[0:19]) & 0xFF  # CRC
    send_jkbms_command(device, command_97)
    time.sleep(1)
    # 第二步:发送0x96命令
    print("发送电池信息命令(0x96)...")
    command_96 = bytearray(20)
    command_96[0:4] = [0xAA, 0x55, 0x90, 0xEB]  # 头部
    command_96[4] = 0x96  # 命令字节
    command_96[5] = 0x00  # 长度字节
    command_96[6:10] = [0x00, 0x00, 0x00, 0x00]  # 值
    command_96[10:19] = [0x00] * 9  # 填充
    command_96[19] = sum(command_96[0:19]) & 0xFF  # CRC
    send_jkbms_command(device, command_96)
    
    # 第二步:等待接收5次AT响应
    print("等待接收5次AT响应...")
    start_time = time.time()
    while callback.at_count < 10 and (time.time() - start_time) < 10:  # 最多等待10秒
        if device.waitForNotifications(1.0):
            continue
        time.sleep(0.1)
    
    if callback.at_count < 10:
        print(f"警告: 只收到 {callback.at_count} 次AT响应,可能无法正常启动数据流")
    else:
        print("已收到5次AT响应,准备发送启动命令")
    
    # 第三步:发送启动数据流命令
    print("发送启动数据流命令...")
    # 你提供的命令: aa5590eb6c04cc9ef80ad4d0528277751b994ab8
    start_command = bytes.fromhex("aa5590eb6c0000000000000000000000000000e6")
    send_jkbms_command(device, start_command)
    
    print("开始持续读取电池数据...")
    
    # 持续读取数据
    while True:
        if device.waitForNotifications(1.0):
            continue
        time.sleep(0.1)
            
except KeyboardInterrupt:
    print("\n用户中断,停止读取")
except Exception as e:
    print(f"发生错误: {e}")
finally:
    try:
        device.disconnect()
        print("已断开连接")
    except:
        pass

if name == "main":
# 你的设备MAC地址
MAC_ADDRESS = "Your JK-MBS MAC,may should pair first"

# 直接启动数据读取流程
read_jkbms_data(MAC_ADDRESS, "jkbms_raw_data.txt")

and my test data jkbms_raw_data.txt

`JK BMS数据记录 - 开始时间:

[2025-11-01 11:24:49.588] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.589] Handle: 000E, Data (20 bytes): 55 AA EB 90 03 10 4A 4B 2D 42 44 36 41 32 34 53 32 30 50 00
[2025-11-01 11:24:49.590] Handle: 000E, Data (20 bytes): 00 18 31 39 41 00 00 00 00 00 31 39 2E 31 33 00 00 00 B0 BC
[2025-11-01 11:24:49.590] Handle: 000E, Data (20 bytes): 0B 00 04 00 00 00 35 30 38 32 37 39 39 35 39 31 30 31 34 36
[2025-11-01 11:24:49.590] Handle: 000E, Data (20 bytes): 34 00 31 32 33 34 00 00 00 00 00 00 00 00 00 00 00 00 32 35
[2025-11-01 11:24:49.591] Handle: 000E, Data (20 bytes): 31 30 32 33 00 00 35 30 38 32 37 39 39 35 39 31 30 31 34 36
[2025-11-01 11:24:49.591] Handle: 000E, Data (20 bytes): 34 00 4A 4B 2D 42 4D 53 00 00 00 00 00 00 00 00 00 00 36 31
[2025-11-01 11:24:49.591] Handle: 000E, Data (20 bytes): 31 35 32 30 00 00 00 00 00 00 00 00 00 00 4A 4B 2D 42 4D 53
[2025-11-01 11:24:49.592] Handle: 000E, Data (10 bytes): 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.592] Handle: 000E, Data (20 bytes): FF FB FF FF 1F A9 0C 0E 00 00 00 00 90 1F 00 00 00 00 C0 D8
[2025-11-01 11:24:49.593] Handle: 000E, Data (20 bytes): E7 33 A4 00 00 00 00 00 00 00 00 00 00 00 01 00 FF 67 01 00
[2025-11-01 11:24:49.593] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 FF 0F 00 00 00 00 00 00
[2025-11-01 11:24:49.593] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 01 FF 67 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.594] Handle: 000E, Data (20 bytes): 00 00 00 00 09 08 00 01 64 00 00 00 5F 00 00 00 3C 00 00 00
[2025-11-01 11:24:49.594] Handle: 000E, Data (20 bytes): 32 00 00 00 00 00 00 00 00 00 00 00 10 0E 00 00 05 32 01 1E
[2025-11-01 11:24:49.594] Handle: 000E, Data (20 bytes): 0A 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 FE 9F 29
[2025-11-01 11:24:49.595] Handle: 000E, Data (10 bytes): 86 08 00 00 00 00 00 00 02 5F
[2025-11-01 11:24:49.595] Handle: 000E, Data (20 bytes): AA 55 90 EB C8 01 01 00 00 00 00 00 00 00 00 00 00 00 00 44
[2025-11-01 11:24:49.595] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.596] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.596] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.597] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.597] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.597] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.598] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.598] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.599] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.599] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.623] Handle: 000E, Data (20 bytes): 55 AA EB 90 01 10 C4 09 00 00 08 07 00 00 3A 07 00 00 8C 0A
[2025-11-01 11:24:49.623] Handle: 000E, Data (20 bytes): 00 00 50 0A 00 00 0A 00 00 00 5A 0A 00 00 30 07 00 00 5F 0A
[2025-11-01 11:24:49.624] Handle: 000E, Data (20 bytes): 00 00 F6 09 00 00 A4 06 00 00 90 5F 01 00 3C 00 00 00 3C 00
[2025-11-01 11:24:49.638] Handle: 000E, Data (20 bytes): 00 00 40 0D 03 00 2C 01 00 00 3C 00 00 00 05 00 00 00 58 02
[2025-11-01 11:24:49.640] Handle: 000E, Data (20 bytes): 00 00 BC 02 00 00 58 02 00 00 BC 02 00 00 58 02 00 00 9C FF
[2025-11-01 11:24:49.641] Handle: 000E, Data (20 bytes): FF FF 00 00 00 00 20 03 00 00 BC 02 00 00 14 00 00 00 01 00
[2025-11-01 11:24:49.641] Handle: 000E, Data (20 bytes): 00 00 01 00 00 00 01 00 00 00 30 75 00 00 05 00 00 00 D0 07
[2025-11-01 11:24:49.653] Handle: 000E, Data (10 bytes): 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.653] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.654] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.655] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.655] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.668] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.668] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.698] Handle: 000E, Data (20 bytes): 01 00 00 00 00 00 00 00 20 A1 07 00 90 10 F6 00 18 FE FB FF
[2025-11-01 11:24:49.698] Handle: 000E, Data (10 bytes): FF 1F A9 6C 0E 00 DD E2 00 80
[2025-11-01 11:24:49.699] Handle: 000E, Data (20 bytes): 55 AA EB 90 03 A5 4A 4B 2D 42 44 36 41 32 34 53 32 30 50 00
[2025-11-01 11:24:49.699] Handle: 000E, Data (20 bytes): 00 18 31 39 41 00 00 00 00 00 31 39 2E 31 33 00 00 00 B0 BC
[2025-11-01 11:24:49.700] Handle: 000E, Data (20 bytes): 0B 00 04 00 00 00 35 30 38 32 37 39 39 35 39 31 30 31 34 36
[2025-11-01 11:24:49.700] Handle: 000E, Data (20 bytes): 34 00 31 32 33 34 00 00 00 00 00 00 00 00 00 00 00 00 32 35
[2025-11-01 11:24:49.713] Handle: 000E, Data (20 bytes): 31 30 32 33 00 00 35 30 38 32 37 39 39 35 39 31 30 31 34 36
[2025-11-01 11:24:49.713] Handle: 000E, Data (20 bytes): 34 00 4A 4B 2D 42 4D 53 00 00 00 00 00 00 00 00 00 00 36 31
[2025-11-01 11:24:49.714] Handle: 000E, Data (20 bytes): 31 35 32 30 00 00 00 00 00 00 00 00 00 00 4A 4B 2D 42 4D 53
[2025-11-01 11:24:49.715] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 FF FB FF FF 1F A9 0C 0E 00 00
[2025-11-01 11:24:49.715] Handle: 000E, Data (20 bytes): 00 00 90 1F 00 00 00 00 C0 D8 E7 33 A4 00 00 00 00 00 00 00
[2025-11-01 11:24:49.728] Handle: 000E, Data (20 bytes): 00 00 00 00 01 00 FF 67 01 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.728] Handle: 000E, Data (20 bytes): 00 00 FF 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF
[2025-11-01 11:24:49.729] Handle: 000E, Data (20 bytes): 67 00 00 00 00 00 00 00 00 00 00 00 00 00 09 08 00 01 64 00
[2025-11-01 11:24:49.730] Handle: 000E, Data (20 bytes): 00 00 5F 00 00 00 3C 00 00 00 32 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.730] Handle: 000E, Data (20 bytes): 00 00 10 0E 00 00 05 32 01 1E 0A 00 00 00 00 00 00 00 01 00
[2025-11-01 11:24:49.743] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 FE 9F 29 86 08 00 00 00 00 00 00 02 F4
[2025-11-01 11:24:49.743] Handle: 000E, Data (20 bytes): AA 55 90 EB C8 01 01 00 00 00 00 00 00 00 00 00 00 00 00 44
[2025-11-01 11:24:49.744] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.851] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:49.953] Handle: 000E, Data (20 bytes): 55 AA EB 90 02 10 67 0A 64 0A 64 0A 62 0A 6A 0A 69 0A 66 0A
[2025-11-01 11:24:49.953] Handle: 000E, Data (20 bytes): 54 0A 69 0A 67 0A 5C 0A 5F 0A 67 0A 61 0A 69 0A 6A 0A 6A 0A
[2025-11-01 11:24:49.954] Handle: 000E, Data (20 bytes): 67 0A 65 0A 65 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.955] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 FF FF 0F 00 65 0A 18 00 09 07
[2025-11-01 11:24:49.968] Handle: 000E, Data (20 bytes): A0 00 98 00 A1 00 9E 00 9F 00 A1 00 A3 00 A3 00 A1 00 A2 00
[2025-11-01 11:24:49.969] Handle: 000E, Data (20 bytes): A3 00 A0 00 A0 00 9B 00 99 00 A1 00 A4 00 A3 00 A2 00 A4 00
[2025-11-01 11:24:49.970] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.970] Handle: 000E, Data (10 bytes): 00 00 00 00 EF 00 00 00 00 00
[2025-11-01 11:24:49.983] Handle: 000E, Data (20 bytes): EA CF 00 00 00 00 00 00 00 00 00 00 E9 00 E6 00 00 00 00 00
[2025-11-01 11:24:49.984] Handle: 000E, Data (20 bytes): 92 FE 02 64 2E 75 00 00 30 75 00 00 03 00 00 00 42 8F 01 00
[2025-11-01 11:24:49.985] Handle: 000E, Data (20 bytes): 64 00 00 00 A0 BD 0B 00 01 01 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:49.985] Handle: 000E, Data (20 bytes): 00 00 00 00 FF 00 01 00 00 00 01 00 00 00 00 00 A6 83 3F 40
[2025-11-01 11:24:49.998] Handle: 000E, Data (20 bytes): 00 00 00 00 CA 14 00 00 00 00 01 01 0C 06 01 00 03 61 75 00
[2025-11-01 11:24:49.998] Handle: 000E, Data (20 bytes): 00 00 00 00 EF 00 30 F8 30 F8 01 00 FD 0C FA 0A 50 00 00 00
[2025-11-01 11:24:49.999] Handle: 000E, Data (20 bytes): 80 51 01 00 00 02 00 01 00 00 00 00 00 00 00 00 00 FE FF 7F
[2025-11-01 11:24:50.000] Handle: 000E, Data (10 bytes): DC 0F 01 00 80 0B 01 00 00 8F
[2025-11-01 11:24:50.001] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:50.103] Handle: 000E, Data (4 bytes): 41 54 0D 0A
[2025-11-01 11:24:50.223] Handle: 000E, Data (20 bytes): 55 AA EB 90 02 11 67 0A 64 0A 64 0A 62 0A 6A 0A 69 0A 66 0A
[2025-11-01 11:24:50.224] Handle: 000E, Data (20 bytes): 54 0A 69 0A 67 0A 5E 0A 5F 0A 6C 0A 61 0A 67 0A 66 0A 6A 0A
[2025-11-01 11:24:50.225] Handle: 000E, Data (20 bytes): 67 0A 5F 0A 60 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:50.225] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 FF FF 0F 00 64 0A 18 00 09 07
[2025-11-01 11:24:50.238] Handle: 000E, Data (20 bytes): A0 00 98 00 A1 00 9E 00 9F 00 A1 00 A3 00 A3 00 A1 00 A2 00
[2025-11-01 11:24:50.238] Handle: 000E, Data (20 bytes): A3 00 A0 00 A0 00 9B 00 99 00 A1 00 A4 00 A3 00 A2 00 A4 00
[2025-11-01 11:24:50.241] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-11-01 11:24:50.241] Handle: 000E, Data (20 bytes): 00 00 00 00 EF 00 00 00 00 00 D6 CF 00 00 00 00 00 00 00 00
[2025-11-01 11:24:50.242] Handle: 000E, Data (20 bytes): 00 00 E9 00 E6 00 00 00 00 00 91 FE 02 64 2E 75 00 00 30 75
[2025-11-01 11:24:50.253] Handle: 000E, Data (20 bytes): 00 00 03 00 00 00 42 8F 01 00 64 00 00 00 A1 BD 0B 00 01 01
[2025-11-01 11:24:50.253] Handle: 000E, Data (20 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 01 00 00 00
[2025-11-01 11:24:50.254] Handle: 000E, Data (20 bytes): 01 00 00 00 00 00 A6 83 3F 40 E4 00 00 00 C8 14 00 00 00 00
[2025-11-01 11:24:50.255] Ha`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions