跟着思兼学习Klipper(12) 调用“Method”优雅关机重启
## 前言原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。
文章如有更新请访问 (https://mc.dfrobot.com.cn/thread-312418-1-1.html?fromuid=725344)。
我们约定:主板 指 MCU 部分,上位机 指运行 Klippy 的 MPU Linux 部分。
看过前文 [*Klipper 温控风扇以及电源管理(部分)*](https://mc.dfrobot.com.cn/thread-312100-1-1.html?fromuid=725344) 的朋友,一定了解到了安全关闭上位机系统的重要性,当然如果你是平日自家电脑关机靠直接拔电的壮士,下面的文章可以不用看了。
由于 Gemini 二合一主板的 MCU 和 MPU 是不是独立供电的,此外越来越多朋友的 3D 打印机为了好看,选择把上位机和主板一起封在电气箱内,通过总电源开关一起控制,所以就有了如何打完自动 **安全** 关机的必要性。注意,这里的安全是先关闭上位机电脑的 Linux 操作系统,再关闭总电源。
## 1、手动安全关机方法的优化 —— 调用 API
前文介绍过,手动关闭上位机系统有四种方式:物理关机按钮,网页关机按钮、KlipperScreen 彩色触摸屏按钮和 12864 等 LCD 屏幕菜单。
其中`使用 Klipper 监听按钮状态` 和 `mini12864 屏幕菜单` 两种方法都需要 shell_cmd 组件,而此组件的缺点也很明显:
* 需要 Klipper Python2 ,默认不支持中文 Gcode 文件
* shell_cmd 命令不支持需要输入用户密码的命令
* shell_cmd 造成系统安全性下降
* 该组件需要自行安装
那么有没有什么法子不安装额外的东西,即可以实现关闭系统吗?我们上面了解到 Moonraker (下文称 mrk) API 的 `machine.shutdown` 方法,而且 `Fluidd 网页`/`KlipperScreen 按钮` 关机的方法就是创建用户组 `mnrkrsudo、klipperscreensudo` ,执行一些系统命令不需要密码,如下所示:
```shell
fly@flygemini:~$ sudo ls /etc/sudoers.d/
020-sudo-for-moonraker021-sudo-for-klipperscreenREADME
fly@flygemini:~$ sudo cat /etc/sudoers.d/020-sudo-for-moonraker
### Elevate moonraker API rights
### Do NOT allow Command Parts only Full Commands
### for example
###
### /sbin/systemctl "reboot", /sbin/apt "update", .....
Defaults!/usr/bin/apt-get env_keep +="DEBIAN_FRONTEND"
Cmnd_Alias REBOOT = /sbin/shutdown -r now, /bin/systemctl "reboot"
Cmnd_Alias SHUTDOWN = /sbin/shutdown now, /sbin/shutdown -h now, /bin/systemctl "poweroff"
Cmnd_Alias APT = /usr/bin/apt-get
Cmnd_Alias SYSTEMCTL = /bin/systemctl
%mnrkrsudo ALL=(ALL) NOPASSWD: REBOOT, SHUTDOWN, APT, SYSTEMCTL
```
### 1.1Klipper 全家桶 API 介绍
我们常见的有 (https://www.klipper3d.org/API_Server.html)、(https://moonraker.readthedocs.io/en/latest/web_api/) ,具体可以查看链接内文档,而其中的 [*machine.shutdown*](https://moonraker.readthedocs.io/en/latest/web_api/#shutdown-the-operating-system)就是属于 mrk api 。由此 mrk client 可以调用 klippy 提供的 API,同时可以被用户调用其 api。那么 klippy 可以调用 mrk api 来实现执行关机命令吗?也是可以的,还记得之前我们从 Klipper 内关闭打印机电源的示例吗,其有一个命令:`action_call_remote_method` ,查看 (https://www.klipper3d.org/Command_Templates.html?h=action#actions),是这么说的:
> - `action_call_remote_method(method_name)`: ***Calls a method registered by a remote client.*** If the method takes parameters they should be provided via keyword arguments, ie: `action_call_remote_method("print_stuff", my_arg="hello_world")`
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313215837.png)
意思就是除了上面两种 API 之外,Moonraker 还可以在 Klippy 那注册一个方法,告诉它(Klippy):我(Mrk)这里有此方法,可以被调用。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313222554.png)
我们以已知方法(method)`set_device_power` 为关键词搜索 mrk 源码,可知关键词为 `register_remote_method` ,再以此搜索即获得支持的方法如下:
* moonraker_test
* **shutdown_machine**
* **reboot_machine**
* process_gcode_response
* process_status_update
* pause_job_queue
* start_job_queue
* set_wled_state
* set_wled
* publish_mqtt_topic
* paneldue_beep
* set_device_power
至此我们找到了想要的两个可以被 Klipper 调用的方法。
> **【更新:2022年3月13日】**
>
> 笔者测试时还没有相关文档,(https://github.com/Arksine/moonraker/commit/65e76aeec8c81481fdd587b046504d63dff52870) 官方更新了 [此部分文档](https://moonraker.readthedocs.io/en/latest/configuration/#machine) ,并补充了注意事项,建议阅读。虽然如此,我们查找答案的方法还是有记录借鉴意义的。
### 1.2 调用 `Method` 实现关机
### 物理关机按钮:
```yaml
# ~/klipper_config/printer.cfg
gcode:
{action_call_remote_method("shutdown_machine")}
# 定义物理按钮 【监听引脚状态】
# 按钮信号连接引脚
pin: host:gpio
# 按下时执行 gcode 宏命令
#press_gcode:
# 松开时执行 gcode 宏命令
release_gcode:
SHUTDOWN
```
测试通过,控制台输入 `SHUTDOWN` 或者被调用即可以实现关闭系统指令。
### 12864 屏幕菜单关机:
```yaml
# printer.cfg
### menu poweroff by 思兼 v2 ###
type: list
enable: {not printer.idle_timeout.state == "Printing"}
name: PowerOff
type: command
name: NO
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
{menu.back()}
type: command
name: YES
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
SHUTDOWN
```
## 2、 传统打完关机方案
我们先说说传统的打完关机功能,适用于 **【上位机独立供电的情况】**,多数朋友借助原来 Marlin 上用的 `打完关机模块`,或者使用 `智能插座`,我们说说各自的优缺点:
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313225817.png)
### 2.1 打完关机模块
#### 优点:
* 可以利用原来的模块不浪费
* 支持断电检测
#### 缺点:
* 接线麻烦
* 价格较高 (79 + 9元)
* 为了安全关闭上位机系统,需要上位机独立供电:
* 如果由上位机 GPIO 引脚控制,支持开、关机操作,上传打印任务后自动开机
* 如果由主板引脚控制,仅支持关机,且要求主板支持从上位机取电,但此时会造成 5v 和 VCC 混合供电,导致潜在的信号干扰
示例如下:
```yaml
# 独立供电打完关机方案,by 思兼
#####################################################################
#方法1,打印机主板 PS_ON 接口
#####################################################################
# 使用主板 PS_ON 引脚,需要上位机通过 USB 接口为主板供电,但此时会出现 5v
# 和 12/24v 同时供电的问题
pin: PS_ON
pwm: False
value: 1
shutdown_value: 0
description: PowerOff
gcode:
M84
SET_PIN PIN=mks_pwc VALUE=0
#####################################################################
#方法2,上位机 GPIO 接口【推荐】
#####################################################################
# 使用上位机 GPIO 接口控制,支持开/关机,尤其适合上位机内置。需要额外修改
# moonraker.cfg 配置文件,可以手动在右上角菜单控制开关机
gcode:
{action_call_remote_method("set_device_power",
device="printer",
state="off")}
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 以下为修改 moonraker.cfg内容,“printer”名称对应。以及不能使用 UART 等引脚
type: gpio
pin: gpio26
off_when_shutdown: True
initial_state: off
#####################################################################
#延时(挤出头降温)自动关机
#####################################################################
# 判断当前为空闲状态,才执行断电操作
initial_duration: 0.
gcode:
{% if printer.idle_timeout.state == "Idle" %}
M81
{% endif %}
# https://www.klipper3d.org/Command_Templates.html?h=update_delayed_gcode#delayed-gcodes
# https://github.com/Klipper3d/klipper/issues/3865 | Firmware Restart 之后,要先home之后才会进入空闲状态
# 空闲状态360s后关闭电机和加热头,60s后关闭电源
gcode:
M84
TURN_OFF_HEATERS
UPDATE_DELAYED_GCODE ID=delayed_printer_off DURATION=60
timeout: 360
```
### 2.2 智能插座
#### 优点:
* 价格相对便宜(30~50元)
* 无需额外接线
#### 缺点:
使用方法有以下几种,各有其不足:
1. 预估打印完成时间定时关机 —— 不准确
2. 使用具有电量检测功能的插座,当打印机处于低耗电时,认为打印完成,实现关机 —— 相比准确,成本提高
3. 使用 Home Assistant 等智能家居系统,Klipper 打印完成后,调用 Moonraker 向 HA 发送关闭智能插座命令 —— 准确,但是需要 HA
其他用法欢迎补充。前两种方法自己从 APP 里设置即可,第三种方法我们下面一起介绍。 厉害厉害 厉害厉害 6666666666666 赞赞赞赞赞 感谢指导 @赤星三春牛! 你这评论太水了 感谢大佬!
页:
[1]