From 6010c7d5897c2c40bfc244346a218d842143acd6 Mon Sep 17 00:00:00 2001 From: Smittix Date: Sun, 8 Feb 2026 17:28:54 +0000 Subject: [PATCH] Add scan progress to frontend, fix Europe band defaults - Forward scanner progress (%) and status to SSE stream - Show progress bar and scan status in TRACKED TOWERS panel - Send scan_complete event with tower count and duration - Fix Europe BAND_CONFIG: only EGSM900 is recommended (GSM850/GSM800 are rarely used in Europe and waste scan time) - DCS1800 available but not recommended (RTL-SDR sensitivity is lower) Co-Authored-By: Claude Opus 4.6 --- routes/gsm_spy.py | 36 +++++++++++++++++++++++++++- templates/gsm_spy_dashboard.html | 40 +++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/routes/gsm_spy.py b/routes/gsm_spy.py index 4b24c21..4acbb01 100644 --- a/routes/gsm_spy.py +++ b/routes/gsm_spy.py @@ -1312,7 +1312,30 @@ def scanner_thread(cmd, device_index): break # EOF last_output = time.time() - logger.info(f"Scanner [{msg_type}]: {line.strip()}") + stripped = line.strip() + logger.info(f"Scanner [{msg_type}]: {stripped}") + + # Forward progress and status info to frontend + progress_match = re.match(r'Scanning:\s+([\d.]+)%\s+done', stripped) + if progress_match: + try: + app_module.gsm_spy_queue.put_nowait({ + 'type': 'progress', + 'percent': float(progress_match.group(1)), + 'scan': scan_count + }) + except queue.Full: + pass + continue + if stripped.startswith('Try scan CCCH'): + try: + app_module.gsm_spy_queue.put_nowait({ + 'type': 'status', + 'message': stripped, + 'scan': scan_count + }) + except queue.Full: + pass parsed = parse_grgsm_scanner_output(line) if parsed: @@ -1375,6 +1398,17 @@ def scanner_thread(cmd, device_index): scan_duration = time.time() - scan_start logger.info(f"Scan #{scan_count} complete (exit code: {exit_code}, duration: {scan_duration:.1f}s)") + # Notify frontend scan completed + try: + app_module.gsm_spy_queue.put_nowait({ + 'type': 'scan_complete', + 'scan': scan_count, + 'duration': round(scan_duration, 1), + 'towers_found': gsm_towers_found + }) + except queue.Full: + pass + # Detect crash pattern: process exits too quickly with no data if scan_duration < 5 and exit_code != 0: crash_count += 1 diff --git a/templates/gsm_spy_dashboard.html b/templates/gsm_spy_dashboard.html index 8d568ac..36af50e 100644 --- a/templates/gsm_spy_dashboard.html +++ b/templates/gsm_spy_dashboard.html @@ -1240,6 +1240,15 @@ TRACKED TOWERS
+
No towers detected
@@ -1344,9 +1353,9 @@ const BAND_CONFIG = { 'Europe': [ { name: 'EGSM900', label: 'EGSM900 (925-960 MHz)', freq: '925-960 MHz', common: true, recommended: true }, - { name: 'GSM850', label: 'GSM850 (869-894 MHz)', freq: '869-894 MHz', common: true, recommended: true }, - { name: 'GSM800', label: 'GSM800 (832-862 MHz)', freq: '832-862 MHz', common: true, recommended: true }, - { name: 'DCS1800', label: 'DCS1800 (1805-1880 MHz)', freq: '1805-1880 MHz', common: false, recommended: false } + { name: 'DCS1800', label: 'DCS1800 (1805-1880 MHz)', freq: '1805-1880 MHz', common: true, recommended: false }, + { name: 'GSM850', label: 'GSM850 (869-894 MHz)', freq: '869-894 MHz', common: false, recommended: false }, + { name: 'GSM800', label: 'GSM800 (832-862 MHz)', freq: '832-862 MHz', common: false, recommended: false } ], 'Americas': [ { name: 'GSM850', label: 'GSM850 (869-894 MHz)', freq: '869-894 MHz', common: true, recommended: true }, @@ -1588,6 +1597,7 @@ eventSource.close(); eventSource = null; } + document.getElementById('scanProgress').style.display = 'none'; console.log('[GSM SPY] Scanner stopped'); }) .catch(error => { @@ -1653,8 +1663,16 @@ addRogueAlert(data); } else if (data.type === 'stats') { updateStats(data); + } else if (data.type === 'progress') { + updateScanProgress(data.percent, data.scan); + } else if (data.type === 'status') { + updateScanStatus(data.message); + } else if (data.type === 'scan_complete') { + updateScanStatus('Scan #' + data.scan + ' complete (' + data.towers_found + ' towers, ' + data.duration + 's)'); + document.getElementById('scanProgressBar').style.width = '100%'; } else if (data.type === 'error') { console.error('[GSM SPY] Server error:', data.message); + updateScanStatus('Error: ' + data.message); } else if (data.type === 'disconnected') { console.warn('[GSM SPY] Server disconnected stream'); } @@ -1896,6 +1914,22 @@ } } + function updateScanProgress(percent, scanNum) { + const progressDiv = document.getElementById('scanProgress'); + const bar = document.getElementById('scanProgressBar'); + const text = document.getElementById('scanPercentText'); + progressDiv.style.display = 'block'; + bar.style.width = percent + '%'; + text.textContent = Math.round(percent) + '% (Scan #' + scanNum + ')'; + } + + function updateScanStatus(message) { + const progressDiv = document.getElementById('scanProgress'); + const statusText = document.getElementById('scanStatusText'); + progressDiv.style.display = 'block'; + statusText.textContent = message; + } + function updateTowersList() { const listDiv = document.getElementById('towersList'); const towerCount = Object.keys(towers).length;