Files
virtual_simulation_midware/main-20260227-01.py
2026-06-16 15:40:19 +08:00

191 lines
7.2 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.
# -*- coding: utf-8 -*-
import sys
import os
import io
import time
# 设置标准输出和标准错误的编码为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 midware.ui.main_ui import start_main_ui
from midware.config.base_config import init_base_config
#from midware.core.data_forward import init_forward_service
from midware.config.excel_config import load_csv_config
from midware.core.error_check import check_checksum, verify_frame_integrity
from midware.network.udp_handler import udp_server
from midware.network.protocol_dispatcher import dispatch_udp_data
import midware.config.base_config as base_config
# from midware.config.base_config import init_base_config
# from midware.config.base_config import DEVICE_CONFIG_DICT
# 先导入配置核心模块
from midware.config.base_config import init_base_config, update_device_config, get_device_config
# 后导入UDP模块此时udp_server还是None
from midware.network.udp_handler import MultiUDPServer, udp_server
# 添加工程根目录到环境变量
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
'''
1. 程序入口main.py
负责初始化日志、加载配置、启动 UI 和核心服务,实现程序一键启动
'''
# 初始化日志
def init_logger():
logger.add(
"logs/run_{time:YYYY-MM-DD}.log",
rotation="daily",
level="INFO",
format="{time} | {level} | {module}:{line} | {message}"
)
logger.add(
"logs/error_{time:YYYY-MM-DD}.log",
rotation="daily",
level="ERROR",
format="{time} | {level} | {module}:{line} | {message}"
)
return logger
if __name__ == "__main__":
# 初始化日志
log = init_logger()
log.info("虚拟仿真平台中间层软件启动")
logger.info("========== 虚拟仿真平台中间层软件 启动 ==========")
##试一下2026/2/27
csv_path = "config_files/device_config.csv"
DEVICE_CONFIG_DICT = load_csv_config(csv_path)
#try:
# 初始化基础配置外设、UDP、总线
# 步骤1初始化外设配置核心先初始化配置再实例化其他模块
init_base_config()
device_config = get_device_config()
if not device_config:
logger.error("配置加载为空,工程无法启动,退出!")
exit(1)
# 初始化数据转发核心服务
#init_forward_service()
if not base_config.DEVICE_CONFIG_DICT:
logger.error("外设配置加载失败,工程启动终止")
else:
logger.info("外设配置加载成功")
print("程序运行到这里了")
# 步骤2实例化UDP单例服务此时配置已初始化能读取到有效数据
global udp_server
udp_server = MultiUDPServer()
logger.info(f"工程启动成功|外设数量:{len(device_config)}UDP监听端口{list(udp_server.udp_sockets.keys())}")
# 初始化UDP服务器
#udp_server.__init__() # 确保先初始化
'''
# # 初始化UDP服务器
# udp_server.init() # 确保先初始化
# 启动主UI
start_main_ui()
log.info("软件运行中...")
except Exception as e:
log.error(f"程序启动失败:{str(e)}", exc_info=True)
sys.exit(1)
'''
# 步骤3工程主循环阻塞运行处理UDP数据
try:
while True:
# 非阻塞接收所有UDP端口数据
recv_data = udp_server.recv_multi_udp_hex()
if recv_data:
# 后续对接协议解析层/总线适配层的逻辑写在这里
for data in recv_data:
port = data["port"]
dev_name = data["dev_name"]
protocol = data["protocol"]
raw_data = data["raw_data"]
if len(raw_data) > 0:
#打印原始数据(测试用)
print(f"接收到 {dev_name} 的原始数据:{raw_data}, 协议类型:{protocol}")
# 根据协议类型进行数据解析和转发
print("后续根据设备的协议类型进行数据解析和转发...")
#判断协议类型,采用不同解析和转发方法
if protocol == "UART":
pass
# 示例:直接回传数据到故障注入软件(测试用)
# 2. 分发处理数据(核心调用)
dispatch_udp_data(recv_data)
# 示例:直接回传数据到故障注入软件(测试用)
udp_server.send_to_fault(raw_data, dev_name)
# 主循环间隔1us不影响实时性
time.sleep(1e-6)
except KeyboardInterrupt:
logger.info("用户终止工程,开始释放资源...")
finally:
# 退出时关闭UDP服务
udp_server.close()
logger.info("========== 虚拟仿真平台中间层软件 退出 ==========")
# if name == "main":
#test_config = load_excel_config("../../config_files/device_config.xlsx")
#test_config = load_excel_config("config_files/device_config.xlsx")
# test_config = load_csv_config("config_files/device_config.csv") ##暂时注释这行
# print(test_config)
'''
#测试校验和代码(单独运行该文件时执行)
#测试 UART 校验:原始数据 + b'x9c\x47'crc16_modbus 校验位)
uart_data = b"test_uart_data" + b'\x9c\x47'
print (f"UART 校验结果:{check_checksum (uart_data, 'UART', 'Uart0')}")
#测试 CAN 校验原始数据10 字节)+b'\x1a\x2b'crc16_ccitt 校验位),总长度 12≤1311+2
can_data = b"test_can_123" + b'\x1a\x2b'
print (f"CAN 校验结果:{check_checksum (can_data, 'CAN', 'CAN1')}")
print (f"CAN 帧完整性结果:{verify_frame_integrity (can_data, 'CAN', 'CAN1')}")
#测试 AD 校验:原始数据 + b'\x5f'(累加和校验位)
ad_data = b"test_ad" + b'\x5f'
print (f"AD 校验结果:{check_checksum (ad_data, 'AD', 'AD0')}")
#测试失败场景:校验位错误
wrong_checksum_data = b"test_uart_data" + b'\x00\x00'
print (f"UART 校验失败场景结果:{check_checksum (wrong_checksum_data, 'UART', 'Uart0')}")
'''
try:
# 初始化基础配置
init_base_config()
# 初始化UDP服务器
udp_server.init() # 确保先初始化
# 测试数据接收
data_list = udp_server.recv_multi_udp_hex()
for data in data_list:
dev_name = data["dev_name"]
raw_data = data["raw_data"]
# 对每个外设的原始数据进行协议处理...
# 2. 向故障注入软件发送数据
if len(raw_data) > 0:
udp_server.send_to_fault(raw_data, dev_name="Uart0")
# 3. 外设配置更新后重新加载UDP端口
udp_server.reload_sockets()
# 4. 程序退出时关闭所有套接字
udp_server.close()
except Exception as e:
log.error(f"程序启动失败:{str(e)}", exc_info=True)
sys.exit(1)