78 lines
3.0 KiB
Python
78 lines
3.0 KiB
Python
"""Bind the optional GPIO watcher to the shared reference-capture action."""
|
|
|
|
from collections.abc import Callable
|
|
import logging
|
|
|
|
from PyQt6.QtCore import QObject
|
|
|
|
from python_app.gui.control_button import ControlButtonWatcher
|
|
from python_app.gui.controllers.log_controller import LogController
|
|
from python_app.models.run_config_schema import ControlButtonModel
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ControlButtonController(QObject):
|
|
def __init__(self, parent: QObject, current_config: Callable[[], ControlButtonModel],
|
|
capture_reference: Callable[[], None], log: LogController) -> None:
|
|
super().__init__(parent)
|
|
self._config, self._capture_reference = current_config, capture_reference
|
|
self._log = log
|
|
self._watcher: ControlButtonWatcher | None = None
|
|
self._closed = False
|
|
|
|
def start(self) -> None:
|
|
if self._closed or self._watcher is not None:
|
|
return
|
|
config = self._config()
|
|
if not config.enabled:
|
|
return
|
|
if config.pin < 0 or not config.gpio_chip or config.action != ControlButtonModel.ACTION_CAPTURE_TMP_REFERENCE:
|
|
logger.warning("GPIO control button configuration is incomplete or unsupported; watcher not started")
|
|
return
|
|
watcher = None
|
|
try:
|
|
watcher = ControlButtonWatcher(chip=config.gpio_chip, pin=config.pin, active_low=config.active_low,
|
|
bias=config.bias, debounce_ms=config.debounce_ms, parent=self)
|
|
watcher.pressed.connect(self._pressed)
|
|
watcher.failed.connect(self._failed)
|
|
watcher.start()
|
|
self._watcher = watcher
|
|
logger.info("GPIO control button watching %s pin=%d action=%s", config.gpio_chip, config.pin, config.action)
|
|
except Exception:
|
|
logger.warning("Failed to start GPIO control button watcher", exc_info=True)
|
|
if watcher is not None:
|
|
self._disconnect(watcher)
|
|
watcher.deleteLater()
|
|
|
|
def _pressed(self) -> None:
|
|
if not self._closed and self._watcher is not None:
|
|
logger.info("GPIO control button pressed: capturing tmp reference")
|
|
with self._log.capture_errors():
|
|
self._capture_reference()
|
|
|
|
def _failed(self, message: str) -> None:
|
|
logger.warning("GPIO control button watcher stopped: %s", message)
|
|
|
|
def close(self) -> None:
|
|
self._closed = True
|
|
watcher, self._watcher = self._watcher, None
|
|
if watcher is None:
|
|
return
|
|
self._disconnect(watcher)
|
|
try:
|
|
watcher.stop()
|
|
except Exception:
|
|
logger.warning("Error stopping GPIO control button watcher", exc_info=True)
|
|
finally:
|
|
self._disconnect(watcher)
|
|
watcher.deleteLater()
|
|
|
|
@staticmethod
|
|
def _disconnect(watcher: ControlButtonWatcher) -> None:
|
|
for signal in (watcher.pressed, watcher.failed):
|
|
try:
|
|
signal.disconnect()
|
|
except (TypeError, RuntimeError):
|
|
pass
|