增加了xc声纳的上电

This commit is contained in:
zjk
2025-09-12 11:35:17 +08:00
parent c2b9bccfc6
commit 481171d9ea
43 changed files with 1921 additions and 296 deletions
+70 -4
View File
@@ -70,13 +70,13 @@ class PowerManagerApp:
# 高压配电板端口
self.disSysPortC1 = 6000
# self.disSysHostC1 = '192.168.1.154'
self.disSysHostC1 = '127.0.0.1'
self.disSysHostC1 = '192.168.1.154'
# self.disSysHostC1 = '127.0.0.1'
# 仪表配电板端口
self.disSysPortC2 = 6000
# self.disSysHostC2 = '192.168.1.158'
self.disSysHostC2 = '127.0.0.1'
self.disSysHostC2 = '192.168.1.158'
# self.disSysHostC2 = '127.0.0.1'
# 数据库配置
self.db = DB(os.path.join(os.path.dirname(__file__), 'test.db'))
@@ -419,6 +419,8 @@ class PowerManagerApp:
menubar.add_cascade(label="配电操作", menu=dis_options_menu)
menubar.add_command(label="DCDC状态", command=lambda: self.show_popup_window("DCDC状态"))
menubar.add_command(label="复合管控面板", command=lambda: self.show_compound_control_window("复合管控面板"))
menubar.add_command(label="软件说明", command=lambda: self.show_help_window("程序说明"))
# 配置菜单栏
self.root.config(menu=menubar)
@@ -1826,6 +1828,70 @@ class PowerManagerApp:
close_button = ttk.Button(popup, text="关闭", command=popup.destroy)
close_button.pack(pady=10)
def show_compound_control_window(self, title):
"""创建并显示弹出窗口"""
popup = tk.Toplevel(self.root)
popup.title(title)
frame = ttk.Frame(popup)
popup.geometry("600x400")
popup.resizable(True, True)
frame.pack(fill="both", expand=True, padx=5, pady=5)
def show_help_window(self, title):
"""显示程序说明弹窗"""
popup = tk.Toplevel(self.root)
popup.title(title)
popup.geometry("600x400")
popup.resizable(True, True)
# 创建文本框和滚动条
frame = ttk.Frame(popup)
frame.pack(fill="both", expand=True, padx=10, pady=10)
text_widget = tk.Text(frame, wrap="word", font=("Microsoft YaHei", 10))
scrollbar = ttk.Scrollbar(frame, orient="vertical", command=text_widget.yview)
text_widget.configure(yscrollcommand=scrollbar.set)
text_widget.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
# 程序说明内容
help_text = """H100动力管理系统程序说明
版本:v1.0
功能概述:
1. 高压母线状态监控 - 实时显示动力母线电压、电流及断路器状态
2. 高压A母线状态监控 - 监控汇流排B电压电流及断路器状态
3. 仪表主母线状态监控 - 显示仪表母线电压电流及配电状态
4. 仪表母线状态监控 - 监控应急电源系统状态
5. 配电指令控制 - 支持远程断路器合分操作
6. 数据记录 - 所有状态数据自动保存到SQLite数据库
7. 模拟模式 - 支持离线模拟测试
通信协议:
- 采用UDP协议与分布式系统通信
- 消息ID范围:0x0001-0x0008
- 支持实时状态反馈和指令下发
操作说明:
1. 主界面显示各母线实时状态
2. 通过菜单栏可打开各配电控制面板
3. 断路器状态:黄色=合闸,黑色=分闸,红色=故障
4. 启用模拟模式可进行离线测试
注意事项:
- 操作前请确认系统连接正常
- 重要操作需双重确认
- 定期检查数据库存储状态"""
text_widget.insert("1.0", help_text)
text_widget.config(state="disabled") # 设置为只读
# 关闭按钮
close_btn = ttk.Button(popup, text="关闭", command=popup.destroy)
close_btn.pack(pady=10)
if __name__ == "__main__":
root = tk.Tk()
app = PowerManagerApp(root)
+3 -3
View File
@@ -59,8 +59,8 @@ class PowerManagerApp:
# self.udp_control_host = "127.0.0.1"
# 下位机端口
# self.udp_ip = "127.0.0.1"
self.udp_ip = "192.168.0.140"
self.udp_ip = "127.0.0.1"
# self.udp_ip = "192.168.0.140"
self.udp_port = 7000
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.udp_ip, self.udp_port))
@@ -1666,4 +1666,4 @@ if __name__ == "__main__":
root.protocol("WM_DELETE_WINDOW", app.on_closing)
print('start')
root.mainloop()
print('end')
print('end')
+636
View File
@@ -0,0 +1,636 @@
import struct
import datetime
class msg_ccUFbMsg:
def __init__(self):
# 消息头
self.start1 = 0x20
self.start2 = 0x20
self.id = 0x0051 # CCU_STATE_FB_ID
self.length = 0
self.checkCode = 0x00
# CCU状态数据 - 根据ccuState结构体定义
self.fc_mode = 0x00
self.fc_status = 0x00
self.fc_fault_level = 0x00
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.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.reserved4 = 0x00
self.heartbeat = 0
def pack(self):
"""打包消息为字节数据"""
# 重置校验码
self.checkCode = 0x00
# 打包消息头
data = struct.pack('<BBHH',
self.start1,
self.start2,
self.id,
self.length)
# 打包CCU状态数据
data += struct.pack('<BBB',
self.fc_mode,
self.fc_status,
self.fc_fault_level)
data += struct.pack('<HHHHHHH',
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)
data += struct.pack('<BB',
self.hydrogen_capacity,
self.liquid_oxygen_capacity)
data += struct.pack('<HHH',
self.palladium_temp,
self.main_pipe_pressure,
self.aux_pipe_pressure)
data += struct.pack('<HHHHHH',
self.cabin_pressure1,
self.cabin_pressure2,
self.cabin_temp1,
self.cabin_temp2,
self.cabin_humidity1,
self.cabin_humidity2)
data += struct.pack('<BB',
self.flame_detector1,
self.flame_detector2)
data += struct.pack('<HHHHHHH',
self.h2_concentration1,
self.h2_concentration2,
self.h2_concentration3,
self.o2_concentration1,
self.o2_concentration2,
self.ch3oh_concentration1,
self.ch3oh_concentration2)
# 保留字段和应急电池数据
data += struct.pack('<HHHHHHHH',
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,
self.emergency_battery2_current)
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',
self.cabin_humidity,
self.cabin_pressure,
self.power_cabin_ox_concentration,
self.power_cabin_temperature,
self.power_cabin_humidity,
self.power_cabin_pressure,
self.reserved2[0], 0) # 填充第二个reserved2字节
# 报警标志数组
for flag in self.dyn_alarm_flag:
data += struct.pack('<B', flag)
for flag in self.ins_alarm_flag:
data += struct.pack('<B', flag)
# 继电器状态
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',
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)
# 充电状态
data += struct.pack('<BB',
self.ins_charge_status,
self.dyn_charge_status)
# 电压电流和绝缘电阻
data += struct.pack('<HHHHHHHHHH',
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)
# 紧急状态和保留字段
data += struct.pack('<BB',
self.ins_emergency_status,
self.dyn_emergency_status)
data += struct.pack('<BB',
self.reserved3[0], self.reserved3[1])
# SOC门限值
data += struct.pack('<BBBBBB',
self.ins_soc_threshold1,
self.ins_soc_threshold2,
self.ins_soc_threshold3,
self.dyn_soc_threshold1,
self.dyn_soc_threshold2,
self.dyn_soc_threshold3)
# 功率限制值
data += struct.pack('<BBBB',
self.ins_power_limit1,
self.ins_power_limit2,
self.dyn_power_limit1,
self.dyn_power_limit2)
# 设备在线状态和心跳
data += struct.pack('<II',
self.device_online_flag1,
self.device_online_flag2)
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)
# 计算校验码
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
# 解析CCU状态数据
(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,
self.emergency_battery2_current) = struct.unpack_from('<HHHHHHHH', data, offset); offset += 16
(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
(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数据
(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门限值
(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,
self.ins_water_leak_dcdc_status, self.reserved4) = struct.unpack_from('<BBBB', data, offset); offset += 4
(self.heartbeat,) = struct.unpack_from('<I', data, offset); offset += 4
# 校验校验码
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"燃料电池模式: 0x{self.fc_mode:02X}")
print(f"燃料电池状态: 0x{self.fc_status:02X}")
print(f"故障等级: 0x{self.fc_fault_level:02X}")
print(f"输出功率限制: {self.output_power_limit}W")
print(f"累计发电时间: {self.total_generation_time * 0.1}小时")
print(f"发电总功率: {self.total_generation_power}W")
print(f"储氢容量: {self.hydrogen_capacity}%")
print(f"液氧容量: {self.liquid_oxygen_capacity}%")
print(f"钯膜温度: {self.palladium_temp}℃")
print(f"主水路压力: {self.main_pipe_pressure * 0.01}kPa")
print(f"辅水路压力: {self.aux_pipe_pressure * 0.01}kPa")
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()
+213
View File
@@ -0,0 +1,213 @@
import tkinter as tk
from tkinter import ttk, scrolledtext
import sys
import os
# 添加当前目录到Python路径,以便能够导入ccuMsg
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
import ccuMsg
from datetime import datetime
class CCUStatusSummaryDialog:
"""CCU状态汇总弹窗"""
def __init__(self, parent, ccu_status=None, title="CCU状态汇总"):
self.parent = parent
self.ccu_status = ccu_status or ccuMsg.msg_ccUFbMsg()
# 创建弹窗
self.dialog = tk.Toplevel(parent)
self.dialog.title(title)
self.dialog.geometry("1000x700")
self.dialog.transient(parent) # 设置为父窗口的临时窗口
self.dialog.grab_set() # 模态对话框
# 创建主框架
main_frame = ttk.Frame(self.dialog, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
# 标题
title_label = ttk.Label(main_frame, text="CCU状态详细信息", font=('Arial', 16, 'bold'))
title_label.pack(pady=10)
# 时间标签
self.time_label = ttk.Label(main_frame, text="", font=('Arial', 10))
self.time_label.pack(pady=5)
# 创建滚动文本框
self.summary_text = scrolledtext.ScrolledText(main_frame, width=90, height=30, wrap=tk.WORD, font=('Courier', 10))
self.summary_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 按钮框架
button_frame = ttk.Frame(main_frame)
button_frame.pack(pady=10)
# 关闭按钮
close_btn = ttk.Button(button_frame, text="关闭", command=self.dialog.destroy)
close_btn.pack(side=tk.LEFT, padx=5)
# 刷新按钮
refresh_btn = ttk.Button(button_frame, text="刷新", command=self.update_display)
refresh_btn.pack(side=tk.LEFT, padx=5)
# 初始更新显示
self.update_display()
def update_display(self):
"""更新显示数据"""
# 更新时间标签
self.time_label.config(text=f"更新时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# 生成汇总信息
summary = self.generate_summary()
# 清空并插入新的汇总信息
self.summary_text.delete(1.0, tk.END)
self.summary_text.insert(1.0, summary)
def generate_summary(self):
"""生成汇总信息"""
return f"""CCU状态汇总 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
燃料电池状态:
运行模式: 0x{self.ccu_status.fc_mode:02X}
运行状态: 0x{self.ccu_status.fc_status:02X}
故障等级: 0x{self.ccu_status.fc_fault_level:02X}
输出功率限制: {self.ccu_status.output_power_limit}W
累计发电时间: {self.ccu_status.total_generation_time * 0.1:.1f}小时
发电总功率: {self.ccu_status.total_generation_power}W
故障等级1-4: {self.ccu_status.fault_level_1}, {self.ccu_status.fault_level_2}, {self.ccu_status.fault_level_3}, {self.ccu_status.fault_level_4}
储氢容量: {self.ccu_status.hydrogen_capacity}%
液氧容量: {self.ccu_status.liquid_oxygen_capacity}%
传感器数据:
钯膜温度: {self.ccu_status.palladium_temp}℃
主水路压力: {self.ccu_status.main_pipe_pressure * 0.01:.2f}kPa
辅水路压力: {self.ccu_status.aux_pipe_pressure * 0.01:.2f}kPa
舱室压力1/2: {self.ccu_status.cabin_pressure1}/{self.ccu_status.cabin_pressure2}Pa
舱室温度1/2: {self.ccu_status.cabin_temp1}/{self.ccu_status.cabin_temp2}℃
舱室湿度1/2: {self.ccu_status.cabin_humidity1}/{self.ccu_status.cabin_humidity2}%
火焰探测器1/2: 0x{self.ccu_status.flame_detector1:02X}/0x{self.ccu_status.flame_detector2:02X}
浓度检测:
H2浓度1/2/3: {self.ccu_status.h2_concentration1}/{self.ccu_status.h2_concentration2}/{self.ccu_status.h2_concentration3}
O2浓度1/2: {self.ccu_status.o2_concentration1}/{self.ccu_status.o2_concentration2}
CH3OH浓度1/2: {self.ccu_status.ch3oh_concentration1}/{self.ccu_status.ch3oh_concentration2}
应急电池:
电池1电压/电流: {self.ccu_status.emergency_battery1_voltage}V/{self.ccu_status.emergency_battery1_current}A
电池1最高温度: {self.ccu_status.emergency_battery1_max_temp}℃
电池1故障字: 0x{self.ccu_status.emergency_battery1_fault_word:04X}
电池2电压/电流: {self.ccu_status.emergency_battery2_voltage}V/{self.ccu_status.emergency_battery2_current}A
电池2最高温度: {self.ccu_status.emergency_battery2_max_temp}℃
电池2故障字: 0x{self.ccu_status.emergency_battery2_fault_word:04X}
舱室环境:
舱室氧浓度: {self.ccu_status.cabin_ox_concentration}
舱室温度: {self.ccu_status.cabin_temperature}℃
舱室湿度: {self.ccu_status.cabin_humidity}%
舱室压力: {self.ccu_status.cabin_pressure}Pa
动力舱氧浓度: {self.ccu_status.power_cabin_ox_concentration}
动力舱温度: {self.ccu_status.power_cabin_temperature}℃
动力舱湿度: {self.ccu_status.power_cabin_humidity}%
动力舱压力: {self.ccu_status.power_cabin_pressure}Pa
报警状态:
动态报警标志: {[flag for flag in self.ccu_status.dyn_alarm_flag]}
绝缘报警标志: {[flag for flag in self.ccu_status.ins_alarm_flag]}
动态报警总数: {sum(self.ccu_status.dyn_alarm_flag)}
绝缘报警总数: {sum(self.ccu_status.ins_alarm_flag)}
继电器状态:
仪表继电器1/2: 0x{self.ccu_status.ins_relay_status1:02X}/0x{self.ccu_status.ins_relay_status2:02X}
动力继电器1/2: 0x{self.ccu_status.dyn_relay_status1:02X}/0x{self.ccu_status.dyn_relay_status2:02X}
功率信息:
仪表最大放电功率: {self.ccu_status.ins_max_discharge_power}W
动力最大放电功率: {self.ccu_status.dyn_max_discharge_power}W
仪表SOC: {self.ccu_status.ins_soc}%
动力SOC: {self.ccu_status.dyn_soc}%
仪表总能量: {self.ccu_status.ins_total_energy}Wh
动力总能量: {self.ccu_status.dyn_total_energy}Wh
仪表功率输入: {self.ccu_status.ins_power_input}W
动力功率输入: {self.ccu_status.dyn_power_input}W
充电状态:
仪表充电状态: 0x{self.ccu_status.ins_charge_status:02X}
动力充电状态: 0x{self.ccu_status.dyn_charge_status:02X}
电气参数:
仪表链路电压: {self.ccu_status.ins_voltage_link * 0.1:.1f}V
仪表电池电压: {self.ccu_status.ins_voltage_pack * 0.1:.1f}V
仪表电流: {self.ccu_status.ins_current * 0.1:.1f}A
仪表正极绝缘电阻: {self.ccu_status.ins_resistance_pos}Ω
仪表负极绝缘电阻: {self.ccu_status.ins_resistance_neg}Ω
动力链路电压: {self.ccu_status.dyn_voltage_link * 0.1:.1f}V
动力电池电压: {self.ccu_status.dyn_voltage_pack * 0.1:.1f}V
动力电流: {self.ccu_status.dyn_current * 0.1:.1f}A
动力正极绝缘电阻: {self.ccu_status.dyn_resistance_pos}Ω
动力负极绝缘电阻: {self.ccu_status.dyn_resistance_neg}Ω
紧急状态:
仪表紧急状态: 0x{self.ccu_status.ins_emergency_status:02X}
动力紧急状态: 0x{self.ccu_status.dyn_emergency_status:02X}
SOC门限值:
仪表SOC门限1/2/3: {self.ccu_status.ins_soc_threshold1}/{self.ccu_status.ins_soc_threshold2}/{self.ccu_status.ins_soc_threshold3}%
动力SOC门限1/2/3: {self.ccu_status.dyn_soc_threshold1}/{self.ccu_status.dyn_soc_threshold2}/{self.ccu_status.dyn_soc_threshold3}%
功率限制值:
仪表功率限制1/2: {self.ccu_status.ins_power_limit1}/{self.ccu_status.ins_power_limit2}W
动力功率限制1/2: {self.ccu_status.dyn_power_limit1}/{self.ccu_status.dyn_power_limit2}W
设备在线状态:
设备在线标志1: 0x{self.ccu_status.device_online_flag1:08X}
设备在线标志2: 0x{self.ccu_status.device_online_flag2:08X}
其他状态:
动力充电等级: 0x{self.ccu_status.dyn_charge_level:02X}
动力漏水状态: 0x{self.ccu_status.dyn_water_leak_status:02X}
仪表漏水DCDC状态: 0x{self.ccu_status.ins_water_leak_dcdc_status:02X}
心跳计数器: {self.ccu_status.heartbeat}
"""
def set_ccu_status(self, ccu_status):
"""设置CCU状态数据"""
self.ccu_status = ccu_status
self.update_display()
# 测试函数
def test_ccu_summary_dialog():
"""测试CCU状态汇总弹窗"""
root = tk.Tk()
root.withdraw() # 隐藏主窗口
# 设置一些测试数据
test_status = ccuMsg.msg_ccUFbMsg()
test_status.fc_mode = 0x02 # 自动模式
test_status.fc_status = 0x06 # 运行状态
test_status.output_power_limit = 15000
test_status.total_generation_time = 100 # 10小时
test_status.hydrogen_capacity = 80
test_status.liquid_oxygen_capacity = 75
test_status.ins_soc = 85
test_status.dyn_soc = 90
test_status.heartbeat = 12345
test_status.palladium_temp = 65
test_status.main_pipe_pressure = 1500 # 15.00 kPa
test_status.aux_pipe_pressure = 800 # 8.00 kPa
# 设置一些报警标志
test_status.dyn_alarm_flag[0] = 1
test_status.ins_alarm_flag[2] = 1
# 创建弹窗
dialog = CCUStatusSummaryDialog(root, test_status)
# 等待弹窗关闭
root.wait_window(dialog.dialog)
root.destroy()
if __name__ == "__main__":
test_ccu_summary_dialog()