diff --git a/.idea/.name b/.idea/.name index 11a5d8e..adc719b 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -main.py \ No newline at end of file +command_07.py \ No newline at end of file diff --git a/charging_pile_proxy/commands/__init__.py b/charging_pile_proxy/commands/__init__.py index e69de29..232848b 100644 --- a/charging_pile_proxy/commands/__init__.py +++ b/charging_pile_proxy/commands/__init__.py @@ -0,0 +1,18 @@ +from .command_02 import Command02 +from .command_03 import Command03 +from .command_heartbeat import CommandHeartbeat +from commands.command_02 import Command02 +from commands.command_03 import Command03 +from commands.command_07 import Command07 +from commands.command_08 import Command08 +from commands.command_09 import Command09 +from commands.command_0A import Command0A +from commands.command_25 import Command25 +from commands.command_30 import Command30 +from commands.command_19_1A import Command191A +from commands.command_21_22 import Command2122 +from commands.command_23_24 import Command2324 +#from commands.command_26_27 import Command2627 + +__all__ = ['Command02', 'Command03', 'CommandHeartbeat','Command07','Command08','Command09', + 'Command0A','Command25','Command30','Command191A','Command2122','Command2324'] \ No newline at end of file diff --git a/charging_pile_proxy/commands/__pycache__/__init__.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/__init__.cpython-311.pyc index 47800df..1c28149 100644 Binary files a/charging_pile_proxy/commands/__pycache__/__init__.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/__init__.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/__pycache__/command_19_1A.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/command_19_1A.cpython-311.pyc index 263e5ca..4e2dcc9 100644 Binary files a/charging_pile_proxy/commands/__pycache__/command_19_1A.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/command_19_1A.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/__pycache__/command_21_22.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/command_21_22.cpython-311.pyc index 8888ba1..190768e 100644 Binary files a/charging_pile_proxy/commands/__pycache__/command_21_22.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/command_21_22.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/__pycache__/command_25.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/command_25.cpython-311.pyc index bf8bfc3..bf589cb 100644 Binary files a/charging_pile_proxy/commands/__pycache__/command_25.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/command_25.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/__pycache__/command_26_27.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/command_26_27.cpython-311.pyc index 83630c6..b0dc85a 100644 Binary files a/charging_pile_proxy/commands/__pycache__/command_26_27.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/command_26_27.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/__pycache__/command_heartbeat.cpython-311.pyc b/charging_pile_proxy/commands/__pycache__/command_heartbeat.cpython-311.pyc index a2ecbac..bb77b8c 100644 Binary files a/charging_pile_proxy/commands/__pycache__/command_heartbeat.cpython-311.pyc and b/charging_pile_proxy/commands/__pycache__/command_heartbeat.cpython-311.pyc differ diff --git a/charging_pile_proxy/commands/command_19_1A.py b/charging_pile_proxy/commands/command_19_1A.py index ed5b136..503d9bd 100644 --- a/charging_pile_proxy/commands/command_19_1A.py +++ b/charging_pile_proxy/commands/command_19_1A.py @@ -1,126 +1,98 @@ import struct import logging -import binascii +from datetime import datetime class Command191A: def __init__(self): - self.command_19 = 0x19 # 卡鉴权上报命令 - self.command_1a = 0x1A # 平台回复卡鉴权命令 + self.command_19 = 0x19 # 卡鉴权命令 + self.command_1a = 0x1A # 卡鉴权响应 - def parse_19_card_auth(self, data): - """ - 解析19H卡鉴权上报命令 - - :param data: 完整的19H命令报文 - :return: 解析后的字典或None - """ + def parse_19h(self, data): + """解析19H卡鉴权命令""" try: - # 验证基本帧格式 - if len(data) < 14 or data[0:2] != b'JX' or data[2] != 0x19: - logging.warning(f"19H命令帧格式不正确,原始报文: {binascii.hexlify(data)}") + print("\n开始解析19H卡鉴权命令...") + print(f"接收数据: {data.hex().upper()}") + + # 基础验证 + if len(data) < 14 or data[0:2] != b'JX' or data[2] != self.command_19: + logging.warning("19H命令帧格式不正确") return None - # 打印完整的原始报文以便调试 - print(f"完整原始报文: {binascii.hexlify(data)}") + # 解析数据 + pile_id = data[3:11] # 桩号 + encrypt_mode = data[11] # 加密方式 + data_len = struct.unpack(" 2025-01-09 12:15:44 + """ - # 提取时间标识 - 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}" + def bcd_to_int(byte): + """BCD转换为整数""" + return ((byte >> 4) * 10) + (byte & 0x0F) - # 解析充电参数 - current_index = 20 - charging_voltage = struct.unpack(" 25 -> 2025年) + month = bcd_to_int(time_bytes[1]) # BCD月 (0x01 -> 1月) + day = bcd_to_int(time_bytes[2]) # BCD日 (0x09 -> 9日) + hour = bcd_to_int(time_bytes[3]) # BCD时 (0x0C -> 12时) + minute = bcd_to_int(time_bytes[4]) # BCD分 (0x16 -> 22分) + second = bcd_to_int(time_bytes[5]) # BCD秒 (0x12 -> 18秒) - charging_current = struct.unpack("= 14 and data[0:2] == b'JX': command = data[2] # 提取命令字节 + # 获取本地和远程端口信息用于日志 + source_local, source_remote = self.utils.get_socket_info(source_socket) + dest_local, dest_remote = self.utils.get_socket_info(destination_socket) + # 根据命令字节处理不同命令 - if command == 0x01: - logging.info(f"处理 01H 命令,数据内容: {data.hex()}") - self.command_handler.parse_01h(data) + if command == 0x01: # 01H命令 + logging.info(f"收到01H连接请求命令: {data.hex().upper()}") + if self.command_handler.process_and_respond(data, destination_socket): + logging.info("01H命令处理完成") + continue # 跳过后续转发 - elif command == 0x02: - logging.info(f"处理 02H 命令,数据内容: {data.hex()}") - self.command_handler.parse_02h(data) + elif command == 0x03: # 03H登录命令 + logging.info(f"收到03H登录命令: {data.hex().upper()}") + self.command_handler.process_03h(data) - elif command == 0x03: - logging.info(f"处理 03H 命令,数据内容: {data.hex()}") - self.command_handler.parse_03h(data) + elif command == 0x0C: # 0CH桩心跳命令 + logging.info(f"收到0CH心跳命令: {data.hex().upper()}") + if self.heartbeat_handler.process_and_respond(data, destination_socket): + logging.info("0CH心跳命令处理完成") + continue # 跳过后续转发 - elif command == 0x07: - logging.info(f"处理 07H 命令,数据内容: {data.hex()}") - self.command_handler.parse_07h(data) + elif command == 0x19: # 19H卡鉴权命令 + logging.info(f"收到19H卡鉴权命令: {data.hex().upper()}") + if self.card_auth_handler.process_and_respond(data, destination_socket): + logging.info("19H卡鉴权命令处理完成") + continue # 跳过后续转发 - elif command == 0x08: - logging.info(f"处理 08H 命令,数据内容: {data.hex()}") - self.command_handler.parse_08h(data) - elif command == 0x09: - logging.info(f"处理 09H 命令,数据内容: {data.hex()}") - self.command_handler.parse_09h(data) + elif command == 0x21: # 21H启动充电结果命令 - elif command == 0x0A: - logging.info(f"处理 0AH 命令,数据内容: {data.hex()}") - self.command_handler.parse_0Ah(data) + logging.info(f"收到21H启动充电结果命令: {data.hex()}") - #其他命令待添加... + if self.charge_result_handler.process_and_respond(data, destination_socket): + continue # 跳过后续转发 + + elif command == 0x23: # 23H充电订单命令 + logging.info(f"收到23H充电订单命令: {data.hex().upper()}") + if self.order_handler.process_and_respond(data, destination_socket): + logging.info("23H充电订单命令处理完成") + continue + + + elif command == 0x25: # 25H充电信息命令 + + logging.info(f"收到25H充电信息命令: {data.hex()}") + + if self.charge_info_handler.process_25h(data): + logging.info("25H命令处理完成") + + elif command == 0x30: # 30H BMS信息命令 + logging.info(f"收到30H BMS信息命令: {data.hex().upper()}") + if self.bms_handler.process_30h(data): + logging.info("30H BMS信息命令处理完成") else: - # 未知命令,日志记录 - logging.warning(f"未知命令:{command:02X},数据内容: {data.hex()}") + # 未知命令,记录日志 + logging.warning(f"未知命令:{command:02X},数据内容: {data.hex().upper()}") - # 将数据转发到远程或充电桩,判断方向 - if source_socket not in self.remote_connections.values(): - # 这里是判断是否是客户端连接,进行桩ID提取 - pile_id = self.utils.extract_pile_id(data) - if pile_id: - self.pile_ids[source_address] = pile_id + # 如果数据来自客户端连接,提取桩号 + if source_socket not in self.remote_connections.values(): + pile_id = self.utils.extract_pile_id(data) + if pile_id: + self.pile_ids[source_address] = pile_id - # 获取本地和远程端口信息 - source_local, source_remote = self.utils.get_socket_info(source_socket) - dest_local, dest_remote = self.utils.get_socket_info(destination_socket) + # 判断数据发送方向:是发送到远程服务器还是充电桩 + is_to_remote = destination_socket in self.remote_connections.values() + direction = "发送到远程服务器" if is_to_remote else "发送到充电桩" + mqtt_direction = "u" if is_to_remote else "d" - # 判断数据发送方向:是发送到远程服务器还是充电桩 - is_to_remote = destination_socket in self.remote_connections.values() - direction = "发送到远程服务器" if is_to_remote else "发送到充电桩" - mqtt_direction = "u" if is_to_remote else "d" + # 发送数据到目的地 + destination_socket.send(data) - # 发送数据到目的地 - destination_socket.send(data) + # 记录数据转发日志 + msg = (f"数据转发成功: {direction} | " + f"本地地址: {source_local} | " + f"远程地址: {dest_remote} | " + f"命令: {command:02X}H | " + f"数据长度: {len(data)}") + logging.info(msg) + self.mqtt_client.publish_message(msg) - # 记录数据转发日志 - msg = f"数据转发成功: {direction} | 本地地址: {source_local} | 远程地址: {dest_remote} | 数据长度: {len(data)}" - logging.info(msg) - self.mqtt_client.publish_message(msg) + # 记录完整的数据内容到调试日志 + logging.debug(f"完整数据内容: {data.hex().upper()}") - # 每次数据转发完成后,处理其他相关操作 - # 例如检查是否需要断开连接等 - if not self.running: - break + # 每次数据转发完成后,检查连接状态 + if not self.running: + break + + except ConnectionResetError: + logging.error(f"连接被重置: {source_remote}") + self.mqtt_client.publish_message(f"连接被重置: {source_remote}") + + except socket.timeout: + logging.error(f"连接超时: {source_remote}") + self.mqtt_client.publish_message(f"连接超时: {source_remote}") except Exception as e: - # 异常处理,日志记录错误信息 logging.error(f"转发数据出错: {str(e)}") - print(f"转发数据出错: {str(e)}") self.mqtt_client.publish_message(f"转发数据出错: {str(e)}") - # 若需要,可以选择关闭连接 - if source_socket: - source_socket.close() - if destination_socket: - destination_socket.close() + + finally: + # 关闭连接 + try: + if source_socket: + source_socket.close() + if destination_socket: + destination_socket.close() + except Exception as e: + logging.error(f"关闭连接出错: {str(e)}") def handle_client(self, client_socket, client_address): """处理客户端连接"""