Files

191 lines
8.4 KiB
Python
Raw Permalink Normal View History

2026-06-16 15:40:19 +08:00
# # -*- coding: utf-8 -*-
"""
Author Tan Mingyan
@Time : 2026/2/27
"""
"""
UDP数据协议分发处理器
功能解析udp_server.recv_multi_udp_hex()返回的数据按protocol字段分发到对应处理函数
支持协议UARTSYNCCAN1553BADOC网络
"""
import sys
import io
import os
# 设置标准输出和标准错误的编码为UTF-8
# sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
from loguru import logger
from typing import List, Dict, Any
from pathlib import Path
# 获取当前文件的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 获取上级目录(项目根目录)
parent_dir = os.path.dirname(current_dir)
# 将项目根目录添加到系统路径
sys.path.append(parent_dir)
sys.path.append(str(Path(__file__).parent.parent.parent))
import midware.config.base_config as base_config
#from midware.config.base_config import DEVICE_CONFIG_DICT, UDP_CONFIG
# ==================== 协议类型常量(统一管理,避免硬编码)====================
# 与你要求的协议类型严格对应
PROTOCOL_UART = "UART"
PROTOCOL_SYNC = "SYNC"
PROTOCOL_CAN = "CAN"
PROTOCOL_1553B = "1553B"
PROTOCOL_AD = "AD"
PROTOCOL_OC = "OC"
PROTOCOL_NETWORK = "网络"
# 支持的协议列表(用于合法性校验)
SUPPORTED_PROTOCOLS = [
PROTOCOL_UART,
PROTOCOL_SYNC,
PROTOCOL_CAN,
PROTOCOL_1553B,
PROTOCOL_AD,
PROTOCOL_OC,
PROTOCOL_NETWORK
]
# ==================== 各协议处理函数(预留接口,按需填充逻辑)====================
def handle_uart(data: Dict[str, Any]) -> None:
"""处理UART协议数据"""
logger.info(f"[UART处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充UART数据解析、转发、故障注入等业务逻辑
pass
def handle_sync(data: Dict[str, Any]) -> None:
"""处理SYNC同步协议数据"""
logger.info(f"[SYNC处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充SYNC同步数据解析、时序控制等业务逻辑
pass
def handle_can(data: Dict[str, Any]) -> None:
"""处理CAN协议数据"""
logger.info(f"[CAN处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充CAN帧解析、总线转发等业务逻辑
pass
def handle_1553b(data: Dict[str, Any]) -> None:
"""处理1553B协议数据"""
logger.info(f"[1553B处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充1553B总线数据解析、RT/BC交互等业务逻辑
pass
def handle_ad(data: Dict[str, Any]) -> None:
"""处理AD模拟量输入协议数据"""
logger.info(f"[AD处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充AD采样值解析、校准、越限告警等业务逻辑
pass
def handle_oc(data: Dict[str, Any]) -> None:
"""处理OC数字量输出协议数据"""
logger.info(f"[OC处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充OC通道控制、状态反馈、故障模拟等业务逻辑
pass
def handle_network(data: Dict[str, Any]) -> None:
"""处理网络协议数据"""
logger.info(f"[网络处理] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | 数据长度:{len(data.get('raw_data', b''))}字节")
# TODO: 补充网络包转发、IP/TCP解析、网络故障注入等业务逻辑
pass
def handle_unknown_protocol(data: Dict[str, Any]) -> None:
"""处理未知协议数据(容错兜底)"""
unknown_protocol = data.get('protocol', '未知')
logger.warning(
f"[未知协议] 外设:{data.get('dev_name', '未知')} | 端口:{data.get('port', '未知')} | "
f"协议类型:{unknown_protocol} | 支持的协议列表:{SUPPORTED_PROTOCOLS}"
)
# ==================== 核心分发函数(对外暴露的唯一入口)====================
def dispatch_udp_data(recv_data: List[Dict[str, Any]]) -> None:
"""
核心分发函数遍历recv_data按protocol分发到对应处理函数
:param recv_data: udp_server.recv_multi_udp_hex()返回的原始数据列表每条数据格式
{"port": 端口号, "dev_name": 外设名, "protocol": 协议类型, "raw_data": 原始二进制数据}
"""
# 第一步:校验输入数据类型
if not isinstance(recv_data, list):
logger.error("分发失败输入的recv_data不是列表类型")
return
# 第二步:空数据直接返回(避免无意义日志)
if not recv_data:
return
# 第三步:构建协议-处理函数映射表(核心:新增/修改协议只需改此表)
protocol_handler_map = {
PROTOCOL_UART: handle_uart,
PROTOCOL_SYNC: handle_sync,
PROTOCOL_CAN: handle_can,
PROTOCOL_1553B: handle_1553b,
PROTOCOL_AD: handle_ad,
PROTOCOL_OC: handle_oc,
PROTOCOL_NETWORK: handle_network
}
# 第四步:遍历每条数据,按协议分发处理
for single_data in recv_data:
try:
# 容错确保protocol字段存在且为字符串
protocol = single_data.get("protocol", "").strip().upper()
port = single_data["port"]
dev_name = single_data["dev_name"]
# protocol = data["protocol"]
raw_data = single_data["raw_data"]
#根据dev_name获取内存基地址偏移地址发送缓存区大小接收缓存区大小
#dev_info = DEVICE_CONFIG_DICT.get(dev_name, {})
if dev_name not in base_config.DEVICE_CONFIG_DICT:
logger.error(f"UART外设不存在{dev_name}")
return False
# 获取外设基地址、偏移地址
base_addr = base_config.DEVICE_CONFIG_DICT[device_name]["base_addr"]
offset_addr = base_config.DEVICE_CONFIG_DICT[device_name]["offset_addr"]
print(f"sysbus WriteDoubleWord {base_addr + offset_addr} {raw_data}")
# 兼容协议名大小写(如"can"→"CAN"、"sync"→"SYNC"
if protocol in protocol_handler_map:
# 调用对应处理函数
protocol_handler_map[protocol](single_data)
else:
# 未知协议调用兜底函数
handle_unknown_protocol(single_data)
except Exception as e:
# 单条数据处理异常不影响整体,记录错误日志
logger.error(
f"[数据处理异常] 外设:{single_data.get('dev_name', '未知')} | 错误信息:{str(e)}",
exc_info=True
)
# ==================== 测试用例(验证分发逻辑是否正常)====================
def test_dispatcher():
"""模拟udp_server.recv_multi_udp_hex()返回的数据,测试分发逻辑"""
# 模拟接收数据
mock_recv_data = [
{"port": 8880, "dev_name": "Uart0", "protocol": "uart", "raw_data": b"UART_TEST_DATA"},
{"port": 8881, "dev_name": "Sync0", "protocol": "SYNC", "raw_data": b"SYNC_TEST_DATA"},
{"port": 8882, "dev_name": "Can1", "protocol": "Can", "raw_data": b"CAN_TEST_DATA"},
{"port": 8883, "dev_name": "1553B0", "protocol": "1553B", "raw_data": b"1553B_TEST_DATA"},
{"port": 8884, "dev_name": "AD0", "protocol": "ad", "raw_data": b"AD_TEST_DATA"},
{"port": 8885, "dev_name": "OC0", "protocol": "OC", "raw_data": b"OC_TEST_DATA"},
{"port": 8886, "dev_name": "Net0", "protocol": "网络", "raw_data": b"NETWORK_TEST_DATA"},
{"port": 8887, "dev_name": "Unknown0", "protocol": "SPI", "raw_data": b"UNKNOWN_TEST_DATA"},
]
# 执行分发
logger.info("开始测试协议分发逻辑...")
dispatch_udp_data(mock_recv_data)
logger.info("协议分发测试完成")
if __name__ == "__main__":
# 运行测试用例,验证分发逻辑
test_dispatcher()