Commit Graph

184 Commits

Author SHA1 Message Date
James Smith f7d8af493a fix(meshcore): make strip and body direct children of visuals container
Remove the intermediate #meshcoreMode wrapper div that was breaking the
flex height chain. Strip and body are now direct children of
#meshcoreVisuals (matching the Meshtastic pattern), so flex: 1 propagates
correctly and the content fills the full panel height.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 12:16:02 +01:00
James Smith 7940728b30 fix(meshcore): restyle to strip layout, fix map tiles
Replaced inner-sidebar layout (which collided with the generic app
sidebar) with a Meshtastic-style top connection strip + body row.
Contacts/nodes panel sits left of the tabbed content area, matching
the established pattern. Map now uses Settings.createTileLayer() with
a dark CartoDB fallback instead of plain OSM light tiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:23:31 +01:00
James Smith 52ab1b60a3 fix(meshcore): move UI into visuals container, fix layout
meshcoreMode partial was inside the generic .sidebar which gets hidden
when meshcore mode is active. Moved the include into meshcoreVisuals
(inside the output panel) — matching the same pattern as Meshtastic.
Also overrides mesh-visuals-container's column/padding defaults so the
meshcore sidebar+main row layout renders correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:15:14 +01:00
James Smith 28a779b91b fix(meshcore): add to nav and fix welcome card styling
Meshcore was missing from both the desktop Wireless dropdown and mobile
nav. The welcome card also used non-standard div/emoji markup instead of
the SVG icon pattern used by every other mode, causing wrong font and
colour rendering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:02:45 +01:00
James Smith 410225d54d fix(drone): conform to established SPA patterns throughout
- Device population: move refreshDroneDevices() inline to index.html
  (same pattern as refreshTscmDevices) and call it from switchMode
  alongside DroneMode.init(); remove _refreshDevices/populateSelect
  from drone.js which was never guaranteed to run before lazy-load
  completed, causing selects to stay on "Loading…" permanently

- IIFE pattern: change from named IIFE + window.DroneMode assignment
  to var DroneMode = (function(){...return{...}})() matching OOK/
  SpyStations convention

- Init guard: add _initialized flag (OOK state.initialized pattern);
  re-entry after destroy() re-registers map/SSE cleanly without
  duplicating click listeners on every mode switch

- Lifecycle: destroy() resets _initialized = false so map and SSE
  are correctly rebuilt on re-entry

- Stop phase: add isDroneRunning tracking variable in index.html;
  _setRunningUI() syncs it; switchMode stop phase now POSTs
  /drone/stop when leaving drone mode while active, matching TSCM

- /drone/devices: add monitor_capable field to WiFi interfaces,
  add running_as_root and warnings array to response (mirrors
  /tscm/devices shape); add os import; show privilege warning div
  in drone.html when not running as root

- drone.html: remove for= attribute from SDR label (plain <label>
  inside .form-group matches TSCM convention); add droneDeviceWarnings
  div for privilege warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:33:38 +01:00
James Smith 4ba8a40af9 feat(drone): replace freeform inputs with populated device selects
Add /drone/devices endpoint that enumerates available WiFi interfaces
(via iw/iwconfig) and RTL-SDR devices (via SDRFactory.detect_devices),
matching the pattern used by TSCM.

Sidebar WiFi interface and RTL-SDR inputs are now <select> elements
populated on init() from /drone/devices, consistent with how other
modes expose hardware selection. HackRF checkbox remains as a toggle
since it's a binary capability rather than an enumerated device list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:25:21 +01:00
James Smith 6523686aca feat(drone): add main visuals panel with map and contact list
- Sidebar inputs now use form-group/label pattern matching other modes
- Move map and contact list out of sidebar into a dedicated droneVisuals
  main panel (same pattern as tscm, spystations, etc.)
- droneVisuals: stats header (contacts / non-compliant / high-risk),
  left contact card panel, and full-height Leaflet map on the right
- Wire droneVisuals into switchMode display toggle and modesWithVisuals
  so the shared signal-feed output is hidden when drone mode is active
- Add invalidateMap() to force Leaflet to recalculate after the
  container becomes visible
