Klipper API 服务器技术文档深度解析
Klipper API服务器技术摘要 Klipper API服务器是一个基于Unix Domain Socket的本地通信服务,采用JSON协议实现打印机控制功能。核心特点包括: 高性能设计:使用Unix Domain Socket实现零拷贝通信,通过文件权限控制访问 异步协议:消息以0x03(ETX)分隔,支持请求-响应和订阅推送两种模式 功能覆盖:提供系统信息查询、紧急停止、G-Code执行、
第 1 章 API 服务器概述
Klipper 的 API 服务器是运行在主机软件 klippy.py 内部的一个 Unix Domain Socket 服务。它允许外部程序(例如 Moonraker、自定义面板)通过标准 JSON 协议对打印机进行查询和控制。
1.1 启动 API 服务器
要让 Klipper 主机进程开启 API 功能,必须使用 -a 参数指定 Unix Domain Socket 的路径。
~/klippy-env/bin/python ~/klipper/klippy/klippy.py ~/printer.cfg -a /tmp/klippy_uds -l /tmp/klippy.log
设计意图
-
选择 Unix Domain Socket 而非 TCP:
-
性能更高,零拷贝,无需经过网络栈。
-
天然具有访问控制(文件权限),安全性优于本地 TCP 监听。
-
符合 Linux 下服务间通信的惯例,便于与 Moonraker 等组件集成。
-
-
路径自定义:可指定任意路径,便于容器或沙盒环境使用。
1.2 客户端连接与调试工具
Klipper 提供了 scripts/whconsole.py 脚本,可以方便地对 API 进行手动测试。该工具实现了消息帧的封装与解析。
~/klipper/scripts/whconsole.py /tmp/klippy_uds
该工具从标准输入读取 JSON 命令(每行一个),自动添加 ASCII 0x03 结束符,并将响应打印到标准输出。这是最快速的调试手段。
调试技巧: 如果需要抓取通信原始数据,可以使用 socat 进行双向转发,例如:
socat -v UNIX-CONNECT:/tmp/klippy_uds,forever OPEN:/dev/null
这样可以在终端看到所有收发的 JSON 消息,便于排查协议错误。
第 2 章 通信协议设计
2.1 消息帧格式
Klipper API 的 Socket 通信采用简单的分隔符协议:
<JSON对象><0x03><JSON对象><0x03>...
-
每条消息是一个完整的 JSON 文本。
-
消息结束符为 ASCII 0x03 (ETX),而非换行。
为何使用 0x03 而非换行? 因为 JSON 文本中可能包含换行符(例如 G-Code 脚本),用 0x03 可避免对消息内容进行转义。这是一个典型的二进制安全的定界符选择。
2.2 请求格式
请求必须是 JSON 对象,包含以下字段:
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
method |
string | 是 | 指定要调用的 API 端点,例如 "gcode/script" |
params |
object | 否 | 传递给端点的参数,必须是一个字典 |
id |
any | 建议 | 用于匹配请求与响应。若省略或为 null,则服务器不返回响应 |
示例:
{"id": 123, "method": "info", "params": {}}
2.3 响应格式
-
成功响应:
{"id": 123, "result": {...}}
-
错误响应:
{"id": 123, "error": {"message": "描述信息", "error": "错误类型"}}
id 字段会原样返回,客户端可借此实现并发请求匹配。没有 id 的请求将不产生任何响应,这类似于 UDP 的“fire and forget”,适合仅需执行不需确认的场景。
2.4 异步与顺序保证
Klipper 会按照接收顺序开始处理请求。但某些端点(如 gcode/script)可能需要等待 G-Code 执行完成才返回。在此期间,后续请求仍会立即开始处理,因此响应顺序可能不保证与请求顺序一致。客户端必须使用 id 字段来识别响应。
设计背景: 这种异步行为使得 Klipper 可以在等待一个长耗时命令(如加热或移动)的同时继续接受并处理其他查询请求,实现了 I/O 复用,避免阻塞。
2.5 订阅机制
许多端点支持订阅模式。客户端在请求的 params 中提供一个 response_template 字典,之后 Klipper 会持续发送异步更新消息,这些消息以模板为基础,并附加 params 字段。
示例请求:
{"id": 123, "method": "gcode/subscribe_output", "params": {"response_template": {"key": 345}}}
后续异步消息可能为:
{"params": {"response": "ok B:22.8 /0.0 T0:22.4 /0.0"}, "key": 345}
每个异步消息都会包含请求时传递的 response_template 中的自定义键,这使得客户端可以在一个 Socket 上建立多个订阅,并通过模板中的唯一标识(如 key)将它们区分开来。
设计精髓:
-
模板机制允许客户端自定义返回的内容,减少解析复杂度。
-
如果不设置
response_template,默认为空{},Klipper 依然会添加params字段。这保证了消息结构的统一。
第 3 章 端点(Endpoint)参考
以下按照模块分类对所有可用的 API 端点进行详解,采用 Doxygen 风格注释,并附上典型应用场景。
3.1 系统信息与紧急停止
3.1.1 info
/** * @brief 获取系统与版本信息,并可上报客户端信息。 * * @param params 可选字典,可以包含 "client_info" 字段, * 该字段为一个任意内容的字典,用于告知 Klipper 客户端的名称与版本。 * @return 成功时返回 "result" 字典,包含主机名、软件版本、配置文件路径、CPU信息等。 * * @note 建议客户端在连接之初调用此端点,传递自身的身份信息,便于日志追踪。 */
请求示例:
{"id": 1, "method": "info", "params": {"client_info": {"version": "my-panel-v2"}}}
3.1.2 emergency_stop
/** * @brief 立即进入紧急停止状态,等价于 M112 命令。 * * @param params 无需参数。 * @return 无特定返回内容。 * * @warning 该操作会立即关闭所有电机和加热器,可能导致打印失败。 */
请求示例:
{"id": 2, "method": "emergency_stop"}
3.2 远程方法注册:register_remote_method
/**
* @brief 允许客户端注册一个可从 Klipper G-Code 宏中调用的远程方法。
*
* @param params 必须包含:
* - "response_template": 字典,作为异步消息的模板(通常包含一个 "action" 键)。
* - "remote_method": 字符串,方法名,G-Code宏中使用的名称。
* @return 成功时返回空对象 {}。
*
* @note 使用 action_call_remote_method() 函数在 gcode_macro 中调用此方法,
* 参数以关键字形式传递。
*
* @see example:
* 注册调用:
* ```json
* {"id":3, "method":"register_remote_method", "params":{"response_template":{"action":"run_beep"}, "remote_method":"my_beep"}}
* ```
* 在宏中调用:
* ```
* [gcode_macro BEEP]
* gcode:
* {action_call_remote_method("my_beep", freq=500, duration=0.2)}
* ```
* Klipper 将发送: `{"action":"run_beep","params":{"freq":500,"duration":0.2}}`
*/
3.3 打印机对象查询与订阅
3.3.1 objects/list
列出所有可查询的打印机对象名称。
请求:
{"id": 4, "method": "objects/list"}
响应:
{"id":4,"result":{"objects":["toolhead", "extruder", "heaters", ...]}}
3.3.2 objects/query
查询指定对象的当前字段值。
/** * @brief 获取一个或多个打印机对象的状态。 * * @param params.objects 是一个字典,键为对象名,值为 null(查询所有字段) * 或一个包含所需字段名的列表。 * @return result.status 包含对应的对象数据,result.eventtime 为采样时间戳。 * * @note 字段定义请参考 Status Reference 文档。 */
示例:
{"id":5, "method":"objects/query", "params":{"objects":{"toolhead":["position"], "heaters":null}}}
3.3.3 objects/subscribe
与 objects/query 格式相同,但会持续推送订阅对象的更新,类似 Flux 流。响应中同样包含初始状态,然后不断发送变更。
应用场景:实时位置监控、温度曲线绘制等。
3.4 G-Code 执行相关端点
3.4.1 gcode/script
/** * @brief 执行一个或多个 G-Code 命令。 * * @param params.script 要执行的 G-Code 字符串,多条命令可用换行分隔。 * @return 请求的 JSON 响应仅在脚本完全执行完毕后返回。 * 若脚本导致错误,则返回 error 对象。 * @warning 终端输出(M117等)不会出现在响应中,需通过 gcode/subscribe_output 获取。 * @note 如果在处理其他 G-Code 时收到此请求,新脚本会被加入队列。 */
使用示例:
{"id":6, "method":"gcode/script", "params":{"script":"G28\nG1 X50 Y50 F3000"}}
3.4.2 gcode/restart 与 gcode/firmware_restart
-
gcode/restart: 触发软件重启(类似 RESTART 命令)。 -
gcode/firmware_restart: 请求固件重启。
两者均需等待待处理命令完成后才完成。
3.4.3 gcode/subscribe_output
/**
* @brief 订阅 G-Code 控制台输出(用于模拟终端窗口)。
*
* @param params.response_template 异步消息模板,默认为 {}。
* @return 初始响应通常是空 result,随后异步推送 {"params":{"response":"..."}}
*
* @note 不建议用于解析状态,状态应使用 objects/subscribe 获取。
*/
3.5 运动诊断端点
3.5.1 motion_report/dump_stepper
/** * @brief 订阅指定步进电机底层的 queue_step 命令流。 * * @param params.name 步进电机的配置名称(如 "stepper_x")。 * @param params.response_template 订阅模板。 * @return 首次响应包含 "header" 描述数据字段,后续推送 "data" 数组。 * * @warning 开启会显著增加系统负载,仅建议调试时使用。 * 数据是内部时间-步数增量序列,需要结合 Klipper 运动学知识分析。 */
3.5.2 motion_report/dump_trapq
类似地订阅工具头的梯形速度队列,用于分析运动规划器的行为。
3.6 传感器诊断端点
3.6.1 adxl345/dump_adxl345
订阅 ADXL345 加速度计原始数据流,可用于共振测试。返回的三轴加速度数据可直接用于绘制频谱。
3.6.2 angle/dump_angle
用于角度传感器(如校准用),输出时间和角度值。
3.6.3 load_cell/dump_force 和 load_cell_probe/dump_taps
-
dump_force: 订阅称重传感器实时压力数据,返回力 (g)、原始计数值等。 -
dump_taps: 用于探测点击事件的详细数据,包含时间和力数组,可绘图。
3.7 打印控制与状态
3.7.1 暂停/恢复/取消
-
pause_resume/pause: 类似 PAUSE 命令。 -
pause_resume/resume: 类似 RESUME 命令。 -
pause_resume/cancel: 类似 PRINT_CANCEL 命令。
这些端点同样会等待当前排队的 G-Code 完成。
3.7.2 query_endstops/status
查询限位开关状态,返回各轴状态("open" 或 "TRIGGERED")。
3.8 床网信息:bed_mesh/dump_mesh
/** * @brief 导出床网网格数据及所有已保存的配置。 * * @param params.mesh_args (可选) 与 BED_MESH_CALIBRATE 相同的参数对象。 * 提供后将使用这些参数重新计算网格数据再返回, * 用于在实际校准前预览探测路径或网格效果。 * @return 包含 current_mesh, profiles, calibration 等详细网格信息。 */
示例:
{"id":100, "method":"bed_mesh/dump_mesh", "params":{"mesh_args":{"ALGO":"lagrange","TENSION":0.3}}}
以上将 Klipper API 的核心部分整理为结构化技术文档。在实际开发中,建议使用 Moonraker 等成熟框架来管理 WebSocket 转发与权限控制。所有端点的详细字段说明需配合官方 Status Reference 一起阅读。
第 4 章 总结与开发注意事项
4.1 设计哲学总结
Klipper API 的设计体现了以下几个核心原则:
-
简单即美:使用纯 JSON 文本协议,不需要二进制序列化库,任何语言都能轻松实现客户端。
-
异步优先:请求响应与订阅推送并存,既能做 RPC 调用,也能做实时数据流。
-
职责分离:API Server 仅提供底层接口,高级功能(如 Web 界面、文件管理、摄像头流)由 Moonraker 等上层组件负责。
-
安全内敛:Unix Domain Socket 天然具有文件权限控制,不暴露网络端口,降低攻击面。
4.2 开发注意事项
| 场景 | 注意点 |
|---|---|
| 订阅管理 | 订阅不会自动取消。若客户端断开连接,Klipper 会清理相关订阅。但若客户端频繁连接断开,可能产生短暂的资源堆积。建议复用连接而非每次请求都新建。 |
| 并发请求 | 响应顺序不保证。务必为每个请求分配唯一的 id,并在客户端维护一个“待处理请求”表进行匹配。 |
| G-Code 执行 | gcode/script 是异步的,响应返回时表示脚本已执行完毕而非提交成功。若需要立即返回,可使用 register_remote_method 自定义行为。 |
| 错误处理 | 错误响应包含 error.message(人类可读描述)和 error.error(错误类型字符串)。客户端应解析后者进行逻辑分支,而非依赖前者。 |
| 性能考虑 | dump_stepper / dump_trapq / adxl345 等诊断端点会产生大量数据,仅在调试时启用。生产环境中长时间开启可能导致 Klipper 主机 CPU 负载过高,影响打印质量。 |
| 协议边界 | 每条 JSON 消息以 0x03 结尾。实现客户端时必须正确处理粘包/半包:接收缓冲可能包含多帧或不完整帧,需扫描 0x03 分割出完整 JSON 再解析。 |
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)