Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STEAPP-800, STEAPP-841, STEAPP-842: added the wizard modules. #224

Merged
merged 13 commits into from
Dec 29, 2023
Merged
2 changes: 2 additions & 0 deletions HTE530-5-4-22.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ path: /home/ste/uploads
[include stereotech_config/common/variables.cfg]
[include stereotech_config/common/diagnostics.cfg]

[include stereotech_config/wizards/wizards.cfg]

[gcode_macro CONSTANTS]
description: Holds printer constants
variable_probe_a_horizontal: 159, 246.5, 40
Expand Down
11 changes: 11 additions & 0 deletions docs/stereotech/error_list_guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ config:
2047: auto_wcs: improperly formatted entry for point %s
2048: The parameter value is out of range, param=%smm max=%smm, min=0.0mm. Check params.
2049: Large difference between two values (x1-x2 or y1-y2), maximum difference=%smm. Check the parameters.
2050: No module named %s, error: %s
2051: Unknown wizard variable '%s'
2052: Unable to parse '%s' as a literal: %s
2053: Unknown step: '%s'
2054: Macro %s called recursively
2055: Failure set value:%s to variable:%s in the slider %s
2056: The selected item %s not in the items %s
2057: error setting the value:%s to move the axis, the value is out of range
2058: error moved the axis:%s, the axis not availability
2059: Macro %s called recursively
2060: The button '%s' does not exist

перефирия(mcu):
301: Timeout on wait for '%s' response
Expand Down
10 changes: 10 additions & 0 deletions klippy/extras/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import importlib


def load_config_prefix(config):
mod_name = 'extras.wizard.' + config.get_name().split()[0]
try:
mod = importlib.import_module(mod_name)
return mod.load_config_prefix(config)
except Exception as e:
raise Exception('2050: No module named %s, error: %s' % (mod_name, e))
100 changes: 100 additions & 0 deletions klippy/extras/wizard/wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import ast
import json


class Wizard:
def __init__(self, config):
if len(config.get_name().split()) > 2:
raise config.error(
"Name of section '%s' contains illegal whitespace"
% (config.get_name()))
self.name = config.get_name().split()[1]
self.enabled = False
self.error = ''
self.variables = {}
self._variables_bk = {}
prefix = 'variable_'
for option in config.get_prefix_options(prefix):
try:
literal = ast.literal_eval(config.get(option))
json.dumps(literal, separators=(',', ':'))
self.variables[option[len(prefix):]] = literal
self._variables_bk[option[len(prefix):]] = literal
except (SyntaxError, TypeError, ValueError) as e:
raise config.error(
"Option '%s' in section '%s' is not a valid literal: %s" % (
option, config.get_name(), e))
# get options from config
self.image = config.get('image', 'image_path')
self.type = config.getlists('type', [])
self.steps = config.getlists('steps', [])
self.current_step = self.steps[0]
# load objects
self.printer = printer = config.get_printer()
self.gcode = printer.lookup_object('gcode')
# register commands
self.gcode.register_mux_command("SET_WIZARD_VARIABLE", "WIZARD",
self.name, self.cmd_SET_WIZARD_VARIABLE,
desc=self.cmd_SET_WIZARD_VARIABLE_help)
self.gcode.register_mux_command("SET_WIZARD_ENABLE", "WIZARD",
self.name, self.cmd_SET_WIZARD_ENABLE,
desc=self.cmd_SET_WIZARD_ENABLE_help)
self.gcode.register_mux_command("SET_WIZARD_STEP", "WIZARD",
self.name, self.cmd_SET_WIZARD_STEP,
desc=self.cmd_SET_WIZARD_STEP_help)
self.gcode.register_mux_command("RESET_WIZARD", "WIZARD",
self.name, self.cmd_RESET_WIZARD,
desc=self.cmd_RESET_WIZARD_help)

def get_status(self, eventtime=None):
return {'current_step': self.current_step,
'enabled': self.enabled,
'error': self.error,
'variables': self.variables,
'name': self.name,
'steps': self.steps,
'type': self.type}

cmd_SET_WIZARD_VARIABLE_help = "Set the value of a wizard variable to wizard"

def cmd_SET_WIZARD_VARIABLE(self, gcmd):
variable = gcmd.get('VARIABLE')
value = gcmd.get('VALUE')
if variable not in self.variables:
raise gcmd.error(
"2051: Unknown wizard variable '%s'" % (variable,))
try:
literal = ast.literal_eval(value)
json.dumps(literal, separators=(',', ':'))
except (SyntaxError, TypeError, ValueError) as e:
raise gcmd.error("2052: Unable to parse '%s' as a literal: %s" %
(value, e))
v = dict(self.variables)
v[variable] = literal
self.variables = v

cmd_SET_WIZARD_ENABLE_help = "Set the enable to WIZARD"

def cmd_SET_WIZARD_ENABLE(self, gcmd):
self.enabled = True if gcmd.get_int('ENABLE', self.enabled) else False
self.error = gcmd.get('ERROR', self.error)

