247 lines
9.2 KiB
Markdown
247 lines
9.2 KiB
Markdown
# 产品-硬件入库测试工具
|
||
|
||
ESP32-S3 类产品的产线入库测试夹具。Python + tkinter 编写,打包为单文件 `.exe`,仓库人员双击即用,不需要装 Python。
|
||
|
||
**版本**:v2.1.1
|
||
|
||
---
|
||
|
||
## 一、项目背景
|
||
|
||
产线测试场景:成箱的硬件设备(ESP32-S3 模组)需要逐台测试合格后入库。每台设备通过 USB 接电脑后,会通过串口输出诊断日志(MAC、按键事件、音频测试等),测试员根据日志和人工耳听判断每台设备是否合格,合格的设备分配唯一 SN 入库,不合格的不入库(拿去维修)。
|
||
|
||
为减少人工记录误差、自动统计不良率、防止 SN 重复分配,做了这套工具。
|
||
|
||
---
|
||
|
||
## 二、核心功能
|
||
|
||
### 1. 多产品支持
|
||
|
||
- 一个工具能测多种产品(ESP32-S3-Airhub、其他型号 …)
|
||
- 每个产品独立的配置:测试项、MAC 提取正则、SN 起始/位数/步长
|
||
- 顶部下拉切换产品,支持新建 / 复制 / 重命名 / 删除 / 导入导出 JSON
|
||
- 配置存放在 `profiles/<产品名>.json`
|
||
|
||
### 2. 测试项五种类型
|
||
|
||
| 类型 | 用途 | 操作 |
|
||
|---|---|---|
|
||
| 自动-关键词命中 | 日志里出现指定字符串就 PASS | 串口自动识别 |
|
||
| 自动-抓取数值 | 从日志抓数字/字符串当值 | 串口自动识别并填入 |
|
||
| 人工-勾选 ✓/✗ | 测试员目测/耳听判断 | 点 ✓ / ✗ |
|
||
| 人工-多选下拉 | 多状态选项(红灯/绿灯/不亮) | 选状态 + 人工 ✓/✗ |
|
||
| 人工-填写文本 | 测试员手填一段文字 | 输入框 + ✓填入 |
|
||
|
||
测试项可在 UI 内任意增删改,每行末尾 ✏ 按钮快速编辑,无需手改 JSON。
|
||
|
||
### 3. MAC 双源校验
|
||
|
||
设备插入时同时显示两个 MAC:
|
||
- **USB SN**(端口栏下小灰字):从 USB 端口的 serial_number 字段读取
|
||
- **串口 MAC**:从串口日志正则匹配
|
||
|
||
两者实时比对,✅ 一致 / ❌ 不一致,防止设备弄混。
|
||
|
||
### 4. SN 智能分配(核心逻辑)
|
||
|
||
**SN 只属于已入库的 PASS 设备**,FAIL 设备不占用 SN。
|
||
|
||
- 主 CSV 里 FAIL 行的 SN 列**为空**
|
||
- 新设备进来时,扫描 CSV 中所有 PASS 行的 SN 数字,自动分配**最小未占用**的编号
|
||
- 设备 FAIL → SN 不占用 → spinbox 不动
|
||
- 设备 PASS → SN 占用 → spinbox 自动 +1
|
||
- 维修后回来 = 当作新设备处理(之前 FAIL 没绑定,重新分配)
|
||
|
||
举例 — 已测 SN1(PASS)、X(FAIL)、SN2(PASS):
|
||
- spinbox 显示 **3**(最小未被 PASS 占用)
|
||
- 下一台 PASS → 占 SN3
|
||
- 下一台 FAIL → spinbox 不动还是 3
|
||
|
||
### 5. MAC 重复检测
|
||
|
||
| 情况 | 行为 |
|
||
|---|---|
|
||
| 同会话同 MAC 反复出现(设备一直插着) | 忽略,不打扰 |
|
||
| CSV 中已有 **PASS 行**匹配此 MAC | 弹窗"该 MAC 已入库为 SN=XX,是否覆盖" |
|
||
| CSV 中只有 **FAIL 行**匹配 / 全新 MAC | 不弹窗,当新设备 |
|
||
|
||
### 6. 批次管理
|
||
|
||
- **批次号**和**数量**用户自定义(如 "2026-05-A" 数量 600)
|
||
- 每个批次独立 CSV 文件:`reports/<产品>_<日期>_批次<批次号>.csv`
|
||
- 切换批次 = 切换 CSV,统计自动刷新
|
||
- 批次测满自动提示生成汇总
|
||
|
||
### 7. 统计-汇总面板
|
||
|
||
实时显示:
|
||
- 累计 / 未测台数
|
||
- 合格台数 / 合格率
|
||
- 不合格台数 / 不良率
|
||
- 不良率公式:`不合格 / 累计 × 100%`(未测不计入分母,0 台时显示 —)
|
||
|
||
### 8. 统计汇总报告导出
|
||
|
||
底部"📊 导出统计汇总"按钮,弹窗让用户选格式:
|
||
|
||
- **`.xlsx`**(推荐):三个 sheet
|
||
- `测试汇总`:产品/日期/测试员(按明细自动汇总)/批次号/数量/合格/不合格/合格率/不良率
|
||
- `PASS 明细`:已入库设备列表
|
||
- `FAIL 明细`:失败设备,SN/MAC 列红字加粗
|
||
- 所有单元格居中对齐 + 自动列宽
|
||
- **`.csv`**:纯文本(汇总 + 明细同 sheet)
|
||
|
||
### 9. 其他
|
||
|
||
- 串口下拉 + 波特率下拉(readonly,不能手输错)
|
||
- 端口下方小灰字显示设备描述 + USB SN(仿 VOFA+ 风格)
|
||
- 串口日志时间戳绿色显示,跟设备打印分离
|
||
- 已连接状态深绿色加粗显眼
|
||
- 字号 5 档可调(小/中/大/特大/超大)保存到 settings
|
||
- 测试项 / 串口日志区域中间可拖动调整宽度
|
||
- 串口日志支持"断开时自动清空"开关
|
||
- 保存一台后自动断开串口,避免同设备 MAC 重复触发检测
|
||
|
||
---
|
||
|
||
## 三、文件结构
|
||
|
||
```
|
||
hardware-test-jig/
|
||
├── HardwareTestJig.exe # 打包后单文件可执行(仓库用)
|
||
├── 使用说明.txt # 仓库人员看的简单说明
|
||
├── test_jig.py # 主程序源码
|
||
├── start.bat # 开发调试用启动脚本
|
||
├── settings.json # 全局设置(串口、波特率、字号、批次号、批次大小)
|
||
├── profiles/ # 产品配置目录
|
||
│ └── ESP32-S3-Airhub.json
|
||
├── reports/ # 每日测试报告输出
|
||
│ └── <产品>_<日期>_批次<批次号>.csv
|
||
└── README.md # 本文档
|
||
```
|
||
|
||
---
|
||
|
||
## 四、使用流程(仓库人员视角)
|
||
|
||
1. 双击 `HardwareTestJig.exe` 启动
|
||
2. 顶部下拉选产品(如 ESP32-S3-Airhub)
|
||
3. 选串口 + 波特率 → 点"连接"
|
||
4. 设置批次号(如 "2026-05-A")、数量(如 600)
|
||
5. 拿一台设备上电 → 串口日志自动滚动,MAC 自动识别
|
||
6. 测试员按提示操作:故事按键、BOOT 按键、喊唤醒词、听喇叭语音…
|
||
7. 自动项(按键、音频)日志命中自动 ✅,人工项点 ✓ / ✗
|
||
8. 所有项判定完成后 → 点 **"💾 保存本台数据"**
|
||
9. 自动断开串口 → 测试员拔下设备、装下一台、重新点"连接"
|
||
10. 批次测完后 → 点 **"📊 导出统计汇总"** 生成 xlsx 报告(自动按 PASS / FAIL 分 sheet)
|
||
|
||
---
|
||
|
||
## 五、关键概念图解
|
||
|
||
### SN 分配示例
|
||
|
||
```
|
||
批次大小 600,spinbox 起始 1:
|
||
|
||
第 1 台 PASS → 分配 SN1 (PASS 占用 = {1}, 下一个 = 2)
|
||
第 2 台 FAIL → SN 留空 (PASS 占用 = {1}, 下一个 = 2)
|
||
第 3 台 PASS → 分配 SN2 (PASS 占用 = {1,2}, 下一个 = 3)
|
||
第 4 台 FAIL → SN 留空 (PASS 占用 = {1,2}, 下一个 = 3)
|
||
第 5 台 PASS → 分配 SN3 (PASS 占用 = {1,2,3}, 下一个 = 4)
|
||
...
|
||
|
||
合格 = 3 台, 不合格 = 2 台, 累计 = 5, 合格率 60%, 不良率 40%
|
||
```
|
||
|
||
### MAC 检测决策树
|
||
|
||
```
|
||
新 MAC 进入
|
||
│
|
||
├─ 同会话内是否已问过此 MAC?
|
||
│ 是 → 跳过,不打扰
|
||
│ 否 ↓
|
||
│
|
||
├─ 主 CSV 中是否有此 MAC 的 PASS 行?
|
||
│ 是 → 弹窗"该 MAC 已入库为 SN=XX,是否覆盖重测?"
|
||
│ 否 ↓
|
||
│
|
||
└─ 当新设备处理,自动重算 SN spinbox = 最小可用编号
|
||
```
|
||
|
||
---
|
||
|
||
## 六、开发与打包
|
||
|
||
### 环境
|
||
- Python 3.11.7(Anaconda)
|
||
- 依赖:pyserial 3.5、openpyxl 3.0.10、tkinter(标准库)
|
||
|
||
### 直接运行源码
|
||
```cmd
|
||
python test_jig.py
|
||
```
|
||
(或双击 `start.bat`)
|
||
|
||
### 打包成 exe
|
||
```cmd
|
||
python -m PyInstaller --onefile --windowed --name "HardwareTestJig" --clean --noconfirm ^
|
||
--hidden-import=openpyxl ^
|
||
--exclude-module=numpy --exclude-module=scipy --exclude-module=pandas ^
|
||
--exclude-module=matplotlib --exclude-module=PIL --exclude-module=lxml ^
|
||
test_jig.py
|
||
```
|
||
|
||
完整的排除清单(避免 Anaconda 把不相关库一起打包导致 exe 暴涨):
|
||
```
|
||
numpy scipy pandas matplotlib PIL Pillow lxml tornado notebook IPython
|
||
ipykernel jupyter jupyter_client jupyter_core sphinx sympy statsmodels
|
||
seaborn bokeh cv2 tables numba llvmlite torch tensorflow sklearn
|
||
```
|
||
|
||
打包结果:约 13 MB 单文件 exe。
|
||
|
||
---
|
||
|
||
## 七、版本说明
|
||
|
||
### v2.1.1(当前)
|
||
|
||
- 新增自定义图标:蓝色渐变 + 白色 IC 芯片轮廓 + 绿色对勾,多尺寸(16/24/32/48/64/128/256)嵌入 exe,窗口标题栏也用同图标
|
||
- 加 `APP_VERSION` 常量,更新一处即可全局同步
|
||
- 产品栏右上角显示版本号(深灰加粗),方便仓库人员一眼看清当前版本
|
||
- 窗口标题不再带版本号(重复)
|
||
- 新增 `generate_icon.py` 独立脚本,手工写多帧 ICO(绕开 PIL writer 只保留单帧的 bug)
|
||
|
||
### v2.1.0
|
||
|
||
**核心改动**(相对 v2.0.0):
|
||
- **SN 不再被 FAIL 占用**:FAIL 行 SN 列留空,PASS 才占编号
|
||
- **SN 自动分配**:扫主 CSV PASS 行找最小未占用编号,spinbox 自动跟新
|
||
- **MAC 检测重构**:只对 PASS 过的 MAC 弹窗,FAIL 过的 MAC 当新设备静默处理
|
||
- **xlsx 导出三 sheet**:测试汇总 / PASS 明细 / FAIL 明细,FAIL 行 SN/MAC 红字加粗
|
||
- 优化:滚轮只在测试项区域生效,统计-汇总 UI 字体字号统一
|
||
|
||
### v2.0.0
|
||
|
||
- 多产品 Profile 切换 / 增删 / 导入导出
|
||
- 5 种测试项类型 + UI 内可编辑
|
||
- SN 自增(前缀+位数+步长)
|
||
- MAC 双源验证(USB serial_number + 串口日志)
|
||
- 报告按产品+日期分文件
|
||
- 测试统计面板 + 批次完成提示
|
||
|
||
---
|
||
|
||
## 八、隐私说明
|
||
|
||
仓库公开/分发时只包含:
|
||
- 源码 `test_jig.py`
|
||
- 默认 profile `profiles/ESP32-S3-Airhub.json`
|
||
- 空的 `settings.json`(无任何个人信息)
|
||
- `.gitignore` 排除了所有运行时生成的报告、日志、build artifacts
|
||
|
||
不会泄露任何测试员姓名、邮箱、实际测试数据。每个产线的 `reports/`、自定义 profile、settings 都是本地生成的。
|