mirror of
https://github.com/smittix/intercept.git
synced 2026-07-08 01:28:13 -07:00
Improve WiFi device identification, remove signal history, fix Listen button
- WiFi interfaces now show driver, chipset, and MAC address for easier identification - Remove signal history feature from WiFi and Bluetooth sections (HTML, JS, CSS, API) - Fix Listen button in Listening Post signal hits to properly tune to frequency - Make stopAudio() async and improve tuneToFrequency() with proper awaits - Fix Device Intelligence panel auto-expand and manufacturer display Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,6 @@ from utils.database import (
|
||||
set_setting,
|
||||
delete_setting,
|
||||
get_all_settings,
|
||||
get_signal_history,
|
||||
add_signal_reading,
|
||||
get_correlations,
|
||||
)
|
||||
from utils.logging import get_logger
|
||||
@@ -145,66 +143,6 @@ def delete_single_setting(key: str) -> Response:
|
||||
}), 500
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Signal History Endpoints
|
||||
# =============================================================================
|
||||
|
||||
@settings_bp.route('/signal-history/<mode>/<device_id>', methods=['GET'])
|
||||
def get_device_signal_history(mode: str, device_id: str) -> Response:
|
||||
"""Get signal strength history for a device."""
|
||||
limit = request.args.get('limit', 100, type=int)
|
||||
since_minutes = request.args.get('since', 60, type=int)
|
||||
|
||||
# Validate mode
|
||||
valid_modes = ['wifi', 'bluetooth', 'adsb', 'pager', 'sensor']
|
||||
if mode not in valid_modes:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': f'Invalid mode. Valid modes: {valid_modes}'
|
||||
}), 400
|
||||
|
||||
try:
|
||||
history = get_signal_history(mode, device_id, limit, since_minutes)
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'mode': mode,
|
||||
'device_id': device_id,
|
||||
'history': history
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting signal history: {e}")
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': str(e)
|
||||
}), 500
|
||||
|
||||
|
||||
@settings_bp.route('/signal-history', methods=['POST'])
|
||||
def add_signal_history() -> Response:
|
||||
"""Add a signal strength reading (for internal use)."""
|
||||
data = request.json or {}
|
||||
|
||||
mode = data.get('mode')
|
||||
device_id = data.get('device_id')
|
||||
signal_strength = data.get('signal_strength')
|
||||
|
||||
if not all([mode, device_id, signal_strength is not None]):
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': 'mode, device_id, and signal_strength are required'
|
||||
}), 400
|
||||
|
||||
try:
|
||||
add_signal_reading(mode, device_id, signal_strength, data.get('metadata'))
|
||||
return jsonify({'status': 'success'})
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding signal reading: {e}")
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': str(e)
|
||||
}), 500
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Device Correlation Endpoints
|
||||
# =============================================================================
|
||||
|
||||
+71
-6
@@ -105,12 +105,18 @@ def detect_wifi_interfaces():
|
||||
current_iface = line.split()[1]
|
||||
elif current_iface and 'type' in line:
|
||||
iface_type = line.split()[-1]
|
||||
interfaces.append({
|
||||
iface_info = {
|
||||
'name': current_iface,
|
||||
'type': iface_type,
|
||||
'monitor_capable': True,
|
||||
'status': 'up'
|
||||
})
|
||||
'status': 'up',
|
||||
'driver': '',
|
||||
'chipset': '',
|
||||
'mac': ''
|
||||
}
|
||||
# Get additional interface details
|
||||
iface_info.update(_get_interface_details(current_iface))
|
||||
interfaces.append(iface_info)
|
||||
current_iface = None
|
||||
except FileNotFoundError:
|
||||
# Fall back to iwconfig if iw is not available
|
||||
@@ -119,12 +125,17 @@ def detect_wifi_interfaces():
|
||||
for line in result.stdout.split('\n'):
|
||||
if 'IEEE 802.11' in line:
|
||||
iface = line.split()[0]
|
||||
interfaces.append({
|
||||
iface_info = {
|
||||
'name': iface,
|
||||
'type': 'managed',
|
||||
'monitor_capable': True,
|
||||
'status': 'up'
|
||||
})
|
||||
'status': 'up',
|
||||
'driver': '',
|
||||
'chipset': '',
|
||||
'mac': ''
|
||||
}
|
||||
iface_info.update(_get_interface_details(iface))
|
||||
interfaces.append(iface_info)
|
||||
except FileNotFoundError:
|
||||
logger.debug("Neither iw nor iwconfig found")
|
||||
except subprocess.SubprocessError as e:
|
||||
@@ -137,6 +148,60 @@ def detect_wifi_interfaces():
|
||||
return interfaces
|
||||
|
||||
|
||||
def _get_interface_details(iface_name):
|
||||
"""Get additional details about a WiFi interface (driver, chipset, MAC)."""
|
||||
details = {'driver': '', 'chipset': '', 'mac': ''}
|
||||
|
||||
# Get MAC address
|
||||
try:
|
||||
mac_path = f'/sys/class/net/{iface_name}/address'
|
||||
with open(mac_path, 'r') as f:
|
||||
details['mac'] = f.read().strip().upper()
|
||||
except (FileNotFoundError, IOError):
|
||||
pass
|
||||
|
||||
# Get driver name
|
||||
try:
|
||||
driver_link = f'/sys/class/net/{iface_name}/device/driver'
|
||||
import os
|
||||
if os.path.islink(driver_link):
|
||||
driver_path = os.readlink(driver_link)
|
||||
details['driver'] = os.path.basename(driver_path)
|
||||
except (FileNotFoundError, IOError, OSError):
|
||||
pass
|
||||
|
||||
# Get chipset info from USB or PCI
|
||||
try:
|
||||
# Check if USB device
|
||||
device_path = f'/sys/class/net/{iface_name}/device'
|
||||
import os
|
||||
if os.path.exists(device_path):
|
||||
# Try to get USB product name
|
||||
for usb_path in [f'{device_path}/product', f'{device_path}/../product']:
|
||||
try:
|
||||
with open(usb_path, 'r') as f:
|
||||
details['chipset'] = f.read().strip()
|
||||
break
|
||||
except (FileNotFoundError, IOError):
|
||||
pass
|
||||
|
||||
# If no USB product, try to get from uevent
|
||||
if not details['chipset']:
|
||||
try:
|
||||
uevent_path = f'{device_path}/uevent'
|
||||
with open(uevent_path, 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('PCI_ID=') or line.startswith('PRODUCT='):
|
||||
details['chipset'] = line.split('=')[1].strip()
|
||||
break
|
||||
except (FileNotFoundError, IOError):
|
||||
pass
|
||||
except (FileNotFoundError, IOError, OSError):
|
||||
pass
|
||||
|
||||
return details
|
||||
|
||||
|
||||
def parse_airodump_csv(csv_path):
|
||||
"""Parse airodump-ng CSV output file."""
|
||||
networks = {}
|
||||
|
||||
Reference in New Issue
Block a user