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

185 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import struct
import logging
import binascii
class Command191A:
def __init__(self):
self.command_19 = 0x19 # 卡鉴权上报命令
self.command_1a = 0x1A # 平台回复卡鉴权命令
def parse_19_card_auth(self, data):
"""
解析19H卡鉴权上报命令
:param data: 完整的19H命令报文
:return: 解析后的字典或None
"""
try:
# 验证基本帧格式
if len(data) < 14 or data[0:2] != b'JX' or data[2] != 0x19:
logging.warning(f"19H命令帧格式不正确原始报文: {binascii.hexlify(data)}")
return None
# 打印完整的原始报文以便调试
print(f"完整原始报文: {binascii.hexlify(data)}")
# 提取桩号
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}"
# 提取卡号通常是ASCII字符串
card_number_start = 22
card_number_end = card_number_start + 16
card_number = data[card_number_start:card_number_end].decode('ascii').rstrip('\x00')
# 打印解析结果
print("\n19H卡鉴权上报命令解析结果:")
print(f"桩号: {pile_id_bytes.hex()}")
print(f"时间标识: {timestamp}")
print(f"卡号: {card_number}")
return {
"pile_id": pile_id_bytes.hex(),
"timestamp": timestamp,
"card_number": card_number
}
except Exception as e:
logging.error(f"解析19H命令失败: {str(e)}")
logging.error(f"原始报文: {binascii.hexlify(data)}")
return None
def generate_1a_card_auth_response(self, card_number):
"""
生成1AH卡鉴权响应命令
:param card_number: 卡号
:return: 1AH响应报文
"""
try:
# 构建帧
frame = bytearray()
frame.extend(b'JX') # 帧起始标志
frame.append(self.command_1a) # 命令码
frame.extend(bytes.fromhex('0317665611360637')) # 桩号(固定值)
frame.append(0x01) # 数据加密方式
# 构建数据域
data = bytearray()
# 时间标识(当前时间)
from datetime import datetime
now = datetime.now()
data.extend(struct.pack("<BBBBBB",
now.year - 2000, now.month, now.day,
now.hour, now.minute, now.second))
# 卡号16字节ASCII不足补0
card_number_bytes = card_number.ljust(16, '\x00').encode('ascii')
data.extend(card_number_bytes)
# 卡余额假设为0
data.extend(struct.pack("<I", 0)) # 4字节分辨率0.01元
# 允许充电标志1-可充电2-禁止充电)
data.append(0x01)
# 不可充电原因如果允许充电则为0
data.append(0x00)
# 计费模型选择1-使用本地计费模型)
data.append(0x01)
# 计费模型版本假设为1
data.extend(struct.pack("<H", 1))
# 停车费费率假设为0
data.extend(struct.pack("<I", 0))
# 时段数假设为1个
data.append(0x01)
# 第1个时段起始时间假设为全天
data.extend([0x00, 0x00]) # 起始时
# 第1个时段类型平段
data.append(0x03)
# 第1个时段电价费率假设为0.1元/kWh
data.extend(struct.pack("<I", 1000))
# 第1个时段服务费率假设为0.05元/kWh
data.extend(struct.pack("<I", 500))
# 数据域长度
frame.extend(struct.pack("<H", len(data)))
# 加入数据域
frame.extend(data)
# 计算校验码
check = 0
for b in frame[2:]:
check ^= b
frame.append(check)
print("1AH卡鉴权响应数据构建成功:")
print(f"数据内容: {frame.hex()}")
print(f"数据长度: {len(frame)}字节")
return bytes(frame)
except Exception as e:
logging.error(f"生成1AH卡鉴权响应出错: {str(e)}")
return None
def process_19_card_auth(self, data):
"""
处理19H卡鉴权上报命令
:param data: 完整的19H命令报文
:return: 是否成功处理
"""
try:
parsed_data = self.parse_19_card_auth(data)
if parsed_data is None:
logging.warning("19H命令解析失败")
return False
# 记录卡鉴权信息日志
logging.info(f"收到桩号 {parsed_data['pile_id']} 的卡鉴权请求,卡号 {parsed_data['card_number']}")
return True
except Exception as e:
logging.error(f"处理19H命令出错: {str(e)}")
return False
# 测试用例
if __name__ == "__main__":
# 19H命令测试报文
test_19_data = bytes.fromhex(
"4A 58 19 03 17 66 56 11 36 06 37 01 16 00 19 01 09 0C 15 2B 65 36 39 61 32 31 30 33 00 00 00 00 00 00 00 00 14")
# 1AH命令测试报文
test_1a_data = bytes.fromhex(
"4A 58 1A 03 17 66 56 11 36 06 37 01 1D 00 19 01 09 0C 15 2E 65 36 39 61 32 31 30 33 00 00 00 00 00 00 00 00 A5 0E 0D 00 01 00 01 BF")
parser = Command191A()
# 测试解析19H命令
parser.process_19_card_auth(test_19_data)
# 测试生成1AH响应
card_number = "e69a21033"
response = parser.generate_1a_card_auth_response(card_number)
print("\n1AH卡鉴权响应:")
print(response.hex())