printer: change how states are transitioned
This commit is contained in:
parent
389eceaf06
commit
c58b040be2
@ -3,20 +3,29 @@ import logging
|
||||
logger = logging.getLogger("KlipperScreen.Printer")
|
||||
|
||||
class Printer:
|
||||
state_callbacks = {
|
||||
"disconnected": None,
|
||||
"error": None,
|
||||
"paused": None,
|
||||
"printing": None,
|
||||
"ready": None,
|
||||
"startup": None,
|
||||
"shutdown": None
|
||||
}
|
||||
|
||||
def __init__(self, printer_info, data):
|
||||
self.config = data['configfile']['config']
|
||||
self.state = "disconnected"
|
||||
self.power_devices = {}
|
||||
|
||||
logger.info("### Reading printer config")
|
||||
def reinit(self, printer_info, data):
|
||||
logger.debug("Moonraker object status: %s" % data)
|
||||
self.config = data['configfile']['config']
|
||||
self.toolcount = 0
|
||||
self.extrudercount = 0
|
||||
self.tools = []
|
||||
self.devices = {}
|
||||
self.state = data['print_stats']['state']
|
||||
self.data = data
|
||||
self.klipper = {}
|
||||
self.power_devices = {}
|
||||
|
||||
self.klipper = {
|
||||
"version": printer_info['software_version']
|
||||
@ -56,17 +65,6 @@ class Printer:
|
||||
logger.info("Klipper version: %s", self.klipper['version'])
|
||||
logger.info("### Toolcount: " + str(self.toolcount) + " Heaters: " + str(self.extrudercount))
|
||||
|
||||
def configure_power_devices(self, data):
|
||||
self.power_devices = {}
|
||||
|
||||
logger.debug("Processing power devices: %s" % data)
|
||||
for x in data['devices']:
|
||||
logger.debug(x)
|
||||
self.power_devices[x['device']] = {
|
||||
"status": "on" if x['status'] == "on" else "off"
|
||||
}
|
||||
logger.debug("Power devices: %s" % self.power_devices)
|
||||
|
||||
def process_update(self, data):
|
||||
keys = [
|
||||
'bed_mesh',
|
||||
@ -76,7 +74,8 @@ class Printer:
|
||||
'pause_resume',
|
||||
'print_stats',
|
||||
'toolhead',
|
||||
'virtual_sdcard'
|
||||
'virtual_sdcard',
|
||||
'webhooks'
|
||||
]
|
||||
for x in keys:
|
||||
if x in data:
|
||||
@ -100,10 +99,53 @@ class Printer:
|
||||
if "temperature" in d:
|
||||
self.set_dev_stat(x, "temperature", d["temperature"])
|
||||
|
||||
if "webhooks" in data or "idle_timeout" in data or "pause_resume" in data or "print_stats" in data:
|
||||
self.evaluate_state()
|
||||
|
||||
def evaluate_state(self):
|
||||
wh_state = self.data['webhooks']['state'] # possible values: startup, ready, shutdown, error
|
||||
idle_state = self.data['idle_timeout']['state'].lower() # possible values: Idle, printing, ready
|
||||
print_state = self.data['print_stats']['state'] # possible values: complete, paused, printing, standby
|
||||
|
||||
if wh_state == "ready":
|
||||
new_state = "ready"
|
||||
if idle_state == "printing" and print_state != "printing": # Not printing a file, toolhead moving
|
||||
new_state = "busy"
|
||||
elif idle_state == "printing" and print_state == "printing":
|
||||
new_state = "printing"
|
||||
elif print_state == "paused":
|
||||
new_state = "paused"
|
||||
|
||||
if new_state != "busy":
|
||||
self.change_state(new_state)
|
||||
else:
|
||||
self.change_state(wh_state)
|
||||
|
||||
def process_power_update(self, data):
|
||||
if data['device'] in self.power_devices:
|
||||
self.power_devices[data['device']]['status'] = data['status']
|
||||
|
||||
def change_state(self, state):
|
||||
if state == self.state or state not in list(self.state_callbacks):
|
||||
return
|
||||
|
||||
logger.debug("Changing state from '%s' to '%s'" % (self.state, state))
|
||||
self.state = state
|
||||
if self.state_callbacks[state] != None:
|
||||
logger.debug("Running callback for state: %s" % state)
|
||||
self.state_callbacks[state]()
|
||||
|
||||
def configure_power_devices(self, data):
|
||||
self.power_devices = {}
|
||||
|
||||
logger.debug("Processing power devices: %s" % data)
|
||||
for x in data['devices']:
|
||||
logger.debug(x)
|
||||
self.power_devices[x['device']] = {
|
||||
"status": "on" if x['status'] == "on" else "off"
|
||||
}
|
||||
logger.debug("Power devices: %s" % self.power_devices)
|
||||
|
||||
def config_section_exists(self, section):
|
||||
return section in list(self.config)
|
||||
|
||||
@ -164,6 +206,9 @@ class Printer:
|
||||
return None
|
||||
return self.data[stat]
|
||||
|
||||
def get_state(self):
|
||||
return self.state
|
||||
|
||||
def set_dev_temps(self, dev, temp, target=None):
|
||||
if dev in self.devices:
|
||||
self.devices[dev]['temperature'] = temp
|
||||
@ -194,6 +239,11 @@ class Printer:
|
||||
return True
|
||||
return False
|
||||
|
||||
def set_callbacks(self, callbacks):
|
||||
for name, cb in callbacks.items():
|
||||
if name in list(self.state_callbacks):
|
||||
self.state_callbacks[name] = cb
|
||||
|
||||
def set_dev_stat(self, dev, stat, value):
|
||||
if dev not in self.devices:
|
||||
return
|
||||
|
121
screen.py
121
screen.py
@ -90,6 +90,15 @@ class KlipperScreen(Gtk.Window):
|
||||
'is_active': False
|
||||
}
|
||||
})
|
||||
self.printer.set_callbacks({
|
||||
"disconnected": self.state_disconnected,
|
||||
"error": self.state_error,
|
||||
"printing": self.state_printing,
|
||||
"ready": self.state_ready,
|
||||
"startup": self.state_startup,
|
||||
"shutdown": self.state_shutdown
|
||||
})
|
||||
|
||||
self.lang = gettext.translation('KlipperScreen', localedir='ks_includes/locales', fallback=True)
|
||||
_ = self.lang.gettext
|
||||
|
||||
@ -138,6 +147,7 @@ class KlipperScreen(Gtk.Window):
|
||||
"fan": ["speed"],
|
||||
"gcode_move": ["extrude_factor","gcode_position","homing_origin","speed_factor"],
|
||||
"heater_bed": ["target","temperature"],
|
||||
"idle_timeout": ["state"],
|
||||
"pause_resume": ["is_paused"],
|
||||
"print_stats": ["print_duration","total_duration","filament_used","filename","state","message"],
|
||||
"toolhead": ["homed_axes","estimated_print_time","print_time","position","extruder"],
|
||||
@ -353,34 +363,54 @@ class KlipperScreen(Gtk.Window):
|
||||
self.subscriptions.pop(i)
|
||||
return
|
||||
|
||||
def state_disconnected(self):
|
||||
_ = self.lang.gettext
|
||||
logger.debug("### Going to disconnected")
|
||||
self.printer_initializing(_("Klipper has disconnected"))
|
||||
|
||||
def state_error(self):
|
||||
_ = self.lang.gettext
|
||||
msg = self.printer.get_stat("webhooks","state_message")
|
||||
if "FIRMWARE_RESTART" in msg:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error.\nIssue a FIRMWARE_RESTART to attempt fixing the issue.")
|
||||
)
|
||||
elif "micro-controller" in msg:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error with the micro-controller.\nPlease recompile and flash.")
|
||||
)
|
||||
else:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error.")
|
||||
)
|
||||
|
||||
def state_printing(self):
|
||||
self.printer_printing()
|
||||
|
||||
def state_ready(self):
|
||||
# Do not return to main menu if completing a job, timeouts/user input will return
|
||||
if "job_status" in self._cur_panels or "main_menu" in self._cur_panels:
|
||||
return
|
||||
self.printer_ready()
|
||||
|
||||
def state_startup(self):
|
||||
_ = self.lang.gettext
|
||||
self.printer_initializing(_("Klipper is attempting to start"))
|
||||
|
||||
def state_shutdown(self):
|
||||
_ = self.lang.gettext
|
||||
self.printer_initializing(_("Klipper has shutdown"))
|
||||
|
||||
def _websocket_callback(self, action, data):
|
||||
_ = self.lang.gettext
|
||||
#print(json.dumps([action, data], indent=2))
|
||||
|
||||
if action == "notify_klippy_disconnected":
|
||||
logger.info("### Going to disconnected state")
|
||||
self.printer_initializing(_("Klipper has shutdown"))
|
||||
self.printer.change_state("disconnected")
|
||||
return
|
||||
elif action == "notify_klippy_ready":
|
||||
logger.info("### Going to ready state")
|
||||
self.init_printer()
|
||||
elif action == "notify_status_update" and self.shutdown == False:
|
||||
self.printer.change_state("ready")
|
||||
elif action == "notify_status_update" and self.printer.get_state() != "shutdown":
|
||||
self.printer.process_update(data)
|
||||
if "webhooks" in data:
|
||||
print(json.dumps([action, data], indent=2))
|
||||
if "webhooks" in data and "state" in data['webhooks']:
|
||||
if data['webhooks']['state'] == "ready":
|
||||
logger.info("### Going to ready state")
|
||||
self.printer_ready()
|
||||
elif data['webhooks']['state'] == "shutdown":
|
||||
self.shutdown == True
|
||||
self.printer_initializing(_("Klipper has shutdown"))
|
||||
else:
|
||||
active = self.printer.get_stat('virtual_sdcard','is_active')
|
||||
paused = self.printer.get_stat('pause_resume','is_paused')
|
||||
if "job_status" not in self._cur_panels:
|
||||
if active == True or paused == True:
|
||||
self.printer_printing()
|
||||
elif action == "notify_filelist_changed":
|
||||
logger.debug("Filelist changed: %s", json.dumps(data,indent=2))
|
||||
#self.files.add_file()
|
||||
@ -389,10 +419,9 @@ class KlipperScreen(Gtk.Window):
|
||||
elif action == "notify_power_changed":
|
||||
logger.debug("Power status changed: %s", data)
|
||||
self.printer.process_power_update(data)
|
||||
elif self.shutdown == False and action == "notify_gcode_response":
|
||||
elif self.printer.get_state() not in ["error","shutdown"] and action == "notify_gcode_response":
|
||||
if "Klipper state: Shutdown" in data:
|
||||
self.shutdown == True
|
||||
self.printer_initializing(_("Klipper has shutdown"))
|
||||
self.printer.change_state("shutdown")
|
||||
|
||||
if not (data.startswith("B:") and
|
||||
re.search(r'B:[0-9\.]+\s/[0-9\.]+\sT[0-9]+:[0-9\.]+', data)):
|
||||
@ -439,7 +468,6 @@ class KlipperScreen(Gtk.Window):
|
||||
|
||||
def init_printer(self):
|
||||
_ = self.lang.gettext
|
||||
self.shutdown = False
|
||||
|
||||
status_objects = [
|
||||
'bed_mesh',
|
||||
@ -452,18 +480,17 @@ class KlipperScreen(Gtk.Window):
|
||||
'print_stats',
|
||||
'heater_bed',
|
||||
'extruder',
|
||||
'pause_resume'
|
||||
'pause_resume',
|
||||
'webhooks'
|
||||
]
|
||||
printer_info = self.apiclient.get_printer_info()
|
||||
logger.debug("Sendingn request %s" % "printer/objects/query?" + "&".join(status_objects))
|
||||
data = self.apiclient.send_request("printer/objects/query?" + "&".join(status_objects))
|
||||
powerdevs = self.apiclient.send_request("machine/device_power/devices")
|
||||
if printer_info == False or data == False:
|
||||
self.printer_initializing(_("Moonraker error"))
|
||||
return
|
||||
data = data['result']['status']
|
||||
|
||||
# Reinitialize printer, in case the printer was shut down and anything has changed.
|
||||
self.printer.__init__(printer_info['result'], data)
|
||||
self.printer.reinit(printer_info['result'], data)
|
||||
self.ws_subscribe()
|
||||
|
||||
if powerdevs != False:
|
||||
@ -474,48 +501,16 @@ class KlipperScreen(Gtk.Window):
|
||||
else:
|
||||
self.files.add_timeout()
|
||||
|
||||
if printer_info['result']['state'] in ("error","shutdown","startup"):
|
||||
if printer_info['result']['state'] == "startup":
|
||||
self.printer_initializing(_("Klipper is attempting to start"))
|
||||
elif printer_info['result']['state'] == "error":
|
||||
if "FIRMWARE_RESTART" in printer_info['result']['state_message']:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error.\nIssue a FIRMWARE_RESTART to attempt fixing the issue.")
|
||||
)
|
||||
elif "micro-controller" in printer_info['result']['state_message']:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error with the micro-controller.\nPlease recompile and flash.")
|
||||
)
|
||||
else:
|
||||
self.printer_initializing(
|
||||
_("Klipper has encountered an error.")
|
||||
)
|
||||
else:
|
||||
self.printer_initializing(_("Klipper has shutdown"))
|
||||
return
|
||||
if (data['print_stats']['state'] == "printing" or data['print_stats']['state'] == "paused"):
|
||||
filename = self.printer.get_stat("print_stats","filename")
|
||||
if not self.files.file_metadata_exists(filename):
|
||||
self.files.request_metadata(filename)
|
||||
self.printer_printing()
|
||||
return
|
||||
self.printer_ready()
|
||||
|
||||
def printer_ready(self):
|
||||
if self.shutdown == True:
|
||||
self.init_printer()
|
||||
return
|
||||
|
||||
self.files.add_timeout()
|
||||
self.close_popup_message()
|
||||
self.show_panel('main_panel', "main_menu", "Main Menu", 2, items=self._config.get_menu_items("__main"),
|
||||
extrudercount=self.printer.get_extruder_count())
|
||||
self.ws_subscribe()
|
||||
if "job_status" in self.panels:
|
||||
self.remove_subscription("job_status")
|
||||
del self.panels["job_status"]
|
||||
|
||||
def printer_printing(self):
|
||||
self.ws_subscribe()
|
||||
self.files.remove_timeout()
|
||||
self.close_popup_message()
|
||||
self.show_panel('job_status',"job_status", "Print Status", 2)
|
||||
|
Loading…
x
Reference in New Issue
Block a user