182 lines
6.0 KiB
Python
Raw Normal View History

2025-01-18 09:10:52 +08:00
import struct
import logging
from datetime import datetime
class Command2122:
def __init__(self):
2025-01-18 13:41:57 +08:00
self.command_21 = 0x21 # 启动充电结果
self.command_22 = 0x22 # 响应启动充电结果
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
def parse_21h(self, data):
"""解析21H启动充电结果命令"""
2025-01-18 09:10:52 +08:00
try:
2025-01-18 13:41:57 +08:00
print("\n开始解析21H启动充电结果命令...")
print(f"接收数据: {data.hex().upper()}")
# 基础验证
if len(data) < 14 or data[0:2] != b'JX' or data[2] != self.command_21:
logging.warning("21H命令帧格式不正确")
2025-01-18 09:10:52 +08:00
return None
2025-01-18 13:41:57 +08:00
# 解析数据
pile_id = data[3:11] # 桩号
encrypt_mode = data[11] # 加密方式
data_len = struct.unpack("<H", data[12:14])[0] # 数据长度
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析数据域
data_field = data[14:14 + data_len]
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析时间标识
time_bytes = data_field[0:6]
2025-01-18 09:10:52 +08:00
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}"
2025-01-18 13:41:57 +08:00
# 解析枪号
gun_no = data_field[6]
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析充电订单号(32字节ASCII)
order_no = data_field[7:39].decode('ascii').rstrip('\x00')
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析用户ID(32字节ASCII)
user_id = data_field[39:71].decode('ascii').rstrip('\x00')
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析用户类型(2字节)
user_type = struct.unpack("<H", data_field[71:73])[0]
# 解析车牌号(9字节)
plate_no = data_field[73:82].decode('ascii').rstrip('\x00')
# 继续解析其他字段...
result = {
"pile_id": pile_id,
2025-01-18 09:10:52 +08:00
"timestamp": timestamp,
2025-01-18 13:41:57 +08:00
"gun_no": gun_no,
"order_no": order_no,
2025-01-18 09:10:52 +08:00
"user_id": user_id,
2025-01-18 13:41:57 +08:00
"user_type": user_type,
"plate_no": plate_no
2025-01-18 09:10:52 +08:00
}
2025-01-18 13:41:57 +08:00
print("\n解析结果:")
print(f"桩号: {pile_id.hex().upper()}")
print(f"时间标识: {timestamp}")
print(f"枪号: {gun_no}")
print(f"订单号: {order_no}")
print(f"用户ID: {user_id}")
print(f"用户类型: {user_type}")
print(f"车牌号: {plate_no}")
return result
2025-01-18 09:10:52 +08:00
except Exception as e:
2025-01-18 13:41:57 +08:00
logging.error(f"解析21H启动充电结果命令失败: {str(e)}")
print(f"解析失败: {str(e)}")
2025-01-18 09:10:52 +08:00
return None
2025-01-18 13:41:57 +08:00
def build_22h_response(self, pile_id, gun_no):
"""构建22H响应"""
2025-01-18 09:10:52 +08:00
try:
2025-01-18 13:41:57 +08:00
print("\n构建22H响应...")
2025-01-18 09:10:52 +08:00
frame = bytearray()
frame.extend(b'JX') # 帧起始标志
2025-01-18 13:41:57 +08:00
frame.append(self.command_22) # 命令码22H
frame.extend(pile_id) # 桩号
frame.append(0x01) # 数据加密方式(不加密)
2025-01-18 09:10:52 +08:00
# 构建数据域
data = bytearray()
2025-01-18 13:41:57 +08:00
# 添加时间标识
2025-01-18 09:10:52 +08:00
now = datetime.now()
data.extend(struct.pack("<BBBBBB",
now.year - 2000, now.month, now.day,
now.hour, now.minute, now.second))
2025-01-18 13:41:57 +08:00
# 添加枪号
data.append(gun_no)
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 计算数据长度
frame.extend(struct.pack("<H", len(data))) # 数据长度
# 添加数据域
2025-01-18 09:10:52 +08:00
frame.extend(data)
# 计算校验码
check = 0
for b in frame[2:]:
check ^= b
frame.append(check)
2025-01-18 13:41:57 +08:00
response = bytes(frame)
print(f"响应数据: {response.hex().upper()}")
return response
2025-01-18 09:10:52 +08:00
except Exception as e:
2025-01-18 13:41:57 +08:00
logging.error(f"构建22H响应失败: {str(e)}")
print(f"构建响应失败: {str(e)}")
2025-01-18 09:10:52 +08:00
return None
2025-01-18 13:41:57 +08:00
def process_and_respond(self, received_data, sock):
"""处理收到的21H命令并回复22H"""
2025-01-18 09:10:52 +08:00
try:
2025-01-18 13:41:57 +08:00
print("\n处理充电启动结果命令...")
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 解析接收到的21H命令
parsed = self.parse_21h(received_data)
if not parsed:
2025-01-18 09:10:52 +08:00
return False
2025-01-18 13:41:57 +08:00
# 构建22H响应
response = self.build_22h_response(
parsed["pile_id"],
parsed["gun_no"]
2025-01-18 09:10:52 +08:00
)
2025-01-18 13:41:57 +08:00
if not response:
return False
# 发送响应
if sock and hasattr(sock, 'send'):
sock.send(response)
print("充电启动结果响应发送成功")
2025-01-18 09:10:52 +08:00
return True
except Exception as e:
2025-01-18 13:41:57 +08:00
logging.error(f"处理充电启动结果命令失败: {str(e)}")
print(f"处理失败: {str(e)}")
2025-01-18 09:10:52 +08:00
return False
2025-01-18 13:41:57 +08:00
def test_charge_result():
"""测试充电启动结果命令处理"""
print("开始测试充电启动结果命令处理...")
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 创建处理器
handler = Command2122()
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
# 测试数据 - 使用实际收到的21H数据(移除所有空格)
test_data = bytes.fromhex("4A58210317665611360637 01B30019010 90C161201303331373636353631313336303633373235303130393132323134333831353465363961323130330000000000000000000000000000000000000000020000000000000000000000000000000000040000000001020100001901090C152C8B6F680100000000000000000003D011261800000000000000000000000000004C5A474A4C4D3434355058313134353337010100000000007701DC05030B601B73E402FF186E".replace(" ", ""))
2025-01-18 09:10:52 +08:00
2025-01-18 13:41:57 +08:00
print("\n测试数据:")
print(f"21H数据: {test_data.hex().upper()}")
# 创建模拟socket
class MockSocket:
def send(self, data):
print(f"\n模拟发送响应数据:")
print(f"22H数据: {data.hex().upper()}")
mock_sock = MockSocket()
# 测试完整处理流程
result = handler.process_and_respond(test_data, mock_sock)
print(f"\n最终处理结果: {'成功' if result else '失败'}")
if __name__ == "__main__":
test_charge_result()