# -*- coding: utf-8 -*- # dispatch/null_hardware_gateway.py """Пустой реализатор `TicketHardwareGateway` для приложения Dispatch. Назначение модуля: В составе Dispatch модуль работы с COM-портом отключён по требованию приложения. Application-сервис Ticket по архитектурному контракту обязан получать на вход реализацию `TicketHardwareGateway` и обращаться к ней при старте, остановке и обновлении состояний кнопок. Данный класс предоставляет канонически совместимую, но полностью бездействующую реализацию шлюза: - `start` / `stop` ничего не делают; - `set_observer` принимает наблюдателя и сразу публикует ему нейтральный статус подключения; - методы управления состояниями кнопок принимают вызовы и молча игнорируют их; - `get_status` всегда возвращает «отключён». Архитектурные ограничения: - Реализация полностью независима от каталога `gui/`. - Никакой предметной логики Ticket здесь не содержится: класс исключительно закрывает контракт `TicketHardwareGateway`. """ from __future__ import annotations from typing import Any, Mapping from PySide6.QtCore import QObject from domain import TicketConnectionStatus, TicketHardwareStatus from services import TicketHardwareObserver class NullHardwareGateway(QObject): """Бездействующий шлюз: закрывает контракт `TicketHardwareGateway`.""" def __init__(self, parent: QObject | None = None): super().__init__(parent) self._observer: TicketHardwareObserver | None = None self._status = TicketHardwareStatus( connection_status=TicketConnectionStatus.DISCONNECTED, message="hardware module is disabled in Dispatch", buttons_initialized=False, button_count=0, ) # ── управление жизненным циклом ── def start(self) -> None: """Обозначить факт «запуска» без обращения к внешнему оборудованию.""" if self._observer is not None: self._observer.on_gateway_status(self._status) def stop(self) -> None: """Завершить работу: ничего не освобождаем, состояние уже нейтральное.""" return # ── подписка наблюдателя ── def set_observer(self, observer: TicketHardwareObserver | None) -> None: """Назначить получателя событий и сразу опубликовать текущий статус.""" self._observer = observer if observer is not None: observer.on_gateway_status(self._status) def get_status(self) -> TicketHardwareStatus: """Вернуть постоянно-нейтральный статус шлюза.""" return self._status # ── управление состояниями кнопок ── def set_button_state(self, button_id: int, state_code: int) -> None: """Принять обновление состояния кнопки и проигнорировать его.""" return def remove_button_state(self, button_id: int) -> None: """Принять снятие состояния кнопки и проигнорировать его.""" return def reset_button_states(self) -> None: """Сбросить «состояния»: для null-шлюза это операция без эффекта.""" return # ── совместимость с возможными внешними действиями ── def emit_external_action(self, raw_action: Mapping[str, Any]) -> None: """Доставить внешнее действие наблюдателю, если он назначен. Метод оставлен для возможной интеграции внешних источников событий в будущем; в текущем составе Dispatch не вызывается. """ if self._observer is not None: self._observer.on_task_action(raw_action)