208 lines
7.5 KiB
Python
Raw Normal View History

2025-01-18 09:10:52 +08:00
import struct
import logging
import binascii
class Command30:
def __init__(self):
self.command = 0x30 # BMS状态信息命令
def parse_30h_bms_status(self, data):
"""
解析30H BMS状态需求报文
:param data: 完整的30H命令报文
:return: 解析后的字典或None
"""
try:
# 验证基本帧格式
if len(data) < 14 or data[0:2] != b'JX' or data[2] != 0x30:
logging.warning(f"30H命令帧格式不正确原始报文: {binascii.hexlify(data)}")
return None
# 打印完整的原始报文以便调试
print(f"完整原始报文: {binascii.hexlify(data)}")
# 提取桩号
pile_id_bytes = data[3:11]
# 提取时间标识
time_bytes = data[14:20]
year = time_bytes[0] + 2000
month, day, hour, minute, second = time_bytes[1:6]
timestamp = f"{year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}"
# 初始化解析索引
current_index = 20
# 解析电压需求
voltage_request = struct.unpack("<H", data[current_index:current_index + 2])[0] / 10 # 0.1V
current_index += 2
# 解析电流需求
current_request = struct.unpack("<H", data[current_index:current_index + 2])[0] / 10 # 0.1A
current_index += 2
# 解析充电模式
charging_mode = data[current_index]
current_index += 1
# 解析最高单体电压
max_cell_voltage = struct.unpack("<H", data[current_index:current_index + 2])[0] / 1000 # 0.001V
current_index += 2
# 解析最高单体电压所在电池组号
max_cell_group = data[current_index]
current_index += 1
# 解析SOC
soc = data[current_index]
current_index += 1
# 解析剩余充电时间
remaining_charging_time = struct.unpack("<H", data[current_index:current_index + 2])[0]
current_index += 2
# 解析最高单体电压电池组编号
max_voltage_group_number = data[current_index]
current_index += 1
# 解析最高动力蓄电池温度
max_battery_temperature = data[current_index] - 50 # 偏移量-50
current_index += 1
# 解析最高温度检测点编号
max_temperature_point = data[current_index]
current_index += 1
# 解析最低动力蓄电池温度
min_battery_temperature = data[current_index] - 50 # 偏移量-50
current_index += 1
# 解析最低温度监测点编号
min_temperature_point = data[current_index]
current_index += 1
# 解析告警信息
warning_bytes = data[current_index]
warnings = {
"单体电压过高/过低": (warning_bytes & 0x03),
"SOC过高/过低": ((warning_bytes >> 2) & 0x03),
"充电过流": ((warning_bytes >> 4) & 0x03),
"动力蓄电池温度过高": ((warning_bytes >> 6) & 0x03)
}
current_index += 1
# 打印解析结果
print("\n30H BMS状态需求报文解析结果:")
print(f"桩号: {pile_id_bytes.hex()}")
print(f"时间标识: {timestamp}")
print(f"电压需求: {voltage_request}V")
print(f"电流需求: {current_request}A")
print(f"充电模式: {self.get_charging_mode_text(charging_mode)}")
print(f"最高单体电压: {max_cell_voltage}V")
print(f"最高单体电压所在电池组号: {max_cell_group}")
print(f"SOC: {soc}%")
print(f"剩余充电时间: {remaining_charging_time}分钟")
print(f"最高单体电压电池组编号: {max_voltage_group_number}")
print(f"最高动力蓄电池温度: {max_battery_temperature}°C")
print(f"最高温度检测点编号: {max_temperature_point}")
print(f"最低动力蓄电池温度: {min_battery_temperature}°C")
print(f"最低温度监测点编号: {min_temperature_point}")
print("告警信息:")
for warning, level in warnings.items():
print(f" {warning}: {self.get_warning_level_text(level)}")
return {
"pile_id": pile_id_bytes.hex(),
"timestamp": timestamp,
"voltage_request": voltage_request,
"current_request": current_request,
"charging_mode": self.get_charging_mode_text(charging_mode),
"max_cell_voltage": max_cell_voltage,
"max_cell_group": max_cell_group,
"soc": soc,
"remaining_charging_time": remaining_charging_time,
"max_voltage_group_number": max_voltage_group_number,
"max_battery_temperature": max_battery_temperature,
"max_temperature_point": max_temperature_point,
"min_battery_temperature": min_battery_temperature,
"min_temperature_point": min_temperature_point,
"warnings": {k: self.get_warning_level_text(v) for k, v in warnings.items()}
}
except Exception as e:
logging.error(f"解析30H命令失败: {str(e)}")
logging.error(f"原始报文: {binascii.hexlify(data)}")
return None
def get_charging_mode_text(self, mode):
"""
解析充电模式
:param mode: 充电模式字节
:return: 充电模式文本描述
"""
mode_map = {
0x01: "恒流充电",
0x02: "恒压充电",
0x03: "涓流充电",
0x04: "充电完成",
0x05: "充电终止"
}
return mode_map.get(mode, f"未知模式 (0x{mode:02X})")
def get_warning_level_text(self, level):
"""
解析告警级别
:param level: 告警级别
:return: 告警级别文本描述
"""
level_map = {
0x00: "正常",
0x01: "预警",
0x02: "严重告警",
0x03: "故障"
}
return level_map.get(level, f"未知级别 (0x{level:02X})")
def process_30h_bms_status(self, data):
"""
处理30H BMS状态信息命令
:param data: 完整的30H命令报文
:return: 是否成功处理
"""
try:
parsed_data = self.parse_30h_bms_status(data)
if parsed_data is None:
logging.warning("30H命令解析失败")
return False
# 记录BMS状态信息日志
logging.info(
f"收到桩号 {parsed_data['pile_id']} 的BMS状态信息: "
f"SOC {parsed_data['soc']}%, "
f"电压需求 {parsed_data['voltage_request']}V, "
f"电流需求 {parsed_data['current_request']}A"
)
return True
except Exception as e:
logging.error(f"处理30H命令出错: {str(e)}")
return False
# 测试用例
if __name__ == "__main__":
# 30H命令测试报文
test_30_data = bytes.fromhex(
"4A 58 30 03 17 66 56 11 36 06 37 01 1C 00 19 01 09 0B 25 15 01 60 1B 8D 07 02 DA 07 A0 0F 4A C1 49 78 00 01 40 03 3C 05 00 10 64")
parser = Command30()
# 测试解析30H命令
parser.process_30h_bms_status(test_30_data)