yw1573 4ae33cbe53 docs: 为全部13个源码模块和5个测试文件添加简体中文注释
- 每个文件补充模块级 docstring、类/函数 docstring、关键逻辑行内注释
- 注释风格:"中文说明" 或 # 中文说明
- 代码结构和逻辑完全不变
2026-07-28 09:39:55 +08:00
2026-04-28 14:39:54 +08:00
2026-04-28 14:39:54 +08:00
2026-04-28 14:39:54 +08:00
2026-04-28 14:39:54 +08:00

A1 Swap Mod Packer

当前版本:v0.5.0

A1 Swap Mod Packer 是一个开源的 3MF 打包工具,专为 Bambu Lab A1 SwapMod 工作流设计。

它接收一个或多个 A1 切片后的 .3mf 文件,根据设定份数重复其面板 G-code,插入外部 SwapMod 弹射/换板 G-code 块,并输出一个新的打包 .3mf 文件,可直接发送至打印机。

A1 Swap Mod Packer 截图

注意事项

  • 本项目不含任何闭源代码。所有功能均通过对比 3MF 文件生成前后的状态独立实现。
  • 目前仅在 Windows 10 上测试验证过。
  • 生产环境使用前,请先在安全/简单的打印任务上测试生成的文件。

主要功能

  • 拖放式批量打包 GUI。
  • 可重复执行的自动化 CLI。
  • 支持多个 .3mf 输入文件。
  • 每个文件独立份数。
  • 自动从 Metadata/slice_info.config 读取并汇总时间和耗材。
  • 外部 SwapMod G-code 模板目录。
  • 可编辑 G-code 补丁文件。
  • 可选通过 M73 R... 编码剩余时间板号。
  • GUI 中选中文件缩略图预览。
  • 最多 9 个不同输入文件的预览图合成,带 {plates} P 绿色标签。
  • 合并模式:所有输入行合并为一个打包 3MF。
  • 独立批处理模式:每行输入各生成一个独立打包 3MF。
  • zlib-ng Deflate ZIP 压缩,默认级别 7。
  • GUI 设置保存到程序目录的 settings.json

源码安装

推荐 Python 3.10 及以上。

安装依赖:

pip install -r requirements.txt

当前运行时依赖:

依赖 用途
PySide6 GUI 界面、拖放表格、文件对话框、缩略图预览、设置界面
Pillow 读取和合成输出 3MF 中的 PNG 预览图,包括 {plates} P 标签
zlib-ng ZIP Deflate 压缩后端,用于写入压缩 3MF 并控制压缩级别

当前 Python 源码版本不需要 Java 运行时、Bambu Studio SDK、外部压缩工具或加密/模板解码器。

启动 GUI

python -m a1_swap_mod_packer.gui

python run_gui.py

启动 CLI

python -m a1_swap_mod_packer.cli --help

python run_cli.py

查看版本:

python -m a1_swap_mod_packer.cli --version

构建 Windows 可执行文件

仓库包含 Windows 构建脚本:

build_win.cmd

脚本使用 Nuitka onefile 模式,生成如下便携发布目录:

build/onefile/

预期输出:

build/onefile/
  a1packer.exe
  a1packer-cli.exe
  gcode_patches.ini
  swap_gcode/
  settings.json      可选;GUI 保存设置后自动生成

外部资源刻意保留在可执行文件外部。不要将这些文件打包进 onefile 二进制:

swap_gcode/
gcode_patches.ini
settings.json

打包为 exe 时,程序会从 exe 所在目录解析这些路径。

Windows 构建要求

已验证的构建环境:

  • Windows 10。
  • Python 3.10 及以上。
  • 虚拟环境 .venv/
  • requirements.txt 中的运行时依赖。
  • Nuitka 支持 onefile 模式。
  • Microsoft C++ Build Tools / Visual Studio Build Tools(含 MSVC 编译器和 Windows SDK)。

在干净的虚拟环境中安装 Python 依赖:

py -3.12 -m venv .venv
.venv\Scripts\python.exe -m pip install --upgrade pip
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe -m pip install "Nuitka[onefile]"

然后执行:

build_win.cmd

构建脚本执行两次 Nuitka 编译:

  • GUIrun_gui.pybuild/onefile/a1packer.exe
  • CLIrun_cli.pybuild/onefile/a1packer-cli.exe

GUI 编译启用 PySide6 插件并包含当前界面所需的 Qt 插件组:

platforms,imageformats,styles,iconengines

构建后验证

发布目录前,先确认 CLI 能识别外部资源:

build\onefile\a1packer-cli.exe --version
build\onefile\a1packer-cli.exe list-swap-gcode

第二条命令应列出:

build/onefile/swap_gcode/

中的文件。

同时启动一次 build/onefile/a1packer.exe,确认:

  • 换料 G-code 下拉框列出已复制的模板。
  • 修改 GUI 选项会创建或更新 build/onefile/settings.json
  • 首次启动前 settings.json 不存在时程序仍能正常运行。

换料 G-code 模板