cmd_SET_WIZARD_STEP_help = "Set the step to WIZARD"

def cmd_SET_WIZARD_STEP(self, gcmd):
step = gcmd.get('STEP')
if step not in self.steps:
raise gcmd.error("2053: Unknown step: '%s'" % step)
self.current_step = step

cmd_RESET_WIZARD_help = "Reset state the wizard"

def cmd_RESET_WIZARD(self, gcmd):
self.error = ''
self.enabled = False
self.current_step = self.steps[0]
self.variables = dict(self._variables_bk)


def load_config_prefix(config):
return Wizard(config)
67 changes: 67 additions & 0 deletions klippy/extras/wizard/wizard_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
class WizardStep:
def __init__(self, config):
if len(config.get_name().split()) > 2:
raise config.error(
"Name of section '%s' contains illegal whitespace"
% (config.get_name()))
section_name = config.get_name().split()
self.name = section_name[1].upper()
self.in_script = False
# load objects
self.printer = printer = config.get_printer()
self.gcode_macro = printer.load_object(config, 'gcode_macro')
self.gcode = printer.lookup_object('gcode')
# get options from config
self.cmd_desc = config.get("description", "G-Code wizard")
self.image = config.get('image', 'image_path')
self.landscape = config.getboolean('landscape', False)
self.description = config.get('description', '')
self.warning = config.get('warning', '')
self.info = config.get('info', '')
self.countdown = config.getint('countdown', 0)
# create template
self.template_action = self.gcode_macro.load_template(
config, 'action_gcode')
self.template_cancel = self.gcode_macro.load_template(
config, 'cancel_gcode')
# register gcode commands
self.gcode.register_mux_command("EXECUTE_WIZARD_STEP", 'STEP',
self.name, self.cmd_EXECUTE_WIZARD_STEP,
desc=self.cmd_EXECUTE_WIZARD_STEP_help)
self.gcode.register_mux_command("CANCEL_WIZARD_STEP", 'STEP',
self.name, self.cmd_CANCEL_WIZARD_STEP,
desc=self.cmd_CANCEL_WIZARD_STEP_help)

cmd_EXECUTE_WIZARD_STEP_help = "Run gcode in the 'action_gcode' option"

def cmd_EXECUTE_WIZARD_STEP(self, gcmd):
self.cmd(gcmd=gcmd, gcode='action_gcode')

cmd_CANCEL_WIZARD_STEP_help = "Run gcode in the 'cancel_gcode' option"

def cmd_CANCEL_WIZARD_STEP(self, gcmd):
self.cmd(gcmd=gcmd, gcode='cancel_gcode')

def cmd(self, gcmd, gcode):
if self.in_script:
raise gcmd.error(
"2054: Macro %s called recursively" % (self.name,))
wizard_name = gcmd.get('WIZARD').upper()
wizard_obj = self.printer.lookup_object('wizard %s' % wizard_name)
kwparams = self.template_action.create_template_context()
kwparams['wizard'] = wizard_obj.get_status()
kwparams['wizard'].update({'wizard_step_name': self.name})
kwparams['params'] = gcmd.get_command_parameters()
kwparams['rawparams'] = gcmd.get_raw_command_parameters()
self.in_script = True
try:
if gcode == 'action_gcode':
self.template_action.run_gcode_from_command(kwparams)
elif gcode == 'cancel_gcode':
self.template_cancel.run_gcode_from_command(kwparams)
finally:
self.in_script = False


def load_config_prefix(config):
return WizardStep(config)
46 changes: 46 additions & 0 deletions klippy/extras/wizard/wizard_step_button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from wizard_step import WizardStep


class WizardStepButton(WizardStep):
def __init__(self, config):
WizardStep.__init__(self, config)
# create template for buttons
self.templates = {}
options_name = config.get_prefix_options('button_')
for option in options_name:
template_button = self.gcode_macro.load_template(
config, option)
button_name = '_'.join(option.split('_')[1:-1])
self.templates.update({button_name: template_button})
# register commands
self.gcode.register_mux_command("WIZARD_STEP_BUTTON", 'STEP',
self.name, self.cmd_WIZARD_STEP_BUTTON,
desc=self.cmd_WIZARD_STEP_BUTTON_help)

cmd_WIZARD_STEP_BUTTON_help = "Run gcode in the 'button_%s_gcode' section"

def cmd_WIZARD_STEP_BUTTON(self, gcmd):
if self.in_script:
raise gcmd.error(
"2054: Macro %s called recursively" % (self.name,))
wizard_name = gcmd.get('WIZARD').upper()
wizard_obj = self.printer.lookup_object('wizard %s' % wizard_name)
button = gcmd.get('BUTTON', '').lower()
template_button = self.templates.get(button, None)
if template_button is None:
raise gcmd.error(
"2060: The button '%s' does not exist" % (button,))
kwparams = template_button.create_template_context()
kwparams['wizard'] = wizard_obj.get_status()
kwparams['wizard'].update({'wizard_step_name': self.name})
kwparams['params'] = gcmd.get_command_parameters()
kwparams['rawparams'] = gcmd.get_raw_command_parameters()
self.in_script = True
try:
template_button.run_gcode_from_command(kwparams)
finally:
self.in_script = False


