From 52754a61a8b851d0eaefdbac670df93dc1b01d01 Mon Sep 17 00:00:00 2001 From: alfrix Date: Fri, 3 May 2024 22:03:25 -0300 Subject: [PATCH] rework websocket disconnect fixes #1352 used a solution closer to the webscocket-client docs --- ks_includes/KlippyWebsocket.py | 22 +++++++++++++--------- panels/base_panel.py | 5 ++++- panels/printer_select.py | 22 ++++++++++++++++------ screen.py | 11 ++++++++--- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/ks_includes/KlippyWebsocket.py b/ks_includes/KlippyWebsocket.py index 124716a4..0c8134a8 100644 --- a/ks_includes/KlippyWebsocket.py +++ b/ks_includes/KlippyWebsocket.py @@ -80,9 +80,11 @@ class KlippyWebsocket(threading.Thread): return False def close(self): + logging.debug("Closing websocket") self.closing = True self.connecting = False if self.ws is not None: + self.ws.keep_running = False self.ws.close() def on_message(self, *args): @@ -100,10 +102,13 @@ class KlippyWebsocket(threading.Thread): if "method" in response and "on_message" in self._callback: args = (response['method'], response['params'][0] if "params" in response else {}) GLib.idle_add(self._callback['on_message'], *args, priority=GLib.PRIORITY_HIGH_IDLE) + if self.closing: + timer = threading.Timer(2, self.ws.close) + timer.start() return def send_method(self, method, params=None, callback=None, *args): - if not self.connected: + if not self.connected or self.closing: return False if params is None: params = {} @@ -132,18 +137,17 @@ class KlippyWebsocket(threading.Thread): def on_close(self, *args): # args: ws, status, message # sometimes ws is not passed due to bugs - message = args[2] if len(args) == 3 else args[1] + if len(args) == 3: + status = args[1] + message = args[2] + else: + status = args[0] + message = args[1] if message is not None: - logging.info(f"{message}") + logging.info(f"{status} {message}") if not self.connected: logging.debug("Connection already closed") return - if self.closing: - logging.debug("Closing websocket") - self.ws.keep_running = False - self.close() - self.closing = False - return if "on_close" in self._callback: GLib.idle_add(self._callback['on_close'], priority=GLib.PRIORITY_HIGH_IDLE) logging.info("Moonraker Websocket Closed") diff --git a/panels/base_panel.py b/panels/base_panel.py index c1a153b3..134e6a5f 100644 --- a/panels/base_panel.py +++ b/panels/base_panel.py @@ -288,13 +288,16 @@ class BasePanel(ScreenPanel): show and self._config.get_main_config().getboolean('side_macro_shortcut', True) and self._printer.get_printer_status_data()["printer"]["gcode_macros"]["count"] > 0 + and self._screen._cur_panels[-1] != 'printer_select' ) self.control['shortcut'].set_visible(show) self.set_control_sensitive(self._screen._cur_panels[-1] != self.shorcut['panel']) self.set_control_sensitive(self._screen._cur_panels[-1] != self.shutdown['panel'], control='shutdown') def show_printer_select(self, show=True): - self.control['printer_select'].set_visible(show) + self.control['printer_select'].set_visible( + show and 'printer_select' not in self._screen._cur_panels + ) def set_title(self, title): self.titlebar.get_style_context().remove_class("message_popup_error") diff --git a/panels/printer_select.py b/panels/printer_select.py index d63955b3..35ae2def 100644 --- a/panels/printer_select.py +++ b/panels/printer_select.py @@ -1,3 +1,4 @@ +import logging import gi gi.require_version("Gtk", "3.0") @@ -12,7 +13,7 @@ class Panel(ScreenPanel): super().__init__(screen, title) printers = self._config.get_printers() - printer_buttons = [] + self.printer_buttons = [] for i, printer in enumerate(printers): name = list(printer)[0] scale = 3 @@ -23,8 +24,8 @@ class Panel(ScreenPanel): image = find_widget(self.labels[name], Gtk.Image) image.set_from_pixbuf(pixbuf) self.labels[name].connect("clicked", self.connect_printer, name) - printer_buttons.append(self.labels[name]) - grid = AutoGrid(printer_buttons, vertical=self._screen.vertical_mode) + self.printer_buttons.append(self.labels[name]) + grid = AutoGrid(self.printer_buttons, vertical=self._screen.vertical_mode) scroll = self._gtk.ScrolledWindow() scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) @@ -35,7 +36,16 @@ class Panel(ScreenPanel): self._screen.connect_printer(name) def activate(self): - self._screen.base_panel.action_bar.hide() - GLib.timeout_add(100, self._screen.base_panel.action_bar.hide) - if self._screen._ws: + if self._screen._ws and self._screen._ws.connected: self._screen.close_websocket() + logging.debug("Waiting for disconnect") + self._screen.base_panel.set_title(_("Please wait")) + b: Gtk.Button + for b in self.printer_buttons: + b.set_sensitive(False) + + def disconnected_callback(self): + logging.debug("Disconnected. Enabling buttons") + self._screen.base_panel.set_title(_("Printer Select")) + for b in self.printer_buttons: + b.set_sensitive(True) diff --git a/screen.py b/screen.py index 305a018c..fc8edda7 100755 --- a/screen.py +++ b/screen.py @@ -210,7 +210,7 @@ class KlipperScreen(Gtk.Window): gc.collect() self.connecting = True self.initialized = False - + self.initializing = False logging.info(f"Connecting to printer: {name}") ind = next( ( @@ -672,13 +672,15 @@ class KlipperScreen(Gtk.Window): def websocket_disconnected(self): logging.debug("### websocket_disconnected") - self.printer_initializing(_("Lost Connection to Moonraker"), go_to_splash=True) self.printer.state = "disconnected" self.connecting = True self.connected_printer = None self.initialized = False if 'printer_select' not in self._cur_panels: + self.printer_initializing(_("Lost Connection to Moonraker"), go_to_splash=True) self.connect_printer(self.connecting_to_printer) + else: + self.panels['printer_select'].disconnected_callback() def state_disconnected(self): logging.debug("### Going to disconnected") @@ -894,7 +896,7 @@ class KlipperScreen(Gtk.Window): def _init_printer(self, msg, go_to_splash=False): self.printer_initializing(msg, go_to_splash) self.initializing = False - if self._ws.connected: + if self._ws.connected and not self._ws.closing: GLib.timeout_add_seconds(4, self.init_klipper) else: GLib.timeout_add_seconds(4, self.connect_to_moonraker) @@ -903,6 +905,9 @@ class KlipperScreen(Gtk.Window): if self.initializing: logging.info("Already Initializing") return False + if self._ws.closing: + logging.info("Cancelling attempt") + return False self.initializing = True if self.reinit_count > self.max_retries or 'printer_select' in self._cur_panels: logging.info("Stopping Retries")