增加了info字段,增加了上电检测,调整了绝缘电阻上报逻辑
This commit is contained in:
@@ -3,6 +3,7 @@ from tkinter import ttk
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
import struct
|
||||
from db import DB
|
||||
import os
|
||||
from udpMsg import (
|
||||
@@ -15,6 +16,10 @@ from udpMsg import (
|
||||
msg_disLVMBCmdMsg,
|
||||
msg_disLVBCmdMsg
|
||||
)
|
||||
from ccuMsg import (
|
||||
msg_ccUFbMsg,
|
||||
# msg_ccUCmdMsg
|
||||
)
|
||||
|
||||
class PowerManagerApp:
|
||||
def __init__(self, root):
|
||||
@@ -32,6 +37,7 @@ class PowerManagerApp:
|
||||
self.simulation_HVBACmdMsg = msg_disHVBACmdMsg()
|
||||
self.simulation_LVMBCmdMsg = msg_disLVMBCmdMsg()
|
||||
self.simulation_LVBCmdMsg = msg_disLVBCmdMsg()
|
||||
self.simulation_ccUFbMsg = msg_ccUFbMsg()
|
||||
|
||||
# 菜单栏复选框状态变量
|
||||
self.menu_checkbox_vars = {
|
||||
@@ -1774,27 +1780,33 @@ class PowerManagerApp:
|
||||
# time.sleep(0.1) # 1秒间隔
|
||||
# 处理高压母线数据
|
||||
packed_data = self.simulation_HighVolBusFbMsg.pack()
|
||||
error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(error_packed_data, self.udp_ip, self.udp_control_port)
|
||||
# time.sleep(0.1)
|
||||
# error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01)
|
||||
|
||||
# 处理高压A母线数据
|
||||
packed_data = self.simulation_HighAVolBusFbMsg.pack()
|
||||
error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(error_packed_data, self.udp_ip, self.udp_control_port)
|
||||
# time.sleep(0.01)
|
||||
# error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01)
|
||||
|
||||
# 处理低压母线数据
|
||||
packed_data = self.simulation_LowBusFbMsg.pack()
|
||||
error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(error_packed_data, self.udp_ip, self.udp_control_port)
|
||||
# time.sleep(0.01)
|
||||
# error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01)
|
||||
|
||||
# 处理仪表主母线数据
|
||||
packed_data = self.simulation_LowMainBusFbMsg.pack()
|
||||
error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(error_packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01) # 1秒间隔
|
||||
# error_packed_data = packed_data[:-1] + b'\x00' # 修改校验位为0x00
|
||||
self.send_udp_command(packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01)
|
||||
|
||||
packed_data = self.simulation_ccUFbMsg.pack()
|
||||
self.send_udp_command(packed_data, self.udp_ip, self.udp_control_port)
|
||||
time.sleep(0.01)
|
||||
|
||||
time.sleep(0.7) # 循环间隔
|
||||
def on_connection_changed(self, *args):
|
||||
"""连接状态改变回调"""
|
||||
if self.Start_Connection.get():
|
||||
|
||||
+218
-398
@@ -3,152 +3,150 @@ import datetime
|
||||
|
||||
class msg_ccUFbMsg:
|
||||
def __init__(self):
|
||||
# 消息头
|
||||
# 消息头 - 对应C++中的m_header
|
||||
self.start1 = 0x20
|
||||
self.start2 = 0x20
|
||||
self.id = 0x0051 # CCU_STATE_FB_ID
|
||||
self.length = 0
|
||||
self.checkCode = 0x00
|
||||
self.checkCode = 0 # 使用4字节校验码,对应C++中的Checksum (unsigned int)
|
||||
|
||||
# CCU状态数据 - 根据ccuState结构体定义
|
||||
self.fc_mode = 0x00
|
||||
self.fc_status = 0x00
|
||||
self.fc_fault_level = 0x00
|
||||
# CCU状态数据 - 完全对应C++中的ccuState结构体
|
||||
self.fc_mode = 0x00 # 燃料电池系统运行模式:00H-无效, 01H-调试, 02H-自动, 03H-补给
|
||||
self.fc_status = 0x00 # 燃料电池状态:00H-无效, 01H-初始化, ..., 0DH-维护完成
|
||||
self.fc_fault_level = 0x00 # 燃料电池故障等级:00H-无故障, 10H-一级, 20H-二级, 30H-三级, 40H-四级
|
||||
|
||||
self.output_power_limit = 0 # 系统输出功率限制值,单位:W,范围:0~30000W
|
||||
self.total_generation_time = 0 # 系统累计发电时间,单位:0.1小时,最大值6553.5小时
|
||||
self.total_generation_power = 0 # 系统累计发电总功率,单位:W
|
||||
self.fault_level_1 = 0 # 一级故障位,按位表示不同的故障项
|
||||
self.fault_level_2 = 0 # 二级故障位
|
||||
self.fault_level_3 = 0 # 三级故障位
|
||||
self.fault_level_4 = 0 # 四级故障位
|
||||
|
||||
self.hydrogen_capacity = 0 # 储氢罐剩余容量百分比,单位:%,范围:0~100
|
||||
self.liquid_oxygen_capacity = 0 # 液氧罐剩余容量百分比,单位:%,范围:0~100
|
||||
|
||||
self.palladium_temp = 0 # 钯膜最高温度,单位:℃
|
||||
self.main_pipe_pressure = 0 # 主水路压力,单位:0.01kPa
|
||||
self.aux_pipe_pressure = 0 # 辅水路压力,单位:0.01kPa
|
||||
|
||||
self.cabin_pressure1 = 0 # 舱室1压力,单位:0.01kPa
|
||||
self.cabin_pressure2 = 0 # 舱室2压力,单位:0.01kPa
|
||||
self.cabin_temp1 = 0 # 舱室1温度,单位:0.01℃
|
||||
self.cabin_temp2 = 0 # 舱室2温度,单位:0.01℃
|
||||
self.cabin_humidity1 = 0 # 舱室1湿度,单位:0.01%RH
|
||||
self.cabin_humidity2 = 0 # 舱室2湿度,单位:0.01%RH
|
||||
|
||||
self.flame_detector1 = 0x00 # 火焰探测器1状态:00H-无效, 01H-报警, 02H-故障
|
||||
self.flame_detector2 = 0x00 # 火焰探测器2状态:00H-无效, 01H-报警, 02H-故障
|
||||
|
||||
self.h2_concentration1 = 0 # 舱室H2浓度1,单位:0.01% LEL
|
||||
self.h2_concentration2 = 0 # 舱室H2浓度2,单位:0.01% LEL
|
||||
self.h2_concentration3 = 0 # 舱室H2浓度3,单位:0.01% LEL
|
||||
self.o2_concentration1 = 0 # 舱室O2浓度1,单位:0.01% LEL
|
||||
self.o2_concentration2 = 0 # 舱室O2浓度2,单位:0.01% LEL
|
||||
self.ch3oh_concentration1 = 0 # 舱室甲醇气体浓度1,单位:0.01% LEL
|
||||
self.ch3oh_concentration2 = 0 # 舱室甲醇气体浓度2,单位:0.01% LEL
|
||||
|
||||
self.reserved1 = [0, 0] # 保留字段前2个元素
|
||||
self.emergency_battery1_voltage = 0 # 应急电池1总电压 [V]
|
||||
self.emergency_battery1_current = 0 # 应急电池1总电流 [A]
|
||||
self.emergency_battery1_max_temp = 0 # 应急电池1最高温度 [°C]
|
||||
self.emergency_battery1_fault_word = 0 # 应急电池1故障字
|
||||
self.emergency_battery2_voltage = 0 # 应急电池2总电压 [V]
|
||||
self.emergency_battery2_current = 0 # 应急电池2总电流 [A]
|
||||
self.emergency_battery2_max_temp = 0 # 应急电池2最高温度 [°C]
|
||||
self.emergency_battery2_fault_word = 0 # 应急电池2故障字
|
||||
|
||||
self.output_power_limit = 0
|
||||
self.total_generation_time = 0
|
||||
self.total_generation_power = 0
|
||||
self.fault_level_1 = 0
|
||||
self.fault_level_2 = 0
|
||||
self.fault_level_3 = 0
|
||||
self.fault_level_4 = 0
|
||||
self.cabin_ox_concentration = 0 # 仪表舱内氧气浓度 [%]
|
||||
self.cabin_temperature = 0 # 仪表舱内温度 [°C]
|
||||
self.cabin_humidity = 0 # 仪表舱内湿度 [%RH]
|
||||
self.cabin_pressure = 0 # 仪表舱内大气压 [kPa]
|
||||
|
||||
self.power_cabin_ox_concentration = 0 # 动力舱内氧气浓度 [%]
|
||||
self.power_cabin_temperature = 0 # 动力舱内温度 [°C]
|
||||
self.power_cabin_humidity = 0 # 动力舱内湿度 [%RH]
|
||||
self.power_cabin_pressure = 0 # 动力舱内大气压 [kPa]
|
||||
self.reserved2 = [0] # 保留字段,地址范围54~55,共2个uint8_t,协议预留
|
||||
|
||||
self.dyn_alarm_flag = [0] * 6 # 动力锂电池报警标志字数组,共6字节,按位表示各类报警
|
||||
self.ins_alarm_flag = [0] * 6 # 仪表锂电池报警标志字数组,共6字节,按位表示各类报警
|
||||
|
||||
self.ins_relay_status1 = 0x00 # 仪表电池继电器状态,高4位表示正极继电器,低4位表示充电继电器
|
||||
self.ins_relay_status2 = 0x00 # 仪表电池预充继电器和负极继电器状态
|
||||
self.dyn_relay_status1 = 0x00 # 动力电池正极与充电继电器状态
|
||||
self.dyn_relay_status2 = 0x00 # 动力电池预充与负极继电器状态
|
||||
|
||||
self.ins_max_discharge_power = 0 # 仪表电池最大允许放电功率,单位:kW,精度0.05kW
|
||||
self.dyn_max_discharge_power = 0 # 动力电池最大允许放电功率,单位:kW,精度0.05kW
|
||||
|
||||
self.ins_soc = 0 # 仪表锂电池荷电状态SOC,范围:0~100
|
||||
self.dyn_soc = 0 # 动力锂电池荷电状态SOC,范围:0~100
|
||||
|
||||
self.ins_total_energy = 0 # 仪表电池总能量,单位:kWh
|
||||
self.dyn_total_energy = 0 # 动力电池总能量,单位:kWh
|
||||
|
||||
self.ins_power_input = 0 # 仪表电池输入功率,单位:kW
|
||||
self.dyn_power_input = 0 # 动力电池输入功率,单位:kW
|
||||
|
||||
self.ins_charge_status = 0x00 # 仪表电池充放电状态:00H-无效,10H-充电,20H-放电
|
||||
self.dyn_charge_status = 0x00 # 动力电池充放电状态:00H-无效,10H-充电,20H-放电
|
||||
|
||||
self.ins_voltage_link = 0 # 仪表电池LINK端电压,单位:0.01V
|
||||
self.ins_voltage_pack = 0 # 仪表电池PACK端电压,单位:0.01V
|
||||
self.ins_current = 0 # 仪表电池电流,单位:0.01A(正值放电)
|
||||
self.ins_resistance_pos = 0 # 仪表电池正极绝缘电阻,单位:kΩ
|
||||
self.ins_resistance_neg = 0 # 仪表电池负极绝缘电阻,单位:kΩ
|
||||
|
||||
self.dyn_voltage_link = 0 # 动力电池LINK端电压,单位:0.01V
|
||||
self.dyn_voltage_pack = 0 # 动力电池PACK端电压,单位:0.01V
|
||||
self.dyn_current = 0 # 动力电池电流,单位:0.01A(正值放电)
|
||||
self.dyn_resistance_pos = 0 # 动力电池正极绝缘电阻,单位:kΩ
|
||||
self.dyn_resistance_neg = 0 # 动力电池负极绝缘电阻,单位:kΩ
|
||||
|
||||
self.ins_emergency_status = 0x00 # 仪表电池紧急状态字,按位表示异常或告警状态
|
||||
self.dyn_emergency_status = 0x00 # 动力电池紧急状态字,按位表示异常或告警状态
|
||||
|
||||
self.reserved3 = [0] * 2 # 保留字节,协议预留
|
||||
|
||||
self.ins_soc_threshold1 = 0 # 仪表电池1 SOC门限,范围:0~100
|
||||
self.ins_soc_threshold2 = 0 # 仪表电池2 SOC门限,范围:0~100
|
||||
self.ins_soc_threshold3 = 0 # 仪表电池3 SOC门限,范围:0~100
|
||||
self.dyn_soc_threshold1 = 0 # 动力电池1 SOC门限,范围:0~100
|
||||
self.dyn_soc_threshold2 = 0 # 动力电池2 SOC门限,范围:0~100
|
||||
self.dyn_soc_threshold3 = 0 # 动力电池3 SOC门限,范围:0~100
|
||||
|
||||
self.ins_power_limit1 = 0 # 仪表电池1功率限制值,单位:%
|
||||
self.ins_power_limit2 = 0 # 仪表电池2功率限制值,单位:%
|
||||
self.dyn_power_limit1 = 0 # 动力电池1功率限制值,单位:%
|
||||
self.dyn_power_limit2 = 0 # 动力电池2功率限制值,单位:%
|
||||
|
||||
self.device_online_flag1 = 0 # 设备在线状态标志1,byte0:低压配电板在线标志位 byte1:复合管控主机在线标志位 byte2:复合管控备机在线标志位
|
||||
self.device_online_flag2 = 0 # 设备在线状态标志2,byte0:仪表锂电在线标志位 byte1:动力锂电在线标志位 byte2:燃电锂电在线标志位 byte3:高压配电板在线标志位
|
||||
|
||||
self.hydrogen_capacity = 0
|
||||
self.liquid_oxygen_capacity = 0
|
||||
|
||||
self.palladium_temp = 0
|
||||
self.main_pipe_pressure = 0
|
||||
self.aux_pipe_pressure = 0
|
||||
|
||||
self.cabin_pressure1 = 0
|
||||
self.cabin_pressure2 = 0
|
||||
self.cabin_temp1 = 0
|
||||
self.cabin_temp2 = 0
|
||||
self.cabin_humidity1 = 0
|
||||
self.cabin_humidity2 = 0
|
||||
|
||||
self.flame_detector1 = 0x00
|
||||
self.flame_detector2 = 0x00
|
||||
|
||||
self.h2_concentration1 = 0
|
||||
self.h2_concentration2 = 0
|
||||
self.h2_concentration3 = 0
|
||||
self.o2_concentration1 = 0
|
||||
self.o2_concentration2 = 0
|
||||
self.ch3oh_concentration1 = 0
|
||||
self.ch3oh_concentration2 = 0
|
||||
|
||||
self.reserved1 = [0, 0]
|
||||
self.emergency_battery1_voltage = 0
|
||||
self.emergency_battery1_current = 0
|
||||
self.emergency_battery1_max_temp = 0
|
||||
self.emergency_battery1_fault_word = 0
|
||||
self.emergency_battery2_voltage = 0
|
||||
self.emergency_battery2_current = 0
|
||||
self.emergency_battery2_max_temp = 0
|
||||
self.emergency_battery2_fault_word = 0
|
||||
|
||||
self.cabin_ox_concentration = 0
|
||||
self.cabin_temperature = 0
|
||||
self.cabin_humidity = 0
|
||||
self.cabin_pressure = 0
|
||||
|
||||
self.power_cabin_ox_concentration = 0
|
||||
self.power_cabin_temperature = 0
|
||||
self.power_cabin_humidity = 0
|
||||
self.power_cabin_pressure = 0
|
||||
self.reserved2 = [0]
|
||||
|
||||
self.dyn_alarm_flag = [0] * 6
|
||||
self.ins_alarm_flag = [0] * 6
|
||||
|
||||
self.ins_relay_status1 = 0x00
|
||||
self.ins_relay_status2 = 0x00
|
||||
self.dyn_relay_status1 = 0x00
|
||||
self.dyn_relay_status2 = 0x00
|
||||
|
||||
self.ins_max_discharge_power = 0
|
||||
self.dyn_max_discharge_power = 0
|
||||
|
||||
self.ins_soc = 0
|
||||
self.dyn_soc = 0
|
||||
|
||||
self.ins_total_energy = 0
|
||||
self.dyn_total_energy = 0
|
||||
|
||||
self.ins_power_input = 0
|
||||
self.dyn_power_input = 0
|
||||
|
||||
self.ins_charge_status = 0x00
|
||||
self.dyn_charge_status = 0x00
|
||||
|
||||
self.ins_voltage_link = 0
|
||||
self.ins_voltage_pack = 0
|
||||
self.ins_current = 0
|
||||
self.ins_resistance_pos = 0
|
||||
self.ins_resistance_neg = 0
|
||||
|
||||
self.dyn_voltage_link = 0
|
||||
self.dyn_voltage_pack = 0
|
||||
self.dyn_current = 0
|
||||
self.dyn_resistance_pos = 0
|
||||
self.dyn_resistance_neg = 0
|
||||
|
||||
self.ins_emergency_status = 0x00
|
||||
self.dyn_emergency_status = 0x00
|
||||
|
||||
self.reserved3 = [0] * 2
|
||||
|
||||
self.ins_soc_threshold1 = 0
|
||||
self.ins_soc_threshold2 = 0
|
||||
self.ins_soc_threshold3 = 0
|
||||
self.dyn_soc_threshold1 = 0
|
||||
self.dyn_soc_threshold2 = 0
|
||||
self.dyn_soc_threshold3 = 0
|
||||
|
||||
self.ins_power_limit1 = 0
|
||||
self.ins_power_limit2 = 0
|
||||
self.dyn_power_limit1 = 0
|
||||
self.dyn_power_limit2 = 0
|
||||
|
||||
self.device_online_flag1 = 0
|
||||
self.device_online_flag2 = 0
|
||||
|
||||
self.dyn_charge_level = 0x00
|
||||
self.dyn_water_leak_status = 0x00
|
||||
self.ins_water_leak_dcdc_status = 0x00
|
||||
self.dyn_charge_level = 0x00 # 动力电池充电状态:01H-1级(不限), 02H-2级(限功率), 03H-3级(关闭)
|
||||
self.dyn_water_leak_status = 0x00 # 动力漏水状态:0XH-正常, 1XH-异常漏水
|
||||
self.ins_water_leak_dcdc_status = 0x00 # 仪表漏水状态与DCDC状态:低4位-漏水状态(0XH正常,1XH异常),高4位-DCDC状态(X0H正常,X1H故障)
|
||||
self.reserved4 = 0x00
|
||||
self.heartbeat = 0
|
||||
self.heartbeat = 0 # 主机心跳计数器或标志值
|
||||
|
||||
def pack(self):
|
||||
"""打包消息为字节数据"""
|
||||
"""打包消息为字节数据 - 完全对应C++中的msg_CcuStateFbMsg结构体"""
|
||||
# 重置校验码
|
||||
self.checkCode = 0x00
|
||||
self.checkCode = 0
|
||||
|
||||
# 打包消息头
|
||||
data = struct.pack('<BBHH',
|
||||
self.start1,
|
||||
self.start2,
|
||||
self.id,
|
||||
self.length)
|
||||
# 首先打包CCU状态数据(不包括消息头和校验码)
|
||||
body_data = b''
|
||||
|
||||
# 打包CCU状态数据
|
||||
data += struct.pack('<BBB',
|
||||
# 打包CCU状态数据 - 完全对应C++中的ccuState结构体
|
||||
# 第一部分:基本状态
|
||||
body_data += struct.pack('<BBB',
|
||||
self.fc_mode,
|
||||
self.fc_status,
|
||||
self.fc_fault_level)
|
||||
|
||||
data += struct.pack('<HHHHHHH',
|
||||
# 第二部分:功率和时间
|
||||
body_data += struct.pack('<HHHHHHH',
|
||||
self.output_power_limit,
|
||||
self.total_generation_time,
|
||||
self.total_generation_power,
|
||||
@@ -157,16 +155,19 @@ class msg_ccUFbMsg:
|
||||
self.fault_level_3,
|
||||
self.fault_level_4)
|
||||
|
||||
data += struct.pack('<BB',
|
||||
# 第三部分:容量
|
||||
body_data += struct.pack('<BB',
|
||||
self.hydrogen_capacity,
|
||||
self.liquid_oxygen_capacity)
|
||||
|
||||
data += struct.pack('<HHH',
|
||||
# 第四部分:温度和压力
|
||||
body_data += struct.pack('<HHH',
|
||||
self.palladium_temp,
|
||||
self.main_pipe_pressure,
|
||||
self.aux_pipe_pressure)
|
||||
|
||||
data += struct.pack('<HHHHHH',
|
||||
# 第五部分:舱室环境
|
||||
body_data += struct.pack('<HHHHHH',
|
||||
self.cabin_pressure1,
|
||||
self.cabin_pressure2,
|
||||
self.cabin_temp1,
|
||||
@@ -174,11 +175,13 @@ class msg_ccUFbMsg:
|
||||
self.cabin_humidity1,
|
||||
self.cabin_humidity2)
|
||||
|
||||
data += struct.pack('<BB',
|
||||
# 第六部分:火焰探测器
|
||||
body_data += struct.pack('<BB',
|
||||
self.flame_detector1,
|
||||
self.flame_detector2)
|
||||
|
||||
data += struct.pack('<HHHHHHH',
|
||||
# 第七部分:气体浓度
|
||||
body_data += struct.pack('<HHHHHHH',
|
||||
self.h2_concentration1,
|
||||
self.h2_concentration2,
|
||||
self.h2_concentration3,
|
||||
@@ -187,8 +190,8 @@ class msg_ccUFbMsg:
|
||||
self.ch3oh_concentration1,
|
||||
self.ch3oh_concentration2)
|
||||
|
||||
# 保留字段和应急电池数据
|
||||
data += struct.pack('<HHHHHHHH',
|
||||
# 第八部分:保留字段和应急电池数据
|
||||
body_data += struct.pack('<HHHHHHHH',
|
||||
self.reserved1[0], self.reserved1[1],
|
||||
self.emergency_battery1_voltage,
|
||||
self.emergency_battery1_current,
|
||||
@@ -197,13 +200,14 @@ class msg_ccUFbMsg:
|
||||
self.emergency_battery2_voltage,
|
||||
self.emergency_battery2_current)
|
||||
|
||||
data += struct.pack('<HHHH',
|
||||
body_data += struct.pack('<HHHH',
|
||||
self.emergency_battery2_max_temp,
|
||||
self.emergency_battery2_fault_word,
|
||||
self.cabin_ox_concentration,
|
||||
self.cabin_temperature)
|
||||
|
||||
data += struct.pack('<HHHHHHHH',
|
||||
# 第九部分:舱室环境2
|
||||
body_data += struct.pack('<HHHHHHHH',
|
||||
self.cabin_humidity,
|
||||
self.cabin_pressure,
|
||||
self.power_cabin_ox_concentration,
|
||||
@@ -212,21 +216,21 @@ class msg_ccUFbMsg:
|
||||
self.power_cabin_pressure,
|
||||
self.reserved2[0], 0) # 填充第二个reserved2字节
|
||||
|
||||
# 报警标志数组
|
||||
# 第十部分:报警标志数组
|
||||
for flag in self.dyn_alarm_flag:
|
||||
data += struct.pack('<B', flag)
|
||||
body_data += struct.pack('<B', flag)
|
||||
for flag in self.ins_alarm_flag:
|
||||
data += struct.pack('<B', flag)
|
||||
body_data += struct.pack('<B', flag)
|
||||
|
||||
# 继电器状态
|
||||
data += struct.pack('<BBBB',
|
||||
# 第十一部分:继电器状态
|
||||
body_data += struct.pack('<BBBB',
|
||||
self.ins_relay_status1,
|
||||
self.ins_relay_status2,
|
||||
self.dyn_relay_status1,
|
||||
self.dyn_relay_status2)
|
||||
|
||||
# 功率和SOC数据
|
||||
data += struct.pack('<HHBBHHHH',
|
||||
# 第十二部分:功率和SOC数据
|
||||
body_data += struct.pack('<HHBBHHHH',
|
||||
self.ins_max_discharge_power,
|
||||
self.dyn_max_discharge_power,
|
||||
self.ins_soc,
|
||||
@@ -236,13 +240,13 @@ class msg_ccUFbMsg:
|
||||
self.ins_power_input,
|
||||
self.dyn_power_input)
|
||||
|
||||
# 充电状态
|
||||
data += struct.pack('<BB',
|
||||
# 第十三部分:充电状态
|
||||
body_data += struct.pack('<BB',
|
||||
self.ins_charge_status,
|
||||
self.dyn_charge_status)
|
||||
|
||||
# 电压电流和绝缘电阻
|
||||
data += struct.pack('<HHHHHHHHHH',
|
||||
# 第十四部分:电压电流和绝缘电阻
|
||||
body_data += struct.pack('<HHHHHHHHHH',
|
||||
self.ins_voltage_link,
|
||||
self.ins_voltage_pack,
|
||||
self.ins_current,
|
||||
@@ -254,16 +258,16 @@ class msg_ccUFbMsg:
|
||||
self.dyn_resistance_pos,
|
||||
self.dyn_resistance_neg)
|
||||
|
||||
# 紧急状态和保留字段
|
||||
data += struct.pack('<BB',
|
||||
# 第十五部分:紧急状态和保留字段
|
||||
body_data += struct.pack('<BB',
|
||||
self.ins_emergency_status,
|
||||
self.dyn_emergency_status)
|
||||
|
||||
data += struct.pack('<BB',
|
||||
body_data += struct.pack('<BB',
|
||||
self.reserved3[0], self.reserved3[1])
|
||||
|
||||
# SOC门限值
|
||||
data += struct.pack('<BBBBBB',
|
||||
# 第十六部分:SOC门限值
|
||||
body_data += struct.pack('<BBBBBB',
|
||||
self.ins_soc_threshold1,
|
||||
self.ins_soc_threshold2,
|
||||
self.ins_soc_threshold3,
|
||||
@@ -271,41 +275,54 @@ class msg_ccUFbMsg:
|
||||
self.dyn_soc_threshold2,
|
||||
self.dyn_soc_threshold3)
|
||||
|
||||
# 功率限制值
|
||||
data += struct.pack('<BBBB',
|
||||
# 第十七部分:功率限制值
|
||||
body_data += struct.pack('<BBBB',
|
||||
self.ins_power_limit1,
|
||||
self.ins_power_limit2,
|
||||
self.dyn_power_limit1,
|
||||
self.dyn_power_limit2)
|
||||
|
||||
# 设备在线状态和心跳
|
||||
data += struct.pack('<II',
|
||||
# 第十八部分:设备在线状态和心跳
|
||||
body_data += struct.pack('<II',
|
||||
self.device_online_flag1,
|
||||
self.device_online_flag2)
|
||||
|
||||
data += struct.pack('<BBBB',
|
||||
body_data += struct.pack('<BBBB',
|
||||
self.dyn_charge_level,
|
||||
self.dyn_water_leak_status,
|
||||
self.ins_water_leak_dcdc_status,
|
||||
self.reserved4)
|
||||
|
||||
data += struct.pack('<I', self.heartbeat)
|
||||
body_data += struct.pack('<I', self.heartbeat)
|
||||
|
||||
# 计算校验码
|
||||
# 计算长度字段:body_data的长度
|
||||
self.length = len(body_data)
|
||||
|
||||
# 打包消息头 - 对应C++中的m_header
|
||||
header_data = struct.pack('<BBHH',
|
||||
self.start1,
|
||||
self.start2,
|
||||
self.id,
|
||||
self.length)
|
||||
|
||||
# 组合头部和body数据
|
||||
data_without_checksum = header_data + body_data
|
||||
|
||||
# 计算校验码 - 根据C++代码,计算所有数据的和(不包括校验码本身)
|
||||
self.checkCode = 0
|
||||
for byte in data:
|
||||
self.checkCode = (self.checkCode + byte) & 0xFF
|
||||
for byte in data_without_checksum:
|
||||
self.checkCode += byte
|
||||
|
||||
# 添加校验码
|
||||
data += struct.pack('<B', self.checkCode)
|
||||
# 添加校验码 - 使用4字节,对应C++中的Checksum (unsigned int)
|
||||
checksum_data = struct.pack('<I', self.checkCode)
|
||||
|
||||
# 更新长度字段
|
||||
self.length = len(data) - 6 # 减去头部6字节
|
||||
# 完整数据:头部 + body + 校验码
|
||||
full_data = data_without_checksum + checksum_data
|
||||
|
||||
return data
|
||||
return full_data
|
||||
|
||||
def unpack(self, data):
|
||||
"""从字节数据解包消息"""
|
||||
"""从字节数据解包消息 - 完全对应C++中的msg_CcuStateFbMsg结构体"""
|
||||
if len(data) < 10: # 最小消息长度检查
|
||||
return False
|
||||
|
||||
@@ -317,30 +334,37 @@ class msg_ccUFbMsg:
|
||||
|
||||
offset = 6 # 头部结束位置
|
||||
|
||||
# 检查数据长度是否足够
|
||||
if len(data) < offset + self.length + 1: # +1 for checksum
|
||||
# 检查数据长度是否足够(现在校验码是4字节)
|
||||
if len(data) < offset + self.length + 4: # +4 for 4-byte checksum
|
||||
return False
|
||||
|
||||
# 解析CCU状态数据
|
||||
# 解析CCU状态数据 - 完全对应C++中的ccuState结构体
|
||||
# 第一部分:基本状态
|
||||
(self.fc_mode, self.fc_status, self.fc_fault_level) = struct.unpack_from('<BBB', data, offset); offset += 3
|
||||
|
||||
# 第二部分:功率和时间
|
||||
(self.output_power_limit, self.total_generation_time, self.total_generation_power,
|
||||
self.fault_level_1, self.fault_level_2, self.fault_level_3, self.fault_level_4) = struct.unpack_from('<HHHHHHH', data, offset); offset += 14
|
||||
|
||||
# 第三部分:容量
|
||||
(self.hydrogen_capacity, self.liquid_oxygen_capacity) = struct.unpack_from('<BB', data, offset); offset += 2
|
||||
|
||||
# 第四部分:温度和压力
|
||||
(self.palladium_temp, self.main_pipe_pressure, self.aux_pipe_pressure) = struct.unpack_from('<HHH', data, offset); offset += 6
|
||||
|
||||
# 第五部分:舱室环境
|
||||
(self.cabin_pressure1, self.cabin_pressure2, self.cabin_temp1, self.cabin_temp2,
|
||||
self.cabin_humidity1, self.cabin_humidity2) = struct.unpack_from('<HHHHHH', data, offset); offset += 12
|
||||
|
||||
# 第六部分:火焰探测器
|
||||
(self.flame_detector1, self.flame_detector2) = struct.unpack_from('<BB', data, offset); offset += 2
|
||||
|
||||
# 第七部分:气体浓度
|
||||
(self.h2_concentration1, self.h2_concentration2, self.h2_concentration3,
|
||||
self.o2_concentration1, self.o2_concentration2, self.ch3oh_concentration1,
|
||||
self.ch3oh_concentration2) = struct.unpack_from('<HHHHHHH', data, offset); offset += 14
|
||||
|
||||
# 保留字段和应急电池数据
|
||||
# 第八部分:保留字段和应急电池数据
|
||||
(self.reserved1[0], self.reserved1[1], self.emergency_battery1_voltage,
|
||||
self.emergency_battery1_current, self.emergency_battery1_max_temp,
|
||||
self.emergency_battery1_fault_word, self.emergency_battery2_voltage,
|
||||
@@ -349,49 +373,50 @@ class msg_ccUFbMsg:
|
||||
(self.emergency_battery2_max_temp, self.emergency_battery2_fault_word,
|
||||
self.cabin_ox_concentration, self.cabin_temperature) = struct.unpack_from('<HHHH', data, offset); offset += 8
|
||||
|
||||
# 第九部分:舱室环境2
|
||||
(self.cabin_humidity, self.cabin_pressure, self.power_cabin_ox_concentration,
|
||||
self.power_cabin_temperature, self.power_cabin_humidity, self.power_cabin_pressure,
|
||||
reserved2_0, reserved2_1) = struct.unpack_from('<HHHHHHBB', data, offset); offset += 16
|
||||
self.reserved2 = [reserved2_0, reserved2_1]
|
||||
|
||||
# 报警标志数组
|
||||
# 第十部分:报警标志数组
|
||||
for i in range(6):
|
||||
self.dyn_alarm_flag[i] = data[offset]; offset += 1
|
||||
for i in range(6):
|
||||
self.ins_alarm_flag[i] = data[offset]; offset += 1
|
||||
|
||||
# 继电器状态
|
||||
# 第十一部分:继电器状态
|
||||
(self.ins_relay_status1, self.ins_relay_status2,
|
||||
self.dyn_relay_status1, self.dyn_relay_status2) = struct.unpack_from('<BBBB', data, offset); offset += 4
|
||||
|
||||
# 功率和SOC数据
|
||||
# 第十二部分:功率和SOC数据
|
||||
(self.ins_max_discharge_power, self.dyn_max_discharge_power,
|
||||
self.ins_soc, self.dyn_soc, self.ins_total_energy, self.dyn_total_energy,
|
||||
self.ins_power_input, self.dyn_power_input) = struct.unpack_from('<HHBBHHHH', data, offset); offset += 14
|
||||
|
||||
# 充电状态
|
||||
# 第十三部分:充电状态
|
||||
(self.ins_charge_status, self.dyn_charge_status) = struct.unpack_from('<BB', data, offset); offset += 2
|
||||
|
||||
# 电压电流和绝缘电阻
|
||||
# 第十四部分:电压电流和绝缘电阻
|
||||
(self.ins_voltage_link, self.ins_voltage_pack, self.ins_current,
|
||||
self.ins_resistance_pos, self.ins_resistance_neg, self.dyn_voltage_link,
|
||||
self.dyn_voltage_pack, self.dyn_current, self.dyn_resistance_pos,
|
||||
self.dyn_resistance_neg) = struct.unpack_from('<HHHHHHHHHH', data, offset); offset += 20
|
||||
|
||||
# 紧急状态和保留字段
|
||||
# 第十五部分:紧急状态和保留字段
|
||||
(self.ins_emergency_status, self.dyn_emergency_status) = struct.unpack_from('<BB', data, offset); offset += 2
|
||||
|
||||
(self.reserved3[0], self.reserved3[1]) = struct.unpack_from('<BB', data, offset); offset += 2
|
||||
|
||||
# SOC门限值
|
||||
# 第十六部分:SOC门限值
|
||||
(self.ins_soc_threshold1, self.ins_soc_threshold2, self.ins_soc_threshold3,
|
||||
self.dyn_soc_threshold1, self.dyn_soc_threshold2, self.dyn_soc_threshold3) = struct.unpack_from('<BBBBBB', data, offset); offset += 6
|
||||
|
||||
# 功率限制值
|
||||
# 第十七部分:功率限制值
|
||||
(self.ins_power_limit1, self.ins_power_limit2,
|
||||
self.dyn_power_limit1, self.dyn_power_limit2) = struct.unpack_from('<BBBB', data, offset); offset += 4
|
||||
|
||||
# 设备在线状态和心跳
|
||||
# 第十八部分:设备在线状态和心跳
|
||||
(self.device_online_flag1, self.device_online_flag2) = struct.unpack_from('<II', data, offset); offset += 8
|
||||
|
||||
(self.dyn_charge_level, self.dyn_water_leak_status,
|
||||
@@ -399,12 +424,16 @@ class msg_ccUFbMsg:
|
||||
|
||||
(self.heartbeat,) = struct.unpack_from('<I', data, offset); offset += 4
|
||||
|
||||
# 校验校验码
|
||||
# 解析校验码(4字节)
|
||||
(self.checkCode,) = struct.unpack_from('<I', data, offset); offset += 4
|
||||
|
||||
# 校验校验码 - 根据C++代码,计算所有数据的和(不包括校验码本身)
|
||||
checkCode = 0
|
||||
for byte in data[:-1]: # 不包括校验码本身
|
||||
checkCode = (checkCode + byte) & 0xFF
|
||||
|
||||
return checkCode == data[-1]
|
||||
# 计算除校验码外的所有字节的和
|
||||
for i in range(len(data) - 4): # 不包括最后4字节的校验码
|
||||
checkCode += data[i]
|
||||
|
||||
return checkCode == self.checkCode
|
||||
|
||||
def print_info(self):
|
||||
"""打印消息信息"""
|
||||
@@ -423,214 +452,5 @@ class msg_ccUFbMsg:
|
||||
print(f"仪表SOC: {self.ins_soc}%")
|
||||
print(f"动力SOC: {self.dyn_soc}%")
|
||||
print(f"心跳计数器: {self.heartbeat}")
|
||||
print(f"校验码: 0x{self.checkCode:02X}")
|
||||
|
||||
|
||||
class msg_ccUCmdMsg:
|
||||
def __init__(self):
|
||||
# 消息头
|
||||
self.start1 = 0x20
|
||||
self.start2 = 0x20
|
||||
self.id = 0x0040 # CCU_CMD_ID
|
||||
self.length = 0
|
||||
self.checkCode = 0x00
|
||||
|
||||
# 时间戳
|
||||
self.year = 0
|
||||
self.month = 0
|
||||
self.day = 0
|
||||
self.hour = 0
|
||||
self.minute = 0
|
||||
self.second = 0
|
||||
self.milliseconds = 0
|
||||
|
||||
# 复合管控器操作指令
|
||||
self.fcmode = 0x00 # 燃料电池运行模式
|
||||
self.fcuCmd = 0x00 # 燃料电池控制命令
|
||||
self.fcuPowerEfficiency = 0x00 # 燃料电池功率效率
|
||||
self.insChargeEnable = 0x00 # 仪表电池充电使能
|
||||
self.insBatCmd = 0x00 # 仪表电池命令
|
||||
self.powerBatCmd = 0x00 # 动力电池命令
|
||||
self.powerBatEfficiency = 0 # 动力电池功率效率
|
||||
self.heartbeat = 0 # 心跳
|
||||
self.masterState = 0x00 # 主控状态
|
||||
self.paceholder1 = 0 # 占位符1
|
||||
self.paceholder2 = 0 # 占位符2
|
||||
|
||||
def pack(self):
|
||||
"""打包消息为字节数据"""
|
||||
# 重置校验码
|
||||
self.checkCode = 0x00
|
||||
|
||||
# 打包消息头
|
||||
data = struct.pack('<BBHH',
|
||||
self.start1,
|
||||
self.start2,
|
||||
self.id,
|
||||
self.length)
|
||||
|
||||
# 打包时间戳
|
||||
data += struct.pack('<HBBBBBB',
|
||||
self.year,
|
||||
self.month,
|
||||
self.day,
|
||||
self.hour,
|
||||
self.minute,
|
||||
self.second,
|
||||
self.milliseconds)
|
||||
|
||||
# 打包复合管控器操作指令
|
||||
data += struct.pack('<BBBBBBHBBII',
|
||||
self.fcmode,
|
||||
self.fcuCmd,
|
||||
self.fcuPowerEfficiency,
|
||||
self.insChargeEnable,
|
||||
self.insBatCmd,
|
||||
self.powerBatCmd,
|
||||
self.powerBatEfficiency,
|
||||
self.heartbeat,
|
||||
self.masterState,
|
||||
self.paceholder1,
|
||||
self.paceholder2)
|
||||
|
||||
# 计算校验码
|
||||
self.checkCode = 0
|
||||
for byte in data:
|
||||
self.checkCode = (self.checkCode + byte) & 0xFF
|
||||
|
||||
# 添加校验码
|
||||
data += struct.pack('<B', self.checkCode)
|
||||
|
||||
# 更新长度字段
|
||||
self.length = len(data) - 6 # 减去头部6字节
|
||||
|
||||
return data
|
||||
|
||||
def unpack(self, data):
|
||||
"""从字节数据解包消息"""
|
||||
if len(data) < 10: # 最小消息长度检查
|
||||
return False
|
||||
|
||||
# 解析消息头
|
||||
self.start1 = data[0]
|
||||
self.start2 = data[1]
|
||||
self.id = struct.unpack_from('<H', data, 2)[0]
|
||||
self.length = struct.unpack_from('<H', data, 4)[0]
|
||||
|
||||
offset = 6 # 头部结束位置
|
||||
|
||||
# 检查数据长度是否足够
|
||||
if len(data) < offset + self.length + 1: # +1 for checksum
|
||||
return False
|
||||
|
||||
# 解析时间戳
|
||||
(self.year, self.month, self.day, self.hour,
|
||||
self.minute, self.second, self.milliseconds) = struct.unpack_from('<HBBBBBB', data, offset); offset += 8
|
||||
|
||||
# 解析复合管控器操作指令
|
||||
(self.fcmode, self.fcuCmd, self.fcuPowerEfficiency,
|
||||
self.insChargeEnable, self.insBatCmd, self.powerBatCmd,
|
||||
self.powerBatEfficiency, self.heartbeat, self.masterState,
|
||||
self.paceholder1, self.paceholder2) = struct.unpack_from('<BBBBBBHBBII', data, offset); offset += 20
|
||||
|
||||
# 校验校验码
|
||||
checkCode = 0
|
||||
for byte in data[:-1]: # 不包括校验码本身
|
||||
checkCode = (checkCode + byte) & 0xFF
|
||||
|
||||
return checkCode == data[-1]
|
||||
|
||||
def print_info(self):
|
||||
"""打印消息信息"""
|
||||
print(f"消息头: start1=0x{self.start1:02X}, start2=0x{self.start2:02X}, id=0x{self.id:04X}, length={self.length}")
|
||||
print(f"时间戳: {self.year}-{self.month:02d}-{self.day:02d} {self.hour:02d}:{self.minute:02d}:{self.second:02d}.{self.milliseconds:03d}")
|
||||
print(f"燃料电池模式: 0x{self.fcmode:02X}")
|
||||
print(f"燃料电池控制命令: 0x{self.fcuCmd:02X}")
|
||||
print(f"燃料电池功率效率: {self.fcuPowerEfficiency}%")
|
||||
print(f"仪表电池充电使能: 0x{self.insChargeEnable:02X}")
|
||||
print(f"仪表电池命令: 0x{self.insBatCmd:02X}")
|
||||
print(f"动力电池命令: 0x{self.powerBatCmd:02X}")
|
||||
print(f"动力电池功率效率: {self.powerBatEfficiency}%")
|
||||
print(f"心跳: {self.heartbeat}")
|
||||
print(f"主控状态: 0x{self.masterState:02X}")
|
||||
print(f"占位符1: {self.paceholder1}")
|
||||
print(f"占位符2: {self.paceholder2}")
|
||||
print(f"校验码: 0x{self.checkCode:02X}")
|
||||
|
||||
|
||||
# 测试函数
|
||||
def test_msg_ccUFbMsg():
|
||||
"""测试msg_ccUFbMsg类"""
|
||||
msg = msg_ccUFbMsg()
|
||||
|
||||
# 设置一些测试数据
|
||||
msg.fc_mode = 0x02 # 自动模式
|
||||
msg.fc_status = 0x06 # 运行状态
|
||||
msg.output_power_limit = 15000
|
||||
msg.total_generation_time = 100 # 10小时
|
||||
msg.hydrogen_capacity = 80
|
||||
msg.liquid_oxygen_capacity = 75
|
||||
msg.ins_soc = 85
|
||||
msg.dyn_soc = 90
|
||||
msg.heartbeat = 12345
|
||||
|
||||
# 打包消息
|
||||
data = msg.pack()
|
||||
print(f"打包后的数据长度: {len(data)} 字节")
|
||||
|
||||
# 解包消息
|
||||
msg2 = msg_ccUFbMsg()
|
||||
if msg2.unpack(data):
|
||||
print("解包成功!")
|
||||
msg2.print_info()
|
||||
else:
|
||||
print("解包失败!")
|
||||
|
||||
return msg2
|
||||
|
||||
|
||||
def test_msg_ccUCmdMsg():
|
||||
"""测试msg_ccUCmdMsg类"""
|
||||
msg = msg_ccUCmdMsg()
|
||||
|
||||
# 设置一些测试数据
|
||||
msg.year = 2025
|
||||
msg.month = 9
|
||||
msg.day = 11
|
||||
msg.hour = 17
|
||||
msg.minute = 5
|
||||
msg.second = 30
|
||||
msg.milliseconds = 123
|
||||
|
||||
msg.fcmode = 0x02 # 自动模式
|
||||
msg.fcuCmd = 0x02 # 启动命令
|
||||
msg.fcuPowerEfficiency = 85 # 85%效率
|
||||
msg.insChargeEnable = 0x01 # 使能充电
|
||||
msg.insBatCmd = 0x10 # 仪表电池启动
|
||||
msg.powerBatCmd = 0x10 # 动力电池启动
|
||||
msg.powerBatEfficiency = 90 # 90%效率
|
||||
msg.heartbeat = 123
|
||||
msg.masterState = 0x01 # 主控正常
|
||||
msg.paceholder1 = 0
|
||||
msg.paceholder2 = 0
|
||||
|
||||
# 打包消息
|
||||
data = msg.pack()
|
||||
print(f"CCU命令消息打包后的数据长度: {len(data)} 字节")
|
||||
|
||||
# 解包消息
|
||||
msg2 = msg_ccUCmdMsg()
|
||||
if msg2.unpack(data):
|
||||
print("CCU命令消息解包成功!")
|
||||
msg2.print_info()
|
||||
else:
|
||||
print("CCU命令消息解包失败!")
|
||||
|
||||
return msg2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=== 测试CCU状态反馈消息 ===")
|
||||
test_msg_ccUFbMsg()
|
||||
print("\n=== 测试CCU命令消息 ===")
|
||||
test_msg_ccUCmdMsg()
|
||||
print(f"校验码: 0x{self.checkCode:08X}")
|
||||
|
||||
Reference in New Issue
Block a user