- Stats now update both sidebar counts and main panel values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:16:54 +01:00
James Smith 2475e5dd5a fix(drone): show sidebar panel and expose SDR config options
Remove inline style="display: none;" that was preventing the droneMode
panel from becoming visible when the active class was toggled — inline
styles override CSS class rules without !important. Add RTL-SDR device
index and HackRF toggle inputs that the backend already accepted but
were never surfaced in the UI; wire them through to the /drone/start
POST body.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:07:42 +01:00
James Smith 71011dd67c feat(meshcore): add HTML partial (sidebar, tabs, modals)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 12:58:29 +01:00
James Smith 62e53c5dfa fix(adsb): fix aircraft photo display and add Drone Intelligence docs
- Fix stale DOM refs in fetchAircraftPhoto: elements were captured before
  await fetch(), but showAircraftDetails rebuilds innerHTML on every RAF
  update, leaving the async path writing to detached nodes. Now re-queries
  the DOM after await, and the cache (synchronous) path queries inline so
  refs are always fresh.
- Add thumbnail fallback in aircraft_photo route: fall back to thumbnail
  when thumbnail_large.src is absent rather than returning null.
- Add Drone Intelligence to nav, help modal, cheat sheets, README, and docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 09:24:30 +01:00
James Smith 333c5cf8d3 feat(drone): merge Drone Intelligence module
Multi-vector UAV detection mode: Remote ID (WiFi/BLE ASTM F3411),
RTL-SDR 433/868MHz control-link detection, HackRF 2.4/5.8GHz wideband.

Workers feed a shared observation queue; DroneCorrelator merges into
DroneContact objects with TTL store, risk scoring, and SSE streaming.
Frontend: two-panel sidebar + Leaflet map with contact cards and trails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 08:36:27 +01:00
James Smith 8632e31c01 fix(drone): resolve critical pipeline, frontend, and input validation issues
Data pipeline (critical): scanners/detectors now write to a separate _obs_queue;
a relay thread reads observations and calls correlator.process(), which emits
processed DroneContact dicts to drone_queue for SSE. Without this the SSE stream
received raw unserializable dataclass objects causing JSON errors.

Frontend (critical):
- Add droneContactList container to drone.html so contact cards render
- Add droneMap container and initialize Leaflet in drone.js init()
- Define dsc-distress-pulse keyframes in drone.css (was referenced but missing)
- Fix SSE reconnect: null _sse before setTimeout to prevent _connectSSE no-op loop

Other fixes:
- Validate rtl_sdr_index with validate_device_index(), return 400 on bad input
- Move _ensure_workers() inside _drone_lock to prevent double-initialization race
- Add double-call guard to RemoteIDScanner.start()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:47:12 +01:00
James Smith e059be2d84 feat(drone): add HTML partial, CSS, and index.html mode panel wiring
- Create templates/partials/modes/drone.html with drone mode sidebar panel
- Create static/css/modes/drone.css with scoped drone UI styles
- Wire drone mode into index.html: CSS map entry, partial include, classList toggle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 17:41:02 +01:00
Mitch Ross 4a149525bd Merge main into misc-fixes and address PR #202 review
Sync with upstream main and fix required items from review:

- updateTimelineLabels() now uses InterceptTime API (getTimezone/getIANA)
  instead of the stale selectedTimezone/TZ_MAP globals that were removed
  during the earlier InterceptTime refactor — fixes ReferenceError on TZ
  change and pass refresh.

- Remove profiles: [basic] from the intercept service in
  docker-compose.yml so bare `docker compose up -d` still starts the
  main service. Profile-gated services (intercept-history, adsb_db)
  stay as-is.
2026-04-24 16:34:09 -04:00
James Smith 3693b02cb9 refactor(radiosonde): use MapUtils.init + Settings tile layer on sonde map
Replace hardcoded L.map() + CartoCD dark tile layer with MapUtils.init()
and add tactical overlays. Adds test verifying the cartocdn URL is gone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 23:27:36 +01:00
James Smith e4df3eaecb feat(maps): add Stadia dark + tactical tile providers with API key support
- Add offline.stadia_key to OFFLINE_DEFAULTS in routes/offline.py
- Add stadia_dark and tactical tile providers to Settings.tileProviders
- Update getTileConfig() to inject Stadia API key or fall back to CartoDB dark
- Add setStadiaKey() method for saving and applying the API key
- Show/hide Stadia key row in setTileProvider() and _updateUI()
- Add Stadia options to tile provider select in settings modal
- Add Stadia API key input row to settings modal
- Add TDD tests for stadia_key backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 22:04:07 +01:00
James Smith 0210791c69 feat(export): AIS UDP NMEA forward and JSON export endpoints for AIS/ADS-B
AIS:
- New optional NMEA UDP forwarding via AIS-catcher's -u flag, configurable
  from the AIS sidebar (host + port). Lets OpenCPN and other NMEA tools
  receive live vessel data directly. All SDR builders updated.
