klipper/klippy/extras/gcode_shell_command.py
Microlay 5e389ec020 feat: Add obstacle detection flag and expand Z limits for ZMAX_HOME
- Create /tmp/homing_obstacle_flag when timeout occurs (no trigger)
- Expand Z limits temporarily to allow full travel during homing
- Add gcode_shell_command.py for shell command execution
- Add obstacle_detector.py Klipper module

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:53:26 +01:00

66 lines
2.1 KiB
Python

# Shell command execution support for Klipper
#
# Copyright (C) 2024 Microlay
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import subprocess
import logging
import os
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')
self.command = config.get('command')
self.timeout = config.getfloat('timeout', 2.0)
self.verbose = config.getboolean('verbose', True)
# Register the gcode command
self.gcode.register_mux_command(
"RUN_SHELL_COMMAND", "CMD", self.name,
self.cmd_RUN_SHELL_COMMAND,
desc="Run a predefined shell command"
)
def cmd_RUN_SHELL_COMMAND(self, gcmd):
# Get optional parameters
params = gcmd.get('PARAMS', '')
# Build the full command
if params:
full_command = f"{self.command} {params}"
else:
full_command = self.command
if self.verbose:
self.gcode.respond_info(f"Running: {full_command}")
try:
# Execute the command
result = subprocess.run(
full_command,
shell=True,
capture_output=True,
text=True,
timeout=self.timeout
)
if self.verbose:
if result.stdout:
self.gcode.respond_info(f"Output: {result.stdout.strip()}")
if result.stderr:
self.gcode.respond_info(f"Stderr: {result.stderr.strip()}")
if result.returncode != 0:
self.gcode.respond_info(f"Return code: {result.returncode}")
except subprocess.TimeoutExpired:
raise self.gcode.error(f"Shell command timed out after {self.timeout}s")
except Exception as e:
raise self.gcode.error(f"Shell command error: {str(e)}")
def load_config_prefix(config):
return ShellCommand(config)