From ea8f72f7ffbe67cac501427c45e6ae85bda97ff2 Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 20 May 2026 22:08:42 +0100 Subject: [PATCH] chore: bump version to 2.27.0 Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 22 +++++ config.py | 243 +++++++++++++++++++++++++------------------------ pyproject.toml | 2 +- 3 files changed, 149 insertions(+), 118 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7b8fc2..f212447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to iNTERCEPT will be documented in this file. +## [2.27.0] - 2026-05-20 + +### Fixed +- **Two-window hang** — Opening the app in two browser tabs/windows caused it to become completely unresponsive. Root cause: HTTP/1.1 limits browsers to 6 connections per origin (shared across all tabs). VoiceAlerts was automatically opening 3 SSE streams per window on page load, so two windows produced 8 persistent connections and permanently blocked all regular HTTP requests. VoiceAlerts streams are now opt-in (disabled by default); users can enable them in settings. +- **Alert messages split between windows** — The `/alerts/stream` SSE endpoint read from a single queue, so two windows would each receive only half the alerts. Now uses `sse_stream_fanout` so every window gets every alert. +- **Bluetooth v2 stream split between windows** — Same single-queue issue in `/api/bluetooth/stream`. Fixed with fanout via `subscribe_fanout_queue`, preserving named SSE events (`device_update`, `scan_started`, etc.). +- **ICAO lookup cache unbounded growth** — `_looked_up_icaos` set was never evicted; capped at 50 000 entries with LRU eviction to prevent memory growth under sustained ADS-B load. +- **Concurrent ICAO clear race** — `popitem()` on the ICAO dict could raise `RuntimeError` if a clear happened concurrently; guarded with try/except. +- **Bluetooth tracker fingerprint stability** — Tracker signature scan was incorrectly resetting stability counters on unchanged payloads; now skips the scan when the BLE payload fingerprint is unchanged. + +### Added +- **UI Tier system** — Three display modes selectable from the nav bar: *Lean* (minimal, no decorative elements), *Standard* (default), and *Enhanced* (full animations and ambient effects). Replaces the old animations toggle. +- **Display mode in first-run setup** — The first-run modal now includes a display mode selection step so new users can pick their preferred visual style during initial setup. + +### Performance +- ADS-B SSE snapshot priming moved inside the response generator (avoids blocking before headers are sent). +- WiFi network filter combined into a single list pass instead of chained filters. +- Bluetooth tracker signature scan skips processing when the BLE payload fingerprint is unchanged. +- `DataStore` cleanup minimises lock hold time by collecting expired keys before acquiring the write lock. + +--- + ## [2.26.11] - 2026-03-14 ### Fixed diff --git a/config.py b/config.py index efd1307..2068763 100644 --- a/config.py +++ b/config.py @@ -7,10 +7,23 @@ import os import sys # Application version -VERSION = "2.26.13" +VERSION = "2.27.0" # Changelog - latest release notes (shown on welcome screen) CHANGELOG = [ + { + "version": "2.27.0", + "date": "May 2026", + "highlights": [ + "Fix: two-window hang caused by browser HTTP/1.1 connection pool exhaustion", + "Fix: SSE alert and Bluetooth streams now fan out to all windows (no more split messages)", + "Feat: UI tier system — lean, standard, enhanced display modes via nav toggle", + "Feat: first-run setup modal includes display mode selection", + "Perf: ADS-B SSE snapshot priming moved into generator; WiFi filter combined into single pass", + "Perf: Bluetooth tracker signature scan skips unchanged fingerprints", + "Fix: ICAO lookup cache capped at 50k entries with LRU eviction", + ], + }, { "version": "2.26.13", "date": "March 2026", @@ -22,70 +35,70 @@ CHANGELOG = [ "Satellite tracker: TLE auto-refresh, polar plot fixes, pass calculation improvements", "Fix weather satellite handoff (remove defunct METEOR-M2)", "Add multi-arch Docker CI workflow (amd64 + arm64)", - ] + ], }, { "version": "2.26.12", "date": "March 2026", "highlights": [ "AIS and ADS-B dashboards now use configured observer position from .env", - ] + ], }, { "version": "2.26.11", "date": "March 2026", "highlights": [ "APRS map now centres on configured observer position from .env", - ] + ], }, { "version": "2.26.8", "date": "March 2026", "highlights": [ "Fix acarsdec build failure on macOS (HOST_NAME_MAX undefined)", - ] + ], }, { "version": "2.26.7", "date": "March 2026", "highlights": [ "Fix health check SDR detection on macOS (timeout command not available)", - ] + ], }, { "version": "2.26.6", "date": "March 2026", "highlights": [ "Fix oversized branded 'i' logo on Aircraft & Vessel dashboards", - ] + ], }, { "version": "2.26.5", "date": "March 2026", "highlights": [ "Fix database errors crashing the entire UI — pages now degrade gracefully", - ] + ], }, { "version": "2.26.4", "date": "March 2026", "highlights": [ "Fix Environment Configurator crash when .env exists but variable is missing", - ] + ], }, { "version": "2.26.3", "date": "March 2026", "highlights": [ "Fix SatDump AVX2 crash on older CPUs — build now targets baseline x86-64", - ] + ], }, { "version": "2.26.2", "date": "March 2026", "highlights": [ "Fix Docker startup crash — data/ Python package was excluded by .dockerignore", - ] + ], }, { "version": "2.26.1", @@ -93,7 +106,7 @@ CHANGELOG = [ "highlights": [ "Fix default admin credentials — now matches README (admin:admin)", "Admin password changes in config.py / env vars now sync to DB on restart", - ] + ], }, { "version": "2.26.0", @@ -101,7 +114,7 @@ CHANGELOG = [ "highlights": [ "Fix SSE fanout thread crash when source queue is None during shutdown", "Fix branded 'i' logo FOUC (flash of unstyled content) on first page load", - ] + ], }, { "version": "2.25.0", @@ -112,7 +125,7 @@ CHANGELOG = [ "Destructive action confirmation modals replace native confirm() dialogs", "CSS variable adoption, inline style extraction, and reduced !important usage", "Loading button states, actionable error reporting, and mobile UX polish", - ] + ], }, { "version": "2.24.0", @@ -122,7 +135,7 @@ CHANGELOG = [ "Mobile navigation reorganized into labeled groups for better usability", "flask-limiter made optional for graceful degradation", "Radiosonde setup fix — missing semver dependency", - ] + ], }, { "version": "2.23.0", @@ -138,7 +151,7 @@ CHANGELOG = [ "GPS mode upgraded to textured 3D globe", "Destroy lifecycle added to all mode modules to prevent resource leaks", "Dozens of bug fixes across ADS-B, APRS, SSE, Morse, waterfall, and more", - ] + ], }, { "version": "2.22.3", @@ -149,7 +162,7 @@ CHANGELOG = [ "Waterfall monitor audio no longer takes minutes to start — playback detection now waits for real audio data instead of just the WAV header", "Waterfall monitor stop is now instant — audio pauses and UI updates immediately instead of waiting for backend cleanup", "Stopping the waterfall no longer shows a stale 'WebSocket closed before ready' message", - ] + ], }, { "version": "2.22.1", @@ -167,7 +180,7 @@ CHANGELOG = [ "WebSDR major overhaul with improved receiver management and audio streaming", "Documentation audit: fixed license, tool names, entry points, and SSTV decoder references", "Help modal updated with ACARS and VDL2 mode descriptions", - ] + ], }, { "version": "2.21.1", @@ -176,7 +189,7 @@ CHANGELOG = [ "BT Locate map first-load fix with render stabilization retries during initial mode open", "BT Locate trail restore optimization for faster startup when historical GPS points exist", "BT Locate mode-switch map invalidation timing fix to prevent delayed/blank map render", - ] + ], }, { "version": "2.21.0", @@ -188,7 +201,7 @@ CHANGELOG = [ "Bluetooth/WiFi runtime health fixes with BT Locate continuity and confidence improvements", "ADS-B/VDL2 streaming reliability upgrades for multi-client SSE fanout and remote decoding", "Analytics enhancements with operational insights and temporal pattern panels", - ] + ], }, { "version": "2.20.0", @@ -199,7 +212,7 @@ CHANGELOG = [ "HF band conditions, D-RAP absorption maps, aurora forecast, and solar imagery", "NOAA Space Weather Scales (G/S/R), flare probability, and active solar regions", "No SDR hardware required — all data from public APIs with server-side caching", - ] + ], }, { "version": "2.19.0", @@ -212,7 +225,7 @@ CHANGELOG = [ "Setup script overhauled for reliability and macOS compatibility", "GPS fix for preserving satellites across DOP-only SKY messages", "Fix gpsd deadlock causing GPS connect to hang", - ] + ], }, { "version": "2.18.0", @@ -224,7 +237,7 @@ CHANGELOG = [ "ADS-B: stale dump1090 process cleanup via PID file tracking", "GPS: error state indicator and UI refinements", "Proximity radar and signal card UI improvements", - ] + ], }, { "version": "2.17.0", @@ -234,7 +247,7 @@ CHANGELOG = [ "IRK auto-detection: extract Identity Resolving Keys from paired devices (macOS/Linux)", "GPS mode: real-time position tracking with live map, speed, altitude, and satellite info", "Bluetooth scanner lifecycle fix for bleak scan timeout tracking", - ] + ], }, { "version": "2.16.0", @@ -246,7 +259,7 @@ CHANGELOG = [ "Shared waterfall UI across SDR modes", "Listening post audio stuttering fix and SDR race condition fixes", "Multi-arch Docker build support (amd64 + arm64)", - ] + ], }, { "version": "2.15.0", @@ -258,7 +271,7 @@ CHANGELOG = [ "Real-time signal scope for pager, sensor, and SSTV modes", "USB-level device probe to prevent cryptic rtl_fm crashes", "SDR device lock-up fix from unreleased device registry on crash", - ] + ], }, { "version": "2.14.0", @@ -269,7 +282,7 @@ CHANGELOG = [ "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", @@ -281,7 +294,7 @@ CHANGELOG = [ "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", @@ -291,7 +304,7 @@ CHANGELOG = [ "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", @@ -302,7 +315,7 @@ CHANGELOG = [ "Real-time Doppler tracking for ISS SSTV reception", "TCP connection support for Meshtastic", "Shared observer location with auto-start options", - ] + ], }, { "version": "2.12.0", @@ -312,7 +325,7 @@ CHANGELOG = [ "GitHub update notifications for new releases", "Meshtastic QR code support and telemetry display", "New Space category with reorganized UI", - ] + ], }, { "version": "2.11.0", @@ -322,7 +335,7 @@ CHANGELOG = [ "Ubertooth One BLE scanning support", "Offline mode with bundled assets", "Settings modal with tile provider configuration", - ] + ], }, { "version": "2.10.0", @@ -332,7 +345,7 @@ CHANGELOG = [ "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", @@ -342,7 +355,7 @@ CHANGELOG = [ "Clickable score cards and device detail expansion", "RF scanning improvements with status feedback", "Root privilege check and warning display", - ] + ], }, { "version": "2.9.0", @@ -352,7 +365,7 @@ CHANGELOG = [ "TSCM baseline recording now captures device data", "Device identity engine integration for threat detection", "Welcome screen with mode selection", - ] + ], }, { "version": "2.8.0", @@ -362,20 +375,20 @@ CHANGELOG = [ "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) + 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))) + return int(os.environ.get(f"INTERCEPT_{key}", str(default))) except ValueError: return default @@ -383,134 +396,130 @@ def _get_env_int(key: str, default: int) -> int: 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))) + 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'): + val = os.environ.get(f"INTERCEPT_{key}", "").lower() + if val in ("true", "1", "yes", "on"): return True - if val in ('false', '0', 'no', 'off'): + if val in ("false", "0", "no", "off"): return False return default # Logging configuration -_log_level_str = _get_env('LOG_LEVEL', 'WARNING').upper() +_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') +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) +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) # HTTPS / SSL settings -HTTPS = _get_env_bool('HTTPS', False) -SSL_CERT = _get_env('SSL_CERT', '') -SSL_KEY = _get_env('SSL_KEY', '') +HTTPS = _get_env_bool("HTTPS", False) +SSL_CERT = _get_env("SSL_CERT", "") +SSL_KEY = _get_env("SSL_KEY", "") # Default RTL-SDR settings -DEFAULT_GAIN = _get_env('DEFAULT_GAIN', '40') -DEFAULT_DEVICE = _get_env('DEFAULT_DEVICE', '0') +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') +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) +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) +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) +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) +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) +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) +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', 30.0) -WEATHER_SAT_SAMPLE_RATE = _get_env_int('WEATHER_SAT_SAMPLE_RATE', 2400000) -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) +WEATHER_SAT_DEFAULT_GAIN = _get_env_float("WEATHER_SAT_GAIN", 30.0) +WEATHER_SAT_SAMPLE_RATE = _get_env_int("WEATHER_SAT_SAMPLE_RATE", 2400000) +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) # WeFax (Weather Fax) settings -WEFAX_DEFAULT_GAIN = _get_env_float('WEFAX_GAIN', 40.0) -WEFAX_SAMPLE_RATE = _get_env_int('WEFAX_SAMPLE_RATE', 22050) -WEFAX_DEFAULT_IOC = _get_env_int('WEFAX_IOC', 576) -WEFAX_DEFAULT_LPM = _get_env_int('WEFAX_LPM', 120) -WEFAX_SCHEDULE_REFRESH_MINUTES = _get_env_int('WEFAX_SCHEDULE_REFRESH_MINUTES', 30) -WEFAX_CAPTURE_BUFFER_SECONDS = _get_env_int('WEFAX_CAPTURE_BUFFER_SECONDS', 30) +WEFAX_DEFAULT_GAIN = _get_env_float("WEFAX_GAIN", 40.0) +WEFAX_SAMPLE_RATE = _get_env_int("WEFAX_SAMPLE_RATE", 22050) +WEFAX_DEFAULT_IOC = _get_env_int("WEFAX_IOC", 576) +WEFAX_DEFAULT_LPM = _get_env_int("WEFAX_LPM", 120) +WEFAX_SCHEDULE_REFRESH_MINUTES = _get_env_int("WEFAX_SCHEDULE_REFRESH_MINUTES", 30) +WEFAX_CAPTURE_BUFFER_SECONDS = _get_env_int("WEFAX_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) +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) # Radiosonde settings -RADIOSONDE_FREQ_MIN = _get_env_float('RADIOSONDE_FREQ_MIN', 400.0) -RADIOSONDE_FREQ_MAX = _get_env_float('RADIOSONDE_FREQ_MAX', 406.0) -RADIOSONDE_DEFAULT_GAIN = _get_env_float('RADIOSONDE_GAIN', 40.0) -RADIOSONDE_UDP_PORT = _get_env_int('RADIOSONDE_UDP_PORT', 55673) +RADIOSONDE_FREQ_MIN = _get_env_float("RADIOSONDE_FREQ_MIN", 400.0) +RADIOSONDE_FREQ_MAX = _get_env_float("RADIOSONDE_FREQ_MAX", 406.0) +RADIOSONDE_DEFAULT_GAIN = _get_env_float("RADIOSONDE_GAIN", 40.0) +RADIOSONDE_UDP_PORT = _get_env_int("RADIOSONDE_UDP_PORT", 55673) # 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) +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) +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') +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 - ) + logging.basicConfig(level=LOG_LEVEL, format=LOG_FORMAT, stream=sys.stderr) # Suppress Flask development server warning - logging.getLogger('werkzeug').setLevel(LOG_LEVEL) + logging.getLogger("werkzeug").setLevel(LOG_LEVEL) diff --git a/pyproject.toml b/pyproject.toml index 238b96e..97c476c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "intercept" -version = "2.26.11" +version = "2.27.0" description = "Signal Intelligence Platform - Pager/433MHz/ADS-B/Satellite/WiFi/Bluetooth" readme = "README.md" requires-python = ">=3.9"