- Add base flex properties to #meshcoreVisuals so it fills full panel
height when meshtastic.css hasn't been lazily loaded yet
- Poll /meshcore/status every 2s after Connect click so the UI
transitions out of "Connecting..." when the backend is ready
- Fix Add Contact and Traceroute modals to use .show class pattern
(signal-details-modal uses opacity/visibility transitions, not display)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
The sidebar-hiding CSS lives only in meshtastic.css, which is lazily
loaded and may not be present when switching directly to Meshcore mode.
Duplicating the three rules into meshcore.css ensures the generic
sidebar is correctly hidden and the output panel fills the screen
regardless of load order.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
meshcore.css was missing the .active display rule, so the meshcoreMode
div (display:none inline) was never made visible when the mode was
selected, leaving only the generic sidebar visible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace height:100% with flex:1+min-height:0 on .drone-visuals-container
so it fills the flex-column .output-panel correctly (height:100% collapses
inside a scroll container). Add min-height:400px to .drone-main-map so
Leaflet has pixel dimensions to render into.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
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>
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>
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>
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>
- 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>
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>
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>
Add flex-shrink: 0 so the strip holds its intrinsic height instead of
being distorted by the parent flex container.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
- Fix globe destroyed on re-render by preserving canvas DOM node across
renderLocationCard() calls instead of recreating from scratch
- Reduce globe.gl camera minDistance (180->120) so globe is visible in
200px container
- Clear stale globeInstance ref when canvas is gone
- Enlarge CPU gauge (90->110px), percentage label (18->22px), core bars
(24->48px height), and detail text (11->12px)
- JS fetchLocation() now supplements server response with client-side
ObserverLocation.getShared() from localStorage when server returns
'default' or 'none', picking up manual coordinates from settings modal
- Location priority: GPS > config env vars > manual (localStorage) > default
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
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>
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>
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>
Resolved conflict in static/js/modes/weather-satellite.js:
- Kept allPasses state variable and applyPassFilter() for satellite pass filtering
- Kept satellite select dropdown listener for filter feature
- Adopted upstream's optimistic stop() UI pattern for better responsiveness
- Kept optional chaining (pass?.trajectory) since drawPolarPlot can receive null
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix "What's New" section shifting up/down on smaller screens (#157) by
isolating the logo pulse animation to its own compositing layer, stabilizing
the scrollbar gutter, and pinning the welcome container dimensions.
Morse mode improvements: relocate scope and decoded output panels to the
main content area, use shared SDR device controls, and reduce panel heights
for better layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New signal mode for decoding Morse code (CW) transmissions via SDR.
Includes route blueprint, utility decoder, frontend UI, and tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace window.open() with a fullscreen modal matching the SSTV
pattern: toolbar with download/delete SVG buttons, close button,
click-outside-to-close, and confirmation before delete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flash the Start button itself with amber pulse when clicked without a
station selected, and show "Select Station" in the strip status text
right next to the button so the error is immediately visible.
Add a 24-hour timeline bar with broadcast window markers, red UTC time
cursor, and countdown boxes (HRS/MIN/SEC) that tick down to the next
broadcast. Broadcasts show as amber blocks on the timeline track with
imminent/active visual states matching the weather satellite pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix silent failure when starting without station/frequency selected by
flashing amber on status text and dropdowns. Add auto-capture scheduler
that uses fixed UTC broadcast schedules from station data to
automatically start/stop WeFax decoding at broadcast times.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement HF radiofax decoding with custom Python DSP pipeline
(rtl_fm USB → Goertzel/Hilbert demodulation), 33-station database
with broadcast schedules, audio waveform scope, live image preview,
and decoded image gallery. Amber/gold UI theme for HF distinction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Click an ACARS message in the left sidebar to zoom the map to the
matching aircraft and open its detail panel. Aircraft with ACARS
activity show a DLK badge in the tracked list. Default NA frequency
changed to only check 131.550 on initial load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>