- New GET /ais/vessels endpoint — clean JSON snapshot of tracked vessels
  for REST integration

ADS-B:
- New GET /adsb/aircraft endpoint — JSON snapshot of all tracked aircraft,
  with optional ?icao= and ?military=true filters. Response includes a
  reminder that port 30003 (SBS) is already available for tools like
  Virtual Radar Server and OpenCPN's AIS/target plugin.

Closes #90
2026-04-05 16:20:10 +01:00
James Smith 592e97719b feat(gain): normalize gain controls across modes
- Pager and sensor gain inputs changed from unvalidated text fields to
  number inputs with min/max/step constraints
- ADS-B dashboard now exposes a gain input in the tracking strip;
  previously gain was hardcoded to 40 dB with no user control
- validate_gain() ceiling raised from 50 to 102 dB to support HackRF
  (LNA 40 + VGA 62 = 102 dB combined) and LimeSDR (73 dB)
- sdrCapabilities gain_max values corrected: HackRF 62→102, Airspy 21→45
- onSDRTypeChanged() now propagates gain_max to all mode gain inputs so
  HTML constraints match the selected SDR's actual range

Closes #162
2026-04-05 16:02:03 +01:00
James Smith ea80b5ebc3 feat(tscm): add custom frequency range option to RF sweep
Adds a "Custom Range" sweep type that lets users specify start/end MHz
instead of using a fixed preset. Useful in dense RF environments where
a full or standard sweep returns too many signals and causes slowdown.

UI shows start/end MHz inputs when "Custom Range" is selected. Range is
validated (0 < start < end ≤ 6000 MHz) before the sweep starts.
Backend threads the ranges through to _scan_rf_signals(), which already
supports arbitrary frequency bands.

Closes #172
2026-04-05 15:46:01 +01:00
James Smith 6ea34a4c60 fix(weather-sat): lower default gain to 30 dB to prevent ADC saturation
Strong passes at 40 dB (the previous default) cause RTL-SDR ADC clipping,
producing a distorted IQ stream that SatDump cannot lock onto. 30 dB is
a safer starting point that still captures weak passes cleanly.

Also adds a UI hint below the gain control explaining the saturation issue.

Closes #185
2026-04-05 14:20:06 +01:00
mitchross f4672cf0c7 Fix global timezone on ADS-B dashboard and harden VDL2 correlation
Timezone fixes:
- Add utils.js (InterceptTime) to adsb_dashboard.html — was completely
  missing, causing all times to fall back to UTC regardless of setting
- Register onChange listener in nav.html so clock updates instantly
  when timezone/format is changed in Settings
- Initialize timezone/format dropdowns on ADS-B dashboard page load
- Browser-verified: ET/12h ↔ UTC/24h switches instantly on ADS-B page

VDL2 correlation fix:
- Force ICAO hex to uppercase when promoting from VDL2 src.addr (dumpvdl2
  may output lowercase, ADS-B stores uppercase — case mismatch prevented
  correlator from matching)
- Move ICAO/addr promotion before ACARS field extraction so even
  non-ACARS VDL2 frames (XID, connection mgmt) get correlated

