"""Configuration settings for intercept application.""" from __future__ import annotations import logging import os import sys # Application version VERSION = "2.15.0" # Changelog - latest release notes (shown on welcome screen) CHANGELOG = [ { "version": "2.15.0", "date": "February 2026", "highlights": [ "Real-time WebSocket waterfall with I/Q capture and server-side FFT", "Cross-module frequency routing from Listening Post to decoders", "Pure Python SSTV decoder replacing broken slowrx dependency", "Real-time signal scope for pager, sensor, and SSTV modes", "USB-level device probe to prevent cryptic rtl_fm crashes", "DMR dsd-fme protocol fixes, tuning controls, and state sync", "SDR device lock-up fix from unreleased device registry on crash", ] }, { "version": "2.14.0", "date": "February 2026", "highlights": [ "DMR/P25/NXDN/D-STAR digital voice decoder with dsd-fme", "DMR visual synthesizer with event-driven spring-physics bars", "HF SSTV general mode with predefined shortwave frequencies", "WebSDR integration for remote HF/shortwave listening", "Listening Post signal scanner and audio pipeline improvements", "TSCM sweep resilience, WiFi detection, and correlation fixes", "APRS rtl_fm startup and SDR device conflict fixes", ] }, { "version": "2.13.1", "date": "February 2026", "highlights": [ "UI overhaul with slate/cyan theme and JetBrains Mono font", "Signal scanner rewritten with rtl_power sweep and SNR filtering", "Listening Post audio streaming via WAV with retry/fallback", "WiFi connected clients panel now filters to selected AP", "Global navigation bar across all dashboards", "Fixed USB device contention when starting audio pipeline", ] }, { "version": "2.13.0", "date": "February 2026", "highlights": [ "WiFi client display in AP detail drawer with real-time SSE updates", "Help modal system with keyboard shortcuts reference", "Global navbar and settings modal accessible from all dashboards", "Probed SSID badges for connected clients", ] }, { "version": "2.12.1", "date": "February 2026", "highlights": [ "SDR device registry to prevent decoder conflicts", "SDR device status panel and ADS-B Bias-T toggle", "Real-time Doppler tracking for ISS SSTV reception", "TCP connection support for Meshtastic", "Shared observer location with auto-start options", ] }, { "version": "2.12.0", "date": "January 2026", "highlights": [ "ISS SSTV decoder with real-time ISS tracking globe", "GitHub update notifications for new releases", "Meshtastic QR code support and telemetry display", "New Space category with reorganized UI", ] }, { "version": "2.11.0", "date": "January 2026", "highlights": [ "Meshtastic LoRa mesh network integration", "Ubertooth One BLE scanning support", "Offline mode with bundled assets", "Settings modal with tile provider configuration", ] }, { "version": "2.10.0", "date": "January 2026", "highlights": [ "AIS vessel tracking with VHF DSC distress monitoring", "Spy Stations database (number stations & diplomatic HF)", "MMSI country identification and distress alert overlays", "SDR device conflict detection for AIS/DSC", ] }, { "version": "2.9.5", "date": "January 2026", "highlights": [ "Enhanced TSCM with MAC-randomization resistant detection", "Clickable score cards and device detail expansion", "RF scanning improvements with status feedback", "Root privilege check and warning display", ] }, { "version": "2.9.0", "date": "January 2026", "highlights": [ "New dropdown navigation menus for cleaner UI", "TSCM baseline recording now captures device data", "Device identity engine integration for threat detection", "Welcome screen with mode selection", ] }, { "version": "2.8.0", "date": "December 2025", "highlights": [ "Added TSCM counter-surveillance mode", "WiFi/Bluetooth device correlation engine", "Tracker detection (AirTag, Tile, SmartTag)", "Risk scoring and threat classification", ] }, ] def _get_env(key: str, default: str) -> str: """Get environment variable with default.""" return os.environ.get(f'INTERCEPT_{key}', default) def _get_env_int(key: str, default: int) -> int: """Get environment variable as integer with default.""" try: return int(os.environ.get(f'INTERCEPT_{key}', str(default))) except ValueError: return default def _get_env_float(key: str, default: float) -> float: """Get environment variable as float with default.""" try: return float(os.environ.get(f'INTERCEPT_{key}', str(default))) except ValueError: return default def _get_env_bool(key: str, default: bool) -> bool: """Get environment variable as boolean with default.""" val = os.environ.get(f'INTERCEPT_{key}', '').lower() if val in ('true', '1', 'yes', 'on'): return True if val in ('false', '0', 'no', 'off'): return False return default # Logging configuration _log_level_str = _get_env('LOG_LEVEL', 'WARNING').upper() LOG_LEVEL = getattr(logging, _log_level_str, logging.WARNING) LOG_FORMAT = _get_env('LOG_FORMAT', '%(asctime)s - %(levelname)s - %(message)s') # Server settings HOST = _get_env('HOST', '0.0.0.0') PORT = _get_env_int('PORT', 5050) DEBUG = _get_env_bool('DEBUG', False) THREADED = _get_env_bool('THREADED', True) # Default RTL-SDR settings DEFAULT_GAIN = _get_env('DEFAULT_GAIN', '40') DEFAULT_DEVICE = _get_env('DEFAULT_DEVICE', '0') # Pager defaults DEFAULT_PAGER_FREQ = _get_env('PAGER_FREQ', '929.6125M') # Timeouts PROCESS_TIMEOUT = _get_env_int('PROCESS_TIMEOUT', 5) SOCKET_TIMEOUT = _get_env_int('SOCKET_TIMEOUT', 5) SSE_TIMEOUT = _get_env_int('SSE_TIMEOUT', 1) # WiFi settings WIFI_UPDATE_INTERVAL = _get_env_float('WIFI_UPDATE_INTERVAL', 2.0) AIRODUMP_HEADER_LINES = _get_env_int('AIRODUMP_HEADER_LINES', 2) # Bluetooth settings BT_SCAN_TIMEOUT = _get_env_int('BT_SCAN_TIMEOUT', 10) 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) ADSB_DB_NAME = _get_env('ADSB_DB_NAME', 'intercept_adsb') ADSB_DB_USER = _get_env('ADSB_DB_USER', 'intercept') ADSB_DB_PASSWORD = _get_env('ADSB_DB_PASSWORD', 'intercept') ADSB_HISTORY_BATCH_SIZE = _get_env_int('ADSB_HISTORY_BATCH_SIZE', 500) ADSB_HISTORY_FLUSH_INTERVAL = _get_env_float('ADSB_HISTORY_FLUSH_INTERVAL', 1.0) ADSB_HISTORY_QUEUE_SIZE = _get_env_int('ADSB_HISTORY_QUEUE_SIZE', 50000) # Observer location settings SHARED_OBSERVER_LOCATION_ENABLED = _get_env_bool('SHARED_OBSERVER_LOCATION', True) DEFAULT_LATITUDE = _get_env_float('DEFAULT_LAT', 0.0) DEFAULT_LONGITUDE = _get_env_float('DEFAULT_LON', 0.0) # Satellite settings SATELLITE_UPDATE_INTERVAL = _get_env_int('SATELLITE_UPDATE_INTERVAL', 30) SATELLITE_TRAJECTORY_POINTS = _get_env_int('SATELLITE_TRAJECTORY_POINTS', 30) SATELLITE_ORBIT_MINUTES = _get_env_int('SATELLITE_ORBIT_MINUTES', 45) # Weather satellite settings WEATHER_SAT_DEFAULT_GAIN = _get_env_float('WEATHER_SAT_GAIN', 40.0) WEATHER_SAT_SAMPLE_RATE = _get_env_int('WEATHER_SAT_SAMPLE_RATE', 1000000) WEATHER_SAT_MIN_ELEVATION = _get_env_float('WEATHER_SAT_MIN_ELEVATION', 15.0) WEATHER_SAT_PREDICTION_HOURS = _get_env_int('WEATHER_SAT_PREDICTION_HOURS', 24) WEATHER_SAT_SCHEDULE_REFRESH_MINUTES = _get_env_int('WEATHER_SAT_SCHEDULE_REFRESH_MINUTES', 30) WEATHER_SAT_CAPTURE_BUFFER_SECONDS = _get_env_int('WEATHER_SAT_CAPTURE_BUFFER_SECONDS', 30) # SubGHz transceiver settings (HackRF) SUBGHZ_DEFAULT_FREQUENCY = _get_env_float('SUBGHZ_FREQUENCY', 433.92) SUBGHZ_DEFAULT_SAMPLE_RATE = _get_env_int('SUBGHZ_SAMPLE_RATE', 2000000) SUBGHZ_DEFAULT_LNA_GAIN = _get_env_int('SUBGHZ_LNA_GAIN', 32) SUBGHZ_DEFAULT_VGA_GAIN = _get_env_int('SUBGHZ_VGA_GAIN', 20) SUBGHZ_DEFAULT_TX_GAIN = _get_env_int('SUBGHZ_TX_GAIN', 20) SUBGHZ_MAX_TX_DURATION = _get_env_int('SUBGHZ_MAX_TX_DURATION', 10) SUBGHZ_SWEEP_START_MHZ = _get_env_float('SUBGHZ_SWEEP_START', 300.0) SUBGHZ_SWEEP_END_MHZ = _get_env_float('SUBGHZ_SWEEP_END', 928.0) # Update checking GITHUB_REPO = _get_env('GITHUB_REPO', 'smittix/intercept') UPDATE_CHECK_ENABLED = _get_env_bool('UPDATE_CHECK_ENABLED', True) UPDATE_CHECK_INTERVAL_HOURS = _get_env_int('UPDATE_CHECK_INTERVAL_HOURS', 6) # Alerting ALERT_WEBHOOK_URL = _get_env('ALERT_WEBHOOK_URL', '') ALERT_WEBHOOK_SECRET = _get_env('ALERT_WEBHOOK_SECRET', '') ALERT_WEBHOOK_TIMEOUT = _get_env_int('ALERT_WEBHOOK_TIMEOUT', 5) # Admin credentials ADMIN_USERNAME = _get_env('ADMIN_USERNAME', 'admin') ADMIN_PASSWORD = _get_env('ADMIN_PASSWORD', 'admin') def configure_logging() -> None: """Configure application logging.""" logging.basicConfig( level=LOG_LEVEL, format=LOG_FORMAT, stream=sys.stderr ) # Suppress Flask development server warning logging.getLogger('werkzeug').setLevel(LOG_LEVEL)