no message
This commit is contained in:
parent
4304015dd6
commit
e8d33efc42
@ -10,9 +10,10 @@ from commands.command_0A import Command0A
|
|||||||
from commands.command_25 import Command25
|
from commands.command_25 import Command25
|
||||||
from commands.command_30 import Command30
|
from commands.command_30 import Command30
|
||||||
from commands.command_19_1A import Command191A
|
from commands.command_19_1A import Command191A
|
||||||
|
from commands.command_1F_20 import Command1F20
|
||||||
from commands.command_21_22 import Command2122
|
from commands.command_21_22 import Command2122
|
||||||
from commands.command_23_24 import Command2324
|
from commands.command_23_24 import Command2324
|
||||||
#from commands.command_26_27 import Command2627
|
from commands.command_26_27 import Command2627
|
||||||
|
|
||||||
__all__ = ['Command02', 'Command03', 'CommandHeartbeat','Command07','Command08','Command09',
|
__all__ = ['Command02', 'Command03', 'CommandHeartbeat','Command07','Command08','Command09',
|
||||||
'Command0A','Command25','Command30','Command191A','Command2122','Command2324']
|
'Command0A','Command25','Command30','Command191A','Command2122','Command2324','Command1F20']
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -46,111 +46,122 @@ class Command02:
|
|||||||
def validate_frame(self, data):
|
def validate_frame(self, data):
|
||||||
"""验证帧格式"""
|
"""验证帧格式"""
|
||||||
try:
|
try:
|
||||||
print(f"\n验证帧格式:")
|
print("\n开始验证帧格式:")
|
||||||
print(f"数据内容: {data.hex()}")
|
print(f"数据内容: {data.hex().upper()}")
|
||||||
print(f"数据长度: {len(data)}字节")
|
print(f"数据长度: {len(data)}字节")
|
||||||
|
|
||||||
# 1. 基本长度检查
|
# 1. 基本格式检查
|
||||||
if len(data) < 14:
|
if len(data) < 14:
|
||||||
print("数据长度不足14字节,无效")
|
print("数据长度不足14字节")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 2. 检查帧起始标志
|
|
||||||
if data[0:2] != b'JX':
|
if data[0:2] != b'JX':
|
||||||
print("帧起始标志不是'JX',无效")
|
print("帧起始标志不是'JX'")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 3. 获取并检查数据域长度
|
# 2. 获取数据域长度
|
||||||
data_len = struct.unpack("<H", data[12:14])[0]
|
data_len = struct.unpack("<H", data[12:14])[0]
|
||||||
print(f"数据域长度字段值: {data_len}")
|
expected_total_len = 14 + data_len + 1 # 头部(14) + 数据域 + 校验码(1)
|
||||||
|
|
||||||
# 4. 计算并检查总长度
|
# 如果数据长度不匹配,尝试修正数据
|
||||||
expected_len = 16 + data_len # 固定部分(14) + 数据域 + 校验码(1)
|
if len(data) != expected_total_len:
|
||||||
print(f"期望总长度: {expected_len}")
|
print(f"数据长度不匹配,尝试修正...")
|
||||||
print(f"实际长度: {len(data)}")
|
if len(data) > expected_total_len:
|
||||||
|
print(f"截断多余数据")
|
||||||
|
data = data[:expected_total_len]
|
||||||
|
else:
|
||||||
|
print("数据不完整")
|
||||||
|
return False
|
||||||
|
|
||||||
if len(data) != expected_len:
|
# 3. 显示数据结构
|
||||||
print("数据总长度不匹配")
|
print(f"\n数据结构分析:")
|
||||||
return False
|
print(f"起始标识: {data[0:2].hex().upper()}")
|
||||||
|
print(f"命令字: {data[2]:02X}")
|
||||||
|
print(f"桩号: {data[3:11].hex().upper()}")
|
||||||
|
print(f"加密方式: {data[11]:02X}")
|
||||||
|
print(f"数据长度: {data_len}")
|
||||||
|
print(f"数据域: {data[14:14 + data_len].hex().upper()}")
|
||||||
|
print(f"校验码: {data[-1]:02X}")
|
||||||
|
|
||||||
# 5. 验证校验码
|
# 4. 校验码验证
|
||||||
check_data = data[2:-1] # 从命令字节到校验码前的数据
|
check_data = data[2:-1]
|
||||||
calculated_check = 0
|
calculated_check = 0
|
||||||
for b in check_data:
|
for b in check_data:
|
||||||
calculated_check ^= b
|
calculated_check ^= b
|
||||||
|
|
||||||
received_check = data[-1]
|
if calculated_check != data[-1]:
|
||||||
print(f"计算得到的校验码: {calculated_check:02X}")
|
print(f"校验码不匹配: 计算值={calculated_check:02X}, 接收值={data[-1]:02X}")
|
||||||
print(f"接收到的校验码: {received_check:02X}")
|
|
||||||
|
|
||||||
if calculated_check != received_check:
|
|
||||||
print("校验码不匹配")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("帧格式验证通过")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"帧格式验证出错: {str(e)}")
|
print(f"验证帧格式异常: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def debug_print_fields(self, data):
|
||||||
|
"""打印数据包的详细字段"""
|
||||||
|
print("\n===== 数据包解析 =====")
|
||||||
|
print("1. 固定头部:")
|
||||||
|
print(f" 起始标识 (2字节): {data[0:2].hex().upper()}")
|
||||||
|
print(f" 命令码 (1字节): {data[2]:02X}")
|
||||||
|
print(f" 桩号 (8字节): {data[3:11].hex().upper()}")
|
||||||
|
print(f" 加密方式 (1字节): {data[11]:02X}")
|
||||||
|
print(f" 数据域长度 (2字节): {struct.unpack('<H', data[12:14])[0]}")
|
||||||
|
|
||||||
|
data_len = struct.unpack("<H", data[12:14])[0]
|
||||||
|
print("\n2. 数据域:")
|
||||||
|
print(f" 时间标识 (6字节): {data[14:20].hex().upper()}")
|
||||||
|
print(f" 密钥版本 (2字节): {data[20:22].hex().upper()}")
|
||||||
|
print(f" 校验密文 (8字节): {data[22:30].hex().upper()}")
|
||||||
|
|
||||||
|
print(f"\n3. 校验码 (1字节): {data[-1]:02X}")
|
||||||
|
|
||||||
|
# 检查是否有多余字节
|
||||||
|
expected_len = 14 + data_len + 1
|
||||||
|
if len(data) > expected_len:
|
||||||
|
print(f"\n警告: 发现多余字节:")
|
||||||
|
print(f"多余字节内容: {data[expected_len:].hex().upper()}")
|
||||||
|
|
||||||
def parse_01h(self, data):
|
def parse_01h(self, data):
|
||||||
"""解析01H命令数据"""
|
"""解析01H命令数据"""
|
||||||
try:
|
try:
|
||||||
print("\n开始解析01H命令...")
|
print("\n开始解析01H命令...")
|
||||||
|
|
||||||
if not self.validate_frame(data):
|
if not self.validate_frame(data):
|
||||||
raise ValueError("帧格式验证失败")
|
raise ValueError("帧格式验证失败")
|
||||||
|
|
||||||
|
# 提取基本信息
|
||||||
command = data[2]
|
command = data[2]
|
||||||
pile_id = data[3:11]
|
pile_id = data[3:11]
|
||||||
encrypt_mode = data[11]
|
encrypt_mode = data[11]
|
||||||
data_len = struct.unpack("<H", data[12:14])[0]
|
data_field = data[14:-1] # 从数据域开始到校验码之前
|
||||||
data_field = data[14:14 + data_len]
|
|
||||||
|
|
||||||
# 解析时间标识
|
# 解析数据域内容
|
||||||
time_bytes = data_field[0:6]
|
time_bytes = data_field[0:6]
|
||||||
year = time_bytes[0] + 2000
|
year = time_bytes[0] + 2000
|
||||||
month, day, hour, minute, second = time_bytes[1:6]
|
month, day, hour, minute, second = time_bytes[1:6]
|
||||||
timestamp = f"{year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}"
|
timestamp = f"{year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}"
|
||||||
|
|
||||||
# 解析密钥版本和校验密文
|
|
||||||
key_version = struct.unpack("<H", data_field[6:8])[0]
|
key_version = struct.unpack("<H", data_field[6:8])[0]
|
||||||
check_text = data_field[8:16]
|
check_text = data_field[8:16]
|
||||||
|
|
||||||
# 解析桩号
|
|
||||||
pile_info = self.parse_pile_id(pile_id)
|
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"command": command,
|
"command": command,
|
||||||
"pile_id": pile_id,
|
"pile_id": pile_id,
|
||||||
"pile_info": pile_info,
|
|
||||||
"encrypt_mode": encrypt_mode,
|
"encrypt_mode": encrypt_mode,
|
||||||
"timestamp": timestamp,
|
"timestamp": timestamp,
|
||||||
"key_version": key_version,
|
"key_version": key_version,
|
||||||
"check_text": check_text
|
"check_text": check_text
|
||||||
}
|
}
|
||||||
|
|
||||||
print("\n解析结果:")
|
|
||||||
print(f"命令码: {command:02X}")
|
|
||||||
print(f"桩号信息: {pile_info}")
|
|
||||||
print(f"加密方式: {encrypt_mode:02X}")
|
|
||||||
print(f"时间标识: {timestamp}")
|
|
||||||
print(f"密钥版本: {key_version}")
|
|
||||||
print(f"校验密文: {check_text.hex()}")
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"解析01H命令失败: {str(e)}")
|
|
||||||
print(f"解析失败: {str(e)}")
|
print(f"解析失败: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def build_02h_response(self, pile_id, allow=True, reject_reason=0):
|
def build_02h_response(self, pile_id, allow=True, reject_reason=0):
|
||||||
"""构建02H响应命令"""
|
"""构建02H响应命令"""
|
||||||
try:
|
try:
|
||||||
print("\n构建02H响应...")
|
|
||||||
|
|
||||||
frame = bytearray()
|
frame = bytearray()
|
||||||
frame.extend(b'JX') # 帧起始标志
|
frame.extend(b'JX') # 帧起始标志
|
||||||
frame.append(self.command) # 命令
|
frame.append(self.command) # 命令
|
||||||
@ -159,83 +170,83 @@ class Command02:
|
|||||||
|
|
||||||
data = bytearray()
|
data = bytearray()
|
||||||
|
|
||||||
# 时间标识
|
# 添加时间标识 (6字节)
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
data.extend(struct.pack("<BBBBBB",
|
data.extend(struct.pack("<BBBBBB",
|
||||||
now.year - 2000, now.month, now.day,
|
now.year - 2000, now.month, now.day,
|
||||||
now.hour, now.minute, now.second))
|
now.hour, now.minute, now.second))
|
||||||
|
|
||||||
# 请求结果
|
# 添加请求结果和拒绝原因
|
||||||
data.append(0x01 if allow else 0x02)
|
data.append(0x01 if allow else 0x02)
|
||||||
|
|
||||||
# 拒绝原因
|
|
||||||
data.append(reject_reason)
|
data.append(reject_reason)
|
||||||
|
|
||||||
if allow:
|
if allow:
|
||||||
# 二维码固定段
|
# 添加二维码固定段 (100字节)
|
||||||
data.extend(self.qr_fixed.ljust(100, '\x00').encode())
|
fixed_part = self.qr_fixed.encode()
|
||||||
|
data.extend(fixed_part.ljust(100, b'\x00'))
|
||||||
|
|
||||||
# 二维码枪号段数量
|
# 添加二维码枪号段数量
|
||||||
data.append(0x02)
|
data.append(0x02) # 2个充电枪
|
||||||
|
|
||||||
# 二维码枪号段1和2
|
# 添加枪号段 (每个20字节)
|
||||||
pile_id_str = ''.join([f"{b:02X}" for b in pile_id])
|
pile_id_str = ''.join([f"{b:02X}" for b in pile_id])
|
||||||
gun1 = f"{pile_id_str}001"
|
gun1 = f"{pile_id_str}001"
|
||||||
gun2 = f"{pile_id_str}002"
|
gun2 = f"{pile_id_str}002"
|
||||||
|
data.extend(gun1.encode().ljust(20, b'\x00'))
|
||||||
|
data.extend(gun2.encode().ljust(20, b'\x00'))
|
||||||
|
|
||||||
data.extend(gun1.ljust(20, '\x00').encode())
|
# 添加数据域长度
|
||||||
data.extend(gun2.ljust(20, '\x00').encode())
|
|
||||||
|
|
||||||
# 数据域长度
|
|
||||||
frame.extend(struct.pack("<H", len(data)))
|
frame.extend(struct.pack("<H", len(data)))
|
||||||
|
|
||||||
# 数据域
|
# 添加数据域
|
||||||
frame.extend(data)
|
frame.extend(data)
|
||||||
|
|
||||||
# 计算校验码
|
# 计算并添加校验码
|
||||||
check = 0
|
check = 0
|
||||||
for b in frame[2:]:
|
for b in frame[2:]: # 从命令字节开始异或
|
||||||
check ^= b
|
check ^= b
|
||||||
frame.append(check)
|
frame.append(check)
|
||||||
|
|
||||||
print("响应数据构建成功:")
|
|
||||||
print(f"数据内容: {frame.hex()}")
|
|
||||||
print(f"数据长度: {len(frame)}字节")
|
|
||||||
|
|
||||||
return bytes(frame)
|
return bytes(frame)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"构建02H响应失败: {str(e)}")
|
logging.error(f"构建02H响应失败: {str(e)}")
|
||||||
print(f"构建响应失败: {str(e)}")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_and_respond(self, received_data, sock):
|
def process_and_respond(self, received_data, sock):
|
||||||
"""处理收到的01H命令并回复02H"""
|
"""处理收到的01H命令并回复02H"""
|
||||||
try:
|
try:
|
||||||
print("\n处理01H命令并生成响应...")
|
# 基础验证
|
||||||
|
if not self.validate_frame(received_data):
|
||||||
# 解析收到的01H命令
|
logging.error("01H命令帧格式验证失败")
|
||||||
parsed = self.parse_01h(received_data)
|
|
||||||
if not parsed:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 构建02H响应
|
# 提取必要信息
|
||||||
allow = True # 这里可以根据业务逻辑判断是否允许连接
|
pile_id = received_data[3:11] # 桩号
|
||||||
reject_reason = 0
|
time_bytes = received_data[14:20] # 时间标识
|
||||||
|
key_version = struct.unpack("<H", received_data[20:22])[0] # 密钥版本
|
||||||
|
|
||||||
response = self.build_02h_response(parsed["pile_id"], allow, reject_reason)
|
# 检查时间是否在合理范围内
|
||||||
if not response:
|
cmd_time = datetime(2000 + time_bytes[0], time_bytes[1], time_bytes[2],
|
||||||
return False
|
time_bytes[3], time_bytes[4], time_bytes[5])
|
||||||
|
time_diff = abs((datetime.now() - cmd_time).total_seconds())
|
||||||
|
|
||||||
# 发送响应
|
if time_diff > 600: # 超过10分钟
|
||||||
if hasattr(sock, 'send'):
|
logging.warning(f"时间差异过大: {time_diff}秒")
|
||||||
|
response = self.build_02h_response(pile_id, False, 6) # 拒绝原因6-时差过大
|
||||||
|
else:
|
||||||
|
# 这里可以添加更多的验证逻辑
|
||||||
|
response = self.build_02h_response(pile_id, True, 0)
|
||||||
|
|
||||||
|
if response and hasattr(sock, 'send'):
|
||||||
sock.send(response)
|
sock.send(response)
|
||||||
|
logging.info(f"成功发送02H响应, 长度: {len(response)}字节")
|
||||||
|
return True
|
||||||
|
|
||||||
return True
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"处理和响应失败: {str(e)}")
|
logging.error(f"处理01H命令失败: {str(e)}")
|
||||||
print(f"处理失败: {str(e)}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -243,29 +254,31 @@ def test_command():
|
|||||||
"""测试函数"""
|
"""测试函数"""
|
||||||
print("开始测试01H/02H命令处理...")
|
print("开始测试01H/02H命令处理...")
|
||||||
|
|
||||||
# 配置日志
|
|
||||||
# logging.basicConfig(
|
|
||||||
# filename='command_response_02h.log',
|
|
||||||
# level=logging.INFO,
|
|
||||||
# format='%(asctime)s - %(levelname)s - %(message)s',
|
|
||||||
# encoding='utf-8'
|
|
||||||
# )
|
|
||||||
|
|
||||||
# 创建响应处理器
|
# 创建响应处理器
|
||||||
handler = Command02()
|
handler = Command02()
|
||||||
|
|
||||||
# 测试数据 - 使用实际收到的数据
|
# 原始测试数据
|
||||||
test_data = bytes.fromhex("4A5801031767631136065701100019010909371501000000000000000000004D")
|
hex_string = "4A5801031767631136065701100019010909371501000000000000000000004D"
|
||||||
|
|
||||||
|
# 解析数据长度字段以确定正确的数据包长度
|
||||||
|
expected_len = 14 + 16 + 1 # 头部(14字节) + 数据域(16字节) + 校验码(1字节)
|
||||||
|
|
||||||
|
# 确保只取需要的字节
|
||||||
|
test_data = bytes.fromhex(hex_string[:expected_len * 2]) # *2是因为hex字符串中一个字节用两个字符表示
|
||||||
|
|
||||||
print("\n测试数据:")
|
print("\n测试数据:")
|
||||||
print(f"十六进制: {test_data.hex()}")
|
print(f"原始数据: {hex_string}")
|
||||||
print(f"长度: {len(test_data)}字节")
|
print(f"处理后数据: {test_data.hex().upper()}")
|
||||||
|
print(f"数据长度: {len(test_data)}字节")
|
||||||
|
|
||||||
|
# 打印详细字段解析
|
||||||
|
handler.debug_print_fields(test_data)
|
||||||
|
|
||||||
# 创建模拟socket
|
# 创建模拟socket
|
||||||
class MockSocket:
|
class MockSocket:
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
print(f"\n模拟发送响应数据:")
|
print(f"\n模拟发送响应数据:")
|
||||||
print(f"数据内容: {data.hex()}")
|
print(f"数据内容: {data.hex().upper()}")
|
||||||
print(f"数据长度: {len(data)}字节")
|
print(f"数据长度: {len(data)}字节")
|
||||||
|
|
||||||
mock_sock = MockSocket()
|
mock_sock = MockSocket()
|
||||||
|
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
import socket
|
import socket
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
from .utils import ProxyUtils
|
from .utils import ProxyUtils
|
||||||
from .mqtt_client import MQTTClient
|
from .mqtt_client import MQTTClient
|
||||||
from commands.command_heartbeat import CommandHeartbeat
|
from commands.command_heartbeat import CommandHeartbeat
|
||||||
@ -61,8 +62,61 @@ class ChargingPileProxyServer:
|
|||||||
# 存储心跳信息的字典
|
# 存储心跳信息的字典
|
||||||
self.heartbeat_info = {}
|
self.heartbeat_info = {}
|
||||||
|
|
||||||
|
self.heartbeat_thread = threading.Thread(target=self.check_heartbeat_timeout)
|
||||||
|
self.heartbeat_thread.daemon = True
|
||||||
|
self.heartbeat_thread.start()
|
||||||
|
|
||||||
|
def check_heartbeat_timeout(self):
|
||||||
|
"""心跳超时检测"""
|
||||||
|
while self.running:
|
||||||
|
try:
|
||||||
|
current_time = time.time()
|
||||||
|
disconnected_piles = []
|
||||||
|
|
||||||
|
for pile_id, last_heartbeat in self.heartbeat_info.items():
|
||||||
|
time_diff = current_time - last_heartbeat
|
||||||
|
|
||||||
|
# 如果超过60秒没收到心跳
|
||||||
|
if time_diff > 60:
|
||||||
|
msg = f"充电桩 {pile_id.hex().upper()} 心跳超时 {time_diff:.1f}秒"
|
||||||
|
logging.warning(msg)
|
||||||
|
print(msg)
|
||||||
|
self.mqtt_client.publish_message(msg)
|
||||||
|
disconnected_piles.append(pile_id)
|
||||||
|
|
||||||
|
# 从心跳信息中移除断开的充电桩
|
||||||
|
for pile_id in disconnected_piles:
|
||||||
|
del self.heartbeat_info[pile_id]
|
||||||
|
self.handle_pile_disconnect(pile_id)
|
||||||
|
|
||||||
|
# 每5秒检查一次
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"心跳检测错误: {str(e)}")
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
def update_heartbeat(self, pile_id):
|
||||||
|
"""更新心跳时间戳"""
|
||||||
|
try:
|
||||||
|
self.heartbeat_info[pile_id] = time.time()
|
||||||
|
logging.debug(f"更新充电桩 {pile_id.hex().upper()} 心跳时间")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"更新心跳时间戳失败: {str(e)}")
|
||||||
|
|
||||||
|
def handle_pile_disconnect(self, pile_id):
|
||||||
|
"""处理充电桩断开连接"""
|
||||||
|
try:
|
||||||
|
msg = f"充电桩 {pile_id.hex().upper()} 断开连接"
|
||||||
|
logging.info(msg)
|
||||||
|
print(msg)
|
||||||
|
self.mqtt_client.publish_message(msg)
|
||||||
|
|
||||||
|
# 可以在这里添加充电桩断开后的清理逻辑
|
||||||
|
# 例如:中断正在进行的充电等
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"处理充电桩断开连接失败: {str(e)}")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""启动代理服务器"""
|
"""启动代理服务器"""
|
||||||
@ -139,16 +193,21 @@ class ChargingPileProxyServer:
|
|||||||
|
|
||||||
# 根据命令字节处理不同命令
|
# 根据命令字节处理不同命令
|
||||||
if command == 0x01: # 01H命令
|
if command == 0x01: # 01H命令
|
||||||
|
logging.info(f"收到01H连接请求命令: {data.hex().upper()}")
|
||||||
if self.command_02_handler.process_and_respond(data, destination_socket):
|
if self.command_02_handler.process_and_respond(data, destination_socket):
|
||||||
continue
|
logging.info("01H命令处理完成")
|
||||||
|
continue # 跳过后续转发,避免重复转发
|
||||||
|
|
||||||
elif command == 0x03: # 03H命令
|
elif command == 0x03: # 03H命令
|
||||||
|
logging.info(f"收到03H登录命令: {data.hex().upper()}")
|
||||||
if self.command_03_handler.process_03h(data):
|
if self.command_03_handler.process_03h(data):
|
||||||
|
logging.info("03H命令处理完成")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif command == 0x0C: # 0CH桩心跳命令
|
elif command == 0x0C: # 0CH桩心跳命令
|
||||||
|
# 提取桩号并更新心跳
|
||||||
|
pile_id = data[3:11]
|
||||||
|
self.update_heartbeat(pile_id)
|
||||||
logging.info(f"收到0CH心跳命令: {data.hex().upper()}")
|
logging.info(f"收到0CH心跳命令: {data.hex().upper()}")
|
||||||
if self.heartbeat_handler.process_and_respond(data, destination_socket):
|
if self.heartbeat_handler.process_and_respond(data, destination_socket):
|
||||||
logging.info("0CH心跳命令处理完成")
|
logging.info("0CH心跳命令处理完成")
|
||||||
@ -160,16 +219,27 @@ class ChargingPileProxyServer:
|
|||||||
logging.info("19H卡鉴权命令处理完成")
|
logging.info("19H卡鉴权命令处理完成")
|
||||||
continue # 跳过后续转发
|
continue # 跳过后续转发
|
||||||
|
|
||||||
|
|
||||||
|
elif command == 0x1F: # 1FH启动充电命令
|
||||||
|
|
||||||
|
logging.info(f"收到1FH启动充电命令: {data.hex()}")
|
||||||
|
|
||||||
|
if self.start_charge_handler.process_and_respond(data, destination_socket):
|
||||||
|
logging.info("1FH命令处理完成")
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
elif command == 0x20: # 20H启动充电回复
|
elif command == 0x20: # 20H启动充电回复
|
||||||
|
|
||||||
logging.info(f"收到20H启动充电回复: {data.hex()}")
|
logging.info(f"收到20H启动充电回复: {data.hex()}")
|
||||||
|
|
||||||
self.start_charge_handler.parse_20h(data)
|
self.start_charge_handler.parse_20h(data)
|
||||||
|
|
||||||
|
|
||||||
elif command == 0x21: # 21H启动充电结果命令
|
elif command == 0x21: # 21H启动充电结果命令
|
||||||
|
|
||||||
logging.info(f"收到21H启动充电结果命令: {data.hex()}")
|
logging.info(f"收到21H启动充电结果命令: {data.hex()}")
|
||||||
|
|
||||||
if self.charge_result_handler.process_and_respond(data, destination_socket):
|
if self.charge_result_handler.process_and_respond(data, destination_socket):
|
||||||
|
logging.info("21H命令处理完成")
|
||||||
continue # 跳过后续转发
|
continue # 跳过后续转发
|
||||||
|
|
||||||
elif command == 0x23: # 23H充电订单命令
|
elif command == 0x23: # 23H充电订单命令
|
||||||
@ -179,6 +249,7 @@ class ChargingPileProxyServer:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
elif command == 0x25: # 25H充电信息命令
|
elif command == 0x25: # 25H充电信息命令
|
||||||
|
|
||||||
logging.info(f"收到25H充电信息命令: {data.hex()}")
|
logging.info(f"收到25H充电信息命令: {data.hex()}")
|
||||||
@ -186,13 +257,19 @@ class ChargingPileProxyServer:
|
|||||||
if self.charge_info_handler.process_25h(data):
|
if self.charge_info_handler.process_25h(data):
|
||||||
logging.info("25H命令处理完成")
|
logging.info("25H命令处理完成")
|
||||||
|
|
||||||
|
elif command == 0x26: # 26H停止充电命令
|
||||||
|
logging.info(f"收到26H停止充电命令: {data.hex()}")
|
||||||
|
if self.stop_charge_handler.build_26h_command(data, destination_socket):
|
||||||
|
logging.info("26H命令处理完成")
|
||||||
|
continue
|
||||||
|
|
||||||
elif command == 0x27: # 27H停止充电回复
|
elif command == 0x27: # 27H停止充电回复
|
||||||
logging.info(f"收到27H停止充电回复: {data.hex()}")
|
logging.info(f"收到27H停止充电回复: {data.hex()}")
|
||||||
self.stop_charge_handler.parse_27h(data)
|
self.stop_charge_handler.parse_27h(data)
|
||||||
|
|
||||||
elif command == 0x30: # 30H BMS信息命令
|
elif command == 0x30: # 30H BMS信息命令
|
||||||
logging.info(f"收到30H BMS信息命令: {data.hex().upper()}")
|
logging.info(f"收到30H BMS信息命令: {data.hex().upper()}")
|
||||||
if self.bms_handler.process_30h(data):
|
if self.bms_handler.parse_30h_bms_status(data):
|
||||||
logging.info("30H BMS信息命令处理完成")
|
logging.info("30H BMS信息命令处理完成")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -4,3 +4,4 @@
|
|||||||
2025-01-17 14:41:09,050 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
2025-01-17 14:41:09,050 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
||||||
2025-01-17 14:58:36,033 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
2025-01-17 14:58:36,033 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
||||||
2025-01-17 17:12:27,913 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
2025-01-17 17:12:27,913 - ERROR - 代理服务器错误: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
|
||||||
|
2025-01-20 09:45:44,376 - INFO - 代理服务器已启动,监听地址: 0.0.0.0:52461
|
||||||
|
Loading…
x
Reference in New Issue
Block a user