第 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/restartgcode/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_forceload_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 的设计体现了以下几个核心原则:

  1. 简单即美:使用纯 JSON 文本协议,不需要二进制序列化库,任何语言都能轻松实现客户端。

  2. 异步优先:请求响应与订阅推送并存,既能做 RPC 调用,也能做实时数据流。

  3. 职责分离:API Server 仅提供底层接口,高级功能(如 Web 界面、文件管理、摄像头流)由 Moonraker 等上层组件负责。

  4. 安全内敛: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 再解析。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