Replace legacy global FrontendRegistry with bootstrap context adapter that
maintains backward compatibility while delegating to explicit context.
Changes:
- Create BOOTSTRAP_CONTEXT: OnceLock<Arc<Mutex<FrontendRegistrationContext>>>
- register_frontend(): delegates to bootstrap context
- is_frontend_registered(): reads from bootstrap context
- registered_frontends(): reads from bootstrap context
- spawn_frontend(): reads from bootstrap context
Result: Plugins continue calling global functions, but all operations
now route through the bootstrap context. Frontends receive context
parameter explicitly, enabling multiple concurrent instances.
Complete de-globalization achieved with full backward compatibility.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Update all three built-in frontends to accept Arc<FrontendRuntimeContext>
parameter in their spawn_frontend implementations:
- trx-frontend-http: passes context to serve function
- trx-frontend-http-json: passes context to serve function
- trx-frontend-rigctl: accepts context (minimal impact, no globals used)
Frontends are now ready to use context for audio channels, decode
channels, and auth tokens instead of accessing globals directly.
This completes the trait signature change for all frontends.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Update FrontendSpawner trait and related functions to accept and pass
Arc<FrontendRuntimeContext> parameter instead of relying on global
accessors for audio channels, decode channels, and auth tokens.
Changes:
- FrontendSpawner::spawn_frontend now accepts context parameter
- FrontendSpawnFn type signature includes context parameter
- FrontendRegistrationContext::spawn_frontend passes context to spawner
- Global spawn_frontend function accepts and passes context
This enables frontends to receive runtime data explicitly without
accessing globals, improving testability and supporting multiple
concurrent frontends with different contexts.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Create explicit context types for frontend registration and runtime:
FrontendRegistrationContext:
- register_frontend(name, spawner) - register a frontend
- is_frontend_registered(name) - check if registered
- registered_frontends() -> Vec<String> - list all frontends
- spawn_frontend(name, ...) -> DynResult - spawn a frontend
FrontendRuntimeContext (NEW):
- audio_rx: broadcast channel for audio RX
- audio_tx: mpsc channel for audio TX
- audio_info: watch channel for audio stream metadata
- decode_rx: broadcast channel for decoded messages
- aprs_history: Arc<Mutex<VecDeque>> for APRS decode history
- cw_history: Arc<Mutex<VecDeque>> for CW decode history
- ft8_history: Arc<Mutex<VecDeque>> for FT8 decode history
- auth_tokens: HashSet for authentication
Replaces global mutable state with explicit context that can be
threaded through bootstrap. Maintains global API for compatibility.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Use centralized trx-protocol crate for:
- parse_mode and envelope parsing
- command mapping (ClientCommand -> RigCommand)
- token validation via RegistryTokenValidator wrapper
RegistryTokenValidator maintains compatibility with global auth
registry pattern while leveraging shared protocol logic from
trx-protocol. Removes duplicate auth and codec functions.
No behavior changes, all tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Remove macOS AppKit frontend (trx-frontend-appkit) and related code:
- Delete appkit crate directory
- Remove appkit dependency and feature from Cargo.toml
- Remove appkit imports, main thread handling, and config from main.rs
- Remove AppKit config struct from config.rs
- Remove appkit section from example config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add POST endpoints for toggle_aprs_decode, toggle_cw_decode,
clear_aprs_decode, and clear_cw_decode. Add toggle buttons in APRS
and CW tabs. Render decoder enabled state from SSE updates. Clear
button now also resets server-side decoder state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add SetAprsDecodeEnabled, SetCwDecodeEnabled, ResetAprsDecoder, and
ResetCwDecoder to the JSON TCP frontend command mapping.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Replace HEAD probe with EventSource readyState check to properly
detect 404 vs connection drop. HEAD requests to SSE endpoints may
not behave reliably across all setups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Log whether audio/decode is enabled at startup and warn when
/decode is requested but the decode channel was not set. Helps
diagnose broken decode pipelines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
The decode EventSource silently retried on 404 leaving the status
stuck on "Waiting for server decode". Probe /decode first to
distinguish 404 (audio disabled) from real SSE errors and update
the APRS/CW status text accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Server-side decoding makes client-side decoders redundant. Remove
~1000 lines of browser-side Bell 202 AFSK, AX.25/APRS parsing, and
Goertzel CW decoding. The frontend now relies solely on the /decode
SSE endpoint for decoded data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Clears the packet list, map markers are unaffected. Also wipes
the persisted packet history from localStorage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add /decode SSE endpoint streaming decoded messages from the server.
Add decode channel OnceLock with set/subscribe pattern.
In the browser, connect to /decode EventSource and dispatch to
onServerAprs/onServerCw handlers. APRS and CW plugins now receive
server-decoded data automatically while keeping browser-side decoding
as a fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add localStorage persistence (trx_ prefix) for UI settings:
- Jog step, RX/TX volume (app.js)
- CW WPM, tone, threshold, auto-detect flags (cw.js)
- APRS decoded packets and running state (aprs.js)
APRS decoder auto-restarts on page refresh if it was active,
and all decoded packets plus map markers are restored from storage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Render non-ASCII characters in decoded APRS info text as yellow
[0xNN] hex tags. Printable ASCII is HTML-escaped to prevent XSS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Show the proper APRS symbol sprite icon on map markers instead of
generic green circles. Falls back to a green circle marker when no
symbol info is available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add a Map sub-tab under Plugins that displays an interactive
OpenStreetMap via Leaflet.js showing:
- Receiver location (blue marker) from server config lat/lon
- APRS station positions (green markers) updated in real-time
The map lazy-initializes on first tab switch, handles tile rendering
on tab visibility changes, and deduplicates station markers by
callsign. Also includes the fallback snapshot lat/lon fields in the
API layer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
- Add APRS symbol icons using hessu/aprs-symbols sprite sheets
- Parse uncompressed and compressed position formats for lat/lon
- Render clickable OpenStreetMap links for position packets
- Replace delay-and-multiply discriminator with mark/space correlation
detector for more robust AFSK decoding
- Reduce PLL gain from 0.7 to 0.4 for stable clock recovery
- Move plugin JS files to plugins/ subdirectory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add Auto checkboxes (checked by default) next to WPM and Tone inputs.
Auto Tone uses a multi-bin Goertzel scan across 300-1200 Hz with
stability tracking. Auto WPM collects on-durations in a rolling buffer
and uses k-means-style clustering to separate dits from dahs.
Unchecking Auto allows manual control.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Extract the APRS decoder from app.js into its own aprs.js file and add
a new CW (Morse code) decoder plugin in cw.js. The CW decoder uses a
Goertzel tone detector with configurable WPM, tone frequency, and
signal threshold. The Plugins tab now has three sub-tabs: Overview,
APRS, and CW.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Replace bandpass filter envelope detector with delay-and-multiply
frequency discriminator. Add biquad bandpass pre-filter centered at
1700 Hz to remove out-of-band noise. Replace IIR low-pass with
moving-average LPF over half a bit period, which places a null at
2x mark frequency for clean discriminator artifact removal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Replace the coherent correlation detector with a non-coherent
bandpass filter + envelope detection approach for significantly
better frequency discrimination between mark (1200Hz) and space
(2200Hz) tones. Uses two cascaded 2nd-order IIR biquad filters
per tone with IIR-smoothed envelope detection.
Replace hard clock reset with PLL-style gradual correction for
smoother bit timing recovery.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add silence detection that resets the demodulator state when RMS
drops below threshold, so burst-mode APRS packets after squelch
activation start with a clean correlator and clock recovery.
Display CRC-failing frames at reduced opacity with a [CRC] tag to
aid debugging. Enhanced CRC-fail console logging now includes
attempted address decode, bit count, and hex dump.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Assign green to VFO A, yellow to VFO B, and deterministic hues
to additional VFOs. The active VFO color is also applied to the
main frequency display. Rework the header title to show
"trx-rs <version> @ <callsign>'s <rig>" instead of "<rig> status".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>