Auth:
- Add INTERCEPT_DISABLE_AUTH env var to skip login for local/dev use
- Configurable via docker-compose.yml environment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 00:05:49 -04:00
mitchross 7d704c9d42 Fix ACARS message display and add missing decoded data types
- Use global InterceptTime for all ACARS timestamps (respects Eastern/12h)
- Add weather message rendering (wind, temperature, turbulence)
- Add CPDLC controller-pilot message rendering (purple highlight)
- Add squawk code change rendering (red highlight)
- Fix engine_data crash when parsed value isn't an object
- Show tail/registration alongside flight number on all cards
- Increase message text truncation to 200 chars
- Add FL prefix to flight level in position reports
- Applied consistently across ADS-B dashboard, sidebar feed, and standalone ACARS mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 01:36:32 -04:00
mitchross ebc838fa9d Add global timezone/12h-24h setting and improve satellite selection
Global time preferences (Settings > Display > Time & Timezone):
- InterceptTime utility in core/utils.js with timezone + 12h/24h support
- Timezone options: UTC, Local, Eastern, Central, Mountain, Pacific
- Time format: 12-hour (AM/PM) or 24-hour toggle
- Defaults to US/Eastern + 12-hour
- Header nav clock updates to use selected timezone and format
- Weather satellite mode delegates to global InterceptTime
- Settings persist via localStorage, change listeners notify all modes

Weather satellite improvements:
- Satellite dropdown defaults to "All Meteor Satellites" showing all passes
- Can still filter to specific satellite (M2-3, M2-4, M2-4-80K)
- Capture button on pass cards auto-selects the correct satellite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 01:24:42 -04:00
mitchross 1e5bc0054d Enhance weather satellite UX with pass geometry, guides, and wider predictions
Pass prediction improvements:
- Widen prediction window to 48h at 5° min elevation (was 24h/15°)
- Add AOS/TCA/LOS pass geometry detail panel with times and bearings
- Fix duration display (was showing seconds labeled as minutes)
- Enhanced pass cards with AOS/LOS times, bearings, and directions
- Add REFRESH button in passes panel header
- Better empty state with clear "set your location" prompt and icon

Countdown and visual:
- Pulse animation on countdown when pass is imminent or active
- Countdown numbers scale up and change color for urgency

Sidebar getting started guide:
- New "Getting Started" section explaining what Meteor satellites are,
  polar orbits, 4-8 passes/day, step-by-step workflow
- "When to look" tips (elevation, day vs night, pass direction)
- "What you need" equipment table with costs
- Collapsed antenna guide by default to reduce initial overwhelm
- Improved offline decode section with clear instructions on where
  to get IQ recordings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 01:13:37 -04:00
mitchross 43fb735e4e Fix Meteor LRPT decoding in Docker and enhance weather satellite UI
Docker fixes:
- Add missing COPY for /usr/local/share/ (pipeline definitions were never
  reaching the runtime image — root cause of silent SatDump failures)
- Add libfftw3-double3 and libfftw3-single3 runtime dependencies
- Handle arm64 vs x86 install path differences (/usr vs /usr/local)
- Split SatDump compile and staging into separate layers for better caching
- Add build-time assertions to catch missing pipelines early

UI enhancements:
- Timezone selector (UTC, Local, Eastern, Central, Mountain, Pacific)
  with localStorage persistence — all time displays update instantly
- Pass analysis bar showing 24h quality breakdown and best upcoming pass
- Enhanced pass cards with cardinal direction (NW→SE), BEST badge
- Console timestamps, log level filters (ALL/SIGNAL/PROG/ERR), COPY/CLR
- Pass count in stats strip
- Demo data mode for UI testing without SDR or live satellite pass
- Meteor M2-4 80k baud fallback pipeline option

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 00:05:31 -04:00
James Smith 18b442eb21 Fix dashboard startup regressions and mode utilities 2026-03-19 10:37:21 +00:00
James Smith 0ff0df632b Open satellite dashboard in new tab 2026-03-18 23:41:29 +00:00
James Smith dd37a0b5a7 Unify satellite navigation to dashboard 2026-03-18 23:29:09 +00:00
James Smith 4cf394f92e Persist Meteor decode job state 2026-03-18 22:20:24 +00:00
Smittix e00fbfddc1 v2.26.0: fix SSE fanout crash and branded logo FOUC
- Fix SSE fanout thread AttributeError when source queue is None during
  interpreter shutdown by snapshotting to local variable with null guard
- Fix branded "i" logo rendering oversized on first page load (FOUC) by
  adding inline width/height to SVG elements across 10 templates
