""" anthor:Tan Mingyan time:2026/3/6 功能:主函数,实现多线程,UDP收发和总线收发 """ import sys import os import io import time from pathlib import Path # main.py 导入解耦模块 from midware.core import start_all_threads, stop_all_threads from midware.network.udp_handler import MultiUDPServer from loguru import logger from midware.config.base_config import ( init_base_config, update_device_config, get_device_config ) import midware.config.base_config as base_config from midware.drivers import DRIVER_MAPPING #2026/3/9 # 添加工程根目录到环境变量(确保配置文件路径正确) PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) sys.path.append(PROJECT_ROOT) # 修正配置文件路径为绝对路径(避免相对路径导致文件找不到) CSV_CONFIG_PATH = os.path.join(PROJECT_ROOT, "config_files/device_config.csv") # 驱动配置(可从yaml文件加载)波特率暂时无效 DRIVER_CONFIGS = { "1553B": {"board_id": 0, "bc_address": 0x01}, "CAN": {"channel": 0, "baudrate": 500000}, "UART": {"port": "COM3", "baudrate": 9600}, "AD": {"sampling_rate": 1000}, "OC": {"output_voltage": 5.0}, "网络": {"ip": "192.168.1.100", "port": 8080} } # ========== 修复点3:初始化日志(避免日志写入触发流错误) ========== def init_logger(): """初始化日志,使用原始stdout避免重定向流关闭问题""" # 清空默认日志配置 logger.remove() # 确保日志目录存在 Path("logs").mkdir(exist_ok=True) # 运行日志 logger.add( "logs/run_{time:YYYY-MM-DD}.log", rotation="daily", level="INFO", format="{time} | {level} | {module}:{line} | {message}", enqueue=True, # 异步写入避免句柄阻塞 catch=True # 捕获日志写入异常 ) # 错误日志 logger.add( "logs/error_{time:YYYY-MM-DD}.log", rotation="daily", level="ERROR", format="{time} | {level} | {module}:{line} | {message}", enqueue=True, catch=True ) # 控制台输出(关键:使用原始stdout,避免重定向流关闭报错) logger.add( sys.__stdout__, level="INFO", format="{time} | {level} | {module}:{line} | {message}", enqueue=True, catch=True ) return logger # 启动线程(无需写冗长路径) #threads = start_all_threads(udp_server) # main.py 核心修改 if __name__ == "__main__": # 初始化日志、加载配置、实例化UDP服务(原有逻辑)... # 初始化日志(最先执行,避免后续报错无日志) log = init_logger() log.info("虚拟仿真平台中间层软件启动") logger.info("========== 虚拟仿真平台中间层软件 启动 ==========") # 初始化基础配置 try: init_base_config() device_config = get_device_config() if not device_config: logger.error("基础配置加载为空,工程无法启动!") sys.exit(1) logger.info("基础配置初始化成功") except Exception as e: logger.error(f"基础配置初始化失败:{str(e)}", exc_info=True) sys.exit(1) # 检查外设配置 if not base_config.DEVICE_CONFIG_DICT: logger.error("外设配置加载失败,工程启动终止") sys.exit(1) else: logger.info("外设配置加载成功") # 改用logger输出,避免print触发流错误 logger.info("程序运行到这里了") # 实例化UDP服务(避免global关键字,减少生命周期问题) udp_server = None try: udp_server = MultiUDPServer() logger.info( f"工程启动成功|外设数量:{len(device_config)}|" f"UDP监听端口:{list(udp_server.udp_sockets.keys()) if hasattr(udp_server, 'udp_sockets') else []}" ) except Exception as e: logger.error(f"UDP服务初始化失败:{str(e)}", exc_info=True) sys.exit(1) # 启动所有解耦线程(替代原主循环) #threads = start_all_threads(udp_server) threads = start_all_threads( udp_server=udp_server, bus_driver_configs=DRIVER_CONFIGS # 2026/3/9 新增驱动配置参数 ) # main.py 主线程 ''' while True: # 打印各队列长度 logger.info("队列状态:") for proto, q in bus_recv_queues.items(): logger.info(f" {proto} 接收队列:{q.qsize()}/{q.maxsize}") for proto, q in bus_send_queues.items(): logger.info(f" {proto} 发送队列:{q.qsize()}/{q.maxsize}") time.sleep(1) # 每秒监控一次 ''' # 主线程:仅负责等待退出信号,不处理业务 # main.py from midware.drivers.renode_agent import renode, renode_async_data_dispatcher # 只加这一行 if not renode.start(): exit() time.sleep(5) renode.start_async_listener(renode_async_data_dispatcher) time.sleep(10) # 加载完DEVICE_CONFIG_DICT之后加: from midware.drivers.renode_agent import start_renode_uart_redirect from midware.drivers.tcp_uart_agent import start_all_tcp_uart_clients # 启动Renode的UART TCP重定向 start_renode_uart_redirect() time.sleep(1) # 启动所有TCP客户端接收 start_all_tcp_uart_clients() try: while True: time.sleep(1) # 主线程休眠,避免CPU占用 except KeyboardInterrupt: logger.info("用户终止程序,开始优雅退出...") stop_all_threads() # 等待队列处理完成 udp_server.close() # 关闭UDP服务 udp_server.socket.close() # 强制关闭系统套接字 logger.info("程序正常退出")