Bambu Lab 接入调研与架构草案¶
调研日期:2026-09-11 BambuHelper 参考快照:
a3d8ba46b7e58d5ab05f88ec9ce0cf1d6c9b0c2d本文是开发前的设计依据,不表示这些非官方协议得到 Bambu Lab 的兼容性承诺。实施更新(2026-09-13):ESP32 Cloud Monitor 的当前落地边界、单一网络 actor、无 PSRAM 大包处理及分阶段任务,以
bambu-esp32-kimi-handoff.md为准。本文中的完整 backend 重构、LAN Developer 和桌面配对仍是后续方向,不作为本轮前置条件。
1. 先说结论¶
Bambu 接入不能只设计成“云端只读、局域网可控”两个布尔分支。至少要分开描述三个维度:
- 打印机生态:Klipper 或 Bambu。
- 连接通道:Moonraker、Bambu Cloud MQTT 或 Bambu LAN MQTT。
- 当前能力:状态、灯光、暂停、温控、移动、文件、摄像头等各自是否可用。
Bambu 的云连接在未获得官方授权的情况下应按状态监视器设计。官方资料仍明确保留状态读取,并曾明确保留 LED 控制;打印启动、运动、温控、风扇、AMS 设置和校准等关键操作受授权机制限制。局域网 Developer Mode 会开放 MQTT、视频和 FTP,适合自定义控制器,但这些通信协议仍被官方标注为“不提供正式支持”。因此即使处于 LAN,也必须根据连接结果、机型和固件动态生成能力集合,不能直接假定所有操作都可用。
建议首个可用版本同时完成两条路径:
- Cloud Monitor:实时状态、温度、进度、剩余时间、层数、AMS 和故障;产品策略默认不显示控制入口。
- LAN Developer:先完成相同的监视能力,再逐项开放已经在真机上验证过的控制。
2. 资料可信度¶
| 等级 | 来源 | 本文如何使用 |
|---|---|---|
| 官方政策 | Firmware Update Introducing New Authorization Control System、Updates and Third-Party Integration with Bambu Connect | 判断哪些操作受授权限制,以及 Developer Mode 的官方定位 |
| 官方客户端接口 | BambuStudio NetworkAgent.hpp |
证明官方 Studio 将网络能力放在独立 Network Plugin 后面;不把它当作开放协议文档 |
| 社区协议文档 | OpenBambuAPI MQTT、FTPS、TLS、Video | 整理线上的消息格式、端口和常见命令;实现后必须真机验证 |
| 中国区登录对照 | OpenBambuAPI Cloud HTTP、中国区登录流程样例 | 对照手机号、短信验证码和验证码登录的请求字段;仍须用真实账号验证 |
| 重点参考实现 | Keralots/BambuHelper | 核对 ESP32 上的 TLS/MQTT 内存、云端保活、增量状态合并、发现和多机型数据差异 |
官方没有公开一套稳定、完整、面向普通开源硬件的 Bambu API。合作伙伴技术资料需要另外联系 Bambu Lab。下面标为“社区协议”的内容可能随固件和云服务变化。
3. 官方授权边界¶
2025 年的官方说明把以下操作列为需要授权的关键操作:
- 绑定和解绑打印机;
- 启动远程视频;
- 固件升级;
- 通过 LAN 或云端发起打印;
- 运动、温度、风扇、AMS 设置和校准等控制。
官方明确表示状态推送不受该机制影响,例如 Home Assistant 使用的 MQTT 状态;同一份 FAQ 还列出了温度、位置、速度等读取和 LED 控制。暂停、继续、取消并没有得到足够清晰的逐项承诺,本项目应先视为受限控制,只有收到成功响应并完成真机验证后才开放。
Developer Mode 的官方描述是手动开放 MQTT、直播和 FTP,由用户自行承担局域网安全责任。它与“是否登录云账号”不是同一个概念,也不应在配置里合并为同一个字段。新机型和不同固件上的菜单名称、是否要求 LAN-only、开放的端口都可能不同,所以设置页只说明前置条件,最终权限由运行时探测决定。
4. 已知通信面¶
4.1 MQTT 连接¶
社区协议和 BambuHelper 当前实现一致使用 MQTT over TLS 端口 8883。
| 通道 | Broker | 用户名 | 密码/凭据 | TLS |
|---|---|---|---|---|
| LAN | printer_ip:8883 |
bblp |
打印机 LAN access code | 应信任 Bambu CA,并用打印机序列号做 SNI/证书名称校验 |
| Cloud(欧美) | us.mqtt.bambulab.com:8883 |
u_{user_id} |
Bambu access token | 公网 CA 完整校验 |
| Cloud(中国) | cn.mqtt.bambulab.com:8883 |
u_{user_id} |
Bambu access token | 公网 CA 完整校验 |
不要照搬 BambuHelper 在 LAN 上直接 setInsecure() 的做法。OpenBambuAPI 已记录 Bambu CA 和序列号 SNI 的校验方式;如果某个平台暂时无法完成主机名校验,应把降级行为限制在明确的兼容选项里,而不是默认关闭证书校验。
4.2 MQTT Topic 与消息封装¶
| Topic | 方向 | 用途 |
|---|---|---|
device/{serial}/report |
打印机 → 客户端 | 状态增量、完整状态、命令应答 |
device/{serial}/request |
客户端 → 打印机 | 请求完整状态或发送控制命令 |
请求基本格式:
{
"pushing": {
"sequence_id": "1",
"command": "pushall",
"version": 1,
"push_target": 1
}
}
命令应答通常在同一业务对象中带回相同 sequence_id、result 和可选 reason。实现必须用序列号关联应答,不能把 MQTT publish 成功当作打印机已经执行成功。
4.3 状态是“完整快照 + 增量”¶
pushing.pushall 请求完整状态,常规上报通常是 print.command = push_status。P1/A1 等机型会只发送发生变化的字段,因此解析器必须把消息作为 patch 合入当前状态,缺字段表示“保持原值”,不能清零。
首版需要解析的公共字段:
| 公共模型 | Bambu 常见字段 |
|---|---|
| 打印状态 | gcode_state、mc_print_stage、print_error、hms |
| 文件与进度 | subtask_name / gcode_file、mc_percent、layer_num、total_layer_num、mc_remaining_time |
| 温度 | nozzle_temper、nozzle_target_temper、bed_temper、bed_target_temper、chamber_temper |
| 速度与风扇 | spd_lvl、spd_mag、cooling_fan_speed、big_fan1_speed、big_fan2_speed、heatbreak_fan_speed |
| 设备状态 | wifi_signal、lights_report、ipcam、门状态(字段依机型变化) |
| AMS | ams.ams[]、tray、当前/目标 tray、湿度、温度、剩余量和烘干状态 |
完整状态消息会明显大于 Moonraker 的常规增量。BambuHelper 为 MQTT payload 预留 40 KiB,并记录 H2C 加三套 AMS 的消息约 33 KiB。本项目应默认允许 48 KiB 可配置上限,并支持 ESP-MQTT 的分片重组;有 PSRAM 时优先放 PSRAM,无 PSRAM 板型只维持一个活动打印机连接。
pushall 只在首次连接、状态恢复和明确的手动刷新时使用。OpenBambuAPI 对 P1P 给出的经验限制是不应高于每五分钟一次;BambuHelper 也为云端恢复设计了更低频率。不要用固定 30 秒轮询代替增量订阅。
4.4 已知控制命令¶
以下是社区协议中已有实现或样例的能力。表中的“首版策略”是本项目的产品决策,不表示协议本身做不到。
| 能力 | Bambu 消息 | Cloud Monitor | LAN Developer | 首版策略 |
|---|---|---|---|---|
| 请求完整状态 | pushing.pushall |
是,限频 | 是,限频 | 实现 |
| 灯光 | system.ledctrl |
官方曾明确保留 | 是 | Cloud 默认仍隐藏,LAN 可开放 |
| 暂停/继续/取消 | print.pause / resume / stop |
不作承诺 | 通常可用 | 真机验证后开放 |
| 打印速度档 | print.print_speed,1..4 |
不作承诺 | 通常可用 | 真机验证后开放 |
| 喷嘴/热床温度 | print.gcode_line 中的 M104 / M140 |
受限 | Developer Mode 下待验证 | 第二批开放 |
| 点动/归位/挤出 | print.gcode_line |
受限 | Developer Mode 下待验证 | 单独真机验证,不与温控一起放开 |
| 发起 SD 卡打印 | print.project_file / gcode_file |
受限 | 依机型和文件格式 | 文件层完成后再做 |
| AMS 设置/换料 | 多个 print.ams_* 命令 |
受限 | 依机型 | 后续专用 UI |
Bambu 的 print.stop 只是取消当前任务,不能当作 Klipper 的 M112 紧急停止。 在找到并验证等价语义前,Bambu 模式下必须隐藏或禁用“急停”,也不能把“固件重启”按钮映射成不相关命令。
4.5 发现、文件和视频¶
- 发现:BambuHelper 同时监听
239.255.255.250:1990和:2021的 SSDP 风格广播,从USN、Location、DevName.bambu.com和DevModel.bambu.com取序列号、IP、名称和型号。发现只能帮助填写地址,不能证明控制权限。 - 文件:社区协议记录的传统 LAN 文件通道是 implicit FTPS
990,用户名bblp,密码为 access code。新机型可能使用不同的隧道或关闭传统通道,应通过能力探测隔离。 - 视频:P1/A1 常见为 TLS
6000上的 JPEG 帧;X1 和部分新机型使用 RTSPS322。视频协议、授权和内存开销差异很大,不进入首版核心范围。
5. Cloud Monitor 的认证设计与当前实现¶
BambuHelper 支持账号密码、邮件验证码和手工 token,并通过账号接口取得用户 ID 与绑定设备列表。它使用的登录端点和网页代理行为不是公开稳定 API,不适合直接固化进首版固件。
Windows 桌面端现已实现首个可测试闭环:
- 登录页可切换中国区(
.cn)和全球区(.com)。 - 全球区使用 Email;中国区允许手机号和 Email 二选一。两者都支持密码登录,验证码登录分别走短信和邮件;密码登录后也支持验证器应用提供的 TFA 验证码。
- 登录成功后立即读取账号绑定的打印机列表,并把用户选择的序列号、型号和名称关联到当前打印机槽位。
- 密码和验证码只存在于当前进程内存,工作线程用完立即清零;不会写入配置或日志。
- access token 和账号使用 Windows DPAPI 加密后存入独立的
bambu_cloud.secret,不进入moonraker.conf。退出登录会清空该文件。 - 网络请求在独立工作线程执行,LVGL 线程只读取加锁快照,因此慢连接不会阻塞界面或旋钮。
- Windows 产品端使用 MQTT 3.1.1 over TLS 订阅所选机器的
device/{serial}/report,连接后发送一次pushall,随后把push_status当作增量 patch 合并。TLS 使用 Windows 系统根证书并校验 Broker 主机名;OpenSSL 静态链接,不给发行包增加运行时 DLL。 - 已接入公共打印机模型的实时字段包括打印状态、任务名、进度、剩余时间、层数、 喷嘴和热床的当前/目标温度。云端能力集合仍为只读,状态同步不会开放控制按钮。
access token 可能是 JWT,也可能是不能本地解析的短令牌。实时通道优先从 JWT
载荷读取 uid/sub/user_id;失败时在线程中调用 Profile API 取得 uidStr/uid,
避免在 LVGL 线程中等待网络。Bambu 云只提供剩余分钟而没有可靠的已用时间字段,
当前 UI 用进度与剩余时间估算“已用”,其余数据均直接来自打印机上报。
当前登录链路基于 BambuHelper 和中国区登录样例使用的网页/API 组合:密码及验证码登录走
/v1/user-service/user/login;邮件验证码走 sendemail/code,中国区短信验证码走
sendsmscode。验证器 TFA 先从网站端取得 CSRF Cookie,再提交
/api/sign-in/tfa;设备列表使用网站代理下的
/api/v1/iot-service/api/user/bind。这些仍是非官方稳定接口,后续变化应只影响
bambu_cloud 端口层。
嵌入式端当前仍保留空实现,避免把账号密码键盘和会变化的网页认证协议塞进固件。 下一阶段把桌面端取得的 cloud profile 配对到 ESP32 时遵守以下边界:
- 固件只接受
region + user_id + access_token + printer_serial,不保存 Bambu 账号密码。 - 如果官方网页接口变化,只更新桌面端登录模块,不迫使所有 ESP32 固件跟着变化。
- UI 明确展示“凭据已过期/认证失败”,不要只显示“打印机离线”。
- 同一账号的 token 是账户级凭据,多个打印机槽只引用一个 cloud profile,不重复存六份。
- 日志、诊断页和崩溃信息永远不输出 token、access code 或完整账号 ID。
秘密存储不应继续塞进当前 moonraker.conf:token 可接近 1 KiB,而且普通文本文件没有保护。Windows 已使用 DPAPI 独立保存;ESP32 配对阶段再增加独立 NVS blob。如果设备未启用 flash encryption,设置页需要诚实说明物理读取仍可能取得凭据。
6. 现有代码的问题¶
当前 UI 已经只通过 printer.h 读取大部分打印机状态,这是正确的起点;但实现仍把“公共打印机模型”和“Klipper 后端”写在同一个 printer_model.c 中:
- 初始化函数直接启动
moonraker_start(); - 控制函数直接生成 Klipper G-code 或调用
klipper_api; - 文件列表直接调用 Moonraker RPC;
- 连接状态和 RTT 的注释、错误文本、枚举都带 Moonraker/Klippy 语义;
panel_main.c、panel_printers.c、panel_moonraker.c仍有少量直接依赖 Moonraker。
如果直接往这些函数里加入 if (Bambu),协议分叉会扩散到每个 UI 面板,而且 Cloud Monitor 的禁用逻辑只能靠面板各自记住。后续添加 AMS、双喷头、摄像头时会再次失控。
7. 目标架构¶
flowchart TB
UI[LVGL panels] --> API[printer service API]
API --> STORE[shared printer store]
API --> CAPS[capability and policy gate]
CAPS --> MANAGER[active backend manager]
MANAGER --> K[Klipper backend]
MANAGER --> B[Bambu backend]
K --> MR[Moonraker WebSocket]
B --> BP[Bambu protocol parser / command builder]
BP --> MQTT[platform MQTT transport]
B --> DISC[LAN discovery]
B -. later .-> FTPS[FTPS files]
B -. later .-> CAM[camera transport]
MR --> STORE
MQTT --> BP --> STORE
7.1 printer_store:只保存领域状态¶
把当前 printer_model.c 拆成不认识 Moonraker 和 MQTT 的状态仓库。建议用一次快照代替继续增加全局 getter:
typedef struct {
uint32_t revision;
printer_state_t state;
printer_connection_state_t connection;
printer_capabilities_t capabilities;
printer_temperature_t nozzle[2];
uint8_t nozzle_count;
printer_temperature_t bed;
printer_temperature_t chamber;
int progress_permille;
uint32_t elapsed_s;
uint32_t remaining_s;
uint32_t layer_current;
uint32_t layer_total;
char job_name[96];
printer_ams_state_t ams;
printer_error_t last_error;
} printer_snapshot_t;
现有 printer_temp_ext() 等访问器先继续保留,并从快照读取,避免一次改完所有面板。后端只能提交 patch 或连接事件,不能直接操作 LVGL 对象。
7.2 printer_backend:生命周期和命令映射¶
typedef struct printer_backend_vtable {
bool (*start)(const printer_profile_t *profile);
void (*stop)(void);
void (*poll)(void);
printer_capabilities_t (*capabilities)(void);
printer_cmd_result_t (*command)(const printer_command_t *cmd);
bool (*files_refresh)(printer_files_cb cb, void *ud);
} printer_backend_vtable_t;
后端管理器只运行当前槽位的一个连接。切换打印机时按 stop old → clear transient state → start new 执行,避免 CYD 一类无 PSRAM 板为六个槽位同时维持 TLS/MQTT 会话。后台多打印机监控以后再作为可选能力增加。
7.3 能力集合,而不是模式判断¶
enum {
PRINTER_CAP_STATUS = 1ull << 0,
PRINTER_CAP_JOB_PROGRESS = 1ull << 1,
PRINTER_CAP_AMS_READ = 1ull << 2,
PRINTER_CAP_LIGHT_CONTROL = 1ull << 3,
PRINTER_CAP_PAUSE = 1ull << 4,
PRINTER_CAP_RESUME = 1ull << 5,
PRINTER_CAP_CANCEL = 1ull << 6,
PRINTER_CAP_TEMP_CONTROL = 1ull << 7,
PRINTER_CAP_MOVE = 1ull << 8,
PRINTER_CAP_EXTRUDE = 1ull << 9,
PRINTER_CAP_FILES = 1ull << 10,
PRINTER_CAP_PRINT_START = 1ull << 11,
PRINTER_CAP_EMERGENCY_STOP = 1ull << 12,
PRINTER_CAP_CAMERA = 1ull << 13,
};
能力来自三层交集:
编译进固件的功能 ∩ 当前连接策略允许的功能 ∩ 真机/固件确认可用的功能
UI 只查询能力位。控制命令返回 QUEUED / OFFLINE / UNSUPPORTED / AUTH_REQUIRED / REJECTED / INVALID,界面据此禁用入口或展示明确原因。MQTT 返回 access_denied 等结果时,后端立即撤掉对应动态能力,不能让用户反复点击一个必然失败的按钮。
7.4 推荐目录¶
src/core/printer/
printer_service.c
printer_store.c
printer_backend.h
printer_types.h
backend_klipper.c
src/core/bambu/
backend_bambu.c
bambu_protocol.c
bambu_status.c
bambu_commands.c
bambu_discovery.h
bambu_cloud_profile.c
src/ports/esp32/bambu/
bambu_mqtt_esp32.c
bambu_discovery_esp32.c
src/ports/desktop/bambu/
bambu_mqtt_desktop.c
bambu_discovery_desktop.c
协议解析和命令构造保持纯 C、无 LVGL、无 socket 依赖。这样 Windows 模拟器可以喂固定 MQTT fixture,Windows 产品和 ESP32 再各自接真实 transport。
8. 配置模型¶
当前 machine_mode_N 已经是每槽字段,但 Bambu 配置不能继续借用 host_N/port_N/api_key_N 的 Moonraker 语义。建议迁移成通用打印机 profile,并保留旧文件自动导入:
active=2
slot_0_type=klipper
slot_0_name=Voron
slot_0_host=192.168.1.20
slot_0_port=7125
slot_0_api_key=
slot_2_type=bambu
slot_2_name=P1S
slot_2_bambu_link=lan
slot_2_host=192.168.1.35
slot_2_serial=01P...
slot_2_secret_ref=bambu_lan_2
slot_3_type=bambu
slot_3_name=X1C Cloud
slot_3_bambu_link=cloud
slot_3_serial=00M...
slot_3_cloud_profile=0
printers.conf 只保存非秘密配置;access code、token 放 bsp_secret。bambu_link 与 machine type 分开,使同一台 Bambu 打印机以后可以在 LAN 不可达时切换到 Cloud Monitor,而不会把它伪装成另一种机型。
设置页建议流程:
- 选择 Klipper / Bambu;
- Bambu 下选择 局域网控制 / 云端监视;
- LAN 页面提供扫描,选中后自动填写 IP、序列号、名称和型号,再输入 access code;
- Cloud 页面选择区域和云账号 profile,再从账号设备列表选择序列号;
- 连接成功后显示实际能力,例如“状态、AMS、灯光、暂停可用;温控被固件拒绝”。
9. Kconfig 边界¶
建议增加:
CONFIG_KR_BACKEND_BAMBU
CONFIG_KR_BAMBU_LAN
CONFIG_KR_BAMBU_CLOUD_MONITOR
CONFIG_KR_BAMBU_DISCOVERY
CONFIG_KR_BAMBU_MQTT_BUFFER_SIZE=49152
CONFIG_KR_BAMBU_FILES # 后续
CONFIG_KR_BAMBU_CAMERA # 后续,依赖 PSRAM/大屏
Cloud 登录网页、保存账号密码和摄像头不应成为默认固件的一部分。桌面产品编译 Klipper、LAN Bambu 和 Cloud Monitor;嵌入式板型可按 flash/RAM 关闭 Cloud、文件或摄像头,但公共 UI 和能力判断保持一致。
10. 实施顺序¶
阶段 A:无行为变化的核心拆分¶
- 建立
printer_store、backend vtable、能力位和带结果的命令 API; - 把现有 Moonraker 实现装进 Klipper backend;
- 清除 UI 对
moonraker_client.h的直接依赖; - Windows 产品、模拟器和四个 ESP32 目标保持现有行为。
阶段 B:Bambu 状态最小闭环¶
- Bambu profile、secret 接口、LAN discovery;
- MQTT transport、分片重组、TLS、report/request topic;
pushall+push_status增量合并;- 使用保存的 MQTT fixture 在 Windows 模拟器展示温度、状态、进度和 AMS;
- 真机只读验证 LAN 与 Cloud 各一台。
阶段 C:LAN 基础控制¶
- 灯光、暂停、继续、取消、速度档;
- 对每条命令检查对应
sequence_id/result/reason; - 真机成功后才设置能力位;
- 温控、点动、归位和挤出分别验证,避免一次开放整组高风险控制。
阶段 D:文件与启动打印¶
- FTPS 文件列表和删除;
- 解析 3MF plate/AMS mapping;
- 为 Bambu 单独设计启动打印确认页,不能复用 Klipper 的“文件名 → 立即打印”参数模型;
- 新机型如果不提供传统 FTPS,能力保持关闭,不在协议层伪装成功。
阶段 E:扩展能力¶
- 摄像头;
- AMS 换料和耗材设置;
- 双喷头、腔温和新机型专有字段;
- 可选的多打印机后台监控。
11. 开工前需要确认的产品决定¶
- Cloud Monitor 是否严格只读:建议首版连官方仍允许的 LED 控制也隐藏,使“云端监视”语义清楚;以后可以单独增加“允许云端灯光”。
- 首批 LAN 控制范围:建议先做灯光、暂停/继续/取消、速度,再做温控;运动、挤出和发起打印等待真机逐项验证。
- 云凭据入口:建议首版手工 token,随后由 Windows 配对助手登录并写入 ESP32;不在 ESP32 的 HTTP 页面收账号密码。
- 首批真机矩阵:至少需要一台 P/A/X 系列 Developer Mode 机器。H2/P2 等新机型由运行时探测支持,不在第一版写死“完整控制”。
- 急停 UI:在 Bambu 没有已验证的等价命令前隐藏急停,保留普通“取消打印”。
确认这些决定后,先实施阶段 A,再用 Bambu MQTT fixture 做阶段 B;这样第一次接真机时验证的是协议和模型,不会同时承担 UI、配置和旧 Klipper 回归三类问题。