- Bump version to 2.26.0 in config.py, pyproject.toml, and CHANGELOG.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:51:27 +00:00
Smittix 44d256179b fix(branding): use inline SVG for branded "i" instead of CSS pseudo-element
The CSS ::after dot positioning was unreliable across fonts and sizes.
Switch to an inline SVG of the "i" glyph (green dot + cyan stem/bars)
extracted from the logo — renders pixel-perfect at any size.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:24:35 +00:00
Smittix 3c05429041 fix(branding): use regular "i" glyph with green dot overlay
The dotless i (ı) wasn't rendering in all fonts. Switch to a regular "i"
with the green dot CSS overlay positioned on top of the native dot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:20:56 +00:00
Smittix 6727b95596 feat(branding): branded "i" with cyan stem and green dot across all titles
Matches the logo icon — the "i" in iNTERCEPT now renders with a cyan
letter and green dot via CSS, consistent across the main header, welcome
card, dashboard headers, help modal, settings modal, and all popout pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:17:24 +00:00
Smittix 90281b1535 fix(modes): deep-linked mode scripts fail when body not yet parsed
ensureModeScript() used document.body.appendChild() to load lazy mode
scripts, but the preload for ?mode= query params runs in <head> before
<body> exists, causing all deep-linked modes to silently fail.

Also fix cross-mode handoffs (BT→BT Locate, WiFi→WiFi Locate,
Spy Stations→Waterfall) that assumed target module was already loaded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 20:49:08 +00:00
Smittix e687862043 feat: UI/UX overhaul — CSS cleanup, accessibility, error handling, inline style extraction
Phase 0 — CSS-only fixes:
- Fix --font-mono to use real monospace stack (JetBrains Mono, Fira Code, etc.)
- Replace hardcoded hex colors with CSS variables across 16+ files
- Merge global-nav.css (507 lines) into layout.css, delete original
- Reduce !important in responsive.css from 71 to 8 via .app-shell specificity
- Standardize breakpoints to 480/768/1024/1280px

Phase 1 — Loading states & SSE connection feedback:
- Add centralized SSEManager (sse-manager.js) with exponential backoff
- Add SSE status indicator dot in nav bar
- Add withLoadingButton() + .btn-loading CSS spinner
- Add mode section crossfade transitions

Phase 2 — Accessibility:
- Add aria-labels to icon-only buttons across mode partials
- Add for/id associations to 42 form labels in 5 mode partials
- Add aria-live on toast stack, enableListKeyNav() utility

Phase 3 — Destructive action guards & list overflow:
- Add confirmAction() styled modal, replace all 25 native confirm() calls
- Add toast cap at 5 simultaneous toasts
- Add list overflow indicator CSS

Phase 4 — Inline style extraction:
- Refactor switchMode() in app.js and index.html to use classList.toggle()
- Add CSS toggle rules for all switchMode-controlled elements
- Remove inline style="display:none" from 7+ HTML elements
- Add utility classes (.hidden, .d-flex, .d-grid, etc.)

Phase 5 — Mobile UX polish:
- pre/code overflow handling already in place
- Touch target sizing via --touch-min variable

Phase 6 — Error handling consistency:
- Add reportActionableError() to user-facing catch blocks in 5 mode JS files
- 28 error toast additions alongside existing console.error calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 13:04:36 +00:00
Smittix ab033b35d3 feat: WiFi Locate mode, mobile nav groups, v2.24.0
Add WiFi Locate mode for locating access points by BSSID with real-time
signal meter, distance estimation, RSSI history chart, and audio
proximity tones. Includes hand-off from WiFi detail drawer, environment
presets (Free Space/Outdoor/Indoor), and signal-lost detection.

Also includes:
- Mobile navigation reorganized into labeled groups (SIG/TRK/SPC/WIFI/INTEL/SYS)
- flask-limiter made optional with graceful degradation
- Fix radiosonde setup missing semver Python dependency
- Documentation updates (FEATURES, USAGE, UI_GUIDE, GitHub Pages site)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:49:03 +00:00
thatsatechnique 18db66bce3 fix(ook): harden for upstream review — tests, cleanup, CSS extraction
- Add kill_all() handler for OOK process cleanup on global reset
- Fix stop_ook() to close pipes and join parser thread (prevents hangs)
- Add ook.css with CSS classes, replace inline styles in ook.html
- Register ook.css in lazy-load style map (INTERCEPT_MODE_STYLE_MAP)
- Fix frontend frequency min=24 to match backend validation
- Add 22 unit tests for decode_ook_frame, ook_parser_thread, and routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:52:32 -08:00
thatsatechnique 93fb694e25 fix(ook): address code review findings from Copilot PR review
- Fix XSS: escape ASCII output in innerHTML via escapeHtml()
- Fix deadlock: use put_nowait() for queue ops under ook_lock
- Fix SSE leak: add ook to moduleDestroyMap so switching modes
  closes the EventSource
