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¶
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) -> intZeigt eine Meldung und liefert den nullbasierten Index der gewählten Schaltfläche.
buttonsdarf für eine reine Information leer sein.levelunddatasind Darstellungshinweise; die Messlogik darf nicht von einer bestimmten Widgetdarstellung abhängen.emit_log(block, *args) -> NoneLeitet einen Logblock an UI und konfigurierte Logziele weiter. Vollständige Fehler- und Sicherheitsmeldungen bleiben erhalten.
poll_key() -> int | NoneFragt ohne Blockierung ab und liefert einen Tastencode oder
None. Messkerne rufen dies an definierten Bedien- und Sicherheitspunkten auf.check_interrupt() -> int | NoneKompatibilitätsname, der an
poll_key()delegiert.pre_user_event()undpost_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:
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_requestedFügt vollständigen Logtext ein, ohne das Widget aus dem Worker zu ändern.
status_changedAktualisiert 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- unduser_interrupt_tester-Callbacks entfernen;QtUIAdapterund dessen manuelle EUT-Überwachung anbinden;MeasurementTaskin einenQThreadverschieben;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
Quitan, wird diese Antwort ausgewählt.Andernfalls wird eine thread-sichere Interruptanforderung gespeichert.
poll_keyliefert 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
EUT-Ereignisstruktur und Bewertungsregeln legen die Rückmeldung an den Messkern fest.
Die vollständige Verwendung und Erweiterung beschreibt
EUT-Überwachung verwenden und erweitern.
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.
Geräte-Lebenszyklus¶
Beim Wechsel des DRIVER-Eintrags beendet die Testoberfläche die bisherige
Treiberinstanz, bevor sie die neue Instanz übernimmt. Sicherheitsrelevante
Geräte erhalten zuvor den passenden Stoppbefehl: RFOff beim
Signalgenerator, Standby beim Verstärker und Move(0) beim
Motorcontroller. Ein Fehler beim sicheren Abschalten bricht den Wechsel ab.
Mehrkanaloberflächen schließen dabei alle bekannten Kanalinstanzen, bevor sie gemeinsame Controllerzustände zurücksetzen. Beim Motorcontroller werden Stop und Quit nicht parallel zu einem laufenden Worker gesendet. Eine Stop- oder Schließanforderung während eines Aufrufs wird vorgemerkt und nach dessen Ende ausgeführt. Nichtnull-Fehlercodes aus Treiberresultaten gelten wie Exceptions als fehlgeschlagene Operation; ausdrücklich definierte NB-Zwischenzustände bleiben davon ausgenommen.
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 kuratierte UI-API listet Adapter, Runner und Worker-Einstiegspunkte.
Signal-Generator-Testoberfläche¶
In mpylab.device.signalgenerator_ui bleiben RF On, RF Off und der
RF-Status oberhalb aller Tabs sichtbar. Rot bedeutet ON, Grün OFF und
Gelb einen unbekannten oder fehlgeschlagenen Zustand; zusätzlich wird der
Zustand als Text angezeigt. Während eines laufenden Treiberaufrufs sind die
Schaltflächen außer RF Off gesperrt. Eine RF-Off-Anforderung bleibt jederzeit
möglich: Sie wird hinter dem laufenden begrenzten Busaufruf eingereiht und als
nächste Operation auf demselben serialisierten Geräte-Worker ausgeführt. So
entstehen keine konkurrierenden Transportzugriffe. RF Off beim Schließen bleibt
erhalten.
Für einen Smoke-Test gewählte Werte werden vor dem Start im GUI-Thread kopiert. Der Worker greift nicht direkt auf Qt-Widgets zu.
Im Tab RF / Level wird der eingegebene Zahlenwert durch Klick auf dBm,
dBuV, mW oder µV unmittelbar in dieser Einheit gesetzt. Actual level
zeigt den zurückgelesenen Wert in der gewählten Einheit. Der Sollwert bleibt
bei Readback unverändert; match bzw. mismatch zeigt den Vergleich.
Nicht verfügbare oder nicht umrechenbare Werte werden ausdrücklich angezeigt.
Die Umrechnung verwendet die bestehenden UConv-Konventionen.
Der SMC100A-Treiber liest den RF-Zustand nach Init und bei Refresh mit
OUTP:STAT? zurück. Ungültige Antworten werden als Fehler behandelt;
ein zuvor bekannter Zustand wird dann nicht weiter als aktuell angezeigt.
Für die Anzeige zwischen Leistungs- und Spannungseinheiten gelten 50 Ω, entsprechend der SetLevel-Konvention des Signalgenerator-Basistreibers.
Aktive Level-Einheiten sind wie Frequenzeinheiten blau markiert.
Actual level zeigt dBm, dBµV, mW und µV gleichzeitig; einzelne nicht
darstellbare Umrechnungen werden als unavailable gekennzeichnet.
Receiver-Pegelanzeige¶
Im Measurement-Tab werden dBµV, dBm, µV und mW gleichzeitig angezeigt.
Leistungs-/Spannungsumrechnungen verwenden die Routinen aus tools/uconv.py
mit einer sichtbar ausgewiesenen Annahme von 50 Ω. Logarithmische Werte
haben höchstens zwei Nachkommastellen, lineare vier signifikante Stellen.
Kleine Werte erscheinen bei Bedarf in wissenschaftlicher Schreibweise.
Die ursprüngliche Quantity einschließlich Unsicherheit bleibt unverändert
und ist im Tooltip zugänglich. Angezeigt werden die Nominalwerte.
Laufende Messungen, Fehler und fehlende Werte haben eigene Statusmeldungen.
Ein vorheriger gültiger Wert bleibt dabei ausdrücklich als letzter gültiger
Messwert gekennzeichnet. Init löscht die vorherige Anzeige. Nicht darstellbare
Umrechnungen, etwa logarithmische Werte bei null Leistung, sind als
unavailable markiert. Last Reading im Status-Tab zeigt dieselben Werte.
Die Pegelanzeige zeigt zusätzlich Standardunsicherheiten: linear als u,
in dB als asymmetrische obere/untere Abweichung aus der Transformation von
Nominalwert ± Standardunsicherheit mit uconv.quantity_to_db. Für die
lineare Leistungs-/Spannungsumrechnung wird die Unsicherheit erster Ordnung
bei exakt angenommenen 50 Ω fortgepflanzt. Eine nichtpositive untere Grenze
erscheint logarithmisch als unbeschränkt (−∞).
Die Geräte-Testoberflächen führen Treiberaufgaben standardmäßig in genau einem
dauerhaften Worker-Thread aus. Alle Aufrufe einer Oberfläche laufen dadurch
seriell im selben Thread, während die Qt-Ereignisschleife ansprechbar bleibt.
Der Schalter --no-threaded aktiviert bei Bedarf den synchronen Fallback im
GUI-Thread. Langsame Geräteantworten können dann die Betriebssystemmeldung
„antwortet nicht“ auslösen. Die Eignung des verwendeten VISA-/GPIB-Backends
muss am jeweiligen Aufbau geprüft werden. Reines Aktualisieren der Detektor-/
Vorverstärkeranzeige sendet keine Set-Befehle.
Spektrumanalysator-Frequenzachse¶
Die Spektrumansicht wählt für die Frequenzachse automatisch Hz, kHz, MHz
oder GHz. Die Tickwerte sind absolute Frequenzen in dieser Einheit; eine
zusätzliche Matplotlib-Offsetangabe wie +1e8 wird nicht verwendet. CSV-
Export und Treiberschnittstelle behalten Frequenzen unverändert in Hz.
Der Spectrum-Tab enthält außerdem eine kompakte Schnellbedienung für Center,
Span, Start, Stop, RBW, VBW, Referenzpegel, Dämpfung, Vorverstärker, Detektor
und Trace-Modus. Frequenzwerte werden durch die Einheitentasten angewendet;
die übrigen Werte besitzen getrennte Apply- und Read-Tasten. Readbacks und
match-/mismatch-Status sind mit dem vollständigen Controls-Tab
synchronisiert und verwenden dieselben Treiberaufrufe.
Nach einer Aufnahme zeigt eine Trace-Statuszeile Frequenzbereich, Punktzahl, RBW, Detektor sowie Trace und Trace-Modus. Dafür werden bereits vorhandene Readbacks verwendet; die Anzeige löst keine zusätzlichen Geräteabfragen aus.
Retrigger wiederholt GetSpectrumNB mit einem einstellbaren Abstand.
Die Aufrufe überlappen sich nicht: Erst nach Abschluss einer Aufnahme wird die
nächste geplant. Ausschalten, Verlassen des Spectrum-Tabs, Init, Quit und
Schließen beenden den Retrigger. Da der generische GetSpectrumNB-Fallback
synchron arbeitet, wird er standardmäßig im dauerhaften Geräte-Worker
ausgeführt. Mit --no-threaded kann er bei langsamer Hardware die Oberfläche
bis zum Ende einer Aufnahme blockieren.