Commit Graph

407 Commits

Author SHA1 Message Date
thatsatechnique
0c3ccac21c feat(ook): add timing presets, RSSI, bit-order suggest, pattern filter, TSCM link
- Timing presets: five quick-fill buttons (300/600, 300/900, 400/800, 500/1500, 500 MC)
  that populate all six pulse-timing fields at once — maps to CTF flag timing profiles
- RSSI per frame: add -M level to rtl_433 command; parse snr/rssi/level from JSON;
  display dB SNR inline with each frame; include rssi_db column in CSV export
- Auto bit-order suggest: "Suggest" button counts printable chars across all stored
  frames for MSB vs LSB, selects the winner, shows count — no decoder restart needed
- Pattern filter: live hex/ASCII filter input above the frame log; hides non-matching
  frames and highlights matches in green; respects current bit order
- TSCM integration: "Decode (OOK)" button in RF signal device details panel switches
  to OOK mode and pre-fills frequency — frontend-only, no backend changes needed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 14:28:49 -08:00
thatsatechnique
4c282bb055 feat: add Generic OOK Signal Decoder module
New 'OOK Decoder' mode for capturing and decoding arbitrary OOK/ASK
signals using rtl_433's flex decoder with fully configurable pulse
timing. Covers PWM, PPM, and Manchester encoding schemes.

Backend (utils/ook.py, routes/ook.py):
- Configurable modulation: OOK_PWM, OOK_PPM, OOK_MC_ZEROBIT
- Full rtl_433 flex spec builder with user-supplied pulse timings
- Bit-inversion fallback for transmitters with swapped short/long mapping
- Optional frame deduplication for repeated transmissions
- SSE streaming via /ook/stream

Frontend (static/js/modes/ook.js, templates/partials/modes/ook.html):
- Live MSB/LSB bit-order toggle — re-renders all stored frames instantly
  without restarting the decoder
- Full-detail frame display: timestamp, bit count, hex, dotted ASCII
- Modulation selector buttons with encoding hint text
- Full timing grid: short, long, gap/reset, tolerance, min bits
- CSV export of captured frames
- Global SDR device panel injection (device, SDR type, rtl_tcp, bias-T)

Integration (app.py, routes/__init__.py, templates/):
- Globals: ook_process, ook_queue, ook_lock
- Registered blueprint, nav entries (desktop + mobile), welcome card
- ookOutputPanel in visuals area with bit-order toolbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 14:28:49 -08:00
Smittix
fef54e5276 Merge pull request #175 from thatsatechnique/fix/pager-display-classification
fix: improve pager message display and mute visibility
2026-03-04 18:00:33 +00:00
Smittix
8d91c200a5 fix: HackRF users get misleading RTL-SDR error in rtlamr/sstv/weather-sat modes
Several modes didn't pass sdr_type to claim_sdr_device(), defaulting to
'rtlsdr' and triggering an rtl_test USB probe that fails for HackRF with
a confusing "check that the RTL-SDR is connected" message.

- Add sdr_type to frontend start requests for rtlamr, weather-sat, sstv-general
- Read sdr_type in backend routes and pass to claim/release_sdr_device()
- Add early guard returning clear "not yet supported" error for non-RTL-SDR
  hardware in modes that are hardcoded to RTL-SDR tools
- Make probe_rtlsdr_device error message device-type-agnostic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 07:52:13 +00:00
ribs
3de5e68e68 fix: improve pager message display and encryption classification
Three issues caused POCSAG messages to be incorrectly hidden or
misclassified in the Device Intelligence panel:

1. detectEncryption used a narrow character class ([a-zA-Z0-9\s.,!?-])
   to measure "printable ratio". Messages containing common printable
   ASCII characters like : = / + @ fell below the 0.8 threshold and
   returned null ("Unknown") instead of false ("Plaintext"). Simplified
   to check all printable ASCII (\x20-\x7E) which correctly classifies
   base64, structured data, and punctuation-heavy content.

2. The default hideToneOnly filter was true, hiding all address-only
   (Tone) pager messages. When RF conditions cause multimon-ng to decode
   the address but not the message content, the resulting Tone card was
   silently filtered. Changed default to false so users see all traffic
   and can opt-in to filtering.

