Show the other computers, and apply the ten-minute rule

Three pieces on top of the link:

**The network status window**, on the entry window's Window menu. A row
per station, this computer included the way N1MM shows it: number,
address, operator, band, mode, run, transmit, pass frequency, the last
message type, how long ago it arrived, the counts each way and the echo
round trip. A station that broadcast the wrong version is named under the
table in red — that is the one fault where everything looks connected
and nothing arrives. The box at the bottom sends a line of chat, and
Echo asks every station whether it is there.

**Where this station is** goes out once a second when it has changed.
The frequency, the mode and run have a dozen places they can change from
— the radio moving, a band button, a QSY typed into the callsign box —
so it is read and compared rather than announced from each of them.

**The ten-minute rule.** `BandChangeRules` already counted changes and
the stay on a band, and the entry window already showed the countdown,
but only a user-defined contest carried a rule, so every built-in
contest allowed anything. `ForCategory` gives a multi-operator entry
with one or two transmitters a ten-minute stay, which is N1MM's fallback
in `ContestInstance.BandChangeTimerDuration` for every contest that does
not name its own. Its per-contest table is a few hundred cases in a
decompiled hash switch and is not repeated.

Config ▸ Edit Networked-Computer Names now covers both networks: the
12060 broadcast to other programs and the 12070 link, with the station
number, the port, the version to claim and stations named by address for
a network where a broadcast does not reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PdAYHcdRktqKry7nk414TU
This commit is contained in:
2026-09-03 15:26:42 +00:00
parent c0e1bc1e1b
commit 6f2f39768c
12 changed files with 588 additions and 3 deletions

View File

@@ -16,6 +16,7 @@ is still sitting there undiscovered.
| `OtrspBox` | a `MemoryStream`, checking the bytes | no real SO2R box. Command forms are from N1MM's `N1MMPort.cs`. |
| `ClusterClient` | a node fake over a real socket, sending the telnet negotiation, the login prompt and spot lines | no live cluster node. Which nodes send bare CR, and which send option negotiation, is guessed from N1MM's code. |
| `StationNetwork` | the message format, round-tripped | no second station, and no N1MM on the same network. |
| `StationLink` | the bytes of every message, and two links talking over loopback | no real N1MM has ever been on the other end. The version check is the thing to try first: N1MM turns away a station whose version is not its own, and this program has to be told what to claim. |
| `CwDaemonSender` | the UDP messages, and a fake daemon that answers the `<ESC>h` reply request | no `cwdaemon`, no radio keyed. |
| `MmttyEngine` and the Wine bridge | MMTTY 1.70 under Wine 10 on a machine with a sound card: started, keyed, a message transmitted and decoded back off the air, and stopped | no radio. No FSK through EXTFSK, no PTT on a serial port, and 2Tone has never been run. Keying was wrong until 2026-09-01: `SetMmttyPTT` stops a transmission and does not start one, which is why nothing ever went out before then. `docs/digital-bridge.md` |
| `WinkeyerSender` | the status-byte reader, on its own | no test of the serial side, and no WinKeyer. The host-mode open sequence is from the WinKeyer datasheet; the status bits are from N1MM's `Winkey.cs`. |
@@ -348,6 +349,55 @@ keyed. Whether MMTTY holds it there with an empty buffer has not been measured:
the probe run that says it does was on a machine with no sound card, where
MMTTY does not really transmit.
**The link between the logging computers.** N1MM has two networks and this
program now has both. Port 12060 carries XML to other programs — a spot tool, a
score poster — which is `StationNetwork`. Computer to computer, N1MM uses port
12070 and a different protocol: `StationLink`.
That protocol is a UDP broadcast to find the other computers and a TCP
connection to each of them, opened both ways. A message reads
```
DATA__07%SHACK-PC%QSO%2026-09-03 12:34:56%DL1ABC%…~__DATA
```
which is the sending station's number, its computer name, the message type and
the fields of that type. `%` and `~` cannot appear in a field, so N1MM writes
`!` in their place. What is read and sent: contacts, edits, deletes, resyncs,
`IAM`, the echo pair, chat, the pass frequency, transmit on and off, and where a
station is. The rest of N1MM's forty-odd types — the score and sked windows, the
log check, the spot lists, the serial-number pool — are passed over, which
N1MM's own reader also does for a type it does not know.
**The version has to match.** N1MM compares the version in the beacon with its
own and, when they differ, puts up "Software versions must match. Update N1MM+."
and drops the station. So the version this program broadcasts is a setting —
Config ▸ Edit Networked-Computer Names — and it has to be the version of the
N1MM copies beside it. Help ▸ About in N1MM says which. A station that
broadcasts something else is kept in the list and the network status window
names it, because that is the one fault where everything looks connected and
nothing arrives.
Where a station is goes out once a second when it has changed, rather than from
each of the dozen places it can change from. In a multi-single entry that is
what the other operators watch.
**The ten-minute rule.** `BandChangeRules` counts band changes and the stay on a
band, and the entry window shows the countdown. What was missing was the rule
itself: only a user-defined contest carried one, so every built-in contest
allowed anything. `BandChangeRules.ForCategory` now gives a multi-operator entry
with one or two transmitters a ten-minute stay, which is N1MM's fallback for
every contest that does not name a number of its own, and a contest that caps
the changes per hour overrides `Contest.BandChangesFor`. N1MM's per-contest table
is not repeated: it is a few hundred cases in a decompiled hash switch, and the
contests this station enters are the ones worth reading out of it one at a time.
What the link does not do yet: N1MM's resync, where a station that has been
away asks another for the contacts it missed, and the log check that compares
two stations' logs row by row. Both are message types this program can already
frame; neither is written. There is also no guard against two stations taking
the same station number.
**Voice keying.** `MessageSender` was written to cover a voice keyer playing a
recording, and nothing implements it. Each operator's recordings folder is
stored with the rest of his settings and waits on the same thing. No DVK support either, so the second radio