pATAq 发表于 2022-3-14 01:45:43

跟着思兼学习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 里设置即可,第三种方法我们下面一起介绍。

QQQQQQQ 发表于 2022-3-14 19:05:59

厉害厉害

赤星三春牛! 发表于 2022-3-17 23:22:11

厉害厉害

赤星三春牛! 发表于 2022-3-17 23:23:29

6666666666666

赤星三春牛! 发表于 2022-3-17 23:24:42

赞赞赞赞赞

狭维失 发表于 2022-10-14 14:36:22

感谢指导

糖醋花生 发表于 2022-12-7 10:17:03

@赤星三春牛! 你这评论太水了

简醉猫 发表于 2023-4-18 19:12:40

感谢大佬!
页: [1]
查看完整版本: 跟着思兼学习Klipper(12) 调用“Method”优雅关机重启