2025-01-18 09:10:52 +08:00

148 lines
5.8 KiB
Python

import struct
import logging
class Command0A:
def __init__(self):
self.command = 0x0A # 0AH命令码
def parse_0ah(self, data):
"""
解析0AH遥测命令
:param data: 完整的0AH命令报文
:return: 解析后的字典或None
"""
try:
# 验证基本帧格式
if len(data) < 14 or data[0:2] != b'JX' or data[2] != 0x0A:
logging.warning("0AH命令帧格式不正确")
return None
# 提取桩号
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
power_params = {
"A相电压": struct.unpack("<H", data[current_index:current_index + 2])[0] / 10, # 0.1V
"B相电压": struct.unpack("<H", data[current_index + 2:current_index + 4])[0] / 10,
"C相电压": struct.unpack("<H", data[current_index + 4:current_index + 6])[0] / 10,
"A相电流": struct.unpack("<H", data[current_index + 6:current_index + 8])[0] / 100, # 0.01A
"B相电流": struct.unpack("<H", data[current_index + 8:current_index + 10])[0] / 100,
"C相电流": struct.unpack("<H", data[current_index + 10:current_index + 12])[0] / 100,
"总电表电量": struct.unpack("<I", data[current_index + 12:current_index + 16])[0] / 100 # 0.01kWh
}
current_index += 16
# 解析温度相关参数
temp_params = {
"桩内温度": data[current_index] - 50, # 偏移量-50℃
"进风口温度": data[current_index + 1] - 50,
"出风口温度": data[current_index + 2] - 50,
"控制板温度": data[current_index + 3] - 50,
"桩内湿度": data[current_index + 4] # 0-100%RH
}
current_index += 5
# 跳过预留字节
current_index += 8
# 解析充电枪数量
gun_count = data[current_index]
current_index += 1
# 存储每个充电枪的遥测数据
gun_params = []
for i in range(gun_count):
gun_data = {
"gun_index": i + 1,
"电表电压": struct.unpack("<H", data[current_index:current_index + 2])[0] / 10, # 0.1V
"电表电流": struct.unpack("<H", data[current_index + 2:current_index + 4])[0] / 100, # 0.01A
"电表电量": struct.unpack("<I", data[current_index + 4:current_index + 8])[0] / 100, # 0.01kWh
"充电模块电压": struct.unpack("<H", data[current_index + 8:current_index + 10])[0] / 10, # 0.1V
"充电模块电流": struct.unpack("<H", data[current_index + 10:current_index + 12])[0] / 10, # 0.1A
"充电模块温度": data[current_index + 12] - 50, # 偏移量-50℃
"充电枪温度": data[current_index + 13] - 50
}
gun_params.append(gun_data)
current_index += 14
# 打印解析结果
print("\n0AH命令解析结果:")
print(f"桩号: {pile_id_bytes.hex()}")
print(f"时间标识: {timestamp}")
print("总体电气参数:")
for param, value in power_params.items():
print(f" {param}: {value}")
print("温度和湿度参数:")
for param, value in temp_params.items():
print(f" {param}: {value}")
print(f"充电枪数量: {gun_count}")
for gun in gun_params:
print(f"{gun['gun_index']} 遥测数据:")
for param, value in gun.items():
if param != "gun_index":
print(f" {param}: {value}")
return {
"pile_id": pile_id_bytes.hex(),
"timestamp": timestamp,
"power_params": power_params,
"temp_params": temp_params,
"gun_count": gun_count,
"gun_params": gun_params
}
except Exception as e:
logging.error(f"解析0AH命令失败: {str(e)}")
return None
def process_0ah(self, data):
"""
处理0AH遥测命令
:param data: 完整的0AH命令报文
:return: 是否成功处理
"""
try:
parsed_data = self.parse_0ah(data)
if parsed_data is None:
logging.warning("0AH命令解析失败")
return False
# 记录遥测信息日志
log_message = (
f"桩号 {parsed_data['pile_id']} 遥测数据: "
f"A相电压 {parsed_data['power_params']['A相电压']}V, "
f"总电量 {parsed_data['power_params']['总电表电量']}kWh, "
f"桩内温度 {parsed_data['temp_params']['桩内温度']}"
)
logging.info(log_message)
return True
except Exception as e:
logging.error(f"处理0AH命令出错: {str(e)}")
return False
# 测试用示例
if __name__ == "__main__":
# 示例报文
test_data = bytes.fromhex(
"4A 58 0A 03 17 67 63 11 36 06 57 01 48 00 19 01 09 09 37 39 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 74 29 AD 00 00 00 00 00 00 67 00 00 00 00 00 00 00 00 27 63 F1 00 00 00 00 00 00 E1 00 00 00 00 F2")
parser = Command0A()
parser.process_0ah(test_data)