-
-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# G-Code Shell Command Extension | ||
|
||
### Creator of this extension is [Arksine](https://github.com/Arksine). | ||
|
||
This is a brief explanation of how to use the shell command extension for Klipper, which you can install with KIAUH. | ||
|
||
After installing the extension you can execute linux commands or even scripts from within Klipper with custom commands defined in your printer.cfg. | ||
|
||
#### How to configure a shell command: | ||
|
||
```shell | ||
# Runs a linux command or script from within klipper. Note that sudo commands | ||
# that require password authentication are disallowed. All executable scripts | ||
# should include a shebang. | ||
# [gcode_shell_command my_shell_cmd] | ||
#command: | ||
# The linux shell command/script to be executed. This parameter must be | ||
# provided | ||
#timeout: 2. | ||
# The timeout in seconds until the command is forcably terminated. Default | ||
# is 2 seconds. | ||
#verbose: True | ||
# If enabled, the command's output will be forwarded to the terminal. Its | ||
# recommended to set this to false for commands that my run in quick | ||
# succession. Default is True. | ||
``` | ||
|
||
Once you have set up a shell command with the given parameters from above in your printer.cfg you can run the command as follows: | ||
`RUN_SHELL_COMMAND CMD=name` | ||
|
||
Example: | ||
|
||
``` | ||
[gcode_shell_command hello_world] | ||
command: echo hello world | ||
timeout: 2. | ||
verbose: True | ||
``` | ||
|
||
Execute with: | ||
`RUN_SHELL_COMMAND CMD=hello_world` | ||
|
||
### Passing parameters: | ||
|
||
As of commit [f231fa9](https://github.com/dw-0/kiauh/commit/f231fa9c69191f23277b4e3319f6b675bfa0ee42) it is also possible to pass optional parameters to a `gcode_shell_command`. | ||
The following short example shows storing the extruder temperature into a variable, passing that value with a parameter to a `gcode_shell_command`, which then, | ||
once the gcode_macro runs and the gcode_shell_command gets called, executes the `script.sh`. The script then echoes a message to the console (if `verbose: True`) | ||
and writes the value of the parameter into a textfile called `test.txt` located in the home directory. | ||
|
||
Content of the `gcode_shell_command` and the `gcode_macro`: | ||
|
||
``` | ||
[gcode_shell_command print_to_file] | ||
command: sh /home/pi/klipper_config/script.sh | ||
timeout: 30. | ||
verbose: True | ||
[gcode_macro GET_TEMP] | ||
gcode: | ||
{% set temp = printer.extruder.temperature %} | ||
{ action_respond_info("%s" % (temp)) } | ||
RUN_SHELL_COMMAND CMD=print_to_file PARAMS={temp} | ||
``` | ||
|
||
Content of `script.sh`: | ||
|
||
```shell | ||
#!/bin/sh | ||
|
||
echo "temp is: $1" | ||
echo "$1" >> "${HOME}/test.txt" | ||
``` | ||
|
||
## Warning | ||
|
||
This extension may have a high potential for abuse if not used carefully! Also, depending on the command you execute, high system loads may occur and can cause system instabilities. | ||
Use this extension at your own risk and only if you know what you are doing! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Run a shell command via gcode | ||
# | ||
# Copyright (C) 2019 Eric Callahan <[email protected]> | ||
# | ||
# This file may be distributed under the terms of the GNU GPLv3 license. | ||
import os | ||
import shlex | ||
import subprocess | ||
import logging | ||
|
||
|
||
class ShellCommand: | ||
def __init__(self, config): | ||
self.name = config.get_name().split()[-1] | ||
self.printer = config.get_printer() | ||
self.gcode = self.printer.lookup_object("gcode") | ||
cmd = config.get("command") | ||
cmd = os.path.expanduser(cmd) | ||
self.command = shlex.split(cmd) | ||
self.timeout = config.getfloat("timeout", 2.0, above=0.0) | ||
self.verbose = config.getboolean("verbose", True) | ||
self.proc_fd = None | ||
self.partial_output = "" | ||
self.gcode.register_mux_command( | ||
"RUN_SHELL_COMMAND", | ||
"CMD", | ||
self.name, | ||
self.cmd_RUN_SHELL_COMMAND, | ||
desc=self.cmd_RUN_SHELL_COMMAND_help, | ||
) | ||
|
||
def _process_output(self, eventime): | ||
if self.proc_fd is None: | ||
return | ||
try: | ||
data = os.read(self.proc_fd, 4096) | ||
except Exception: | ||
pass | ||
data = self.partial_output + data.decode() | ||
if "\n" not in data: | ||
self.partial_output = data | ||
return | ||
elif data[-1] != "\n": | ||
split = data.rfind("\n") + 1 | ||
self.partial_output = data[split:] | ||
data = data[:split] | ||
else: | ||
self.partial_output = "" | ||
self.gcode.respond_info(data) | ||
|
||
cmd_RUN_SHELL_COMMAND_help = "Run a linux shell command" | ||
|
||
def cmd_RUN_SHELL_COMMAND(self, params): | ||
gcode_params = params.get("PARAMS", "") | ||
gcode_params = shlex.split(gcode_params) | ||
reactor = self.printer.get_reactor() | ||
try: | ||
proc = subprocess.Popen( | ||
self.command + gcode_params, | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.STDOUT, | ||
) | ||
except Exception: | ||
logging.exception( | ||
"shell_command: Command {%s} failed" % (self.name) | ||
) | ||
raise self.gcode.error("Error running command {%s}" % (self.name)) | ||
if self.verbose: | ||
self.proc_fd = proc.stdout.fileno() | ||
self.gcode.respond_info("Running Command {%s}...:" % (self.name)) | ||
hdl = reactor.register_fd(self.proc_fd, self._process_output) | ||
eventtime = reactor.monotonic() | ||
endtime = eventtime + self.timeout | ||
complete = False | ||
while eventtime < endtime: | ||
eventtime = reactor.pause(eventtime + 0.05) | ||
if proc.poll() is not None: | ||
complete = True | ||
break | ||
if not complete: | ||
proc.terminate() | ||
if self.verbose: | ||
if self.partial_output: | ||
self.gcode.respond_info(self.partial_output) | ||
self.partial_output = "" | ||
if complete: | ||
msg = "Command {%s} finished\n" % (self.name) | ||
else: | ||
msg = "Command {%s} timed out" % (self.name) | ||
self.gcode.respond_info(msg) | ||
reactor.unregister_fd(hdl) | ||
self.proc_fd = None | ||
|
||
|
||
def load_config_prefix(config): | ||
return ShellCommand(config) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Test case for gcode_shell_command | ||
[mcu] | ||
serial: /dev/ttyACM0 | ||
|
||
[printer] | ||
kinematics: none | ||
max_velocity: 300 | ||
max_accel: 3000 | ||
|
||
[gcode_shell_command HELLO_WORLD] | ||
command: echo hello world | ||
timeout: 2. | ||
verbose: True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Test case for gcode_shell_command | ||
CONFIG gcode_shell_command.cfg | ||
DICTIONARY atmega2560.dict | ||
|
||
HELLO_WORLD |