- Fix RSSI: explicit null check preserves valid zero values in
  JSON export
- Add frame cap: trim oldest frames at 5000 to prevent unbounded
  memory growth on busy bands
- Validate timing params: wrap int() casts in try/except, return
  400 instead of 500 on invalid input
- Fix PWM hint: correct to short=0/long=1 matching rtl_433
  OOK_PWM convention (UI, JS hints, and cheat sheet)
- Fix inversion docstring: clarify fallback only applies when
  primary hex parse fails, not for valid decoded frames

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:29:55 -08:00
thatsatechnique cde24642ac feat(ook): add persistent frequency presets with add/remove/reset
Replace hardcoded frequency buttons with localStorage-backed presets.
Default presets are standard ISM frequencies (433.920, 315, 868, 915 MHz).
Users can add custom frequencies, right-click to remove, and reset to
defaults — matching the pager module pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:28:49 -08:00
thatsatechnique f771100a4c fix(ook): fix output panel layout, persist frames, wire global status bar
- Fix double-scroll by switching ookOutputPanel to flex layout
- Keep decoded frames visible after stopping (persist for review)
- Wire global Clear/CSV/JSON status bar buttons to OOK functions
- Hide default output pane in OOK mode (uses own panel)
- Add command display showing the active rtl_433 command
- Add JSON export and auto-scroll support
- Fix 0x prefix stripping in OOK hex decoder
- Fix PWM encoding hint text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:28:49 -08:00
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
ribs ec62cd9083 fix: prevent silent muting from hiding pager messages
The "Mute" button on pager cards persists muted addresses to
localStorage with no visible indicator, making it easy to
accidentally hide an address and forget about it. This caused
flag fragment messages on RIC 1337 to silently disappear.

- Add "X muted source(s) — Unmute All" indicator to sidebar
- Stop persisting hideToneOnly filter across sessions so the
  default (show all) always applies on page load
- Remove default checked state from Tone Only filter checkbox

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:05:01 -08:00
Smittix 38644bced6 fix: replace 100+ hardcoded colors with CSS variables for light theme
Add theme-aware severity/neon CSS variables and replace hardcoded hex
colors (#fff, #000, #00ff88, #ffcc00, etc.) with var() references
across 26 files so text remains readable in both dark and light themes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:35:17 +00:00
Smittix eea44f9a6b fix: move meteor scatter start button below antenna guide
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:02:15 +00:00
Smittix 845629ea46 feat: enhance Meteor Scatter with sidebar fixes and visual effects
Move SDR Device below mode title, add sidebar Start/Stop buttons,
and add starfield canvas, meteor streak animations, particle bursts,
signal strength meter, and enhanced ping flash effects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:04:35 +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 be70d2e43b feat: move radiosonde status display to main pane stats strip
Move tracking state, balloon count, last update, and waveform from the
sidebar into a stats strip above the map, matching the APRS strip pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:58:16 +00:00
Smittix 90b455aa6c feat: add signal activity waveform component for radiosonde mode
Reusable SVG bar waveform (SignalWaveform.Live) that animates in response
to incoming SSE data — idle breathing when stopped, active oscillation
proportional to telemetry update frequency, smooth decay on signal loss.

Integrated into radiosonde Status section with ping() on each balloon
message and stop() on tracking stop. Also hardens the fetch error path
to show a readable message instead of a JSON parse error when the server
returns HTML.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:27:09 +00:00
Smittix d087780d9f fix: WeFax sidebar minor GUI issues (#167)
Remove section hover shift, fix broken NOAA PDF link, reorder sections
to match Weather Satellite pattern, and fix text alignment spacing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:48:42 +00:00