Rsclub2_2andClaude Opus 5.5 2db71ee864 Loopback tests for the network threads (#106) (#124)
* test: pin the Win-Test sked frames over a loopback socket (#106)

WinTestSkedSender is pointed at the loopback address instead of a
broadcast address, and a socket on an ephemeral port receives the
LOCKSKED/ADDSKED/UNLOCKSKED sequence. The frames and their checksum
byte are written out literally, including the \260 degree escape and
the SSB fallback for an unexpected mode ID.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: cover the PSTRotator UDP client over loopback (#106)

A socket on an ephemeral loopback port plays PSTRotator. The tests pin
the poll queries, the <PST> command frames, the AZ:/EL:/MODE: replies
reaching the listener, an unparsable reply leaving the loop alive, and
the explicit-port constructor reporting its status after start() (#115).
The reply format is derived from the parser and the PSTRotator UDP
documentation, not from a capture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: cover the AirScout UDP listener over loopback (#106)

ReadUDPbyAirScoutMessageThread gains a package-private constructor that
takes an already bound socket, as ReadUDPbyUCXMessageThread has; the
public constructor still binds the configured port in run(). The tests
pin applying an ASNEAREST response to every active variant of the
receiver, the case-sensitive server/client match with a UTF-8 client
name, the disabled listener, the poison pill, recovery from a malformed
response, and the date losing its space because the parser strips all
spaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: cover UCXLog/DXLog QSO packets over loopback (#106)

The UCX loopback test now sends contactinfo and contactreplace packets:
transport bytes before the XML are dropped, the QSO reaches the
controller with band, locator and source, the gross field is
registered, an unknown station is stored in the database and the UDP
backup file, a known one is only updated, and nothing happens while log
sync is disabled. A RadioInfo packet sent afterwards serves as an
ordering marker instead of a sleep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: cover the local DX Cluster server over loopback (#106)

DXClusterThreadPooledServer gains a package-private constructor that
takes an already bound server socket; the public constructor still binds
the configured port in run(). Plain sockets on the loopback address act
as logging programs. The tests pin the listening status, the "login: "
prompt, one DXSpider-style line with BEL BEL CR LF per spot to every
client, the rejection of spots that cannot be formatted, and stop()
closing the clients and ending the server thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the UCXLog/DXLog listener alive on bad input (#106)

An unwritable or empty backup path left the FileWriter null, and the
following BufferedWriter threw a NullPointerException; a RadioInfo
without <Freq> or <Mode> threw one as well. Neither was caught, so the
listener thread ended for good. The backup line is now written with
try-with-resources and skipped with a log line when the file cannot be
opened, an incomplete RadioInfo element is skipped, and run() drops a
packet whose processing throws any RuntimeException, reports a
non-critical status and keeps receiving.

The loopback tests cover all three paths. The interrupt test now waits
for a processed marker packet instead of sleeping and no longer claims
more than it can observe, and the marker helper states its in-order
assumption for UDP on loopback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: let a second DX Cluster server run() bind again (#106)

The pre-bound-socket constructor made run() skip binding whenever a
server socket existed. A run() after the first one ended would then
accept on a closed socket. Bind whenever the socket is missing or
closed, which restores the behaviour of the public constructor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: make the ignored AirScout responses observable (#106)

The tests for responses to another client or server and for the
disabled listener only checked that nothing happened before the poison
pill, which a listener that never read the datagrams would also pass.
Each now sends a valid sentinel afterwards and waits for it, and the
ignored responses name a different receiver, so a wrongly processed
copy is detectable; the disabled case also shows that the switch was
asked once per response. The date test is renamed and documented as a
pinned known defect, so a parser fix knows to flip it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: wait for the PSTRotator listener thread after stop() (#106)

The client keeps its listener thread private, so the test finds it by
the name start() gives it and joins it after stop(), asserting that
exactly one such thread existed and that it ended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep the UCX listener alive when the status callback throws (#106)

Review follow-up. The safety net reported a dropped packet through the
status callback without guarding it, so a throwing callback still ended
the listener. The test for an unwritable backup file is renamed to what
it proves, and the changelog mentions that any unexpected error now
drops only the affected packet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:19:22 +02:00
2023-11-10 08:33:17 +01:00
2026-10-08 23:22:11 +02:00
2026-10-08 23:22:11 +02:00
2024-01-16 22:51:30 +01:00
2023-11-09 22:53:59 +01:00
2023-11-14 00:50:10 +01:00
2023-11-10 08:33:17 +01:00

KST4Contest

KST4Contest is a Java-based client for the ON4KST chat, developed for coordinated VHF, UHF and microwave contest operation.

The application is developed by Marc Fröhlich (DO5AMF) and since 2026 Philipp Wagner (DN9APW).

Start here

What KST4Contest does

KST4Contest combines the ON4KST chat with information that is useful when coordinating contacts during a contest.

Among other things, it can:

  • display and filter stations from the supported ON4KST chat categories;
  • derive band and frequency information from chat messages and station names;
  • maintain Worked and NOT QRV information for the available bands;
  • calculate station priorities from distance, activity and other available information;
  • manage internal skeds and received Win-Test skeds;
  • use AirScout information when evaluating possible aircraft-scatter contacts;
  • display stations, paths and additional propagation information on maps;
  • exchange information with supported logging programs, Win-Test, PSTRotator and a local DX Cluster interface;
  • provide configurable automatic replies for recurring chat requests.

Calculated scores, aircraft-scatter information and path assessments are operating aids. They depend on the available data and should not be treated as guarantees that a contact is possible.

Installation

Ready-to-use packages are available for Windows, Linux and macOS. These packages include the required Java runtime, so a separate Java installation is normally not necessary.

Use the central download page to select the appropriate build:

  • Stable is intended for normal contest operation.
  • Beta contains changes that are being prepared for a stable release.
  • Nightly contains the latest automated development build and is mainly intended for testing.

Open the download page

Documentation

The documentation is available in German and English:

The Markdown sources used for the wiki and the generated PDF manuals are stored in github_docs.

Changes to operating behaviour should be documented together with their purpose and limitations. This is especially important for functions whose result depends on external data, heuristics or information derived from chat messages.

Building from source

Building KST4Contest requires JDK 21. The Gradle Wrapper included in the repository should be used, so a separate Gradle installation is not required.

Linux and macOS:

./gradlew clean build

Windows:

.\gradlew.bat clean build

Repository structure

  • core/ – domain, controller and network code, free of user-interface technology
  • app-desktop/ – the Compose Multiplatform user interface and the packaging tasks
  • github_docs/ – German and English manual sources
  • website/ – project website sources
  • packaging/ – platform-specific packaging files

CI status

Documentation

Publish wiki

Docs PDF

Builds

Nightly Runtime Artifacts

License

KST4Contest is distributed under the GNU General Public License v3.0.

Supporters/Sponsor

This Project is possible due to donations of the community.

You can sponsor KST4Contest here: Support on Ko-Fi. If you add an Display Name there you will be mentioned here.

The following people are sponsoring KST4Contest:

  • Marco (DJ5KW)
S
Description
No description provided
Readme GPL-3.0
1 GiB
0 Stars 1 Watchers 0 Forks
Languages
Java 54%
Kotlin 36.3%
JavaScript 5%
Nunjucks 1.8%
CSS 0.9%
Other 2%