GUI 会自动扫描以下固定目录:

swap_gcode/

纯 UTF-8 文本文件直接读取。当前扫描器接受以下后缀:

.gcode
.nc
.ngc
.txt

当前源码版本不解码加密的或厂商模板的 G-code 归档。

GUI 中使用方法:

  1. 将模板文件放入 swap_gcode/
  2. 点击 换料 G-code 旁的 刷新
  3. 从下拉框中选择模板。

可编辑 G-code 补丁

GUI 和 CLI 都读取固定补丁文件:

gcode_patches.ini

默认规则:

[patch.a1_start_y]
enabled = true
flag = G0 X128 F30000
find = G0 Y254 F3000
replace = G0 Y250 F3000 ; Patched
max_count = 1

含义:

  • 从可选的 flag 行之后开始查找。
  • 将第一个匹配 find 的行替换为 replace
  • 最多替换 max_count 次。

可在 GUI 中通过 G-code 补丁 复选框禁用,或编辑 INI 文件并保持启用。

换板插入标记也可编辑:

[swap]
insert_before_marker = ;=====printer finish  sound=========

GUI 使用指南

输入 3MF 文件

输入表格支持:

  • 添加 3MF:选择一个或多个 .3mf 文件。
  • 拖放 .3mf 文件到表格中。
  • 拖放文件夹到表格中。GUI 会添加该文件夹内所有顶层 .3mf 文件。
  • 移除:移除选中行。
  • 全部移除:清空全部输入列表。
  • 上移 / 下移:调整输入顺序。
  • 应用默认份数至选中行:将当前默认份数覆盖到选中行。

列说明:

  • 3MF 文件:源文件路径。
  • 份数:该源文件重复的次数。
  • 时间:预估打印时间 × 份数。
  • 耗材:预估耗材用量 × 份数。

时间和耗材数据读取自:

Metadata/slice_info.config

如果源 3MF 缺少此元数据,GUI 显示"未知"。

输入列表下方的汇总行显示当前表格的总板数、预估时间和耗材。

右侧缩略图面板显示选中输入文件的活动面板预览(若 3MF 中包含)。

构建 3MF 按钮

构建 3MF 按钮位于输入列表右下方,便于快速批量操作。

正常合并模式下,一次点击生成一个包含所有输入行的输出 3MF。

独立批处理模式下,一次点击为每行输入各生成一个输出 3MF。

换料 G-code

选择插入到每个重复面板中的弹射/换板 G-code 块。

下拉框内容来自:

swap_gcode/

按钮:

  • 刷新:重新扫描目录。
  • 打开文件夹:打开模板目录。

新输入的默认份数

设置添加到或拖入的新文件的默认份数。

这不会自动更改已有行。对已有行使用 应用默认份数至选中行

热床降温

控制是否在 SwapMod G-code 块之前插入热床等待温度。

启用示例:

M190 S45

禁用后,打包器不添加 M190 行。

弹射后等待时间

在 SwapMod G-code 块之后添加驻留时间。

45 秒示例:

G4 P45000

剩余时间板号

启用后,打包器按以下公式偏移 M73 ... R... 剩余时间值:

板号 × 100 小时 × 60 分钟

这使得 A1 剩余时间的百位能显示当前板号。

示例:

  • 第 1 板:+6000 分钟
  • 第 2 板:+12000 分钟
  • 第 3 板:+18000 分钟

最后换料

启用后,换板/弹射块也会插入到最后一个重复面板之后。

禁用后,最后一个重复面板正常结束,不执行换料 G-code 块。

G-code 补丁

应用来自以下文件的规则:

gcode_patches.ini

打开配置文件 按钮打开该固定文件进行编辑。

3MF 元数据

选项:

  • 保留原始预测和重量
    保持基础 3MF 中 slice_info.config 的预测和重量值不变。这与观察到的厂商打包器行为最一致。

  • 累加预测和耗材用量
    使用所有重复面板的总和更新第一块面板的元数据。从统计角度看更合理,但可能与厂商软件的表现不同。

预览图处理

默认情况下,输出 3MF 保留基础归档中对应当前输出面板的预览成员,并用以下内容重写这些 PNG 预览:

  • 最多 9 个不同输入文件的预览图合成;
  • 一个简短的绿色标签(如 5 P),施加在最终合成图上。

如果预览图缺失或无法读取,打包器保留可用基础预览,仍尝试施加面板标签。

CLI 可通过以下选项禁用预览重写:

--no-preview-label

批处理模式

合并模式

默认行为。

所有输入行打包为一个输出文件。

示例:

A.3mf 份数 2
B.3mf 份数 3

输出:

一个打包 3MF,包含 A, A, B, B, B

独立批处理模式

启用时,GUI 显示说明弹窗。

每行输入被视为独立构建。

示例:

A.3mf 份数 5
B.3mf 份数 5
C.3mf 份数 5

输出:

5 Plates - A.3mf
5 Plates - B.3mf
5 Plates - C.3mf

