mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-10-18 21:34:03 +02:00
* Spec: SO2R with two radios in one instance (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Plan: SO2R implementation (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move the rotator command rules into RotatorControl (#46) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Store the SO2R switch, the second Win-Test station and rotator 2 (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Route frequency reports to radio 1 or 2 (#46) Add the RadioSlot enum (FIRST, SECOND) with its QRG and QTF targets, and the pure RadioSlotRouter that decides per RadioInfo packet and per Win-Test station which radio a report belongs to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Send RadioInfo of radio 2 to SECONDQRG when SO2R is on (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Send Win-Test STATUS of the second station to SECONDQRG when SO2R is on (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Run a second PSTRotator for radio 2 with SO2R (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start rotator 2 only while an ON4KST session runs (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Settings for SO2R, the second Win-Test station and rotator 2 (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Turn antenna 2 and show QTF2 with SO2R (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make the SO2R switches observable so Apply shows them (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document SO2R (#46) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Refuse clashing PSTRotator ports in both directions (#46) Writing either port now checks same-or-adjacent against the drafted value of the other; rotor 1 is only checked while SO2R and rotor 2 are on. Also fixes a misplaced Javadoc, stale WinTest parseStatus Javadoc, docs wording and removes an unused import and dead comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove the executed SO2R plan (#46) The plan's content lives on in the commits, the spec and PROJECT_CONTEXT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
feb4b4e2c9
commit
5b7c774f5f
37 files changed
+1587
-266
No files matched your search
@@ -278,6 +278,7 @@ section records only the durable architecture and operational boundaries.
|
||||
|
||||
## Important Decisions and Workarounds
|
||||
|
||||
- SO2R (issue #46): `RadioSlot` FIRST/SECOND; `RadioSlotRouter` assigns RadioInfo by `RadioNr` and Win-Test STATUS by station name, everything to FIRST while `trxSynch_so2rEnabled` is off. Radio 2 writes SECONDQRG and `actualQTF2`. Rotator logic lives in `RotatorControl`, one per radio; the compatibility retry is unchanged. MO2R and multi-PC are separate projects and need their own design.
|
||||
- **Settings take effect with Apply, not while they are edited** (release 1.50,
|
||||
`docs/superpowers/specs/2026-10-16-settings-apply-drafts-design.md`): the settings window
|
||||
stages every edit in a `SettingsDraft` that the tab states read through; Apply/Close, Save
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
# Entwurf — SO2R: zwei Funkgeräte, eine Instanz (#46)
|
||||
|
||||
Freigegeben vom Maintainer am 2026-10-16 (Gespräch). Erster Schritt zu #46; MO2R und
|
||||
Multi-Operator über mehrere Rechner sind eigene Vorhaben mit eigenem Entwurf.
|
||||
|
||||
## Warum
|
||||
|
||||
KST4Contest kennt heute genau ein Funkgerät:
|
||||
|
||||
- Jede RadioInfo-Meldung aus dem Logprogramm (N1MM, DXLog, UCXLog) überschreibt MYQRG. Das
|
||||
Feld `RadioNr` wird nicht gelesen. Wer mit zwei Geräten arbeitet, sieht MYQRG bei jedem
|
||||
Gerätewechsel springen, und die Makros tragen die QRG des zuletzt gemeldeten Geräts.
|
||||
- Win-Test kennt einen einzigen Stationsnamen-Filter, also ebenfalls ein Gerät.
|
||||
- Es gibt einen PSTRotator-Client, also nur „Antenne 1 drehen".
|
||||
|
||||
Ein SO2R-Platz (ein Operator, ein Rechner, eine ON4KST-Anmeldung, zwei Geräte mit je eigener
|
||||
Antenne) braucht pro Gerät eine eigene QRG und einen eigenen Rotor.
|
||||
|
||||
## Umfang
|
||||
|
||||
Drin:
|
||||
|
||||
- Pro Gerät eine eigene QRG: Gerät 1 schreibt MYQRG, Gerät 2 schreibt SECONDQRG.
|
||||
- Zuordnung über `RadioNr` (N1MM, DXLog, UCXLog) und über je einen Win-Test-Stationsnamen.
|
||||
- Ein zweiter PSTRotator mit Button „Antenne 2 drehen" und eigenem QTF-Feld.
|
||||
- Ein Schalter „SO2R", standardmäßig aus. Aus heißt: alles wie heute.
|
||||
|
||||
Bewusst nicht drin:
|
||||
|
||||
- Ein eigenes Rechenband pro Gerät (Pfadanalyse, Tropo-Spalte, Karte bleiben wie heute).
|
||||
- Ein „aktiver Platz", auf den sich Gearbeitet, Skeds und Makros beziehen.
|
||||
- Strahlrichtung beider Antennen auf der Karte.
|
||||
- Mehr als zwei Geräte.
|
||||
- MO2R und Multi-Operator. Das Modell schließt sie nicht aus (siehe unten), wird aber nicht
|
||||
dafür ausgebaut.
|
||||
|
||||
## Modell
|
||||
|
||||
### `RadioSlot` (core)
|
||||
|
||||
Genau zwei Instanzen, Platz 1 und Platz 2. Ein Platz bündelt:
|
||||
|
||||
| | Platz 1 | Platz 2 |
|
||||
|---|---|---|
|
||||
| QRG-Ziel | `getMYQRGFirstCat()` (MYQRG) | `getMYQRGSecondCat()` (SECONDQRG) |
|
||||
| Rotor | `RotatorControl` über `stn_pstRotator*` | `RotatorControl` über `stn_pstRotator2*` |
|
||||
| gemeldete Richtung | `getActualQTF()` | neu `getActualQTF2()` |
|
||||
| Win-Test-Stationsname | vorhandener Filter `logsynch_wintestNetworkStationNameOfWintestClient1` | neu `logsynch_wintestNetworkStationNameOfWintestClient2` |
|
||||
|
||||
Platz 2 existiert nur bei eingeschaltetem SO2R. Ohne SO2R gibt es keinen Rotor 2 und kein
|
||||
QTF2.
|
||||
|
||||
`RadioSlot` ist die Einheit, an die ein späteres MO2R einen Operator oder eine Arbeitsfläche
|
||||
hängen kann. Für SO2R wird nichts davon gebaut.
|
||||
|
||||
### `RotatorControl` (core, herausgezogen)
|
||||
|
||||
Drehbefehl, Wiederholung und die Toleranz „erreicht" (1°, `ROTATOR_REACHED_TOLERANCE_DEGREES`)
|
||||
liegen heute im `ChatController`. Sie ziehen unverändert in eine eigene Klasse, die einmal pro
|
||||
Platz instanziert wird: eigener `PstRotatorClient`, eigener Wiederholungs-Scheduler, eigene
|
||||
zuletzt gemeldete Richtung. Das Verhalten bleibt bitgenau gleich, einschließlich der
|
||||
vorhandenen Kompatibilitäts-Wiederholung; der `ChatController` delegiert nur noch.
|
||||
|
||||
PSTRotator antwortet auf Port+1. Eine zweite PSTRotator-Instanz braucht also eigene Ports; die
|
||||
Vorgabe für Rotor 2 ist 12010 (Antwort auf 12011).
|
||||
|
||||
### `RadioSlotRouter` (core, rein)
|
||||
|
||||
Entscheidet, zu welchem Platz eine Meldung gehört. Rein und ohne Abhängigkeiten, damit die
|
||||
Regel ohne Netz testbar ist.
|
||||
|
||||
RadioInfo:
|
||||
|
||||
| SO2R | `RadioNr` | Platz |
|
||||
|---|---|---|
|
||||
| aus | beliebig, auch fehlend | 1 |
|
||||
| an | 1 | 1 |
|
||||
| an | 2 | 2 |
|
||||
| an | fehlend | 1 |
|
||||
| an | anderer Wert oder nicht lesbar | verworfen, geloggt |
|
||||
|
||||
Win-Test STATUS:
|
||||
|
||||
| SO2R | Stationsname | Platz |
|
||||
|---|---|---|
|
||||
| aus | wie heute: Filter leer oder passt | 1, sonst verworfen |
|
||||
| an | passt auf Name von Platz 2 | 2 |
|
||||
| an | Name von Platz 1 leer oder passt | 1 |
|
||||
| an | sonst | verworfen |
|
||||
|
||||
Namensvergleich wie heute beim Filter (`equalsIgnoreCase`). Die Filterung der ADDQSO-Pakete nach Stationsname bleibt unberührt.
|
||||
|
||||
## Datenfluss und Fäden
|
||||
|
||||
- `ReadUDPbyUCXMessageThread` liest zusätzlich `RadioNr`, fragt den Router und schreibt die QRG
|
||||
über `uiDispatcher.runOnUi` in das QRG-Ziel des Platzes. Der Weg für eine RadioInfo ohne
|
||||
Freq oder Mode bleibt unverändert (Paket verwerfen, weiter empfangen).
|
||||
- `ReadUDPByWintestThread` fragt den Router mit dem Stationsnamen; Passfrequenz-Option und
|
||||
Formatierung bleiben, nur das Ziel hängt vom Platz ab.
|
||||
- Rotor-Rückmeldungen laufen im Empfangsfaden des jeweiligen Rotors und schreiben die Richtung
|
||||
des Platzes, wie heute bei Rotor 1. Nichts wartet auf dem AWT-Ereignisfaden.
|
||||
|
||||
## Einstellungen
|
||||
|
||||
### Reiter TRX-Abgleich
|
||||
|
||||
- Neuer Schalter „SO2R: zwei Geräte getrennt führen" (`trxSynch_so2rEnabled`, Vorgabe aus).
|
||||
- Bei SO2R an wird der vorhandene Win-Test-Stationsnamen-Filter zum Namen für Platz 1; ein neues
|
||||
Feld nimmt den Namen für Platz 2 auf. Bei SO2R aus ist das neue Feld ausgegraut.
|
||||
- Hinweistext: N1MM, DXLog und UCXLog werden über `RadioNr` zugeordnet, dafür ist nichts
|
||||
einzustellen.
|
||||
|
||||
### Reiter Station, Abschnitt PSTRotator
|
||||
|
||||
- Zweiter Block „PSTRotator 2 (SO2R)": Schalter, Host, Port (Vorgaben aus, 127.0.0.1, 12010).
|
||||
- Nur aktiv bei SO2R an. Der Hinweis „antwortet auf Port+1" gilt auch hier.
|
||||
- Gleicher Port wie Rotor 1 wird beim Übernehmen abgelehnt, mit Meldung, wie andere ungültige
|
||||
Eingaben.
|
||||
|
||||
### Übernehmen
|
||||
|
||||
Wie seit dem Entwurf vom 2026-10-16 (Einstellungen mit „Übernehmen"): alles wirkt erst mit
|
||||
Übernehmen/Schließen oder Speichern.
|
||||
|
||||
- Ändern sich SO2R oder ein Wert von Rotor 2, wird Rotor 2 einmal neu gestartet oder gestoppt —
|
||||
ein eigener Effekt-Schlüssel neben dem von Rotor 1.
|
||||
- SO2R aus stoppt Rotor 2 und leert QTF2.
|
||||
|
||||
### preferences.xml
|
||||
|
||||
Neue Elemente: `trxSynch_so2rEnabled`, `logsynch_wintestNetworkStationNameOfWintestClient2`,
|
||||
`stn_pstRotator2Enabled`, `stn_pstRotator2Host`, `stn_pstRotator2Port`. Fehlen sie in einer
|
||||
älteren Datei, gelten die Vorgaben; keine Migration. Alles gilt pro Profil.
|
||||
|
||||
## Oberfläche
|
||||
|
||||
### Stationspanel
|
||||
|
||||
- Neben „Antenne 1 Richtung {0} drehen" steht „Antenne 2 Richtung {0} drehen"
|
||||
(`selected.turnAntenna2`, de/en).
|
||||
- Sichtbar nur bei SO2R an und aktiviertem Rotor 2. Ausgegraut nach derselben Regel wie
|
||||
`canTurnAntenna` bei Rotor 1 (Rotor nicht verbunden, Station ohne Locator).
|
||||
- Überall, wo heute „Antenne 1 drehen" angeboten wird, kommt „Antenne 2 drehen" dazu.
|
||||
|
||||
### Sendezeile
|
||||
|
||||
- Reihenfolge MYQRG | SECONDQRG | QTF | QTF2. QTF2 zeigt die Richtung von Rotor 2, nur zur
|
||||
Anzeige, und ist nur bei SO2R sichtbar.
|
||||
- Bei SO2R an lautet der Tooltip von SECONDQRG „QRG Gerät 2 (aus RadioNr 2 bzw.
|
||||
Win-Test-Station 2)".
|
||||
- Bei SO2R aus sieht die Zeile aus wie heute.
|
||||
|
||||
### Statusleiste
|
||||
|
||||
Rotor 2 meldet seinen Zustand wie Rotor 1 über `ThreadStatusCallback`, aber unter eigenem Thread-Namen, und bekommt so einen eigenen Knopf in der Statusleiste. Ein
|
||||
Ausfall von Rotor 2 berührt Rotor 1 nicht.
|
||||
|
||||
### Unverändert
|
||||
|
||||
QTF-Filter der Stationsliste (Rotor 1), Karte, Pfadanalyse, Gearbeitet-Logik. Die Makros
|
||||
MYQRG und SECONDQRG tragen bei SO2R die Frequenzen der beiden Geräte.
|
||||
|
||||
## Dokumentation
|
||||
|
||||
- Changelog-Eintrag de/en.
|
||||
- Handbuch: kurzer Abschnitt „SO2R" — N1MM/DXLog/UCXLog brauchen nichts, Win-Test braucht zwei
|
||||
Stationsnamen, die zweite PSTRotator-Instanz braucht einen anderen Port.
|
||||
|
||||
## Tests
|
||||
|
||||
Core:
|
||||
|
||||
- `RadioSlotRouterTest`: alle Zeilen der beiden Tabellen oben.
|
||||
- `RotatorControlTest`: Toleranz „erreicht", keine Wiederholung bei Bewegung, die vorhandene
|
||||
Wiederholung bei Stillstand — mit Fake-Client und Fake-Scheduler. Die bisherigen Rotor-Tests
|
||||
bleiben unverändert grün; sie sichern das Herausziehen ab.
|
||||
- Empfänger: ein echtes RadioInfo-Paket mit `RadioNr` 2 bzw. ein Win-Test-STATUS mit
|
||||
Stationsname 2 setzt SECONDQRG, MYQRG bleibt unverändert. Bei SO2R aus setzt dasselbe Paket
|
||||
MYQRG.
|
||||
- `ChatPreferences`: Roundtrip der fünf neuen Elemente; eine alte Datei ohne sie ergibt die
|
||||
Vorgaben (SO2R aus, Port 12010).
|
||||
|
||||
App:
|
||||
|
||||
- Einstellungen (`DraftedSettingsTableTest`-Gerüst): Übernehmen startet bzw. stoppt Rotor 2
|
||||
genau einmal; gleicher Port wie Rotor 1 wird abgelehnt; SO2R aus stoppt Rotor 2 und leert
|
||||
QTF2.
|
||||
- Oberfläche (Compose-UI-Tests wie beim Stationspanel): Button Antenne 2 und QTF2 nur bei SO2R
|
||||
sichtbar; Button ohne Rotor 2 ausgegraut; ohne SO2R ist die Sendezeile wie heute.
|
||||
- i18n: neue Schlüssel de/en, vom Erzeuger beim Bau geprüft.
|
||||
|
||||
Live, durch den Maintainer:
|
||||
|
||||
- N1MM oder DXLog mit zwei Geräten: Gerätewechsel bewegt MYQRG und SECONDQRG getrennt.
|
||||
- Zwei PSTRotator-Instanzen auf verschiedenen Ports: beide Buttons drehen die richtige Antenne,
|
||||
QTF und QTF2 folgen.
|
||||
- Win-Test mit zwei Stationen, falls verfügbar.
|
||||
Reference in new issue
Block a user