171 lines
5.7 KiB
Python
171 lines
5.7 KiB
Python
|
|
"""
|
|||
|
|
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("程序正常退出")
|
|||
|
|
|
|||
|
|
|