feat: Ultrabeam over USB, Paper QSL from the awards grid, per-role schemas
Ultrabeam on a serial port never worked, and three faults were stacked so
each hid the next:
- Stop() did not wait for the poll loop, so a stopped client kept the COM
port. Every later client then failed with "Serial port busy" — the
program holding it being OpsLog itself.
- startUltrabeam tore the old client down CONCURRENTLY with starting the
new one, and "Test connection" built a second client on a port already
ours. Harmless over TCP, fatal on a port with one owner.
- A silent serial port returns (0, nil) and bufio retries that a hundred
times: a 4 s timeout became ~7 minutes of a frozen poll loop logging
nothing.
The controller then answered at once. Confirmed on hardware: the USB cable
presents TWO COM ports, only the second reaches the controller, and only at
19200 baud — so the speed is pinned in code (an FTDI cable opens at any
speed, and a wrong one is indistinguishable from a dead controller) and the
port field says which one to pick. The first exchange after each connect is
hex-dumped, which separates silence from a wrong baud from a misread frame.
Databases now carry only the tables their role needs. Every target used to
get the whole migration set, so a shared MySQL logbook grew settings and
station_profiles tables nothing ever wrote to — an operator inspecting the
server could not tell which copy was authoritative. Statements are filtered
by role, unknown tables are kept in both (fail-safe), and existing databases
are cleaned once, dropping only EMPTY tables. Settings → Database gains a
Compact button, since SQLite frees pages inside the file and never shrinks it.
Also:
- Awards: the callsigns behind a cell open the QSL Manager on Paper QSL,
searched, ready for the card dates.
- The record button no longer goes missing after an update: whether manual
recording is possible is a per-profile question that was asked once, at
startup, before the profile was known.
- Alert rules and filter presets confirm that they were saved.
- Spot clicks on the radio panadapter carry the POTA park into F3.
- The build gate is re-checked wherever the active callsign can change; it
ran at startup alone, and a fresh install has no callsign then.
This commit is contained in:
@@ -3589,7 +3589,7 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
{isSerial ? (
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div className="space-y-1 col-span-2">
|
||||
<Label>{t('hw.motorCom')}</Label>
|
||||
<Label>{t('hw.motorCom')}{!isSteppir && <span className="ml-1.5 font-normal text-muted-foreground">{t('hw.motorComUb')}</span>}</Label>
|
||||
{/* A list AND a text field, which is why this is a Combobox and
|
||||
not the Select the other serial devices use: the port for a
|
||||
USB adapter that is currently unplugged does not appear in
|
||||
@@ -3613,12 +3613,19 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label>{t('hw.motorBaud')}</Label>
|
||||
<Select value={String(ultrabeam.baud || 9600)} onValueChange={(v) => setUltrabeam((s) => ({ ...s, baud: parseInt(v, 10) || 9600 }))}>
|
||||
<SelectTrigger className="h-9"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{[1200, 4800, 9600, 19200].map((b) => <SelectItem key={b} value={String(b)}>{b}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{/* The Ultrabeam answers on 19200 and on nothing else, so there is
|
||||
no choice to offer — an FTDI cable opens at any speed, and a
|
||||
wrong one is indistinguishable from a dead controller. */}
|
||||
{!isSteppir ? (
|
||||
<Input className="h-9 font-mono" value="19200" readOnly disabled />
|
||||
) : (
|
||||
<Select value={String(ultrabeam.baud || 9600)} onValueChange={(s2) => setUltrabeam((s) => ({ ...s, baud: parseInt(s2, 10) || 9600 }))}>
|
||||
<SelectTrigger className="h-9"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200].map((b) => <SelectItem key={b} value={String(b)}>{b}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user