diff --git a/cpdctrl_gui/ui/main_window.py b/cpdctrl_gui/ui/main_window.py index 41977d8..5e4c349 100644 --- a/cpdctrl_gui/ui/main_window.py +++ b/cpdctrl_gui/ui/main_window.py @@ -136,8 +136,10 @@ class MainWindow(QMainWindow): self.power_switch = ClewareSwitch(exe) self.vmdev = None self.leddev = None - self.vmdev_autoconnect() - self.leddev_autoconnect() + if AppConfig.MAIN_CFG.get_or("voltage_measurement_device_auto_reconnect", False): + self.vmdev_autoconnect() + if AppConfig.MAIN_CFG.get_or("led_device_auto_reconnect", False): + self.leddev_autoconnect() # Measurement self.idle_timer = None @@ -206,8 +208,11 @@ class MainWindow(QMainWindow): try: self.leddev = ledd.connect_device(leddev_type, leddev_name) except Exception as e: - if not fail_silently: - QMessageBox.critical(self, "Connection failed", f"Failed to connect to '{leddev_name}', the following error occured: \n{e}") + if fail_silently: + raise e + else: + QMessageBox.critical(self, "Connection failed", f"Failed to connect to '{leddev_name}', the following error occurred: \n{e}") + log.error(f"Failed to connect to '{leddev_name}', the following error occured: \n{e}") return AppConfig.MAIN_CFG.set("led_device_last.type", leddev_type) AppConfig.MAIN_CFG.set("led_device_last.name", leddev_name) @@ -224,15 +229,14 @@ class MainWindow(QMainWindow): self.w_measurement_settings.set_value("device_led", led_name) def leddev_autoconnect(self): - if AppConfig.MAIN_CFG.get_or("led_device_auto_reconnect", False): - try: - leddev_type = AppConfig.MAIN_CFG.get("led_device_last.type") - leddev_name = AppConfig.MAIN_CFG.get("led_device_last.name") - self.leddev_connect(leddev_type, leddev_name, fail_silently=True) - except KeyError: - pass - except Exception as e: - log.error(f"Failed to auto-connect to LED device: {e}") + try: + leddev_type = AppConfig.MAIN_CFG.get("led_device_last.type") + leddev_name = AppConfig.MAIN_CFG.get("led_device_last.name") + self.leddev_connect(leddev_type, leddev_name, fail_silently=True) + except KeyError: + pass + except Exception as e: + log.error(f"Failed to auto-connect to LED device: {e}") def leddev_connect_from_dialog(self): """ @@ -245,13 +249,13 @@ class MainWindow(QMainWindow): leddev_type, leddev_name = device_dialog.get_selected() self.leddev_connect(leddev_type, leddev_name) - def leddev_test_connection(self) -> bool: + def leddev_test_connection(self, silent=False) -> bool: if self.leddev is not None: try: self.leddev.test_connection() return True except ConnectionError as e: - QMessageBox.warning(self, "LED Controller Disconnected", f"Lost connection to the LED controller '{self.leddev}'") + if not silent: QMessageBox.warning(self, "LED Controller Disconnected", f"Lost connection to the LED controller '{self.leddev}'") self.leddev = None self.leddev_connected() return False @@ -262,8 +266,11 @@ class MainWindow(QMainWindow): try: self.vmdev = vmd.connect_device(vmdev_type, vmdev_name) except Exception as e: - if not fail_silently: - QMessageBox.critical(self, "Connection failed", f"Failed to connect to '{leddev_name}', the following error occured: \n{e}") + if fail_silently: + raise e + else: + QMessageBox.critical(self, "Connection failed", f"Failed to connect to '{vmdev_name}', the following error occured: \n{e}") + log.error(f"Failed to connect to '{vmdev_name}', the following error occured: \n{e}") return AppConfig.MAIN_CFG.set("voltage_measurement_device_last.type", vmdev_type) AppConfig.MAIN_CFG.set("voltage_measurement_device_last.name", vmdev_name) @@ -274,15 +281,14 @@ class MainWindow(QMainWindow): self.w_measurement_settings.set_value("device_voltage_measurement", self.vmdev) def vmdev_autoconnect(self): - if AppConfig.MAIN_CFG.get_or("voltage_measurement_device_auto_reconnect", False): - try: - vmdev_type = AppConfig.MAIN_CFG.get("voltage_measurement_device_last.type") - vmdev_name = AppConfig.MAIN_CFG.get("voltage_measurement_device_last.name") - self.vmdev_connect(vmdev_type, vmdev_name, fail_silently=True) - except KeyError: - pass - except Exception as e: - log.error(f"Failed to auto-connect to voltage measurement device: {e}") + try: + vmdev_type = AppConfig.MAIN_CFG.get("voltage_measurement_device_last.type") + vmdev_name = AppConfig.MAIN_CFG.get("voltage_measurement_device_last.name") + self.vmdev_connect(vmdev_type, vmdev_name, fail_silently=True) + except KeyError: + pass + except Exception as e: + log.error(f"Failed to auto-connect to voltage measurement device: {e}") def vmdev_connect_from_dialog(self): """ Open a dialog that lets the user choose a voltage measurement device, @@ -294,13 +300,13 @@ class MainWindow(QMainWindow): vmdev_type, vmdev_name = device_dialog.get_selected() self.vmdev_connect(vmdev_type, vmdev_name) - def vmdev_test_connection(self) -> bool: + def vmdev_test_connection(self, silent=False) -> bool: if self.vmdev is not None: try: self.vmdev.test_connection() return True except ConnectionError as e: - QMessageBox.warning(self, "Voltage Measurement Device Disconnected", f"Lost connection to the voltage measurement device '{self.vmdev}'") + if not silent: QMessageBox.warning(self, "Voltage Measurement Device Disconnected", f"Lost connection to the voltage measurement device '{self.vmdev}'") self.vmdev = None self.vmdev_connected() return False @@ -460,6 +466,10 @@ class MainWindow(QMainWindow): self.w_plot.update_plot(tval, vval, led_val) else: # measurement might have stopped after max N or script end self.measure_stop() + # this should only be run when the measurement is stopped automatically + # and is therefore not part of measure_stop() + if AppConfig.MAIN_CFG.get_or("power_switch_turn_off_when_measurement_ends", False): + self.power_off() def measurement_is_running(self): return self.proc_measure is not None @@ -595,14 +605,59 @@ class MainWindow(QMainWindow): self.command_queue.put(("metadata", metadata)) def power_on(self): + """ + Send power on command to the power switch. + If configured, wait for a while and then try to reconnect to unconnected devices. + """ if self.power_switch is None: raise RuntimeError("No power switch configured") + log.info("Powering on") self.power_switch.on() + # TODO: change to zero + timeout = AppConfig.MAIN_CFG.get_or("power_switch_autoconnect_devices_timeout_s", 20) + if not timeout > 0: return + if self.vmdev and self.leddev: return + dialog = QDialog() + dialog.setWindowTitle("Autoconnect devices") + buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Cancel) + buttons.accepted.connect(dialog.accept) + buttons.rejected.connect(dialog.reject) + dialog.setLayout(QVBoxLayout()) + dialog.l_time = QLabel(f"{timeout} s") + dialog.time_left = timeout + dialog.layout().addWidget(QLabel(f"Trying to reconnect to devices in")) + dialog.layout().addWidget(dialog.l_time) + dialog.layout().addWidget(buttons) + dialog.time_left = timeout + def update_time_left(dialog): + dialog.time_left -= 1 + dialog.l_time.setText(f"{dialog.time_left} s") + if dialog.time_left <= 0: + dialog.accept() + dialog.update_time_left = update_time_left + dialog.timer = QTimer() + dialog.timer.timeout.connect(lambda: dialog.update_time_left(dialog)) + dialog.timer.start(1000) + ret = dialog.exec() + dialog.timer.stop() + if ret == QDialog.DialogCode.Accepted: + log.info("Trying to autoconnect last devices") + if self.vmdev is None: + self.vmdev_autoconnect() + if self.leddev is None: + self.leddev_autoconnect() + else: + pass def power_off(self): if self.power_switch is None: raise RuntimeError("No power switch configured") + log.info("Powering off") self.power_switch.off() + silent = True + self.leddev_test_connection(silent=silent) + self.vmdev_test_connection(silent=silent) + def app_exit(self) -> None: """ diff --git a/cpdctrl_gui/ui/widgets/settings/app_settings.py b/cpdctrl_gui/ui/widgets/settings/app_settings.py index 24b6db5..a197f41 100644 --- a/cpdctrl_gui/ui/widgets/settings/app_settings.py +++ b/cpdctrl_gui/ui/widgets/settings/app_settings.py @@ -49,6 +49,11 @@ class AppSettings(QWidget): # power_switch w_usb_switch_exe = FileSelection(filemode=QFileDialog.FileMode.ExistingFile) self.w_form.add_form_row("power_switch_exe", "Power Switch Executable", "", w_usb_switch_exe, "Path to the USBSwitchCmd executable for the Cleware USB switch\nRequires a relaunch to take effect", group="power_switch") + w_power_on_reconnect_dt = QSpinBox() + w_power_on_reconnect_dt.setMinimum(0) + w_power_on_reconnect_dt.setMaximum(60) + w_power_on_reconnect_dt.setSingleStep(1) + self.w_form.add_form_row("power_switch_autoconnect_devices_timeout_s", "Autoconnect devices after (s)", 15, w_power_on_reconnect_dt, "After switching on, wait x seconds before trying to reconnect to the last devices\nSet to 0 to disable the auto-connection attempt.", group="power_switch") self.w_form.update_alignment()