aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/extras/led.py
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2022-03-23 18:06:09 -0400
committerKevin O'Connor <kevin@koconnor.net>2022-03-31 13:08:12 -0400
commit1ab3ac39e410441190690d43f6d2ef339f23a155 (patch)
treef1be1eab0194a7f6539a7cb16926fbf687750997 /klippy/extras/led.py
parenta6ab56c0a6c7c532f1f1e2b5b5b4060cea7001a5 (diff)
downloadkutter-1ab3ac39e410441190690d43f6d2ef339f23a155.tar.gz
kutter-1ab3ac39e410441190690d43f6d2ef339f23a155.tar.xz
kutter-1ab3ac39e410441190690d43f6d2ef339f23a155.zip
led: Support automated LED updates based on display_template results
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/extras/led.py')
-rw-r--r--klippy/extras/led.py95
1 files changed, 94 insertions, 1 deletions
diff --git a/klippy/extras/led.py b/klippy/extras/led.py
index bfc85956..e77450b4 100644
--- a/klippy/extras/led.py
+++ b/klippy/extras/led.py
@@ -4,6 +4,10 @@
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
+from .display import display
+
+# Time between each led template update
+RENDER_TIME = 0.500
# Helper code for common LED initialization and control
class LEDHelper:
@@ -66,8 +70,97 @@ class LEDHelper:
class PrinterLED:
def __init__(self, config):
self.printer = config.get_printer()
+ self.led_helpers = {}
+ self.active_templates = {}
+ self.render_timer = None
+ # Load templates
+ dtemplates = display.lookup_display_templates(config)
+ self.templates = dtemplates.get_display_templates()
+ gcode_macro = self.printer.lookup_object("gcode_macro")
+ self.create_template_context = gcode_macro.create_template_context
+ # Register handlers
+ gcode = self.printer.lookup_object('gcode')
+ gcode.register_command("SET_LED_TEMPLATE", self.cmd_SET_LED_TEMPLATE,
+ desc=self.cmd_SET_LED_TEMPLATE_help)
def setup_helper(self, config, update_func, led_count=1, has_white=False):
- return LEDHelper(config, update_func, led_count, has_white)
+ led_helper = LEDHelper(config, update_func, led_count, has_white)
+ name = config.get_name().split()[-1]
+ self.led_helpers[name] = led_helper
+ return led_helper
+ def _activate_timer(self):
+ if self.render_timer is not None or not self.active_templates:
+ return
+ reactor = self.printer.get_reactor()
+ self.render_timer = reactor.register_timer(self._render, reactor.NOW)
+ def _activate_template(self, led_helper, index, template):
+ key = (led_helper, index)
+ if template is not None:
+ self.active_templates[key] = template
+ return
+ if key in self.active_templates:
+ del self.active_templates[key]
+ def _render(self, eventtime):
+ if not self.active_templates:
+ # Nothing to do - unregister timer
+ reactor = self.printer.get_reactor()
+ reactor.register_timer(self.render_timer)
+ self.render_timer = None
+ return reactor.NEVER
+ # Setup gcode_macro template context
+ context = self.create_template_context(eventtime)
+ def render(name, **kwargs):
+ return self.templates[name].render(context, **kwargs)
+ context['render'] = render
+ # Render all templates
+ need_transmit = {}
+ rendered = {}
+ for (led_helper, index), template in self.active_templates.items():
+ color = rendered.get(template)
+ if color is None:
+ try:
+ text = template.render(context)
+ parts = [max(0., min(1., float(f)))
+ for f in text.split(',', 4)]
+ except Exception as e:
+ logging.exception("led template render error")
+ parts = []
+ if len(parts) < 4:
+ parts += [0.] * (4 - len(parts))
+ rendered[template] = color = tuple(parts)
+ prev_color = led_helper.led_state[index-1]
+ if color != prev_color:
+ if led_helper not in need_transmit:
+ need_transmit[led_helper] = 1
+ led_helper.led_state = list(led_helper.led_state)
+ led_helper.led_state[index-1] = color
+ context.clear() # Remove circular references for better gc
+ # Transmit pending changes
+ for led_helper in need_transmit.keys():
+ try:
+ led_helper.update_func(led_helper.led_state, None)
+ except Exception as e:
+ logging.exception("led template transmit error")
+ return eventtime + RENDER_TIME
+ cmd_SET_LED_TEMPLATE_help = "Assign a display_template to an LED"
+ def cmd_SET_LED_TEMPLATE(self, gcmd):
+ led_name = gcmd.get("LED")
+ led_helper = self.led_helpers.get(led_name)
+ if led_helper is None:
+ raise gcmd.error("Unknown LED '%s'" % (led_name,))
+ led_count = led_helper.led_count
+ index = gcmd.get_int("INDEX", None, minval=1, maxval=led_count)
+ template = None
+ 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,))
+ if index is not None:
+ self._activate_template(led_helper, index, template)
+ else:
+ for i in range(led_count):
+ self._activate_template(led_helper, i+1, template)
+ self._activate_timer()
PIN_MIN_TIME = 0.100
MAX_SCHEDULE_TIME = 5.0