Klipper / Moonraker API 参考文档¶
面向 ESP32 资源受限客户端的 Moonraker Web API 参考。 信息来源:Moonraker 官方文档(GitHub docs)、Klipper Status Reference、Klipper API Server。
1. 网络服务拓扑¶
┌─────────┐ Unix Socket ┌───────────┐ HTTP/WS (7125) ┌────────────┐
│ klippy │ ◀────────────▶ │ Moonraker │ ◀────────────────▶ │ 本 ESP32 │
│ (Klipper│ (Klipper API │ (Tornado) │ │ 客户端 │
│ 进程) │ Server) │ │ │ │
└─────────┘ └───────────┘ └────────────┘
- ESP32 只与 Moonraker 通信,不直连 klippy。
- 默认端口:7125(HTTP/WebSocket),SSL 端口 7130。
- 端点总览:
| 端点 | 协议 | 用途 |
|---|---|---|
ws://host:7125/websocket |
WebSocket | 主通道,JSON-RPC 2.0 长连接 |
ws://host:7125/klippysocket |
WebSocket | 桥接 Klipper API Server(一般用不到) |
POST /server/jsonrpc |
HTTP | JSON-RPC over HTTP(纯轮询方案可用) |
/printer/... |
HTTP REST | 打印机控制与对象查询(多数由 Klipper 注册、Moonraker 透传) |
/server/... |
HTTP REST | 服务器状态、文件、历史、数据库 |
/access/... |
HTTP REST | 鉴权 |
/machine/... |
HTTP REST | 系统管理、电源设备、更新 |
/api/... |
HTTP REST | OctoPrint 兼容层(不需要) |
- HTTP 成功响应统一包一层
{"result": ...}。 - Query string 类型提示:
?seconds:int=120&enabled:bool=true(:int、:float、:bool、:json)。
1.1 鉴权¶
- 局域网通常免鉴权:
moonraker.conf的trusted_clients(CIDR)内的客户端无需任何凭据。ESP32 与打印机同网段时通常直接可信。 - 非可信客户端:
- HTTP:
Authorization: Bearer <JWT>或X-Api-Key: <key>头。 POST /access/login:{"username","password","source":"moonraker"}→{"token"(JWT, 1h), "refresh_token"(~90d)}。POST /access/refresh_jwt:刷新 JWT。GET /access/api_key/POST /access/api_key:查询/重置全局 API key。GET /access/oneshot_token:一次性 token(5 秒有效),拼到 query:ws://host:7125/websocket?token=<base32>(无法设 header 的场景,如 WS 握手、文件下载)。- WS 也可连接后用
server.connection.identify传access_token/api_key。 GET /access/info:查login_required与当前连接是否trusted。
2. WebSocket JSON-RPC 2.0¶
2.1 报文格式¶
请求:
{"jsonrpc":"2.0","method":"printer.info","params":{"arg_one":1},"id":354}
{"jsonrpc":"2.0","result":{...},"id":354}
{"jsonrpc":"2.0","error":{"code":36000,"message":"..."},"id":354}
id):
{"jsonrpc":"2.0","method":"notify_status_update","params":[{...}, 578243.578]}
注意:Moonraker 通知的
params始终是位置参数数组(常为单元素包一个对象)。
2.2 推荐启动连接流程¶
- 循环重试连接
ws://host:7125/websocket。 - 连上后调用
server.info,检查klippy_state: -ready→ 继续; -startup→ 2 秒后重查; -error/shutdown→ 显示printer.info.state_message提示用户; -disconnected→ klippy 未运行或未启用 API Server。 ready后:调printer.objects.list→ 构建并发送printer.objects.subscribe(响应即全量状态)→ 拉文件列表等。- 收到
notify_klippy_disconnected后回到步骤 2 重新等待。
可选:连接后调一次 server.connection.identify(只能调一次):
{"jsonrpc":"2.0","method":"server.connection.identify","params":{
"client_name":"KlipperRemoteESP32","version":"0.1.0","type":"display",
"url":"https://..."},"id":1}
type 对显示屏类应用填 "display"。返回 {"connection_id": ...}。
3. 打印机对象查询与订阅¶
3.1 列出对象¶
GET /printer/objects/list # JSON-RPC: printer.objects.list
→ {"result": {"objects": ["webhooks","toolhead","extruder","heater_bed",...]}}
3.2 查询(一次性)¶
{"jsonrpc":"2.0","method":"printer.objects.query","id":4654,
"params":{"objects":{"gcode_move":null,"toolhead":["position"],
"extruder":["temperature","target"]}}}
null = 全部字段;字符串数组 = 仅指定字段(ESP32 应充分利用以减流量)。
- HTTP 简写:GET /printer/objects/query?gcode_move&toolhead&extruder=target,temperature
- 响应:{"result":{"eventtime":578243.578,"status":{...}}}
- 请求不存在的对象/字段不报错,只是省略。
3.3 订阅(仅 WebSocket/Unix Socket)¶
{"jsonrpc":"2.0","method":"printer.objects.subscribe","id":5434,
"params":{"objects":{"webhooks":["state","state_message"],
"print_stats":null,"virtual_sdcard":["progress","is_active"],
"display_status":["progress","message"],
"extruder":["temperature","target"],"heater_bed":["temperature","target"],
"fan":["speed"]}}}
notify_status_update 推送,只含增量字段。
- 新订阅请求整体覆盖旧订阅;"objects":{} 取消订阅。
- 温度类字段推送频率约 1Hz 量级。
3.4 核心对象字段速查¶
| 对象 | 关键字段 | 含义 |
|---|---|---|
webhooks |
state, state_message |
klippy 状态:ready/startup/error/shutdown |
toolhead |
position [X,Y,Z,E]、homed_axes、max_velocity、max_accel、estimated_print_time、extruder |
指令坐标与运动限制 |
gcode_move |
gcode_position、speed_factor、extrude_factor、speed、absolute_coordinates、homing_origin |
G-code 层位置与倍率 |
extruder / extruder1… |
temperature、target、power(0–1)、can_extrude、pressure_advance |
|
heater_bed |
temperature、target、power(0–1) |
|
fan |
speed(0–1)、rpm(可为 null) |
部件冷却风扇 |
heater_fan <name> |
speed、rpm |
|
print_stats |
state(standby/printing/paused/complete/error/cancelled)、filename、total_duration、print_duration、filament_used(mm)、message、info.total_layer/current_layer |
打印状态主数据源 |
virtual_sdcard |
progress(0–1)、is_active、file_position、file_size、file_path |
文件进度 |
display_status |
progress(M73,5s 超时回落)、message(M117) |
|
idle_timeout |
state(Printing/Ready/Idle)、printing_time |
不能用于判断是否在打印文件 |
motion_report |
live_position、live_velocity、live_extruder_velocity |
实时估算位置 |
pause_resume |
is_paused |
|
stepper_enable |
steppers: {name: bool} |
电机使能 |
temperature_sensor <name> |
temperature、measured_min_temp、measured_max_temp |
|
temperature_fan <name> |
temperature、target、speed |
|
filament_switch_sensor <name> |
filament_detected、enabled |
|
output_pin <name> |
value(数字 0/1,PWM 0.0–1.0) |
|
mcu |
mcu_version、mcu_build_versions、mcu_constants |
|
z_tilt / quad_gantry_level |
applied(bool) |
|
gcode_macro <name> |
variable_* |
宏变量 |
⚠ 嵌入式慎用的大对象:configfile(可能非常大,官方明确警告嵌入式内存风险)、bed_mesh(网格矩阵)、exclude_object。本项目 v1 不订阅。
坐标一律为 4 元素数组 [X, Y, Z, E]。
4. G-code¶
4.1 执行脚本¶
POST /printer/gcode/script # JSON-RPC: printer.gcode.script
{"jsonrpc":"2.0","method":"printer.gcode.script","params":{"script":"G28"},"id":...}
\n 分隔;返回 "ok"。
- 温度/风扇等控制没有专用 API,全部拼 gcode:
- 喷嘴:M104 S{temp}(多挤出头 M104 T{n} S{temp})
- 热床:M140 S{temp}
- 通用加热器:SET_HEATER_TEMPERATURE heater="{name}" target={temp}
- 温度风扇:SET_TEMPERATURE_FAN_TARGET temperature_fan="{name}" target={temp}
- 风扇:M106 S{0-255};速度倍率:M220 S{pct};流量:M221 S{pct}
- 警告:经此端点发 M112 会排队而非立即停机;急停必须用 /printer/emergency_stop。
4.2 命令帮助¶
GET /printer/gcode/help # JSON-RPC: printer.gcode.help
→ {"result": {"RESTART":"Reload config...","SET_HEATER_TEMPERATURE":"...",...}}
5. 打印控制与重启¶
| HTTP | JSON-RPC method | 说明 |
|---|---|---|
POST /printer/print/start?filename=x.gcode |
printer.print.start {"filename":...} |
路径相对 gcodes root |
POST /printer/print/pause |
printer.print.pause |
|
POST /printer/print/resume |
printer.print.resume |
|
POST /printer/print/cancel |
printer.print.cancel |
|
POST /printer/emergency_stop |
printer.emergency_stop |
立即停机(M112 立即版) |
POST /printer/restart |
printer.restart |
klippy 软重启 |
POST /printer/firmware_restart |
printer.firmware_restart |
完全重启 klippy + MCU |
POST /server/restart |
server.restart |
重启 Moonraker |
POST /machine/shutdown / POST /machine/reboot |
machine.shutdown / machine.reboot |
主机关机/重启 |
/printer/* 控制类成功均返回字符串 "ok"。
6. 文件管理(/server/files)¶
Root 概念:默认 gcodes、config(可写)、logs/config_examples/docs(只读)。路径形如 /server/files/gcodes/subdir/a.gcode。
6.1 列表与元数据¶
GET /server/files/list?root=gcodes # server.files.list
→ {"result":[{"path":"a.gcode","modified":...,"size":...,"permissions":"rw"},...]}
GET /server/files/metadata?filename=a.gcode # server.files.metadata
→ {"result":{"size":...,"slicer":"PrusaSlicer","estimated_time":3600,
"object_height":20.0,"layer_height":0.2,"filament_total":5200.0,
"filament_weight_total":15.4,"first_layer_extr_temp":215,
"first_layer_bed_temp":60,
"thumbnails":[{"width":32,"height":32,"size":1234,"relative_path":".thumbs/a-32x32.png"},...],
"job_id":"...","print_start_time":...}}
6.2 缩略图¶
- 取
thumbnails[]中最小尺寸;下载 URL:GET /server/files/gcodes/{gcode所在目录}/{relative_path}例:GET /server/files/gcodes/.thumbs/a-32x32.png - 另有
GET /server/files/thumbnails?filename=...,返回的thumbnail_path相对 gcodes root。
6.3 目录与其他操作¶
| 操作 | HTTP | JSON-RPC |
|---|---|---|
| 目录信息 | GET /server/files/directory?path=gcodes/sub&extended=true |
server.files.get_directory |
| 创建目录 | POST /server/files/directory {"path":"gcodes/d"} |
server.files.post_directory |
| 删除目录 | DELETE /server/files/directory?path=...&force=false |
server.files.delete_directory |
| 移动/重命名 | POST /server/files/move {"source","dest"} |
server.files.move_file |
| 复制 | POST /server/files/copy {"source","dest"} |
server.files.copy_file |
| 上传(仅 HTTP) | POST /server/files/upload(multipart,字段 file,可选 root/path/checksum/print) |
— |
| 下载(仅 HTTP) | GET /server/files/{root}/{filename} |
— |
| 删除文件 | DELETE /server/files/{root}/{filename} |
server.files.delete_file {"path":"{root}/{filename}"} |
| 日志快捷下载 | GET /server/files/klippy.log / moonraker.log |
— |
上传上限 max_upload_size(默认约 210MB);print=true 上传后自动打印。
7. 打印历史与服务器通知¶
7.1 历史¶
GET /server/history/list?limit=50&start=0&order=desc # server.history.list
→ {"result":{"count":N,"jobs":[{"job_id":"...","filename":"...","exists":true,
"status":"completed","start_time":...,"end_time":...,"print_duration":...,
"filament_used":...,"metadata":{...}},...]}}
in_progress/completed/cancelled/error/klippy_shutdown/klippy_disconnect/interrupted
- 其他:GET /server/history/totals、GET /server/history/job?uid=xxx、DELETE /server/history/job?uid=xxx、POST /server/history/reset_totals。
7.2 通知(notify_*)¶
全部经 WebSocket 推送,params 为位置数组:
| method | params | 说明 |
|---|---|---|
notify_status_update |
[{增量对象}, eventtime] |
订阅更新(核心) |
notify_gcode_response |
["message"] |
所有 gcode 输出广播(M117/M118/!!错误)。流量可能很大,ESP32 不需要 console 时收到即丢弃 |
notify_klippy_ready / notify_klippy_shutdown / notify_klippy_disconnected |
无 | 收到 disconnected 需重走启动流程 |
notify_history_changed |
[{action:added/finished, job:{...}}] |
|
notify_filelist_changed |
[{action, item, source_item?}] |
action: create_file/delete_file/move_file… |
notify_proc_stat_update |
[{moonraker_stats, cpu_temp, network, ...}] |
周期性主机资源统计 |
notify_cpu_throttled |
[{bits}] |
主机欠压/降频 |
notify_update_response / notify_update_refreshed |
更新管理 | |
notify_job_queue_changed |
打印队列 | |
notify_active_spool_set / notify_spoolman_status_changed |
Spoolman | |
notify_announcement_update/dismissed/wake |
公告 |
8. 服务器状态 / 健康检查¶
8.1 server.info(ESP32 首要健康检查端点)¶
GET /server/info # JSON-RPC: server.info
→ {"result":{
"klippy_connected":true,
"klippy_state":"ready", // disconnected/startup/ready/error/shutdown
"components":["database","file_manager","klippy_apis","history",...],
"failed_components":[],
"registered_directories":["config","gcodes"],
"warnings":[],
"websocket_count":2,
"moonraker_version":"v0.7.1-...",
"api_version":[1,4,0],"api_version_string":"1.4.0"}}
8.2 printer.info¶
GET /printer/info # JSON-RPC: printer.info
→ {"result":{"state":"ready","state_message":"","hostname":"...",
"software_version":"v0.12.0-...","config_file":"...","cpu_info":"..."}}
state_message 显示原因。
8.3 klippy 未连接时的行为¶
/printer/*端点需要 klippy 已连接,多数还要求ready;否则返回错误。query返回空status对象也是 klippy 异常的信号。server.info、/access/*、多数/machine/*不依赖 klippy。
8.4 其他¶
GET /server/temperature_store?include_monitors=false:每秒采样的温度/目标/功率 FIFO 历史(默认最多 1200 点),适合初始化温度曲线。GET /server/gcode_store?count=100:gcode 响应缓存(console 面板初始化用)。GET /server/config:完整 Moonraker 配置(大,慎用)。
9. 其他有用接口¶
9.1 电源设备(需 [power <name>] 配置)¶
GET /machine/device_power/devices # machine.device_power.devices
→ {"devices":[{"device":"printer","status":"on","locked_while_printing":true,"type":"tplink_smartplug"}]}
GET /machine/device_power/device?device=printer # machine.device_power.get_device
POST /machine/device_power/device # machine.device_power.post_device
{"device":"printer","action":"on"|"off"|"toggle"}
9.2 更新管理¶
GET /machine/update/status、POST /machine/update/refresh、POST /machine/update/upgrade?name=xxx、POST /machine/update/full 等。
9.3 系统管理¶
GET /machine/system_info、GET /machine/proc_stats(cpu_temp、throttled_state)、POST /machine/services/restart|stop|start、GET /machine/peripherals/usb|serial|video|canbus。
9.4 打印队列¶
GET /server/job_queue/status、POST /server/job_queue/job?filenames=a.gcode,b.gcode、DELETE /server/job_queue/job?job_ids=...、POST /server/job_queue/pause|start。
10. ESP32 客户端实践建议(流量/内存控制)¶
- 纯轮询备选方案(官方 tutorial 以 ESP32 为例):不维持 WS,1~2 秒一次
GET /printer/objects/query?webhooks&virtual_sdcard&print_stats。 ETA 计算:eta = metadata.estimated_time − progress × estimated_time,或print_duration/progress − print_duration(防除零)。本项目默认用 WebSocket,但保留此方案作为弱网降级。 - 订阅一次合并:一次
subscribe请求包含全部所需对象与字段(覆盖式语义);只订阅需要的字段。 - 绝不订阅
configfile、bed_mesh等大对象;配置信息按需一次性 query 指定字段。 - 订阅响应即全量,无需额外 query 初始化。
- 缩略图只拉最小尺寸;metadata 每次打印只取一次。
notify_gcode_response打印期流量大:不做 console 时快速丢弃。- klippy 断连后停止对象订阅,改低频(数秒)轮询
server.info直到klippy_state==ready,再重建订阅。 - WS 断线带指数退避重连(1s → 2s → 4s → 封顶 30s)。
- 单帧 JSON 设上限(如 8KB),超限断开重连保护内存。
附录:v1 最小 API 调用清单¶
| 时机 | 调用 |
|---|---|
| 连接后 | server.connection.identify(type=display) |
| 握手 | server.info → printer.info → printer.objects.list |
| 初始化 | printer.objects.subscribe(最小字段集,响应即全量) |
| 温度曲线初始化 | server.temperature_store |
| 温度/风扇/点动 | printer.gcode.script(拼 gcode) |
| 打印控制 | printer.print.start/pause/resume/cancel |
| 急停/重启 | printer.emergency_stop / printer.restart / printer.firmware_restart |
| 文件列表 | server.files.list + server.files.metadata(懒加载) |
| 缩略图 | GET /server/files/gcodes/...(HTTP) |
| 运行中 | 收 notify_status_update 增量合并 |