From 740c0ae6369c3bc7213abe84eac2f65782ab523f Mon Sep 17 00:00:00 2001 From: Arksine Date: Sat, 15 Feb 2020 15:03:28 -0500 Subject: [PATCH] filament_switch_sensor: Replace BaseSensor with RunoutHelper Rather than inherit from the BaseSensor, filament sensor implementatons may instantiate the RunoutHelper and update the filament state via its note_filament_present method. Signed-off-by: Eric Callahan --- klippy/extras/filament_switch_sensor.py | 126 ++++++++++++------------ 1 file changed, 61 insertions(+), 65 deletions(-) diff --git a/klippy/extras/filament_switch_sensor.py b/klippy/extras/filament_switch_sensor.py index 257980a8..aef1259e 100644 --- a/klippy/extras/filament_switch_sensor.py +++ b/klippy/extras/filament_switch_sensor.py @@ -5,10 +5,11 @@ # This file may be distributed under the terms of the GNU GPLv3 license. import logging -class BaseSensor(object): +class RunoutHelper: def __init__(self, config): - self.name = config.get_name().split()[1] + self.name = config.get_name().split()[-1] self.printer = config.get_printer() + self.reactor = self.printer.get_reactor() self.gcode = self.printer.lookup_object('gcode') self.runout_pause = config.getboolean('pause_on_runout', True) if self.runout_pause: @@ -22,10 +23,16 @@ class BaseSensor(object): self.insert_gcode = gcode_macro.load_template( config, 'insert_gcode') self.pause_delay = config.getfloat('pause_delay', .5, above=.0) + self.event_delay = config.getfloat('event_delay', 3., above=0.) + self.start_time = self.reactor.NEVER + self.last_event_time = 0. + self.filament_present = False self.runout_enabled = False self.insert_enabled = self.insert_gcode is not None + self.sensor_enabled = True self.event_running = False self.print_status = "idle" + self.printer.register_event_handler("klippy:ready", self._handle_ready) self.printer.register_event_handler( "idle_timeout:idle", (lambda e, s=self, st="idle": s._update_print_status(e, st))) @@ -35,6 +42,16 @@ class BaseSensor(object): self.printer.register_event_handler( "idle_timeout:printing", (lambda e, s=self, st="printing": s._update_print_status(e, st))) + self.gcode.register_mux_command( + "QUERY_FILAMENT_SENSOR", "SENSOR", self.name, + self.cmd_QUERY_FILAMENT_SENSOR, + desc=self.cmd_QUERY_FILAMENT_SENSOR_help) + self.gcode.register_mux_command( + "SET_FILAMENT_SENSOR", "SENSOR", self.name, + self.cmd_SET_FILAMENT_SENSOR, + desc=self.cmd_SET_FILAMENT_SENSOR_help) + def _handle_ready(self): + self.start_time = self.reactor.monotonic() + 2. def _update_print_status(self, eventtime, status): if status == "printing": runout_en = self.runout_gcode is not None @@ -43,9 +60,6 @@ class BaseSensor(object): insert_en = self.insert_gcode is not None self.set_enable(False, insert_en) def _runout_event_handler(self, eventtime): - if self.event_running: - return - self.event_running = True # Pausing from inside an event requires that the pause portion # of pause_resume execute immediately. pause_prefix = "" @@ -55,13 +69,8 @@ class BaseSensor(object): pause_prefix = "PAUSE\n" self.printer.get_reactor().pause(eventtime + self.pause_delay) self._exec_gcode(pause_prefix, self.runout_gcode) - self.event_running = False def _insert_event_handler(self, eventtime): - if self.event_running: - return - self.event_running = True self._exec_gcode("", self.insert_gcode) - self.event_running = False def _exec_gcode(self, prefix, template): try: self.gcode.run_script(prefix + template.render() + "\nM400") @@ -73,67 +82,54 @@ class BaseSensor(object): insert = False self.runout_enabled = runout self.insert_enabled = insert + def note_filament_present(self, state): + eventtime = self.reactor.monotonic() + if (eventtime < self.start_time or state == self.filament_present + or (eventtime - self.last_event_time) < self.event_delay + or not self.sensor_enabled or self.event_running): + # do not process during the initialization time, duplicates, + # during the event delay time, while an event is running, or + # when the sensor is disabled + self.filament_present = state + return + self.filament_present = state + self.event_running = True + if state: + if self.insert_enabled: + # insert detected + self.last_event_time = eventtime + logging.info( + "Filament Sensor %s: insert event detected, Time %.2f" % + (self.name, eventtime)) + self._insert_event_handler(eventtime) + elif self.runout_enabled: + # runout detected + self.last_event_time = eventtime + logging.info( + "Filament Sensor %s: runout event detected, Time %.2f" % + (self.name, eventtime)) + self._runout_event_handler(eventtime) + self.event_running = False cmd_QUERY_FILAMENT_SENSOR_help = "Query the status of the Filament Sensor" def cmd_QUERY_FILAMENT_SENSOR(self, params): - raise NotImplementedError( - "Sensor must implement cmd_QUERY_FILAMENT_SENSOR") - cmd_SET_FILAMENT_SENSOR_help = "Sets the filament sensor on/off" - def cmd_SET_FILAMENT_SENSOR(self, params): - raise NotImplementedError( - "Sensor must implement cmd_SET_FILAMENT_SENSOR") - -class SwitchSensor(BaseSensor): - def __init__(self, config): - super(SwitchSensor, self).__init__(config) - self.reactor = self.printer.get_reactor() - self.buttons = self.printer.try_load_module(config, 'buttons') - switch_pin = config.get('switch_pin') - self.buttons.register_buttons([switch_pin], self._button_handler) - self.event_delay = config.getfloat('event_delay', 3., above=0.) - self.start_time = self.reactor.NEVER - self.sensor_enabled = True - self.last_button_state = False - self.last_cb_event_time = 0. - self.gcode.register_mux_command( - "QUERY_FILAMENT_SENSOR", "SENSOR", self.name, - self.cmd_QUERY_FILAMENT_SENSOR, - desc=self.cmd_QUERY_FILAMENT_SENSOR_help) - self.gcode.register_mux_command( - "SET_FILAMENT_SENSOR", "SENSOR", self.name, - self.cmd_SET_FILAMENT_SENSOR, - desc=self.cmd_SET_FILAMENT_SENSOR_help) - self.printer.register_event_handler("klippy:ready", self._handle_ready) - def _handle_ready(self): - self.start_time = self.reactor.monotonic() + 2. - def _button_handler(self, eventtime, state): - if eventtime < self.start_time or state == self.last_button_state: - self.last_button_state = state - return - if state: - # button pushed, check if insert callback should happen - if (self.insert_enabled and self.sensor_enabled and - (eventtime - self.last_cb_event_time) > self.event_delay): - self.last_cb_event_time = eventtime - logging.info( - "switch_sensor: insert event detected, Time %.2f", - eventtime) - self.reactor.register_callback(self._insert_event_handler) - elif (self.runout_enabled and self.sensor_enabled and - (eventtime - self.last_cb_event_time) > self.event_delay): - # Filament runout detected - self.last_cb_event_time = eventtime - logging.info( - "switch_sensor: runout event detected, Time %.2f", eventtime) - self.reactor.register_callback(self._runout_event_handler) - self.last_button_state = state - def cmd_QUERY_FILAMENT_SENSOR(self, params): - if self.last_button_state: - msg = "Switch Sensor: filament detected" + if self.filament_present: + msg = "Filament Sensor %s: filament detected" % (self.name) else: - msg = "Switch Sensor: filament not detected" + msg = "Filament Sensor %s: filament not detected" % (self.name) self.gcode.respond_info(msg) + cmd_SET_FILAMENT_SENSOR_help = "Sets the filament sensor on/off" def cmd_SET_FILAMENT_SENSOR(self, params): self.sensor_enabled = self.gcode.get_int("ENABLE", params, 1) +class SwitchSensor: + def __init__(self, config): + printer = config.get_printer() + buttons = printer.try_load_module(config, 'buttons') + switch_pin = config.get('switch_pin') + buttons.register_buttons([switch_pin], self._button_handler) + self.runout_helper = RunoutHelper(config) + def _button_handler(self, eventtime, state): + self.runout_helper.note_filament_present(state) + def load_config_prefix(config): return SwitchSensor(config)