feat: 产品更名 DLPilot(3D 光固化光机调试台) + 按标记调整界面

This commit is contained in:
2026-09-12 03:05:32 +08:00
parent 90433064ec
commit 744fbfd298
11 changed files with 131 additions and 87 deletions
+1
View File
@@ -9,6 +9,7 @@ dist/
# 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release # 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release
HDMI-Tool/release/*.zip HDMI-Tool/release/*.zip
DLPilot/release/*.zip
# ZCode 客户端本地会话数据(计划留档等), 非项目配置 # ZCode 客户端本地会话数据(计划留档等), 非项目配置
.zcode/ .zcode/
+13 -13
View File
@@ -1,4 +1,4 @@
# AGENTS.md — HDMI-Tool 工程档案(供 AI/Agent 使用) # AGENTS.md — DLPilot 工程档案(供 AI/Agent 使用)
> **本文档面向 AI/Agent**,是人类文档 [README.md](README.md) 的姊妹篇,两者不重叠: > **本文档面向 AI/Agent**,是人类文档 [README.md](README.md) 的姊妹篇,两者不重叠:
> README 回答"这是什么、怎么用";本文回答"代码怎么组织、怎么构建发布、改动时哪些约束不能破坏"。 > README 回答"这是什么、怎么用";本文回答"代码怎么组织、怎么构建发布、改动时哪些约束不能破坏"。
@@ -9,17 +9,17 @@
仓库 `LT8619C_Debug_Tools` 是 LT8619CHDMI→RGB888)→ DLPC3421 投影转接板的**调试上位机工具集**, 仓库 `LT8619C_Debug_Tools` 是 LT8619CHDMI→RGB888)→ DLPC3421 投影转接板的**调试上位机工具集**,
上游主仓库(固件)为 `hulk/LT8619C_DLPC3421_HDMI`(同 Gitea 实例 `gitea.hulk.wang`), 上游主仓库(固件)为 `hulk/LT8619C_DLPC3421_HDMI`(同 Gitea 实例 `gitea.hulk.wang`),
本仓库本机路径 `E:\Hulk-Coding\LT8619C_DLPC3421_HDMI` 本仓库本机路径 `E:\Hulk-Coding\LT8619C_DLPC3421_HDMI`
HDMI-Tool 工作在两端:HDMI **源端**(PC 显卡侧,EDID/分辨率/图案)与**光机控制端** DLPilot 工作在两端:HDMI **源端**(PC 显卡侧,EDID/分辨率/图案)与**光机控制端**
RS485 → 板载 GD32E230 网关 → DLPC3421)。寄存器语义判读基线(0x606E 位交换 / RS485 → 板载 GD32E230 网关 → DLPC3421)。寄存器语义判读基线(0x606E 位交换 /
0x606D 整组顺序)与光机协议规程都在上游仓库 `doc/architecture/``protocols.md`,不在本仓库。 0x606D 整组顺序)与光机协议规程都在上游仓库 `doc/architecture/``protocols.md`,不在本仓库。
## 2. 目录契约(重要) ## 2. 目录契约(重要)
``` ```
HDMI-Tool/ DLPilot/
├── src/ 源代码区 —— 只有这里可以手改(logos/ 改图标源后重跑 make_ico.py ├── src/ 源代码区 —— 只有这里可以手改(logos/ 改图标源后重跑 make_ico.py
├── assets/ 生成资产区 —— gen_*.py 的产物(PNG 图案),可随时再生成,改动需提交 ├── assets/ 生成资产区 —— gen_*.py 的产物(PNG 图案),可随时再生成,改动需提交
├── release/ 产物区 —— 机器生成,禁止手改:HDMI-Tool.exe、pattern_slots.json、 ├── release/ 产物区 —— 机器生成,禁止手改:DLPilot.exe、pattern_slots.json、
│ bw/solid 图案(package_release.py 从 assets/ 平铺复制来,均入库)、 │ bw/solid 图案(package_release.py 从 assets/ 平铺复制来,均入库)、
│ *.zipgitignore,只上传 Release)。release/ 本身=完整可直接运行的 │ *.zipgitignore,只上传 Release)。release/ 本身=完整可直接运行的
│ 发布文件夹(exe+附属平铺),内容与 zip 一致 │ 发布文件夹(exe+附属平铺),内容与 zip 一致
@@ -42,8 +42,8 @@ HDMI-Tool/
| `src/config.py` | 运行目录定位(BASE_DIR)与 pattern_slots.json 读写(slots/area/serial 三键) | | `src/config.py` | 运行目录定位(BASE_DIR)与 pattern_slots.json 读写(slots/area/serial 三键) |
| `src/dlpc_rs485.py` | 光机 RS485 协议模块: 帧构造/增量解析/译码表/预设命令/串口线程(DLPC485) | | `src/dlpc_rs485.py` | 光机 RS485 协议模块: 帧构造/增量解析/译码表/预设命令/串口线程(DLPC485) |
| `src/selftest_rs485.py` | 光机协议自检(对照上游实测帧向量, 无硬件回归, 改协议代码后必跑) | | `src/selftest_rs485.py` | 光机协议自检(对照上游实测帧向量, 无硬件回归, 改协议代码后必跑) |
| `src/build_exe.py` | PyInstaller 打包 → `release/HDMI-Tool.exe`onefile/noconsole, 内嵌图标+pyserial+customtkinter | | `src/build_exe.py` | PyInstaller 打包 → `release/DLPilot.exe`onefile/noconsole, 内嵌图标+pyserial+customtkinter |
| `src/package_release.py` | 复制图案到 release/(平铺) → `release/HDMI-Tool-v<ver>-win64.zip`(校验栏位引用完整性; release/ 与 zip 内容一致) | | `src/package_release.py` | 复制图案到 release/(平铺) → `release/DLPilot-v<ver>-win64.zip`(校验栏位引用完整性; release/ 与 zip 内容一致) |
| `src/publish_gitea.py` | 建/复用 Gitea Release 并上传 ziptag 默认取 zip 文件名) | | `src/publish_gitea.py` | 建/复用 Gitea Release 并上传 ziptag 默认取 zip 文件名) |
| `src/hdmi_source.ps1/.bat` | 独立 PowerShell 命令行工具(自包含,与 GUI 无代码共享) | | `src/hdmi_source.ps1/.bat` | 独立 PowerShell 命令行工具(自包含,与 GUI 无代码共享) |
| `src/gen_bw_patterns.py` | 生成 `assets/bw_*.png` ×5640x360 黑白,需 Pillow | | `src/gen_bw_patterns.py` | 生成 `assets/bw_*.png` ×5640x360 黑白,需 Pillow |
@@ -87,7 +87,7 @@ HDMI-Tool/
纯数组(无 area)与无 serial 键两种历史格式,save 永远写全三键。`serial` 子键为 纯数组(无 area)与无 serial 键两种历史格式,save 永远写全三键。`serial` 子键为
`{port, baud, bytesize(8/7/6/5), parity(N/E/O), stopbits(1/2)}`,旧配置缺子键按 `{port, baud, bytesize(8/7/6/5), parity(N/E/O), stopbits(1/2)}`,旧配置缺子键按
默认 8-N-1 补齐。 默认 8-N-1 补齐。
12. **GUI = app_gui.py 双栏仪表盘**(规格:`HDMI-Tool/UI参考布局.svg`):左列 HDMI 源端 12. **GUI = app_gui.py 双栏仪表盘**(规格:`DLPilot/UI参考布局.svg`):左列 HDMI 源端
五卡(显示器/模式/EDID 信息/测试图案/hex),右列光机四卡(串口/数据/命令/滑条), 五卡(显示器/模式/EDID 信息/测试图案/hex),右列光机四卡(串口/数据/命令/滑条),
顶栏 Dark/Light/System 切换(ttk.Treeview 颜色随动)。打包必须 `--collect-all 顶栏 Dark/Light/System 切换(ttk.Treeview 颜色随动)。打包必须 `--collect-all
customtkinter`build_exe.py 已内置,勿删)——CTk 主题/字体数据缺失会让 exe 启动即崩。 customtkinter`build_exe.py 已内置,勿删)——CTk 主题/字体数据缺失会让 exe 启动即崩。
@@ -111,14 +111,14 @@ HDMI-Tool/
```powershell ```powershell
python gen_bw_patterns.py ; python gen_solid_colors.py # 仅当改了图案生成逻辑 python gen_bw_patterns.py ; python gen_solid_colors.py # 仅当改了图案生成逻辑
python build_exe.py # → ../release/HDMI-Tool.exe(缺 PyInstaller 会自动 pip install python build_exe.py # → ../release/DLPilot.exe(缺 PyInstaller 会自动 pip install
python build_exe.py --debug # 附加带控制台的 HDMI-Tool-console.exe(调试 --dump 用) python build_exe.py --debug # 附加带控制台的 DLPilot-console.exe(调试 --dump 用)
python package_release.py <版本> # → ../release/HDMI-Tool-v<版本>-win64.zip python package_release.py <版本> # → ../release/DLPilot-v<版本>-win64.zip
python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --replace --insecure # 上传(需 GITEA_TOKEN) python publish_gitea.py DLPilot-v<版本>-win64.zip --replace --insecure # 上传(需 GITEA_TOKEN)
``` ```
发布约定: 发布约定:
- tag/release 命名 `HDMI-Tool-vX.Y.Z`zip 命名 `HDMI-Tool-vX.Y.Z-win64.zip`publish_gitea.py - tag/release 命名 `DLPilot-vX.Y.Z`zip 命名 `DLPilot-vX.Y.Z-win64.zip`publish_gitea.py
依赖此命名从文件名推 tag); 依赖此命名从文件名推 tag);
- **exe、pattern_slots.json 与 release/ 下平铺的图案 png 改动跟随源码/资产生成提交入库; - **exe、pattern_slots.json 与 release/ 下平铺的图案 png 改动跟随源码/资产生成提交入库;
zip 永不入库**.gitignore 已挡); zip 永不入库**.gitignore 已挡);
@@ -151,5 +151,5 @@ python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --replace --insecure #
4. `python hdmi_gui.py --test-pattern Checker --area 800x600 --seconds 3` —— 投图链路; 4. `python hdmi_gui.py --test-pattern Checker --area 800x600 --seconds 3` —— 投图链路;
5. `python hdmi_gui.py --dump` —— EDID 解算不抛异常; 5. `python hdmi_gui.py --dump` —— EDID 解算不抛异常;
6. `python hdmi_gui.py --dlpc-cmd M999`(不带 --port)—— 应明确报错而非崩溃(无硬件时的优雅降级); 6. `python hdmi_gui.py --dlpc-cmd M999`(不带 --port)—— 应明确报错而非崩溃(无硬件时的优雅降级);
7. `python build_exe.py` → 双击 release/HDMI-Tool.exe 确认图标/双栏布局/投图/光机区渲染; 7. `python build_exe.py` → 双击 release/DLPilot.exe 确认图标/双栏布局/投图/光机区渲染;
8. `python package_release.py <版本>` —— 不报"引用图片缺失"即栏位完整性 OK。 8. `python package_release.py <版本>` —— 不报"引用图片缺失"即栏位完整性 OK。
+13 -13
View File
@@ -1,11 +1,11 @@
# HDMI-Tool — HDMI 源端调试 + 光机控制工具 # DLPilot — HDMI 源端调试 + 光机控制工具
> LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具: > LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具:
> HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制** > HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制**
> RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。 > RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。
> >
> - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) > - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases)
> 下载 `HDMI-Tool-vX.Y.Z-win64.zip`,解压双击 `HDMI-Tool.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 > 下载 `DLPilot-vX.Y.Z-win64.zip`,解压双击 `DLPilot.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。
> - **要改代码/重新打包**:见 §8、§9。 > - **要改代码/重新打包**:见 §8、§9。
> >
> 更新:2026-09-11 > 更新:2026-09-11
@@ -29,15 +29,15 @@
## 2. 下载与安装 ## 2. 下载与安装
1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的 1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的
`HDMI-Tool-vX.Y.Z-win64.zip` `DLPilot-vX.Y.Z-win64.zip`
2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边); 2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边);
3. 双击 `HDMI-Tool.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 3. 双击 `DLPilot.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。
包内包含: 包内包含:
``` ```
HDMI-Tool/ DLPilot/
├── HDMI-Tool.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) ├── DLPilot.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置)
├── pattern_slots.json 预置自定义栏位 + 串口记忆 ├── pattern_slots.json 预置自定义栏位 + 串口记忆
├── bw_*.png ×5 640x360 黑白测试图 ├── bw_*.png ×5 640x360 黑白测试图
├── solid_*.png ×10 800x600 纯色测试图 ├── solid_*.png ×10 800x600 纯色测试图
@@ -72,7 +72,7 @@ HDMI-Tool/
## 4. 典型测试场景 ## 4. 典型测试场景
``` ```
1. HDMI 接转接板 → 启动 HDMI-Tool → 刷新 → 选中板卡显示器 1. HDMI 接转接板 → 启动 DLPilot → 刷新 → 选中板卡显示器
2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1) 2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1)
3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机 3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机
4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出 4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出
@@ -180,7 +180,7 @@ python la_wave_analyzer3.py <capture.csv> # 3 通道(RGB 三组同拍, ch8/
## 8. 目录结构与从源码运行 ## 8. 目录结构与从源码运行
``` ```
HDMI-Tool/ DLPilot/
├── src/ # 源代码(人工维护区) ├── src/ # 源代码(人工维护区)
│ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发) │ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发)
│ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘) │ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘)
@@ -202,7 +202,7 @@ HDMI-Tool/
│ ├── bw_*.png ×5 # 640x360 黑白系列 │ ├── bw_*.png ×5 # 640x360 黑白系列
│ └── solid_*.png ×10 # 800x600 纯色系列 │ └── solid_*.png ×10 # 800x600 纯色系列
├── release/ # 构建与发布产物(机器生成区, 不手改) ├── release/ # 构建与发布产物(机器生成区, 不手改)
│ ├── HDMI-Tool.exe # 打包单文件版(改动跟随源码提交入库) │ ├── DLPilot.exe # 打包单文件版(改动跟随源码提交入库)
│ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆) │ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆)
│ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步) │ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步)
│ └── *.zip # 发布包(不入库, 上传 Gitea Release │ └── *.zip # 发布包(不入库, 上传 Gitea Release
@@ -220,11 +220,11 @@ GUI 需 customtkinter`py -m pip install customtkinter`);光机控制需 p
```powershell ```powershell
cd src cd src
python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑) python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑)
python build_exe.py # 打包 → ../release/HDMI-Tool.exe(自动装 PyInstaller; python build_exe.py # 打包 → ../release/DLPilot.exe(自动装 PyInstaller;
# 内置 pyserial/customtkinter, CTk 主题数据自动收集) # 内置 pyserial/customtkinter, CTk 主题数据自动收集)
python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出) python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出)
python package_release.py 0.2.0 # 组装 release/HDMI-Tool-v0.2.0-win64.zip python package_release.py 0.2.0 # 组装 release/DLPilot-v0.2.0-win64.zip
python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) python publish_gitea.py DLPilot-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN)
``` ```
## 10. 注意事项 / FAQ ## 10. 注意事项 / FAQ
@@ -235,6 +235,6 @@ python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea R
- **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下; - **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下;
- **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可; - **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可;
- **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致); - **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致);
- **残留进程**:修改源码重新打包前先结束残留的 HDMI-Tool 进程(`build_exe.py` 会自动 taskkill); - **残留进程**:修改源码重新打包前先结束残留的 DLPilot 进程(`build_exe.py` 会自动 taskkill);
- **改 logo**:改 `src/logos/logo_ph_orange.svg``python src/logos/make_ico.py` → 重新打包; - **改 logo**:改 `src/logos/logo_ph_orange.svg``python src/logos/make_ico.py` → 重新打包;
- **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。 - **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。
+13 -13
View File
@@ -1,11 +1,11 @@
# HDMI-Tool — HDMI 源端调试 + 光机控制工具 # DLPilot — HDMI 源端调试 + 光机控制工具
> LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具: > LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具:
> HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制** > HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制**
> RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。 > RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。
> >
> - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) > - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases)
> 下载 `HDMI-Tool-vX.Y.Z-win64.zip`,解压双击 `HDMI-Tool.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 > 下载 `DLPilot-vX.Y.Z-win64.zip`,解压双击 `DLPilot.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。
> - **要改代码/重新打包**:见 §8、§9。 > - **要改代码/重新打包**:见 §8、§9。
> >
> 更新:2026-09-11 > 更新:2026-09-11
@@ -29,15 +29,15 @@
## 2. 下载与安装 ## 2. 下载与安装
1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的 1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的
`HDMI-Tool-vX.Y.Z-win64.zip` `DLPilot-vX.Y.Z-win64.zip`
2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边); 2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边);
3. 双击 `HDMI-Tool.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 3. 双击 `DLPilot.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。
包内包含: 包内包含:
``` ```
HDMI-Tool/ DLPilot/
├── HDMI-Tool.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) ├── DLPilot.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置)
├── pattern_slots.json 预置自定义栏位 + 串口记忆 ├── pattern_slots.json 预置自定义栏位 + 串口记忆
├── bw_*.png ×5 640x360 黑白测试图 ├── bw_*.png ×5 640x360 黑白测试图
├── solid_*.png ×10 800x600 纯色测试图 ├── solid_*.png ×10 800x600 纯色测试图
@@ -72,7 +72,7 @@ HDMI-Tool/
## 4. 典型测试场景 ## 4. 典型测试场景
``` ```
1. HDMI 接转接板 → 启动 HDMI-Tool → 刷新 → 选中板卡显示器 1. HDMI 接转接板 → 启动 DLPilot → 刷新 → 选中板卡显示器
2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1) 2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1)
3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机 3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机
4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出 4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出
@@ -180,7 +180,7 @@ python la_wave_analyzer3.py <capture.csv> # 3 通道(RGB 三组同拍, ch8/
## 8. 目录结构与从源码运行 ## 8. 目录结构与从源码运行
``` ```
HDMI-Tool/ DLPilot/
├── src/ # 源代码(人工维护区) ├── src/ # 源代码(人工维护区)
│ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发) │ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发)
│ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘) │ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘)
@@ -202,7 +202,7 @@ HDMI-Tool/
│ ├── bw_*.png ×5 # 640x360 黑白系列 │ ├── bw_*.png ×5 # 640x360 黑白系列
│ └── solid_*.png ×10 # 800x600 纯色系列 │ └── solid_*.png ×10 # 800x600 纯色系列
├── release/ # 构建与发布产物(机器生成区, 不手改) ├── release/ # 构建与发布产物(机器生成区, 不手改)
│ ├── HDMI-Tool.exe # 打包单文件版(改动跟随源码提交入库) │ ├── DLPilot.exe # 打包单文件版(改动跟随源码提交入库)
│ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆) │ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆)
│ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步) │ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步)
│ └── *.zip # 发布包(不入库, 上传 Gitea Release │ └── *.zip # 发布包(不入库, 上传 Gitea Release
@@ -220,11 +220,11 @@ GUI 需 customtkinter`py -m pip install customtkinter`);光机控制需 p
```powershell ```powershell
cd src cd src
python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑) python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑)
python build_exe.py # 打包 → ../release/HDMI-Tool.exe(自动装 PyInstaller; python build_exe.py # 打包 → ../release/DLPilot.exe(自动装 PyInstaller;
# 内置 pyserial/customtkinter, CTk 主题数据自动收集) # 内置 pyserial/customtkinter, CTk 主题数据自动收集)
python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出) python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出)
python package_release.py 0.2.0 # 组装 release/HDMI-Tool-v0.2.0-win64.zip python package_release.py 0.2.0 # 组装 release/DLPilot-v0.2.0-win64.zip
python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) python publish_gitea.py DLPilot-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN)
``` ```
## 10. 注意事项 / FAQ ## 10. 注意事项 / FAQ
@@ -235,6 +235,6 @@ python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea R
- **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下; - **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下;
- **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可; - **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可;
- **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致); - **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致);
- **残留进程**:修改源码重新打包前先结束残留的 HDMI-Tool 进程(`build_exe.py` 会自动 taskkill); - **残留进程**:修改源码重新打包前先结束残留的 DLPilot 进程(`build_exe.py` 会自动 taskkill);
- **改 logo**:改 `src/logos/logo_ph_orange.svg``python src/logos/make_ico.py` → 重新打包; - **改 logo**:改 `src/logos/logo_ph_orange.svg``python src/logos/make_ico.py` → 重新打包;
- **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。 - **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。
+56 -13
View File
@@ -1,9 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
HDMI-Tool 主界面 — CustomTkinter 双栏仪表盘 DLPilot 主界面 — CustomTkinter 双栏仪表盘
================================================================ ================================================================
布局(HDMI-Tool/UI参考布局.svg): 布局(DLPilot/UI参考布局.svg):
左列 显示器选择 | 支持的模式 | EDID 信息 | 测试图案/纯色/自定义 | EDID 原始数据 左列 显示器选择 | 支持的模式 | EDID 信息 | 测试图案/纯色/自定义 | EDID 原始数据
右列 串口选择与参数 | 串口数据(收发日志) | 预设与自定义命令 | 光强/定时快捷滑条 右列 串口选择与参数 | 串口数据(收发日志) | 预设与自定义命令 | 光强/定时快捷滑条
默认深色外观, 顶栏可切换 Dark/Light/System。 默认深色外观, 顶栏可切换 Dark/Light/System。
@@ -12,6 +12,7 @@ HDMI-Tool 主界面 — CustomTkinter 双栏仪表盘
投屏窗口在 patterns, 串口协议在 dlpc_rs485, 运行配置在 config。 投屏窗口在 patterns, 串口协议在 dlpc_rs485, 运行配置在 config。
""" """
import ctypes
import ctypes import ctypes
import os import os
import queue import queue
@@ -63,7 +64,11 @@ def run_gui(auto_close=0):
class App(ctk.CTk): class App(ctk.CTk):
def __init__(self, auto_close=0): def __init__(self, auto_close=0):
super().__init__() super().__init__()
self.title('HDMI-Tool — EDID 查看器 + 测试图案 + 光机控制 (LT8619C 转接板调试)') self.title('DLPilot — 3D 光固化光机调试台 (EDID · 测试图案 · RS485 光机控制)')
try: # 任务栏独立分组
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('hulk.DLPilot')
except Exception:
pass
self.geometry('1440x920') self.geometry('1440x920')
self.minsize(1180, 800) self.minsize(1180, 800)
ic = get_icon_path() ic = get_icon_path()
@@ -97,8 +102,10 @@ class App(ctk.CTk):
def _set_appearance(self, mode): def _set_appearance(self, mode):
ctk.set_appearance_mode(mode) ctk.set_appearance_mode(mode)
def _card(self, parent, title, button=None, command=None, right_label=None): def _card(self, parent, title, button=None, command=None, right_label=None,
"""卡片容器: 圆角边框 + 标题行(可带右侧小按钮/右对齐标签), 返回 (卡片, 内容 frame) right_widget=None):
"""卡片容器: 圆角边框 + 标题行(可带右侧小按钮/右对齐标签/自定义控件),
返回 (卡片, 内容 frame)
卡片自身用 grid 参与列布局; 卡片内部(head/content/行控件)一律用 pack。 卡片自身用 grid 参与列布局; 卡片内部(head/content/行控件)一律用 pack。
""" """
@@ -107,6 +114,8 @@ class App(ctk.CTk):
head = ctk.CTkFrame(card, fg_color='transparent') head = ctk.CTkFrame(card, fg_color='transparent')
head.pack(fill='x', padx=12, pady=(8, 0)) head.pack(fill='x', padx=12, pady=(8, 0))
ctk.CTkLabel(head, text=title, font=BOLD, anchor='w').pack(side='left') ctk.CTkLabel(head, text=title, font=BOLD, anchor='w').pack(side='left')
if right_widget is not None: # 自定义控件(如 电流读数+查电流)
right_widget.pack(side='right')
if right_label is not None: if right_label is not None:
ctk.CTkLabel(head, textvariable=right_label, ctk.CTkLabel(head, textvariable=right_label,
text_color='gray60').pack(side='right') text_color='gray60').pack(side='right')
@@ -120,7 +129,7 @@ class App(ctk.CTk):
def _build(self): def _build(self):
top = ctk.CTkFrame(self, fg_color='transparent') top = ctk.CTkFrame(self, fg_color='transparent')
top.pack(fill='x', padx=12, pady=(10, 2)) top.pack(fill='x', padx=12, pady=(10, 2))
ctk.CTkLabel(top, text='HDMI-Tool', font=TITLE_FONT).pack(side='left') ctk.CTkLabel(top, text='DLPilot', font=TITLE_FONT).pack(side='left')
ctk.CTkLabel(top, text='EDID · 测试图案 · 光机控制', ctk.CTkLabel(top, text='EDID · 测试图案 · 光机控制',
text_color='gray60').pack(side='left', padx=10, pady=(6, 0)) text_color='gray60').pack(side='left', padx=10, pady=(6, 0))
seg = ctk.CTkSegmentedButton(top, values=['Dark', 'Light', 'System'], seg = ctk.CTkSegmentedButton(top, values=['Dark', 'Light', 'System'],
@@ -149,8 +158,8 @@ class App(ctk.CTk):
).pack(expand=True) ).pack(expand=True)
def _build_left(self, col): def _build_left(self, col):
col.grid_rowconfigure(1, weight=2) # 支持的模式(与 EDID 信息等高) col.grid_rowconfigure(1, weight=2) # 支持的模式
col.grid_rowconfigure(2, weight=2) # EDID 信息 col.grid_rowconfigure(2, weight=1) # EDID 信息(压缩高度)
col.grid_rowconfigure(4, weight=0) # EDID 原始数据(固定高, 压缩) col.grid_rowconfigure(4, weight=0) # EDID 原始数据(固定高, 压缩)
col.grid_columnconfigure(0, weight=1) col.grid_columnconfigure(0, weight=1)
@@ -218,7 +227,7 @@ class App(ctk.CTk):
row3 = ctk.CTkFrame(c, fg_color='transparent') row3 = ctk.CTkFrame(c, fg_color='transparent')
row3.pack(fill='x', pady=(6, 0)) row3.pack(fill='x', pady=(6, 0))
self.slot_buttons = [] self.slot_buttons = []
for i in range(config.SLOT_COUNT): for i in range(3): # 自定义栏位(沿用原 3 槽配置)
cell = ctk.CTkFrame(row3, fg_color='transparent') cell = ctk.CTkFrame(row3, fg_color='transparent')
cell.pack(side='left', padx=(0, 10)) cell.pack(side='left', padx=(0, 10))
btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96, btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96,
@@ -231,6 +240,22 @@ class App(ctk.CTk):
self.slot_buttons.append(btn) self.slot_buttons.append(btn)
ctk.CTkLabel(row3, text='点击投图, 齿轮按钮配置图片', ctk.CTkLabel(row3, text='点击投图, 齿轮按钮配置图片',
text_color='gray50').pack(side='left', padx=4) text_color='gray50').pack(side='left', padx=4)
# -- 光校图案(预留 5 槽): 3D 光固化打印测试/校准用图 --
row4 = ctk.CTkFrame(c, fg_color='transparent')
row4.pack(fill='x', pady=(6, 0))
for i in range(3, config.SLOT_COUNT):
cell = ctk.CTkFrame(row4, fg_color='transparent')
cell.pack(side='left', padx=(0, 10))
btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96,
command=lambda i=i: self._show_custom(i))
btn.pack(side='left')
ctk.CTkButton(cell, text='\uE713', width=30, height=24,
font=('Segoe MDL2 Assets', 13),
command=lambda i=i: self._configure_slot(i)
).pack(side='left', padx=(4, 0))
self.slot_buttons.append(btn)
ctk.CTkLabel(row4, text='校准图案(预留 5 槽, 齿轮改图)',
text_color='gray50').pack(side='left', padx=4)
# -- EDID 原始数据 -- # -- EDID 原始数据 --
card, c = self._card(col, 'EDID 原始数据', card, c = self._card(col, 'EDID 原始数据',
@@ -293,12 +318,20 @@ class App(ctk.CTk):
'累加和校验; 全部命令见 README"光机控制"') '累加和校验; 全部命令见 README"光机控制"')
# -- 光机命令 -- # -- 光机命令 --
card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC') # 标题行右侧: 电流实时读数 + 查电流按钮(okR..G..B.. 应答解析)
cur_frame = ctk.CTkFrame(self, fg_color='transparent')
self.var_current = tk.StringVar(value='电流: —')
ctk.CTkLabel(cur_frame, textvariable=self.var_current, width=168,
anchor='e', text_color='#3B8ED0').pack(side='left')
ctk.CTkButton(cur_frame, text='查电流', width=64, height=24,
command=self._query_current).pack(side='left', padx=(6, 0))
card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC',
right_widget=cur_frame)
card.grid(row=2, column=0, sticky='ew', pady=(10, 0)) card.grid(row=2, column=0, sticky='ew', pady=(10, 0))
row1 = ctk.CTkFrame(c, fg_color='transparent') row1 = ctk.CTkFrame(c, fg_color='transparent')
row1.pack(fill='x') row1.pack(fill='x')
for name, cmd in (('开光机', 'M730S0'), ('关光机', 'M730S1'), for name, cmd in (('开光机', 'M730S0'), ('关光机', 'M730S1'),
('电流', 'M732'), ('版本', 'M999'), ('软件重启', 'M888'), ('查版本', 'M999'), ('软件重启', 'M888'),
('开TEC', 'M7S0'), ('关TEC', 'M7S1'), ('TEC33.0°C', 'M8S330')): ('开TEC', 'M7S0'), ('关TEC', 'M7S1'), ('TEC33.0°C', 'M8S330')):
ctk.CTkButton(row1, text=name, width=64, ctk.CTkButton(row1, text=name, width=64,
command=lambda cc=cmd: self._dlpc_send(cc) command=lambda cc=cmd: self._dlpc_send(cc)
@@ -365,7 +398,7 @@ class App(ctk.CTk):
textvariable=self.var_light) textvariable=self.var_light)
self.ent_light.pack(side='left') self.ent_light.pack(side='left')
self.ent_light.bind('<Return>', self._light_entry_apply) self.ent_light.bind('<Return>', self._light_entry_apply)
ctk.CTkButton(rowa, text='下发 M731S', width=110, ctk.CTkButton(rowa, text='下发电流值', width=110,
command=self._dlpc_send_light).pack(side='left', padx=(6, 0)) command=self._dlpc_send_light).pack(side='left', padx=(6, 0))
rowb = ctk.CTkFrame(c, fg_color='transparent') rowb = ctk.CTkFrame(c, fg_color='transparent')
rowb.pack(fill='x', pady=(8, 0)) rowb.pack(fill='x', pady=(8, 0))
@@ -395,7 +428,7 @@ class App(ctk.CTk):
textvariable=self.var_tec) textvariable=self.var_tec)
self.ent_tec.pack(side='left') self.ent_tec.pack(side='left')
self.ent_tec.bind('<Return>', self._tec_entry_apply) self.ent_tec.bind('<Return>', self._tec_entry_apply)
ctk.CTkButton(rowc, text='下发 M8S', width=110, ctk.CTkButton(rowc, text='下发温度值', width=110,
command=self._dlpc_send_tec).pack(side='left', padx=(6, 0)) command=self._dlpc_send_tec).pack(side='left', padx=(6, 0))
# ============================================================ # ============================================================
@@ -634,8 +667,16 @@ class App(ctk.CTk):
except ValueError: except ValueError:
text = f'{which}: {m.group(1)}' text = f'{which}: {m.group(1)}'
self._dlpc_log_q.put(('temp', text)) self._dlpc_log_q.put(('temp', text))
# 电流查询应答: okR<n>G<n>B<n> -> 标题行实时读数
m = re.search(r'← okR(\d+)G(\d+)B(\d+)', line)
if m:
self._dlpc_log_q.put(('current', f'电流 R:{m.group(1)} '
f'G:{m.group(2)} B:{m.group(3)}'))
self._dlpc_log_q.put(('event', line)) self._dlpc_log_q.put(('event', line))
def _query_current(self):
self._dlpc_send('M732')
def _query_dmd(self): def _query_dmd(self):
self._tl_order.append('DMD') self._tl_order.append('DMD')
self._dlpc_send('M201') self._dlpc_send('M201')
@@ -666,6 +707,8 @@ class App(ctk.CTk):
self.var_dmd.set(text) self.var_dmd.set(text)
else: else:
self.var_lamp.set(text) self.var_lamp.set(text)
elif kind == 'current':
self.var_current.set(text)
self._dlpc_log(text) self._dlpc_log(text)
except queue.Empty: except queue.Empty:
pass pass
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
把 hdmi_gui.py 打包成单文件 exe(工具名: HDMI-Tool) 把 hdmi_gui.py 打包成单文件 exe(工具名: DLPilot)
================================ ================================
使用 PyInstaller --onefile --noconsole: Python 解释器 + 标准库 + tkinter 使用 PyInstaller --onefile --noconsole: Python 解释器 + 标准库 + tkinter
全部打进一个 exe, 目标机器无需安装任何依赖。 全部打进一个 exe, 目标机器无需安装任何依赖。
@@ -10,7 +10,7 @@
python build_exe.py 自动安装 PyInstaller(如缺)并打包 python build_exe.py 自动安装 PyInstaller(如缺)并打包
python build_exe.py --debug 额外打一个带控制台的变体(--dump 可用) python build_exe.py --debug 额外打一个带控制台的变体(--dump 可用)
产物: release/HDMI-Tool.exe(及 --debug 时的 HDMI-Tool-console.exe) 产物: release/DLPilot.exe(及 --debug 时的 DLPilot-console.exe)
首次运行 onefile exe 会先解压到临时目录, 启动比脚本慢一两秒, 属正常现象。 首次运行 onefile exe 会先解压到临时目录, 启动比脚本慢一两秒, 属正常现象。
""" """
@@ -84,10 +84,10 @@ def main():
build_console = '--debug' in sys.argv build_console = '--debug' in sys.argv
ensure_pyinstaller() ensure_pyinstaller()
# 常规版: 双击即用, 无黑框(GUI/图案/自定义栏位全部可用, --dump 除外) # 常规版: 双击即用, 无黑框(GUI/图案/自定义栏位全部可用, --dump 除外)
build('HDMI-Tool', ['--noconsole']) build('DLPilot', ['--noconsole'])
if build_console: if build_console:
# 调试版: 带控制台, --dump / 异常栈可见 # 调试版: 带控制台, --dump / 异常栈可见
build('HDMI-Tool-console', []) build('DLPilot-console', [])
if __name__ == '__main__': if __name__ == '__main__':
+1 -1
View File
@@ -39,7 +39,7 @@ if getattr(sys, 'frozen', False):
BASE_DIR = os.path.dirname(os.path.abspath(sys.executable)) BASE_DIR = os.path.dirname(os.path.abspath(sys.executable))
else: else:
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
SLOT_COUNT = 3 SLOT_COUNT = 8
SLOT_CONFIG = os.path.join(BASE_DIR, 'pattern_slots.json') SLOT_CONFIG = os.path.join(BASE_DIR, 'pattern_slots.json')
IMG_EXTS = ['.png', '.gif'] + (['.jpg', '.jpeg', '.bmp', '.webp'] if HAS_PIL else []) IMG_EXTS = ['.png', '.gif'] + (['.jpg', '.jpeg', '.bmp', '.webp'] if HAS_PIL else [])
+13 -13
View File
@@ -1,22 +1,22 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
组装 HDMI-Tool 发布包: exe + 附属资产 → 一个文件夹 + 一个 zip(解压即用) 组装 DLPilot 发布包: exe + 附属资产 → 一个文件夹 + 一个 zip(解压即用)
================================================================ ================================================================
先把 assets/ 的图案复制进 release/(与 exe 平铺), 使 release/ 本身就是 先把 assets/ 的图案复制进 release/(与 exe 平铺), 使 release/ 本身就是
可直接使用的完整文件夹; 再原样压成 zip —— 两者内容始终一致。 可直接使用的完整文件夹; 再原样压成 zip —— 两者内容始终一致。
zip 解压后根目录为 HDMI-Tool/, 与 exe 运行目录结构一致: zip 解压后根目录为 DLPilot/, 与 exe 运行目录结构一致:
HDMI-Tool.exe 主程序(先运行 build_exe.py 打包) DLPilot.exe 主程序(先运行 build_exe.py 打包)
pattern_slots.json 预置自定义栏位(指向前 3 张 bw 图案) pattern_slots.json 预置自定义栏位(指向前 3 张 bw 图案)
bw_*.png 640x360 黑白测试图 ×5(自定义栏位用) bw_*.png 640x360 黑白测试图 ×5(自定义栏位用)
solid_*.png 800x600 纯色测试图 ×10(RGB 位交换测试用) solid_*.png 800x600 纯色测试图 ×10(RGB 位交换测试用)
README.md 使用说明 README.md 使用说明
用法: 用法:
python package_release.py 版本号自动取最近 git tag(HDMI-Tool-v*) python package_release.py 版本号自动取最近 git tag(DLPilot-v*)
python package_release.py 0.1.0 手动指定版本号 python package_release.py 0.1.0 手动指定版本号
产物: release/HDMI-Tool-v<版本>-win64.zip(zip 不入库, 上传到 Gitea Release) 产物: release/DLPilot-v<版本>-win64.zip(zip 不入库, 上传到 Gitea Release)
""" """
import os import os
@@ -35,23 +35,23 @@ PATTERN_GLOBS = ('bw_*.png', 'solid_*.png')
def detect_version(): def detect_version():
"""从最近的 HDMI-Tool-v* tag 推断版本号, 无 tag 则报错提示手动指定""" """从最近的 DLPilot-v* tag 推断版本号, 无 tag 则报错提示手动指定"""
try: try:
out = subprocess.check_output( out = subprocess.check_output(
['git', 'describe', '--tags', '--abbrev=0', '--match', 'HDMI-Tool-v*'], ['git', 'describe', '--tags', '--abbrev=0', '--match', 'DLPilot-v*'],
cwd=BASE, stderr=subprocess.DEVNULL) cwd=BASE, stderr=subprocess.DEVNULL)
return out.decode().strip().removeprefix('HDMI-Tool-v') return out.decode().strip().removeprefix('DLPilot-v')
except Exception: except Exception:
sys.exit('未能从 git tag 推断版本号, 请手动指定: python package_release.py <版本号>') sys.exit('未能从 git tag 推断版本号, 请手动指定: python package_release.py <版本号>')
def main(): def main():
version = (sys.argv[1] if len(sys.argv) > 1 else detect_version()).lstrip('v') version = (sys.argv[1] if len(sys.argv) > 1 else detect_version()).lstrip('v')
exe = os.path.join(RELEASE, 'HDMI-Tool.exe') exe = os.path.join(RELEASE, 'DLPilot.exe')
slots = os.path.join(RELEASE, 'pattern_slots.json') slots = os.path.join(RELEASE, 'pattern_slots.json')
readme = os.path.join(BASE, 'README.md') readme = os.path.join(BASE, 'README.md')
if not os.path.exists(exe): if not os.path.exists(exe):
sys.exit('缺少 release/HDMI-Tool.exe, 先运行: python build_exe.py') sys.exit('缺少 release/DLPilot.exe, 先运行: python build_exe.py')
for must in (slots, readme): for must in (slots, readme):
if not os.path.exists(must): if not os.path.exists(must):
sys.exit(f'缺少 {must}') sys.exit(f'缺少 {must}')
@@ -70,11 +70,11 @@ def main():
shutil.copy2(os.path.join(ASSETS, p), os.path.join(RELEASE, p)) shutil.copy2(os.path.join(ASSETS, p), os.path.join(RELEASE, p))
shutil.copy2(readme, os.path.join(RELEASE, 'README.md')) shutil.copy2(readme, os.path.join(RELEASE, 'README.md'))
zip_name = f'HDMI-Tool-v{version}-win64.zip' zip_name = f'DLPilot-v{version}-win64.zip'
zip_path = os.path.join(RELEASE, zip_name) zip_path = os.path.join(RELEASE, zip_name)
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as z: with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as z:
for p in ['HDMI-Tool.exe', 'pattern_slots.json', 'README.md'] + patterns: for p in ['DLPilot.exe', 'pattern_slots.json', 'README.md'] + patterns:
z.write(os.path.join(RELEASE, p), f'HDMI-Tool/{p}') z.write(os.path.join(RELEASE, p), f'DLPilot/{p}')
print(f'发布文件夹: {RELEASE} (exe+配置+说明+{len(patterns)} 张图案, 平铺即用)') print(f'发布文件夹: {RELEASE} (exe+配置+说明+{len(patterns)} 张图案, 平铺即用)')
print(f'发布包: {zip_path} ({os.path.getsize(zip_path) / 1024 / 1024:.1f} MB)') print(f'发布包: {zip_path} ({os.path.getsize(zip_path) / 1024 / 1024:.1f} MB)')
print('下一步上传: python publish_gitea.py', zip_name) print('下一步上传: python publish_gitea.py', zip_name)
+8 -8
View File
@@ -4,12 +4,12 @@
创建/更新 Gitea Release 并上传发布 zip(纯标准库, 无需安装依赖) 创建/更新 Gitea Release 并上传发布 zip(纯标准库, 无需安装依赖)
================================================================ ================================================================
用法: 用法:
python publish_gitea.py HDMI-Tool-v0.1.0-win64.zip python publish_gitea.py DLPilot-v0.1.0-win64.zip
python publish_gitea.py <zip> --notes-file release/notes-v0.1.0.md python publish_gitea.py <zip> --notes-file release/notes-v0.1.0.md
python publish_gitea.py <zip> --tag HDMI-Tool-v0.1.0 --replace python publish_gitea.py <zip> --tag DLPilot-v0.1.0 --replace
行为: 行为:
- tag 与版本默认取 zip 文件名(HDMI-Tool-vX.Y.Z-win64.zip → HDMI-Tool-vX.Y.Z) - tag 与版本默认取 zip 文件名(DLPilot-vX.Y.Z-win64.zip → DLPilot-vX.Y.Z)
- release 不存在则创建(tag 不存在时 Gitea 在默认分支头自动建 tag); - release 不存在则创建(tag 不存在时 Gitea 在默认分支头自动建 tag);
已存在则复用, 仅上传/更新资产 已存在则复用, 仅上传/更新资产
- release 上已有同名资产时: 默认跳过, --replace 删旧再传 - release 上已有同名资产时: 默认跳过, --replace 删旧再传
@@ -27,16 +27,16 @@ import urllib.error
import urllib.request import urllib.request
import uuid import uuid
DEFAULT_NOTES = """## HDMI-Tool {version} DEFAULT_NOTES = """## DLPilot {version}
HDMI 源端调试工具(LT8619C → DLPC3421 转接板配套): EDID 查看/逐字节解析、 HDMI 源端调试工具(LT8619C → DLPC3421 转接板配套): EDID 查看/逐字节解析、
分辨率切换、纯色与测试图案全屏投屏。 分辨率切换、纯色与测试图案全屏投屏。
### 安装 ### 安装
下载 `HDMI-Tool-v{version}-win64.zip`, 解压后双击 `HDMI-Tool.exe`(Windows 10/11 x64, 免安装)。 下载 `DLPilot-v{version}-win64.zip`, 解压后双击 `DLPilot.exe`(Windows 10/11 x64, 免安装)。
### 包内容 ### 包内容
- `HDMI-Tool.exe` — 主程序 - `DLPilot.exe` — 主程序
- `pattern_slots.json` — 预置自定义栏位(指向 bw_*.png) - `pattern_slots.json` — 预置自定义栏位(指向 bw_*.png)
- `bw_*.png` ×5 / `solid_*.png` ×10 — 测试图案 - `bw_*.png` ×5 / `solid_*.png` ×10 — 测试图案
- `README.md` — 完整使用说明 - `README.md` — 完整使用说明
@@ -119,7 +119,7 @@ def main():
sys.exit('缺少 API token: 传 --token 或设环境变量 GITEA_TOKEN') sys.exit('缺少 API token: 传 --token 或设环境变量 GITEA_TOKEN')
tag = args.tag or re.sub(r'-win64\.zip$', '', os.path.basename(args.zipfile_path)) tag = args.tag or re.sub(r'-win64\.zip$', '', os.path.basename(args.zipfile_path))
version = tag.removeprefix('HDMI-Tool-v') version = tag.removeprefix('DLPilot-v')
notes = open(args.notes_file, encoding='utf-8').read() if args.notes_file \ notes = open(args.notes_file, encoding='utf-8').read() if args.notes_file \
else DEFAULT_NOTES.format(version=version) else DEFAULT_NOTES.format(version=version)
@@ -133,7 +133,7 @@ def main():
else: else:
status, rel = api.request('POST', '/releases', json.dumps({ status, rel = api.request('POST', '/releases', json.dumps({
'tag_name': tag, 'tag_name': tag,
'name': f'HDMI-Tool v{version}', 'name': f'DLPilot v{version}',
'body': notes, 'body': notes,
}).encode(), {'Content-Type': 'application/json'}) }).encode(), {'Content-Type': 'application/json'})
if status != 201: if status != 201:
+9 -9
View File
@@ -7,16 +7,16 @@ LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套上位机工
| 工具 | 用途 | 获取 | | 工具 | 用途 | 获取 |
|---|---|---| |---|---|---|
| [HDMI-Tool](HDMI-Tool/) | HDMI 源端(EDID 查看/逐字节解析、分辨率切换、纯色与测试图案全屏投屏)+ 光机控制(RS485→GD32 网关→DLPC3421:开关光机/设光强/查温度电流) | 到 [Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) 下 `HDMI-Tool-vX.Y.Z-win64.zip`,解压即用;详见 [HDMI-Tool/README.md](HDMI-Tool/README.md) | | [DLPilot](DLPilot/) | HDMI 源端(EDID 查看/逐字节解析、分辨率切换、纯色与测试图案全屏投屏)+ 光机控制(RS485→GD32 网关→DLPC3421:开关光机/设光强/查温度电流) | 到 [Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) 下 `DLPilot-vX.Y.Z-win64.zip`,解压即用;详见 [DLPilot/README.md](DLPilot/README.md) |
| [I2C-Inject](I2C-Inject/) | LT8619C 寄存器在线读写:RP2040 注入器在 demo 板 I2C 总线上择机注入(避让主控轮询,写后自动读回校验) | 需配合 RP2040 固件 `rp2040_inject.py`;详见 [I2C-Inject/README.md](I2C-Inject/README.md) | | [I2C-Inject](I2C-Inject/) | LT8619C 寄存器在线读写:RP2040 注入器在 demo 板 I2C 总线上择机注入(避让主控轮询,写后自动读回校验) | 需配合 RP2040 固件 `rp2040_inject.py`;详见 [I2C-Inject/README.md](I2C-Inject/README.md) |
## 环境要求 ## 环境要求
- 发布版 zip 开箱即用(Windows 10/11 x64,无需安装 Python - 发布版 zip 开箱即用(Windows 10/11 x64,无需安装 Python
- 源码运行:Python ≥3.10HDMI-Tool 命令行/EDID 纯标准库,GUI 需 - 源码运行:Python ≥3.10DLPilot 命令行/EDID 纯标准库,GUI 需
`py -m pip install customtkinter`(自定义图片 JPG/BMP 可选 Pillow、光机控制可选 pyserial); `py -m pip install customtkinter`(自定义图片 JPG/BMP 可选 Pillow、光机控制可选 pyserial);
I2C-Inject 需 `py -m pip install pyserial` I2C-Inject 需 `py -m pip install pyserial`
- 重新打包:`HDMI-Tool/src/build_exe.py`(自动安装 PyInstaller);I2C-Inject 目录内 `python build_exe.py` - 重新打包:`DLPilot/src/build_exe.py`(自动安装 PyInstaller);I2C-Inject 目录内 `python build_exe.py`
## 目录结构 ## 目录结构
@@ -25,7 +25,7 @@ LT8619CHDMI→RGB888)→ DLPC3421 投影转接板调试配套上位机工
``` ```
LT8619C_Debug_Tools/ LT8619C_Debug_Tools/
├── HDMI-Tool/ ├── DLPilot/
│ ├── src/ # 源码 + 打包/发布脚本 + 图标源 │ ├── src/ # 源码 + 打包/发布脚本 + 图标源
│ ├── assets/ # 生成的测试图案 PNGgen_*.py 产物) │ ├── assets/ # 生成的测试图案 PNGgen_*.py 产物)
│ ├── release/ # 打包 exe + 运行配置(入库);发布 zip(不入库) │ ├── release/ # 打包 exe + 运行配置(入库);发布 zip(不入库)
@@ -36,13 +36,13 @@ LT8619C_Debug_Tools/
└── README.md └── README.md
``` ```
## 发布流程(HDMI-Tool ## 发布流程(DLPilot
```powershell ```powershell
cd HDMI-Tool/src cd DLPilot/src
python build_exe.py # 打包 → ../release/HDMI-Tool.exe python build_exe.py # 打包 → ../release/DLPilot.exe
python package_release.py <版本> # → ../release/HDMI-Tool-v<版本>-win64.zip python package_release.py <版本> # → ../release/DLPilot-v<版本>-win64.zip
python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) python publish_gitea.py DLPilot-v<版本>-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN)
``` ```
## 备注 ## 备注