From 1b5bf4c061a0dcce79a424f79794b66e737fc977 Mon Sep 17 00:00:00 2001 From: James Ward Date: Fri, 30 Jan 2026 00:17:32 -0800 Subject: [PATCH] fix: make ADS-B auto-start opt-in --- config.py | 1 + docker-compose.yml | 4 ++ docs/USAGE.md | 7 ++- routes/adsb.py | 2 + templates/adsb_dashboard.html | 79 +++++++++++++++++------------- templates/satellite_dashboard.html | 44 ++++++++++------- 6 files changed, 82 insertions(+), 55 deletions(-) diff --git a/config.py b/config.py index 8e3e1ef..2250f1d 100644 --- a/config.py +++ b/config.py @@ -139,6 +139,7 @@ BT_UPDATE_INTERVAL = _get_env_float('BT_UPDATE_INTERVAL', 2.0) # ADS-B settings ADSB_SBS_PORT = _get_env_int('ADSB_SBS_PORT', 30003) ADSB_UPDATE_INTERVAL = _get_env_float('ADSB_UPDATE_INTERVAL', 1.0) +ADSB_AUTO_START = _get_env_bool('ADSB_AUTO_START', False) ADSB_HISTORY_ENABLED = _get_env_bool('ADSB_HISTORY_ENABLED', False) ADSB_DB_HOST = _get_env('ADSB_DB_HOST', 'localhost') ADSB_DB_PORT = _get_env_int('ADSB_DB_PORT', 5432) diff --git a/docker-compose.yml b/docker-compose.yml index 18695c2..234eb3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,8 @@ services: # - INTERCEPT_ADSB_DB_NAME=intercept_adsb # - INTERCEPT_ADSB_DB_USER=intercept # - INTERCEPT_ADSB_DB_PASSWORD=intercept + # ADS-B auto-start on dashboard load (default false) + - INTERCEPT_ADSB_AUTO_START=${INTERCEPT_ADSB_AUTO_START:-false} # Shared observer location across modules - INTERCEPT_SHARED_OBSERVER_LOCATION=${INTERCEPT_SHARED_OBSERVER_LOCATION:-true} # Network mode for WiFi scanning (requires host network) @@ -70,6 +72,8 @@ services: - INTERCEPT_ADSB_DB_NAME=intercept_adsb - INTERCEPT_ADSB_DB_USER=intercept - INTERCEPT_ADSB_DB_PASSWORD=intercept + # ADS-B auto-start on dashboard load (default false) + - INTERCEPT_ADSB_AUTO_START=${INTERCEPT_ADSB_AUTO_START:-false} # Shared observer location across modules - INTERCEPT_SHARED_OBSERVER_LOCATION=${INTERCEPT_SHARED_OBSERVER_LOCATION:-true} restart: unless-stopped diff --git a/docs/USAGE.md b/docs/USAGE.md index b98f73d..c2a455f 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -68,11 +68,14 @@ INTERCEPT automatically detects known trackers: - **Shared Location** - By default, the observer location is shared across modules (disable with `INTERCEPT_SHARED_OBSERVER_LOCATION=false`) 4. **Start Tracking** - Click "Start Tracking" to begin ADS-B reception -5. **View Map** - Aircraft appear on the interactive Leaflet map +5. **View Map** - Aircraft appear on the interactive Leaflet map 6. **Click Aircraft** - Click markers for detailed information 7. **Display Options** - Toggle callsigns, altitude, trails, range rings, clustering 8. **Filter Aircraft** - Use dropdown to show all, military, civil, or emergency only -9. **Full Dashboard** - Click "Full Screen Dashboard" for dedicated radar view +9. **Full Dashboard** - Click "Full Screen Dashboard" for dedicated radar view + +> Note: ADS-B auto-start is disabled by default. To enable auto-start on dashboard load, +> set `INTERCEPT_ADSB_AUTO_START=true`. ### Emergency Squawks diff --git a/routes/adsb.py b/routes/adsb.py index 6ecb111..7bd8e1b 100644 --- a/routes/adsb.py +++ b/routes/adsb.py @@ -33,6 +33,7 @@ from config import ( ADSB_DB_PASSWORD, ADSB_DB_PORT, ADSB_DB_USER, + ADSB_AUTO_START, ADSB_HISTORY_ENABLED, SHARED_OBSERVER_LOCATION_ENABLED, ) @@ -816,6 +817,7 @@ def adsb_dashboard(): return render_template( 'adsb_dashboard.html', shared_observer_location=SHARED_OBSERVER_LOCATION_ENABLED, + adsb_auto_start=ADSB_AUTO_START, ) diff --git a/templates/adsb_dashboard.html b/templates/adsb_dashboard.html index 5383460..725e3ca 100644 --- a/templates/adsb_dashboard.html +++ b/templates/adsb_dashboard.html @@ -22,6 +22,7 @@ @@ -2541,28 +2542,32 @@ sudo make install } } - async function syncTrackingStatus() { - // This function checks LOCAL tracking status on page load - // For local mode: auto-start if session is already running OR SDR is available - // For agent mode: don't auto-start (user controls agent tracking) - - const useAgent = typeof adsbCurrentAgent !== 'undefined' && adsbCurrentAgent !== 'local'; - if (useAgent) { - console.log('[ADS-B] Agent mode on page load - not auto-starting local'); - return; - } - - try { - const response = await fetch('/adsb/session'); - if (!response.ok) { - // No session info - try to auto-start if SDR available - console.log('[ADS-B] No session found, attempting auto-start...'); - await tryAutoStartLocal(); - return; - } - const data = await response.json(); - - if (data.tracking_active) { + async function syncTrackingStatus() { + // This function checks LOCAL tracking status on page load + // For local mode: auto-start if session is already running OR SDR is available + // For agent mode: don't auto-start (user controls agent tracking) + + const useAgent = typeof adsbCurrentAgent !== 'undefined' && adsbCurrentAgent !== 'local'; + if (useAgent) { + console.log('[ADS-B] Agent mode on page load - not auto-starting local'); + return; + } + + try { + const response = await fetch('/adsb/session'); + if (!response.ok) { + // No session info - only auto-start if enabled + if (window.INTERCEPT_ADSB_AUTO_START) { + console.log('[ADS-B] No session found, attempting auto-start...'); + await tryAutoStartLocal(); + } else { + console.log('[ADS-B] No session found; auto-start disabled'); + } + return; + } + const data = await response.json(); + + if (data.tracking_active) { // Session is running - auto-connect to stream console.log('[ADS-B] Local session already active - auto-connecting to stream'); @@ -2598,18 +2603,24 @@ sudo make install document.getElementById('trackingDot').classList.add('active'); const statusEl = document.getElementById('trackingStatus'); statusEl.textContent = 'TRACKING'; - } else { - // Session not active - try to auto-start - console.log('[ADS-B] No active session, attempting auto-start...'); - await tryAutoStartLocal(); - } - - } catch (err) { - console.warn('[ADS-B] Failed to sync tracking status:', err); - // Try auto-start anyway - await tryAutoStartLocal(); - } - } + } else { + // Session not active - only auto-start if enabled + if (window.INTERCEPT_ADSB_AUTO_START) { + console.log('[ADS-B] No active session, attempting auto-start...'); + await tryAutoStartLocal(); + } else { + console.log('[ADS-B] No active session; auto-start disabled'); + } + } + + } catch (err) { + console.warn('[ADS-B] Failed to sync tracking status:', err); + // Try auto-start only if enabled + if (window.INTERCEPT_ADSB_AUTO_START) { + await tryAutoStartLocal(); + } + } + } async function tryAutoStartLocal() { // Try to auto-start local ADS-B tracking if SDR is available diff --git a/templates/satellite_dashboard.html b/templates/satellite_dashboard.html index 8da5071..cd05609 100644 --- a/templates/satellite_dashboard.html +++ b/templates/satellite_dashboard.html @@ -431,28 +431,34 @@ now.toISOString().substring(11, 19) + ' UTC'; } - function initGroundMap() { - groundMap = L.map('groundMap', { - center: [20, 0], - zoom: 2, - minZoom: 1, - maxZoom: 10, - worldCopyJump: true - }); + function initGroundMap() { + groundMap = L.map('groundMap', { + center: [20, 0], + zoom: 2, + minZoom: 1, + maxZoom: 10, + worldCopyJump: true + }); // Use settings manager for tile layer (allows runtime changes) window.groundMap = groundMap; - if (typeof Settings !== 'undefined' && Settings.createTileLayer) { - Settings.createTileLayer().addTo(groundMap); - Settings.registerMap(groundMap); - } else { - L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', { - attribution: '© OSM © CARTO', - maxZoom: 19, - subdomains: 'abcd' - }).addTo(groundMap); - } - } + if (typeof Settings !== 'undefined' && Settings.createTileLayer) { + Settings.createTileLayer().addTo(groundMap); + Settings.registerMap(groundMap); + } else { + L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', { + attribution: '© OSM © CARTO', + maxZoom: 19, + subdomains: 'abcd' + }).addTo(groundMap); + } + + const lat = parseFloat(document.getElementById('obsLat')?.value); + const lon = parseFloat(document.getElementById('obsLon')?.value); + if (!Number.isNaN(lat) && !Number.isNaN(lon)) { + groundMap.setView([lat, lon], 3); + } + } function getLocation() { if (navigator.geolocation) {