diff --git a/routes/tscm.py b/routes/tscm.py index 518af75..3aa38f9 100644 --- a/routes/tscm.py +++ b/routes/tscm.py @@ -368,25 +368,21 @@ def _check_available_devices(wifi: bool, bt: bool, rf: bool) -> dict: # Check WiFi if wifi: if platform.system() == 'Darwin': - # macOS: Check for airport utility - airport_path = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport' - if os.path.exists(airport_path): - try: - result = subprocess.run( - [airport_path, '-I'], - capture_output=True, - text=True, - timeout=5 - ) - if result.returncode == 0: - available['wifi'] = True - available['wifi_reason'] = 'macOS WiFi available' - else: - available['wifi_reason'] = 'WiFi interface not active' - except (subprocess.TimeoutExpired, subprocess.SubprocessError): - available['wifi_reason'] = 'Cannot access WiFi interface' - else: - available['wifi_reason'] = 'macOS airport utility not found' + # macOS: Use networksetup to detect WiFi interfaces (same as /tscm/devices endpoint) + try: + result = subprocess.run( + ['networksetup', '-listallhardwareports'], + capture_output=True, + text=True, + timeout=5 + ) + if result.returncode == 0 and ('Wi-Fi' in result.stdout or 'AirPort' in result.stdout): + available['wifi'] = True + available['wifi_reason'] = 'macOS WiFi available' + else: + available['wifi_reason'] = 'No WiFi hardware port found' + except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError): + available['wifi_reason'] = 'Cannot detect WiFi interfaces' else: # Linux: Check for wireless tools if shutil.which('airodump-ng') or shutil.which('iwlist') or shutil.which('iw'): @@ -1981,8 +1977,8 @@ def _run_sweep( time.sleep(2) # Update every 2 seconds - # Complete sweep - if _sweep_running and _current_sweep_id: + # Complete sweep (run even if stopped by user so correlations/clusters are computed) + if _current_sweep_id: # Run cross-protocol correlation analysis correlations = correlation.correlate_devices() findings = correlation.get_all_findings() diff --git a/static/css/modes/tscm.css b/static/css/modes/tscm.css index 89f1153..0335c0c 100644 --- a/static/css/modes/tscm.css +++ b/static/css/modes/tscm.css @@ -69,11 +69,6 @@ min-height: 200px; height: 200px; } -/* Full-width panels (like Detected Threats) get more height */ -.tscm-panel[style*="grid-column: span 2"] { - min-height: 150px; - height: 150px; -} .tscm-panel-header { padding: 10px 12px; background: rgba(0,0,0,0.3); diff --git a/templates/index.html b/templates/index.html index 7aeed4e..7fa8171 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1557,7 +1557,7 @@ -
+
Detected Threats 0 diff --git a/utils/tscm/advanced.py b/utils/tscm/advanced.py index a0b12e9..b36efd1 100644 --- a/utils/tscm/advanced.py +++ b/utils/tscm/advanced.py @@ -372,8 +372,10 @@ def _detect_rf_capabilities(caps: SweepCapabilities, sdr_device: Any) -> None: if devices: device = devices[0] # Use first device rf_cap.available = True - rf_cap.device_type = device.get('type', 'unknown') - rf_cap.driver = device.get('driver', '') + rf_cap.device_type = getattr(device, 'sdr_type', 'unknown') + if hasattr(rf_cap.device_type, 'value'): + rf_cap.device_type = rf_cap.device_type.value + rf_cap.driver = getattr(device, 'driver', '') # Set frequency ranges based on device type if 'rtl' in rf_cap.device_type.lower():