Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9037adf6eb |
@@ -63,8 +63,6 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
New-Item -ItemType Directory -Force -Path dist | Out-Null
|
||||
$addModules = & java packaging/AddModules.java
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed to resolve --add-modules from module-info.java" }
|
||||
jpackage `
|
||||
--type app-image `
|
||||
--name praktiKST `
|
||||
@@ -73,7 +71,7 @@ jobs:
|
||||
--main-jar app.jar `
|
||||
--main-class kst4contest.view.Kst4ContestApplication `
|
||||
--module-path target/dist-libs `
|
||||
--add-modules $addModules `
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec `
|
||||
--dest dist
|
||||
|
||||
- name: Create Windows ZIP
|
||||
@@ -122,7 +120,6 @@ jobs:
|
||||
- name: Build app-image with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -131,7 +128,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
- name: Create AppDir metadata
|
||||
@@ -209,7 +206,6 @@ jobs:
|
||||
- name: Build Debian package
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type deb \
|
||||
--name KST4Contest \
|
||||
@@ -218,7 +214,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--linux-package-deps "libgstreamer1.0-0,libgstreamer-plugins-base1.0-0,gstreamer1.0-plugins-good" \
|
||||
--dest dist
|
||||
DEB="$(ls dist/*.deb | head -n 1)"
|
||||
@@ -270,7 +266,6 @@ jobs:
|
||||
- name: Build Fedora package
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type rpm \
|
||||
--name KST4Contest \
|
||||
@@ -279,7 +274,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--linux-package-deps "gstreamer1,gstreamer1-plugins-base,gstreamer1-plugins-good" \
|
||||
--dest dist
|
||||
RPM="$(ls dist/*.rpm | head -n 1)"
|
||||
@@ -333,7 +328,6 @@ jobs:
|
||||
- name: Build app-image with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -342,7 +336,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
- name: Build Arch Linux package artifact
|
||||
@@ -453,7 +447,6 @@ jobs:
|
||||
./mvnw -B -DskipTests package dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dist-libs
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
mkdir -p target/flatpak-src
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -462,7 +455,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest target/flatpak-src
|
||||
|
||||
- name: Create Flatpak manifest
|
||||
@@ -642,7 +635,6 @@ jobs:
|
||||
- name: Build macOS DMG with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type dmg \
|
||||
--name KST4Contest \
|
||||
@@ -651,7 +643,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
env:
|
||||
|
||||
@@ -27,8 +27,5 @@ jobs:
|
||||
- name: Ensure mvnw is executable
|
||||
run: chmod +x mvnw
|
||||
|
||||
- name: Verify packaging module list matches module-info.java
|
||||
run: java packaging/AddModules.java --verify-pom
|
||||
|
||||
- name: Compile
|
||||
run: ./mvnw -B -DskipTests compile
|
||||
|
||||
@@ -48,8 +48,6 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
New-Item -ItemType Directory -Force -Path dist | Out-Null
|
||||
$addModules = & java packaging/AddModules.java
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed to resolve --add-modules from module-info.java" }
|
||||
jpackage `
|
||||
--type app-image `
|
||||
--name praktiKST `
|
||||
@@ -58,7 +56,7 @@ jobs:
|
||||
--main-jar app.jar `
|
||||
--main-class kst4contest.view.Kst4ContestApplication `
|
||||
--module-path target/dist-libs `
|
||||
--add-modules $addModules `
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec `
|
||||
--dest dist
|
||||
|
||||
- name: Create Windows ZIP
|
||||
@@ -100,7 +98,6 @@ jobs:
|
||||
- name: Build app-image with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -109,7 +106,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
- name: Create AppDir metadata
|
||||
@@ -180,7 +177,6 @@ jobs:
|
||||
- name: Build Debian package
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type deb \
|
||||
--name KST4Contest \
|
||||
@@ -189,7 +185,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--linux-package-deps "libgstreamer1.0-0,libgstreamer-plugins-base1.0-0,gstreamer1.0-plugins-good" \
|
||||
--dest dist
|
||||
DEB="$(ls dist/*.deb | head -n 1)"
|
||||
@@ -234,7 +230,6 @@ jobs:
|
||||
- name: Build Fedora package
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type rpm \
|
||||
--name KST4Contest \
|
||||
@@ -243,7 +238,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--linux-package-deps "gstreamer1,gstreamer1-plugins-base,gstreamer1-plugins-good" \
|
||||
--dest dist
|
||||
RPM="$(ls dist/*.rpm | head -n 1)"
|
||||
@@ -288,7 +283,6 @@ jobs:
|
||||
- name: Build app-image with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -297,7 +291,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
- name: Build Arch Linux package artifact
|
||||
@@ -399,7 +393,6 @@ jobs:
|
||||
./mvnw -B -DskipTests package dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dist-libs
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
mkdir -p target/flatpak-src
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -408,7 +401,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest target/flatpak-src
|
||||
|
||||
- name: Create Flatpak manifest
|
||||
@@ -530,7 +523,6 @@ jobs:
|
||||
- name: Build macOS DMG with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type dmg \
|
||||
--name KST4Contest \
|
||||
@@ -539,7 +531,7 @@ jobs:
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
|
||||
env:
|
||||
|
||||
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 36 KiB |
@@ -4,22 +4,11 @@
|
||||
|
||||
## Verbinden mit dem Chat
|
||||
|
||||
Vor dem ersten Verbindungsaufbau müssen im Einstellungsfenster mindestens Rufzeichen, Passwort, Locator und primäre Chat-Kategorie konfiguriert werden. Soll zusätzlich eine zweite Kategorie verwendet werden, muss auch deren Login aktiviert und vollständig eingerichtet sein.
|
||||
1. Im Einstellungsfenster eine **Chat-Kategorie** auswählen (z. B. 144 MHz VHF, 432 MHz UHF, …).
|
||||
2. **Connect**-Button klicken.
|
||||
3. Warten bis die Verbindung aufgebaut ist.
|
||||
|
||||
Die Verbindung kann auf zwei Wegen aufgebaut werden:
|
||||
|
||||
- Mit **Connect to …** im Einstellungsfenster werden die dort eingetragenen Werte übernommen und die Verbindung gestartet.
|
||||
- **File → Connect to …** verwendet die bereits in KST4Contest übernommenen Einstellungen.
|
||||
|
||||
Geänderte Einstellungen müssen mit **Save Settings** gespeichert werden, wenn sie auch beim nächsten Programmstart verwendet werden sollen.
|
||||
|
||||
Eine bestehende Verbindung kann über **File → Disconnect** oder über **Disconnect** im Einstellungsfenster beendet werden. **Exit + disconnect** beendet zusätzlich das Programm.
|
||||
|
||||
Bei einem unerwarteten Verbindungsverlust versucht KST4Contest nach einer begrenzten Wartezeit, die ON4KST-Verbindung kontrolliert neu aufzubauen. Ein fehlgeschlagener Erstaufbau blockiert die Benutzeroberfläche nicht mehr.
|
||||
|
||||
Ob die Verbindung lediglich als TCP-Verbindung besteht oder bereits vollständig angemeldet und synchronisiert ist, zeigt der [`LINK`-Status](#statusleiste-und-hinweise) im Hauptfenster.
|
||||
|
||||
---
|
||||
> Trennen und Neu-Verbinden ist nur über das Einstellungsfenster möglich. Es empfiehlt sich daher, das Einstellungsfenster geöffnet zu lassen.
|
||||
|
||||
---
|
||||
|
||||
@@ -27,40 +16,10 @@ Ob die Verbindung lediglich als TCP-Verbindung besteht oder bereits vollständig
|
||||
|
||||
Das Hauptfenster besteht aus mehreren Bereichen:
|
||||
|
||||
|
||||
### Statusleiste und Hinweise
|
||||
|
||||
Die Statusleiste befindet sich am oberen Rand des Hauptfensters neben dem Menü.
|
||||
|
||||

|
||||
|
||||
Der dauerhaft sichtbare `LINK`-Indikator zeigt den tatsächlichen Zustand der ON4KST-Verbindung:
|
||||
|
||||
| Anzeige | Bedeutung |
|
||||
|---|---|
|
||||
| grünes `LINK` | Login und Synchronisation der konfigurierten Chat-Kategorien sind vollständig abgeschlossen |
|
||||
| gelbes `LINK…` | Verbindung, Anmeldung, Benutzerlistensynchronisation oder kontrolliertes Beenden läuft |
|
||||
| rotes `LINK!` | keine Verbindung oder Wartezeit vor einem automatischen Neuaufbau |
|
||||
|
||||
Der Tooltip enthält den internen Verbindungsstatus und eine genauere Beschreibung des aktuellen Schritts. Der Indikator ist keine Schaltfläche.
|
||||
|
||||
`ONLINE` wird erst gemeldet, nachdem die Anmeldung bestätigt und die Benutzerlisten der konfigurierten Kategorien vollständig empfangen wurden. Während die Verbindung noch aufgebaut oder neu synchronisiert wird, bleiben Sendfeld und **TX** deaktiviert.
|
||||
|
||||
Bei bestimmten Ereignissen erscheinen vorübergehend weitere Hinweise:
|
||||
|
||||
- `SKED` weist auf eine fällige Sked-Erinnerung hin. Der Text enthält das vollständige Zielrufzeichen und die verbleibende Zeit.
|
||||
- `BAND+` erscheint nach einem Logeintrag, wenn für die gearbeitete Station noch mindestens ein gemeinsames, aktiviertes und nicht gearbeitetes Band erkannt wurde.
|
||||
|
||||
Beide Hinweise blinken ungefähr zwölf Sekunden und verschwinden anschließend wieder. Der vollständige Inhalt beziehungsweise die Herleitung steht im jeweiligen Tooltip. Die Anzeigen sind nicht anklickbar.
|
||||
|
||||
|
||||
### PM-Fenster (oben links)
|
||||
|
||||
Das PM-Fenster zeigt die an die eigenen Chat-Logins gerichteten Privatnachrichten und die zugehörigen ausgehenden Antworten.
|
||||
Zeigt alle empfangenen **Privatnachrichten** sowie abgefangene öffentliche Nachrichten, die das eigene Rufzeichen enthalten. Neue Nachrichten erscheinen in **Rot** und faden alle 30 Sekunden über Gelb bis Weiß ab.
|
||||
|
||||
Ist das [QSO-Monitoring](de-Funktionen#qso-monitoring-ab-v131) aktiviert, erscheinen dort zusätzlich die erfassten Nachrichten der überwachten Basisrufzeichen. Diese Einträge erhalten eine `Sniffed:`-Kennzeichnung mit dem vollständigen sichtbaren Absender und Empfänger.
|
||||
|
||||
Neue Nachrichten werden zunächst auffällig dargestellt und wechseln anschließend schrittweise zur normalen Tabellenfarbe. Die farbliche Hervorhebung dient nur als zeitlicher Hinweis; sie verändert weder Inhalt noch Routing der Nachricht.
|
||||
### Benutzerliste (Chat Members)
|
||||
|
||||
Die zentrale Tabelle aller aktuell aktiven Chat-Nutzer. Spalten (je nach Konfiguration):
|
||||
@@ -101,47 +60,15 @@ Jede Statuszelle besitzt einen Tooltip mit der Legende und dem für die betreffe
|
||||
Ein grün und fett dargestelltes Rufzeichen kennzeichnet eine aus einer gerichteten Nachricht hergeleitete Richtungsgelegenheit. Die Markierung bezieht sich auf den Absender der Nachricht und bleibt höchstens fünf Minuten sichtbar. Herleitung und Grenzen: [Richtungsgelegenheiten aus gerichteten Nachrichten](de-Funktionen#richtungsgelegenheiten-aus-gerichteten-nachrichten).
|
||||
### Sendfeld
|
||||
|
||||
Das Sendfeld enthält den vorbereiteten Text für die nächste ausgehende Nachricht.
|
||||
Texteingabe für ausgehende Nachrichten. Nach Klick auf ein Rufzeichen in der Benutzerliste erhält das Sendfeld automatisch den Fokus – sofort tippen ohne Doppelklick (ab v1.22).
|
||||
|
||||
Wird eine Station bewusst per Maus oder Tastatur in der Benutzerliste ausgewählt, bereitet KST4Contest eine gerichtete Nachricht vor:
|
||||
### MYQRG-Feld
|
||||
|
||||
```text
|
||||
/cq RUFZEICHEN
|
||||
```
|
||||
Rechts neben dem Sendbutton. Zeigt die aktuelle eigene QRG an, kann auch manuell eingetragen werden.
|
||||
|
||||
Dabei werden das vollständige sichtbare Rufzeichen einschließlich eines vorhandenen Suffixes und die Chat-Kategorie der ausgewählten Station beibehalten. Ein Ziel wie `9A0BB-70` wird nicht auf `9A0BB` verkürzt.
|
||||
### MYQTF-Feld *(für v1.3)*
|
||||
|
||||
Eine Hintergrundaktualisierung, Neusortierung oder Filteränderung darf einen bereits bearbeiteten Nachrichtentext nicht überschreiben. Nur eine tatsächliche Auswahl durch den Operator bereitet den `/cq`-Empfänger erneut vor.
|
||||
|
||||
- **TX** oder `Enter` sendet den vorbereiteten Text.
|
||||
- `Esc` leert das Sendfeld.
|
||||
- Während KST4Contest nicht vollständig mit ON4KST verbunden ist, bleiben Sendfeld und **TX** deaktiviert.
|
||||
|
||||
Shortcuts, Snippets und Variablen sind unter [Makros und Variablen](de-Makros-und-Variablen) beschrieben.
|
||||
|
||||
### MYQRG- und SECONDQRG-Feld
|
||||
|
||||
Die beiden QRG-Felder enthalten die eigenen Frequenzen der primären und sekundären Chat-Kategorie.
|
||||
|
||||
`MYQRG` kann von einer aktivierten TRX-Synchronisation aktualisiert oder – bei deaktivierten automatischen QRG-Quellen – von Hand eingetragen werden. `SECONDQRG` bleibt davon unabhängig und enthält die QRG der zweiten Kategorie.
|
||||
|
||||
Die Auswahl einer Station aus dem zweiten Chat verändert die Bedeutung der beiden Werte nicht: `MYQRG` gehört weiterhin zur primären, `SECONDQRG` zur sekundären Kategorie.
|
||||
|
||||
Weitere Einzelheiten: [TRX-Sync-Einstellungen](de-Konfiguration#trx-sync-einstellungen).
|
||||
|
||||
### MYQTF-Feld
|
||||
|
||||
Das MYQTF-Feld zeigt die aktuelle Antennenrichtung als numerischen Winkel in Grad.
|
||||
|
||||
Ist PSTRotator aktiviert, wird der Wert automatisch übernommen und das Feld ist nicht manuell bearbeitbar. Ohne aktive Rotatorsynchronisation kann die Antennenrichtung direkt eingetragen werden. Die Änderung wird beim Verlassen des Feldes übernommen.
|
||||
|
||||
Der Wert beeinflusst unter anderem:
|
||||
|
||||
- die QTF-Filterung,
|
||||
- die Darstellung des Antennensektors auf der Stationskarte,
|
||||
- die Prioritätsberechnung,
|
||||
- die AP-Timeline und
|
||||
- die Variable `MYQTF`.
|
||||
Eingabefeld für die aktuelle Antennenrichtung. Wird für die geplante `MYQTF`-Variable verwendet.
|
||||
|
||||
---
|
||||
|
||||
@@ -159,77 +86,27 @@ Damit muss der Divider nicht allein deshalb verschoben werden, um eine einzelne
|
||||
|
||||
---
|
||||
|
||||
## Filter und Reachability-Steuerung
|
||||
## Filter
|
||||
|
||||
Die Filterleiste befindet sich oberhalb der Chatmember-Tabelle. Filter können miteinander kombiniert werden; eine Station bleibt nur sichtbar, wenn sie alle aktiven Bedingungen erfüllt.
|
||||
Die Filterleiste befindet sich oberhalb der Chatmember-Tabelle. Sie ist in mehrere logisch zusammengehörige Bereiche gegliedert:
|
||||
|
||||
- **Show only QTF** begrenzt die Liste auf eine gewählte Antennenrichtung.
|
||||
- **Show only QRB [km] <=** setzt eine maximale Entfernung.
|
||||
- **Find** sucht nach einem Rufzeichen.
|
||||
- **wkd** blendet Rufzeichen aus, die bereits auf mindestens einem Band gearbeitet wurden.
|
||||
- Die einzelnen Band-Schaltflächen blenden eine Station aus, wenn sie auf dem betreffenden Band bereits gearbeitet oder dort als NOT QRV markiert wurde. Angezeigt werden nur die für die eigene Station aktivierten Bänder.
|
||||
- **Only new grids** zeigt ausschließlich Stationen aus vierstelligen Großfeldern, die auf noch keinem Band gearbeitet wurden.
|
||||
- **Grid color** ist kein Filter. Die Funktion markiert das QRA-Feld bereits gearbeiteter Großfelder, ohne Stationen auszublenden.
|
||||
- **New bands** zeigt Stationen mit mindestens einer erkannten, an der eigenen Station aktivierten und noch nicht gearbeiteten Bandmöglichkeit. NOT-QRV-Markierungen haben Vorrang.
|
||||
- **Reachability**, **Tropo >=0dB** und **AS next 5m** schränken die Liste anhand der gewählten Strecken- beziehungsweise AirScout-Bedingungen ein.
|
||||
|
||||
Die Filterleiste besitzt keine feste Breite. QTF sowie die Worked- und Reachability-Filter nutzen zunächst den gesamten Platz ihrer jeweiligen Zeile. Wird der horizontale Divider nach rechts verschoben und die Chatmember-Ansicht dadurch schmaler, wechseln die Controls erst dann in die nächste Zeile, wenn ihre tatsächlich benötigte Breite nicht mehr zur Verfügung steht.
|
||||
|
||||

|
||||
|
||||
### Stationsfilter
|
||||
|
||||
| Bedienelement | Wirkung |
|
||||
|---|---|
|
||||
| **Show only QTF** | Zeigt nur Stationen innerhalb der gewählten Antennenrichtung und des konfigurierten Öffnungswinkels |
|
||||
| **Show only QRB [km] <=** | Begrenzt die Liste auf die eingetragene maximale Entfernung |
|
||||
| **Find** | Filtert nach einem vollständigen oder teilweisen Rufzeichen |
|
||||
| **wkd** | Blendet Basisrufzeichen aus, die bereits auf mindestens einem unterstützten Band gearbeitet wurden |
|
||||
| einzelne Band-Schaltflächen | Blenden Stationen aus, die auf dem betreffenden Band bereits gearbeitet oder dort als NOT QRV markiert wurden |
|
||||
| **Inactive stations** | Blendet Stationen aus, deren letzte Chataktivität mehr als 20 Minuten zurückliegt |
|
||||
| **Only new grids** | Zeigt nur Stationen aus vierstelligen Großfeldern, die bisher auf keinem Band gearbeitet wurden |
|
||||
| **New bands** | Zeigt Stationen mit mindestens einer erkannten, lokal aktivierten und noch nicht gearbeiteten Bandmöglichkeit |
|
||||
| **Tropo >=0dB** | Zeigt Stationen mit einer berechneten, nicht negativen SSB-Marge |
|
||||
| **AS next 5m** | Zeigt Stationen mit einem aktuellen oder innerhalb der nächsten fünf Minuten erwarteten AirScout-Fenster |
|
||||
|
||||
Bei **New bands** werden aktuelle QRGs, Bandangaben im Namensfeld und aktive Rufzeichenvarianten gemeinsam ausgewertet. Manuelle NOT-QRV-Markierungen haben Vorrang.
|
||||
|
||||
Der Filter **Tropo >=0dB** entfernt nur Stationen, für die eine abgeschlossene Berechnung eine negative Marge ergeben hat. Noch nicht berechnete oder fehlgeschlagene Auswertungen bleiben sichtbar. Andernfalls würde ein fehlender API-Wert wie ein nachgewiesen ungeeigneter Funkweg behandelt.
|
||||
|
||||
### Grid color
|
||||
|
||||
**Grid color** ist kein Filter. Die Funktion verändert ausschließlich die Darstellung des QRA-Feldes und kennzeichnet bereits gearbeitete vierstellige Großfelder.
|
||||
|
||||
Die Station bleibt unabhängig von der Farbmarkierung in der Tabelle sichtbar. **Reset filters** deaktiviert diese Anzeige deshalb nicht.
|
||||
|
||||
### Reachability und Calc selected
|
||||
|
||||
Das Dropdown **Reachability** bestimmt das Band, auf das sich die Tropo-Spalte, der Tropo-Filter und eine ausdrücklich gestartete Streckenberechnung beziehen.
|
||||
|
||||
- **Auto** leitet das Band aus der aktuellen Stations-QRG, Bandangaben im Namensfeld und der unterstützten Chat-Kategorie her.
|
||||
- Ein ausdrücklich gewähltes Band übersteuert diese automatische Auswahl für die Reachability-Auswertung.
|
||||
|
||||
Eine Änderung des Dropdowns startet keine Berechnung für die gesamte Benutzerliste. Das wäre bei einer Online-Höhendatenquelle unnötig langsam und würde externe API-Abfragen vervielfachen.
|
||||
|
||||
**Calc selected** berechnet ausschließlich die aktuell ausgewählte Station auf dem gewählten beziehungsweise automatisch hergeleiteten Band. Das Ergebnis wird anschließend in der Tropo-Spalte und den zugehörigen Ansichten verwendet.
|
||||
|
||||
### Filter zurücksetzen
|
||||
|
||||
**Reset filters** entfernt:
|
||||
|
||||
- den QTF-Filter,
|
||||
- den QRB-Filter,
|
||||
- den Inhalt des Rufzeichen-Suchfeldes,
|
||||
- alle Worked- und Bandfilter,
|
||||
- **Inactive stations**,
|
||||
- **Only new grids**,
|
||||
- **New bands**,
|
||||
- **Tropo >=0dB** und
|
||||
- **AS next 5m**.
|
||||
|
||||
Die internen Filterprädikate werden dabei ausdrücklich geleert. Es genügt nicht, lediglich die sichtbaren Toggle-Buttons zurückzusetzen.
|
||||
|
||||
Nicht verändert werden:
|
||||
|
||||
- **Grid color**, weil es sich um eine Darstellungsoption handelt, und
|
||||
- die Auswahl im **Reachability**-Dropdown, weil sie das Berechnungsband festlegt und nicht unmittelbar die Tabelle filtert.
|
||||
|
||||
### Verhalten bei schmaler Ansicht
|
||||
|
||||
Die Filterleiste besitzt keine feste Breite. QTF-, Worked- und Reachability-Controls nutzen zunächst den verfügbaren Platz ihrer jeweiligen Zeile.
|
||||
|
||||
Wird der mittlere Divider nach rechts verschoben und die Chatmember-Ansicht dadurch schmaler, wechseln Bedienelemente erst dann in die nächste Zeile, wenn ihre tatsächlich benötigte Breite nicht mehr ausreicht. Wird der Bereich wieder breiter, ordnen sie sich unmittelbar neu an.
|
||||
|
||||
Im Klartext: Die Filter bestimmen den Tabelleninhalt, aber nicht mehr die Mindestbreite der gesamten rechten Programmseite.
|
||||
Im Klartext: Die Filter bestimmen weiterhin den Inhalt der Tabelle, aber nicht mehr die Mindestbreite der gesamten rechten Programmseite. In der normalen Ansicht bleibt die Leiste kompakt. Erst bei einer tatsächlich schmalen Ansicht benötigt sie mehr Höhe. Der Divider kann anschließend wieder nach links verschoben werden; die Controls ordnen sich unmittelbar neu an.
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
## Stationsinfo-Panel (Further Info)
|
||||
@@ -305,67 +182,28 @@ Herleitung und Grenzen: [Prioritätsscore und Prioritätsliste](de-Funktionen#pr
|
||||
Die Stationskarte kann auf zwei Wegen geöffnet werden:
|
||||
|
||||
- **Windows → Show / hide station map** öffnet oder schließt das Kartenfenster.
|
||||
- **Show on map** im **Further Info**-Bereich öffnet die Karte und fokussiert die ausgewählte Station.
|
||||
- **Show on map** im **Further Info**-Bereich öffnet die Karte und zentriert sie auf die ausgewählte Station.
|
||||
|
||||
Die Karte verwendet die Stationen, die nach Anwendung der aktuellen Benutzerlistenfilter noch sichtbar sind. Die Kopfzeile zeigt die Anzahl der dargestellten Stationen und weist mit `filtered view active` auf eine gefilterte Ansicht hin.
|
||||
Die Karte zeigt die Stationen, die auch nach Anwendung der aktuellen Benutzerlistenfilter noch sichtbar sind. Ein Hinweis in der Kopfzeile zeigt an, wenn eine gefilterte Ansicht aktiv ist.
|
||||
|
||||

|
||||
|
||||
### Station auswählen
|
||||
Ein einzelner Stationsmarker kann direkt angeklickt werden. KST4Contest übernimmt die Station daraufhin als aktuelle Auswahl, scrollt die Benutzerliste zum passenden Chatmember und aktualisiert den **Further Info**-Bereich.
|
||||
|
||||
Ein einzelner Stationsmarker kann direkt angeklickt werden. KST4Contest:
|
||||
Marker, die bei der aktuellen Zoomstufe zu dicht beieinanderliegen, werden als Cluster mit einer Stationsanzahl angezeigt. Ein Klick auf einen Cluster vergrößert den betreffenden Kartenausschnitt. Erst ein anschließend sichtbarer einzelner Marker wählt eine konkrete Station aus.
|
||||
|
||||
1. übernimmt den konkreten Chatmember als aktuelle Auswahl,
|
||||
2. scrollt die Benutzerliste zum entsprechenden Eintrag,
|
||||
3. aktualisiert den **Further Info**-Bereich und
|
||||
4. bereitet das vollständige sichtbare Rufzeichen als `/cq`-Empfänger vor.
|
||||
Für die ausgewählte Station erscheinen rechts unter **Selected station**:
|
||||
|
||||
Marker, die bei der aktuellen Zoomstufe zu dicht beieinanderliegen, werden als Cluster mit einer Stationsanzahl dargestellt. Ein Klick auf einen Cluster vergrößert den betreffenden Kartenausschnitt. Erst ein anschließend sichtbarer einzelner Marker wählt eine konkrete Station aus.
|
||||
|
||||
Die Kopfzeile ergänzt bei ausgewählter Station:
|
||||
|
||||
- vollständiges Rufzeichen,
|
||||
- Rufzeichen,
|
||||
- Locator,
|
||||
- QRB und QTF,
|
||||
- erkannte aktive Bänder,
|
||||
- eine gegebenenfalls vorhandene `B+`-Bandmöglichkeit und
|
||||
- gegebenenfalls `B+` für eine offene Bandmöglichkeit und
|
||||
- die zuletzt bekannten QRGs.
|
||||
|
||||
Lange Inhalte werden in der Kopfzeile gekürzt. Der vollständige Text steht im Tooltip.
|
||||
**Trigger cluster spot** sendet für die ausgewählte Station einen einzelnen Spot an die mit dem integrierten DX-Cluster-Server verbundenen Logprogramme. Die Schaltfläche setzt deshalb einen aktivierten Cluster-Server und mindestens einen verbundenen Client voraus.
|
||||
|
||||
### Auswahl mit Reset view löschen
|
||||
|
||||
**Reset view** löscht die Stationsauswahl, ohne die Kartenposition oder den Zoomlevel zu verändern.
|
||||
|
||||
Dabei werden:
|
||||
|
||||
- die ausgewählte Station zurückgesetzt,
|
||||
- die Auswahl in der Benutzerliste aufgehoben,
|
||||
- die Verbindungslinie zur Gegenstation entfernt,
|
||||
- eine noch laufende Auswertung der vorherigen Station verworfen und
|
||||
- der rechte Analysebereich entfernt.
|
||||
|
||||
Die Karte selbst bleibt im zuvor gewählten Ausschnitt. Die Funktion ist deshalb kein geografischer Reset auf den eigenen Standort.
|
||||
|
||||

|
||||
|
||||
Wird anschließend wieder ein einzelner Marker gewählt, erscheinen Stationsauswahl und Analysebereich erneut.
|
||||
|
||||
### DX-Cluster-Spot auslösen
|
||||
|
||||
**Trigger cluster spot** erscheint nur bei ausgewählter Station. Die Schaltfläche sendet einen einzelnen Spot an die mit dem integrierten DX-Cluster-Server verbundenen Logprogramme.
|
||||
|
||||
Vorausgesetzt werden:
|
||||
|
||||
- ein aktivierter lokaler DX-Cluster-Server,
|
||||
- mindestens ein verbundener Cluster-Client und
|
||||
- eine für die ausgewählte Station verwendbare QRG.
|
||||
|
||||
Der Spot wird nicht an einen öffentlichen Internet-Cluster gesendet.
|
||||
|
||||
### Streckenanalyse
|
||||
|
||||
Unterhalb der Karte befindet sich das Höhenprofil. Der rechte Analysebereich zeigt unter anderem:
|
||||
Unterhalb der Karte befindet sich das Höhenprofil. Rechts werden die dazugehörigen Detailwerte angezeigt, unter anderem:
|
||||
|
||||
- verwendete Datenquelle und Anzahl der Höhenpunkte,
|
||||
- Analysefrequenz,
|
||||
@@ -374,28 +212,18 @@ Unterhalb der Karte befindet sich das Höhenprofil. Der rechte Analysebereich ze
|
||||
- Fresnel-Freiheit,
|
||||
- erkannte Hindernisse,
|
||||
- Link-Budget,
|
||||
- geschätzten Empfangspegel und
|
||||
- geschätzter Empfangspegel und
|
||||
- eine zusammenfassende Pfadbewertung.
|
||||
|
||||
Die Auswertung verwendet dasselbe zentral hergeleitete Band wie die Reachability-Funktionen. Ein im **Reachability**-Dropdown ausdrücklich gewähltes Band wird berücksichtigt.
|
||||
|
||||
Die Werte bleiben technische Abschätzungen. Gebäude, Bewuchs, lokale Abschattungen, aktuelle Ausbreitungsbedingungen und nicht bekannte Stationsparameter können das reale Ergebnis deutlich verändern.
|
||||
|
||||
### Streckenanalyse ausblenden
|
||||
|
||||
Mit **Hide path analysis** werden Höhenprofil und rechter Analysebereich gemeinsam ausgeblendet. Der Kartenbereich erhält dadurch mehr Platz.
|
||||
Mit **Hide path analysis** werden das Profil unterhalb der Karte und die ausführlichen Analysewerte rechts gemeinsam ausgeblendet. Der Kartenbereich erhält dadurch mehr Platz.
|
||||
|
||||

|
||||
|
||||
Der Hinweis **Path analysis is hidden** und die Schaltfläche **Show path analysis** bleiben sichtbar. Die Funktion kann daher ohne Umweg wieder eingeschaltet werden.
|
||||
Der Hinweis **Path analysis is hidden** bleibt zusammen mit **Show path analysis** sichtbar. Die Funktion kann daher ohne Umweg wieder eingeschaltet werden. Der Zustand wird gespeichert.
|
||||
|
||||
Ist beim Wiedereinblenden keine Station ausgewählt, erscheint kein leerer rechter Bereich. Er wird erst wieder aufgebaut, nachdem eine konkrete Station gewählt wurde.
|
||||
Der Divider zwischen Karte und Detailbereich lässt sich horizontal verschieben. Bei schmalem Detailbereich werden längere Angaben umgebrochen; falls die Höhe nicht ausreicht, erscheint dort eine vertikale Scrollleiste.
|
||||
|
||||
Die Auswahl wird gespeichert und beim nächsten Programmstart wiederhergestellt.
|
||||
|
||||
Der Divider zwischen Karte und Detailbereich lässt sich horizontal verschieben. Bei einem schmalen Detailbereich werden längere Angaben umgebrochen; reicht die verfügbare Höhe nicht aus, erscheint eine vertikale Scrollleiste.
|
||||
|
||||
Ausführliche Herleitung und Grenzen: [Stationskarte und Streckenanalyse](de-Funktionen#stationskarte-und-streckenanalyse-ab-v141).
|
||||
Ausführliche Herleitung und Grenzen: [Stationskarte und Streckenanalyse](de-Funktionen#stationskarte-und-streckenanalyse-ab-v141)
|
||||
|
||||
---
|
||||
|
||||
@@ -442,29 +270,12 @@ Herleitung und Grenzen: [Globale Nachrichtenansichten](de-Funktionen#globale-nac
|
||||
|
||||
## Menü
|
||||
|
||||
### File
|
||||
|
||||
- **Connect to …** startet die Verbindung mit den bereits übernommenen Einstellungen.
|
||||
- **Disconnect** beendet die aktuelle ON4KST-Verbindung, ohne KST4Contest zu schließen.
|
||||
- **Exit + disconnect** beendet die Verbindung und anschließend das Programm.
|
||||
|
||||
Die Connect- und Disconnect-Einträge werden entsprechend dem aktuellen Verbindungszustand aktiviert oder deaktiviert.
|
||||
|
||||
### Options
|
||||
|
||||
- **Set QRG as name in Chat (main category)** sendet `/SETNAME` mit der aktuellen `MYQRG` an die primäre Chat-Kategorie.
|
||||
- **Show me as away in chat** sendet `/AWAY`.
|
||||
- **Show me as active in chat** sendet `/BACK`.
|
||||
- **Show options** blendet das Einstellungsfenster ein beziehungsweise aus.
|
||||
|
||||
Die serverbezogenen Funktionen sind nur bei vollständig aufgebauter ON4KST-Verbindung verfügbar.
|
||||
|
||||
### Windows
|
||||
|
||||
- **Hide cluster / stranger QSOs** beziehungsweise **Show cluster / stranger QSOs** blendet das zusätzliche Cluster- und QSO-Monitorfenster aus oder wieder ein.
|
||||
- **hide options** beziehungsweise **show options** blendet das Einstellungsfenster aus oder wieder ein.
|
||||
- **Use dark mode design** aktiviert das dunkle Farbschema.
|
||||
- **Use default mode design** aktiviert das normale helle Farbschema.
|
||||
- **Hide cluster / stranger QSOs** beziehungsweise **Show cluster / stranger QSOs**: Blendet das zusätzliche Cluster- und QSO-Monitorfenster aus oder wieder ein.
|
||||
- **hide options** beziehungsweise **show options**: Blendet das Einstellungsfenster aus oder wieder ein.
|
||||
- **Use dark mode design**: Aktiviert das dunkle Farbschema.
|
||||
- **Use default mode design**: Aktiviert das normale helle Farbschema.
|
||||
- **Show / hide station map** öffnet beziehungsweise schließt das separate Fenster mit Stationskarte und Streckenanalyse.
|
||||
|
||||
---
|
||||
|
||||
@@ -10,15 +10,13 @@ Die veröffentlichten Stable-Versionen und ihre Programmpakete stehen unter [Git
|
||||
|
||||
## v1.42 – Nightly / in Entwicklung
|
||||
|
||||
> Stand dieses Abschnitts: 14. August 2026.
|
||||
> Stand dieses Abschnitts: 10. August 2026.
|
||||
> v1.42 ist noch kein veröffentlichtes Stable-Release. Bis zur Freigabe können weitere Änderungen hinzukommen.
|
||||
|
||||
v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen, Worked-Status, NOT-QRV-Markierungen, Rufzeichensuffixe und Frequenzen werden dadurch konsistenter in der Benutzerliste, der Stationskarte, der Prioritätsberechnung und den externen Schnittstellen verwendet.
|
||||
|
||||
### Neu
|
||||
|
||||
- **Sichtbarer ON4KST-Verbindungsstatus:** Ein kompakter `LINK`-Indicator im Hauptfenster zeigt den tatsächlichen Zustand der ON4KST-Verbindung an. Grün bedeutet vollständig angemeldet und synchronisiert, Gelb kennzeichnet Verbindungsaufbau und Synchronisation, Rot eine unterbrochene Verbindung, einen Fehler oder die Wartezeit vor dem nächsten Verbindungsversuch.
|
||||
|
||||
- **Gemeinsame Herleitung verfügbarer Bänder:** Ein zentraler `BandOpportunityResolver` wertet aktuelle QRGs, Bandangaben im Namensfeld, aktive Rufzeichenvarianten, Worked-Informationen und NOT-QRV-Markierungen gemeinsam aus. Benutzerliste, **New bands**, Band-Upgrade-Hinweis, Priority Score, Stationskarte und automatische Bandauswahl verwenden damit dieselbe Grundlage.
|
||||
|
||||
- **Erweiterte Bandanzeige:** Die Bandspalten unterscheiden jetzt:
|
||||
@@ -43,10 +41,6 @@ v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen,
|
||||
|
||||
### Geändert
|
||||
|
||||
- **Sessionbezogene ON4KST-Verbindungssteuerung:** Socket, Reader, Writer, Messagebus und Warteschlangen gehören jetzt zu einer eindeutig identifizierten Verbindungssession. Veraltete Threads einer abgelösten Verbindung können dadurch keine Daten mehr verarbeiten oder die neue Verbindung schließen. `ONLINE` wird erst nach bestätigtem Login und vollständig empfangenen Benutzerlisten gemeldet. Verbindungsaufbau, Login und Synchronisation besitzen feste Zeitlimits; Heartbeats, ausbleibende Eingangsdaten, EOF sowie Lese- und Schreibfehler werden überwacht und lösen bei Bedarf einen kontrollierten Neuaufbau mit Backoff aus.
|
||||
|
||||
- **ON4KST-Protokollbefehle abgesichert:** Ausgehende Befehle werden zentral aufgebaut und auf gültige Kategorien, Locatoren und unerlaubte Frame-Trennzeichen geprüft. Da ON4KST pro TCP-Session nur einen Locator verwaltet, wird für beide Chat-Kategorien der Hauptlocator verwendet und eine abweichende zweite Konfiguration protokolliert, statt widersprüchliche Befehle an den Server zu senden.
|
||||
|
||||
- **QRG-Erkennung präzisiert:** Vollständige und relative Frequenzangaben werden weiterhin erkannt. Nackte dreistellige Zahlen gelten nur noch bei erkennbarem Frequenzkontext als QRG. Signalrapporte, Bandangaben und andere Zahlen erzeugen dadurch seltener falsche Frequenzen.
|
||||
|
||||
- **Stationsbezogener Frequenzkontext:** Bei relativen QRGs verwendet KST4Contest zuerst einen höchstens 30 Minuten alten Bandkontext derselben Station. Erst wenn dieser fehlt, wird das global konfigurierte Fallback-Band verwendet.
|
||||
@@ -85,16 +79,6 @@ v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen,
|
||||
|
||||
### Behoben
|
||||
|
||||
- **Zuverlässige Benutzerliste beim Login:** Ungültige oder unvollständige `UA0`-Teilnehmerdatensätze werden einzeln verworfen und protokolliert, ohne die Verarbeitung der alphabetisch folgenden Teilnehmer abzubrechen. Die gültigen Einträge werden zunächst pro Kategorie gesammelt und erst mit dem ersten zugehörigen `UE`-Abschlussframe vollständig veröffentlicht.
|
||||
|
||||
- **Benutzerliste verschwindet nach dem Login:** ON4KST kann nach Namens-, Status- oder anderen Live-Änderungen weitere `UE`-Frames für dieselbe Kategorie senden. Wiederholte Abschlussframes werden jetzt erkannt und ignoriert, damit eine bereits gefüllte Benutzerliste nicht durch eine leere Momentaufnahme ersetzt wird.
|
||||
|
||||
- **Fehlgeschlagener Erstaufbau und Verbindungsverlust:** Wenn beim Programmstart keine Verbindung zum Server hergestellt werden kann, läuft KST4Contest nicht mehr in eine Endlos- oder Busy-Wait-Schleife. Die Oberfläche bleibt bedienbar und weitere Versuche erfolgen mit begrenztem Backoff. Auch ein vom Server geschlossener oder über längere Zeit stummer Socket wird zuverlässig erkannt.
|
||||
|
||||
- **Messagebus-Protokollierung:** Bereits korrekt verarbeitete ON4KST-Frames werden nicht mehr zusätzlich als `Critical, detected unhandled Chatmessage` gemeldet. Nur tatsächlich unbekannte Telegramme erreichen noch diesen Logzweig.
|
||||
|
||||
- **Passwort im Fehlerlog:** Das ON4KST-Passwort wird beim Verbindungsaufbau nicht mehr im Klartext in die Konsole oder Logdatei geschrieben.
|
||||
|
||||
- **Langzeitfehler der Stationsauswahl:** Die vom Message-Thread verwalteten Chatmember wurden von der JavaFX-Ansicht entkoppelt. Gleichzeitige Änderungen der Daten und Tabellenansicht führen dadurch nicht mehr nach längerer Laufzeit zu fehlerhaften Auswahlmodellen oder Concurrent-Modification-Problemen.
|
||||
|
||||
- **Keine Phantom-Chatmember durch UM3:** Historische oder zusätzliche Servermeldungen erzeugen keine Benutzerlisteneinträge für Stationen, die nicht tatsächlich im Chat angemeldet sind.
|
||||
|
||||
@@ -143,17 +143,15 @@ Mehrere DX-Cluster-Clients können gleichzeitig verbunden werden. Ein erzeugter
|
||||
|
||||
## Verbindung testen
|
||||
|
||||
Die Schaltfläche **Send test spot** erzeugt folgenden Testeintrag:
|
||||
Die Schaltfläche **Send test spot** erzeugt einen neutralen Testeintrag:
|
||||
|
||||
```text
|
||||
Spotted callsign: DO5AMF
|
||||
Comment: Testing DXC-Spot: Congrats, you donated $100!
|
||||
Comment: KST4CONTEST TEST
|
||||
Frequency: .300 des konfigurierten Fallback-Bandes
|
||||
```
|
||||
|
||||
Bei einem Fallback-Band von `144 MHz` erscheint der Spot daher auf ungefähr `144.300 MHz`.
|
||||
|
||||
Der Kommentar ist ein bewusst beibehaltenes Easteregg. Er dient ausschließlich dazu, den Testspot im Logprogramm eindeutig wiederzuerkennen. Eine tatsächliche Spende oder sonstige externe Aktion wird dadurch selbstverständlich nicht ausgelöst.
|
||||
Bei einem Fallback-Band von `144` erscheint der Spot daher auf ungefähr `144.300 MHz`.
|
||||
|
||||
Vor dem Test müssen drei Bedingungen erfüllt sein:
|
||||
|
||||
|
||||
@@ -277,13 +277,9 @@ Nicht jede im ON4KST-Chat eingeloggte Station nimmt am gerade laufenden Contest
|
||||
|
||||
KST4Contest kann darauf mit einem vorher festgelegten Text reagieren. Die eingehende Privatnachricht bleibt dabei sichtbar; sie wird weder blockiert noch verworfen. Davon getrennt lässt sich eine QRG-Antwort aktivieren, die auf typische Fragen wie `qrg?`, `freq?` oder `pse qrg` reagiert.
|
||||
|
||||
Bei zwei gleichzeitig geöffneten Chat-Kategorien bleibt der Zusammenhang erhalten: Die Antwort wird an das vollständige Absenderrufzeichen und in der Kategorie der eingegangenen Nachricht gesendet. Eine QRG-Anfrage erhält außerdem nur die QRG dieser Kategorie und nicht eine Liste aller konfigurierten Frequenzen.
|
||||
Bei zwei gleichzeitig geöffneten Chat-Kategorien bleibt der Zusammenhang erhalten: Die Antwort wird in der Kategorie der eingegangenen Nachricht gesendet. Eine QRG-Anfrage erhält außerdem nur die QRG dieser Kategorie und nicht eine Liste aller konfigurierten Frequenzen.
|
||||
|
||||
Fehlt die QRG der betreffenden Kategorie, sendet KST4Contest keine inhaltslose Auskunft. Auch ein leerer oder protokollwidriger allgemeiner Antworttext wird nicht in die Sendequeue übernommen.
|
||||
|
||||
Automatische Antworten benötigen Grenzen. KST4Contest versieht sie daher mit `[KST4C Automsg]`, ignoriert entsprechend gekennzeichnete Nachrichten und begrenzt weitere Antworten an dasselbe vollständige Rufzeichen in derselben Kategorie auf eine Nachricht innerhalb von zwei Minuten. Der Schutz gilt gemeinsam für die allgemeine und die QRG-bezogene Antwort.
|
||||
|
||||
Die Sperrzeit wird nur nach einer vollständigen und lokal gültigen Antwort gestartet. Eine fehlende QRG oder ein verworfener Antworttext verhindert daher keine spätere gültige Antwort.
|
||||
Automatische Antworten benötigen Grenzen. KST4Contest versieht sie daher mit `[KST4C Automsg]`, ignoriert entsprechend gekennzeichnete Nachrichten bei der allgemeinen und QRG-bezogenen Antwort und begrenzt weitere Antworten an dieselbe Station in derselben Kategorie auf eine Nachricht innerhalb von zwei Minuten. Der Schutz gilt gemeinsam für beide Antwortarten.
|
||||
|
||||
Im Klartext: Die Funktion verhindert keine Massenanfragen. Sie verhindert aber, dass der Empfänger jede davon einzeln mit derselben Absage beantworten muss. Sie soll keine Unterhaltung simulieren und erst recht keine endlose Diskussion mit einem zweiten automatischen Client beginnen.
|
||||
|
||||
@@ -291,7 +287,6 @@ Konfiguration, erkannte QRG-Anfragen und genaue Kategorienzuordnung: [Konfigurat
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Multi-Channel-Login (ab v1.26)
|
||||
|
||||
Gleichzeitiger Login in **zwei Chat-Kategorien** (z. B. 144 MHz und 432 MHz). Beide Chats werden parallel überwacht.
|
||||
@@ -401,49 +396,12 @@ Win-Test-Übergabe: [Log-Synchronisation – Win-Test](de-Log-Synchronisation#wi
|
||||
|
||||
## QSO-Monitoring (ab v1.31)
|
||||
|
||||
Während eines Contests kann es sinnvoll sein, die Kommunikation einer bestimmten Station zu verfolgen. Das betrifft nicht nur seltene Stationen oder DXpeditionen. Auch die Sked-Absprachen einer anderen Station des eigenen Teams können im öffentlichen Nachrichtenaufkommen schnell übersehen werden.
|
||||
Für ausgewählte Rufzeichen kann KST4Contest gerichtete Nachrichten zusätzlich in der PM-Tabelle anzeigen. Dabei werden sowohl Nachrichten berücksichtigt, die das überwachte Rufzeichen sendet, als auch Nachrichten, die an dieses Rufzeichen gerichtet sind.
|
||||
|
||||
KST4Contest kann deshalb alle Nachrichten, die eine überwachte Station sendet oder empfängt, zusätzlich in der PM-Tabelle anzeigen. Die Nachricht bleibt gleichzeitig in ihrer ursprünglichen Tabelle erhalten.
|
||||
|
||||
Die Überwachung arbeitet mit dem normalisierten Basisrufzeichen. Ein Eintrag für `DN9APW` erfasst daher auch Nachrichten von oder an:
|
||||
|
||||
```text
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
DN9APW-144
|
||||
DN9APW-432
|
||||
```
|
||||
|
||||
Auch wenn `DN9APW-70` in die Monitoring-Liste eingegeben wird, speichert KST4Contest nur `DN9APW`. Eine Station mit mehreren band- oder arbeitsplatzbezogenen KST-Suffixen muss dadurch nur einmal eingetragen werden.
|
||||
|
||||
Die eigentliche Nachricht behält trotzdem die vollständigen Rufzeichen:
|
||||
|
||||
```text
|
||||
Sniffed: (DN9APW-70 > 9A0BB-23) pse sked 19:30
|
||||
```
|
||||
|
||||
Das ist ein wichtiger Unterschied. Das Monitoring fasst die Varianten zusammen, damit keine Nachricht übersehen wird. Das Nachrichtenrouting fasst sie nicht zusammen, weil andernfalls nicht mehr eindeutig wäre, welcher Login tatsächlich angesprochen wurde.
|
||||
|
||||
Das Basisrufzeichen wird außerdem unabhängig von der Chat-Kategorie ausgewertet. Ist KST4Contest gleichzeitig mit zwei Kategorien verbunden, gilt derselbe Monitoring-Eintrag für beide Nachrichtenströme. Die Kategorie der einzelnen Nachricht bleibt dabei erhalten.
|
||||
|
||||
Erfasst werden:
|
||||
|
||||
- gerichtete Nachrichten, die eine überwachte Station sendet,
|
||||
- gerichtete Nachrichten an eine überwachte Station und
|
||||
- öffentliche Nachrichten, die eine überwachte Station an `ALL` sendet.
|
||||
|
||||
Eine bloße Nennung des Rufzeichens im Nachrichtentext löst das Monitoring nicht aus.
|
||||
|
||||
Nachrichten, die bereits direkt an das eigene Rufzeichen gerichtet sind, erscheinen als normale Privatnachrichten. Sie werden nicht zusätzlich als `Sniffed:` gekennzeichnet. Das QSO-Monitoring erzeugt außerdem keinen eigenen Hinweiston. Die akustische Benachrichtigung für tatsächlich an die eigene Station gerichtete Privatnachrichten bleibt davon unabhängig.
|
||||
|
||||
Die Funktion fordert keine zusätzlichen Nachrichten vom ON4KST-Server an. Sie ordnet lediglich den bereits empfangenen Chatverkehr zusätzlich in die PM-Ansicht ein.
|
||||
|
||||
Im Klartext: Das QSO-Monitoring entscheidet nicht, ob eine Nachricht tatsächlich einen Sked enthält oder für den eigenen Contestbetrieb relevant ist. Es sorgt lediglich dafür, dass die Kommunikation der ausgewählten Station nicht zwischen den übrigen Nachrichten verschwindet.
|
||||
Die Nachricht bleibt gleichzeitig in ihrer ursprünglichen Tabelle erhalten und wird im PM-Fenster mit Absender und Empfänger als überwachte Kommunikation gekennzeichnet.
|
||||
|
||||
Konfiguration: [Konfiguration – Sniffer-Einstellungen](de-Konfiguration#sniffer-einstellungen-ab-v131)
|
||||
|
||||
Trennung vollständiger Rufzeichen und Chat-Kategorien: [Multi-Channel-Login und Rufzeichenvarianten](#multi-channel-login-ab-v126)
|
||||
|
||||
---
|
||||
|
||||
## Win-Test-Integration
|
||||
@@ -464,54 +422,14 @@ Einstellungen: [Win-Test-Netzwerk-Listener](de-Konfiguration#win-test-netzwerk-l
|
||||
|
||||
|
||||
|
||||
## PSTRotator-Interface (ab v1.31, vollständig konfigurierbar ab v1.40)
|
||||
## PSTRotator-Interface (ab v1.31, vollständig ab v1.40)
|
||||
|
||||
KST4Contest kann die Antenne über die UDP-Schnittstelle von PSTRotator auf die ausgewählte Gegenstation drehen. Der dafür verwendete Azimut wird aus dem eigenen und dem fremden Locator berechnet.
|
||||
KST4Contest kann die Antennenrichtung direkt über **PSTRotator** steuern. Wenn in der Benutzerliste eine Station ausgewählt wird, kann der Rotator automatisch auf den QTF zur ausgewählten Station gedreht werden.
|
||||
|
||||
Nach der Auswahl einer Station steht im **Further Info**-Bereich der Button **Turn ant1 to …** zur Verfügung:
|
||||
|
||||

|
||||
|
||||
Ein Klick führt folgende Schritte aus:
|
||||
|
||||
1. KST4Contest beendet den Tracking-Modus von PSTRotator.
|
||||
2. Der QTF der ausgewählten Station wird als ganzzahliger Azimut übertragen.
|
||||
3. PSTRotator steuert den konfigurierten Rotator.
|
||||
4. Die zurückgemeldete Position wird als aktuelle QTF in KST4Contest übernommen.
|
||||
|
||||
Der Button bleibt auch sichtbar, wenn die PSTRotator-Integration deaktiviert ist. In diesem Fall wird kein Rotatorbefehl gesendet.
|
||||
|
||||
### Rückmeldung und SPID-Kompatibilität
|
||||
|
||||
KST4Contest fragt die aktuelle Azimutposition alle zwei Sekunden ab. Die Rückmeldung aktualisiert das eigene QTF-Feld und damit alle Funktionen, die von der Antennenrichtung abhängen.
|
||||
|
||||
Einige SPID-Konfigurationen übernehmen den ersten Richtungsbefehl gelegentlich nicht. KST4Contest prüft deshalb zwei Sekunden nach dem Befehl, ob PSTRotator eine Bewegung beziehungsweise das Erreichen des Ziels gemeldet hat.
|
||||
|
||||
Ist die Position unverändert und wurde das Ziel nicht erreicht, sendet KST4Contest einmalig eine Kompatibilitätssequenz über `0°` und anschließend erneut den eigentlichen Zielwert.
|
||||
|
||||
Diese Prüfung läuft im Hintergrund. Die Benutzeroberfläche bleibt während der zwei Sekunden bedienbar. Wird zwischenzeitlich ein neuer Drehbefehl ausgelöst, ersetzt er die noch ausstehende Prüfung des vorherigen Befehls.
|
||||
|
||||
### Was bestätigt die Positionsanzeige?
|
||||
|
||||
Die angezeigte QTF ist die von PSTRotator gemeldete Azimutposition. Sie bestätigt, dass KST4Contest eine auswertbare UDP-Rückmeldung erhalten hat.
|
||||
|
||||
Sie beweist nicht in jedem Aufbau, dass die Antenne mechanisch exakt in dieser Richtung steht. Das hängt von PSTRotator, dem angeschlossenen Controller, der Kalibrierung, möglichen Offsets und der tatsächlichen Rückmeldung des Rotors ab.
|
||||
|
||||
UDP selbst bestätigt außerdem keine Paketzustellung. Bleibt die QTF unverändert, sollten daher zuerst folgende Punkte geprüft werden:
|
||||
|
||||
- **UDP Control** ist in PSTRotator aktiviert.
|
||||
- Host und Steuerport stimmen überein.
|
||||
- Der Rückmeldeport `Steuerport + 1` ist frei.
|
||||
- Die Firewall lässt beide UDP-Richtungen zu.
|
||||
- PSTRotator zeigt selbst eine plausible Rotorposition an.
|
||||
|
||||
Im Klartext: KST4Contest liefert die Zielrichtung und verarbeitet die gemeldete Position. Die mechanische Realität bleibt Aufgabe des Rotators – und gelegentlich der Blick aus dem Fenster.
|
||||
|
||||
Konfiguration und Portbelegung: [Konfiguration – PSTRotator-Einstellungen](de-Konfiguration#pstrotator-einstellungen-ab-v131-vollstaendig-konfigurierbar-ab-v140).
|
||||
Konfiguration: [Konfiguration – PSTRotator-Einstellungen](de-Konfiguration#pstrotator-einstellungen-ab-v131)
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Band-Upgrade-Hinweis nach einem Logeintrag
|
||||
|
||||
Meldet UCXLog oder Win-Test einen neuen Logeintrag mit Bandinformation, prüft KST4Contest, ob die gearbeitete Station noch ein weiteres gemeinsames Band anbietet.
|
||||
@@ -687,21 +605,13 @@ Die Timeline ist eine Vorschau. AirScout-Daten können sich ändern, und ein ein
|
||||
|
||||
## Intervall-Beacon
|
||||
|
||||
KST4Contest kann wiederkehrende CQ-Nachrichten in den öffentlichen Chat senden. Der Beacon ist für längeres CQ-Rufen auf einer festen Frequenz gedacht: Die eigene QRG wird regelmäßig veröffentlicht, ohne dass derselbe Text von Hand wiederholt werden muss.
|
||||
KST4Contest kann wiederkehrende CQ-Nachrichten in den öffentlichen Chat senden. Beide Chat-Kategorien verwenden ein gemeinsames Intervall, besitzen aber jeweils einen eigenen Aktivierungsschalter und Nachrichtentext. Globale Variablen wie `MYQRG`, `SECONDQRG` oder `MYLOCATOR` werden unmittelbar vor jeder Aussendung aktualisiert.
|
||||
|
||||
|
||||
Beide Chat-Kategorien verwenden ein gemeinsames Intervall, besitzen aber jeweils einen eigenen Aktivierungsschalter und Nachrichtentext. Der zweite Beacon wird nur gesendet, wenn auch der zweite Chat aktiviert und verbunden ist.
|
||||
|
||||
Globale Variablen wie `MYQRG`, `SECONDQRG`, `MYLOCATOR` oder `MYQTF` werden unmittelbar vor jeder Aussendung neu aufgelöst. Eine zwischenzeitlich vom Logprogramm aktualisierte QRG kann dadurch bereits im nächsten Beacon erscheinen.
|
||||
|
||||
Vor dem Versand prüft KST4Contest den vollständig aufgelösten Nachrichtentext. Leere Nachrichten, Zeilenumbrüche, das Protokoll-Trennzeichen `|` und Texte mit mehr als 120 Zeichen werden nicht gesendet.
|
||||
|
||||
Beim Absuchen oder häufigen Wechseln der QRG sollte der Beacon ausgeschaltet werden. Eine automatisch verbreitete Frequenz ist nur dann hilfreich, wenn dort tatsächlich jemand hört und ruft.
|
||||
|
||||
Konfiguration, Timer-Verhalten und verfügbare Variablen: [Konfiguration – Beacon Settings](de-Konfiguration#beacon-settings-automatischer-beacon).
|
||||
Der Beacon ist für längeres CQ-Rufen auf einer festen Frequenz gedacht. Beim Absuchen oder häufigen Wechseln der QRG sollte er ausgeschaltet werden, damit keine inzwischen falsche Frequenz verbreitet wird. Details: [Konfiguration – Beacon Settings](de-Konfiguration#beacon-settings-automatischer-beacon).
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Simplelogfile
|
||||
|
||||
Details: [Log-Synchronisation](de-Log-Synchronisation#methode-1-universal-file-based-callsign-interpreter-simplelogfile).
|
||||
|
||||
@@ -122,197 +122,18 @@ Dedizierter Netzwerk-Erkenner für Win-Test. KST4Contest empfängt und verarbeit
|
||||
|
||||
## TRX-Sync-Einstellungen
|
||||
|
||||
Die TRX-Synchronisation übernimmt die aktuelle Frequenz aus dem Logprogramm und stellt sie in KST4Contest als eigene QRG der ersten Chat-Kategorie bereit. QSO- und Frequenzsynchronisation verwenden teilweise denselben UDP-Empfänger, sind funktional aber voneinander getrennt: Ein empfangenes `RadioInfo`-Paket markiert keine Station als gearbeitet, und ein QSO-Paket ändert nicht automatisch die eigene QRG.
|
||||
Empfängt die aktuelle Frequenz des Transceivers vom Logprogramm via UDP. Ermöglicht die automatische Befüllung der Variable `MYQRG`. Nützlich für:
|
||||
|
||||

|
||||
- Schnelles Einfügen der eigenen QRG in Chat-Nachrichten.
|
||||
- Automatische CQ-Baken mit aktueller Frequenz.
|
||||
|
||||
### Verfügbare QRG-Quellen
|
||||
|
||||
| Quelle | Aktivierung | Verhalten |
|
||||
|---|---|---|
|
||||
| **Allgemeiner RadioInfo-Listener** | `Update MYQRG from RadioInfo messages received on the shared log-sync port` | Verarbeitet kompatible `RadioInfo`-Pakete auf dem gemeinsam mit der QSO-Synchronisation verwendeten UDP-Port. Der Standardport ist `12060`. |
|
||||
| **Win-Test STATUS** | `Win-Test STATUS QRG Sync` | Verarbeitet die Haupt- oder Pass-Frequenz aus nativen Win-Test-`STATUS`-Paketen. Der Win-Test-Listener verwendet seinen separat konfigurierten Port, standardmäßig `9871`. |
|
||||
| **Manuelle Eingabe** | Beide automatischen QRG-Quellen deaktivieren | Die eigene QRG kann im Hauptfenster von Hand eingetragen werden. |
|
||||
|
||||
Der allgemeine Listener ist für Logprogramme vorgesehen, die kompatible `RadioInfo`-Pakete senden. Dazu gehören – abhängig von deren jeweiliger Konfiguration – UCXLog, N1MM+, QARTest und DXLog.net. QSO- und `RadioInfo`-Pakete verwenden denselben unter **Log sync** konfigurierten Port. Dort wird jedoch getrennt festgelegt, ob KST4Contest QSO-Informationen, TRX-Informationen oder beide Paketarten verarbeitet.
|
||||
|
||||
Wird der gemeinsame UDP-Port geändert, muss KST4Contest neu gestartet werden. Eine reine Änderung der Checkboxen wird dagegen sofort berücksichtigt.
|
||||
|
||||
### Welche QRG wird aktualisiert?
|
||||
|
||||
Beide automatischen Quellen aktualisieren ausschließlich `MYQRG`. Das ist die eigene QRG der ersten beziehungsweise primären Chat-Kategorie.
|
||||
|
||||
Bei aktiviertem zweiten Chat bleibt dessen QRG davon unabhängig. Sie wird nicht aus den empfangenen TRX-Paketen abgeleitet und steht als `SECONDQRG` zur Verfügung. Dadurch kann beispielsweise die erste Kategorie automatisch der Frequenz des Logprogramms folgen, während für die zweite Kategorie eine eigene QRG von Hand eingetragen wird.
|
||||
|
||||
Sobald mindestens eine automatische QRG-Quelle aktiviert ist, wird das QRG-Feld der ersten Kategorie im Hauptfenster an den empfangenen Wert gebunden. Eine manuelle Eingabe in dieses Feld ist wieder möglich, wenn sowohl der allgemeine RadioInfo-Listener als auch die Win-Test-STATUS-Synchronisation deaktiviert sind.
|
||||
|
||||
### Haupt- oder Pass-Frequenz aus Win-Test
|
||||
|
||||
Standardmäßig verwendet KST4Contest die Hauptfrequenz des empfangenen Win-Test-`STATUS`-Pakets.
|
||||
|
||||
Die Option `Use pass frequency from Win-Test STATUS` verwendet stattdessen die im Paket enthaltene Pass-Frequenz. Das ist beispielsweise sinnvoll, wenn Win-Test im Split-Betrieb eine abweichende Frequenz führt und genau diese im Chat als Arbeitsfrequenz veröffentlicht werden soll.
|
||||
|
||||
Enthält das Paket keine gültige Pass-Frequenz, fällt KST4Contest automatisch auf die Hauptfrequenz zurück. Eine fehlende Pass-Frequenz löscht daher weder `MYQRG` noch ersetzt sie den Wert durch eine offensichtlich falsche Zahl.
|
||||
|
||||
Die Frequenzen werden einheitlich im KST4Contest-Format dargestellt, beispielsweise:
|
||||
|
||||
```text
|
||||
50.300.00
|
||||
144.300.00
|
||||
1296.100.00
|
||||
10368.100.00
|
||||
```
|
||||
|
||||
Die Werte werden erst beim Auflösen des Nachrichtentextes eingesetzt. Ändert das Logprogramm zwischen zwei Beacon-Läufen die Frequenz, verwendet die nächste Nachricht bereits den aktualisierten Wert.
|
||||
|
||||
Die eigene QRG kann außerdem als Fallback für die Übergabe eines Skeds an Win-Test verwendet werden. Das geschieht nur, wenn die QRG auswertbar ist und zum ausdrücklich ausgewählten Sked-Band gehört. Einzelheiten stehen unter [Log-Synchronisation](de-Log-Synchronisation#skeds-an-win-test-übergeben).
|
||||
|
||||
Weitere Informationen zu den Textvariablen: [Makros und Variablen](de-Makros-und-Variablen#variablen).
|
||||
|
||||
### Mehrere Logger oder Funkgeräte
|
||||
|
||||
Alle aktivierten QRG-Quellen schreiben in denselben Wert `MYQRG`. KST4Contest ordnet eingehende `RadioInfo`- oder `STATUS`-Pakete derzeit weder einem bestimmten Funkgerät noch einer Chat-Kategorie zu.
|
||||
|
||||
Sind der allgemeine RadioInfo-Listener und die Win-Test-Synchronisation gleichzeitig aktiviert, bestimmt deshalb das zuletzt verarbeitete Paket die angezeigte QRG. Dasselbe gilt, wenn mehrere Logger ihre Frequenzpakete an dieselbe KST4Contest-Instanz senden.
|
||||
|
||||
Für ein Setup mit mehreren Funkgeräten gilt daher:
|
||||
|
||||
- QSO-Pakete dürfen von mehreren Loggern empfangen werden.
|
||||
- Frequenzpakete sollten nur von der Quelle gesendet werden, die `MYQRG` tatsächlich steuern soll.
|
||||
- In einem Win-Test-Netzwerk sollte zusätzlich der Stationsfilter verwendet werden.
|
||||
- Werden zwei vollständig unabhängige QRG-Synchronisationen benötigt, sind zwei getrennte KST4Contest-Instanzen die eindeutigere Lösung.
|
||||
|
||||
Anders ausgedrückt: Mehrere Worked-Quellen lassen sich sinnvoll zusammenführen. Mehrere gleichzeitig sendende Frequenzquellen erzeugen dagegen keine zusätzliche Information, sondern lediglich einen Wettbewerb darum, welches Paket zuletzt angekommen ist.
|
||||
|
||||
Nach Abschluss der Konfiguration **Save Settings** verwenden.
|
||||
> **Hinweis für Multi-Setup**: Wenn zwei Logprogramme an zwei Computern betrieben werden, aber nur eine KST4Contest-Instanz, darf nur ein Logprogramm die Frequenzpakete senden. KST4Contest kann nicht zwischen den Quellen unterscheiden.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## AirScout-Einstellungen
|
||||
|
||||
Im Reiter **AirScout** wird die UDP-Verbindung zwischen KST4Contest und AirScout eingerichtet. KST4Contest fordert dort keine allgemeinen Flugzeugdaten an, sondern übermittelt die aktuell relevanten Stationspfade. AirScout berechnet die dazu passenden Flugzeuge und sendet das Ergebnis an die anfragende KST4Contest-Instanz zurück.
|
||||
|
||||
Vorausgesetzt wird AirScout `0.9.9.5` oder neuer.
|
||||
|
||||
{ width=85% }
|
||||
|
||||
### Einstellungen der UDP-Verbindung
|
||||
|
||||
| Einstellung | Standardwert | Verwendung |
|
||||
|---|---:|---|
|
||||
| **Enable AirScout UDP integration** | deaktiviert | Aktiviert das Senden von AirScout-Anfragen und die Verarbeitung der Antworten |
|
||||
| **AirScout server identifier** | `AS` | Logischer Name der angesprochenen AirScout-Instanz |
|
||||
| **KST4Contest client identifier** | `KST` | Logischer Name dieser KST4Contest-Instanz |
|
||||
| **AirScout UDP port** | `9872` | Gemeinsamer UDP-Port für Anfragen und Antworten |
|
||||
| **Select AirScout frequency automatically per station** | aktiviert | Ermittelt Band und Frequenz für jede Gegenstation aus dem aktuellen Stationskontext |
|
||||
| **Forced AirScout band value** | `1440000` | Verwendet bei deaktivierter Automatik einen festen AirScout-Bandwert für alle Stationen |
|
||||
|
||||
Ist **Enable AirScout UDP integration** deaktiviert, sendet KST4Contest keine AirScout-Anfragen und verwirft eingehende AirScout-Antworten. Der UDP-Empfänger kann trotzdem gebunden bleiben, damit sich die Funktion während einer laufenden Verbindung wieder einschalten lässt.
|
||||
|
||||
KST4Contest verwendet für ausgehende AirScout-Pakete die Broadcast-Adresse `255.255.255.255`. Eine Ziel-IP wird deshalb nicht separat konfiguriert. AirScout und KST4Contest müssen den verwendeten UDP-Broadcast empfangen können; Router leiten einen solchen Broadcast normalerweise nicht in ein anderes Netz weiter. Bei Problemen sollten daher zuerst der UDP-Port, die lokale Firewall und die Netzzuordnung geprüft werden.
|
||||
|
||||
### Automatische Bandauswahl pro Station
|
||||
|
||||
**Auto per station** ist die empfohlene Einstellung. KST4Contest verwendet dann nicht einen festen Bandwert für alle Gegenstationen, sondern leitet eine geeignete Frequenz aus den verfügbaren Informationen ab.
|
||||
|
||||
Die Quellen werden in folgender Reihenfolge ausgewertet:
|
||||
|
||||
1. die zuletzt erkannte, höchstens 30 Minuten alte QRG der Gegenstation,
|
||||
2. eine eindeutige vollständige QRG im Namensfeld eines aktiven Chat-Eintrags,
|
||||
3. eindeutige Bandangaben im Namensfeld,
|
||||
4. 432 MHz, wenn dieselbe Station gleichzeitig in der VHF/UHF- und Microwave-Kategorie aktiv ist und 432 MHz für die eigene Station aktiviert wurde,
|
||||
5. das niedrigste für die eigene Station aktivierte Band, das zur unterstützten Chat-Kategorie passt.
|
||||
|
||||
Aktive Chat-Varianten desselben Basisrufzeichens werden gemeinsam ausgewertet. Die Einträge `CALLSIGN`, `CALLSIGN-2` und `CALLSIGN-432` können dadurch gemeinsam zur Bandherleitung beitragen, bleiben für die Nachrichtenverarbeitung aber getrennte Chat-Teilnehmer.
|
||||
|
||||
Nur Bänder, die unter **My station uses …** aktiviert wurden, kommen für die automatische Auswahl infrage. Ein manuell gesetztes NOT-QRV-Kennzeichen schließt das betreffende Band aus und hat Vorrang vor automatisch erkannten QRG- oder Namensinformationen.
|
||||
|
||||
Unterstützt werden die Chat-Kategorien für 50/70 MHz, VHF/UHF, Microwave und EME/JT65. Andere ON4KST-Kategorien werden für die AirScout-Bandherleitung ignoriert. Kann keine ausreichend belastbare Frequenz bestimmt werden, sendet KST4Contest für diese Station keine Anfrage. Ein beliebiger Rückfall auf 144 MHz würde zwar ein syntaktisch vollständiges Paket erzeugen, aber nicht zwangsläufig eine sinnvolle Berechnung.
|
||||
|
||||
Die automatische AirScout-Auswahl verwendet dieselbe Herleitung wie die interne Streckenanalyse. Damit bewerten beide Funktionen den Stationspfad auf derselben fachlichen Grundlage.
|
||||
|
||||
### Festes AirScout-Band
|
||||
|
||||
Wird **Auto per station** deaktiviert, verwendet KST4Contest den unter **Forced AirScout band value** eingetragenen Wert für alle Stationen.
|
||||
|
||||
Der Wert wird in der von der AirScout-UDP-Schnittstelle verwendeten Einheit eingetragen:
|
||||
|
||||
| Band | AirScout-Wert |
|
||||
|---|---:|
|
||||
| 50 MHz | `500000` |
|
||||
| 70 MHz | `700000` |
|
||||
| 144 MHz | `1440000` |
|
||||
| 432 MHz | `4320000` |
|
||||
| 1296 MHz | `12960000` |
|
||||
| 2320 MHz | `23200000` |
|
||||
| 3400 MHz | `34000000` |
|
||||
| 5760 MHz | `57600000` |
|
||||
| 10368 MHz | `103680000` |
|
||||
| 24048 MHz | `240480000` |
|
||||
|
||||
Im festen Modus wird weder die zuletzt erkannte QRG noch das im Namen genannte Band der Gegenstation berücksichtigt. Diese Einstellung ist deshalb hauptsächlich für einen eindeutig auf ein Band begrenzten Stationsbetrieb oder zur Fehlersuche sinnvoll.
|
||||
|
||||
### Server- und Client-Identifier
|
||||
|
||||
Die Identifier gehören zum AirScout-Protokoll und sind keine DNS-Namen oder IP-Adressen.
|
||||
|
||||
Ausgehende Anfragen enthalten zunächst den Client- und anschließend den Server-Identifier:
|
||||
|
||||
```text
|
||||
"KST" "AS"
|
||||
```
|
||||
|
||||
AirScout antwortet in umgekehrter Reihenfolge:
|
||||
|
||||
```text
|
||||
"AS" "KST"
|
||||
```
|
||||
|
||||
KST4Contest verarbeitet eine Antwort nur, wenn beide Identifier exakt mit der aktuellen Konfiguration übereinstimmen. Der Vergleich unterscheidet zwischen Groß- und Kleinschreibung.
|
||||
|
||||
Die Identifier dürfen nicht leer sein und keine Anführungszeichen oder Zeilenumbrüche enthalten.
|
||||
|
||||
Werden mehrere KST4Contest-Instanzen im selben Netz betrieben, sollte jede einen eigenen Client-Identifier erhalten, beispielsweise:
|
||||
|
||||
```text
|
||||
KST-144
|
||||
KST-432
|
||||
```
|
||||
|
||||
Bei mehreren AirScout-Instanzen müssen zusätzlich unterschiedliche Server-Identifier verwendet werden. Dadurch wird verhindert, dass die Antwort für einen Arbeitsplatz von einer anderen KST4Contest-Instanz verarbeitet wird.
|
||||
|
||||
### Welche Stationen werden angefragt?
|
||||
|
||||
KST4Contest startet die erste periodische AirScout-Abfrage ungefähr zehn Sekunden nach dem Aufbau der Chat-Verbindung. Weitere Abfragen folgen im Abstand von 60 Sekunden.
|
||||
|
||||
Eine aktive Station wird nur berücksichtigt, wenn:
|
||||
|
||||
- ein verwendbares Rufzeichen vorhanden ist,
|
||||
- ein Locator vorhanden ist,
|
||||
- die Entfernung berechnet werden konnte,
|
||||
- die Entfernung kleiner als das konfigurierte **Maximum-QRB** ist und
|
||||
- ein verwendbares Band bestimmt werden konnte.
|
||||
|
||||
Mehrere aktive Chat-Einträge desselben Basisrufzeichens erzeugen nicht für jeden Suffix eine eigene identische Pfadberechnung. Die zurückgegebenen AirScout-Informationen werden anschließend wieder den passenden aktiven Chat-Varianten zugeordnet.
|
||||
|
||||
Die Auswahl begrenzt nicht nur den Netzwerkverkehr. Sie verhindert außerdem, dass AirScout dauerhaft Pfade berechnet, die außerhalb des für die eigene Station vorgesehenen Arbeitsbereichs liegen.
|
||||
|
||||
### Übernahme geänderter Einstellungen
|
||||
|
||||
Folgende Änderungen werden nach Verlassen des Eingabefeldes beziehungsweise Betätigen der Checkbox sofort für neue Pakete verwendet:
|
||||
|
||||
- Aktivierung oder Deaktivierung der AirScout-Integration,
|
||||
- Server-Identifier,
|
||||
- Client-Identifier,
|
||||
- automatische oder feste Bandauswahl und
|
||||
- fester Bandwert.
|
||||
|
||||
Nach einer Änderung des UDP-Ports muss die Chat-Verbindung getrennt und neu aufgebaut oder KST4Contest neu gestartet werden. Der bereits laufende UDP-Empfänger bleibt sonst weiterhin an den vorherigen Port gebunden.
|
||||
|
||||
Zum dauerhaften Speichern anschließend **Save Settings** verwenden.
|
||||
|
||||
Die Einrichtung der AirScout-Seite, die Anzeige der Flugzeuge und die Bedeutung der AP-Daten sind unter [AirScout-Integration](de-AirScout-Integration) beschrieben.
|
||||
Konfiguration der Schnittstelle zu AirScout für die Flugzeug-Scatter-Erkennung. Details: [AirScout-Integration](de-AirScout-Integration).
|
||||
|
||||
---
|
||||
|
||||
@@ -370,28 +191,11 @@ Folgende Einstellungen und Schaltflächen gehören zur lokalen DX-Cluster-Ausgab
|
||||
- **TCP port**: Port, auf dem KST4Contest Verbindungen von DX-Cluster-Clients annimmt. Der Standardwert ist `8000`. Wird der Port während einer laufenden Verbindung geändert, startet KST4Contest den Server auf dem neuen Port neu. Der Logger muss sich anschließend ebenfalls mit dem neuen Port verbinden.
|
||||
- **Fallback band for relative QRG detection**: Das oben beschriebene globale Fallback-Band. Der Testspot verwendet `.300` dieses Bandes. Reale Spots verwenden dagegen die für den jeweiligen Absender erkannte QRG.
|
||||
- **Spotter callsign**: Rufzeichen, das im erzeugten DX-Cluster-Spot als Spotter erscheint. Hier sollte ein anderes Rufzeichen als das im Contest verwendete Stationsrufzeichen eingetragen werden. Einige Logprogramme filtern Spots des eigenen Rufzeichens oder behandeln sie anders als fremde Spots.
|
||||
- **Send test spot**: Sendet den folgenden Testspot an alle aktuell verbundenen DX-Cluster-Clients:
|
||||
- **Send test spot**: Sendet einen Testspot für `DL0TEST` auf `.300` des ausgewählten Fallback-Bandes. Der Test funktioniert nur, wenn KST4Contest mit dem Chat verbunden, der lokale DX-Cluster-Server aktiviert und mindestens ein DX-Cluster-Client verbunden ist.
|
||||
|
||||
```text
|
||||
Spotted callsign: DO5AMF
|
||||
Comment: Testing DXC-Spot: Congrats, you donated $100!
|
||||
Frequency: .300 des ausgewählten Fallback-Bandes
|
||||
```
|
||||
|
||||
Bei einem Fallback-Band von `144 MHz` wird daraus beispielsweise eine Frequenz von ungefähr `144.300 MHz`.
|
||||
|
||||
Der Kommentar des Testspots ist ein bewusst beibehaltenes Easteregg. Er hat keine technische Bedeutung und löst – trotz seiner erfreulich konkreten Formulierung – keine Zahlung aus. Entscheidend ist, dass der Spot im verbundenen Logprogramm erscheint.
|
||||
|
||||
Der Test funktioniert nur, wenn
|
||||
|
||||
1. KST4Contest mit dem ON4KST-Chat verbunden ist,
|
||||
2. der lokale DX-Cluster-Server aktiviert ist und
|
||||
3. mindestens ein DX-Cluster-Client mit KST4Contest verbunden ist.
|
||||
|
||||
KST4Contest erzeugt nicht bei jeder im Chat gefundenen Frequenz automatisch einen Spot. Ein realer Spot entsteht nur dann, wenn eine gerichtete Nachricht zwischen zwei Stationen auf eine für die eigene Station interessante Antennenrichtung schließen lässt und für den Absender eine nutzbare Frequenz bekannt ist.
|
||||
KST4Contest erzeugt nicht bei jeder im Chat gefundenen Frequenz automatisch einen Spot. Ein Spot entsteht nur dann, wenn eine gerichtete Nachricht zwischen zwei Stationen auf eine für die eigene Station interessante Antennenrichtung schließen lässt und für den Absender eine nutzbare Frequenz bekannt ist.
|
||||
|
||||
Die vollständige Herleitung und die Einrichtung des Logprogramms sind im Kapitel [Integrierter DX-Cluster-Server](de-DX-Cluster-Server) beschrieben.
|
||||
|
||||
### Band-Upgrade-Hinweis nach einem Logeintrag
|
||||
|
||||
Nach einem über UCXLog oder Win-Test empfangenen Logeintrag kann KST4Contest prüfen, ob die gerade gearbeitete Station noch ein weiteres gemeinsames, aber bisher nicht gearbeitetes Band anbietet.
|
||||
@@ -425,42 +229,17 @@ Weitere Hintergründe: [Band-Upgrade-Hinweis nach einem Logeintrag](de-Funktione
|
||||
|
||||
### Sniffer-Einstellungen (ab v1.31)
|
||||
|
||||
Das QSO-Monitoring ist für Stationen gedacht, deren Kommunikation man gezielt verfolgen möchte. Das kann beispielsweise eine seltene Station, eine DXpedition oder eine andere Station des eigenen Contest-Teams sein, deren Sked-Absprachen im allgemeinen Chatverkehr nicht untergehen sollen.
|
||||
Das QSO-Monitoring ist für Stationen gedacht, deren Kommunikation man gezielt verfolgen möchte. Das kann beispielsweise eine seltene Station, eine DXpedition oder eine andere Station des eigenen Contest-Teams sein.
|
||||
|
||||
Die Rufzeichen werden im Reiter **Notification** unter **QSO monitoring** verwaltet.
|
||||
Für jedes eingetragene Rufzeichen zeigt KST4Contest Nachrichten zusätzlich in der PM-Tabelle an, wenn das Rufzeichen entweder Absender oder Empfänger der Nachricht ist. Die ursprüngliche Nachricht wird dabei nicht aus ihrer normalen Tabelle entfernt.
|
||||
|
||||
Für jedes eingetragene Basisrufzeichen zeigt KST4Contest Nachrichten zusätzlich in der PM-Tabelle an, wenn eine Variante dieses Rufzeichens entweder Absender oder Empfänger der Nachricht ist. Berücksichtigt werden beide verbundenen Chat-Kategorien.
|
||||
|
||||
Die Liste arbeitet bewusst mit dem normalisierten Basisrufzeichen. Folgende Eingaben erzeugen deshalb denselben Monitoring-Eintrag:
|
||||
Überwachte Nachrichten werden in der PM-Tabelle eindeutig gekennzeichnet:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
DN9APW-144
|
||||
Sniffed: (SENDER > RECEIVER) Nachrichtentext
|
||||
```
|
||||
|
||||
In allen Fällen speichert und zeigt KST4Contest den Eintrag als:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
```
|
||||
|
||||
Damit müssen die verschiedenen KST-Suffixe einer Station nicht einzeln eingetragen werden. Wird später eine Nachricht von `DN9APW-2` gesendet oder an `DN9APW-70` adressiert, wird sie durch denselben Eintrag erfasst.
|
||||
|
||||
Diese Zusammenführung gilt ausschließlich für das QSO-Monitoring. Die aktiven ChatMember-Objekte, vollständigen Nachrichtenempfänger und Chat-Kategorien bleiben getrennt. Eine an `DN9APW-70` gerichtete Nachricht wird deshalb nicht an `DN9APW-2` umgeleitet.
|
||||
|
||||
Überwachte Nachrichten werden in der PM-Tabelle mit den vollständigen sichtbaren Rufzeichen von Absender und Empfänger gekennzeichnet:
|
||||
|
||||
```text
|
||||
Sniffed: (DN9APW-2 > DL0ABC-70) Nachrichtentext
|
||||
```
|
||||
|
||||
Die ursprüngliche Nachricht bleibt gleichzeitig in ihrer normalen Tabelle erhalten. Das Monitoring verändert weder den Nachrichteninhalt noch dessen Routing.
|
||||
|
||||
Erfasst werden Nachrichten, bei denen das überwachte Rufzeichen tatsächlich Absender oder Empfänger ist. Eine bloße Erwähnung des Rufzeichens im Nachrichtentext reicht nicht aus. Öffentliche Nachrichten einer überwachten Station werden ebenfalls angezeigt; als Empfänger erscheint dabei `ALL`.
|
||||
|
||||
Ist eine Nachricht bereits direkt an das eigene Rufzeichen gerichtet, erscheint sie als normale Privatnachricht und erhält keine zusätzliche `Sniffed:`-Kennzeichnung.
|
||||
So wird sichtbar, dass die Nachricht nicht an die eigene Station gerichtet war.
|
||||
|
||||
Rufzeichen werden folgendermaßen verwaltet:
|
||||
|
||||
@@ -468,97 +247,27 @@ Rufzeichen werden folgendermaßen verwaltet:
|
||||
2. Ein vorhandenes Rufzeichen per Doppelklick bearbeiten und die Änderung mit `Enter` übernehmen.
|
||||
3. Zum Entfernen den Inhalt einer Tabellenzelle löschen und mit `Enter` bestätigen.
|
||||
|
||||
Die Eingabe darf ein sichtbares KST-Suffix oder portable Bestandteile enthalten. KST4Contest normalisiert sie vor dem Speichern auf das Basisrufzeichen. Mehrere Varianten desselben Basisrufzeichens gelten deshalb als Duplikat.
|
||||
Doppelte oder syntaktisch ungültige Rufzeichen werden nicht übernommen. Die Liste wird mit **Save Settings** in der `preferences.xml` gespeichert und beim nächsten Programmstart wiederhergestellt.
|
||||
|
||||
Die Änderung der Liste wirkt sofort. Zum dauerhaften Speichern anschließend **Save Settings** verwenden. Die Basisrufzeichen werden in der `preferences.xml` gespeichert und beim nächsten Programmstart wiederhergestellt.
|
||||
|
||||
> Die Zusammenführung der KST-Suffixe über das Basisrufzeichen ist im Nightly beziehungsweise ab v1.42 enthalten.
|
||||
|
||||
Weitere Hintergründe und die Abgrenzung zum Nachrichtenrouting: [QSO-Monitoring](de-Funktionen#qso-monitoring-ab-v131).
|
||||
---
|
||||
|
||||
## Shortcut Settings (Schnellzugriff-Schaltflächen)
|
||||
|
||||

|
||||
|
||||
Jeder Eintrag im oberen Bereich des Reiters **Shortcuts** erzeugt eine Schaltfläche oberhalb des Nachrichteneingabefeldes im Hauptfenster. Ein Klick hängt den konfigurierten Text an den bereits vorhandenen Inhalt des Sendfeldes an.
|
||||
|
||||
Enthält der Shortcut eine [Variable](de-Makros-und-Variablen#variablen), wird sie beim Einfügen durch ihren aktuellen Wert ersetzt. Ein Shortcut wie
|
||||
|
||||
```text
|
||||
pse call me at MYQRGSHORT
|
||||
```
|
||||
|
||||
kann dadurch beispielsweise folgenden Text einfügen:
|
||||
|
||||
```text
|
||||
pse call me at 144.388
|
||||
```
|
||||
|
||||
Die exakten Einträge `MYQRG` und `SECONDQRG` werden zusätzlich als QRG-Schaltflächen hervorgehoben. Sie fügen die aktuelle QRG der ersten beziehungsweise zweiten Chat-Kategorie ein.
|
||||
|
||||
Auch der Shortcut `/SETNAME MYQRG` wird hervorgehoben. Beim Anklicken löst KST4Contest `MYQRG` auf und übernimmt den vollständigen Serverbefehl in das Sendfeld. Der Befehl wird nicht automatisch versendet und kann vor dem Senden mit `Enter` oder **TX** noch geprüft werden.
|
||||
|
||||
|
||||
Die Reihenfolge der Tabelle entspricht der Reihenfolge der Schaltflächen im Hauptfenster. Die Einträge werden folgendermaßen verwaltet:
|
||||
|
||||
1. Mit **Add shortcut** wird am Anfang der Liste ein neuer Eintrag angelegt und sofort zur Bearbeitung geöffnet.
|
||||
2. Ein vorhandener Eintrag kann per Doppelklick bearbeitet werden. `Enter` übernimmt die Änderung.
|
||||
3. Wird der Inhalt vollständig gelöscht und anschließend mit `Enter` bestätigt, entfernt KST4Contest den Eintrag.
|
||||
4. Mit **Move selected up** und **Move selected down** wird der markierte Eintrag innerhalb der Liste verschoben.
|
||||
|
||||
Änderungen werden sofort im Hauptfenster sichtbar. Damit sie auch nach dem nächsten Programmstart erhalten bleiben, anschließend **Save Settings** verwenden.
|
||||
Konfiguration von Schnellzugriff-Schaltflächen, die direkt im Hauptfenster erscheinen. Ein Klick auf eine Schaltfläche fügt den konfigurierten Text in das Sendfeld ein. Alle [Variablen](de-Makros-und-Variablen#variablen) können verwendet werden.
|
||||
|
||||
---
|
||||
|
||||
## Snippet Settings (Text-Snippets)
|
||||
|
||||
Snippets sind längere Textbausteine, die vor allem für Nachrichten an eine ausgewählte Station vorgesehen sind. Sie können über folgende Wege aufgerufen werden:
|
||||
Text-Snippets sind über folgende Wege abrufbar:
|
||||
|
||||
- per Rechtsklick auf eine Station in der Benutzerliste,
|
||||
- per Rechtsklick auf eine Nachricht in der öffentlichen Chat-Tabelle,
|
||||
- per Rechtsklick auf eine Nachricht in der PM-Tabelle oder
|
||||
- mit `Ctrl+1` bis `Ctrl+0` für die ersten zehn Einträge der Snippet-Liste.
|
||||
- **Rechtsklick** auf ein Rufzeichen in der Benutzerliste
|
||||
- **Rechtsklick** in der CQ-Nachrichtentabelle
|
||||
- **Rechtsklick** in der PM-Nachrichtentabelle
|
||||
- **Tastenkombinationen**: `Ctrl+1` bis `Ctrl+0` für die ersten 10 Snippets
|
||||
|
||||
Bei den Tastenkombinationen entspricht die Zuordnung der Tabellenreihenfolge:
|
||||
|
||||
| Tastenkombination | Snippet |
|
||||
|---|---:|
|
||||
| `Ctrl+1` | erster Eintrag |
|
||||
| `Ctrl+2` | zweiter Eintrag |
|
||||
| … | … |
|
||||
| `Ctrl+9` | neunter Eintrag |
|
||||
| `Ctrl+0` | zehnter Eintrag |
|
||||
|
||||
Ein über das Kontextmenü ausgewähltes Snippet wird an den bereits vorbereiteten Nachrichtentext angehängt. Die Auswahl einer Station oder Nachricht hat das Sendfeld zuvor normalerweise bereits mit dem passenden `/cq`-Empfänger vorbereitet.
|
||||
|
||||
Eine Tastenkombination verhält sich etwas anders: Sie ersetzt den bisherigen Inhalt des Sendfeldes durch eine vollständig adressierte Privatnachricht:
|
||||
|
||||
```text
|
||||
/cq RUFZEICHEN Snippet-Text
|
||||
```
|
||||
|
||||
Dabei wird das vollständige sichtbare Rufzeichen einschließlich eines vorhandenen Suffixes verwendet. Für `9A0BB-70` entsteht daher beispielsweise:
|
||||
|
||||
```text
|
||||
/cq 9A0BB-70 pse ur qrg?
|
||||
```
|
||||
|
||||
Die Chat-Kategorie der ausgewählten Station bleibt für den späteren Versand erhalten. Ist keine Station ausgewählt oder ist für die gedrückte Tastenkombination kein Snippet vorhanden, wird nichts eingefügt.
|
||||
|
||||
Variablen werden beim Einfügen des Snippets aufgelöst. Stationsbezogene Variablen wie `QRZNAME`, `FIRSTAP` oder `SECONDAP` verwenden die aktuell ausgewählte Station. Der vorbereitete Text wird nicht automatisch gesendet und kann deshalb noch geprüft oder geändert werden. `Enter` oder **TX** sendet die Nachricht; `Esc` leert das Sendfeld.
|
||||
|
||||
Die Snippet-Liste wird genauso bearbeitet wie die Shortcut-Liste:
|
||||
|
||||
1. **Add new snippet** legt am Anfang der Liste einen neuen Eintrag an.
|
||||
2. Ein Doppelklick öffnet einen vorhandenen Eintrag zur Bearbeitung.
|
||||
3. `Enter` übernimmt die Änderung.
|
||||
4. Ein leer bestätigter Eintrag wird entfernt.
|
||||
5. **Move selected up** und **Move selected down** ändern die Reihenfolge und damit auch die Zuordnung zu `Ctrl+1` bis `Ctrl+0`.
|
||||
|
||||
Die Kontextmenüs und Tastenkombinationen werden nach einer Änderung sofort aktualisiert. Für die dauerhafte Speicherung anschließend **Save Settings** verwenden.
|
||||
|
||||
Eine vollständige Übersicht der verfügbaren Platzhalter und ihrer Grenzen steht unter [Makros und Variablen](de-Makros-und-Variablen).
|
||||
Wenn in der Benutzerliste ein Rufzeichen ausgewählt ist, wird der Snippet als Direktnachricht adressiert:
|
||||
`/CQ RUFZEICHEN <Snippet-Text>`
|
||||
|
||||
---
|
||||
|
||||
@@ -566,7 +275,7 @@ Eine vollständige Übersicht der verfügbaren Platzhalter und ihrer Grenzen ste
|
||||
|
||||

|
||||
|
||||
Ein Beacon sendet in regelmäßigen Abständen eine öffentliche CQ-Nachricht. Er ist für Betriebssituationen gedacht, in denen die eigene Station über längere Zeit auf einer festen Frequenz ruft. Andere Stationen erhalten dadurch eine aktuelle QRG-Information, ohne dass der Operator denselben Text immer wieder von Hand in den Chat schreiben muss.
|
||||
Ein Beacon sendet in regelmäßigen Abständen eine öffentliche CQ-Nachricht. Er ist für Betriebssituationen gedacht, in denen die eigene Station über längere Zeit auf einer festen Frequenz ruft. Andere Stationen erhalten dadurch eine aktuelle QRG-Information, ohne dass der Operator denselben Text wiederholt von Hand in den Chat schreiben muss.
|
||||
|
||||
KST4Contest verwendet einen gemeinsamen Timer für beide Chat-Kategorien. Aktivierung und Nachrichtentext werden trotzdem getrennt konfiguriert:
|
||||
|
||||
@@ -580,56 +289,21 @@ Sind beide Beacons aktiviert, werden sie beim selben Timer-Lauf nacheinander in
|
||||
|
||||
Das Intervall wird in ganzen Minuten angegeben. Der kleinste zulässige Wert ist eine Minute.
|
||||
|
||||
Nach dem Aufbau der Chat-Verbindung prüft KST4Contest die Beacons erstmals nach ungefähr zehn Sekunden. Anschließend gilt das eingestellte Intervall.
|
||||
|
||||
Wird das Intervall während einer laufenden Verbindung geändert, beginnt der Countdown mit dem neuen Wert erneut. Die Änderung selbst löst keine sofortige Beacon-Nachricht aus.
|
||||
|
||||
Beide Kategorien verwenden denselben Timer. Unterschiedliche Intervalle für den ersten und zweiten Chat können deshalb nicht eingestellt werden.
|
||||
Nach dem Aufbau der Chat-Verbindung prüft KST4Contest die Beacons erstmals nach ungefähr zehn Sekunden. Anschließend gilt das eingestellte Intervall. Wird der Wert während einer laufenden Verbindung geändert, beginnt der Countdown mit dem neuen Intervall erneut. Die Änderung selbst löst keine sofortige Nachricht aus.
|
||||
|
||||
### Nachrichtentext und Variablen
|
||||
|
||||
Ein Beacon darf die [globalen Variablen](de-Makros-und-Variablen#variablen-im-beacon) verwenden, die sich ausschließlich auf die eigene Station beziehen:
|
||||
Ein Beacon darf nach der Variablenauflösung höchstens 120 Zeichen enthalten. KST4Contest prüft deshalb nicht nur das eingetragene Template, sondern den tatsächlich zu sendenden Text.
|
||||
|
||||
- `MYQRG`
|
||||
- `MYQRGSHORT`
|
||||
- `SECONDQRG`
|
||||
- `MYLOCATOR`
|
||||
- `MYLOCATORSHORT`
|
||||
- `MYCALL`
|
||||
- `MYQTF`
|
||||
|
||||
Eine mögliche Nachricht für die erste Chat-Kategorie ist:
|
||||
Im Beacon können alle [globalen Variablen](de-Makros-und-Variablen#variablen-im-beacon) verwendet werden, beispielsweise:
|
||||
|
||||
```text
|
||||
calling cq at MYQRGSHORT, ant MYQTF deg, loc MYLOCATOR
|
||||
calling cq at MYQRG, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Für den zweiten Chat muss `SECONDQRG` verwendet werden, wenn dessen Frequenz von der ersten Kategorie abweicht:
|
||||
Die Variablen werden bei jedem Timer-Lauf neu aufgelöst. Ändert die Logsoftware zwischenzeitlich die in `MYQRG` gespeicherte Frequenz, verwendet bereits der nächste Beacon den neuen Wert.
|
||||
|
||||
```text
|
||||
calling cq at SECONDQRG, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Die Variablen werden bei jedem Timer-Lauf neu aufgelöst. Ändert die Logsoftware zwischenzeitlich die in `MYQRG` gespeicherte Frequenz, verwendet bereits der nächste Beacon den aktualisierten Wert. Das Template selbst muss dafür nicht geändert werden.
|
||||
|
||||
`MYQRG` und `MYQRGSHORT` beziehen sich immer auf die erste Chat-Kategorie. Die Auswahl oder Aktivierung des zweiten Chats ändert diese Zuordnung nicht.
|
||||
|
||||
Stationsbezogene Variablen wie `QRZNAME`, `FIRSTAP` oder `SECONDAP` benötigen eine ausgewählte Gegenstation. Da ein öffentlicher Beacon keine bestimmte Station adressiert, werden diese Variablen im Beacon nicht aufgelöst.
|
||||
|
||||
### Prüfung des Nachrichtentextes
|
||||
|
||||
KST4Contest prüft sowohl das eingetragene Template als auch den nach der Variablenauflösung tatsächlich zu sendenden Text.
|
||||
|
||||
Für Beacon-Nachrichten gelten folgende Bedingungen:
|
||||
|
||||
- Der endgültige Nachrichtentext darf nicht leer sein.
|
||||
- Er darf höchstens 120 Zeichen enthalten.
|
||||
- Das Protokoll-Trennzeichen `|` ist nicht zulässig.
|
||||
- Zeilenumbrüche sind nicht zulässig.
|
||||
|
||||
Eine ungültige Eingabe wird nicht als neue Beacon-Konfiguration übernommen. Wird ein Template erst durch eine spätere Variablenauflösung ungültig, beispielsweise weil der aufgelöste Text länger als 120 Zeichen ist, wird dieser Beacon-Lauf ausgelassen.
|
||||
|
||||
Ein Template, das ausschließlich aus einer momentan noch leeren globalen Variable besteht, kann gespeichert werden. Das ist beispielsweise beim Start möglich, bevor die erste QRG vom Logprogramm empfangen wurde. Solange die Variable keinen verwendbaren Inhalt liefert, sendet KST4Contest jedoch keine leere Nachricht.
|
||||
Stationsbezogene Variablen wie `QRZNAME`, `FIRSTAP` oder `SECONDAP` benötigen dagegen eine ausgewählte Gegenstation. Da ein öffentlicher Beacon keine Gegenstation adressiert, werden diese Variablen im Beacon nicht aufgelöst.
|
||||
|
||||
### Wann sollte der Beacon ausgeschaltet werden?
|
||||
|
||||
@@ -638,7 +312,6 @@ Der Beacon ist nur dann hilfreich, wenn seine QRG-Angabe zum tatsächlichen Betr
|
||||
Im Klartext: Solange auf einer festen QRG CQ gerufen wird, spart der Beacon Arbeit. Beim „Schleichen“ über das Band sollte er ausgeschaltet werden.
|
||||
|
||||
Änderungen wirken während der laufenden Verbindung. Damit Aktivierung, Texte und Intervall auch nach dem nächsten Programmstart erhalten bleiben, anschließend **Save Settings** verwenden.
|
||||
|
||||
---
|
||||
|
||||
## Messagehandling Settings (ab v1.25)
|
||||
@@ -659,19 +332,9 @@ Eine zweckmäßige Nachricht ist beispielsweise:
|
||||
Sri, I am not taking part in this contest. No skeds.
|
||||
```
|
||||
|
||||
Das Präfix `[KST4C Automsg]` muss nicht in das Eingabefeld geschrieben werden. KST4Contest ergänzt es automatisch.
|
||||
|
||||
Die beim Empfänger sichtbare Nachricht lautet daher beispielsweise:
|
||||
|
||||
```text
|
||||
[KST4C Automsg] Sri, I am not taking part in this contest. No skeds.
|
||||
```
|
||||
|
||||
Die eingegangene Privatnachricht bleibt sichtbar. Die Funktion blockiert oder verwirft keine Anfrage, sondern erspart lediglich die wiederholte manuelle Antwort.
|
||||
|
||||
Die Antwort wird an das vollständige Rufzeichen des Absenders einschließlich eines vorhandenen Suffixes und in derselben Chat-Kategorie gesendet, in der die Privatnachricht eingegangen ist. Das ist bei einem parallelen Login in zwei Kategorien entscheidend: Eine Nachricht aus dem Microwave-Chat darf nicht versehentlich im VHF/UHF-Chat beantwortet werden.
|
||||
|
||||
Ein leerer oder ausschließlich aus Leerzeichen bestehender Antworttext erzeugt keine automatische Nachricht. Enthält der Text ein Protokoll-Trennzeichen wie `|` oder einen Zeilenumbruch, wird die Antwort ebenfalls verworfen.
|
||||
Die Antwort wird in derselben Chat-Kategorie gesendet, in der die Privatnachricht eingegangen ist. Das ist bei einem parallelen Login in zwei Kategorien entscheidend: Eine Nachricht aus dem Microwave-Chat darf nicht versehentlich im VHF/UHF-Chat beantwortet werden.
|
||||
|
||||
### Automatische QRG-Antwort
|
||||
|
||||
@@ -685,24 +348,16 @@ freq?
|
||||
pse qrg
|
||||
```
|
||||
|
||||
Die Antwort enthält ausschließlich die QRG der Kategorie, in der die Anfrage eingegangen ist:
|
||||
Die Antwort enthält nur die QRG der Kategorie, in der die Anfrage eingegangen ist:
|
||||
|
||||
| Eingegangene Privatnachricht | Verwendete QRG |
|
||||
|---|---|
|
||||
| Hauptkategorie | aktuelle QRG der Hauptkategorie |
|
||||
| zweite Chat-Kategorie | aktuelle QRG der zweiten Kategorie |
|
||||
|
||||
Eine mögliche Antwort lautet:
|
||||
|
||||
```text
|
||||
[KST4C Automsg] QRG is: 144.300.00
|
||||
```
|
||||
|
||||
Die Werte stammen aus denselben QRG-Feldern, die auch von `MYQRG` und `SECONDQRG` verwendet werden. Die Haupt-QRG kann manuell eingetragen oder durch die [TRX-Synchronisation](#trx-sync-einstellungen) aktualisiert werden. Für die zweite Kategorie wird der dort konfigurierte beziehungsweise manuell eingetragene Wert verwendet.
|
||||
|
||||
Ist für die betreffende Kategorie keine QRG vorhanden, sendet KST4Contest keine unvollständige Antwort. Eine Nachricht wie `QRG is:` ohne Frequenz würde zwar auf die Frage reagieren, dem Anfragenden aber keine Information liefern. Sie wird deshalb bereits vor der Übergabe an die Sendequeue verworfen.
|
||||
|
||||
Sind die allgemeine und die QRG-bezogene Antwort gleichzeitig aktiviert, hat die QRG-Antwort Vorrang. Eine erkannte QRG-Anfrage erzeugt daher nicht zusätzlich den allgemeinen Antworttext. Fehlt die benötigte QRG, fällt KST4Contest auch nicht auf die allgemeine Antwort zurück.
|
||||
Sind die allgemeine und die QRG-bezogene Antwort gleichzeitig aktiviert, hat die QRG-Antwort Vorrang. Eine erkannte QRG-Anfrage erzeugt daher nicht zusätzlich den allgemeinen Antworttext.
|
||||
|
||||
### Schutz vor wiederholten Antworten
|
||||
|
||||
@@ -714,16 +369,9 @@ Jede automatisch erzeugte Nachricht trägt das feste Präfix:
|
||||
|
||||
Die allgemeine und die QRG-bezogene Antwort reagieren nicht auf Nachrichten, die dieses Präfix bereits enthalten. Dadurch beantworten sich zwei entsprechend arbeitende Clients nicht gegenseitig in einer Schleife.
|
||||
|
||||
Zusätzlich gilt eine gemeinsame Sperrzeit von zwei Minuten für beide Antwortarten. Die Sperre wird getrennt nach vollständigem Rufzeichen und Chat-Kategorie geführt.
|
||||
Zusätzlich gilt eine gemeinsame Sperrzeit von zwei Minuten für beide Antwortarten. Die Sperre wird getrennt je Rufzeichen und Chat-Kategorie geführt. Hat eine Station gerade in der Hauptkategorie eine automatische Antwort erhalten, kann sie deshalb weiterhin eine Antwort in der zweiten Kategorie erhalten. Weitere Nachrichten derselben Station in derselben Kategorie lösen während der folgenden zwei Minuten dagegen keine neue automatische Antwort aus.
|
||||
|
||||
Daraus folgt:
|
||||
|
||||
- `CALLSIGN-2` und `CALLSIGN-70` besitzen getrennte Sperrzeiten.
|
||||
- Dasselbe vollständige Rufzeichen kann in einer anderen Chat-Kategorie unabhängig beantwortet werden.
|
||||
- Eine allgemeine Antwort sperrt für zwei Minuten auch eine QRG-Antwort an dasselbe Rufzeichen in derselben Kategorie.
|
||||
- Eine QRG-Antwort sperrt entsprechend auch die allgemeine Antwort.
|
||||
|
||||
Die Sperrzeit beginnt nur, wenn KST4Contest eine vollständige und lokal gültige Antwort in die Sendequeue übernimmt. Eine fehlende QRG, ein leerer allgemeiner Antworttext oder ein wegen ungültiger Zeichen verworfener Text startet keine Sperrzeit. Sobald die fehlende Information korrigiert wurde, kann daher unmittelbar eine gültige Antwort erzeugt werden.
|
||||
Die Sperrzeit beginnt nur, wenn KST4Contest tatsächlich eine Antwort sendet.
|
||||
|
||||
> **Hinweis**: Der Antworttext sollte den tatsächlichen Status eindeutig benennen. Wer den Contest nur beobachtet und keine Skeds fahren möchte, sollte genau das mitteilen. Eine vage Nachricht erzeugt im Zweifel nur die nächste Rückfrage – und damit exakt die Arbeit, welche die Funktion vermeiden soll.
|
||||
|
||||
@@ -775,63 +423,16 @@ Nach Änderungen **Save Settings** verwenden, damit Port, Stationsname, Broadcas
|
||||
Datenbehandlung und QRG-Auswahl: [Log-Synchronisation – Win-Test](de-Log-Synchronisation#win-test)
|
||||
|
||||
|
||||
## PSTRotator-Einstellungen (ab v1.31, vollständig konfigurierbar ab v1.40)
|
||||
## PSTRotator-Einstellungen (ab v1.31)
|
||||
|
||||
KST4Contest kann eine ausgewählte Antennenrichtung über die UDP-Schnittstelle von [PSTRotator](https://www.pstrotator.com/) einstellen und die von PSTRotator gemeldete aktuelle Position als eigene QTF übernehmen.
|
||||
KST4Contest kann die Antennenrichtung über PSTRotator steuern.
|
||||
|
||||
Die Einstellungen befinden sich im Reiter **Station**:
|
||||
Einstellungen:
|
||||
- **Aktivieren/Deaktivieren**: Checkbox in den Preferences (ab v1.40).
|
||||
- **IP-Adresse**: IP-Adresse des PSTRotator-Rechners (Standard: `127.0.0.1` bei Betrieb auf demselben PC).
|
||||
- **Port**: Kommunikationsport von PSTRotator.
|
||||
|
||||
| Einstellung | Standardwert | Verwendung |
|
||||
|---|---:|---|
|
||||
| **Enable PSTRotator** | deaktiviert | Startet die UDP-Kommunikation mit PSTRotator |
|
||||
| **PSTRotator host** | `127.0.0.1` | Hostname oder IP-Adresse des Rechners, auf dem PSTRotator läuft |
|
||||
| **PSTRotator UDP port** | `12000` | UDP-Port, auf dem PSTRotator die Steuerbefehle empfängt |
|
||||
|
||||
Bei Betrieb auf demselben Rechner ist `127.0.0.1` normalerweise die eindeutigste Einstellung. Läuft PSTRotator auf einem anderen Rechner im Stationsnetz, muss dessen erreichbare IP-Adresse oder DNS-Name eingetragen werden.
|
||||
|
||||
Der Port darf zwischen `1` und `65534` liegen. Port `65535` ist nicht möglich, weil PSTRotator seine Positionsmeldungen auf dem jeweils folgenden Port sendet.
|
||||
|
||||
### PSTRotator vorbereiten
|
||||
|
||||
In PSTRotator muss unter **Communication → UDP Control Port** derselbe UDP-Port eingetragen werden wie in KST4Contest. Anschließend muss **UDP Control** in PSTRotator aktiviert werden.
|
||||
|
||||
Bei der Standardeinstellung ergibt sich folgendes Portpaar:
|
||||
|
||||
| Richtung | UDP-Port |
|
||||
|---|---:|
|
||||
| KST4Contest → PSTRotator | `12000` |
|
||||
| PSTRotator → KST4Contest | `12001` |
|
||||
|
||||
KST4Contest bindet den Empfangsport automatisch. Er wird nicht separat konfiguriert.
|
||||
|
||||
Bei Betrieb auf zwei Rechnern müssen die lokale Firewall und das Stationsnetz UDP-Pakete in beiden Richtungen zulassen. Ist der Empfangsport bereits durch ein anderes Programm belegt, kann KST4Contest die Positionsmeldungen nicht empfangen.
|
||||
|
||||
Das vollständige UDP-Protokoll ist im [PSTRotatorAz User Manual](https://www.qsl.net/yo3dmu/ANT/PstRotatorAz%20User%20Manual.pdf) beschrieben.
|
||||
|
||||
### Übernahme der aktuellen QTF
|
||||
|
||||
KST4Contest fragt PSTRotator alle zwei Sekunden nach der aktuellen Azimutposition und dem Betriebsmodus. Die zurückgemeldete Azimutposition wird als `actualQTF` übernommen.
|
||||
|
||||
Bei aktivierter PSTRotator-Integration ist das QTF-Feld im Hauptfenster deshalb nicht manuell editierbar. Es zeigt die zuletzt von PSTRotator gemeldete Position.
|
||||
|
||||
Diese QTF wird unter anderem verwendet für:
|
||||
|
||||
- den Richtungsfilter,
|
||||
- die Bewertung von Richtungsgelegenheiten,
|
||||
- den Priority Score,
|
||||
- die Darstellung des Antennensektors auf der Stationskarte,
|
||||
- die AP- und Sked-Timeline und
|
||||
- die Variable `MYQTF`.
|
||||
|
||||
Eine empfangene Rotatorposition ist damit nicht nur eine Anzeige. Sie verändert mehrere Funktionen, die auf der aktuellen Antennenrichtung beruhen.
|
||||
|
||||
KST4Contest verwendet derzeit nur den Azimut. Eine Elevationssteuerung oder eine vollständige Azimut-/Elevationsnachführung ist nicht Bestandteil dieser Integration.
|
||||
|
||||
### Änderungen übernehmen
|
||||
|
||||
Aktivierung, Host und Port werden beim Start der Rotatorverbindung ausgewertet. Nach einer Änderung sollte die ON4KST-Verbindung getrennt und erneut aufgebaut oder KST4Contest neu gestartet werden.
|
||||
|
||||
Anschließend **Save Settings** verwenden, damit die Werte auch beim nächsten Programmstart wiederhergestellt werden.
|
||||
> **Hinweis**: Nach einem Klick auf den Richtungs-Button wartet KST4Contest kurz auf die Rotatorantwort. Bei langsamen Rotoren (z. B. SPID) kann es zu einer kleinen Verzögerung kommen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,363 +2,177 @@
|
||||
|
||||
> 🇬🇧 [English version](en-Macros-and-Variables) | 🇩🇪 Du liest gerade die deutsche Version
|
||||
|
||||
KST4Contest unterscheidet zwischen Shortcut-Schaltflächen, Text-Snippets und Variablen. Shortcuts und Snippets enthalten vorbereitete Texte. Variablen ergänzen Informationen, die sich während des Betriebs ändern können.
|
||||
|
||||
Der eingefügte Text bleibt im Sendfeld sichtbar und kann vor dem Senden geprüft oder geändert werden.
|
||||
KST4Contest bietet ein flexibles System aus Text-Snippets, Shortcuts und eingebauten Variablen, die den Chat-Workflow im Contest erheblich beschleunigen.
|
||||
|
||||
---
|
||||
|
||||
## Überblick
|
||||
|
||||
| Mechanismus | Aufruf | Verwendung |
|
||||
| Typ | Aufruf | Zweck |
|
||||
|---|---|---|
|
||||
| **Shortcut** | Schaltfläche oberhalb des Sendfeldes | Fügt einen konfigurierten Text in das Sendfeld ein |
|
||||
| **Snippet** | Kontextmenü oder `Ctrl+1` bis `Ctrl+0` | Bereitet einen Text für die ausgewählte Station vor |
|
||||
| **Variable** | Platzhalter innerhalb eines Nachrichtentextes | Fügt aktuelle QRG-, Locator-, Richtungs-, Stations- oder AirScout-Informationen ein |
|
||||
|
||||
Shortcuts und Snippets speichern Texte. Variablen liefern die dazugehörigen aktuellen Werte.
|
||||
|
||||
Ein Shortcut wie
|
||||
|
||||
```text
|
||||
pse sked?
|
||||
```
|
||||
|
||||
fügt immer denselben Text ein. Ein Shortcut mit
|
||||
|
||||
```text
|
||||
pse call me at MYQRGSHORT
|
||||
```
|
||||
|
||||
verwendet dagegen die QRG, die beim Anklicken des Shortcuts aktuell in KST4Contest hinterlegt ist.
|
||||
| **Shortcuts** | Button in der Toolbar | Schneller Text-Insert ins Sendfeld |
|
||||
| **Snippets** | Rechtsklick / Ctrl+1..0 | Text-Bausteine, optionaler PM-Versand |
|
||||
| **Variablen** | In allen Text-Feldern verwendbar | Dynamische Werte (QRG, Locator, AP-Daten) |
|
||||
|
||||
---
|
||||
|
||||
## Shortcut-Schaltflächen
|
||||
## Shortcuts (Schnellzugriff-Schaltflächen)
|
||||
|
||||
Shortcuts werden unter **Preferences → Shortcut Settings** konfiguriert.
|
||||
Konfigurierbar in den Preferences → **Shortcut Settings**.
|
||||
|
||||

|
||||
- Jeder konfigurierte Text erzeugt **einen Button** in der Benutzeroberfläche.
|
||||
- Ein Klick fügt den Text in das **Sendfeld** ein.
|
||||
- **Alle Variablen** können in Shortcuts verwendet werden und werden beim Einfügen sofort aufgelöst.
|
||||
- Auch längere Texte möglich.
|
||||
|
||||
Jeder Eintrag erzeugt eine Schaltfläche im Hauptfenster. Ein Klick hängt den konfigurierten Text an den vorhandenen Inhalt des Sendfeldes an. Ein bereits vorbereiteter Nachrichtentext wird dabei nicht gelöscht.
|
||||
|
||||
Enthält der Shortcut eine Variable, wird sie beim Einfügen aufgelöst. Aus
|
||||
|
||||
```text
|
||||
pse call me at MYQRGSHORT
|
||||
```
|
||||
|
||||
kann beispielsweise werden:
|
||||
|
||||
```text
|
||||
pse call me at 144.388
|
||||
```
|
||||
|
||||
Die exakten Einträge `MYQRG` und `SECONDQRG` werden als QRG-Schaltflächen hervorgehoben. Sie fügen die aktuelle QRG der ersten beziehungsweise zweiten Chat-Kategorie ein.
|
||||
|
||||
Auch der Shortcut
|
||||
|
||||
```text
|
||||
/SETNAME MYQRG
|
||||
```
|
||||
|
||||
wird hervorgehoben. Beim Anklicken wird `MYQRG` aufgelöst und der daraus entstehende Serverbefehl in das Sendfeld übernommen. Der Befehl wird nicht automatisch gesendet.
|
||||
|
||||
Die Reihenfolge der Einträge in den Einstellungen bestimmt die Reihenfolge der Schaltflächen im Hauptfenster. Bearbeitung, Sortierung und Speicherung sind unter [Konfiguration – Shortcut Settings](de-Konfiguration#shortcut-settings-schnellzugriff-schaltflächen) beschrieben.
|
||||
**Tipp**: Häufig verwendete Abkürzungen wie „pse", „rrr", „tnx", „73" als Shortcuts anlegen.
|
||||
|
||||
---
|
||||
|
||||
## Text-Snippets
|
||||
## Snippets (Text-Bausteine)
|
||||
|
||||
Snippets werden unter **Preferences → Snippet Settings** konfiguriert. Sie sind vor allem für wiederkehrende Nachrichten an eine bestimmte Station vorgesehen.
|
||||
Konfigurierbar in den Preferences → **Snippet Settings**.
|
||||
|
||||
Snippets können aufgerufen werden:
|
||||
### Aufruf
|
||||
|
||||
- per Rechtsklick auf eine Station in der Benutzerliste,
|
||||
- per Rechtsklick auf eine öffentliche Nachricht,
|
||||
- per Rechtsklick auf eine Privatnachricht oder
|
||||
- mit `Ctrl+1` bis `Ctrl+0` für die ersten zehn Einträge der Snippet-Liste.
|
||||
- **Rechtsklick** auf ein Rufzeichen in der Benutzerliste
|
||||
- **Rechtsklick** in der CQ-Nachrichtentabelle
|
||||
- **Rechtsklick** in der PM-Nachrichtentabelle
|
||||
- **Tastaturkürzel**: `Ctrl+1` bis `Ctrl+0` für die ersten 10 Snippets
|
||||
|
||||
### Verwendung über das Kontextmenü
|
||||
### Verhalten mit ausgewähltem Rufzeichen
|
||||
|
||||
Die Auswahl einer Station oder Nachricht bereitet normalerweise bereits den passenden `/cq`-Empfänger im Sendfeld vor. Das anschließend im Kontextmenü ausgewählte Snippet wird an diesen Text angehängt.
|
||||
Wenn in der Benutzerliste ein Rufzeichen ausgewählt ist, wird der Snippet als **Privatnachricht** adressiert:
|
||||
|
||||
Ein bereits vorhandener Nachrichtentext kann dadurch gezielt erweitert werden.
|
||||
|
||||
### Verwendung über die Tastatur
|
||||
|
||||
Ein mit `Ctrl+1` bis `Ctrl+0` aufgerufenes Snippet ersetzt den bisherigen Inhalt des Sendfeldes durch eine vollständig adressierte Nachricht:
|
||||
|
||||
```text
|
||||
/cq RUFZEICHEN Snippet-Text
|
||||
```
|
||||
/CQ RUFZEICHEN <Snippet-Text>
|
||||
```
|
||||
|
||||
Das vollständige sichtbare Rufzeichen einschließlich eines vorhandenen Suffixes bleibt erhalten. Für die ausgewählte Station `9A0BB-70` kann beispielsweise entstehen:
|
||||
Anschließend kann mit **Enter** direkt gesendet werden – auch wenn das Sendfeld nicht den Fokus hat.
|
||||
|
||||
```text
|
||||
/cq 9A0BB-70 pse ur qrg?
|
||||
```
|
||||
### Hardware-Makro-Tastatur
|
||||
|
||||
KST4Contest behält intern auch die Chat-Kategorie der ausgewählten Station bei. Ein Snippet für `9A0BB-70` wird deshalb nicht versehentlich über die andere aktive Chat-Kategorie gesendet.
|
||||
*(Idee von IU3OAR, Gianluca Costantino)*
|
||||
|
||||
Ist keine Station ausgewählt oder existiert für die gedrückte Tastenkombination kein Snippet, wird nichts eingefügt.
|
||||
Die Tastenkombinationen `Ctrl+1` bis `Ctrl+0` können auf einer programmierbaren Makro-Tastatur belegt werden. Ein weiterer Tastendruck (auf eine „Enter"-Taste) sendet den Text sofort. Im Contest-Betrieb spart das erheblich Zeit.
|
||||
|
||||
Der vorbereitete Text wird nicht automatisch versendet:
|
||||
### Vordefinierte Standard-Snippets
|
||||
|
||||
- `Enter` oder **TX** sendet die Nachricht.
|
||||
- `Esc` leert das Sendfeld.
|
||||
Beim ersten Start werden einige Snippets vorbelegt, z. B.:
|
||||
|
||||
### Zuordnung der Tastenkombinationen
|
||||
- `Hi OM, try sked?`
|
||||
- `I am calling cq ur dir, pse lsn to me at MYQRG`
|
||||
- `pse ur qrg?`
|
||||
- `rrr, I move to your qrg nw, pse ant dir me`
|
||||
|
||||
Die Zuordnung folgt der Reihenfolge in der Snippet-Liste:
|
||||
|
||||
| Tastenkombination | Verwendeter Eintrag |
|
||||
|---|---:|
|
||||
| `Ctrl+1` | erster Eintrag |
|
||||
| `Ctrl+2` | zweiter Eintrag |
|
||||
| … | … |
|
||||
| `Ctrl+9` | neunter Eintrag |
|
||||
| `Ctrl+0` | zehnter Eintrag |
|
||||
|
||||
Die Tastenkombinationen können auch einer programmierbaren Makro-Tastatur zugewiesen werden. Die Idee zu dieser Bedienung stammt von IU3OAR, Gianluca Costantino.
|
||||
|
||||
KST4Contest legt keine verbindliche Liste von Standard-Snippets fest. Welche Texte sinnvoll sind, hängt vom eigenen Contestbetrieb und der verwendeten Betriebsart ab.
|
||||
|
||||
Bearbeitung, Sortierung und Speicherung sind unter [Konfiguration – Snippet Settings](de-Konfiguration#snippet-settings-text-snippets) beschrieben.
|
||||
Diese können in den Preferences angepasst oder gelöscht werden.
|
||||
|
||||
---
|
||||
|
||||
## Variablen
|
||||
|
||||
Variablen sind reservierte Platzhalter innerhalb eines Nachrichtentextes. Sie müssen in Großbuchstaben geschrieben werden und unterscheiden zwischen Groß- und Kleinschreibung.
|
||||
Variablen werden in geschriebenen Texten (Snippets, Shortcuts, Beacon, Sendfeld) durch ihre aktuellen Werte ersetzt. Einfach den Variablennamen **großgeschrieben** in den Text einfügen.
|
||||
|
||||
Variablen können verwendet werden in:
|
||||
### MYQRG
|
||||
|
||||
- Shortcuts,
|
||||
- Snippets,
|
||||
- Beacon-Texten und
|
||||
- direkt eingegebenen oder eingefügten Nachrichtentexten.
|
||||
Wird durch die aktuelle Transceiverfrequenz ersetzt.
|
||||
|
||||
Bei einem Shortcut oder Snippet werden die Variablen bereits beim Einfügen in das Sendfeld aufgelöst. Direkt in das Sendfeld geschriebene oder eingefügte Variablen werden unmittelbar vor der Übernahme in die Sendewarteschlange aufgelöst.
|
||||
- Quelle: TRX-Sync via UDP vom Logprogramm (wenn aktiviert)
|
||||
- Fallback: Manuell eingetragener Wert im MYQRG-Textfeld rechts neben dem Sendbutton
|
||||
- Format: `144.388.03`
|
||||
|
||||
Stationsbezogene Variablen verwenden immer die aktuell ausgewählte Station. KST4Contest leitet diese Station nicht aus einem von Hand in den Nachrichtentext geschriebenen `/cq`-Empfänger ab.
|
||||
**Beispiel**: `calling cq at MYQRG` → `calling cq at 144.388.03`
|
||||
|
||||
---
|
||||
### MYQRGSHORT
|
||||
|
||||
## Globale Variablen
|
||||
Wie MYQRG, aber nur die ersten 7 Zeichen.
|
||||
|
||||
Globale Variablen benötigen keine ausgewählte Gegenstation.
|
||||
- Format: `144.388`
|
||||
|
||||
| Variable | Ersetzter Wert |
|
||||
|---|---|
|
||||
| `MYQRG` | aktuelle QRG der ersten beziehungsweise primären Chat-Kategorie |
|
||||
| `MYQRGSHORT` | erste sieben Zeichen von `MYQRG` |
|
||||
| `SECONDQRG` | aktuelle QRG der zweiten Chat-Kategorie |
|
||||
| `MYLOCATOR` | vollständiger Locator der eigenen Station |
|
||||
| `MYLOCATORSHORT` | erste vier Zeichen des eigenen Locators |
|
||||
| `MYCALL` | konfiguriertes eigenes Rufzeichen |
|
||||
| `MYQTF` | aktuelle Antennenrichtung als numerischer Wert in Grad |
|
||||
**Beispiel**: `qrg: MYQRGSHORT` → `qrg: 144.388`
|
||||
|
||||
Beispiel:
|
||||
### MYLOCATOR
|
||||
|
||||
```text
|
||||
cq at MYQRGSHORT, qtf MYQTF, loc MYLOCATOR
|
||||
```
|
||||
Wird durch den eigenen Maidenhead-Locator (6-stellig) ersetzt.
|
||||
|
||||
kann aufgelöst werden zu:
|
||||
- Format: `JO51IJ`
|
||||
|
||||
```text
|
||||
cq at 144.388, qtf 135, loc JO51IJ
|
||||
```
|
||||
**Beispiel**: `my loc: MYLOCATOR` → `my loc: JO51IJ`
|
||||
|
||||
### QRG-Variablen
|
||||
### MYLOCATORSHORT
|
||||
|
||||
`MYQRG` enthält die QRG der ersten Chat-Kategorie. Der Wert kann aus der TRX-Synchronisation des Logprogramms oder aus dem manuell bearbeiteten QRG-Feld stammen.
|
||||
Wie MYLOCATOR, aber nur die ersten 4 Zeichen.
|
||||
|
||||
`MYQRGSHORT` verwendet denselben Wert, beschränkt ihn aber auf die ersten sieben Zeichen:
|
||||
- Format: `JO51`
|
||||
|
||||
```text
|
||||
144.388.03 → 144.388
|
||||
```
|
||||
|
||||
`SECONDQRG` enthält die QRG der zweiten Chat-Kategorie. Die Auswahl einer Station aus dem zweiten Chat verändert die Bedeutung von `MYQRG` nicht. Soll ausdrücklich die QRG der zweiten Kategorie eingesetzt werden, muss `SECONDQRG` verwendet werden.
|
||||
|
||||
### Locator-Variablen
|
||||
|
||||
`MYLOCATOR` übernimmt den vollständigen konfigurierten Locator der eigenen Station:
|
||||
|
||||
```text
|
||||
JO51IJ
|
||||
```
|
||||
|
||||
`MYLOCATORSHORT` verwendet nur die ersten vier Zeichen:
|
||||
|
||||
```text
|
||||
JO51
|
||||
```
|
||||
|
||||
### MYQTF
|
||||
|
||||
`MYQTF` übernimmt die aktuelle, in KST4Contest hinterlegte Antennenrichtung als numerischen Winkel in Grad.
|
||||
|
||||
Beispiel:
|
||||
|
||||
```text
|
||||
ant MYQTF deg
|
||||
```
|
||||
|
||||
kann werden zu:
|
||||
|
||||
```text
|
||||
ant 135 deg
|
||||
```
|
||||
|
||||
Die Richtung wird nicht in Himmelsrichtungen wie `north`, `north-east` oder `south-west` umgewandelt.
|
||||
|
||||
---
|
||||
|
||||
## Variablen für die ausgewählte Station
|
||||
|
||||
Diese Variablen benötigen eine ausgewählte Gegenstation:
|
||||
|
||||
| Variable | Ersetzter Wert |
|
||||
|---|---|
|
||||
| `QRZNAME` | Name der ausgewählten Station oder deren vollständiges Rufzeichen, wenn kein Name verfügbar ist |
|
||||
| `FIRSTAP` | Beschreibung und Ankunftszeit des ersten von AirScout gemeldeten Flugzeugs |
|
||||
| `SECONDAP` | Beschreibung und Ankunftszeit des zweiten von AirScout gemeldeten Flugzeugs |
|
||||
|
||||
Beispiel:
|
||||
|
||||
```text
|
||||
Hi QRZNAME, FIRSTAP, pse lsn at MYQRGSHORT
|
||||
```
|
||||
|
||||
kann werden zu:
|
||||
|
||||
```text
|
||||
Hi David, a very big AP in 2 min, pse lsn at 144.388
|
||||
```
|
||||
**Beispiel**: `loc: MYLOCATORSHORT` → `loc: JO51`
|
||||
|
||||
### QRZNAME
|
||||
|
||||
KST4Contest verwendet den Namen aus dem Namensfeld der ausgewählten Station. Ist dort kein verwendbarer Name vorhanden, wird stattdessen das vollständige sichtbare Rufzeichen eingesetzt.
|
||||
Wird durch den **Namen** der aktuell ausgewählten Station aus dem Chat-Namenfeld ersetzt.
|
||||
|
||||
**Beispiel**: `Hi QRZNAME, sked?` → `Hi Gianluca, sked?`
|
||||
|
||||
### FIRSTAP
|
||||
|
||||
Ist ein AirScout-Kandidat verfügbar, enthält `FIRSTAP` dessen Beschreibung und die voraussichtliche Zeit bis zum Reflexionsfenster.
|
||||
Wird durch Daten des ersten reflektierbaren Flugzeugs zur ausgewählten Station ersetzt (sofern vorhanden).
|
||||
|
||||
Beispiel:
|
||||
- Bedingung: AirScout ist aktiv und ein Flugzeug ist verfügbar.
|
||||
- Format-Beispiel: `a very big AP in 1 min`
|
||||
|
||||
```text
|
||||
a very big AP in 2 min
|
||||
```
|
||||
|
||||
Ist für die ausgewählte Station kein Flugzeug verfügbar, wird eingesetzt:
|
||||
|
||||
```text
|
||||
no ap available
|
||||
```
|
||||
**Beispiel**: `AP info: FIRSTAP` → `AP info: a very big AP in 1 min`
|
||||
|
||||
### SECONDAP
|
||||
|
||||
`SECONDAP` verwendet den zweiten verfügbaren AirScout-Kandidaten.
|
||||
Wie FIRSTAP, aber für das zweite verfügbare Flugzeug.
|
||||
|
||||
Beispiel:
|
||||
- Format-Beispiel: `Next big AP in 9 min`
|
||||
|
||||
```text
|
||||
Next big AP in 9 min
|
||||
```
|
||||
**Beispiel**: `also: SECONDAP` → `also: Next big AP in 9 min`
|
||||
|
||||
Ist kein zweiter Kandidat vorhanden, wird `SECONDAP` durch einen leeren Text ersetzt.
|
||||
### MYQTF *(geplant für v1.3)*
|
||||
|
||||
### Verhalten ohne ausgewählte Station
|
||||
Wird durch die aktuelle Antennenrichtung in Worten ersetzt (z. B. `north`, `north east`, `east`, …).
|
||||
|
||||
Ist keine Station ausgewählt, bleiben `QRZNAME`, `FIRSTAP` und `SECONDAP` im Text sichtbar. KST4Contest entfernt diese Platzhalter nicht automatisch.
|
||||
|
||||
Ein sichtbarer, nicht aufgelöster Platzhalter ist eindeutiger als eine formal vollständige Nachricht, in der unbemerkt eine wichtige Information fehlt. Vor dem Senden sollte deshalb geprüft werden, ob die richtige Station ausgewählt ist und alle benötigten Variablen aufgelöst wurden.
|
||||
- Quelle: Winkelwert im MYQTF-Eingabefeld (rechts neben dem MYQRG-Feld)
|
||||
|
||||
---
|
||||
|
||||
## Variablen im Beacon
|
||||
## Variablen im Beacon
|
||||
|
||||
Ein öffentlicher Beacon besitzt keine ausgewählte Gegenstation. Deshalb können dort ausschließlich globale Variablen verwendet werden:
|
||||
Ein öffentlicher Beacon besitzt keine ausgewählte Gegenstation. Deshalb können hier ausschließlich Variablen verwendet werden, die nur von der eigenen Station und ihrer aktuellen Konfiguration abhängen:
|
||||
|
||||
- `MYQRG`
|
||||
- `MYQRGSHORT`
|
||||
- `SECONDQRG`
|
||||
- `MYLOCATOR`
|
||||
- `MYLOCATORSHORT`
|
||||
- `MYCALL`
|
||||
- `MYQTF`
|
||||
| Variable | Wert im Beacon |
|
||||
|---|---|
|
||||
| `MYQRG` | aktuelle QRG der ersten Chat-Kategorie |
|
||||
| `MYQRGSHORT` | auf sieben Zeichen gekürzte QRG der ersten Kategorie |
|
||||
| `SECONDQRG` | aktuelle QRG der zweiten Chat-Kategorie |
|
||||
| `MYLOCATOR` | eigener vollständiger Locator |
|
||||
| `MYLOCATORSHORT` | eigener vierstelliger Locator |
|
||||
| `MYCALL` | eigenes Rufzeichen |
|
||||
| `MYQTF` | aktuelle Antennenrichtung |
|
||||
|
||||
`QRZNAME`, `FIRSTAP` und `SECONDAP` dürfen in einem Beacon nicht verwendet werden.
|
||||
`QRZNAME`, `FIRSTAP` und `SECONDAP` benötigen eine ausgewählte Station. In einem öffentlichen Beacon werden sie daher nicht aufgelöst.
|
||||
|
||||
Eine mögliche Vorlage für die erste Chat-Kategorie ist:
|
||||
Eine zweckmäßige Konfiguration ist beispielsweise:
|
||||
|
||||
```text
|
||||
calling cq at MYQRGSHORT, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
calling cq at MYQRG, loc MYLOCATOR, GL all!
|
||||
```
|
||||
|
||||
Verwendet die zweite Chat-Kategorie eine andere QRG, muss deren Vorlage `SECONDQRG` enthalten:
|
||||
Die globalen Variablen werden bei jedem Timer-Lauf neu ausgewertet. Dadurch kann eine vom Logprogramm aktualisierte QRG bereits in der nächsten Beacon-Nachricht erscheinen.
|
||||
|
||||
```text
|
||||
calling cq at SECONDQRG, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Die globalen Variablen werden bei jedem Timer-Lauf erneut ausgewertet. Eine inzwischen vom Logprogramm aktualisierte QRG kann dadurch bereits in der nächsten Beacon-Nachricht erscheinen.
|
||||
|
||||
Der vollständig aufgelöste Beacon-Text:
|
||||
|
||||
- muss mindestens ein gültiges Zeichen enthalten,
|
||||
- darf höchstens 120 Zeichen lang sein,
|
||||
- darf das Protokoll-Trennzeichen `|` nicht enthalten und
|
||||
- darf keine Zeilenumbrüche enthalten.
|
||||
|
||||
Ist der Text beim vorgesehenen Versand leer oder ungültig, wird der betreffende Beacon-Lauf ausgelassen.
|
||||
|
||||
Intervall, Aktivierung und Verhalten beider Kategorien sind unter [Konfiguration – Beacon Settings](de-Konfiguration#beacon-settings-automatischer-beacon) beschrieben.
|
||||
Der vollständig aufgelöste Nachrichtentext darf höchstens 120 Zeichen enthalten. Weitere Angaben zum gemeinsamen Intervall und zum Verhalten beider Chat-Kategorien stehen unter [Konfiguration – Beacon Settings](de-Konfiguration#beacon-settings-automatischer-beacon).
|
||||
|
||||
---
|
||||
## Beispiel-Workflow mit Makros im Contest
|
||||
|
||||
## Beispiel für einen Snippet-Workflow
|
||||
1. Station in der Benutzerliste auswählen → Rufzeichen ist nun vorausgewählt.
|
||||
2. `Ctrl+1` drücken → Snippet „Hi OM, try sked?" wird als PM adressiert.
|
||||
3. Enter drücken → Nachricht wird gesendet.
|
||||
4. Station antwortet mit Frequenz → QRG-Spalte wird automatisch befüllt.
|
||||
5. `Ctrl+2` → Snippet „I am calling cq ur dir, pse lsn to me at 144.388" (MYQRG aufgelöst).
|
||||
6. Enter → Gesendet.
|
||||
|
||||
Als erstes Snippet ist beispielsweise konfiguriert:
|
||||
|
||||
```text
|
||||
Hi QRZNAME, pse sked? I call at MYQRGSHORT
|
||||
```
|
||||
|
||||
Der Ablauf kann dann folgendermaßen aussehen:
|
||||
|
||||
1. In der Benutzerliste wird `DL1ABC-432` ausgewählt.
|
||||
2. `Ctrl+1` wird gedrückt.
|
||||
3. KST4Contest bereitet die adressierte Nachricht vor und löst die Variablen auf.
|
||||
4. Der vollständige Text wird im Sendfeld geprüft.
|
||||
5. Falls die Gegenstation eine andere QRG vorgeschlagen hat, wird der Text entsprechend angepasst.
|
||||
6. `Enter` oder **TX** sendet die Nachricht.
|
||||
|
||||
Das Ergebnis kann beispielsweise lauten:
|
||||
|
||||
```text
|
||||
/cq DL1ABC-432 Hi Peter, pse sked? I call at 432.088
|
||||
```
|
||||
|
||||
Das vollständige Rufzeichen bestimmt den Empfänger. Die ausgewählte Chat-Kategorie bestimmt den Versandweg. Die Variablen verringern die wiederholte Texteingabe, entscheiden aber nicht, ob die eingesetzten Informationen noch zur aktuellen Betriebssituation passen.
|
||||
|
||||
---
|
||||
|
||||
## Grenzen der Variablenauflösung
|
||||
|
||||
Variablen geben den Informationsstand wieder, den KST4Contest im Moment der Auflösung besitzt.
|
||||
|
||||
Dabei ist insbesondere zu beachten:
|
||||
|
||||
- Eine vom Logprogramm gelieferte QRG kann sich inzwischen geändert haben.
|
||||
- Eine manuell eingetragene QRG bleibt aktiv, bis sie erneut geändert wird.
|
||||
- `MYQRG` bleibt die QRG der primären Kategorie, auch wenn eine Station aus der zweiten Kategorie ausgewählt wurde.
|
||||
- Die ausgewählte Station kann von einem manuell eingegebenen `/cq`-Empfänger abweichen.
|
||||
- AirScout kann für die betreffende Strecke keine aktuellen Flugzeugdaten liefern.
|
||||
- Stationsbezogene Variablen bleiben sichtbar, wenn keine Station ausgewählt ist.
|
||||
- Der eingefügte Text wird nicht automatisch auf seine betriebliche Richtigkeit geprüft.
|
||||
|
||||
Das Sendfeld bleibt deshalb nach dem Einfügen eines Shortcuts oder Snippets bearbeitbar. Die Variablen vermeiden wiederholte Eingaben; die abschließende Prüfung bleibt beim Operator.
|
||||
Ohne manuelle Tipparbeit, ohne Fehler, ohne Unterbrechung des CQ-Rufens.
|
||||
|
||||
@@ -10,15 +10,13 @@ Published Stable versions and their application packages are available under [Gi
|
||||
|
||||
## v1.42 – Nightly / in development
|
||||
|
||||
> Status of this section: 14 August 2026.
|
||||
> Status of this section: 10 August 2026.
|
||||
> v1.42 is not a published Stable release yet. Further changes may be added before release.
|
||||
|
||||
v1.42 brings several previously separate calculations together. Band information, Worked status, NOT-QRV marks, callsign suffixes and frequencies are now used more consistently by the user list, station map, priority calculation and external interfaces.
|
||||
|
||||
### Added
|
||||
|
||||
- **Visible ON4KST connection state:** A compact `LINK` indicator in the main window displays the actual state of the ON4KST connection. Green means fully authenticated and synchronised, yellow indicates connection setup or synchronisation, and red indicates a lost connection, an error or the delay before the next connection attempt.
|
||||
|
||||
- **Shared band-opportunity calculation:** A central `BandOpportunityResolver` evaluates recent QRGs, band designators in station names, active callsign variants, Worked information and NOT-QRV marks. The user list, **New bands**, band-upgrade hint, Priority Score, station map and automatic band selection now use the same basis.
|
||||
|
||||
- **Extended band status display:** The band columns now distinguish:
|
||||
@@ -43,10 +41,6 @@ v1.42 brings several previously separate calculations together. Band information
|
||||
|
||||
### Changed
|
||||
|
||||
- **Session-based ON4KST connection lifecycle:** Each socket, reader, writer, message bus and queue now belongs to an explicitly identified connection session. Delayed threads from an obsolete connection can therefore no longer process data or close its replacement. `ONLINE` is reported only after the login has been accepted and all requested user lists have been received. Connection setup, login and synchronisation use bounded timeouts, while heartbeats, missing inbound traffic, EOF and read or write failures trigger controlled reconnect attempts with backoff where appropriate.
|
||||
|
||||
- **Validated ON4KST protocol commands:** Outgoing frames are built centrally and checked for valid categories, locators and prohibited frame delimiters. Because ON4KST maintains one locator per TCP session, the main locator is used for both chat categories and a conflicting secondary configuration is logged instead of sending contradictory commands to the server.
|
||||
|
||||
- **More precise QRG recognition:** Complete and relative frequency references continue to be recognised. Bare three-digit numbers are treated as QRGs only when a frequency context is available. Signal reports, band designators and unrelated numbers therefore produce fewer false frequencies.
|
||||
|
||||
- **Station-specific frequency context:** For relative QRGs, KST4Contest first uses a band context for the same station which is no more than 30 minutes old. The globally configured fallback band is used only when this context is unavailable.
|
||||
@@ -85,14 +79,6 @@ v1.42 brings several previously separate calculations together. Band information
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Reliable initial user list:** Invalid or incomplete `UA0` member records are rejected and logged individually without preventing alphabetically following members from being processed. Valid entries are staged per category and published as one complete snapshot when the first corresponding `UE` end marker is received.
|
||||
|
||||
- **User list disappearing after login:** ON4KST may send additional `UE` frames for the same category after name, state or other live updates. Repeated end markers are now detected and ignored so that an already populated user list cannot be replaced by an empty snapshot.
|
||||
|
||||
- **Failed initial connection and lost sockets:** An unavailable server during startup no longer sends KST4Contest into an endless or busy-wait loop. The user interface remains responsive and further attempts use bounded reconnect backoff. Sockets closed by the server, or connections without inbound traffic for an excessive period, are also detected reliably.
|
||||
|
||||
- **Message-bus diagnostics:** Correctly processed ON4KST frames are no longer reported additionally as `Critical, detected unhandled Chatmessage`. Only genuinely unknown frames reach the fallback diagnostic branch.
|
||||
|
||||
- **Long-running station-selection failure:** Chat members managed by the message thread have been decoupled from the JavaFX view. Simultaneous data and table updates therefore no longer cause broken selection models or concurrent-modification problems after longer runtimes.
|
||||
|
||||
- **No phantom chat members from UM3:** Historical or additional server messages no longer create user-list entries for stations which are not actually logged into the chat.
|
||||
|
||||
@@ -131,231 +131,18 @@ Configuration of the individual logging applications, band and locator handling,
|
||||
|
||||
## TRX Sync Settings
|
||||
|
||||
TRX synchronisation imports the current frequency from the logging application and makes it available in KST4Contest as the local QRG of the first chat category. QSO and frequency synchronisation may use the same UDP receiver, but they remain separate functions: receiving a `RadioInfo` packet does not mark a station as worked, and receiving a QSO packet does not automatically change the local QRG.
|
||||
Receives the current transceiver frequency from the logging software via UDP. This enables the automatic population of the `MYQRG` variable. Useful for:
|
||||
|
||||

|
||||
- Quickly inserting your own QRG into chat messages.
|
||||
- Automatic CQ beacon with current frequency.
|
||||
|
||||
### Available QRG Sources
|
||||
|
||||
| Source | Setting | Behaviour |
|
||||
|---|---|---|
|
||||
| **General RadioInfo listener** | `Update MYQRG from RadioInfo messages received on the shared log-sync port` | Processes compatible `RadioInfo` packets on the UDP port shared with QSO synchronisation. The default port is `12060`. |
|
||||
| **Win-Test STATUS** | `Win-Test STATUS QRG Sync` | Processes the main or pass frequency from native Win-Test `STATUS` packets. The Win-Test listener uses its separately configured port, which defaults to `9871`. |
|
||||
| **Manual entry** | Disable both automatic QRG sources | The local QRG can be entered manually in the main window. |
|
||||
|
||||
The general listener is intended for logging applications which transmit compatible `RadioInfo` packets. Depending on their individual configuration, this includes UCXLog, N1MM+, QARTest and DXLog.net. QSO and `RadioInfo` packets use the same port configured under **Log sync**, but separate options determine whether KST4Contest processes QSO information, TRX information or both packet types.
|
||||
|
||||
Restart KST4Contest after changing the shared UDP port. Changes to the two QRG-sync checkboxes take effect immediately.
|
||||
|
||||
### Which QRG Is Updated?
|
||||
|
||||
Both automatic sources update `MYQRG` only. This is the local QRG of the first or primary chat category.
|
||||
|
||||
If a second chat is enabled, its QRG remains independent. It is not derived from incoming TRX packets and is available through `SECONDQRG`. The first category can therefore follow the logging application's frequency automatically while a separate QRG is entered manually for the second category.
|
||||
|
||||
As soon as at least one automatic QRG source is enabled, the first category's QRG field in the main window is bound to the received value. Manual entry becomes available again when both the general RadioInfo listener and Win-Test STATUS synchronisation are disabled.
|
||||
|
||||
### Main or Pass Frequency from Win-Test
|
||||
|
||||
By default, KST4Contest uses the main frequency contained in the Win-Test `STATUS` packet.
|
||||
|
||||
Enable `Use pass frequency from Win-Test STATUS` to use the packet's pass frequency instead. This is useful, for example, when Win-Test maintains a different frequency during split operation and that is the frequency which should be announced in the chat.
|
||||
|
||||
If the packet does not contain a valid pass frequency, KST4Contest automatically falls back to the main frequency. A missing pass frequency therefore neither clears `MYQRG` nor replaces it with an obviously incorrect number.
|
||||
|
||||
Frequencies use a consistent KST4Contest display format, for example:
|
||||
|
||||
```text
|
||||
50.300.00
|
||||
144.300.00
|
||||
1296.100.00
|
||||
10368.100.00
|
||||
```
|
||||
|
||||
The number of digits before the first dot is derived from the frequency. Microwave frequencies with four or five MHz digits are therefore formatted correctly as well.
|
||||
|
||||
### Selecting the Win-Test Station
|
||||
|
||||
Several stations in a Win-Test network may transmit `STATUS` packets at the same time. `Win-Test station name filter` selects the station which is allowed to update the local QRG in KST4Contest.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
STN1
|
||||
```
|
||||
|
||||
The comparison is case-insensitive. If the field is empty, `STATUS` packets from every Win-Test station are accepted.
|
||||
|
||||
In a multi-operator setup, set the filter to the station name of the operating position which actually belongs to this KST4Contest instance. Otherwise, a packet from another position may replace the QRG currently being displayed.
|
||||
|
||||
### Using MYQRG and SECONDQRG
|
||||
|
||||
The synchronised QRG can be used in every text processed by the common KST4Contest variable resolver. This includes:
|
||||
|
||||
- the send field,
|
||||
- shortcuts,
|
||||
- snippets, and
|
||||
- automatic beacons.
|
||||
|
||||
`MYQRG` contains the complete QRG of the first chat category. `MYQRGSHORT` uses only its first seven characters. `SECONDQRG` contains the separately entered QRG of the second chat category.
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
I am calling cq at MYQRG
|
||||
cq on MYQRGSHORT
|
||||
second chat qrg SECONDQRG
|
||||
```
|
||||
|
||||
The values are inserted when the message text is resolved. If the logging application changes frequency between two beacon runs, the next message already uses the updated value.
|
||||
|
||||
The local QRG may also be used as a fallback when handing a sked over to Win-Test. This only happens if the QRG can be parsed and belongs to the band explicitly selected for the sked. See [Log Synchronisation](en-Log-Sync#handing-skeds-over-to-win-test) for details.
|
||||
|
||||
Further information about text variables: [Macros and Variables](en-Macros-and-Variables#variables).
|
||||
|
||||
### Multiple Loggers or Radios
|
||||
|
||||
Every enabled QRG source writes to the same `MYQRG` value. KST4Contest does not currently assign incoming `RadioInfo` or `STATUS` packets to a particular radio or chat category.
|
||||
|
||||
If the general RadioInfo listener and Win-Test synchronisation are enabled at the same time, the most recently processed packet therefore determines the displayed QRG. The same applies when several logging applications send frequency packets to one KST4Contest instance.
|
||||
|
||||
For a setup containing several radios:
|
||||
|
||||
- QSO packets may be received from several logging applications.
|
||||
- Frequency packets should only be transmitted by the source which is intended to control `MYQRG`.
|
||||
- A Win-Test network should additionally use the station-name filter.
|
||||
- If two completely independent QRG synchronisations are required, two separate KST4Contest instances provide the clearer arrangement.
|
||||
|
||||
In other words, combining several Worked sources is useful. Combining several simultaneously transmitting frequency sources merely creates a contest over which packet arrived last.
|
||||
|
||||
Click **Save Settings** after completing the configuration.
|
||||
> **Note for multi-setup**: When running two logging programs on two computers but only one KST4Contest instance, only one logging program should send frequency packets. KST4Contest cannot distinguish between sources.
|
||||
|
||||
---
|
||||
|
||||
## AirScout Settings
|
||||
|
||||
The **AirScout** tab configures the UDP connection between KST4Contest and AirScout. KST4Contest does not request a general aircraft feed. It submits the station paths which are currently relevant, while AirScout calculates the matching aircraft and returns the result to the requesting KST4Contest instance.
|
||||
|
||||
AirScout `0.9.9.5` or newer is required.
|
||||
|
||||
{ width=85% }
|
||||
|
||||
### UDP Connection Settings
|
||||
|
||||
| Setting | Default | Use |
|
||||
|---|---:|---|
|
||||
| **Enable AirScout UDP integration** | disabled | Enables AirScout requests and the processing of returned information |
|
||||
| **AirScout server identifier** | `AS` | Logical name of the AirScout instance being addressed |
|
||||
| **KST4Contest client identifier** | `KST` | Logical name of this KST4Contest instance |
|
||||
| **AirScout UDP port** | `9872` | Shared UDP port for requests and responses |
|
||||
| **Select AirScout frequency automatically per station** | enabled | Derives a suitable band and frequency from the current context of each remote station |
|
||||
| **Forced AirScout band value** | `1440000` | Uses one fixed AirScout band value for every station when automatic selection is disabled |
|
||||
|
||||
When **Enable AirScout UDP integration** is disabled, KST4Contest neither sends AirScout requests nor processes incoming AirScout responses. The UDP receiver may remain bound so that the integration can be enabled again during the current connection.
|
||||
|
||||
KST4Contest sends AirScout packets to the broadcast address `255.255.255.255`. No separate destination IP address is therefore configured. AirScout and KST4Contest must be able to receive the same UDP broadcast; routers do not normally forward this type of broadcast into another network. If communication fails, check the UDP port, local firewall and network assignment first.
|
||||
|
||||
### Automatic Band Selection per Station
|
||||
|
||||
**Auto per station** is the recommended setting. Instead of using one fixed band value for every remote station, KST4Contest derives a suitable frequency from the available operating context.
|
||||
|
||||
The sources are evaluated in this order:
|
||||
|
||||
1. the most recently detected QRG of the remote station, provided that it is no more than 30 minutes old,
|
||||
2. one unambiguous complete QRG in the name field of an active chat entry,
|
||||
3. unambiguous band designators in the name field,
|
||||
4. 432 MHz if the same station is active in both the VHF/UHF and Microwave categories and 432 MHz is enabled for the local station,
|
||||
5. the lowest locally enabled band belonging to the supported chat category.
|
||||
|
||||
Active chat variants of the same base callsign are evaluated together. Entries such as `CALLSIGN`, `CALLSIGN-2` and `CALLSIGN-432` can therefore contribute to the same band decision while remaining separate chat members for message processing.
|
||||
|
||||
Only bands enabled under **My station uses …** are eligible for automatic selection. A manually assigned NOT-QRV mark excludes the corresponding band and takes precedence over automatically detected QRG or name information.
|
||||
|
||||
The 50/70 MHz, VHF/UHF, Microwave and EME/JT65 chat categories are supported. Other ON4KST categories do not participate in AirScout band resolution. If no sufficiently reliable frequency can be determined, KST4Contest omits the request for that station. An arbitrary fallback to 144 MHz would produce a syntactically complete packet, but not necessarily a useful calculation.
|
||||
|
||||
Automatic AirScout selection uses the same propagation-frequency resolver as the internal path analysis. Both functions therefore evaluate the station path from the same technical basis.
|
||||
|
||||
### Fixed AirScout Band
|
||||
|
||||
When **Auto per station** is disabled, KST4Contest uses the value entered under **Forced AirScout band value** for every station.
|
||||
|
||||
Enter the value in the unit used by the AirScout UDP interface:
|
||||
|
||||
| Band | AirScout value |
|
||||
|---|---:|
|
||||
| 50 MHz | `500000` |
|
||||
| 70 MHz | `700000` |
|
||||
| 144 MHz | `1440000` |
|
||||
| 432 MHz | `4320000` |
|
||||
| 1296 MHz | `12960000` |
|
||||
| 2320 MHz | `23200000` |
|
||||
| 3400 MHz | `34000000` |
|
||||
| 5760 MHz | `57600000` |
|
||||
| 10368 MHz | `103680000` |
|
||||
| 24048 MHz | `240480000` |
|
||||
|
||||
In fixed mode, neither the remote station's recently detected QRG nor a band stated in its name is considered. This option is therefore mainly useful for a station setup which is clearly limited to one band, or for troubleshooting.
|
||||
|
||||
### Server and Client Identifiers
|
||||
|
||||
The identifiers belong to the AirScout protocol. They are not DNS names or IP addresses.
|
||||
|
||||
Outgoing requests contain the client identifier followed by the server identifier:
|
||||
|
||||
```text
|
||||
"KST" "AS"
|
||||
```
|
||||
|
||||
AirScout returns them in the opposite order:
|
||||
|
||||
```text
|
||||
"AS" "KST"
|
||||
```
|
||||
|
||||
KST4Contest processes a response only if both identifiers exactly match the current configuration. The comparison is case-sensitive.
|
||||
|
||||
Identifiers must not be empty and must not contain quotation marks or line breaks.
|
||||
|
||||
If several KST4Contest instances operate in the same network, assign a distinct client identifier to each one, for example:
|
||||
|
||||
```text
|
||||
KST-144
|
||||
KST-432
|
||||
```
|
||||
|
||||
If several AirScout instances are present, use distinct server identifiers as well. This prevents a response intended for one operating position from being processed by another KST4Contest instance.
|
||||
|
||||
### Which Stations Are Requested?
|
||||
|
||||
KST4Contest starts the first periodical AirScout request approximately ten seconds after the chat connection has been established. Further requests follow every 60 seconds.
|
||||
|
||||
An active station is included only if:
|
||||
|
||||
- a usable callsign is available,
|
||||
- a locator is available,
|
||||
- its distance has been calculated,
|
||||
- its distance is below the configured **Maximum QRB**, and
|
||||
- a usable band can be determined.
|
||||
|
||||
Several active chat entries of the same base callsign do not create a separate identical path calculation for every suffix. The returned AirScout information is subsequently assigned to the corresponding active chat variants.
|
||||
|
||||
This selection does more than reduce network traffic. It also prevents AirScout from continuously calculating paths outside the intended working range of the local station.
|
||||
|
||||
### Applying Changed Settings
|
||||
|
||||
The following changes are used for new packets immediately after leaving the input field or changing the checkbox:
|
||||
|
||||
- enabling or disabling the AirScout integration,
|
||||
- server identifier,
|
||||
- client identifier,
|
||||
- automatic or fixed band selection, and
|
||||
- the forced band value.
|
||||
|
||||
After changing the UDP port, disconnect and reconnect the chat or restart KST4Contest. The existing UDP receiver otherwise remains bound to the previous port.
|
||||
|
||||
Click **Save Settings** afterwards to retain the configuration.
|
||||
|
||||
AirScout setup, aircraft display and the meaning of the returned AP information are described under [AirScout Integration](en-AirScout-Integration).
|
||||
Configuration of the interface to AirScout for aircraft scatter detection. Details: [AirScout Integration](en-AirScout-Integration).
|
||||
|
||||
---
|
||||
|
||||
@@ -392,44 +179,7 @@ The dropdown is neither a filter nor an override for complete frequencies. `432.
|
||||
|
||||
Before using the fallback, KST4Contest checks the sender's recent band context. If a complete frequency has been detected for the same station during the previous 30 minutes, that band takes precedence. A fallback setting of `144 MHz` therefore still turns `.100` into `432.100 MHz` if the station mentioned `432.088` shortly before.
|
||||
|
||||
Although this setting is located in the Notification tab, it affects the general QRG parser. It therefore influences the QRG column, detected active bands, priority calculations, band-upgrade hints and other functions which use a known station frequency – not only DX cluster spots.
|
||||
|
||||
Further details, including numbers which are deliberately ignored, are described under [QRG Detection](en-Features#qrg-detection).
|
||||
|
||||
### Local DX Cluster Output
|
||||
|
||||
KST4Contest can forward detected directional opportunities to logging software as DX cluster spots. A frequency recognised in the chat can therefore appear directly in the logger's band map without being entered manually.
|
||||
|
||||
The **Enable the local DX Cluster server …** checkbox starts or stops the local TCP server. When KST4Contest is connected to the chat, the change takes effect immediately.
|
||||
|
||||
The following settings and controls belong to the local DX cluster output:
|
||||
|
||||
- **TCP port**: Port on which KST4Contest accepts connections from DX cluster clients. The default is `8000`. Changing the port while the server is running restarts it on the new port. The logger must then reconnect to that port.
|
||||
- **Fallback band for relative QRG detection**: The global fallback band described above. The test spot uses `.300` on this band. Actual spots use the QRG detected for the respective sender.
|
||||
- **Spotter callsign**: Callsign shown as the spotter in generated DX cluster entries. A callsign different from the contest callsign should be used. Some logging programs filter spots apparently sent by the local station or treat them differently from external spots.
|
||||
- **Send test spot**: Sends the following entry to every currently connected DX cluster client:
|
||||
|
||||
```text
|
||||
Spotted callsign: DO5AMF
|
||||
Comment: Testing DXC-Spot: Congrats, you donated $100!
|
||||
Frequency: .300 on the selected fallback band
|
||||
```
|
||||
|
||||
With `144 MHz` selected as the fallback band, the resulting frequency is approximately `144.300 MHz`.
|
||||
|
||||
The comment is a deliberately retained Easter egg. It has no technical meaning and, despite being remarkably specific, does not initiate a payment. Its practical purpose is to make the test spot easy to identify in the logging software.
|
||||
|
||||
The test works only if
|
||||
|
||||
1. KST4Contest is connected to the ON4KST chat,
|
||||
2. the local DX cluster server is enabled, and
|
||||
3. at least one DX cluster client is connected to KST4Contest.
|
||||
|
||||
KST4Contest does not generate a spot for every frequency found in the chat. An actual spot is created only when a directed message between two stations indicates a relevant antenna direction for the local station and a usable frequency is known for the sender.
|
||||
|
||||
The complete derivation and logger setup are described under [Built-in DX Cluster Server](en-DX-Cluster-Server).
|
||||
|
||||
---
|
||||
Although the setting is located in the Notification tab, it affects the general QRG parser. It therefore influences the QRG column, detected active bands, priority calculations, band-upgrade hints and other functions which use a known station frequency – not only DX cluster spots.
|
||||
|
||||
### Band Upgrade Hint after a Log Entry
|
||||
|
||||
@@ -467,261 +217,42 @@ Further explanation: [Band Upgrade Hint after a Log Entry](en-Features#band-upgr
|
||||
|
||||
## Shortcut Settings
|
||||
|
||||

|
||||
|
||||
Each entry in the upper part of the **Shortcuts** tab creates one button above the message field in the main window. Pressing the button appends its configured text to the current contents of the send field.
|
||||
|
||||
If the shortcut contains a [variable](en-Macros-and-Variables#variables), it is replaced with its current value when the text is inserted. A shortcut such as
|
||||
|
||||
```text
|
||||
pse call me at MYQRGSHORT
|
||||
```
|
||||
|
||||
may therefore insert:
|
||||
|
||||
```text
|
||||
pse call me at 144.388
|
||||
```
|
||||
|
||||
The exact entries `MYQRG` and `SECONDQRG` are additionally highlighted as QRG buttons. They insert the current frequency of the primary or secondary chat category respectively.
|
||||
|
||||
The shortcut `/SETNAME MYQRG` is highlighted as well. When it is pressed, KST4Contest resolves `MYQRG` and inserts the complete server command into the send field. The command is not transmitted automatically and can still be checked before it is sent with `Enter` or **TX**.
|
||||
|
||||
|
||||
The order of the table determines the order of the buttons in the main window. Manage the entries as follows:
|
||||
|
||||
1. **Add shortcut** creates a new entry at the beginning of the list and immediately opens it for editing.
|
||||
2. Double-click an existing entry to edit it. Press `Enter` to accept the change.
|
||||
3. To remove an entry, delete its complete contents and confirm with `Enter`.
|
||||
4. Use **Move selected up** and **Move selected down** to change the position of the selected entry.
|
||||
|
||||
Changes appear in the main window immediately. Use **Save Settings** afterwards if they should remain available after the next program start.
|
||||
Configuration of quick-access buttons that appear directly in the main window. Clicking a button inserts the configured text into the send field. All [variables](en-Macros-and-Variables#variables) can be used.
|
||||
|
||||
---
|
||||
|
||||
## Snippet Settings
|
||||
|
||||
Snippets are longer text blocks intended primarily for messages to a selected station. They can be opened through:
|
||||
Text snippets are accessible via:
|
||||
|
||||
- a right-click on a station in the user list;
|
||||
- a right-click on a message in the public chat table;
|
||||
- a right-click on a message in the PM table; or
|
||||
- `Ctrl+1` through `Ctrl+0` for the first ten entries in the snippet list.
|
||||
- **Right-click** on a callsign in the user list
|
||||
- **Right-click** in the CQ message table
|
||||
- **Right-click** in the PM message table
|
||||
- **Keyboard shortcuts**: `Ctrl+1` to `Ctrl+0` for the first 10 snippets
|
||||
|
||||
The keyboard mapping follows the order of the table:
|
||||
|
||||
| Key combination | Snippet |
|
||||
|---|---:|
|
||||
| `Ctrl+1` | first entry |
|
||||
| `Ctrl+2` | second entry |
|
||||
| … | … |
|
||||
| `Ctrl+9` | ninth entry |
|
||||
| `Ctrl+0` | tenth entry |
|
||||
|
||||
A snippet selected from a context menu is appended to the message already prepared in the send field. Selecting a station or message will normally have inserted the appropriate `/cq` destination first.
|
||||
|
||||
A keyboard shortcut behaves differently: it replaces the current contents of the send field with a complete directed message:
|
||||
|
||||
```text
|
||||
/cq CALLSIGN snippet text
|
||||
```
|
||||
|
||||
The complete visible callsign, including any suffix, is retained. Selecting `9A0BB-70` may therefore produce:
|
||||
|
||||
```text
|
||||
/cq 9A0BB-70 pse ur qrg?
|
||||
```
|
||||
|
||||
The selected station's chat category is retained for transmission. If no station is selected, or no snippet is assigned to the chosen key combination, nothing is inserted.
|
||||
|
||||
Variables are resolved when the snippet is inserted. Station-specific variables such as `QRZNAME`, `FIRSTAP` and `SECONDAP` refer to the currently selected station. The prepared message is not sent automatically and can still be checked or edited. Press `Enter` or **TX** to send it; `Esc` clears the send field.
|
||||
|
||||
The snippet list is edited in the same way as the shortcut list:
|
||||
|
||||
1. **Add new snippet** creates a new entry at the beginning of the list.
|
||||
2. Double-click an existing entry to edit it.
|
||||
3. Press `Enter` to accept the change.
|
||||
4. Confirming an empty entry removes it.
|
||||
5. **Move selected up** and **Move selected down** change both the displayed order and the assignment to `Ctrl+1` through `Ctrl+0`.
|
||||
|
||||
The context menus and keyboard mappings are updated immediately. Use **Save Settings** afterwards to store the modified list permanently.
|
||||
|
||||
The complete list of available placeholders and their limitations is described under [Macros and Variables](en-Macros-and-Variables).
|
||||
If a callsign is selected in the user list, the snippet is addressed as a direct message:
|
||||
`/CQ CALLSIGN <snippet text>`
|
||||
|
||||
---
|
||||
|
||||
## Beacon Settings
|
||||
|
||||

|
||||
Configuration of an automatic interval beacon in the public chat channel. Recommended: use the `MYQRG` variable in the text so the current frequency is always up to date. Interval and text are freely configurable.
|
||||
|
||||
A beacon sends a public CQ message at regular intervals. It is intended for operating situations in which the local station calls CQ on a fixed frequency for an extended period. Other stations receive current QRG information without requiring the operator to enter the same message repeatedly.
|
||||
|
||||
KST4Contest uses one shared timer for both chat categories. Each category nevertheless has its own enable setting and message template:
|
||||
|
||||
- **Enable CQ beacon** enables the beacon for the respective category.
|
||||
- **Beacon message** contains the public message for that category.
|
||||
- **Shared beacon interval** sets the common interval used by both categories.
|
||||
|
||||
When both beacons are enabled, they are sent one after the other in their respective categories during the same timer run. The second beacon is only considered while the second chat is enabled and connected.
|
||||
|
||||
### Interval and timer behaviour
|
||||
|
||||
The interval is entered in whole minutes. The minimum permitted value is one minute.
|
||||
|
||||
After the chat connection has been established, KST4Contest performs the first beacon check after approximately ten seconds. The configured interval applies after that initial check.
|
||||
|
||||
Changing the interval while connected restarts the countdown with the new value. The change itself does not cause an immediate beacon message.
|
||||
|
||||
Both categories use the same timer. Separate intervals for the primary and secondary chat cannot be configured.
|
||||
|
||||
### Message text and variables
|
||||
|
||||
A beacon may use the [global variables](en-Macros-and-Variables#variables-in-the-beacon) which depend only on the local station:
|
||||
|
||||
- `MYQRG`
|
||||
- `MYQRGSHORT`
|
||||
- `SECONDQRG`
|
||||
- `MYLOCATOR`
|
||||
- `MYLOCATORSHORT`
|
||||
- `MYCALL`
|
||||
- `MYQTF`
|
||||
|
||||
A suitable message for the primary chat category is:
|
||||
|
||||
```text
|
||||
calling cq at MYQRGSHORT, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Use `SECONDQRG` for the second chat if it operates on a different frequency:
|
||||
|
||||
```text
|
||||
calling cq at SECONDQRG, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Variables are resolved again on every timer run. If the logging software changes the QRG stored in `MYQRG`, the next beacon can already contain the updated value. The message template does not have to be edited.
|
||||
|
||||
`MYQRG` and `MYQRGSHORT` always refer to the primary chat category. Enabling or selecting the second chat does not change this assignment.
|
||||
|
||||
Station-specific variables such as `QRZNAME`, `FIRSTAP` and `SECONDAP` require a selected remote station. A public beacon has no such destination, so these variables are not resolved in beacon messages.
|
||||
|
||||
### Message validation
|
||||
|
||||
KST4Contest validates both the configured template and the message which remains after all variables have been resolved.
|
||||
|
||||
The following restrictions apply:
|
||||
|
||||
- The final message must not be empty.
|
||||
- It must not exceed 120 characters.
|
||||
- The protocol separator `|` is not permitted.
|
||||
- Line breaks are not permitted.
|
||||
|
||||
An invalid entry is not accepted as the new beacon configuration. If a template becomes invalid only after resolving its variables, for example because the resulting text exceeds 120 characters, that beacon run is skipped.
|
||||
|
||||
A template which consists only of a temporarily empty global variable may still be stored. This can happen during startup before the first QRG has been received from the logger. KST4Contest does not send an empty message while the variable has no usable value.
|
||||
|
||||
### When should the beacon be disabled?
|
||||
|
||||
The beacon is useful only while its QRG matches the actual operation. Leaving it enabled while searching the band or changing frequencies frequently may cause other stations to look for the local station on an obsolete frequency.
|
||||
|
||||
In plain terms: the beacon saves work while calling CQ on a fixed QRG. It should be disabled while moving around the band.
|
||||
|
||||
Changes take effect during the current connection. Use **Save Settings** afterwards to retain the enable settings, message templates and interval for the next program start.
|
||||
> **Tip**: Enable the beacon when calling CQ and quickly disable it in the settings window when not calling.
|
||||
|
||||
---
|
||||
|
||||
## Messagehandling Settings (from v1.25)
|
||||
|
||||

|
||||
New settings section with the following options:
|
||||
|
||||
The most important use of the general automatic reply concerns stations which are logged into the ON4KST chat but are not taking part in the current contest. During larger contests, sked requests are sometimes sent to many logged-in stations without first checking whether they are participating. Without an automatic reply, the recipients would have to enter the same refusal repeatedly.
|
||||
|
||||
KST4Contest can answer these requests with a predefined message. A separate function provides the local QRG when a private message contains a recognised frequency request. Both functions can be enabled independently.
|
||||
|
||||
### General automatic reply
|
||||
|
||||
**Enable automatic reply to all private messages** answers incoming private messages with the text entered in the adjacent field. One common text is used for both chat categories. The configured capitalisation is preserved.
|
||||
|
||||
A suitable message is:
|
||||
|
||||
```text
|
||||
Sri, I am not taking part in this contest. No skeds.
|
||||
```
|
||||
|
||||
Do not add the `[KST4C Automsg]` prefix to the configured text. KST4Contest inserts it automatically.
|
||||
|
||||
The message received by the remote station may therefore be:
|
||||
|
||||
```text
|
||||
[KST4C Automsg] Sri, I am not taking part in this contest. No skeds.
|
||||
```
|
||||
|
||||
The incoming private message remains visible. The function neither blocks nor discards the request; it merely avoids entering the same answer repeatedly.
|
||||
|
||||
The reply is addressed to the sender's complete callsign, including any visible suffix, and sent through the chat category in which the private message was received. This distinction matters when two categories are connected at the same time: a request received through the microwave chat must not be answered accidentally through the VHF/UHF chat.
|
||||
|
||||
An empty or whitespace-only answer does not produce an automatic message. A configured text containing the protocol separator `|` or a line break is rejected as well.
|
||||
|
||||
### Automatic QRG reply
|
||||
|
||||
**Enable automatic QRG replies** reacts to common QRG requests. Matching is case-insensitive and looks for the following text fragments:
|
||||
|
||||
```text
|
||||
ur qrg?
|
||||
your qrg?
|
||||
qrg?
|
||||
freq?
|
||||
pse qrg
|
||||
```
|
||||
|
||||
The answer contains only the QRG belonging to the category in which the request was received:
|
||||
|
||||
| Incoming private message | QRG used for the reply |
|
||||
|---|---|
|
||||
| Primary category | current QRG of the primary category |
|
||||
| Second chat category | current QRG of the second category |
|
||||
|
||||
A possible reply is:
|
||||
|
||||
```text
|
||||
[KST4C Automsg] QRG is: 144.300.00
|
||||
```
|
||||
|
||||
The values come from the same QRG fields used by `MYQRG` and `SECONDQRG`. The primary QRG may be entered manually or updated through [TRX synchronisation](#trx-sync-settings). The second category uses the value configured or entered for that category.
|
||||
|
||||
If no QRG is available for the incoming category, KST4Contest does not send an incomplete reply. A message containing `QRG is:` without a frequency would technically answer the request while providing no useful information. It is therefore rejected before reaching the transmit queue.
|
||||
|
||||
When both automatic-reply functions are enabled, the QRG reply takes precedence. A recognised QRG request does not additionally produce the general reply. If the required QRG is missing, KST4Contest does not fall back to the general answer.
|
||||
|
||||
### Protection against repeated replies
|
||||
|
||||
Every automatically generated reply contains the fixed prefix:
|
||||
|
||||
```text
|
||||
[KST4C Automsg]
|
||||
```
|
||||
|
||||
The general and QRG-specific functions ignore messages which already contain this prefix. This prevents two clients with automatic replies enabled from answering each other indefinitely.
|
||||
|
||||
A common two-minute cooldown additionally applies to both reply types. The cooldown is tracked separately for each complete callsign and chat category.
|
||||
|
||||
This means:
|
||||
|
||||
- `CALLSIGN-2` and `CALLSIGN-70` have separate cooldowns.
|
||||
- The same complete callsign can still receive an independent reply in another chat category.
|
||||
- A general reply also suppresses a QRG reply to the same callsign in the same category for two minutes.
|
||||
- A QRG reply likewise suppresses the general reply.
|
||||
|
||||
The cooldown starts only after KST4Contest has produced a complete, locally valid message and placed it in the transmit queue. A missing QRG, an empty general reply or a message rejected because of invalid characters does not start the cooldown. Once the missing information has been corrected, a valid reply can therefore be generated immediately.
|
||||
|
||||
> **Note**: The configured text should describe the actual operating status clearly. If the station is only observing the contest and does not accept skeds, say exactly that. A vague automatic message is likely to produce another question – which is precisely the work this function is intended to avoid.
|
||||
|
||||
Changes take effect during the current connection. Use **Save Settings** afterwards to retain the enable settings and general reply text for the next program start.
|
||||
|
||||
Further background: [Automatic Replies to Private Messages](en-Features#automatic-replies-to-private-messages-from-v125).
|
||||
- **Auto-reply to all incoming messages**: Configurable automatic reply to private messages.
|
||||
- **Auto-reply with own CQ QRG**: When someone asks for your QRG, KST4Contest automatically replies with the content of the `MYQRG` variable.
|
||||
- **Default filter for the userinfo window**: Pre-configured message filter for the station info window *(for Gianluca :-) )*.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Win-Test Network Listener (from v1.31)
|
||||
|
||||
The Win-Test network listener processes the native Win-Test UDP protocol. It is independent of the general QSO UDP listener on port `12060` and has three separate tasks:
|
||||
@@ -765,118 +296,27 @@ Data handling and QRG selection: [Log Synchronisation – Win-Test](en-Log-Sync#
|
||||
|
||||
---
|
||||
|
||||
## PSTRotator Settings (from v1.31)## PSTRotator Settings (from v1.31, fully configurable from v1.40)
|
||||
## PSTRotator Settings (from v1.31)
|
||||
|
||||
KST4Contest can set an antenna direction through the PSTRotator UDP interface and use the current position reported by PSTRotator as the local QTF.
|
||||
KST4Contest can control antenna direction via PSTRotator.
|
||||
|
||||
The settings are located in the **Station** tab:
|
||||
Settings:
|
||||
- **Enable/Disable**: Checkbox in Preferences (from v1.40).
|
||||
- **IP address**: IP address of the PSTRotator computer (default: `127.0.0.1` when running on the same PC).
|
||||
- **Port**: Communication port of PSTRotator.
|
||||
|
||||
| Setting | Default | Purpose |
|
||||
|---|---:|---|
|
||||
| **Enable PSTRotator** | disabled | Starts UDP communication with PSTRotator |
|
||||
| **PSTRotator host** | `127.0.0.1` | Hostname or IP address of the computer running PSTRotator |
|
||||
| **PSTRotator UDP port** | `12000` | UDP port on which PSTRotator receives control commands |
|
||||
|
||||
When both applications run on the same computer, `127.0.0.1` is normally the clearest setting. If PSTRotator runs on another computer in the station network, enter its reachable IP address or DNS name.
|
||||
|
||||
The port must be between `1` and `65534`. Port `65535` cannot be used because PSTRotator reports its position on the following port.
|
||||
|
||||
### Preparing PSTRotator
|
||||
|
||||
Configure the same UDP port under **Communication → UDP Control Port** in PSTRotator and enable **UDP Control**.
|
||||
|
||||
The default configuration uses the following pair:
|
||||
|
||||
| Direction | UDP port |
|
||||
|---|---:|
|
||||
| KST4Contest → PSTRotator | `12000` |
|
||||
| PSTRotator → KST4Contest | `12001` |
|
||||
|
||||
KST4Contest binds the return port automatically. It is not configured separately.
|
||||
|
||||
When the programs run on different computers, the local firewalls and station network must permit UDP traffic in both directions. KST4Contest cannot receive position reports if another program already occupies the return port.
|
||||
|
||||
The complete UDP protocol is documented in the [PSTRotatorAz User Manual](https://www.qsl.net/yo3dmu/ANT/PstRotatorAz%20User%20Manual.pdf).
|
||||
|
||||
### Updating the local QTF
|
||||
|
||||
KST4Contest asks PSTRotator for the current azimuth and operating mode every two seconds. The reported azimuth becomes `actualQTF`.
|
||||
|
||||
While PSTRotator integration is enabled, the QTF field in the main window is therefore read-only. It displays the most recent position reported by PSTRotator.
|
||||
|
||||
This QTF is used by:
|
||||
|
||||
- the direction filter;
|
||||
- the derivation of direction opportunities;
|
||||
- the Priority Score;
|
||||
- the antenna sector on the station map;
|
||||
- the AP and sked timeline; and
|
||||
- the `MYQTF` variable.
|
||||
|
||||
A received rotator position is therefore more than a displayed value. It changes several functions which depend on the current antenna direction.
|
||||
|
||||
The current integration uses azimuth only. Elevation control and complete azimuth/elevation tracking are outside its present scope.
|
||||
|
||||
### Applying changed settings
|
||||
|
||||
The enable setting, host and port are evaluated when the rotator connection is started. After changing them, disconnect and reconnect the ON4KST session or restart KST4Contest.
|
||||
|
||||
Use **Save Settings** afterwards so that the values are restored at the next program start.
|
||||
> **Note**: After clicking a direction button, KST4Contest waits briefly for the rotator response. With slow rotors (e.g. SPID) there may be a small delay.
|
||||
|
||||
---
|
||||
|
||||
## Sniffer Settings (from v1.31)
|
||||
|
||||
QSO monitoring is intended for stations whose communication should remain visible during busy chat activity. This may be a rare station, a DXpedition or another station in the same contest team whose sked arrangements should not disappear in the general message traffic.
|
||||
The QSO sniffer filters chat messages from configurable callsigns and forwards them to the PM window.
|
||||
|
||||
The callsign list is maintained under **QSO monitoring** in the **Notification** tab.
|
||||
Settings:
|
||||
- **Callsign list**: Comma-separated list of callsigns whose messages are always forwarded to the PM window.
|
||||
|
||||
For every monitored base callsign, KST4Contest additionally shows messages in the PM table when a variant of that callsign is either the sender or the receiver. Both connected chat categories are included.
|
||||
|
||||
The list intentionally uses the normalised base callsign. The following entries therefore produce the same monitoring entry:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
DN9APW-144
|
||||
```
|
||||
|
||||
In every case, KST4Contest stores and displays:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
```
|
||||
|
||||
The different KST suffixes of one station do not have to be entered separately. A later message sent by `DN9APW-2` or addressed to `DN9APW-70` is covered by the same entry.
|
||||
|
||||
This aggregation applies to QSO monitoring only. Active ChatMember objects, complete message destinations and chat categories remain separate. A message addressed to `DN9APW-70` is therefore not redirected to `DN9APW-2`.
|
||||
|
||||
A monitored message is marked in the PM table using the complete visible callsigns of its sender and receiver:
|
||||
|
||||
```text
|
||||
Sniffed: (DN9APW-2 > DL0ABC-70) Message text
|
||||
```
|
||||
|
||||
The original message remains in its normal table. Monitoring changes neither its contents nor its routing.
|
||||
|
||||
A message is included only when the monitored station is actually its sender or receiver. Merely mentioning the callsign in the message text is not sufficient. Public messages sent by a monitored station are included as well; their receiver is displayed as `ALL`.
|
||||
|
||||
A message which is already addressed directly to the local callsign remains a normal private message and does not receive an additional `Sniffed:` marker.
|
||||
|
||||
Manage the list as follows:
|
||||
|
||||
1. Press **Add monitored callsign** to add an entry.
|
||||
2. Double-click an existing entry to edit it and press `Enter` to apply the change.
|
||||
3. To remove an entry, delete the complete cell contents and press `Enter`.
|
||||
|
||||
The entered value may contain a visible KST suffix or portable components. KST4Contest normalises it to the base callsign before storing it. Different variants of the same base callsign are therefore treated as duplicates.
|
||||
|
||||
Changes to the list take effect immediately. Press **Save Settings** afterwards to retain them. The base callsigns are stored in `preferences.xml` and restored at the next program start.
|
||||
|
||||
> Base-callsign monitoring across KST suffixes is included in Nightly / v1.42.
|
||||
|
||||
Further background and the distinction from message routing: [QSO Sniffer](en-Features#qso-sniffer-from-v131).
|
||||
Use case: Keep track of important stations (e.g. DX expeditions or trusted contest allies) without constantly monitoring the main chat.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -43,30 +43,6 @@ Similar settings:
|
||||
|
||||
---
|
||||
|
||||
## Testing the Connection
|
||||
|
||||
After the logger's DX cluster client has connected, use **Send test spot** to generate the following entry:
|
||||
|
||||
```text
|
||||
Spotted callsign: DO5AMF
|
||||
Comment: Testing DXC-Spot: Congrats, you donated $100!
|
||||
Frequency: .300 on the configured fallback band
|
||||
```
|
||||
|
||||
With `144 MHz` selected as the fallback band, the spot appears at approximately `144.300 MHz`.
|
||||
|
||||
The comment is a deliberately retained Easter egg. It makes the test entry easy to identify but has no other function. In particular, no donation or other external action is triggered.
|
||||
|
||||
Three conditions must be met before running the test:
|
||||
|
||||
1. KST4Contest is connected to the ON4KST chat.
|
||||
2. The local DX cluster server is enabled.
|
||||
3. The logging software's DX cluster client is connected to KST4Contest.
|
||||
|
||||
If no client is connected, KST4Contest displays a corresponding message. A successful test therefore confirms that at least one connected client received the generated spot.
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
A spot is generated when **both** conditions are met:
|
||||
|
||||
@@ -185,27 +185,6 @@ KST4Contest detects such messages that contain your own callsign and automatical
|
||||
|
||||
---
|
||||
|
||||
## Automatic Replies to Private Messages (from v1.25)
|
||||
|
||||
Not every station logged into the ON4KST chat is taking part in the current contest. Sked requests may nevertheless be sent to many visible callsigns without first checking whether they are participating. Without an automatic reply, those stations would have to enter the same refusal repeatedly.
|
||||
|
||||
KST4Contest can answer such private messages with a predefined text. The incoming message remains visible; it is neither blocked nor discarded. A separate QRG reply recognises common requests such as `qrg?`, `freq?` and `pse qrg`.
|
||||
|
||||
When two chat categories are connected, the original context is retained. The reply is addressed to the complete sender callsign and sent through the category in which the request arrived. A QRG request receives only the QRG belonging to that category.
|
||||
|
||||
If the required QRG is missing, KST4Contest sends no incomplete answer. Empty or locally invalid general reply texts are rejected as well.
|
||||
|
||||
Automatic replies need limits. KST4Contest adds the fixed prefix `[KST4C Automsg]`, ignores incoming messages which already contain that prefix and permits only one automatic reply to the same complete callsign in the same category within two minutes. The cooldown is shared by the general and QRG-specific reply functions.
|
||||
|
||||
A rejected reply does not start the cooldown. After entering the missing QRG or correcting the configured text, KST4Contest can therefore answer the next request immediately.
|
||||
|
||||
In plain terms: the function cannot prevent indiscriminate sked requests. It prevents the recipient from having to answer every one of them with the same refusal. It is not intended to simulate a conversation, let alone start an endless discussion with another automatic client.
|
||||
|
||||
Configuration, recognised QRG requests and category handling: [Configuration – Messagehandling Settings](en-Configuration#messagehandling-settings-from-v125).
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Multi-Channel Login (from v1.26)
|
||||
|
||||
Simultaneous login to **two chat categories** (e.g. 144 MHz and 432 MHz). Both chats are monitored in parallel.
|
||||
@@ -315,49 +294,10 @@ Win-Test handover: [Log Synchronisation – Win-Test](en-Log-Sync#win-test)
|
||||
|
||||
## QSO Sniffer (from v1.31)
|
||||
|
||||
During a contest, it may be useful to follow the communication of one particular station. This is not limited to rare stations or DXpeditions. Sked arrangements made by another station in the same team can disappear just as easily in a busy public chat.
|
||||
|
||||
KST4Contest can therefore show every message sent or received by a monitored station additionally in the PM table. The message remains in its original table at the same time.
|
||||
|
||||
Monitoring uses the normalised base callsign. An entry for `DN9APW` consequently covers messages sent by or addressed to:
|
||||
|
||||
```text
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
DN9APW-144
|
||||
DN9APW-432
|
||||
```
|
||||
|
||||
Entering `DN9APW-70` in the monitoring list still stores `DN9APW`. A station using several band- or operating-position-specific KST suffixes therefore needs only one entry.
|
||||
|
||||
The actual message retains the complete callsigns:
|
||||
|
||||
```text
|
||||
Sniffed: (DN9APW-70 > 9A0BB-23) pse sked 19:30
|
||||
```
|
||||
|
||||
This distinction is intentional. Monitoring aggregates the variants so that their communication remains visible. Message routing does not aggregate them because the intended login would otherwise become ambiguous.
|
||||
|
||||
The base callsign is evaluated across both connected chat categories. The category of each individual message remains unchanged.
|
||||
|
||||
The monitoring view includes:
|
||||
|
||||
- directed messages sent by a monitored station;
|
||||
- directed messages addressed to a monitored station; and
|
||||
- public messages sent by a monitored station to `ALL`.
|
||||
|
||||
A callsign which merely occurs in the message text does not trigger monitoring.
|
||||
|
||||
Messages already addressed directly to the local callsign remain normal private messages and are not additionally marked as `Sniffed:`. QSO monitoring also does not generate a separate notification sound. Sound notifications for private messages actually addressed to the local station remain independent.
|
||||
|
||||
The function does not request additional messages from the ON4KST server. It only provides another view of chat traffic which KST4Contest has already received.
|
||||
|
||||
In plain terms: QSO monitoring does not decide whether a message really contains a sked or matters to the local contest operation. It makes the communication of the selected station easier to find. The operator still decides what to do with it.
|
||||
The QSO sniffer monitors the chat for messages from a configurable callsign list and automatically forwards them to the **PM window**. This prevents relevant messages from being lost in the general chat traffic.
|
||||
|
||||
Configuration: [Configuration – Sniffer Settings](en-Configuration#sniffer-settings-from-v131)
|
||||
|
||||
Complete callsigns and chat-category separation: [Multi-Channel Login](#multi-channel-login-from-v126)
|
||||
|
||||
---
|
||||
|
||||
## Win-Test Integration
|
||||
@@ -379,48 +319,9 @@ Settings: [Win-Test Network Listener](en-Configuration#win-test-network-listener
|
||||
|
||||
## PSTRotator Interface (from v1.31, fully configurable from v1.40)
|
||||
|
||||
KST4Contest can point the antenna at the selected remote station through the PSTRotator UDP interface. The required azimuth is calculated from the local and remote locators.
|
||||
KST4Contest can control antenna direction directly via **PSTRotator**. When a station is selected in the user list, the rotator can automatically be turned to the QTF of the selected station.
|
||||
|
||||
After selecting a station, the **Further Info** section provides the **Turn ant1 to …** button:
|
||||
|
||||

|
||||
|
||||
Pressing the button performs the following steps:
|
||||
|
||||
1. KST4Contest disables PSTRotator tracking mode.
|
||||
2. The QTF of the selected station is transmitted as an integer azimuth.
|
||||
3. PSTRotator controls the configured rotor.
|
||||
4. The reported position becomes the current QTF in KST4Contest.
|
||||
|
||||
The button remains visible while PSTRotator integration is disabled. In that case, no rotator command is sent.
|
||||
|
||||
### Position feedback and SPID compatibility
|
||||
|
||||
KST4Contest requests the current azimuth every two seconds. Position reports update the local QTF field and every function which depends on the antenna direction.
|
||||
|
||||
Some SPID configurations occasionally ignore the first direction command. KST4Contest therefore checks two seconds later whether PSTRotator reported movement or reached the requested target.
|
||||
|
||||
If the position remained unchanged and the target was not reached, KST4Contest sends one compatibility sequence through `0°` followed by the actual target value.
|
||||
|
||||
This check runs in the background. The user interface remains responsive during the two-second interval. A new direction command replaces the pending check belonging to the previous command.
|
||||
|
||||
### What does the reported position confirm?
|
||||
|
||||
The displayed QTF is the azimuth reported by PSTRotator. It confirms that KST4Contest received a usable UDP position message.
|
||||
|
||||
Depending on the station setup, it does not necessarily prove that the antenna is mechanically aligned to exactly that value. This still depends on the controller, calibration, configured offsets and the feedback available to PSTRotator.
|
||||
|
||||
UDP itself provides no delivery acknowledgement. If the displayed QTF does not change, check:
|
||||
|
||||
- that **UDP Control** is enabled in PSTRotator;
|
||||
- that the host and control port match;
|
||||
- that `control port + 1` is available for the position report;
|
||||
- that the firewall permits both UDP directions; and
|
||||
- that PSTRotator itself displays a plausible rotor position.
|
||||
|
||||
In plain terms: KST4Contest provides the target and processes the reported position. The mechanical reality remains the responsibility of the rotor – and occasionally a glance outside.
|
||||
|
||||
Configuration and port assignment: [Configuration – PSTRotator Settings](en-Configuration#pstrotator-settings-from-v131-fully-configurable-from-v140).
|
||||
Configuration: [Configuration – PSTRotator Settings](en-Configuration#pstrotator-settings-from-v131)
|
||||
|
||||
---
|
||||
|
||||
@@ -602,21 +503,10 @@ The timeline is a preview. AirScout data can change, and a stored sked guarantee
|
||||
|
||||
## Interval Beacon
|
||||
|
||||
KST4Contest can send recurring CQ messages to the public chat. The beacon is intended for longer periods of calling CQ on a fixed frequency: it publishes the local QRG regularly without requiring the operator to enter the same text again.
|
||||
|
||||
Both chat categories use one shared interval, but each category has its own enable setting and message template. The second beacon is only sent while the second chat is enabled and connected.
|
||||
|
||||
Global variables such as `MYQRG`, `SECONDQRG`, `MYLOCATOR` and `MYQTF` are resolved immediately before every transmission. A QRG updated by the logging software can therefore appear in the next beacon.
|
||||
|
||||
Before transmission, KST4Contest validates the completely resolved message. Empty messages, line breaks, the protocol separator `|` and messages exceeding 120 characters are not sent.
|
||||
|
||||
Disable the beacon while searching the band or changing QRG frequently. An automatically published frequency is useful only while somebody is actually listening and calling there.
|
||||
|
||||
Configuration, timer behaviour and available variables: [Configuration – Beacon Settings](en-Configuration#beacon-settings).
|
||||
Automatic CQ messages in the public channel at a configurable interval. Recommended: use the `MYQRG` variable so the current frequency is always accurate. Details: [Configuration – Beacon Settings](en-Configuration#beacon-settings).
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Simplelogfile
|
||||
|
||||
File-based log evaluation using regex. Details: [Log Synchronisation](en-Log-Sync#method-1-universal-file-based-callsign-interpreter-simplelogfile).
|
||||
|
||||
@@ -140,41 +140,16 @@ Replaced by the current antenna direction in words (e.g. `north`, `north east`,
|
||||
|
||||
## Variables in the Beacon
|
||||
|
||||
A public beacon has no selected remote station. It can therefore make meaningful use only of variables which depend on the local station and its current configuration:
|
||||
All variables can also be used in the **automatic beacon** (interval messages). Recommended beacon configuration:
|
||||
|
||||
| Variable | Value used in the beacon |
|
||||
|---|---|
|
||||
| `MYQRG` | current QRG of the primary chat category |
|
||||
| `MYQRGSHORT` | first seven characters of the primary QRG |
|
||||
| `SECONDQRG` | current QRG of the second chat category |
|
||||
| `MYLOCATOR` | complete configured locator of the local station |
|
||||
| `MYLOCATORSHORT` | four-character locator of the local station |
|
||||
| `MYCALL` | configured local callsign |
|
||||
| `MYQTF` | current antenna heading |
|
||||
|
||||
`QRZNAME`, `FIRSTAP` and `SECONDAP` require a selected remote station. They are therefore not resolved in a public beacon.
|
||||
|
||||
A suitable configuration for the primary category is:
|
||||
|
||||
```text
|
||||
calling cq at MYQRGSHORT, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
calling cq at MYQRG, loc MYLOCATOR, GL all!
|
||||
```
|
||||
|
||||
For the second category, use `SECONDQRG` if that category should publish a different frequency:
|
||||
|
||||
```text
|
||||
calling cq at SECONDQRG, ant MYQTF deg, loc MYLOCATOR
|
||||
```
|
||||
|
||||
Global variables are evaluated again on every timer run. A QRG updated by the logging software can therefore appear in the next beacon message.
|
||||
|
||||
The completely resolved text must contain at least one valid character and must not exceed 120 characters. The protocol separator `|` and line breaks are not permitted. If the text is still empty or invalid when transmission is due, that beacon run is skipped.
|
||||
|
||||
The common interval and the behaviour of both chat categories are described under [Configuration – Beacon Settings](en-Configuration#beacon-settings).
|
||||
Since KST4Contest automatically reads QRG data from chat messages: if other stations also use KST4Contest, they will immediately see your QRG in the QRG column of their user list.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Example Contest Workflow with Macros
|
||||
|
||||
1. Select a station in the user list → callsign is now pre-selected.
|
||||
|
||||
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 324 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 4.1 MiB After Width: | Height: | Size: 5.1 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.4 MiB |
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Derives the jpackage --add-modules list from module-info.java so that the
|
||||
* packaging scripts never drift from the module descriptor again.
|
||||
*
|
||||
* Run as a single file source program, which behaves identically on the Linux,
|
||||
* macOS and Windows runners:
|
||||
*
|
||||
* java packaging/AddModules.java print the module list
|
||||
* java packaging/AddModules.java --verify-pom fail if pom.xml drifted
|
||||
*
|
||||
* Only platform modules are emitted. Third party requires such as jlayer are
|
||||
* skipped because they are supplied as ordinary jars on the class path, and
|
||||
* automatic modules cannot be linked into a runtime image at all. Test only
|
||||
* requires such as org.junit.jupiter.api are skipped for the same reason.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class AddModules {
|
||||
|
||||
private static final Path DESCRIPTOR =
|
||||
Path.of("src", "main", "java", "module-info.java");
|
||||
|
||||
private static final Path POM = Path.of("pom.xml");
|
||||
|
||||
/** Matches "requires [transitive] [static] some.module;" in any order. */
|
||||
private static final Pattern REQUIRES = Pattern.compile(
|
||||
"requires\\s+((?:transitive\\s+|static\\s+)*)([A-Za-z0-9_.]+)\\s*;");
|
||||
|
||||
private static final Pattern ADD_MODULE =
|
||||
Pattern.compile("<addmodule>\\s*([A-Za-z0-9_.]+)\\s*</addmodule>");
|
||||
|
||||
private static final Pattern BLOCK_COMMENT =
|
||||
Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL);
|
||||
|
||||
private static final Pattern LINE_COMMENT = Pattern.compile("//[^\\n]*");
|
||||
|
||||
private AddModules() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
boolean verifyPom = args.length > 0 && "--verify-pom".equals(args[0]);
|
||||
|
||||
Set<String> required = platformModules(read(DESCRIPTOR));
|
||||
if (required.isEmpty()) {
|
||||
fail("No platform modules found in " + DESCRIPTOR);
|
||||
}
|
||||
|
||||
if (!verifyPom) {
|
||||
System.out.println(String.join(",", required));
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> declared = new TreeSet<>();
|
||||
Matcher matcher = ADD_MODULE.matcher(read(POM));
|
||||
while (matcher.find()) {
|
||||
declared.add(matcher.group(1));
|
||||
}
|
||||
|
||||
if (declared.equals(required)) {
|
||||
System.out.println("pom.xml <addmodules> matches module-info.java ("
|
||||
+ required.size() + " modules)");
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> missing = new TreeSet<>(required);
|
||||
missing.removeAll(declared);
|
||||
Set<String> extra = new TreeSet<>(declared);
|
||||
extra.removeAll(required);
|
||||
|
||||
System.err.println("pom.xml <addmodules> drifted from module-info.java.");
|
||||
if (!missing.isEmpty()) {
|
||||
System.err.println(" missing in pom.xml: " + String.join(", ", missing));
|
||||
}
|
||||
if (!extra.isEmpty()) {
|
||||
System.err.println(" not required by module-info.java: "
|
||||
+ String.join(", ", extra));
|
||||
}
|
||||
System.err.println(" expected: " + String.join(",", required));
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/** Returns the platform modules required by the given descriptor, sorted. */
|
||||
static Set<String> platformModules(String source) {
|
||||
String stripped = LINE_COMMENT.matcher(
|
||||
BLOCK_COMMENT.matcher(source).replaceAll(" ")).replaceAll(" ");
|
||||
|
||||
Set<String> modules = new TreeSet<>();
|
||||
Matcher matcher = REQUIRES.matcher(stripped);
|
||||
while (matcher.find()) {
|
||||
// "requires static" is a compile time only dependency and must not
|
||||
// be linked into the shipped runtime image.
|
||||
if (matcher.group(1).contains("static")) {
|
||||
continue;
|
||||
}
|
||||
String module = matcher.group(2);
|
||||
if (isPlatformModule(module)) {
|
||||
modules.add(module);
|
||||
}
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
private static boolean isPlatformModule(String module) {
|
||||
return module.startsWith("java.")
|
||||
|| module.startsWith("jdk.")
|
||||
|| module.startsWith("javafx.");
|
||||
}
|
||||
|
||||
private static String read(Path path) throws IOException {
|
||||
if (!Files.isRegularFile(path)) {
|
||||
fail("Not found: " + path.toAbsolutePath()
|
||||
+ " (run this from the repository root)");
|
||||
}
|
||||
return Files.readString(path);
|
||||
}
|
||||
|
||||
private static void fail(String message) {
|
||||
System.err.println(message);
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ build() {
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -41,7 +40,7 @@ build() {
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
}
|
||||
|
||||
|
||||
@@ -26,14 +26,6 @@ build() {
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
|
||||
mkdir -p dist
|
||||
# This PKGBUILD builds from a released source tarball, which may predate
|
||||
# packaging/AddModules.java. Older tarballs carry the same list in pom.xml,
|
||||
# which the build keeps in sync with module-info.java from v1.42.0 onwards.
|
||||
if [ -f packaging/AddModules.java ]; then
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
else
|
||||
ADD_MODULES="$(sed -n 's:.*<addmodule>\(.*\)</addmodule>.*:\1:p' pom.xml | paste -sd,)"
|
||||
fi
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
@@ -41,7 +33,7 @@ build() {
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--add-modules javafx.controls,javafx.graphics,javafx.fxml,javafx.web,javafx.media,java.sql,java.net.http,jdk.crypto.ec \
|
||||
--dest dist
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
<javafx.maven.plugin>0.0.8</javafx.maven.plugin>
|
||||
<spotbugs.maven.plugin>4.9.8.2</spotbugs.maven.plugin>
|
||||
<spotbugs.version>4.9.8</spotbugs.version>
|
||||
<exec.maven.plugin>3.1.0</exec.maven.plugin>
|
||||
|
||||
<!-- other properties -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -209,36 +208,6 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Fails the build whenever the jpackage module list below drifts
|
||||
from the requires clauses in src/main/java/module-info.java.
|
||||
This is bound to validate rather than to a workflow trigger so
|
||||
it also fires on direct pushes to main, on local builds and in
|
||||
the AUR PKGBUILDs, which never run the pull request check.
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec.maven.plugin}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>verify-packaging-module-list</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>${java.home}/bin/java</executable>
|
||||
<workingDirectory>${project.basedir}</workingDirectory>
|
||||
<arguments>
|
||||
<argument>packaging/AddModules.java</argument>
|
||||
<argument>--verify-pom</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
@@ -467,26 +436,16 @@
|
||||
</dependencyset>
|
||||
</dependencysets>
|
||||
</modulepath>
|
||||
<!--
|
||||
Keep in sync with the requires clauses in
|
||||
src/main/java/module-info.java. The packaging
|
||||
scripts derive this list automatically via
|
||||
packaging/AddModules.java, and the PR check
|
||||
runs that helper in its pom verification mode
|
||||
so this block cannot drift unnoticed.
|
||||
-->
|
||||
<addmodules>
|
||||
<addmodule>java.desktop</addmodule>
|
||||
<addmodule>java.net.http</addmodule>
|
||||
<addmodule>java.sql</addmodule>
|
||||
<addmodule>javafx.controls</addmodule>
|
||||
<addmodule>javafx.graphics</addmodule>
|
||||
<addmodule>javafx.fxml</addmodule>
|
||||
<addmodule>javafx.media</addmodule>
|
||||
<addmodule>javafx.web</addmodule>
|
||||
<addmodule>javafx.media</addmodule>
|
||||
<addmodule>java.sql</addmodule>
|
||||
<addmodule>java.net.http</addmodule>
|
||||
<addmodule>jdk.crypto.ec</addmodule>
|
||||
<addmodule>jdk.jsobject</addmodule>
|
||||
<addmodule>jdk.net</addmodule>
|
||||
<addmodule>jdk.xml.dom</addmodule>
|
||||
</addmodules>
|
||||
<mainclass>${main.class}</mainclass>
|
||||
<input>${project.build.directory}/modules</input>
|
||||
|
||||
@@ -2,7 +2,6 @@ package kst4contest.controller;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
import kst4contest.model.ChatCategory;
|
||||
import kst4contest.model.ChatMessage;
|
||||
import kst4contest.model.ThreadStateMessage;
|
||||
|
||||
@@ -13,10 +12,6 @@ import kst4contest.model.ThreadStateMessage;
|
||||
* interval. Their enable flags and message templates remain independent. Every
|
||||
* run reads the current preferences, resolves global message variables and
|
||||
* sends only the categories which are currently enabled.</p>
|
||||
*
|
||||
* <p>Beacon messages use the regular outbound chat-message pipeline. They are
|
||||
* not assembled as raw ON4KST frames, because that would bypass the common
|
||||
* category, delimiter and message-text validation.</p>
|
||||
*/
|
||||
public class BeaconTask extends TimerTask {
|
||||
|
||||
@@ -44,40 +39,35 @@ public class BeaconTask extends TimerTask {
|
||||
Thread.currentThread().setName("BeaconTask");
|
||||
reportStatus(THREAD_NICKNAME, true, "initialized", false);
|
||||
|
||||
sendMainCategoryBeacon();
|
||||
sendSecondCategoryBeacon();
|
||||
MessageVariableResolver variableResolver =
|
||||
new MessageVariableResolver(chatController.getChatPreferences());
|
||||
|
||||
sendMainCategoryBeacon(variableResolver);
|
||||
sendSecondCategoryBeacon(variableResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the main-category beacon if it is currently enabled.
|
||||
*/
|
||||
private void sendMainCategoryBeacon() {
|
||||
if (!chatController.getChatPreferences()
|
||||
.isBcn_beaconsEnabledMainCat()) {
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 1",
|
||||
false,
|
||||
"off",
|
||||
false
|
||||
);
|
||||
private void sendMainCategoryBeacon(MessageVariableResolver variableResolver) {
|
||||
if (!chatController.getChatPreferences().isBcn_beaconsEnabledMainCat()) {
|
||||
reportStatus(THREAD_NICKNAME + " 1", false, "off", false);
|
||||
return;
|
||||
}
|
||||
|
||||
String resolvedText = variableResolver.resolveGlobalVariables(
|
||||
chatController.getChatPreferences().getBcn_beaconTextMainCat()
|
||||
);
|
||||
ChatMessage beaconMessage = buildBeaconMessage(
|
||||
chatController.getChatPreferences()
|
||||
.getLoginChatCategoryMain(),
|
||||
chatController.getChatPreferences()
|
||||
.getBcn_beaconTextMainCat(),
|
||||
.getLoginChatCategoryMain()
|
||||
.getCategoryNumber(),
|
||||
resolvedText,
|
||||
"main category"
|
||||
);
|
||||
|
||||
if (beaconMessage == null) {
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 1",
|
||||
false,
|
||||
"invalid text",
|
||||
true
|
||||
);
|
||||
reportStatus(THREAD_NICKNAME + " 1", false, "invalid text", true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,50 +76,37 @@ public class BeaconTask extends TimerTask {
|
||||
+ " [BeaconTask, Info]: Sending main-category CQ: "
|
||||
+ beaconMessage.getMessageText()
|
||||
);
|
||||
|
||||
chatController.getMessageTXBus().add(beaconMessage);
|
||||
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 1",
|
||||
true,
|
||||
"on",
|
||||
false
|
||||
);
|
||||
reportStatus(THREAD_NICKNAME + " 1", true, "on", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the second-category beacon if the second login and its beacon are
|
||||
* currently enabled.
|
||||
*/
|
||||
private void sendSecondCategoryBeacon() {
|
||||
if (!chatController.getChatPreferences()
|
||||
.isLoginToSecondChatEnabled()
|
||||
private void sendSecondCategoryBeacon(
|
||||
MessageVariableResolver variableResolver
|
||||
) {
|
||||
if (!chatController.getChatPreferences().isLoginToSecondChatEnabled()
|
||||
|| !chatController.getChatPreferences()
|
||||
.isBcn_beaconsEnabledSecondCat()) {
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 2",
|
||||
false,
|
||||
"off",
|
||||
false
|
||||
);
|
||||
reportStatus(THREAD_NICKNAME + " 2", false, "off", false);
|
||||
return;
|
||||
}
|
||||
|
||||
String resolvedText = variableResolver.resolveGlobalVariables(
|
||||
chatController.getChatPreferences().getBcn_beaconTextSecondCat()
|
||||
);
|
||||
ChatMessage beaconMessage = buildBeaconMessage(
|
||||
chatController.getChatPreferences()
|
||||
.getLoginChatCategorySecond(),
|
||||
chatController.getChatPreferences()
|
||||
.getBcn_beaconTextSecondCat(),
|
||||
.getLoginChatCategorySecond()
|
||||
.getCategoryNumber(),
|
||||
resolvedText,
|
||||
"second category"
|
||||
);
|
||||
|
||||
if (beaconMessage == null) {
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 2",
|
||||
false,
|
||||
"invalid text",
|
||||
true
|
||||
);
|
||||
reportStatus(THREAD_NICKNAME + " 2", false, "invalid text", true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,65 +115,47 @@ public class BeaconTask extends TimerTask {
|
||||
+ " [BeaconTask, Info]: Sending second-category CQ: "
|
||||
+ beaconMessage.getMessageText()
|
||||
);
|
||||
|
||||
chatController.getMessageTXBus().add(beaconMessage);
|
||||
|
||||
reportStatus(
|
||||
THREAD_NICKNAME + " 2",
|
||||
true,
|
||||
"on",
|
||||
false
|
||||
);
|
||||
reportStatus(THREAD_NICKNAME + " 2", true, "on", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and validates one beacon before placing it in the regular outbound
|
||||
* message queue.
|
||||
* Builds the server-directed message after validating the resolved payload.
|
||||
*
|
||||
* <p>The returned message contains only the public-chat payload and its chat
|
||||
* category. {@link WriteThread} creates the final ON4KST frame through
|
||||
* {@link On4KstProtocol#chatMessage(int, String)}. This prevents a configurable
|
||||
* beacon text from bypassing the common protocol validation.</p>
|
||||
* <p>The resolved text is checked rather than only the configured template
|
||||
* because inserted values can increase the final message length.</p>
|
||||
*
|
||||
* @param category target ON4KST chat category
|
||||
* @param configuredText configured beacon template
|
||||
* @param categoryNumber ON4KST category number
|
||||
* @param resolvedText fully resolved beacon payload
|
||||
* @param categoryDescription text used in diagnostic output
|
||||
* @return prepared message, or {@code null} if the category or text is invalid
|
||||
* @return prepared message, or {@code null} if the payload is invalid
|
||||
*/
|
||||
private ChatMessage buildBeaconMessage(
|
||||
ChatCategory category,
|
||||
String configuredText,
|
||||
int categoryNumber,
|
||||
String resolvedText,
|
||||
String categoryDescription
|
||||
) {
|
||||
try {
|
||||
if (category == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"No chat category is configured."
|
||||
);
|
||||
}
|
||||
|
||||
On4KstProtocol.category(category.getCategoryNumber());
|
||||
|
||||
String resolvedText =
|
||||
chatController.resolveAndValidateBeaconText(
|
||||
configuredText
|
||||
);
|
||||
|
||||
ChatMessage beaconMessage = new ChatMessage();
|
||||
beaconMessage.setMessageText(resolvedText);
|
||||
beaconMessage.setChatCategory(category);
|
||||
beaconMessage.setMessageDirectedToServer(false);
|
||||
|
||||
return beaconMessage;
|
||||
} catch (IllegalArgumentException exception) {
|
||||
if (resolvedText == null
|
||||
|| resolvedText.length() > ChatController.MAX_BEACON_TEXT_LENGTH) {
|
||||
int actualLength = resolvedText == null ? 0 : resolvedText.length();
|
||||
System.out.println(
|
||||
"[BeaconTask, Warning]: Beacon for "
|
||||
+ categoryDescription
|
||||
+ " was not queued: "
|
||||
+ exception.getMessage()
|
||||
+ " was not sent because the resolved text contains "
|
||||
+ actualLength
|
||||
+ " characters; maximum is "
|
||||
+ ChatController.MAX_BEACON_TEXT_LENGTH
|
||||
+ "."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
ChatMessage beaconMessage = new ChatMessage();
|
||||
beaconMessage.setMessageText(
|
||||
"MSG|" + categoryNumber + "|0|" + resolvedText + "|0|"
|
||||
);
|
||||
beaconMessage.setMessageDirectedToServer(true);
|
||||
return beaconMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,9 +173,6 @@ public class BeaconTask extends TimerTask {
|
||||
information,
|
||||
criticalState
|
||||
);
|
||||
callbackToController.onThreadStatus(
|
||||
THREAD_NICKNAME,
|
||||
stateMessage
|
||||
);
|
||||
callbackToController.onThreadStatus(THREAD_NICKNAME, stateMessage);
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import kst4contest.logic.FrequencyTextParser;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
|
||||
|
||||
@@ -70,30 +69,8 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
|
||||
public static final int MAX_BEACON_TEXT_LENGTH = 120;
|
||||
private static final long INITIAL_BEACON_DELAY_MILLIS = 10_000L;
|
||||
|
||||
private volatile PstRotatorClient rotatorClient;
|
||||
private Consumer<Double> viewRotorCallback;
|
||||
|
||||
/*
|
||||
* The rotator retry must never block the JavaFX Application Thread.
|
||||
* A daemon scheduler performs the delayed SPID compatibility check.
|
||||
*/
|
||||
private final ScheduledExecutorService rotatorCommandScheduler =
|
||||
Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||
Thread thread = new Thread(
|
||||
runnable,
|
||||
"PSTRotator-Command-Retry"
|
||||
);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
private ScheduledFuture<?> pendingRotatorRetry;
|
||||
|
||||
/*
|
||||
* Updated directly by the PSTRotator receiver thread. This avoids reading
|
||||
* a JavaFX property from the command scheduler.
|
||||
*/
|
||||
private volatile double lastReportedRotatorAzimuth = Double.NaN;
|
||||
private PstRotatorClient rotatorClient;
|
||||
private Consumer<Double> viewRotorCallback;
|
||||
|
||||
private Kst4ContestApplication view; //effectively final, for recoupling of the controller to the view
|
||||
|
||||
@@ -326,142 +303,41 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
|
||||
rotatorClient.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a new azimuth to PSTRotator without blocking the JavaFX thread.
|
||||
*
|
||||
* <p>Some SPID configurations occasionally ignore the first azimuth
|
||||
* command. KST4Contest therefore checks the latest reported position after
|
||||
* two seconds. If no movement was reported and the target has not already
|
||||
* been reached, the original compatibility sequence is sent again.</p>
|
||||
*
|
||||
* @param azimuth required antenna azimuth in degrees
|
||||
*/
|
||||
public void rotateTo(double azimuth) {
|
||||
if (!Double.isFinite(azimuth)) {
|
||||
LOGGER.log(
|
||||
Level.WARNING,
|
||||
"Ignoring invalid PSTRotator azimuth: {0}",
|
||||
azimuth
|
||||
);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* sets rotator to "AZ DEGREE" by button click <br/><br/>
|
||||
* <b>Note that there is a workaround for spid rotators: <br/>
|
||||
* The AZ will be set, after 'time' secs it will be controlled if the rotator started, If not, the rotator will<br/>
|
||||
* be homed to 0 deg for very shord period, then the AZ value will be set again.
|
||||
* </b>
|
||||
* @param azimuth
|
||||
*/
|
||||
public void rotateTo(double azimuth) {
|
||||
|
||||
PstRotatorClient activeClient = rotatorClient;
|
||||
if (activeClient == null) {
|
||||
LOGGER.log(
|
||||
Level.WARNING,
|
||||
"Cannot rotate antenna to {0} degrees: "
|
||||
+ "PSTRotator integration is not active.",
|
||||
azimuth
|
||||
);
|
||||
return;
|
||||
}
|
||||
double beforeRotateAzWas = chatPreferences.getActualQTF().getValue();
|
||||
|
||||
double targetAzimuth = normalizeAzimuth(azimuth);
|
||||
double positionBeforeCommand = lastReportedRotatorAzimuth;
|
||||
if (rotatorClient != null) {
|
||||
rotatorClient.setTrackingMode(false);
|
||||
System.out.println("Chatcontroller, Info: turning ant to " + azimuth + " by user request");
|
||||
rotatorClient.setAzimuth(azimuth);
|
||||
|
||||
activeClient.setTrackingMode(false);
|
||||
Object lockDelay = new Object();
|
||||
synchronized (lockDelay) {
|
||||
try{
|
||||
|
||||
LOGGER.log(
|
||||
Level.INFO,
|
||||
"Sending PSTRotator azimuth requested by the operator: {0}",
|
||||
targetAzimuth
|
||||
);
|
||||
TimeUnit.SECONDS.sleep(2);; //wait 2s, then check if rotator does anything due SPID
|
||||
// sometimes does simply not accept a rotating value for first try!
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
activeClient.setAzimuth(targetAzimuth);
|
||||
}
|
||||
}
|
||||
|
||||
ScheduledFuture<?> previousRetry = pendingRotatorRetry;
|
||||
if (previousRetry != null) {
|
||||
previousRetry.cancel(false);
|
||||
}
|
||||
if (chatPreferences.getActualQTF().getValue() == beforeRotateAzWas) {
|
||||
rotatorClient.setAzimuth(0); //do some reset
|
||||
rotatorClient.setAzimuth(azimuth); //then rotate
|
||||
}
|
||||
|
||||
pendingRotatorRetry = rotatorCommandScheduler.schedule(
|
||||
() -> retryRotatorCommandIfRequired(
|
||||
positionBeforeCommand,
|
||||
targetAzimuth
|
||||
),
|
||||
2,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the delayed SPID compatibility check.
|
||||
*
|
||||
* <p>No retry is required when the requested position has already been
|
||||
* reached or when PSTRotator reported movement after the original command.
|
||||
* Missing feedback is treated like an unchanged position.</p>
|
||||
*/
|
||||
private void retryRotatorCommandIfRequired(
|
||||
double positionBeforeCommand,
|
||||
double targetAzimuth
|
||||
) {
|
||||
PstRotatorClient activeClient = rotatorClient;
|
||||
if (activeClient == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
double currentAzimuth = lastReportedRotatorAzimuth;
|
||||
|
||||
if (Double.isFinite(currentAzimuth)
|
||||
&& angularDistance(currentAzimuth, targetAzimuth) < 0.5) {
|
||||
|
||||
LOGGER.log(
|
||||
Level.FINE,
|
||||
"PSTRotator reached the requested azimuth without retry: {0}",
|
||||
targetAzimuth
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean noPositionFeedback =
|
||||
!Double.isFinite(currentAzimuth);
|
||||
|
||||
boolean positionUnchanged =
|
||||
Double.isFinite(positionBeforeCommand)
|
||||
&& Double.isFinite(currentAzimuth)
|
||||
&& angularDistance(
|
||||
positionBeforeCommand,
|
||||
currentAzimuth
|
||||
) < 0.5;
|
||||
|
||||
if (!noPositionFeedback && !positionUnchanged) {
|
||||
LOGGER.log(
|
||||
Level.FINE,
|
||||
"PSTRotator reported movement towards {0}; no retry required.",
|
||||
targetAzimuth
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.log(
|
||||
Level.WARNING,
|
||||
"PSTRotator reported no movement after the command for {0} degrees; "
|
||||
+ "sending the SPID compatibility retry.",
|
||||
targetAzimuth
|
||||
);
|
||||
|
||||
activeClient.setAzimuth(0.0);
|
||||
activeClient.setAzimuth(targetAzimuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest angular distance between two azimuth values.
|
||||
*/
|
||||
private static double angularDistance(double first, double second) {
|
||||
double difference = Math.abs(
|
||||
normalizeAzimuth(first) - normalizeAzimuth(second)
|
||||
);
|
||||
return Math.min(difference, 360.0 - difference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalises an azimuth to the range from 0 inclusive to 360 exclusive.
|
||||
*/
|
||||
private static double normalizeAzimuth(double azimuth) {
|
||||
double normalized = azimuth % 360.0;
|
||||
return normalized < 0.0 ? normalized + 360.0 : normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an external logger reports that a QSO was logged.
|
||||
@@ -565,42 +441,16 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
|
||||
}
|
||||
|
||||
|
||||
public void stopRotator() {
|
||||
ScheduledFuture<?> pendingRetry = pendingRotatorRetry;
|
||||
if (pendingRetry != null) {
|
||||
pendingRetry.cancel(false);
|
||||
pendingRotatorRetry = null;
|
||||
}
|
||||
|
||||
PstRotatorClient activeClient = rotatorClient;
|
||||
rotatorClient = null;
|
||||
lastReportedRotatorAzimuth = Double.NaN;
|
||||
|
||||
if (activeClient != null) {
|
||||
activeClient.stop();
|
||||
}
|
||||
}
|
||||
public void stopRotator() {
|
||||
if (rotatorClient != null) {
|
||||
rotatorClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAzimuthUpdate(double azimuth) {
|
||||
if (!Double.isFinite(azimuth)) {
|
||||
LOGGER.log(
|
||||
Level.WARNING,
|
||||
"Ignoring invalid azimuth reported by PSTRotator: {0}",
|
||||
azimuth
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
double normalizedAzimuth = normalizeAzimuth(azimuth);
|
||||
lastReportedRotatorAzimuth = normalizedAzimuth;
|
||||
|
||||
/*
|
||||
* The callback runs in the PSTRotator receiver thread. JavaFX properties
|
||||
* must be updated on the JavaFX Application Thread.
|
||||
*/
|
||||
Runnable fxUpdate = () ->
|
||||
chatPreferences.getActualQTF().setValue(normalizedAzimuth);
|
||||
// We are in the rotor client thread. JavaFX properties must be updated on the FX thread.
|
||||
Runnable fxUpdate = () -> chatPreferences.getActualQTF().setValue(azimuth);
|
||||
|
||||
if (Platform.isFxApplicationThread()) {
|
||||
fxUpdate.run();
|
||||
@@ -2977,82 +2827,6 @@ private ObservableList<String>
|
||||
this.dbHandler = dbHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates a configured beacon template before it is stored.
|
||||
*
|
||||
* <p>The template itself must be a non-empty, protocol-safe message. Global
|
||||
* variables are resolved as far as their values are currently available.
|
||||
* A template which temporarily resolves to an empty string, for example
|
||||
* {@code MYQRG} before a frequency is known, remains valid. The timer performs
|
||||
* the stricter final validation immediately before transmission.</p>
|
||||
*
|
||||
* @param configuredText configured beacon template
|
||||
* @throws IllegalArgumentException if the template contains invalid protocol
|
||||
* content or currently resolves to more than
|
||||
* {@value MAX_BEACON_TEXT_LENGTH} characters
|
||||
*/
|
||||
public void validateBeaconTemplate(String configuredText) {
|
||||
String normalizedTemplate =
|
||||
On4KstProtocol.messageText(configuredText);
|
||||
|
||||
String resolvedText =
|
||||
new MessageVariableResolver(chatPreferences)
|
||||
.resolveGlobalVariables(normalizedTemplate);
|
||||
|
||||
/*
|
||||
* A template consisting only of a variable such as MYQRG may temporarily
|
||||
* resolve to an empty value. It can still be stored because the value may
|
||||
* become available through TRX synchronisation before the timer runs.
|
||||
*/
|
||||
if (resolvedText == null || resolvedText.isBlank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
validateResolvedBeaconText(resolvedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and validates the final beacon text immediately before transmission.
|
||||
*
|
||||
* <p>This is deliberately stricter than {@link #validateBeaconTemplate(String)}.
|
||||
* A timer run must never queue an empty message merely because a dynamic value
|
||||
* is not available at that moment.</p>
|
||||
*
|
||||
* @param configuredText configured beacon template
|
||||
* @return normalized text which may safely pass through the regular ON4KST
|
||||
* message pipeline
|
||||
* @throws IllegalArgumentException if the resolved message is empty, too long
|
||||
* or contains an ON4KST delimiter
|
||||
*/
|
||||
public String resolveAndValidateBeaconText(String configuredText) {
|
||||
String resolvedText =
|
||||
new MessageVariableResolver(chatPreferences)
|
||||
.resolveGlobalVariables(configuredText);
|
||||
|
||||
return validateResolvedBeaconText(resolvedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the message-text and length rules to a fully resolved beacon.
|
||||
*/
|
||||
private String validateResolvedBeaconText(String resolvedText) {
|
||||
String normalizedText =
|
||||
On4KstProtocol.messageText(resolvedText);
|
||||
|
||||
if (normalizedText.length() > MAX_BEACON_TEXT_LENGTH) {
|
||||
throw new IllegalArgumentException(
|
||||
"The resolved beacon message contains "
|
||||
+ normalizedText.length()
|
||||
+ " characters; maximum is "
|
||||
+ MAX_BEACON_TEXT_LENGTH
|
||||
+ "."
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the shared beacon timer with the interval currently stored in the
|
||||
* preferences.
|
||||
@@ -3775,7 +3549,7 @@ private ObservableList<String>
|
||||
/**
|
||||
* Reloads the worked/not-QRV state from the internal database and applies the
|
||||
* result both to the active chatmember list and to the database table list in the
|
||||
* settings dialog. UI-bound list modifications are executed on the JavaFX thread..
|
||||
* settings dialog. UI-bound list modifications are executed on the JavaFX thread.
|
||||
*/
|
||||
public void refreshWorkedStateAndDatabaseListFromDatabase() {
|
||||
|
||||
@@ -3981,96 +3755,42 @@ private ObservableList<String>
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a message belongs to a monitored base callsign.
|
||||
*
|
||||
* <p>QSO monitoring intentionally combines all visible ON4KST variants of
|
||||
* the same station. An entry for DN9APW therefore also matches DN9APW-2,
|
||||
* DN9APW-70 and other suffixes. This affects monitoring only; message
|
||||
* routing continues to use the complete callsign and chat category.</p>
|
||||
*
|
||||
* @param chatMessage message to examine
|
||||
* @return true if sender or receiver belongs to a monitored base callsign
|
||||
* decides if a message in the in-queue is directed to me or if its directed to another station and sniffed
|
||||
* @param chatMessage
|
||||
* @return
|
||||
*/
|
||||
public boolean isSniffedMessage(ChatMessage chatMessage) {
|
||||
|
||||
if (chatMessage == null
|
||||
|| chatMessage.getSender() == null
|
||||
|| chatMessage.getReceiver() == null) {
|
||||
if (chatMessage == null || chatMessage.getSender() == null || chatMessage.getReceiver() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String senderCall =
|
||||
chatMessage.getSender().getCallSign();
|
||||
String receiverCall =
|
||||
chatMessage.getReceiver().getCallSign();
|
||||
String senderCall = chatMessage.getSender().getCallSign();
|
||||
String receiverCall = chatMessage.getReceiver().getCallSign();
|
||||
|
||||
if (senderCall == null || receiverCall == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lstNotify_QSOSniffer_sniffedCallSignList == null
|
||||
|| lstNotify_QSOSniffer_sniffedCallSignList.isEmpty()) {
|
||||
if (lstNotify_QSOSniffer_sniffedCallSignList == null || lstNotify_QSOSniffer_sniffedCallSignList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String senderBaseCall =
|
||||
ChatMember.normalizeCallSignToBaseCallSign(
|
||||
senderCall
|
||||
);
|
||||
String receiverBaseCall =
|
||||
ChatMember.normalizeCallSignToBaseCallSign(
|
||||
receiverCall
|
||||
);
|
||||
|
||||
boolean observedCall =
|
||||
lstNotify_QSOSniffer_sniffedCallSignList
|
||||
.stream()
|
||||
.anyMatch(
|
||||
monitoredCall -> {
|
||||
String monitoredBaseCall =
|
||||
ChatMember
|
||||
.normalizeCallSignToBaseCallSign(
|
||||
monitoredCall
|
||||
);
|
||||
|
||||
return monitoredBaseCall != null
|
||||
&& (
|
||||
monitoredBaseCall
|
||||
.equalsIgnoreCase(
|
||||
senderBaseCall
|
||||
)
|
||||
|| monitoredBaseCall
|
||||
.equalsIgnoreCase(
|
||||
receiverBaseCall
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
lstNotify_QSOSniffer_sniffedCallSignList.contains(senderCall)
|
||||
|| lstNotify_QSOSniffer_sniffedCallSignList.contains(receiverCall);
|
||||
|
||||
if (!observedCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String myCall =
|
||||
getChatPreferences() != null
|
||||
? getChatPreferences().getStn_loginCallSign()
|
||||
: null;
|
||||
String myRawCall =
|
||||
getChatPreferences() != null
|
||||
? getChatPreferences().getStn_loginCallSignRaw()
|
||||
: null;
|
||||
String myCall = getChatPreferences() != null ? getChatPreferences().getStn_loginCallSign() : null;
|
||||
String myRawCall = getChatPreferences() != null ? getChatPreferences().getStn_loginCallSignRaw() : null;
|
||||
|
||||
/*
|
||||
* Messages which are already addressed directly to the local station
|
||||
* belong in the PM table without an additional Sniffed marker.
|
||||
* Sniffed messages should appear in the private table only if they are not
|
||||
* already direct messages to my own callsign.
|
||||
*/
|
||||
boolean directedToOwnCall =
|
||||
(myCall != null
|
||||
&& receiverCall.equalsIgnoreCase(myCall))
|
||||
|| (myRawCall != null
|
||||
&& receiverCall.equalsIgnoreCase(myRawCall));
|
||||
|
||||
return !directedToOwnCall;
|
||||
return !receiverCall.equals(myCall) && !receiverCall.equals(myRawCall);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1167,22 +1167,16 @@ public class MessageBusManagementThread extends Thread {
|
||||
// }
|
||||
// }
|
||||
|
||||
// ==== Unified auto-answer (generic + QRG) with ping-pong guard
|
||||
// and per-remote cooldown ====
|
||||
// ==== Unified auto-answer (generic + QRG) with ping-pong guard and per-remote cooldown ====
|
||||
final String incomingText = newMessageArrived.getMessageText();
|
||||
final String incomingLower =
|
||||
(incomingText == null)
|
||||
? ""
|
||||
: incomingText.toLowerCase(Locale.ROOT);
|
||||
final String incomingLower = (incomingText == null) ? "" : incomingText.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Never answer another automatically generated message.
|
||||
// Never answer another automatically generated message.
|
||||
if (!isAutoMessage(newMessageArrived)) {
|
||||
|
||||
boolean qrgRequested = false;
|
||||
|
||||
if (this.client.getChatPreferences()
|
||||
.isMessageHandling_autoAnswerToQRGRequestEnabled()) {
|
||||
|
||||
if (this.client.getChatPreferences().isMessageHandling_autoAnswerToQRGRequestEnabled()) {
|
||||
for (String lookForQRGString : qrgQuestionTexts) {
|
||||
if (incomingLower.contains(lookForQRGString)) {
|
||||
qrgRequested = true;
|
||||
@@ -1191,47 +1185,36 @@ public class MessageBusManagementThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
boolean genericEnabled =
|
||||
this.client.getChatPreferences()
|
||||
.isMsgHandling_autoAnswerEnabled();
|
||||
boolean genericEnabled = this.client.getChatPreferences().isMsgHandling_autoAnswerEnabled();
|
||||
|
||||
String automaticAnswerText = buildAutoAnswerMessageText(
|
||||
newMessageArrived,
|
||||
qrgRequested,
|
||||
genericEnabled
|
||||
);
|
||||
// A QRG reply takes precedence over the generic reply.
|
||||
String payload = null;
|
||||
|
||||
/*
|
||||
* Invalid or incomplete replies are rejected before the cooldown
|
||||
* is checked or updated. A missing QRG must therefore not suppress
|
||||
* a later valid reply.
|
||||
*/
|
||||
if (automaticAnswerText != null
|
||||
&& isAutoAnswerAllowedNow(newMessageArrived)) {
|
||||
if (qrgRequested) {
|
||||
payload = "QRG is: " + getAutoAnswerQrgForCategory(newMessageArrived.getChatCategory());
|
||||
} else if (genericEnabled) {
|
||||
|
||||
payload = this.client.getChatPreferences().getMessageHandling_autoAnswerTextMainCat();
|
||||
}
|
||||
|
||||
// Apply the cooldown only when this client is about to send a reply.
|
||||
if (payload != null && isAutoAnswerAllowedNow(newMessageArrived)) {
|
||||
|
||||
ChatMessage automaticAnswer = new ChatMessage();
|
||||
ChatMember itsMe = new ChatMember();
|
||||
|
||||
itsMe.setCallSign(
|
||||
this.client.getChatPreferences()
|
||||
.getStn_loginCallSign()
|
||||
);
|
||||
itsMe.setCallSign(this.client.getChatPreferences().getStn_loginCallSign());
|
||||
|
||||
automaticAnswer.setSender(itsMe);
|
||||
automaticAnswer.setReceiver(
|
||||
newMessageArrived.getSender()
|
||||
);
|
||||
automaticAnswer.setChatCategory(
|
||||
newMessageArrived.getChatCategory()
|
||||
);
|
||||
automaticAnswer.setMessageText(automaticAnswerText);
|
||||
automaticAnswer.setReceiver(newMessageArrived.getSender());
|
||||
automaticAnswer.setChatCategory(newMessageArrived.getChatCategory());
|
||||
|
||||
// The fixed prefix prevents automatic clients from answering each other.
|
||||
automaticAnswer.setMessageText("/CQ " + newMessageArrived.getSender().getCallSign()
|
||||
+ " " + AUTOANSWER_PREFIX + " " + payload);
|
||||
|
||||
this.client.getMessageTXBus().add(automaticAnswer);
|
||||
|
||||
/*
|
||||
* Record the cooldown only after a complete and locally
|
||||
* validated reply has been placed in the transmit queue.
|
||||
*/
|
||||
// Record only locally generated replies, not the later server echo.
|
||||
markLocalAutoAnswerSent(newMessageArrived);
|
||||
}
|
||||
}
|
||||
@@ -1923,101 +1906,6 @@ public class MessageBusManagementThread extends Thread {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds and validates one automatic private reply.
|
||||
*
|
||||
* <p>A QRG request is answered only when the QRG belonging to the
|
||||
* incoming chat category is available. The generic answer is used
|
||||
* only for other private messages and only when it contains actual
|
||||
* text.</p>
|
||||
*
|
||||
* <p>The complete message is validated before it enters the transmit
|
||||
* queue. Invalid configuration values must neither produce an empty
|
||||
* automatic reply nor start the cooldown.</p>
|
||||
*
|
||||
* @param incoming incoming private message
|
||||
* @param qrgRequested whether the message contains a recognised QRG request
|
||||
* @param genericEnabled whether the general automatic reply is enabled
|
||||
* @return validated message text or {@code null} when no reply may be sent
|
||||
*/
|
||||
private String buildAutoAnswerMessageText(
|
||||
ChatMessage incoming,
|
||||
boolean qrgRequested,
|
||||
boolean genericEnabled
|
||||
) {
|
||||
if (incoming == null
|
||||
|| incoming.getSender() == null
|
||||
|| incoming.getSender().getCallSign() == null
|
||||
|| incoming.getSender().getCallSign().isBlank()) {
|
||||
|
||||
System.err.println(
|
||||
"KST4Contest auto-answer skipped: "
|
||||
+ "incoming message has no valid sender callsign."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
String payload;
|
||||
|
||||
if (qrgRequested) {
|
||||
String qrg = getAutoAnswerQrgForCategory(
|
||||
incoming.getChatCategory()
|
||||
);
|
||||
|
||||
if (qrg == null || qrg.isBlank()) {
|
||||
System.err.println(
|
||||
"KST4Contest QRG auto-answer skipped for "
|
||||
+ incoming.getSender().getCallSign()
|
||||
+ ": no QRG is available for chat category "
|
||||
+ autoAnswerCooldownKey(incoming)
|
||||
+ "."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
payload = "QRG is: " + qrg.trim();
|
||||
|
||||
} else if (genericEnabled) {
|
||||
payload = this.client.getChatPreferences()
|
||||
.getMessageHandling_autoAnswerTextMainCat();
|
||||
|
||||
if (payload == null || payload.isBlank()) {
|
||||
System.err.println(
|
||||
"KST4Contest generic auto-answer skipped for "
|
||||
+ incoming.getSender().getCallSign()
|
||||
+ ": the configured answer text is empty."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
payload = payload.trim();
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
String messageText =
|
||||
"/CQ "
|
||||
+ incoming.getSender().getCallSign().trim()
|
||||
+ " "
|
||||
+ AUTOANSWER_PREFIX
|
||||
+ " "
|
||||
+ payload;
|
||||
|
||||
try {
|
||||
return On4KstProtocol.messageText(messageText);
|
||||
|
||||
} catch (IllegalArgumentException invalidMessage) {
|
||||
System.err.println(
|
||||
"KST4Contest auto-answer skipped for "
|
||||
+ incoming.getSender().getCallSign()
|
||||
+ ": "
|
||||
+ invalidMessage.getMessage()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a message carries the fixed marker used for automatic replies.
|
||||
*/
|
||||
|
||||
@@ -285,10 +285,7 @@ final class On4KstConnectionManager {
|
||||
scheduler.schedule(
|
||||
() -> sendLogin(token), LOGIN_FALLBACK_MILLIS,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} catch (Throwable exception) {
|
||||
// Errors must be caught as well: an Error escaping here would be
|
||||
// swallowed by the scheduler and leave the state machine stuck in
|
||||
// CONNECTING without any reconnect attempt or user visible failure.
|
||||
} catch (Exception exception) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ignored) {
|
||||
@@ -702,9 +699,7 @@ final class On4KstConnectionManager {
|
||||
socket.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, 45);
|
||||
socket.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, 15);
|
||||
socket.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, 3);
|
||||
} catch (UnsupportedOperationException | IOException | LinkageError exception) {
|
||||
// LinkageError covers runtime images built without the jdk.net module;
|
||||
// the connection stays usable, only kernel side keepalive is missing.
|
||||
} catch (UnsupportedOperationException | IOException exception) {
|
||||
LOGGER.log(Level.INFO,
|
||||
"Platform does not support configurable TCP keepalive; "
|
||||
+ "application heartbeat remains active", exception);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package kst4contest.controller;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@@ -10,8 +7,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import kst4contest.model.ChatPreferences;
|
||||
|
||||
|
||||
class On4KstProtocolTest {
|
||||
@Test
|
||||
@@ -71,72 +66,4 @@ class On4KstProtocolTest {
|
||||
On4KstConnectionManager.parseMessageTimestamp(
|
||||
"CH|2|20260813123456|DL1ABC|Op|0|msg|0|"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesBeaconVariablesBeforeApplyingProtocolValidation() {
|
||||
ChatPreferences preferences = new ChatPreferences();
|
||||
preferences.setMYQRGFirstCat("144.300");
|
||||
|
||||
ChatController controller = new ChatController();
|
||||
controller.setChatPreferences(preferences);
|
||||
|
||||
controller.validateBeaconTemplate(
|
||||
"calling cq at MYQRG"
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"calling cq at 144.300",
|
||||
controller.resolveAndValidateBeaconText(
|
||||
"calling cq at MYQRG"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsTemporarilyUnresolvedVariableOnlyBeaconTemplate() {
|
||||
ChatPreferences preferences = new ChatPreferences();
|
||||
preferences.setMYQRGFirstCat("");
|
||||
|
||||
ChatController controller = new ChatController();
|
||||
controller.setChatPreferences(preferences);
|
||||
|
||||
assertDoesNotThrow(
|
||||
() -> controller.validateBeaconTemplate("MYQRG")
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> controller.resolveAndValidateBeaconText("MYQRG")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsEmptyOverlongAndProtocolBreakingBeaconText() {
|
||||
ChatPreferences preferences = new ChatPreferences();
|
||||
|
||||
ChatController controller = new ChatController();
|
||||
controller.setChatPreferences(preferences);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> controller.validateBeaconTemplate(" ")
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> controller.validateBeaconTemplate(
|
||||
"cq at 144.300|0|QUIT"
|
||||
)
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> controller.validateBeaconTemplate(
|
||||
"x".repeat(
|
||||
ChatController.MAX_BEACON_TEXT_LENGTH
|
||||
+ 1
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -164,79 +165,18 @@ public class ReadUDPByWintestThread extends Thread {
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a frequency from a Win-Test STATUS packet for use as MYQRG.
|
||||
* Parse Win-Test STATUS packets and update own QRG from WT station.
|
||||
*
|
||||
* <p>Win-Test transmits the frequency in units of 0.1 kHz. KST4Contest
|
||||
* displays frequencies as {@code MHz.kHz.10Hz}, for example
|
||||
* {@code 144.300.00} or {@code 10368.100.00}. The MHz part may contain
|
||||
* between one and five digits. Deriving its length from the complete value
|
||||
* avoids separate and incomplete handling for individual bands.</p>
|
||||
*
|
||||
* @param frequencyIn100Hz frequency received from Win-Test in units of
|
||||
* 0.1 kHz, equivalent to 100 Hz
|
||||
* @return frequency formatted for MYQRG
|
||||
* @throws IllegalArgumentException if the supplied frequency is not positive
|
||||
* or too small to be formatted
|
||||
* @throws ArithmeticException if the supplied value exceeds the supported
|
||||
* numeric range
|
||||
*/
|
||||
private String helper_formatWinTestFrequency(long frequencyIn100Hz) {
|
||||
if (frequencyIn100Hz <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Win-Test frequency must be greater than zero"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiplication by ten creates a digit sequence whose final five
|
||||
* digits represent kHz and 10-Hz groups:
|
||||
*
|
||||
* 1443210 -> 14432100 -> 144.321.00
|
||||
* 103681000 -> 1036810000 -> 10368.100.00
|
||||
*/
|
||||
long frequencyIn10Hz = Math.multiplyExact(
|
||||
frequencyIn100Hz,
|
||||
10L
|
||||
);
|
||||
|
||||
String frequencyDigits = Long.toString(frequencyIn10Hz);
|
||||
|
||||
if (frequencyDigits.length() < 6) {
|
||||
throw new IllegalArgumentException(
|
||||
"Win-Test frequency is too small: " + frequencyIn100Hz
|
||||
);
|
||||
}
|
||||
|
||||
int mhzEndIndex = frequencyDigits.length() - 5;
|
||||
int khzEndIndex = frequencyDigits.length() - 2;
|
||||
|
||||
return frequencyDigits.substring(0, mhzEndIndex)
|
||||
+ "."
|
||||
+ frequencyDigits.substring(mhzEndIndex, khzEndIndex)
|
||||
+ "."
|
||||
+ frequencyDigits.substring(khzEndIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Win-Test STATUS packet and optionally updates MYQRG.
|
||||
*
|
||||
* <p>The packet is tokenised while preserving quoted station names.
|
||||
* The configured station-name filter is applied before any frequency is
|
||||
* processed. An empty filter accepts STATUS packets from every Win-Test
|
||||
* station.</p>
|
||||
*
|
||||
* <p>The main frequency is read from token 7. If pass-frequency use is
|
||||
* enabled and token 11 contains a valid frequency, the pass frequency is
|
||||
* used instead. A missing or invalid pass frequency deliberately falls
|
||||
* back to the main frequency.</p>
|
||||
*
|
||||
* @param msg complete Win-Test STATUS packet
|
||||
* Parsing model (tokenized with quotes preserved):
|
||||
* parts[0] = "STATUS"
|
||||
* parts[1] = station name (example: "STN1")
|
||||
* parts[5] = val2 (used to derive mode: 1 => SSB, else CW)
|
||||
* parts[7] = frequency in 0.1 kHz units (example: 1443210 => 144321.0)
|
||||
*/
|
||||
private void parseStatus(String msg) {
|
||||
try {
|
||||
ArrayList<String> parts = new ArrayList<>();
|
||||
Matcher matcher = STATUS_TOKEN_PATTERN.matcher(msg);
|
||||
|
||||
while (matcher.find()) {
|
||||
if (matcher.group(1) != null) {
|
||||
parts.add(matcher.group(1));
|
||||
@@ -246,105 +186,86 @@ public class ReadUDPByWintestThread extends Thread {
|
||||
}
|
||||
|
||||
if (parts.size() < 8) {
|
||||
System.out.println(
|
||||
"[WinTest] STATUS too short: " + msg
|
||||
);
|
||||
System.out.println("[WinTest] STATUS too short: " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
String stationName = parts.get(1);
|
||||
String stationFilter = client
|
||||
.getChatPreferences()
|
||||
.getLogsynch_wintestNetworkStationNameOfWintestClient1();
|
||||
|
||||
if (stationFilter != null
|
||||
&& !stationFilter.isBlank()
|
||||
&& !stationName.equalsIgnoreCase(stationFilter)) {
|
||||
String stn = parts.get(1);
|
||||
String stationFilter = client.getChatPreferences().getLogsynch_wintestNetworkStationNameOfWintestClient1();
|
||||
if (stationFilter != null && !stationFilter.isBlank() && !stn.equalsIgnoreCase(stationFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String modeValue = parts.get(5);
|
||||
long mainFrequencyRaw = Long.parseLong(parts.get(7));
|
||||
double mainFrequencyKHz = mainFrequencyRaw / 10.0;
|
||||
String val2 = parts.get(5);
|
||||
String freqRaw = parts.get(7);
|
||||
double freqFloat = Integer.parseInt(freqRaw) / 10.0;
|
||||
|
||||
String mode;
|
||||
|
||||
if ("1".equals(modeValue)) {
|
||||
mode = mainFrequencyKHz > 10000.0 ? "usb" : "lsb";
|
||||
if ("1".equals(val2)) {
|
||||
mode = freqFloat > 10000.0 ? "usb" : "lsb";
|
||||
} else {
|
||||
mode = "cw";
|
||||
}
|
||||
|
||||
String formattedMainQrg =
|
||||
helper_formatWinTestFrequency(mainFrequencyRaw);
|
||||
|
||||
/*
|
||||
* Token 11 may contain the pass frequency, depending on the
|
||||
* Win-Test STATUS packet. Small numeric flag values must not be
|
||||
* interpreted as frequencies.
|
||||
*/
|
||||
String formattedPassQrg = null;
|
||||
|
||||
// Format as MMM.KKK.HH display format (e.g. 144.300.00) consistent with UCX thread
|
||||
// freqFloat is in kHz (e.g. 144300.0), convert to Hz-string for formatting
|
||||
long freqHzTimes100 = Math.round(freqFloat * 100.0); // e.g. 14430000
|
||||
String hzStr = String.valueOf(freqHzTimes100);
|
||||
String formattedQRG;
|
||||
if (hzStr.length() == 8) {
|
||||
// 144MHz range: 14430000 -> 144.300.00
|
||||
formattedQRG = String.format("%s.%s.%s", hzStr.substring(0, 3), hzStr.substring(3, 6), hzStr.substring(6, 8));
|
||||
} else if (hzStr.length() == 9) {
|
||||
// 1296MHz range: 129600000 -> 1296.000.00
|
||||
formattedQRG = String.format("%s.%s.%s", hzStr.substring(0, 4), hzStr.substring(4, 7), hzStr.substring(7, 9));
|
||||
} else if (hzStr.length() == 7) {
|
||||
// 70MHz range: 7010000 -> 70.100.00
|
||||
formattedQRG = String.format("%s.%s.%s", hzStr.substring(0, 2), hzStr.substring(2, 5), hzStr.substring(5, 7));
|
||||
} else if (hzStr.length() == 6) {
|
||||
// 50MHz range: 5030000 but 6 digits: 503000 -> 5.030.00
|
||||
formattedQRG = String.format("%s.%s.%s", hzStr.substring(0, 1), hzStr.substring(1, 4), hzStr.substring(4, 6));
|
||||
} else {
|
||||
formattedQRG = String.format(Locale.US, "%.1f", freqFloat); // fallback
|
||||
}
|
||||
// Parse pass frequency from parts[11] if available (WT STATUS format)
|
||||
String formattedPassQRG = null;
|
||||
if (parts.size() > 11) {
|
||||
try {
|
||||
long passFrequencyRaw =
|
||||
Long.parseLong(parts.get(11));
|
||||
double passFrequencyKHz =
|
||||
passFrequencyRaw / 10.0;
|
||||
|
||||
if (passFrequencyKHz > 100.0) {
|
||||
formattedPassQrg =
|
||||
helper_formatWinTestFrequency(
|
||||
passFrequencyRaw
|
||||
);
|
||||
String passFreqRaw = parts.get(11);
|
||||
double passFreqFloat = Integer.parseInt(passFreqRaw) / 10.0;
|
||||
if (passFreqFloat > 100) { // Must be a valid radio frequency (> 100 kHz), protects against parsing boolean flag tokens
|
||||
long passFreqHzTimes100 = Math.round(passFreqFloat * 100.0);
|
||||
String passHzStr = String.valueOf(passFreqHzTimes100);
|
||||
if (passHzStr.length() == 8) {
|
||||
formattedPassQRG = String.format("%s.%s.%s", passHzStr.substring(0, 3), passHzStr.substring(3, 6), passHzStr.substring(6, 8));
|
||||
} else if (passHzStr.length() == 9) {
|
||||
formattedPassQRG = String.format("%s.%s.%s", passHzStr.substring(0, 4), passHzStr.substring(4, 7), passHzStr.substring(7, 9));
|
||||
} else if (passHzStr.length() == 7) {
|
||||
formattedPassQRG = String.format("%s.%s.%s", passHzStr.substring(0, 2), passHzStr.substring(2, 5), passHzStr.substring(5, 7));
|
||||
} else if (passHzStr.length() == 6) {
|
||||
formattedPassQRG = String.format("%s.%s.%s", passHzStr.substring(0, 1), passHzStr.substring(1, 4), passHzStr.substring(4, 6));
|
||||
} else {
|
||||
formattedPassQRG = String.format(Locale.US, "%.1f", passFreqFloat);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException
|
||||
| ArithmeticException ignored) {
|
||||
/*
|
||||
* Token 11 does not contain a usable frequency.
|
||||
* The main frequency remains the safe fallback.
|
||||
*/
|
||||
} catch (Exception ignored) {
|
||||
// parts[11] not a valid frequency, leave formattedPassQRG as null
|
||||
}
|
||||
}
|
||||
|
||||
boolean usePassQrg = client
|
||||
.getChatPreferences()
|
||||
.isLogsynch_wintestUsePassQrg();
|
||||
|
||||
final String qrgToSet =
|
||||
usePassQrg && formattedPassQrg != null
|
||||
? formattedPassQrg
|
||||
: formattedMainQrg;
|
||||
|
||||
if (client
|
||||
.getChatPreferences()
|
||||
.isLogsynch_wintestQrgSyncEnabled()) {
|
||||
Platform.runLater(
|
||||
() -> client
|
||||
.getChatPreferences()
|
||||
.getMYQRGFirstCat()
|
||||
.set(qrgToSet)
|
||||
);
|
||||
if (this.client.getChatPreferences().isLogsynch_wintestQrgSyncEnabled()) {
|
||||
final String qrgToSet = (this.client.getChatPreferences().isLogsynch_wintestUsePassQrg() && formattedPassQRG != null)
|
||||
? formattedPassQRG
|
||||
: formattedQRG;
|
||||
// JavaFX StringProperty must be updated on the FX Application Thread
|
||||
Platform.runLater(() -> this.client.getChatPreferences().getMYQRGFirstCat().set(qrgToSet));
|
||||
}
|
||||
|
||||
System.out.println(
|
||||
"[WinTest STATUS] stn=" + stationName
|
||||
+ ", mode=" + mode
|
||||
+ ", qrg=" + formattedMainQrg
|
||||
+ (formattedPassQrg != null
|
||||
? ", passQrg=" + formattedPassQrg
|
||||
: "")
|
||||
+ ", selectedQrg=" + qrgToSet
|
||||
+ ", syncActive="
|
||||
+ client
|
||||
.getChatPreferences()
|
||||
.isLogsynch_wintestQrgSyncEnabled()
|
||||
);
|
||||
} catch (Exception exception) {
|
||||
System.out.println(
|
||||
"[WinTest] STATUS parsing error: "
|
||||
+ exception.getMessage()
|
||||
);
|
||||
System.out.println("[WinTest STATUS] stn=" + stn + ", mode=" + mode + ", qrg=" + formattedQRG
|
||||
+ (formattedPassQRG != null ? ", passQrg=" + formattedPassQRG : "")
|
||||
+ ", syncActive=" + this.client.getChatPreferences().isLogsynch_wintestQrgSyncEnabled());
|
||||
} catch (Exception e) {
|
||||
System.out.println("[WinTest] STATUS parsing error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -820,11 +820,7 @@ public class ChatPreferences {
|
||||
}
|
||||
|
||||
public void setStn_pstRotatorPort(int stn_pstRotatorPort) {
|
||||
/*
|
||||
* PSTRotator sends position reports to the configured UDP port + 1.
|
||||
* Port 65535 would therefore require the invalid local port 65536.
|
||||
*/
|
||||
if (stn_pstRotatorPort < 1 || stn_pstRotatorPort > 65534) {
|
||||
if (stn_pstRotatorPort < 1 || stn_pstRotatorPort > 65535) {
|
||||
this.stn_pstRotatorPort = 12000;
|
||||
} else {
|
||||
this.stn_pstRotatorPort = stn_pstRotatorPort;
|
||||
@@ -2631,15 +2627,10 @@ public class ChatPreferences {
|
||||
|
||||
if (callSign != null
|
||||
&& !callSign.isBlank()) {
|
||||
/*
|
||||
* Older preference files may still contain complete KST callsigns
|
||||
* such as DN9APW-2. Monitoring is stored by base callsign so that
|
||||
* every suffix of the same station is covered by one entry.
|
||||
*/
|
||||
String normalizedCallSign =
|
||||
ChatMember.normalizeCallSignToBaseCallSign(
|
||||
callSign
|
||||
);
|
||||
callSign
|
||||
.trim()
|
||||
.toUpperCase();
|
||||
|
||||
if (!lstNotify_QSOSniffer_sniffedCallSignList
|
||||
.contains(normalizedCallSign)) {
|
||||
@@ -2665,28 +2656,12 @@ public class ChatPreferences {
|
||||
for (int i = 0; i < children.getLength(); i++) {
|
||||
Node child = children.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String callSign = child.getTextContent();
|
||||
|
||||
if (callSign != null
|
||||
&& !callSign.isBlank()) {
|
||||
|
||||
/*
|
||||
* Older preference files may contain complete KST callsigns
|
||||
* such as DN9APW-2. QSO monitoring is stored by base callsign,
|
||||
* so one entry covers every suffix of the same station.
|
||||
*/
|
||||
String normalizedCallSign =
|
||||
ChatMember.normalizeCallSignToBaseCallSign(
|
||||
callSign
|
||||
);
|
||||
|
||||
if (normalizedCallSign != null
|
||||
&& !normalizedCallSign.isBlank()
|
||||
&& !lstNotify_QSOSniffer_sniffedCallSignList
|
||||
.contains(normalizedCallSign)) {
|
||||
lstNotify_QSOSniffer_sniffedCallSignList
|
||||
.add(normalizedCallSign);
|
||||
}
|
||||
String word = child.getTextContent();
|
||||
if (word != null) {
|
||||
word = word.trim();
|
||||
}
|
||||
if (word != null && !word.isEmpty()) {
|
||||
lstNotify_QSOSniffer_sniffedWordsList.add(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4775,31 +4775,21 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
callSignColumn.setOnEditCommit(event -> {
|
||||
int row = event.getTablePosition().getRow();
|
||||
|
||||
String enteredCallSign =
|
||||
String newValue =
|
||||
event.getNewValue() == null
|
||||
? ""
|
||||
: event.getNewValue()
|
||||
.trim()
|
||||
.toUpperCase(Locale.ROOT);
|
||||
|
||||
if (enteredCallSign.isBlank()) {
|
||||
if (newValue.isBlank()) {
|
||||
event.getTableView()
|
||||
.getItems()
|
||||
.remove(row);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* QSO monitoring intentionally works with the base callsign.
|
||||
* Entering DN9APW, DN9APW-2 or DN9APW-70 therefore produces
|
||||
* the same monitoring entry: DN9APW.
|
||||
*/
|
||||
String monitoredBaseCall =
|
||||
ChatMember.normalizeCallSignToBaseCallSign(
|
||||
enteredCallSign
|
||||
);
|
||||
|
||||
if (!GuiUtils.isCallSignSyntax(monitoredBaseCall)) {
|
||||
if (!GuiUtils.isCallSignSyntax(newValue)) {
|
||||
alertWindowEvent(
|
||||
"Please enter a valid callsign."
|
||||
);
|
||||
@@ -4823,9 +4813,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
.get(i);
|
||||
|
||||
if (existing != null
|
||||
&& existing.equalsIgnoreCase(
|
||||
monitoredBaseCall
|
||||
)) {
|
||||
&& existing.equalsIgnoreCase(newValue)) {
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
@@ -4833,7 +4821,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
if (duplicate) {
|
||||
alertWindowEvent(
|
||||
"This base callsign is already "
|
||||
"This callsign is already "
|
||||
+ "in the monitoring list."
|
||||
);
|
||||
event.getTableView().refresh();
|
||||
@@ -4842,7 +4830,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
event.getTableView()
|
||||
.getItems()
|
||||
.set(row, monitoredBaseCall);
|
||||
.set(row, newValue);
|
||||
});
|
||||
|
||||
table.getColumns().add(callSignColumn);
|
||||
@@ -4945,51 +4933,40 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores one beacon template.
|
||||
* Validates and stores one beacon text.
|
||||
*
|
||||
* <p>The template is checked against the same protocol and length rules which
|
||||
* are applied by the timer before transmission. A variable-only template may
|
||||
* temporarily resolve to an empty value and can still be stored; the timer will
|
||||
* not send it until a usable value is available.</p>
|
||||
* <p>The final text is checked after global variables have been resolved.
|
||||
* Otherwise a template with at most 120 characters could still exceed the
|
||||
* server limit after values such as MYQRG or MYLOCATOR were inserted.</p>
|
||||
*
|
||||
* @param textField field containing the configured beacon template
|
||||
* @param mainCategory {@code true} for the main category, {@code false} for
|
||||
* the optional second category
|
||||
*/
|
||||
private void applyBeaconTextSetting(
|
||||
TextField textField,
|
||||
boolean mainCategory
|
||||
) {
|
||||
String configuredText =
|
||||
textField.getText() == null
|
||||
? ""
|
||||
: textField.getText();
|
||||
|
||||
try {
|
||||
chatcontroller.validateBeaconTemplate(configuredText);
|
||||
private void applyBeaconTextSetting(TextField textField, boolean mainCategory) {
|
||||
String configuredText = textField.getText() == null ? "" : textField.getText();
|
||||
String resolvedText = messageVariableResolver.resolveGlobalVariables(configuredText);
|
||||
|
||||
if (resolvedText != null
|
||||
&& resolvedText.length() <= ChatController.MAX_BEACON_TEXT_LENGTH) {
|
||||
if (mainCategory) {
|
||||
chatcontroller.getChatPreferences()
|
||||
.setBcn_beaconTextMainCat(configuredText);
|
||||
chatcontroller.getChatPreferences().setBcn_beaconTextMainCat(configuredText);
|
||||
} else {
|
||||
chatcontroller.getChatPreferences()
|
||||
.setBcn_beaconTextSecondCat(configuredText);
|
||||
chatcontroller.getChatPreferences().setBcn_beaconTextSecondCat(configuredText);
|
||||
}
|
||||
} catch (IllegalArgumentException exception) {
|
||||
String previousText =
|
||||
mainCategory
|
||||
? chatcontroller.getChatPreferences()
|
||||
.getBcn_beaconTextMainCat()
|
||||
: chatcontroller.getChatPreferences()
|
||||
.getBcn_beaconTextSecondCat();
|
||||
|
||||
textField.setText(previousText);
|
||||
|
||||
alertWindowEvent(
|
||||
"The beacon message is invalid: "
|
||||
+ exception.getMessage()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
String previousText = mainCategory
|
||||
? chatcontroller.getChatPreferences().getBcn_beaconTextMainCat()
|
||||
: chatcontroller.getChatPreferences().getBcn_beaconTextSecondCat();
|
||||
|
||||
textField.setText(previousText);
|
||||
alertWindowEvent(
|
||||
"The resolved beacon message must not exceed "
|
||||
+ ChatController.MAX_BEACON_TEXT_LENGTH
|
||||
+ " characters."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8426,12 +8403,12 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
Predicate<ChatMember> inactivePredicate = new Predicate<ChatMember>() {
|
||||
@Override
|
||||
public boolean test(ChatMember chatMember) {
|
||||
long inactiveMinutes =
|
||||
Utils4KST.time_getSecondsBetweenEpochAndNow(
|
||||
chatMember.getActivityTimeLastInEpoch() + ""
|
||||
) / 60L;
|
||||
|
||||
return inactiveMinutes <= 20L;
|
||||
|
||||
if ((Utils4KST.time_getSecondsBetweenEpochAndNow(chatMember.getActivityTimeLastInEpoch()+"") /60%60) > 20) {
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
}
|
||||
};
|
||||
btnTglInactive.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@@ -9414,7 +9391,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
txtFld_station_pstRotatorPort.getText().trim()
|
||||
);
|
||||
|
||||
if (configuredPort < 1 || configuredPort > 65534) {
|
||||
if (configuredPort < 1 || configuredPort > 65535) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
@@ -9424,7 +9401,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
} catch (NumberFormatException exception) {
|
||||
showUserInputErrorWindow(
|
||||
"\"" + txtFld_station_pstRotatorPort.getText()
|
||||
+ "\" is not a valid UDP port. Enter a value between 1 and 65534. PSTRotator reports its position on the following UDP port."
|
||||
+ "\" is not a valid UDP port. Enter a value between 1 and 65535."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9535,7 +9512,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
} catch (NumberFormatException exception) {
|
||||
showUserInputErrorWindow(
|
||||
"\"" + stn_txtServerPort.getText()
|
||||
+ "\" is not a valid TCP port. Enter a value between 1 and 65534. PSTRotator reports its position on the following UDP port."
|
||||
+ "\" is not a valid TCP port. Enter a value between 1 and 65535."
|
||||
);
|
||||
|
||||
stn_txtServerPort.setText(
|
||||
@@ -10261,7 +10238,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
showUserInputErrorWindow(
|
||||
"\"" + txtFld_asUDPPortInt.getText()
|
||||
+ "\" is not a valid UDP port. "
|
||||
+ "Enter a value between 1 and 65534. PSTRotator reports its position on the following UDP port."
|
||||
+ "Enter a value between 1 and 65535."
|
||||
);
|
||||
|
||||
txtFld_asUDPPortInt.setText(
|
||||
@@ -10747,7 +10724,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
testSpot.setFrequency(
|
||||
new SimpleStringProperty("300")
|
||||
);
|
||||
testSpot.setQra("Testing DXC-Spot: Congrats, you donated $100!");
|
||||
testSpot.setQra("Congrats, you donated $100");
|
||||
testSpot.setCallSign("DO5AMF");
|
||||
|
||||
if (!dxClusterServer
|
||||
@@ -10927,21 +10904,15 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
dialog.showAndWait().ifPresent(
|
||||
input -> {
|
||||
String enteredCallSign =
|
||||
String callSign =
|
||||
input
|
||||
.trim()
|
||||
.toUpperCase(
|
||||
Locale.ROOT
|
||||
);
|
||||
|
||||
String monitoredBaseCall =
|
||||
ChatMember
|
||||
.normalizeCallSignToBaseCallSign(
|
||||
enteredCallSign
|
||||
);
|
||||
|
||||
if (!GuiUtils.isCallSignSyntax(
|
||||
monitoredBaseCall
|
||||
callSign
|
||||
)) {
|
||||
alertWindowEvent(
|
||||
"Please enter "
|
||||
@@ -10956,16 +10927,15 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
.stream()
|
||||
.anyMatch(
|
||||
existing ->
|
||||
existing != null
|
||||
&& existing
|
||||
existing
|
||||
.equalsIgnoreCase(
|
||||
monitoredBaseCall
|
||||
callSign
|
||||
)
|
||||
);
|
||||
|
||||
if (duplicate) {
|
||||
alertWindowEvent(
|
||||
"This base callsign is already "
|
||||
"This callsign is already "
|
||||
+ "in the monitoring list."
|
||||
);
|
||||
return;
|
||||
@@ -10973,7 +10943,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
chatcontroller
|
||||
.getLstNotify_QSOSniffer_sniffedCallSignList()
|
||||
.add(monitoredBaseCall);
|
||||
.add(callSign);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -11714,16 +11684,12 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
//here is where all settings has to be written to the preferences instance
|
||||
|
||||
|
||||
LOGGER.log(
|
||||
Level.INFO,
|
||||
"Settings window: ON4KST connection requested for {0} in {1}; "
|
||||
+ "second chat enabled: {2}",
|
||||
new Object[] {
|
||||
chatcontroller.getChatPreferences().getStn_loginCallSign(),
|
||||
choiceBxChatChategory.getSelectionModel().getSelectedItem(),
|
||||
chatcontroller.getChatPreferences().isLoginToSecondChatEnabled()
|
||||
}
|
||||
);
|
||||
System.out.println("[Info] Main.java: connect clicked, using "
|
||||
+ chatcontroller.getChatPreferences().getStn_loginCallSign() + " / "
|
||||
+ chatcontroller.getChatPreferences().getStn_loginPassword() + " / "
|
||||
+ chatcontroller.getChatPreferences().getStn_loginNameMainCat() + " / "
|
||||
+ chatcontroller.getChatPreferences().getStn_loginLocatorMainCat() + " at category "
|
||||
+ choiceBxChatChategory.getSelectionModel().getSelectedItem());
|
||||
|
||||
try {
|
||||
|
||||
|
||||
@@ -279,15 +279,6 @@ public final class StationMapView {
|
||||
updateStatusLabel();
|
||||
updateDetailPanel(selectedSnapshot);
|
||||
|
||||
/*
|
||||
* The detail pane is useful only while path analysis is enabled and a
|
||||
* concrete station is selected. Reset view therefore removes the pane
|
||||
* instead of leaving an empty analysis area beside the map.
|
||||
*/
|
||||
updateDetailPanePresence(
|
||||
profileSection.isVisible() && selectedSnapshot != null
|
||||
);
|
||||
|
||||
if (mapReady) {
|
||||
renderAll();
|
||||
}
|
||||
@@ -550,15 +541,7 @@ public final class StationMapView {
|
||||
|
||||
pathAnalysisSection.setVisible(visible);
|
||||
pathAnalysisSection.setManaged(visible);
|
||||
|
||||
/*
|
||||
* Showing path analysis must not create an empty detail pane when no
|
||||
* station is selected. The pane is restored automatically with the next
|
||||
* valid station selection.
|
||||
*/
|
||||
updateDetailPanePresence(
|
||||
visible && lastSelectedSnapshot != null
|
||||
);
|
||||
updateDetailPanePresence(visible);
|
||||
|
||||
pathAnalysisHiddenHintLabel.setVisible(!visible);
|
||||
pathAnalysisHiddenHintLabel.setManaged(!visible);
|
||||
|
||||
@@ -2386,8 +2386,4 @@ PA2RU;René;JO32LT;StringProperty [value: null]; wkd true; wkd144 false; wkd432f
|
||||
SM6VTZ;Chris .135;JO58UJ;StringProperty [value: 144.135]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
SM7EYW;Torleif 432,205;JO65NK;StringProperty [value: 144.205]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
DJ8MS;Tor_70cm;JO54UC;StringProperty [value: null]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
DK0MM;Jens/Alex;JN49IU;StringProperty [value: 432.305]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
SM6VTZ;Chris .135;JO58UJ;StringProperty [value: 144.135]; wkd true; wkd144 true; wkd432false; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
SM6VTZ;Chris .135;JO58UJ;StringProperty [value: 432.135]; wkd true; wkd144 true; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
LA0BY;Stefan @ hilltop;JO59IX;StringProperty [value: 144.062]; wkd true; wkd144 true; wkd432false; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
LA0BY;null;JO49ML;StringProperty [value: null]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; null
|
||||
DK0MM;Jens/Alex;JN49IU;StringProperty [value: 432.305]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
title: Automatic Private Replies
|
||||
icon: ↩️
|
||||
category: ON4KST Chat
|
||||
since: "1.25"
|
||||
summary: Answer repeated private messages or QRG requests without losing the complete callsign, chat category or protection against automatic reply loops.
|
||||
description: KST4Contest can send a predefined answer to incoming private messages and provide the QRG belonging to the category in which a request was received.
|
||||
tagsList:
|
||||
- ON4KST
|
||||
- automatic reply
|
||||
- private message
|
||||
- QRG
|
||||
- sked request
|
||||
- dual chat
|
||||
related:
|
||||
- dual-chat
|
||||
- macros
|
||||
- sked-reminder
|
||||
---
|
||||
|
||||
## Why use an automatic reply?
|
||||
|
||||
Not every station visible in the ON4KST chat is taking part in the current contest. Some operators may be monitoring activity, testing their station or simply remaining logged in while not accepting skeds.
|
||||
|
||||
That distinction is not always checked before requests are sent. During a busy contest, the same station may therefore receive several similar private messages and have to enter the same refusal repeatedly.
|
||||
|
||||
KST4Contest can provide that answer automatically while leaving the incoming message visible.
|
||||
|
||||
## Two separate reply functions
|
||||
|
||||
The general automatic reply sends one configured text in response to an incoming private message. A practical example is:
|
||||
|
||||
```text
|
||||
Sri, I am not taking part in this contest. No skeds.
|
||||
```
|
||||
|
||||
The QRG reply serves a different purpose. It recognises common questions such as:
|
||||
|
||||
```text
|
||||
qrg?
|
||||
freq?
|
||||
pse qrg
|
||||
```
|
||||
|
||||
and answers with the QRG belonging to the chat category in which the request was received:
|
||||
|
||||
```text
|
||||
[KST4C Automsg] QRG is: 144.300.00
|
||||
```
|
||||
|
||||
When both functions are enabled, a recognised QRG request receives the QRG reply only. It does not additionally trigger the general answer.
|
||||
|
||||
## Category and callsign remain part of the message
|
||||
|
||||
An automatic reply is addressed to the complete callsign of the sender, including any visible suffix. It is also sent through the same chat category as the incoming message.
|
||||
|
||||
A request from `CALLSIGN-70` is therefore not silently redirected to `CALLSIGN`, and a message received through the microwave chat is not answered through the primary VHF/UHF category.
|
||||
|
||||
This is particularly important in station setups which use separate suffixes for different bands or operating positions.
|
||||
|
||||
## Missing information is not useful information
|
||||
|
||||
KST4Contest sends a QRG reply only when a QRG is available for the relevant category. It does not produce an answer containing only:
|
||||
|
||||
```text
|
||||
QRG is:
|
||||
```
|
||||
|
||||
A general answer must likewise contain actual text and must not contain characters which would break the ON4KST protocol frame.
|
||||
|
||||
Rejecting these replies locally is intentional. An automatic response which contains no usable information has saved nobody any work.
|
||||
|
||||
## Preventing loops and repeated answers
|
||||
|
||||
Every automatic reply contains:
|
||||
|
||||
```text
|
||||
[KST4C Automsg]
|
||||
```
|
||||
|
||||
Messages which already contain this prefix are not answered automatically. Two KST4Contest clients therefore do not continue replying to each other.
|
||||
|
||||
A shared two-minute cooldown additionally applies to the general and QRG-specific functions. It is tracked separately for each complete callsign and chat category.
|
||||
|
||||
A rejected reply does not start the cooldown. If a QRG was missing and is entered afterwards, the next request can be answered immediately.
|
||||
|
||||
## Operational limits
|
||||
|
||||
The function reacts to incoming text. It does not decide whether the sender's request was reasonable, whether a sked could be possible later or whether the configured refusal still reflects the current operating status.
|
||||
|
||||
The general reply should therefore be enabled only while its text remains correct. A message which says that the station is not participating becomes misleading if the operator starts working the contest half an hour later.
|
||||
|
||||
In plain terms: automatic replies remove repetitive typing. They do not take over the conversation.
|
||||
|
||||
[Read the complete configuration and recognised QRG requests in the manual.](/manual/en/configuration/#messagehandling-settings-from-v125)
|
||||
|
||||
[Read how two chat categories and suffixed callsigns are kept separate.](/features/dual-chat/)
|
||||
@@ -20,8 +20,6 @@ related:
|
||||
|
||||
## Three different mechanisms
|
||||
|
||||

|
||||
|
||||
KST4Contest uses three related but distinct mechanisms:
|
||||
|
||||
| Mechanism | Purpose |
|
||||
@@ -52,10 +50,7 @@ pse call me at MYQRGSHORT
|
||||
|
||||
Shortcuts are useful for short expressions which are required frequently and are not necessarily addressed to a particular station.
|
||||
|
||||
The exact entries `MYQRG` and `SECONDQRG` are recognised as frequency buttons and insert the corresponding current QRG.
|
||||
|
||||
The shortcut `/SETNAME MYQRG` is highlighted as well. It resolves the current primary QRG and prepares the complete server command in the send field. The command is not transmitted automatically and remains available for review.
|
||||
|
||||
`MYQRG` and `SECONDQRG` are also recognised as frequency buttons and insert the corresponding current QRG.
|
||||
|
||||
## Text snippets
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
title: QSO Monitoring
|
||||
icon: 👁️
|
||||
category: ON4KST Chat
|
||||
since: "1.31"
|
||||
summary: Follow messages sent or received by one station across its KST suffixes without changing the actual message destination or chat category.
|
||||
description: KST4Contest can show the communication of selected stations additionally in the PM table while keeping complete callsigns, message routing and chat categories intact.
|
||||
tagsList:
|
||||
- ON4KST
|
||||
- QSO monitoring
|
||||
- QSO sniffer
|
||||
- callsign suffix
|
||||
- sked
|
||||
- contest team
|
||||
- dual chat
|
||||
related:
|
||||
- dual-chat
|
||||
- sked-reminder
|
||||
- automatic-replies
|
||||
---
|
||||
|
||||
## Why monitor another station?
|
||||
|
||||
During a busy contest, an interesting exchange can disappear quickly in the general chat traffic. This is particularly relevant when another station in the same team is arranging skeds or when a rare station is communicating with several potential callers.
|
||||
|
||||
KST4Contest can show this communication additionally in the PM table.
|
||||
|
||||

|
||||
|
||||
## One station may use several chat callsigns
|
||||
|
||||
Band- or operating-position-specific KST suffixes are common:
|
||||
|
||||
```text
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
DN9APW-144
|
||||
DN9APW-432
|
||||
```
|
||||
|
||||
Entering every variant manually would be possible, but it would also be unnecessary work and easy to forget when another suffix appears.
|
||||
|
||||
QSO monitoring therefore uses the normalised base callsign. Entering any of the callsigns above creates one entry:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
```
|
||||
|
||||
That entry covers messages sent by or addressed to every visible suffix of the same base callsign.
|
||||
|
||||
## What is shown?
|
||||
|
||||
A monitored message appears in the PM table with its complete sender and receiver:
|
||||
|
||||
```text
|
||||
Sniffed: (DN9APW-70 > 9A0BB-23) pse sked 19:30
|
||||
```
|
||||
|
||||
The display includes:
|
||||
|
||||
- directed messages sent by the monitored station;
|
||||
- directed messages addressed to the monitored station; and
|
||||
- public messages which the monitored station sends to `ALL`.
|
||||
|
||||
The original message remains in its normal table. KST4Contest does not remove, redirect or rewrite it.
|
||||
|
||||
## Monitoring and routing solve different problems
|
||||
|
||||
The base callsign is used to decide whether a message should be shown in the monitoring view. The complete visible callsign and chat category are still used for message routing.
|
||||
|
||||
A message for `DN9APW-70` therefore remains a message for `DN9APW-70`. It is not redirected to `DN9APW`, `DN9APW-2` or another suffix.
|
||||
|
||||
This is the same distinction used elsewhere in KST4Contest: station-related information may be shared through the base callsign, while communication remains attached to the actual ON4KST login.
|
||||
|
||||
## Both chat categories are included
|
||||
|
||||
When two ON4KST categories are connected, the same monitoring list applies to both. There is no need to configure the station separately for each category.
|
||||
|
||||
The category of the individual message remains part of its context. Combining the monitoring view does not merge the underlying chat connections.
|
||||
|
||||
## What the function does not do
|
||||
|
||||
QSO monitoring does not search the message text for callsign mentions. The monitored station must be the actual sender or receiver.
|
||||
|
||||
It also does not generate a separate notification sound and does not decide whether the message really contains a useful sked arrangement. It provides visibility, not interpretation.
|
||||
|
||||
No additional messages are requested from the ON4KST server. The function only presents chat traffic which KST4Contest has already received.
|
||||
|
||||
## Configuration
|
||||
|
||||
Add a callsign under **QSO monitoring** in the **Notification** tab. KST4Contest immediately reduces any visible KST suffix or portable addition to the base callsign.
|
||||
|
||||
The list can be edited directly and is stored with **Save Settings**.
|
||||
|
||||
[Read the complete QSO monitoring configuration in the manual.](/manual/en/configuration/#sniffer-settings-from-v131)
|
||||
|
||||
[Read why complete callsigns and chat categories remain separate.](/features/dual-chat/)
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
title: PSTRotator Control
|
||||
icon: 🧭
|
||||
category: Station Control
|
||||
since: "1.31"
|
||||
summary: Point the antenna at a selected chat station and use the azimuth reported by PSTRotator throughout the KST4Contest operating context.
|
||||
description: KST4Contest calculates the direction of a selected station, sends it to PSTRotator and uses the reported antenna position for filters, priorities, timelines and map displays.
|
||||
tagsList:
|
||||
- PSTRotator
|
||||
- antenna rotator
|
||||
- azimuth
|
||||
- QTF
|
||||
- UDP
|
||||
- SPID
|
||||
related:
|
||||
- priority-score
|
||||
- timeline
|
||||
- airscout
|
||||
---
|
||||
|
||||
## Why connect the rotator to the chat client?
|
||||
|
||||
A station selected in the chat already has a locator and a calculated QTF. Entering the same direction manually into another application adds another small task at precisely the point where the operator is preparing a contact.
|
||||
|
||||
KST4Contest can send that direction directly to PSTRotator.
|
||||
|
||||

|
||||
|
||||
## Sending a direction
|
||||
|
||||
Press **Turn ant1 to …** in the Further Info section of the selected station.
|
||||
|
||||
KST4Contest:
|
||||
|
||||
1. calculates the azimuth from both station locators;
|
||||
2. disables PSTRotator tracking mode;
|
||||
3. sends the target as an integer azimuth; and
|
||||
4. receives the current position reported by PSTRotator.
|
||||
|
||||
The function uses UDP. PSTRotator receives commands on the configured control port and reports its position on the following port.
|
||||
|
||||
With the default control port `12000`, KST4Contest therefore listens on `12001`.
|
||||
|
||||
## One position, several consumers
|
||||
|
||||
The reported azimuth becomes the current QTF in KST4Contest. The value is subsequently used by:
|
||||
|
||||
- the direction filter;
|
||||
- direction-opportunity detection;
|
||||
- the Priority Score;
|
||||
- the antenna sector on the map;
|
||||
- the AP and sked timeline; and
|
||||
- the `MYQTF` message variable.
|
||||
|
||||
This shared use is intentional. The antenna should not be shown pointing in one direction while the filters and candidate calculations continue to assume another.
|
||||
|
||||
## SPID compatibility check
|
||||
|
||||
Some SPID configurations occasionally fail to react to the first direction command.
|
||||
|
||||
KST4Contest checks the reported position after two seconds. If no movement was reported and the target has not been reached, it sends one compatibility sequence through `0°` and then repeats the intended target.
|
||||
|
||||
The check runs in the background and does not block the user interface.
|
||||
|
||||
## Limits of the integration
|
||||
|
||||
The current interface controls and evaluates azimuth only. It does not provide elevation tracking.
|
||||
|
||||
The reported QTF describes what PSTRotator returns. Whether the antenna mechanically reaches that exact position still depends on the rotor, controller, calibration and configured offsets.
|
||||
|
||||
UDP also provides no delivery confirmation. Correct host, port, return port and firewall settings remain necessary.
|
||||
|
||||
In plain terms: KST4Contest removes the repeated transfer of a direction from one window to another. It does not turn an uncalibrated rotor into a calibrated one.
|
||||
|
||||
[Read the complete setup and port assignment in the manual.](/manual/en/configuration/#pstrotator-settings-from-v131-fully-configurable-from-v140)
|
||||
|
||||
[Open the PSTRotator website.](https://www.pstrotator.com/)
|
||||