3. The multimon-ng output parser only recognized "Alpha" and "Numeric"
   content type labels. Added a catch-all pattern to capture any
   additional content type labels that future multimon-ng versions or
   forks might emit, rather than dropping them to raw output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:05:01 -08:00
Smittix
325dafacbc fix: improve startup error reporting with full stderr logging and dependency pre-check
Radiosonde route now runs a quick import check before launching the full
subprocess, catching missing Python dependencies immediately with a clear
message instead of a truncated traceback. Error messages are context-aware:
import errors suggest re-running setup.sh rather than checking SDR connections.

Increased stderr truncation limit from 200 to 500 chars and added full stderr
logging via logger.error() across all affected routes (radiosonde, ais, aprs,
acars, vdl2) for easier debugging.

Closes #173

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:46:14 +00:00
Smittix
2f5f429e83 fix: airband start crash when device selector not yet populated
When the /devices fetch hasn't completed or fails, parseInt on an empty
select returns NaN which JSON-serializes to null. The backend then calls
int(None) and raises TypeError. Fix both layers: frontend falls back to
0 on NaN, backend uses `or` defaults so null values don't bypass the
fallback.

Also adds a short TTL cache to detect_all_devices() so multiple
concurrent callers on the same page load don't each spawn blocking
subprocess probes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 18:56:38 +00:00
Smittix
f07ec23da9 feat: add space weather image prefetch and stable cache-busting
Backend: Add /prefetch-images endpoint that warms the image cache in
parallel using a thread pool, skipping already-cached images.

Frontend: Trigger prefetch on mode init so images load instantly.
Replace per-request Date.now() cache-bust with a 5-minute rotating
key to allow browser caching aligned with backend max-age.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:21:55 +00:00
Smittix
4b64862eb4 fix: release SDR device when switching modes across pages
When navigating from another mode (e.g. pager) to the ADS-B dashboard,
the old process could still hold the USB device. Two fixes:

1. routes/adsb.py: If dump1090 starts but SBS port never comes up,
   kill the process and return a DEVICE_BUSY error instead of silently
   claiming success with no data.

2. templates/adsb_dashboard.html: Pre-flight conflict check in
   toggleTracking() queries /devices/status and auto-stops any
   conflicting mode before starting ADS-B, with a 1.5s USB release
   delay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:21:30 +00:00
Smittix
7311dd10ab feat: add Meteor Scatter mode for VHF beacon ping detection
Full-stack meteor scatter monitoring mode that captures IQ data from
an RTL-SDR, computes FFT waterfall frames via WebSocket, and runs a
real-time detection engine to identify transient VHF reflections from
meteor ionization trails (e.g. GRAVES radar at 143.050 MHz).

Backend: MeteorDetector with EMA noise floor, SNR threshold state
machine (IDLE/DETECTING/ACTIVE/COOLDOWN), hysteresis, and CSV/JSON
export. WebSocket at /ws/meteor for binary waterfall frames, SSE at
/meteor/stream for detection events and stats.

Frontend: spectrum + waterfall + timeline canvases, event table with
SNR/duration/confidence, stats strip, turbo colour LUT. Uses shared
SDR device selection panel with conflict tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:38:15 +00:00
Smittix
e2e92b6b38 fix: cache ISS position/schedule and parallelize SSTV init API calls
SSTV mode was slow to populate next-pass countdown and ISS location map
due to uncached skyfield computation and sequential JS API calls.

- Cache ISS position (10s TTL) and schedule (15min TTL, keyed by rounded lat/lon)
- Cache skyfield timescale object (expensive to create on every request)
- Reduce external API timeouts from 5s to 3s
- Fire checkStatus, loadImages, loadIssSchedule, updateIssPosition in parallel via Promise.all

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 18:05:57 +00:00
Smittix
5534493bd1 fix: parallelize space weather API fetches to reduce cold-cache latency
The /space-weather/data endpoint made 13 sequential HTTP requests, each
with a 15s timeout, causing 30-195s load times on cold cache. Now uses
ThreadPoolExecutor to fetch all sources concurrently, reducing worst-case
latency to ~15s (single slowest request).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:51:31 +00:00
Smittix
e89a0ef486 fix: pass config file path (not directory) to radiosonde_auto_rx -c flag
Reverts the incorrect assumption from f8e5d61 that -c expects a
directory. The auto_rx -c flag expects the full path to station.cfg.
Passing the directory caused "Config file ... does not exist!" on start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:35:25 +00:00
Smittix
bcf447fe4e fix: prevent root-owned data files from breaking radiosonde start
Running via sudo creates data/radiosonde/ as root. On next run the
config write fails with an unhandled OSError, Flask returns an HTML 500,
and the frontend shows a cryptic JSON parse error.