def load_config_prefix(config):
return WizardStepButton(config)
64 changes: 64 additions & 0 deletions klippy/extras/wizard/wizard_step_jog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from wizard_step import WizardStep


class WizardStepJog(WizardStep):
def __init__(self, config):
WizardStep.__init__(self, config)
# get options
self.axes = config.getlists('axes', ['x', 'y', 'z'])
self.steps = config.getfloatlist('steps')
self.default_step = config.getfloat('default_step', 10)
# create template
self.template_jog = self.gcode_macro.load_template(config, 'jog_gcode')
# register gcode commands
self.gcode.register_mux_command("WIZARD_STEP_JOG", 'STEP',
self.name, self.cmd_WIZARD_STEP_JOG,
desc=self.cmd_WIZARD_STEP_JOG_help)
self.gcode.register_mux_command("WIZARD_STEP_SET_STEP", 'STEP',
self.name, self.cmd_WIZARD_STEP_SET_STEP,
desc=self.cmd_WIZARD_STEP_SET_STEP_help)

cmd_WIZARD_STEP_SET_STEP_help = "Set step for moving the axis"

def cmd_WIZARD_STEP_SET_STEP(self, gcmd):
value = gcmd.get_float('VALUE')
if value not in self.steps:
raise gcmd.error(
"2057: error setting the value:%s to move the axis, the value is out of range" % (value,))
self.default_step = value

cmd_WIZARD_STEP_JOG_help = "Perform axis movement"

def cmd_WIZARD_STEP_JOG(self, gcmd):
axis = gcmd.get('AXIS').lower()
# get direction move, 1-positive, 0-negative moving
direction = gcmd.get('DIRECTION', 1)
if axis not in self.axes:
raise gcmd.error(
"2058: error moved the axis:%s, the axis not availability" % (axis,))
if self.in_script:
raise gcmd.error(
"2059: Macro %s called recursively" % (self.name,))
# update status to the wizard
wizard_name = gcmd.get('WIZARD').upper()
wizard_obj = self.printer.lookup_object('wizard %s' % wizard_name)
kwparams = self.template_action.create_template_context()
kwparams['wizard'] = wizard_obj.get_status()
kwparams['wizard'].update({'wizard_step_name': self.name})
kwparams['params'] = gcmd.get_command_parameters()
kwparams['rawparams'] = gcmd.get_raw_command_parameters()
kwparams['axis'] = axis
kwparams['step'] = self.default_step
kwparams['direction'] = direction
self.in_script = True
try:
self.template_jog.run_gcode_from_command(kwparams)
finally:
self.in_script = False

def get_status(self, eventtime):
return {'step': self.default_step}


def load_config_prefix(config):
return WizardStepJog(config)
48 changes: 48 additions & 0 deletions klippy/extras/wizard/wizard_step_selector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from wizard_step import WizardStep


class WizardStepSelector(WizardStep):
def __init__(self, config):
WizardStep.__init__(self, config)
self.selected = ''
# get options
self.items = config.getlists('items', [])
# create template
self.template = self.gcode_macro.load_template(config, 'select_gcode')
# register commands
self.gcode.register_mux_command("WIZARD_STEP_SELECT", 'STEP',
self.name, self.cmd_WIZARD_STEP_SELECT,
desc=self.cmd_WIZARD_STEP_SELECT_help)

cmd_WIZARD_STEP_SELECT_help = "Run gcode in the 'select_gcode' section"

def cmd_WIZARD_STEP_SELECT(self, gcmd):
if self.in_script:
raise gcmd.error(
"2054: Macro %s called recursively" % (self.name,))
selected = gcmd.get('ITEM')
if selected not in self.items:
raise gcmd.error(
"2056: The selected item %s not in the items %s" % (selected, self.items))
self.selected = selected
wizard_name = gcmd.get('WIZARD').upper()
wizard_obj = self.printer.lookup_object('wizard %s' % wizard_name)
kwparams = self.template_action.create_template_context()
kwparams['wizard'] = wizard_obj.get_status()
kwparams['wizard'].update({'wizard_step_name': self.name})
kwparams['params'] = gcmd.get_command_parameters()
kwparams['rawparams'] = gcmd.get_raw_command_parameters()
kwparams['selected'] = self.selected
self.in_script = True
try:
self.template.run_gcode_from_command(kwparams)
finally:
self.in_script = False

def get_status(self, eventtime):
return {'selected': self.selected
}


def load_config_prefix(config):
return WizardStepSelector(config)
Loading
Loading