diff --git a/pytec/tec_qt.py b/pytec/tec_qt.py index 3d45c15..58ea46f 100755 --- a/pytec/tec_qt.py +++ b/pytec/tec_qt.py @@ -63,6 +63,7 @@ class MainWindow(QtWidgets.QMainWindow): self.info_box = InfoBox() self.thermostat = Thermostat(self, self.report_refresh_spin.value()) + self._connecting_task = None def handle_connection_error(): self.info_box.display_info_box( @@ -231,38 +232,37 @@ class MainWindow(QtWidgets.QMainWindow): @asyncSlot() async def on_connect_btn_clicked(self): - host, port = ( - self.conn_menu.host_set_line.text(), - self.conn_menu.port_set_spin.value(), - ) + if (self._connecting_task is None) and (not self.thermostat.connected()): + self.status_lbl.setText("Connecting...") + self.connect_btn.setText("Stop") + self.conn_menu.host_set_line.setEnabled(False) + self.conn_menu.port_set_spin.setEnabled(False) - self._connecting_task = None - try: - if (self._connecting_task is None) or (not self.thermostat.connected()): - self.status_lbl.setText("Connecting...") - self.connect_btn.setText("Stop") - self.conn_menu.host_set_line.setEnabled(False) - self.conn_menu.port_set_spin.setEnabled(False) - - try: - self._connecting_task = asyncio.wait_for( - self.thermostat.start_session(host=host, port=port), timeout=5 - ) - await self._connecting_task - except asyncio.TimeoutError: - return - await self._on_connection_changed(True) - else: - if self._connecting_task is not None: - self._connecting_task.cancel() - await self.bail() - - # TODO: Remove asyncio.TimeoutError in Python 3.11 - except (OSError, asyncio.TimeoutError): + self._connecting_task = asyncio.create_task( + asyncio.wait_for( + self.thermostat.start_session( + host=self.conn_menu.host_set_line.text(), + port=self.conn_menu.port_set_spin.value(), + ), + timeout=5, + ) + ) try: + await self._connecting_task + except (OSError, asyncio.TimeoutError, asyncio.CancelledError) as exc: await self.bail() - except ConnectionResetError: - pass + if isinstance(exc, asyncio.CancelledError): + return + raise + else: + await self._on_connection_changed(True) + finally: + self._connecting_task = None + + elif self._connecting_task is not None: + self._connecting_task.cancel() + else: + await self.bail() @asyncSlot() async def bail(self):