Three-layer fix:
- start.sh: pre-create known data dirs before chown, add certs/ to the
  list, export INTERCEPT_SUDO_UID/GID for runtime use
- generate_station_cfg: catch OSError with actionable message, chown
  newly created files to the real user via _fix_data_ownership()
- start_radiosonde: wrap config generation in try/except so it returns
  JSON instead of letting Flask emit an HTML error page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:27:20 +00:00
Smittix
f8e5d61fa9 fix: pass config directory (not file path) to radiosonde_auto_rx -c flag
The -c flag expects a directory containing station.cfg, but we were
passing the full file path, so auto_rx could never find its config.
Also fix sonde_type priority to prefer subtype over type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:12:30 +00:00
Smittix
8379f42ec3 fix: close leaked file descriptors on mode switch (#169)
SSE EventSource connections for AIS, ACARS, VDL2, and radiosonde were
not closed when switching modes, causing fd exhaustion after repeated
switches. Also fixes socket leaks on exception paths in AIS/ADS-B
stream parsers, closes subprocess pipes in safe_terminate/cleanup, and
caches skyfield timescale at module level to avoid per-request fd churn.

Closes #169

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:38:21 +00:00
Smittix
ff9961b846 fix: add missing METEOR-M2-4 TLE data for pass predictions
METEOR-M2-4 was defined as an active weather satellite but had no
orbital data, so pass predictions always returned empty. Added TLE
entry and CelesTrak name mapping for automatic refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:45:20 +00:00
Smittix
910b69594d Merge pull request #145 from mitchross/main
All review issues addressed. Merging with fixup commit for XSS escaping, import cleanup, VDL2 click behavior, frequency defaults, and misc fixes.
2026-03-01 20:42:50 +00:00
Smittix
a154601e86 fix: address PR #145 review issues
- Escape ac.icao, callsign, typeCode with escapeHtml() in aircraft card (XSS)
- Add linking comments between duplicated IATA_TO_ICAO mappings
- VDL2 sidebar: single-click selects aircraft, double-click opens modal
- Remove stale ICAOs from acarsAircraftIcaos in cleanupOldAircraft()
- Add null guard to drawPolarPlot() in weather-satellite.js
- Move deferred imports (translate_message, get_flight_correlator) to module level
- Check all frequency checkboxes by default on initial load
- Remove extra blank lines and uncertain MC/MCO airline code entry
- Add TODO comments linking duplicated renderAcarsCard implementations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:42:14 +00:00
Smittix
bdeb32e723 feat: add rtl_tcp remote SDR support to weather satellite decoder
Extends the rtl_tcp support (added in c1339b6 for APRS, Morse, DSC) to
the weather satellite mode. When a remote SDR host is provided, SatDump
uses --source rtltcp instead of --source rtlsdr, local device claiming
is skipped, and the frontend sends rtl_tcp params via getRemoteSDRConfig().

Closes #166

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:55:04 +00:00
Mitch Ross
b5c3d71247 Merge branch 'smittix:main' into main 2026-02-28 16:30:56 -05:00
Smittix
c1339b6c65 feat: add rtl_tcp remote SDR support to aprs, morse, and dsc routes
Closes #164. Only pager and sensor routes supported rtl_tcp connections.
Now aprs, morse, and dsc routes follow the same pattern: extract
rtl_tcp_host/port from the request, skip local device claiming for
remote connections, and use SDRFactory.create_network_device(). DSC also
refactored from manual rtl_fm command building to use SDRFactory's
builder abstraction. Frontend wired up for all three modes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:21:28 +00:00
Smittix
10e4804e0a fix: bluetooth no results, audio waveform leak, and mode switch cleanup
- Change 'already_running' to 'already_scanning' status in bluetooth_v2
  so frontend recognizes the response and connects the SSE stream
- Hide pagerScopePanel and sensorScopePanel in switchMode() to prevent
  audio waveform bars leaking into other modes
- Clear devices Map, pendingDeviceIds Set, and UI in BluetoothMode.destroy()
  to prevent memory accumulation on repeated mode switches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:16:55 +00:00
Smittix
7d1fcfe895 feat: add station location and distance tracking to radiosonde mode
- Pass observer location and gpsd status to radiosonde_auto_rx station config
- Add station marker on radiosonde map with GPS live position updates
- Display distance from station to each balloon in cards and popups
- Update aircraft database

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 19:49:58 +00:00
mitchross
29873fb3c0 Merge upstream/main and resolve acars, vdl2, dashboard conflicts
Resolved conflicts:
- routes/acars.py: keep /messages and /clear endpoints for history reload
- routes/vdl2.py: keep /messages and /clear endpoints for history reload
- templates/adsb_dashboard.html: keep removal of hardcoded device-1
  defaults for ACARS/VDL2 selectors (users pick their own device)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:47:57 -05:00
ribs
377519fd95 feat: add OOK/AM envelope detection mode to Morse decoder
Re-implements envelope detection on top of the rewritten Morse decoder.
Addresses PR #160 review feedback:
- Rebase: rebuilt on current upstream/main (lifecycle state machine)
- Gap thresholds: 2.0/5.0 for envelope only; goertzel keeps 2.6/6.0
- Frequency validation: max_mhz=1766 for envelope, 30 for goertzel
- Tests: EnvelopeDetector unit tests + envelope-mode decoder test
- Envelope uses direct magnitude threshold (no SNR/noise ref)
- Goertzel path completely unchanged

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:35:56 -08:00
Smittix
824514d922 fix: use complete station.cfg with all required fields for auto_rx v1.8+
Auto_rx reads many config keys without defaults and crashes if they're
missing, even for disabled features like email. Include every section
and key from the example config to prevent missing-key errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:31:41 +00:00
Smittix
79a0dae04b fix: rewrite radiosonde station.cfg to match auto_rx v1.8+ format
The config format changed significantly: SDR settings moved to [sdr_1],
[positioning] became [location], and many sections are now required.
Also enable payload_summary UDP output so telemetry reaches our listener.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:29:53 +00:00
Smittix
e176438934 fix: radiosonde config path and dependency detection
- Pass config file path (not directory) to auto_rx -c flag
- Use absolute paths in generated station.cfg since auto_rx runs
  with cwd set to its install directory
- Teach dependency checker about auto_rx.py at /opt install path
  so the "missing dependency" banner no longer appears

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:27:16 +00:00
Smittix
db2f3fc8e5 fix: use sys.executable for radiosonde subprocess to find venv packages
The subprocess was launched with bare 'python' which on Debian doesn't
exist (python3 only) and wouldn't have access to the venv-installed
radiosonde dependencies anyway. Using sys.executable ensures the same
interpreter (with all installed packages) is used.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:17:19 +00:00
Smittix
952736c127 fix: set cwd for radiosonde subprocess so autorx package imports resolve
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:15:50 +00:00
Smittix
997dac3b9f fix: ADS-B device release leak and startup performance
Move adsb_active_device/sdr_type assignment to immediately after
claim_sdr_device so stop_adsb() can always release the device, even
during startup. Sync sdr_type_str after SDRType fallback to prevent
claim/release key mismatch. Clear active device on all error paths.

Replace blind 3s sleep for dump1090 readiness with port-polling loop
(100ms intervals, 3s max). Replace subprocess.run() in rtl_test probe
with Popen + select-based early termination on success/error detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:13:44 +00:00
Smittix
5b06c57565 feat: add radiosonde weather balloon tracking mode
Integrate radiosonde_auto_rx for automatic weather balloon detection and
decoding on 400-406 MHz. Includes UDP telemetry parsing, Leaflet map with
altitude-colored markers and trajectory tracks, SDR device registry
integration, setup script installation, and Docker support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:46:33 +00:00
Smittix
5aa68a49c6 fix: SDR device registry collision with multiple SDR types
The registry used plain int keys (device index), so HackRF at index 0
and RTL-SDR at index 0 would collide. Changed to composite string keys
("sdr_type:index") so each SDR type+index pair is tracked independently.
Updated all route callers, frontend device selectors, and session restore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:06:41 +00:00
Smittix
0d13638d70 fix: APRS 15-minute startup delay caused by pipe buffering
Switch direwolf subprocess output from PIPE to PTY (pseudo-terminal),
forcing line-buffered output so packets arrive immediately instead of
waiting for a 4-8KB pipe buffer to fill. Matches the proven pattern
used by pager mode.

Also enhances direwolf config with FIX_BITS error correction and
disables unused AGWPE/KISS server ports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:43:54 +00:00
Smittix
4b31474080 fix: location fallback to constants, compact card sizing
- Add third location fallback to utils/constants (London 51.5074/-0.1278)
  so location always resolves even without GPS or env vars configured
- Remove min-height from sys-card to eliminate wasted space
- Switch System Info to vertical key-value layout filling the card
- Clean up OS string (strip glibc suffix), use locale date for boot time
- Bump info grid font size from 11px to 12px for readability

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:55:36 +00:00
Smittix
f72b43c6bf fix: use GPS utility for location, compact dashboard layout
Replace broken app.gps_state lookup with utils.gps.get_current_position()
and return GPS metadata (fix quality, satellites, accuracy). Shrink location
card to single-column with 200px globe, move System Info into row 2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:51:26 +00:00
Smittix
0a90010c1f feat: enhance System Health dashboard with rich telemetry and visualizations
Add SVG arc gauge, per-core CPU bars, temperature sparkline, network
interface monitoring with bandwidth deltas, disk I/O rates, 3D globe
with observer location, weather overlay, battery/fan/throttle support,
and process grid layout. New /system/location and /system/weather endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:42:45 +00:00
mitchross
81a8f24e27 Merge upstream/main and resolve weather-satellite.js conflict
Keep allPasses assignment for satellite filtering support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:37:09 -05:00
Smittix
1cfeb193c7 feat: add System Health monitoring mode
Real-time dashboard for host metrics (CPU, memory, disk, temperatures),
active decoder process status, and SDR device enumeration via SSE streaming.
Auto-connects when entering the mode with graceful psutil fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:21:52 +00:00
Smittix
69b402f872 fix: prevent APRS stream crash on invalid UTF-8 bytes from decoder
Switch decoder subprocess from text mode to binary mode and decode
each line with errors='replace' so corrupted radio bytes (e.g. 0xf7)
are substituted instead of raising UnicodeDecodeError after long runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:02:07 +00:00
Smittix
33a360b483 morse: fix startup race and stuck noise floor in Goertzel decoder
Filter decoder-thread 'stopped' status events that race with the route
lifecycle, causing the frontend to drop back to idle on first start.
Pull noise floor upward using adjacent-frequency Goertzel reference when
warmup calibration runs before AGC converges, preventing permanent
tone-on with zero character decodes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:05:25 +00:00
Smittix
2e1b9b27be morse: replace multimon-ng with custom Goertzel decoder for live CW
The multimon-ng MORSE_CW decoder never reliably decoded characters.
Switch live decode to use the existing morse_decoder_thread() which
wraps MorseDecoder with Goertzel tone detection, adaptive thresholds,
and proper timing estimation — eliminating multimon-ng, PTY plumbing,
and the relay thread from the CW pipeline entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:47:51 +00:00
Smittix
d6fe1123b4 morse: tune usb capture by cw tone offset 2026-02-26 18:16:43 +00:00
Smittix
24d1777e63 morse: add multimon decoder alias fallback and clear stale idle scope 2026-02-26 17:43:23 +00:00
Smittix
794dd693cf morse: auto-fallback to alternate SDR device on no-PCM startup 2026-02-26 17:38:22 +00:00
Smittix
0cadf07985 morse: stop forcing rtl_fm squelch flag 2026-02-26 17:31:25 +00:00
Smittix
bb263ce1b0 morse: remove select()-based pipe polling for capture/output 2026-02-26 17:29:41 +00:00
Smittix
23d592af1d morse: align rtl_fm streaming path with pager backend 2026-02-26 17:25:33 +00:00
Smittix
ababa63856 morse: switch live decode to rtl_fm + multimon backend 2026-02-26 17:20:20 +00:00