此模式用于快速将大量独立的单板 3MF 文件批量转换为多份数 SwapMod 包。

GUI 并行构建这些独立输出,并发数受 CPU 核心数及安全上限限制。

不会将所有输入合并为一个文件。

输入处理

选项:

  • 添加输入时跳过重复文件路径
    防止意外多次添加同一路径。

  • 构建成功后清空输入列表
    构建成功后清空表格。在独立批处理模式下,仅当所有输出构建成功后才会清空。

输出目录

如果此字段为空:

  • 合并模式写入第一个输入文件同目录。
  • 独立批处理模式将每个输出写入各自输入文件同目录。

如果选择了目录,所有输出都写入该目录。

输出文件名规则

默认规则:

{plates} Plates - {sources}.3mf

点击规则字段旁的 ? 按钮显示标记帮助。

可用标记:

标记 含义
{source} 第一个输入文件的文件名(不含 .3mf
{sources} 源文件摘要。单个源使用其文件名;多个源则显示为 first_source_and_N_more
{plates} 本输出中的总板数
{copies} 本输出中的总份数
{date} 当前日期,格式 YYYYMMDD
{time} 当前时间,格式 HHMMSS

在独立批处理模式下,标记按每行输入单独计算。

示例:

{plates} Plates - {sources}.3mf
SwapMod - {source} - x{copies}.3mf
{date}_{time}_{source}.3mf

GUI 设置

GUI 将设置写入程序目录:

settings.json

这是有意为之,以便便携式解压目录或打包的 .exe 版本能将选项保持在应用程序旁边。

保存的选项包括:

  • 当前选中的换料 G-code 文件。
  • 默认份数。
  • 热床降温设置。
  • 弹射后等待时间。
  • 剩余时间板号开关。
  • 最后换料开关。
  • G-code 补丁开关。
  • 元数据模式。
  • ZIP 压缩级别。
  • 独立批处理模式。
  • 输入处理选项。
  • 输出目录。
  • 输出文件名规则。

CLI 使用示例

列出可用的换料 G-code 文件:

python -m a1_swap_mod_packer.cli list-swap-gcode

单源文件 × 5 份:

python -m a1_swap_mod_packer.cli build \
  --item "SC05720_01.gcode(1).3mf" 5 \
  --swap-gcode "a1_swap.gcode" \
  --cool-bed 45 \
  --wait 45 \
  --show-plate-number \
  -o "5 Plates - SC05720_01.gcode(1).3mf"

多源文件合并输出:

python -m a1_swap_mod_packer.cli build \
  --item "A.3mf" 2 \
  --item "B.3mf" 3 \
  --swap-gcode "a1_swap.gcode" \
  -o "5 Plates - A_and_B.3mf"

使用累加元数据模式:

python -m a1_swap_mod_packer.cli build \
  --item "A.3mf" 5 \
  --swap-gcode "a1_swap.gcode" \
  --metadata-mode sum \
  -o "5 Plates - A.3mf"

禁用 G-code 补丁:

python -m a1_swap_mod_packer.cli build \
  --item "A.3mf" 5 \
  --swap-gcode "a1_swap.gcode" \
  --no-gcode-patches \
  -o "5 Plates - A.3mf"

位置参数输入 + 统一份数:

python -m a1_swap_mod_packer.cli build \
  "A.3mf" "B.3mf" \
  --copies 2 \
  --swap-gcode "a1_swap.gcode" \
  -o "4 Plates - A_and_B.3mf"

指定换料 G-code 目录和 ZIP 压缩级别:

python -m a1_swap_mod_packer.cli build \
  --item "A.3mf" 5 \
  --swap-gcode "a1_swap.gcode" \
  --swap-gcode-dir "D:\SwapMod\swap_gcode" \
  --zip-level 9 \
  -o "5 Plates - A.3mf"

禁用最后换料和预览标签重写:

python -m a1_swap_mod_packer.cli build \
  --item "A.3mf" 5 \
  --swap-gcode "a1_swap.gcode" \
  --no-swap-after-final \
  --no-preview-label \
  -o "5 Plates - A.3mf"

CLI 常用选项速查:

选项 含义
--version 打印当前版本
list-swap-gcode 列出换料 G-code 目录中的文件
--item PATH COPIES 添加一个带独立份数的输入;可多次使用
位置参数 inputs + --copies N 添加多个使用相同份数的输入
--swap-gcode-dir DIR 使用自定义换料 G-code 目录
--no-bed-cooldown 不在换料块前插入 M190
--no-swap-after-final 最后一块板后不执行换料块
--line-ending lf|crlf 选择生成 G-code 的换行符;默认 crlf
--zip-level 1-9 zlib-ng Deflate 压缩级别;默认 7
--no-preview-label 不重写预览图标签/合成图
--no-gcode-patches 不应用 gcode_patches.ini 中的规则
S
Description
Open-source 3MF packer for Bambu Lab A1 SwapMod workflows.
Readme GPL-3.0 3.9 MiB
Languages
Python 98.1%
G-code 1.4%
Batchfile 0.5%