Files
chuan 652d5d0dc1 feat!: 接入可选送丝机与双型号焊枪仿真
- 增加送丝机及两种焊枪的启动选择,未启用时保留原有简化外设
- 实现外设串口协议、工艺缓存与导入、参数保存、报警输入和独立供电
- 提供外设 WebSocket 状态及控制接口,按连接管理按钮持有和碰撞故障释放
- 添加外设卡片、静态光斑、监控输入与故障操作,统一布局并保存展开状态
- 添加外设协议与固件联动用例,以及点射收尾期间再次出光的回执回归用例
- 整理协议边界及测试条目,记录旧款焊枪驱动和电源报警未被固件转发的现状
- BREAKING CHANGE: 自定义平台实例化 BoardWebSocketServer 时需提供 ExternalDevices 依赖
2026-10-23 14:08:01 +08:00

81 lines
4.6 KiB
Python

"""解析项目命令行参数,将配置检查、镜像清理和仿真生命周期交给对应模块"""
import argparse
from pathlib import Path
import subprocess
import sys
# 直接执行脚本时也能导入同级的 scripts 包
if __package__ in (None, ''):
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts.environment import RUNTIME, check, format_paths, free_port, set_elf, setting
from scripts.flash_images import clean
from scripts.renode_process import exit_previous
from scripts.settings import as_boolean, as_port
# 保留现有项目下载脚本使用的 simulation 与 free_port 导入入口
from scripts.simulation import run, simulation
from scripts.external_devices import ExternalDevices
def main():
"""执行子命令并将预期的配置、进程和文件错误转换为非零退出码"""
parser = argparse.ArgumentParser(description=__doc__)
sub = parser.add_subparsers(dest='task', required=True)
dependencies = sub.add_parser('check')
dependencies.add_argument('--usb', action='store_true', help='Also check the installed virtual serial-port driver')
sub.add_parser('format')
sub.add_parser('stop', help='Stop this project instance and release its virtual COM port')
cleanup = sub.add_parser('clean', help='Remove persistent Flash images; stop Renode first')
cleanup.add_argument('target', nargs='?', choices=('flash1', 'flash2'), help='flash1: internal Flash; flash2: external W25Q16; default: both')
firmware = sub.add_parser('elf')
firmware.add_argument('path', help='ELF path to save as H723_ELF in .env')
launch = sub.add_parser('run')
for device in ('wire', 'laser1', 'laser2'):
launch.add_argument('--' + device, action=argparse.BooleanOptionalAction, default=None,
help='Enable the external ' + device + ' device model')
launch.add_argument('--debug', action=argparse.BooleanOptionalAction, default=None, help='Wait paused for GDB')
launch.add_argument('--usb', action=argparse.BooleanOptionalAction, default=None, help='Create a project-owned virtual COM port')
launch.add_argument('--com', default=None, help='Unused virtual COM port for --usb (default: COM12)')
launch.add_argument('--flash', type=Path, help='External Flash image (default: .runtime/w25q16.bin)')
launch.add_argument('-f', '--force', action='store_true', help='Quit this project\'s previous instance before starting')
launch.add_argument('--uart-port', type=as_port, help='Override the network UART port')
launch.add_argument('--gdb-port', type=as_port, help='Override the GDB port')
launch.add_argument('--ws-port', type=as_port, help='Override the board WebSocket port (default: 12322)')
launch.add_argument('--fast-serial', action=argparse.BooleanOptionalAction,
default=None, help='Accelerate serial timing for protocol and firmware upgrade simulation (default: disabled)')
args = parser.parse_args()
try:
if args.task == 'check':
return check(args.usb)
if args.task == 'format':
format_paths()
return 0
if args.task == 'clean':
return clean(args.target)
if args.task == 'stop':
from scripts.virtual_com import cleanup_virtual_com
stopped = exit_previous()
removed = cleanup_virtual_com(RUNTIME)
if removed:
print(f'Removed {removed} stale project virtual COM port(s).', flush=True)
elif not stopped:
print('No project instance or owned virtual COM port is running.', flush=True)
return 0
if args.task == 'elf':
set_elf(args.path)
return 0
if args.task == 'run':
# 显式命令行参数优先,其次为进程环境变量和 .env,最后使用默认值
debug = args.debug if args.debug is not None else as_boolean(setting('H723_DEBUG', 'false'))
usb = args.usb if args.usb is not None else as_boolean(setting('H723_USB', 'false'))
fast_serial = args.fast_serial if args.fast_serial is not None else as_boolean(setting('H723_FAST_SERIAL', 'false'))
devices = ExternalDevices.resolve(args.wire, args.laser1, args.laser2)
return run(debug, usb, args.flash, args.force, args.com if args.com is not None else setting('H723_COM', 'COM12'), args.uart_port, args.gdb_port, args.ws_port, fast_serial, devices)
except (OSError, RuntimeError, ValueError, subprocess.SubprocessError) as error:
print(f'ERROR: {error}', file=sys.stderr)
return 1
if __name__ == '__main__':
raise SystemExit(main())