From e6bfc4c9aaf60a3dd1784575fabceb11136a2dad Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Fri, 25 Mar 2022 11:46:45 -0400 Subject: [PATCH] led: Support setting display_template parameters via SET_LED_TEMPLATE Signed-off-by: Kevin O'Connor --- docs/G-Codes.md | 16 +++++++++------- klippy/extras/display/display.py | 2 ++ klippy/extras/led.py | 33 +++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/docs/G-Codes.md b/docs/G-Codes.md index bef64dc4..80a99d3f 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -716,7 +716,7 @@ idle timeout. #### SET_LED_TEMPLATE `SET_LED_TEMPLATE LED= TEMPLATE= -[INDEX=]`: Assign a +[=] [INDEX=]`: Assign a [display_template](Config_Reference.md#display_template) to a given [LED](Config_Reference.md#leds). For example, if one defined a `[display_template my_led_template]` config section then one could @@ -724,12 +724,14 @@ assign `TEMPLATE=my_led_template` here. The display_template should produce a comma separated string containing four floating point numbers corresponding to red, green, blue, and white color settings. The template will be continuously evaluated and the LED will be -automatically set to the resulting colors. If INDEX is not specified -then all chips in the LED's daisy-chain will be set to the template, -otherwise only the chip with the given index will be updated. If -TEMPLATE is an empty string then this command will clear any previous -template assigned to the LED (one can then use `SET_LED` commands to -manage the LED's color settings). +automatically set to the resulting colors. One may set +display_template parameters to use during template evaluation +(parameters will be parsed as Python literals). If INDEX is not +specified then all chips in the LED's daisy-chain will be set to the +template, otherwise only the chip with the given index will be +updated. If TEMPLATE is an empty string then this command will clear +any previous template assigned to the LED (one can then use `SET_LED` +commands to manage the LED's color settings). ### [output_pin] diff --git a/klippy/extras/display/display.py b/klippy/extras/display/display.py index 7ad1243e..2ce352de 100644 --- a/klippy/extras/display/display.py +++ b/klippy/extras/display/display.py @@ -39,6 +39,8 @@ class DisplayTemplate: option, config.get_name())) gcode_macro = self.printer.load_object(config, 'gcode_macro') self.template = gcode_macro.load_template(config, 'text') + def get_params(self): + return self.params def render(self, context, **kwargs): params = dict(self.params) params.update(**kwargs) diff --git a/klippy/extras/led.py b/klippy/extras/led.py index e77450b4..5830d77e 100644 --- a/klippy/extras/led.py +++ b/klippy/extras/led.py @@ -3,7 +3,7 @@ # Copyright (C) 2019-2022 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. -import logging +import logging, ast from .display import display # Time between each led template update @@ -92,10 +92,11 @@ class PrinterLED: return reactor = self.printer.get_reactor() self.render_timer = reactor.register_timer(self._render, reactor.NOW) - def _activate_template(self, led_helper, index, template): + def _activate_template(self, led_helper, index, template, lparams): key = (led_helper, index) if template is not None: - self.active_templates[key] = template + uid = (template,) + tuple(sorted(lparams.items())) + self.active_templates[key] = (uid, template, lparams) return if key in self.active_templates: del self.active_templates[key] @@ -114,11 +115,12 @@ class PrinterLED: # Render all templates need_transmit = {} rendered = {} - for (led_helper, index), template in self.active_templates.items(): - color = rendered.get(template) + template_info = self.active_templates.items() + for (led_helper, index), (uid, template, lparams) in template_info: + color = rendered.get(uid) if color is None: try: - text = template.render(context) + text = template.render(context, **lparams) parts = [max(0., min(1., float(f))) for f in text.split(',', 4)] except Exception as e: @@ -126,7 +128,7 @@ class PrinterLED: parts = [] if len(parts) < 4: parts += [0.] * (4 - len(parts)) - rendered[template] = color = tuple(parts) + rendered[uid] = color = tuple(parts) prev_color = led_helper.led_state[index-1] if color != prev_color: if led_helper not in need_transmit: @@ -150,16 +152,29 @@ class PrinterLED: led_count = led_helper.led_count index = gcmd.get_int("INDEX", None, minval=1, maxval=led_count) template = None + lparams = {} tpl_name = gcmd.get("TEMPLATE") if tpl_name: template = self.templates.get(tpl_name) if template is None: raise gcmd.error("Unknown display_template '%s'" % (tpl_name,)) + tparams = template.get_params() + for p, v in gcmd.get_command_parameters().items(): + if not p.startswith("PARAM_"): + continue + p = p.lower() + if p not in tparams: + raise gcmd.error("Invalid display_template parameter: %s" + % (p,)) + try: + lparams[p] = ast.literal_eval(v) + except ValueError as e: + raise gcmd.error("Unable to parse '%s' as a literal" % (v,)) if index is not None: - self._activate_template(led_helper, index, template) + self._activate_template(led_helper, index, template, lparams) else: for i in range(led_count): - self._activate_template(led_helper, i+1, template) + self._activate_template(led_helper, i+1, template, lparams) self._activate_timer() PIN_MIN_TIME = 0.100