Add VDL2 (VHF Digital Link Mode 2) decoding via dumpvdl2 as a new mode,
and promote ACARS from ADS-B-dashboard-only to a first-class standalone
mode in the main SPA. Both aviation datalink modes now have full nav
entries, sidebar partials with region-based frequency selectors, and
SSE streaming. VDL2 also integrated into the ADS-B dashboard as a
collapsible sidebar alongside ACARS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bluetooth enhancements (service data inspector, appearance codes, MAC
cluster tracking, behavioral flags, IRK badges, distance estimation),
ACARS SoapySDR multi-backend support, dump1090 stale process cleanup,
GPS error state, and proximity radar/signal card UI improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add .gitignore entry for data/subghz/captures/ to prevent large
IQ recording files from being committed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security: replace path traversal-vulnerable str().startswith() with
is_relative_to(), anchor path checks to app root, strip filesystem
paths from error responses, add decoder-level path validation.
Architecture: use safe_terminate/register_process for subprocess
lifecycle, replace custom SSE generator with sse_stream(), use
centralized validate_* functions, remove unused app.py declarations.
Bugs: add thread-safe singleton locks, protect _images list across
threads, move blocking process.wait() to async daemon thread, fix
timezone handling for tz-aware datetimes, use full path for image
deduplication, guard TLE auto-refresh during tests, validate
scheduler parameters to avoid 500 errors.
Docker: pin SatDump to v1.2.2 and slowrx to ca6d7012, document
INTERCEPT_IMAGE fallback pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflicts keeping local GSM tools in kill_all() process list
and weather satellite config settings while merging upstream changes
including GSM spy removal, DMR fixes, USB device probe, APRS crash
fix, and cross-module frequency routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an external process (or stale handle from a crash) holds an SDR
device, claim_sdr_device() registry check passes but rtl_fm fails with
usb_claim_interface error -6. This adds a quick rtl_test probe inside
claim_sdr_device() so all modes get a clear error message before the
decoder pipeline is launched.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all GSM cellular intelligence features including tower scanning,
signal monitoring, rogue detection, crowd density analysis, and
OpenCellID integration across routes, templates, utils, tests, and
build configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- kill_all() now resets gsm_spy_scanner_running and related state so
the scanner thread stops after killall
- scanner_thread sets flag to False instead of None on exit
- Restore alert_rules, alert_events, recording_sessions tables and
wifi_clients column removed by PR in database.py
- Escape all server-sourced values in analysis modals with escapeHtml()
- Reset gsm_towers_found/gsm_devices_tracked on stop to prevent
counter drift across sessions
- Replace raw terminate/kill with safe_terminate() in scanner_thread
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The before_request require_login hook was returning a 302 redirect
for WebSocket upgrade requests, which browsers report as "Invalid
frame header". WebSocket requests don't always carry session cookies
reliably. Allow /ws/ paths through the login check since the page
that initiates these connections already requires authentication.
Also keeps the prior fix: serialize WebSocket sends through a queue
to avoid concurrent read/write on the non-thread-safe simple-websocket.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the batch rtl_power SSE pipeline with continuous I/Q streaming
via WebSocket for smooth ~25fps waterfall display. The server captures
raw I/Q samples (rtl_sdr/rx_sdr), computes Hann-windowed FFT, and
sends compact binary frames (1035 bytes vs ~15KB JSON, 93% reduction).
Client falls back to existing SSE path if WebSocket is unavailable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Waterfall clicks now auto-select the correct modulation for the frequency
band (e.g., WFM for FM broadcast, AM for airband) instead of using whatever
modulation was last selected. Adds a hover tooltip showing frequency and
suggested modulation. Fixes the kill-all notification to show a clean
"All processes stopped" message instead of listing "bluetooth_scanner".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverts IQ pipeline and removes syncWaterfallToFrequency calls from
pager, sensor, rtlamr, DMR, SSTV, and SSTV general modes. Waterfall
is now exclusive to listening post mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace rtl_fm/rtl_433 with rtl_sdr for raw IQ capture when available,
enabling a Python IQ processor to compute FFT for the waterfall while
simultaneously feeding decoded data to multimon-ng (pager) or rtl_433
(sensor). Falls back to the legacy pipeline when rtl_sdr is unavailable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merges upstream changes into fork while preserving weather satellite
(NOAA APT/Meteor LRPT via SatDump), rtlamr, multi-arch build, and
decoder console features from our branch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stream threads for sensor, pager, acars, rtlamr, dmr, and dsc modes
never called release_sdr_device() when their SDR process crashed,
leaving devices permanently locked in the registry. Also fixes orphaned
companion processes (rtl_fm, rtl_tcp) not being killed on crash, start
path failures leaking processes, DMR stop handler missing lock, and
listening post/audio websocket pkill nuking all system-wide rtl_fm
processes. Wires up register_process()/unregister_process() so the
atexit/signal cleanup safety net actually works, and adds rtl_tcp,
rtl_power, rtlamr, ffmpeg to the killall endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DMR/P25 digital voice decoder mode with DSD-FME integration
- WebSDR mode with KiwiSDR audio proxy and websocket-client support
- Listening post waterfall/spectrogram visualization and audio streaming
- Dockerfile updates for mbelib and DSD-FME build dependencies
- New tests for DMR, WebSDR, KiwiSDR, waterfall, and signal guess API
- Chart.js date adapter for time-scale axes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Issues fixed:
- #113: Display RTL-SDR serial numbers in device selector
- #112: Kill all processes now stops Bluetooth scans
- #111: BLE device list no longer overflows container bounds
- #109: WiFi scanner panels maintain minimum width (no more "imploding")
- #108: Radar device hover no longer causes violent shaking
- #106: "Use GPS" button now uses gpsd for USB GPS devices
- #105: Meter trend text no longer overlaps adjacent columns
- #104: dump1090 errors now provide specific troubleshooting guidance
Changes:
- app.py: Add Bluetooth cleanup to /killall endpoint
- routes/adsb.py: Parse dump1090 stderr for specific error messages
- templates/index.html: Show SDR serial numbers in device dropdown
- static/css/index.css: Fix WiFi/BT panel layouts with proper min-width
- static/css/components/signal-cards.css: Fix meter grid overflow
- static/css/components/proximity-viz.css: Fix radar hover transform
- static/css/settings.css: Add GPS detection spinner
- static/js/components/proximity-radar.js: Add invisible hit areas
- static/js/core/settings-manager.js: Use gpsd before browser geolocation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /devices/status endpoint showing which SDR is in use and by what mode
- Add real-time status panel on main dashboard with 5s auto-refresh
- Add Bias-T toggle to ADS-B dashboard with localStorage persistence
- Auto-detect correct dump1090 bias-t flag (--enable-biast vs unsupported)
- Standardize SDR device labels across all pages
Closes#102
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements centralized tracking of SDR device allocation to prevent
multiple decoders from trying to use the same device simultaneously.
- Add sdr_device_registry with claim/release/status functions in app.py
- Update all SDR-based routes to claim devices on start and release on stop
- Return HTTP 409 with DEVICE_BUSY error when device is already in use
- Clear registry on /killall
- Skip device claims for remote connections (rtl_tcp, remote SBS)
Fixes#100Fixes#101
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add refresh_tle_data() function for reusable TLE updates
- Automatically fetch fresh TLE from CelesTrak when app starts
- Runs in background thread to avoid slowing down startup
- Includes NOAA-20 and NOAA-21 in name mappings
- Gracefully handles failures (uses cached data if offline)
- Existing /update-tle endpoint now uses shared function
This ensures satellite tracking data is always fresh, fixing
inaccurate positions caused by stale TLE data.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New Features:
- Meshtastic LoRa mesh network integration
- Real-time message streaming via SSE
- Channel configuration with encryption
- Node information with RSSI/SNR metrics
- Ubertooth One BLE scanner backend
- Passive capture across all 40 BLE channels
- Raw advertising payload access
- Offline mode with bundled assets
- Local Leaflet, Chart.js, and fonts
- Multiple map tile providers
- Settings modal for configuration
Technical Changes:
- New routes: meshtastic.py, offline.py
- New utils: ubertooth_scanner.py, meshtastic.py
- New CSS/JS for meshtastic and settings
- Updated dashboard templates with conditional asset loading
- Added context processor for offline settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Features:
- Standalone agent server (intercept_agent.py) for remote sensor nodes
- Controller API blueprint for agent management and data aggregation
- Push mechanism for agents to send data to controller
- Pull mechanism for controller to proxy requests to agents
- Multi-agent SSE stream for combined data view
- Agent management page at /controller/manage
- Agent selector dropdown in main UI
- GPS integration for location tagging
- API key authentication for secure agent communication
- Integration with Intercept's dependency checking system
New files:
- intercept_agent.py: Remote agent HTTP server
- intercept_agent.cfg: Agent configuration template
- routes/controller.py: Controller API endpoints
- utils/agent_client.py: HTTP client for agents
- utils/trilateration.py: Multi-agent position calculation
- static/js/core/agents.js: Frontend agent management
- templates/agents.html: Agent management page
- docs/DISTRIBUTED_AGENTS.md: System documentation
Modified:
- app.py: Register controller blueprint
- utils/database.py: Add agents and push_payloads tables
- templates/index.html: Add agent selector section
- Added rtlamr mode for decoding utility meters (water, gas, electric)
- Starts rtl_tcp server first, then connects rtlamr to it
- Supports multiple message types: SCM, SCM+, IDM, NetIDM, R900, R900 BCD
- Added frequency presets for 912 MHz (NA) and 868 MHz (EU)
- Includes meter ID filtering and unique message options
- Updated setup.sh to check and install rtlamr and rtl_tcp
- Added UI components: navigation button, mode template, JavaScript functions
- Integrated into SDR/RF dropdown menu with lightning bolt icon
- Updates mode indicator with frequency when listening
- Added help documentation and requirements section
Introduced Flask-Limiter to restrict login attempts to 5 per minute per IP, enhancing security against brute-force attacks. Updated error handling to display a user-friendly message when the rate limit is exceeded. Minor improvements to the login page, including clearer error messages and display of the user's IP address.
- Replace simple splash screen with comprehensive welcome page
- Show version number and latest changelog entries
- Add 9-button mode selection grid for direct navigation
- User can now choose which mode to start with
- Responsive layout adapts to mobile screens
- Flow: Welcome → Disclaimer (if needed) → Selected mode
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add startup check in app.py for root/sudo privileges
- Show warning in terminal if not running as root
- Add running_as_root flag to TSCM devices API response
- Display privilege warning in TSCM UI when not running as root
- Show command to run with sudo in the warning
- Add CSS styling for privilege warning banner
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create routes/aprs.py with start/stop/stream endpoints for APRS decoding
- Support multiple regional frequencies (North America, Europe, Australia, etc.)
- Use direwolf (preferred) or multimon-ng as AFSK1200 decoder
- Parse APRS packets for position, weather, messages, and telemetry
- Add APRS visualization panel with Leaflet map and station tracking
- Include station list with callsigns, distance, and last heard time
- Add packet log with raw APRS data display
- Register APRS blueprint and add global state management
- Add direwolf and multimon-ng to dependency definitions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add routes/acars.py with start/stop/stream endpoints for ACARS decoding
- Build acarsdec from source in Dockerfile (not available in Debian slim)
- Add acarsdec installation script to setup.sh for native installs
- Add ACARS to dependency checker in utils/dependencies.py
- Add collapsible ACARS sidebar next to map in aircraft tracking tab
- Add collapsible ACARS panel in ADS-B dashboard with same layout
- Include guidance about needing two SDRs for simultaneous ADS-B + ACARS
- Support regional frequency presets (N.America, Europe, Asia-Pacific)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'health' to allowed routes to prevent Docker healthcheck failures
- Translate Spanish comments to English for consistency
- Reset binary database file to avoid committing user data
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces hardcoded admin credentials with a users table in the database, storing hashed passwords and user roles. Updates the login logic in app.py to authenticate against the database using Werkzeug's password hashing utilities. Adds admin credential configuration to config.py and ensures a default admin user is created during database initialization.
Introduced a login system to restrict access to the application. Added session-based authentication in app.py, including login and logout routes, and a new login.html template for the login form. Updated .dockerignore to exclude .uv directory.