.. index:: UI-Adapter, Qt-Worker, Mess-Worker, RF-Off UI-Adapter und Worker-Schnittstelle =================================== Messklassen sind unabhängig von einer Terminal- oder Qt-Darstellung. Ein ``MeasurementUIAdapter`` überträgt Bedienerfragen, Logging und manuelle Interrupts über diese Grenze. Lang laufende Mess- und Geräteoperationen sind eine getrennte Aufgabe und werden in einem Worker ausgeführt. Verantwortungsbereiche ---------------------- .. list-table:: Verantwortlichkeiten von UI und Worker :header-rows: 1 :widths: 24 38 38 * - Komponente - Verantwortlich für - Nicht verantwortlich für * - Messklasse - Ablauf, Autosave, Resume, EUT-Bewertung, Gerätelebenszyklus, Sicherheit - Widgetzustand und Qt-Ereignisverarbeitung * - UI-Adapter - Fragen, Logtransport, Bedienereignisse, Interruptanforderungen - Messentscheidungen und direkten Gerätezugriff * - Worker - Blockierende Skript- oder Geräteaufrufe, kooperativen Abbruch, Endzustand - Direkte Änderung von Widgets * - GUI-Thread - Widgets, Dialoge, Plots und Ereignisschleife - Blockierende Mess- oder Kommunikationsaufrufe Adaptermethoden --------------- ``ask(msg, buttons, level, data) -> int`` Zeigt eine Meldung und liefert den nullbasierten Index der gewählten Schaltfläche. ``buttons`` darf für eine reine Information leer sein. ``level`` und ``data`` sind Darstellungshinweise; die Messlogik darf nicht von einer bestimmten Widgetdarstellung abhängen. ``emit_log(block, *args) -> None`` Leitet einen Logblock an UI und konfigurierte Logziele weiter. Vollständige Fehler- und Sicherheitsmeldungen bleiben erhalten. ``poll_key() -> int | None`` Fragt ohne Blockierung ab und liefert einen Tastencode oder ``None``. Messkerne rufen dies an definierten Bedien- und Sicherheitspunkten auf. ``check_interrupt() -> int | None`` Kompatibilitätsname, der an ``poll_key()`` delegiert. ``pre_user_event()`` und ``post_user_event()`` Markieren Anfang und Ende einer Bedieninteraktion, beispielsweise für den sichtbaren UI-Status oder die Terminalbehandlung. ``run_interactive(obj, banner)`` Startet eine interaktive Terminalsitzung, sofern unterstützt. Eine GUI darf melden, dass diese Funktion nicht verfügbar ist. Der konkrete ``TUIAdapter`` erlaubt zusätzlich das Ersetzen von Messenger, Logger, Interrupttester, Pre-/Post-Callbacks und interaktivem Runner. Ein eigener Adapter benötigt den jeweiligen Setter nur, wenn Anwendungscode nach seiner Installation die entsprechende ``Measure.set_*``-Methode aufruft. Anbindung an Measure -------------------- ``Measure`` erzeugt standardmäßig einen ``TUIAdapter``. ``set_ui_adapter(adapter)`` bindet folgende Kompatibilitätsattribute an den neuen Adapter: .. code-block:: text messenger -> ui.ask UserInterruptTester -> ui.check_interrupt PollKey -> ui.poll_key PreUserEvent -> ui.pre_user_event PostUserEvent -> ui.post_user_event Gepflegter Code verwendet ``set_user_interrupt_tester``. Die historische Schreibweise ``set_user_interrupt_Tester`` ist nur ein Kompatibilitätsalias. Beim Wiederherstellen eines Pickles wird der TUI-Standardadapter neu erzeugt, weil UI-Objekte und Callbacks nicht serialisiert werden. Skript oder Runner binden den gewünschten Adapter deshalb nach dem Laden erneut an. ``resolve_poll_key(handler, caller_locals)`` bevorzugt einen expliziten Callback. Die Suche im Aufrufer-Frame bleibt nur als Rückfallebene erhalten. Neue Messkerne übergeben die Pollingfunktion ausdrücklich. Qt-Adapter ---------- ``QtUIAdapter`` kommuniziert mit ``MeasurementControlWidget`` über queued Qt-Signale: ``prompt_requested`` Überträgt Meldung, Schaltflächen, Level und Daten in den GUI-Thread. ``log_requested`` Fügt vollständigen Logtext ein, ohne das Widget aus dem Worker zu ändern. ``status_changed`` Aktualisiert den sichtbaren Lebenszykluszustand. ``ask`` wartet im Mess-Worker auf einer ``threading.Condition``, während die Qt-Ereignisschleife ansprechbar bleibt. Eine Schaltfläche ruft im GUI-Thread ``submit_answer`` auf und weckt den Worker. Diese blockierende Methode darf nicht aus dem GUI-Thread selbst aufgerufen werden. Der gemeinsame ``qt_runner`` übernimmt die Standardanbindung: #. Text-Messskript als Modul laden; #. Konfiguration kopieren und aktualisieren; #. Quellen und Änderungen der effektiven Konfiguration erfassen; #. terminalgebundene ``messenger``- und ``user_interrupt_tester``-Callbacks entfernen; #. ``QtUIAdapter`` und dessen manuelle EUT-Überwachung anbinden; #. ``MeasurementTask`` in einen ``QThread`` verschieben; #. Erfolg, Stop und vollständige Exceptions über Signale zurückgeben; #. Worker und Thread nach Abschluss beenden und freigeben. Das Steuerfenster trennt Messung und effektive Konfiguration in Tabs. Der Konfigurationstab ist read-only und zeigt Wert sowie zuletzt ändernde Quelle. Die Schaltfläche **Stop / RF Off** liegt außerhalb der Tabs und bleibt daher auch beim Prüfen der Konfiguration unmittelbar erreichbar. Stop und RF-Off --------------- Die Qt-Schaltfläche **Stop / RF Off** verwendet zwei Pfade: * Bietet eine aktive Frage ``Quit`` an, wird diese Antwort ausgewählt. * Andernfalls wird eine thread-sichere Interruptanforderung gespeichert. ``poll_key`` liefert den synthetischen Tastencode genau einmal. Der Adapter greift nicht auf Hardware zu. Der Mess-Worker erhält die Anforderung am nächsten Pollingpunkt und führt den regulären RF-Off- und Abschlusspfad aus. Die Reaktionszeit hängt daher von begrenzten Geräteaufrufen und kurzen, dokumentierten Pollingintervallen ab. Ein unbegrenzt im Treiber blockierter Worker wird nicht allein durch eine GUI-Schaltfläche sicher. Ein separater unmittelbarer Hardware-Sicherheitspfad ist nur zulässig, wenn Gerät und Kommunikationsschicht dies ausdrücklich unterstützen. Zugriffe auf einen gemeinsamen Transport müssen serialisiert werden; konkurrierende Kommandos aus GUI- und Worker-Thread können den Protokollzustand beschädigen. Manuelle und automatische EUT-Überwachung ----------------------------------------- Manuelle Intervention bleibt bei jeder Störfestigkeitsexposition verfügbar. ``QtUIAdapter.manual_eut_monitor`` wird durch ``qt_runner`` an passende Messparameter gebunden. Während der Exposition kann der Bediener ``degraded``, ``failed`` oder ``not_evaluated`` melden. Nach der Exposition werden Zustand und Wiederherstellung getrennt eingegeben. Automatische Kamera-, Kommunikations- oder Messkanalüberwachungen ergänzen diesen manuellen Pfad über ``CompositeEUTMonitor`` und können in einem ``ThreadedEUTMonitor`` laufen. Sie ersetzen die Bedienereingabe nicht. Die :doc:`EUT-Ereignisstruktur und Bewertungsregeln <../results/immunity-results>` legen die Rückmeldung an den Messkern fest. Die vollständige Verwendung und Erweiterung beschreibt :doc:`eut-monitoring`. Worker-Aufbau ------------- Ein Worker benötigt genau einen Start-Slot, begrenzte Operationen, kooperativen Abbruch und genau einen Endzustand für Erfolg, Abbruch oder Fehler. Qt-Signale transportieren kleine, unveränderliche Objekte. Hochratige Scans müssen Fortschrittsdaten bündeln; tausende queued Einzelsignale können die GUI noch blockiert erscheinen lassen, wenn das Gerät bereits fertig ist. Callbacks des ``ReceiverScanWorker`` laufen in dessen Python-Worker-Thread. Eine GUI überführt sie über Qt-Signale oder eine thread-sichere Queue in den GUI-Thread. Das optionale ``safety_stop`` wird bei Abbruch oder Fehler höchstens einmal ausgeführt. Beim Schließen während einer laufenden Aufgabe wird Stop angefordert, begrenzt gewartet und ein eindeutiger Endzustand angezeigt. ``QThread.quit()`` beendet nur die Ereignisschleife des Threads; bereits laufender Python-Code in einem Worker-Slot wird dadurch nicht unterbrochen. Implementierungs-Checkliste --------------------------- Für eine neue Oberfläche: * alle Kernmethoden des Adapters mit obiger Rückgabesemantik implementieren; * Widgets ausschließlich im GUI-Thread erzeugen und ändern; * das vollständige Messskript in genau einem verwalteten Worker ausführen; * Fragen, Logs, Fortschritt, Abbruch und Exceptions ausdrücklich überbrücken; * manuelle EUT-Meldung jederzeit erreichbar halten; * Stop während Warten, Scan, Frage, Leveling und Fehlerbehandlung testen; * vollständigen RF-Off-/Abschlusspfad und Autosave-Zustand erhalten. Tests ----- Qt-Tests laufen mit ``QT_QPA_PLATFORM=offscreen``. Sie prüfen mindestens: ansprechbare UI, Wecken des Workers durch Fragen, inkrementellen Fortschritt, einmalige Stopverarbeitung mit RF-Off, vollständigen Traceback, getrennte EUT-Zustands- und Wiederherstellungsangaben sowie begrenztes Verhalten beim Schließen. Die englischsprachige :doc:`kuratierte UI-API <../../api/ui>` listet Adapter, Runner und Worker-Einstiegspunkte.