需求文档
Test Interface Client — 需求规格说明书
文档信息
| 项目 | 内容 |
|---|---|
| 项目名称 | Test Interface Client |
| 文档版本 | 1.0 |
| 编写日期 | 2026-04-02 |
| 目标读者 | 开发人员、实习生、测试人员 |
1. 项目概述
1.1 项目目标
Test Interface Client 是一个桌面 GUI 应用程序,用于通过 gRPC 协议与测试接口板(NIB / TIB3 / TCPe3)通信,实现对 DUT(Device Under Test,被测设备)的自动化测试控制。
1.2 设计原则
- 轻量级:最小化外部依赖
- 高可定制性:通过 Profile JSON 文件驱动 UI 动态配置
- 非阻塞:所有 gRPC 操作在后台线程执行,UI 始终保持响应
1.3 技术栈
| 组件 | 技术 | 说明 |
|---|---|---|
| 编程语言 | Python 3 | 核心实现语言 |
| UI 框架 | PySide6 (Qt6) | 跨平台桌面 GUI |
| 通信协议 | gRPC + Protocol Buffers | 遵循 Raptor2 标准 |
| 配置格式 | YAML | 面板状态持久化 |
| Profile 格式 | JSON | 板卡配置文件(支持注释) |
| 打包工具 | PyInstaller | 生成独立可执行文件 |
| 测试框架 | pytest | 单元测试和集成测试 |
1.4 支持的硬件
| 板卡类型 | IP 范围 | 端口 | 说明 |
|---|---|---|---|
| NIB | 192.168.2.51 ~ 58 | 50053 | Network Interface Board |
| TIB3 | 192.168.2.61 ~ 68 | 50050 | Test Interface Board 3 |
| TCPe3 | 192.168.2.71 ~ 78 | 50051 | TCP enhanced 3 |
2. 系统架构
2.1 分层架构
┌─────────────────────────────────────────────────────────────┐
│ UI 层 (PySide6 界面) │
│ MainWindow → 7 个 Tab 面板 + StatusIndicator + StatusBar │
│ + TerminalWindow (独立日志窗口) │
├─────────────────────────────────────────────────────────────┤
│ Workers 层 (后台线程) │
│ GrpcWorker / ScanWorker / FirmwareUpgradeWorker / │
│ DZLoadWorker / AutoConfigWorker │
├─────────────────────────────────────────────────────────────┤
│ Service Clients 层 (gRPC 客户端封装) │
│ ConfigurationClient / GPIOClient / ModeSelectClient / │
│ TriggerClient / StatusClient / DutConnectionClient / │
│ PMBusClient / FirmwareUpdateClient / │
│ SoftwareRepositoryClient │
├─────────────────────────────────────────────────────────────┤
│ gRPC 通信层 (Protobuf 生成代码) │
│ generated/ 目录下的 *_pb2.py 和 *_pb2_grpc.py │
├─────────────────────────────────────────────────────────────┤
│ 后端 (外部 gRPC 服务器) │
│ 运行在测试接口板 (NIB/TIB3/TCPe3) 上的服务 │
└─────────────────────────────────────────────────────────────┘
2.2 核心设计模式
- Signal/Slot 机制:Qt 信号槽连接 UI 事件与处理逻辑,实现松耦合
- Worker 线程模式:所有 gRPC 调用在 QThread 后台线程执行,通过信号返回结果
- 队列式执行:GrpcWorker 使用线程安全队列(
queue.Queue),面板通过submit()提交操作 - Profile 驱动 UI:GPIO 和 DZ 面板根据 JSON Profile 文件动态填充内容
- YAML 配置持久化:用户可保存/加载整个应用状态
2.3 入口点
| 入口 | 文件 | 用途 |
|---|---|---|
| GUI 入口 | ui/app.py |
桌面应用程序(打包时使用) |
| CLI 入口 | main.py |
命令行测试脚本(开发调试用) |
3. 功能需求
3.1 主窗口 (MainWindow)
文件: ui/main_window.py
3.1.1 窗口布局
- 使用
QMainWindow作为主窗口 - 中央区域:
QTabWidget包含 7 个功能 Tab - 底部:
StatusIndicator(单行状态显示) - 状态栏:
StatusBar(连接状态、板卡类型、DUT 位置) - 工具栏:Save Config / Load Config / Auto Config 按钮
- 独立窗口:
TerminalWindow(完整日志输出)
3.1.2 Tab 页列表
| Tab 名称 | 面板类 | 功能 |
|---|---|---|
| Connection | ConnectionPanel |
设备扫描、连接管理 |
| Configuration | ConfigurationPanel |
Profile 加载、HW/SW 信息 |
| GPIO | GPIOPanel |
GPIO 控制、启动模式、触发器 |
| Firmware Update | FirmwarePanel |
固件升级 |
| DZ Loading | DZLoadingPanel |
软件加载 |
| DCDC FW | DCDC_FW_Panel |
DC/DC 固件控制 |
| Test Execution | (占位) | 测试执行(未实现) |
3.1.3 配置工具栏
- Save Config:将所有面板当前状态保存为 YAML 文件
- Load Config:从 YAML 文件恢复面板状态(仅填充 UI,不执行 gRPC 操作)
- Auto Config:一键自动配置序列(需已连接设备)
3.1.4 Profile 联动
- 当
ConnectionPanel发出board_type_changed信号时,MainWindow通过ProfileSectionLoader加载对应板卡类型的 Profile 配置段 - 加载后自动刷新 GPIO 面板(IO 配置、触发器源)和 DZ Loading 面板(软件区域配置)
3.1.5 窗口几何持久化
- 使用
QSettings保存/恢复窗口位置和大小 - 关闭时保存,启动时恢复
3.1.6 优雅关闭
closeEvent中停止所有后台 Worker 线程- 每个 Worker 等待最多 3 秒,超时则强制终止
- 关闭 TerminalWindow
3.2 连接面板 (ConnectionPanel)
文件: ui/panels/connection_panel.py
3.2.1 设备扫描
- 点击 "Scan Devices" 按钮启动设备扫描
- 扫描范围:3 个固定 IP 段(NIB: .51-.58, TIB3: .61-.68, TCPe3: .71-.78)
- 并发扫描:使用
ThreadPoolExecutor(最多 24 个线程)同时探测所有地址 - 每个地址超时 0.5 秒
- 扫描过程中显示进度条,支持取消
- 扫描完成后自动弹出设备下拉列表
- 应用启动时自动触发一次扫描
3.2.2 自动连接
- 用户从下拉列表选择设备后自动连接(无需单独点击 Connect 按钮)
- 连接在后台线程
_ConnectWorker中执行,超时 5 秒 - 连接过程中显示不确定进度条
- 连接成功后:
- 创建所有 Service Client(Configuration、GPIO、ModeSelect、Trigger、Status、DutConnection、PMBus)
- 将
StatusLogHandler安装到service_clientlogger - 更新状态栏(连接状态、板卡类型、DUT 位置)
- 发出
connected信号
- 连接失败后:重置设备下拉列表,显示错误日志
3.2.3 板卡类型自动识别
- 根据 IP 地址最后一个字节自动判断板卡类型和 DUT 位置:
- 51-58 → NIB, dut_position = last_octet - 50
- 61-68 → TIB3, dut_position = last_octet - 60
- 71-78 → TCPe3, dut_position = last_octet - 70
- 其他 → UNKNOWN, dut_position = 1
- 板卡类型变化时发出
board_type_changed信号
3.2.4 断开连接
- 点击 "Disconnect" 按钮断开当前连接
- 关闭 gRPC channel,清空所有 Service Client
- 更新状态栏,发出
disconnected信号
3.2.5 配置文件下拉
- 自动扫描
configuration/目录下的*.yaml文件 - 选择配置文件后自动加载到所有面板
3.2.6 设备显示格式
- 下拉列表显示格式:
192.168.2.61:50050 TIB3#1 - 包含 IP:端口 + 板卡类型 + DUT 编号
3.3 配置面板 (ConfigurationPanel)
文件: ui/panels/configuration_panel.py
3.3.1 Profile 加载
- 通过 "Browse..." 按钮选择 Profile JSON 文件
- 点击 "Load Profile" 按钮将 Profile 发送到设备
- 加载时根据当前连接的板卡类型,只发送匹配的 Profile 段
- 加载完成后发出
profile_loaded信号,触发 GPIO 面板刷新
3.3.2 硬件信息管理 (HW Info)
- 统一可编辑表格,列:HW Name / Serial Number / Product Number / R-State / Production Date / Comment / Actions
- Read:从设备读取所有 HW Info 并填充表格
- Write All:将表格中所有行写入设备
- Write(单行):写入指定行的 HW Info
- Erase(单行):根据 HW Name 擦除指定行
- Add Row:手动添加空行
- 表格高度根据行数动态调整(最少 4 行,最多 11 行)
3.3.3 软件信息查询 (SW Info)
- 点击 "Get SW Info" 按钮从设备读取所有 SW Info
- 只读表格,列:SW Name / Product Number / R-State / Comment
- 表格高度根据行数动态调整
3.3.4 忙碌指示器
- 所有 gRPC 操作期间显示不确定进度条 + Cancel 按钮
- 支持取消正在执行的操作
3.4 GPIO 面板 (GPIOPanel)
文件: ui/panels/gpio_panel.py
3.4.1 GPIO 控制表格
支持两种填充模式:
Profile 驱动模式(首选):
- 从 Profile JSON 的
IOConfigurationInitialSetting和IOConfigurations填充 - 表格列:Alias / Actual Name / Direction / State / Action
- Input IO:显示 "Get State" 按钮,点击读取当前状态
- Output IO:显示 "True" / "False" 两个按钮,点击设置 GPIO 状态
- 使用
IOConfigurations中的ActualName → Alias映射
传统模式(向后兼容):
- 从平面 alias 列表填充
- Output:使用 QCheckBox 切换 High/Low
- Input:使用 "Read Input" 按钮
3.4.2 安全默认值
- "Restore Safe Defaults" 按钮:将所有 GPIO 恢复到安全默认状态
3.4.3 DUT 连接状态
- "Get DUT Connection Status" 按钮:查询 DUT 是否已连接
- 结果显示在只读文本框中(Connected / Not Connected)
3.4.4 启动模式选择 (Boot Mode)
- 两个直接操作按钮:
- "External Boot" → 发送
BOOT_MODE_SELECTION_ENTER_DUT_BOOT_MODE_EXTERNAL - "Internal Boot" → 发送
BOOT_MODE_SELECTION_ENTER_DUT_BOOT_MODE_INTERNAL
- "External Boot" → 发送
- 按钮驱动,无持久化选择状态
3.4.5 接口状态查询 (Interface Status)
- "Get Once" 按钮:单次查询接口状态
- "Start Polling" 按钮:每 2 秒自动轮询接口状态
- "Stop Polling" 按钮:停止自动轮询
- 结果格式化为逗号分隔的键值对(snake_case → Title Case,布尔值 → Yes/No)
3.4.6 触发器控制 (Trigger Control)
- 触发器状态:
- "Enable" 按钮 → 发送
ENABLED - "Disable" 按钮 → 发送
DISABLED
- "Enable" 按钮 → 发送
- 触发器源:
- 动态按钮容器,从 Profile 的
TriggerConfigurations填充 - 每个触发器源一个按钮,点击直接设置
- 动态按钮容器,从 Profile 的
3.5 固件升级面板 (FirmwarePanel)
文件: ui/panels/firmware_panel.py
3.5.1 固件文件选择
- "Browse..." 按钮选择
.tar固件文件 - 自动解析文件名提取:设备名、产品号、R-state、校验码
- 文件名格式:
{DeviceName}_software_package_{ProductNumber}-{Rstate}-{BuildInfo}-{CheckCode} - 选择文件后自动填充 Product Number 和 R-state 字段
3.5.2 固件信息对比
- 左侧面板:新固件包信息(设备名、产品号、R-state、SHA、文件大小、SHA-256)
- 右侧面板:当前设备固件信息(从设备 SW Info 读取)
- 版本不匹配时显示橙色警告标签
3.5.3 固件升级流程
- 点击 "Start Update" 按钮启动升级
- 在后台线程
FirmwareUpgradeWorker中执行:- 连接固件更新服务
- 流式上传固件文件(显示百分比进度条)
- 等待设备重启(显示等待时间)
- 验证升级结果
- 升级完成后显示版本对比表格(Before / After)
- 支持取消操作
3.5.4 进度显示
- 上传阶段:百分比进度条(0-100%)
- 等待阶段:显示已等待秒数
- 步骤标签:显示当前阶段(Step 1/2/3)
3.6 DZ 加载面板 (DZLoadingPanel)
文件: ui/panels/dz_loading_panel.py
3.6.1 DZ 容器选择
- "Browse..." 按钮选择 DZ 容器目录
- 参数输入:Product Number、R-state、Security Level(None / Secure Locked / Secure Unlocked)
- "Load DZ Container" 按钮解析容器内容
3.6.2 软件区域表格 (Software Areas)
- 从 Profile 的
SoftwareAreaConfigurations填充 - 列:SwType / StartAddress / AreaSize / EraseStartAddress / EraseAreaSize
- 地址以十六进制格式显示
3.6.3 软件项表格 (Software Items)
- 从 DZ 容器解析结果填充
- 列:Send(复选框)/ Area / ProductNumber / R-state / Filename / Size / Hash / Browse
- 每行可单独选择是否发送
- 支持为缺失文件手动浏览选择替代文件
3.6.4 加载控制
- "Start Loading" 按钮:开始上传选中的软件项
- "Cancel Loading" 按钮:取消正在进行的上传
- "Cleanup After Boot" 按钮:启动后清理
- 每个软件项显示独立的进度条
3.6.5 安全级别
| 显示名称 | API 值 |
|---|---|
| None | none |
| Secure Locked | secure_locked |
| Secure Unlocked | secure_unlocked |
3.7 DCDC FW 面板 (DCDC_FW_Panel)
文件: ui/panels/dcdc_fw_panel.py
3.7.1 PMBus 控制模式
- "Normal" 按钮:设置 PMBus 为正常模式
- "Programming" 按钮:设置 PMBus 为编程模式
3.7.2 PMBus 时钟频率
- "100KHz" 按钮:设置时钟频率为 100KHz
- "400KHz" 按钮:设置时钟频率为 400KHz
3.7.3 DC/DC 固件加载
- "Browse..." 按钮选择固件文件夹
- "Load DC/DC Firmware" 按钮执行加载
3.8 自动配置 (Auto Config)
文件: ui/workers/auto_config_worker.py
3.8.1 执行序列
Auto Config 按顺序执行以下 5 个步骤:
| 步骤 | 名称 | 操作 |
|---|---|---|
| 1 | Connect Server | 验证 gRPC channel 就绪 |
| 2 | Load Profile | 加载 Profile 文件到设备 |
| 3 | Set GPIO Outputs | 设置所有 Output GPIO 状态 |
| 4 | Select Boot Mode | 选择启动模式(默认 Internal Boot) |
| 5 | Configure Trigger | 设置触发器状态和源 |
3.8.2 前置条件
- 必须已连接设备
- 必须已设置 Profile 路径
3.8.3 信号通知
step_started(str):步骤开始step_completed(str):步骤完成auto_config_complete(list):全部完成,附带摘要auto_config_error(str, str):步骤失败,附带步骤名和错误信息
4. 通信协议需求
4.1 gRPC 服务定义
文件: protos/service_ms_test_interface.proto
所有服务遵循 Raptor2 标准,使用 proto3 语法。
4.1.1 服务列表
| 服务名 | 功能 | 对应面板 |
|---|---|---|
TestInterfaceConfigurationService |
Profile 加载、HW/SW 信息管理 | Configuration |
TestInterfaceGPIOService |
GPIO 输出设置、输入读取、安全默认值 | GPIO |
TestInterfaceModeSelectService |
启动模式选择 | GPIO |
TestInterfaceTriggerService |
触发器状态/源设置 | GPIO |
TestInterfaceStatusService |
接口状态查询 | GPIO |
TestInterfaceDutConnectionService |
DUT 连接状态查询 | GPIO |
TestInterfacePMBusService |
PMBus 控制模式、时钟频率、DC/DC 固件 | DCDC FW |
TestInterfaceFirmwareUpdateService |
固件流式上传 | Firmware Update |
TestInterfaceSoftwareRepositoryService |
软件仓库管理、DZ 加载 | DZ Loading |
TestInterfaceUartService |
UART 通信测试 | (未实现) |
TestInterfaceTspUartService |
TSP UART 配置 | (未实现) |
TestInterfaceExternalAlarmService |
外部告警设置 | (未实现) |
TestInterfaceFanControlService |
风扇控制 | (未实现) |
TestInterfaceMeasureVoltageService |
电压测量 | (未实现) |
TestInterfaceBpmService |
BPM 编程 | (未实现) |
TestInterfaceModemService |
调制解调器控制 | (未实现) |
TestInterfacePdbService |
PDB 通道配置 | (未实现) |
TestInterfacePaxService |
PAX 测量和开关控制 | (未实现) |
4.1.2 关键 RPC 方法
ConfigurationService:
SetProfile— 设置 HW ProfileSetHWInfo— 写入硬件信息GetHWInfos— 读取硬件信息GetSWInfos— 读取软件信息EraseHwInfo— 擦除硬件信息LoadConfigurationFile— 加载配置文件
GPIOService:
SetOutput— 设置 GPIO 输出状态GetInput— 读取 GPIO 输入状态SetSafeDefaults— 恢复安全默认值
FirmwareUpdateService:
FirmwareUpdate— 流式固件上传(client streaming)
SoftwareRepositoryService:
InitiateBootSoftwareRequest— 双向流式软件加载CleanupAfterBoot— 启动后清理
4.2 连接方式
- 使用
grpc.insecure_channel(非加密连接) - 连接超时:5 秒
- 扫描探测超时:0.5 秒
5. UI/UX 需求
5.1 全局样式 (QSS Theme)
文件: ui/styles/theme.qss
- 主题风格:Light Professional(浅色专业风格)
- 主色调:蓝色系(#2563EB)
- 背景色:白色(#FFFFFF)
- 表面色:浅灰(#F5F7FA)
- 边框色:中灰(#D1D5DB)
- 字体:Segoe UI / Microsoft YaHei, 13px
- 所有控件统一样式:按钮、表格、下拉框、进度条、Tab 页等
- 按钮状态:正常 / 悬停 / 按下 / 禁用 / 聚焦
- 表格内按钮使用紧凑样式(max-height: 18px, font-size: 10px)
5.2 状态指示器 (StatusIndicator)
文件: ui/widgets/status_indicator.py
- 固定高度 28px 的单行状态显示
- 始终显示最新一条日志消息
- 根据日志级别显示不同颜色:
- WARNING → 橙色 (#FFA500)
- ERROR → 红色 (#FF0000)
- DEBUG → 灰色 (#808080)
- INFO → 默认颜色
- 超过 200 字符的消息截断显示
- 可通过
install_on_logger()挂载到 Python logger
5.3 状态栏 (StatusBar)
文件: ui/widgets/status_bar.py
- 三个永久标签:
- gRPC 连接状态:
gRPC: Connected (192.168.2.61:50050)/gRPC: Disconnected - DUT 位置:
DUT Position: 1/DUT Position: N/A - 板卡类型:
Device: TIB3/Device: N/A
- gRPC 连接状态:
5.4 终端日志窗口 (TerminalWindow)
文件: ui/widgets/terminal_window.py
- 独立窗口,标题 "Terminal Log"
- 默认大小 800×400
- 等宽字体 Courier New 10pt
- 深色背景(#1e1e1e)+ 浅色文字(#dcdcdc)
- 只读 QTextEdit,禁用自动换行
- 自动滚动到底部,水平滚动条重置到最左
- 日志格式:
YYYY-MM-DD HH:MM:SS [LEVEL] message - 挂载到根 logger,接收所有日志输出
5.5 表格紧凑设计
所有表格统一使用紧凑设计:
- 字体大小:9pt
- 最小行高:10px(部分 28px)
- 默认行高:22-31px
- 表格高度根据行数动态调整,避免空白区域
- 行数 ≤ max_rows 时隐藏垂直滚动条
5.6 忙碌指示器
所有执行 gRPC 操作的面板统一使用:
- 不确定进度条(
setRange(0, 0)) - Cancel 按钮
- 操作开始时显示,完成/失败/取消时隐藏
6. 配置管理需求
6.1 YAML 配置文件格式
文件: ui/config_manager.py
# 连接信息
address: "192.168.2.61:50050"
dut_position: 1
# Profile 路径
profile_path: "configuration/profile.json"
# 硬件信息
test_hw_infos:
- hw_name: "NIB"
serial_number: "SN123"
product_number: "PN456"
product_rstate: "R1A"
production_date: "2025-01-15"
comment: "test comment"
# GPIO 配置
gpio:
outputs:
- alias: "GPIO_1"
state: true
inputs:
- "GPIO_IN"
# 固件升级
upgrade_file: "/path/to/firmware.tar"
firmware:
product_number: "PN789"
product_rstate: "R2B"
# DZ 加载
dz_loading:
dz_container_path: "/path/to/container"
product_number: "CXP123"
product_rstate: "R1A"
security_level: "secure_locked"
extra_sw_files:
Pboot: "/path/to/pboot.bin"
# DC/DC 固件
dc_firmware:
folder: "/path/to/dcdc"
6.2 保存行为
- 遍历所有面板,收集当前 UI 状态
- 空字段不写入 YAML
- 启动模式和触发器状态不保存(按钮驱动,无持久化状态)
6.3 加载行为
- 读取 YAML 文件,填充对应面板字段
- 缺失字段保留面板当前值(不清空)
- 加载时阻塞信号,防止触发自动连接等副作用
- 记录未覆盖的字段列表到日志
- 仅填充 UI,不执行任何 gRPC 操作
6.4 值映射
| UI 显示 | YAML 值 |
|---|---|
| Internal Boot | BOOT_MODE_SELECTION_ENTER_DUT_BOOT_MODE_INTERNAL |
| External Boot | BOOT_MODE_SELECTION_ENTER_DUT_BOOT_MODE_EXTERNAL |
| None | none |
| Secure Locked | secure_locked |
| Secure Unlocked | secure_unlocked |
| Normal | NORMAL |
| Programming | PROGRAMMING |
| 100KHz | 100KHZ |
| 400KHz | 400KHZ |
| Enabled | ENABLED |
| Disabled | DISABLED |
7. Profile 文件需求
7.1 Profile JSON 结构
文件: ui/profile_section_loader.py
{
"TestInterfaceConfiguration": {
"<ProductName>": {
"TIB3": {
"IOConfigurationInitialSetting": [...],
"IOConfigurations": [...],
"TriggerConfigurations": [...],
"SoftwareAreaConfigurations": [...]
},
"TCPE": { ... },
"NIB": { ... }
}
}
}
7.2 板卡类型到 JSON 键映射
| board_type | JSON Section Key |
|---|---|
| TIB3 | TIB3 |
| TCPe3 | TCPE |
| NIB | NIB |
7.3 JSON 注释支持
- 支持 JavaScript 风格的
//行注释 - 支持行内注释(引号内的
//不受影响) - 加载前自动剥离注释
7.4 Profile 加载后的面板刷新
- GPIO 面板:
IOConfigurationInitialSetting→ GPIO 表格行IOConfigurations→ Alias 映射和初始状态TriggerConfigurations→ 触发器源按钮
- DZ Loading 面板:
SoftwareAreaConfigurations→ 软件区域表格
8. 后台线程需求
8.1 GrpcWorker(通用 gRPC 执行器)
文件: ui/workers/grpc_worker.py
- 继承
QThread,在后台线程中执行 gRPC 操作 - 使用线程安全队列(
queue.Queue)接收操作 - 公共 API:
submit(name, callable, *args, **kwargs)— 提交操作到队列stop()— 优雅停止(放入哨兵对象)cancel()— 设置取消标志is_cancelled()— 检查是否已取消
- 信号:
result_ready(object)— 操作成功error_occurred(str)— 操作失败operation_started(str)— 操作开始
- 被取消的操作结果会被丢弃
- 使用面板:ConfigurationPanel、GPIOPanel、DCDC_FW_Panel
8.2 ScanWorker(设备扫描)
文件: ui/workers/scan_worker.py
- 继承
QThread - 使用
ThreadPoolExecutor(24 线程)并发探测 - 每个地址通过
grpc.channel_ready_future探测,超时 0.5 秒 - 支持中断请求(
isInterruptionRequested()) - 结果排序后发出
- 信号:
scan_progress(int, int)/scan_complete(list)
8.3 FirmwareUpgradeWorker(固件升级)
文件: ui/workers/firmware_worker.py
- 继承
QThread - 创建独立的
FirmwareUpdateClient实例 - 通过日志拦截器
_ProgressCapture捕获进度信息:Progress: N%→upload_progress信号Still waiting... Ns elapsed→waiting_device信号Step 3: Waiting for device to restart→device_restarting信号
- 信号:
upload_progress(int)/waiting_device(int)/device_restarting()/upgrade_complete(list, list)/upgrade_error(str)
8.4 DZLoadWorker(DZ 加载)
文件: ui/workers/dz_load_worker.py
- 继承
QThread - 通过日志拦截器
_DZProgressCapture捕获进度信息 - 信号:
item_progress(str, int)/load_complete(list)/load_error(str)
8.5 AutoConfigWorker(自动配置)
文件: ui/workers/auto_config_worker.py
- 继承
QThread - 顺序执行 5 个步骤,任一步骤失败则中止
- 使用传入的 gRPC channel(不创建新连接)
- 信号:
step_started(str)/step_completed(str)/auto_config_complete(list)/auto_config_error(str, str)
9. 工具模块需求
9.1 固件包解析器
文件: ui/utils/fw_package_parser.py
parse_fw_filename(filename)— 从文件名提取 FWPackageInfo(设备名、产品号、R-state、校验码)parse_sw_info(sw_infos)— 从 protobuf SWInfos 响应提取 DeviceFWInfocompare_fw_versions(package, device)— 比较包版本和设备版本是否一致
9.2 资源路径解析
文件: ui/utils/resource_path.py
resource_path(relative_path)— 统一解析资源文件路径- 开发环境:基于项目根目录
- PyInstaller 打包环境:基于
sys._MEIPASS
is_frozen()— 检测是否在打包环境中运行
9.3 版本管理
文件: version.py
- 版本读取优先级:
setup.py→pyproject.toml→setup.cfg→ 默认0.1.0 - 模块级常量
VERSION在导入时计算一次
10. 打包与发布需求
10.1 PyInstaller 配置
文件: TestInterfaceClient.spec
- 入口点:
ui/app.py - 打包模式:onedir(单目录)
- 输出目录:
dist/TestInterfaceClient/ - GUI 模式:
console=False(无控制台窗口)
包含的数据文件
| 源路径 | 打包路径 | 说明 |
|---|---|---|
configuration/ |
configuration/ |
配置文件模板 |
ui/styles/ |
ui/styles/ |
QSS 样式表 |
generated/ |
generated/ |
gRPC 生成代码 |
Hidden Imports
- gRPC 核心:
grpc,grpc._cython,grpc._cython.cygrpc - Protobuf:
google.protobuf.* - 生成代码:所有
generated.*_pb2和generated.*_pb2_grpc - 其他:
yaml,PySide6.QtCore/QtGui/QtWidgets
排除的模块
- 未使用的 Qt 模块:WebEngine, 3D, Quick, Multimedia, Bluetooth 等
- 未使用的 Python 库:tkinter, unittest, pytest, matplotlib, numpy 等
10.2 发布脚本
文件: scripts/create_release.py
- 从
dist/TestInterfaceClient/创建 ZIP 包 - 命名格式:
TestInterfaceClient-vX.Y.Z.zip - 包含可选的
README.txt - 输出:版本号、文件数、包大小
10.3 构建命令
| 命令 | 说明 |
|---|---|
make build |
编译 proto 文件 + PyInstaller 打包 |
make dist |
build + 创建发布 ZIP |
make clean-dist |
清理构建产物 |
11. 测试需求
11.1 测试框架
- 使用 pytest
- 共享 fixture:
tests/conftest.pyqapp(session 级别):确保整个测试会话只有一个 QApplication_cleanup_qt_objects(autouse):每个测试后处理 Qt 事件并垃圾回收
11.2 测试覆盖范围
| 测试文件 | 覆盖模块 |
|---|---|
test_config_manager.py |
YAML 配置保存/加载、往返一致性 |
test_connection_panel.py |
设备扫描、自动连接、断开 |
test_configuration_panel.py |
Profile 加载、HW/SW 信息 |
test_gpio_panel.py |
GPIO 表格填充、按钮处理 |
test_firmware_panel.py |
固件升级工作流 |
test_firmware_worker.py |
固件升级后台线程 |
test_dz_loading_panel.py |
DZ 加载面板 |
test_dz_load_worker.py |
DZ 加载后台线程 |
test_dcdc_fw_panel.py |
DCDC FW 面板 |
test_main_window_config.py |
主窗口配置工具栏 |
test_status_indicator.py |
状态指示器 |
test_status_bar.py |
状态栏 |
test_terminal_window.py |
终端日志窗口 |
test_board_type_resolver.py |
板卡类型解析 |
test_fw_package_parser.py |
固件包文件名解析 |
test_grpc_worker.py |
通用 gRPC Worker |
test_scan_worker.py |
设备扫描 Worker |
test_auto_config_worker.py |
自动配置 Worker |
test_profile_section_loader.py |
Profile 加载器 |
test_resource_path.py |
资源路径解析 |
test_version.py |
版本管理 |
test_theme.py |
QSS 主题 |
test_visual_indicators.py |
视觉指示器 |
test_table_compactness.py |
表格紧凑性 |
test_polling_manager.py |
轮询管理器(no-op stub) |
test_release_script.py |
发布脚本 |
11.3 测试原则
- 不依赖真实 gRPC 服务器
- 使用 Mock/Patch 隔离 gRPC 调用
- GrpcWorker 线程在测试 teardown 中正确停止
- Qt 对象在测试间正确清理
12. 非功能需求
12.1 性能
- UI 线程不执行任何 gRPC 调用,保持界面响应
- 设备扫描总时间约等于单次超时(~0.5s),而非 N × 超时
- 表格高度动态调整,避免不必要的布局计算
12.2 可靠性
- 所有 gRPC 操作支持取消
- 连接失败时优雅降级(显示错误,不崩溃)
- 关闭窗口时确保所有后台线程停止
- Worker 线程超时后强制终止
12.3 可维护性
- 模块化设计:每个面板独立文件
- 统一的 Worker 模式:GrpcWorker 可复用
- 统一的日志模式:所有面板通过
_log()方法输出 - 统一的忙碌指示器模式
12.4 可扩展性
- 新面板只需创建 QWidget 子类并添加到 MainWindow 的 Tab
- 新 gRPC 服务只需创建 Service Client 并在 ConnectionPanel 中实例化
- Profile 驱动的 UI 支持不同板卡类型的差异化配置
12.5 平台支持
- 主要支持 Windows
- macOS / Linux 扩展点已预留但未完全验证
- 资源路径兼容 PyInstaller 打包环境
12.6 安全性
- 使用非加密 gRPC 连接(
insecure_channel)— 适用于内网测试环境 - 无用户认证机制
13. 目录结构参考
TestInterfaceClient/
├── main.py # CLI 入口(测试脚本)
├── version.py # 版本管理
├── TestInterfaceClient.spec # PyInstaller 打包配置
├── README.md # 项目说明
│
├── ui/ # GUI 应用
│ ├── app.py # GUI 入口
│ ├── main_window.py # 主窗口
│ ├── config_manager.py # YAML 配置管理
│ ├── board_type_resolver.py # IP → 板卡类型映射
│ ├── profile_section_loader.py # Profile JSON 解析
│ │
│ ├── panels/ # 功能面板
│ │ ├── connection_panel.py # 连接管理
│ │ ├── configuration_panel.py # 配置管理
│ │ ├── gpio_panel.py # GPIO 控制
│ │ ├── firmware_panel.py # 固件升级
│ │ ├── dz_loading_panel.py # DZ 加载
│ │ └── dcdc_fw_panel.py # DC/DC 固件
│ │
│ ├── workers/ # 后台线程
│ │ ├── grpc_worker.py # 通用 gRPC 执行器
│ │ ├── scan_worker.py # 设备扫描
│ │ ├── firmware_worker.py # 固件升级
│ │ ├── dz_load_worker.py # DZ 加载
│ │ ├── auto_config_worker.py # 自动配置
│ │ └── polling_manager.py # 轮询管理(已废弃)
│ │
│ ├── widgets/ # 可复用组件
│ │ ├── status_indicator.py # 单行状态显示
│ │ ├── status_bar.py # 底部状态栏
│ │ └── terminal_window.py # 终端日志窗口
│ │
│ ├── utils/ # 工具函数
│ │ ├── fw_package_parser.py # 固件文件名解析
│ │ └── resource_path.py # 资源路径解析
│ │
│ └── styles/
│ └── theme.qss # 全局 QSS 样式表
│
├── protos/ # Protobuf 定义
│ ├── service_ms_test_interface.proto
│ ├── test_interface.proto
│ ├── status.proto
│ ├── enums.proto
│ ├── common_enums.proto
│ ├── common_types.proto
│ └── type.proto
│
├── generated/ # Protobuf 生成代码
│ ├── *_pb2.py # 消息类
│ ├── *_pb2_grpc.py # 服务桩
│ └── *_pb2.pyi # 类型提示
│
├── service_client/ # gRPC 客户端封装
│ ├── configuration.py
│ ├── gpio.py
│ ├── mode_select.py
│ ├── trigger.py
│ ├── status.py
│ ├── dut_connect.py
│ ├── pm_bus.py
│ ├── fw_update.py
│ └── software_repository_client.py
│
├── test_case/ # CLI 测试用例
│ ├── test_configuration.py
│ ├── test_gpio.py
│ ├── test_fw_update.py
│ └── ...
│
├── tests/ # pytest 测试套件
│ ├── conftest.py
│ └── test_*.py (30+ 文件)
│
├── configuration/ # YAML 配置文件模板
├── scripts/
│ └── create_release.py # 发布脚本
└── util/
└── logger_handler.py # 日志处理器
14. 术语表
| 术语 | 全称 | 说明 |
|---|---|---|
| DUT | Device Under Test | 被测设备 |
| NIB | Network Interface Board | 网络接口板 |
| TIB3 | Test Interface Board 3 | 测试接口板第三代 |
| TCPe3 | TCP enhanced 3 | TCP 增强板第三代 |
| GPIO | General Purpose Input/Output | 通用输入输出 |
| gRPC | Google Remote Procedure Call | 远程过程调用框架 |
| Protobuf | Protocol Buffers | 序列化协议 |
| DZ | (内部术语) | 软件容器/部署包 |
| FAAP | (内部术语) | 应用固件包 |
| PMBus | Power Management Bus | 电源管理总线 |
| DCDC | DC-to-DC Converter | 直流-直流转换器 |
| R-state | Revision State | 版本修订状态 |
| Profile | 配置文件 | JSON 格式的板卡配置描述 |
| QSS | Qt Style Sheets | Qt 样式表 |

浙公网安备 33010602011771号