mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Remove Iridium (demo-only) and add version display
- Remove Iridium satellite decoding feature (was placeholder/demo only) - Delete routes/iridium.py - Remove Iridium UI elements from index.html - Remove Iridium CSS styles - Remove Iridium dependencies and logger - Clean up SDR docstrings mentioning Iridium - Add version number display (fixes #31) - Add VERSION constant to config.py - Add --version / -V CLI flag to intercept.py - Display version badge in web UI header
This commit is contained in:
4
app.py
4
app.py
@@ -25,6 +25,7 @@ from typing import Any
|
||||
|
||||
from flask import Flask, render_template, jsonify, send_file, Response, request
|
||||
|
||||
from config import VERSION
|
||||
from utils.dependencies import check_tool, check_all_dependencies, TOOL_DEPENDENCIES
|
||||
from utils.process import cleanup_stale_processes
|
||||
from utils.sdr import SDRFactory
|
||||
@@ -91,7 +92,6 @@ bt_services = {} # MAC -> list of services
|
||||
adsb_aircraft = {} # ICAO hex -> aircraft info
|
||||
|
||||
# Satellite state
|
||||
iridium_bursts = [] # List of detected Iridium bursts
|
||||
satellite_passes = [] # Predicted satellite passes
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ def index() -> str:
|
||||
'rtl_433': check_tool('rtl_433')
|
||||
}
|
||||
devices = [d.to_dict() for d in SDRFactory.detect_devices()]
|
||||
return render_template('index.html', tools=tools, devices=devices)
|
||||
return render_template('index.html', tools=tools, devices=devices, version=VERSION)
|
||||
|
||||
|
||||
@app.route('/favicon.svg')
|
||||
|
||||
10
config.py
10
config.py
@@ -6,6 +6,9 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Application version
|
||||
VERSION = "1.0.0"
|
||||
|
||||
|
||||
def _get_env(key: str, default: str) -> str:
|
||||
"""Get environment variable with default."""
|
||||
@@ -56,10 +59,6 @@ DEFAULT_DEVICE = _get_env('DEFAULT_DEVICE', '0')
|
||||
# Pager defaults
|
||||
DEFAULT_PAGER_FREQ = _get_env('PAGER_FREQ', '929.6125M')
|
||||
|
||||
# Iridium defaults
|
||||
DEFAULT_IRIDIUM_FREQ = _get_env('IRIDIUM_FREQ', '1626.0')
|
||||
DEFAULT_IRIDIUM_SAMPLE_RATE = _get_env('IRIDIUM_SAMPLE_RATE', '2.048e6')
|
||||
|
||||
# Timeouts
|
||||
PROCESS_TIMEOUT = _get_env_int('PROCESS_TIMEOUT', 5)
|
||||
SOCKET_TIMEOUT = _get_env_int('SOCKET_TIMEOUT', 5)
|
||||
@@ -82,9 +81,6 @@ 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)
|
||||
|
||||
# Maximum burst count for Iridium monitoring
|
||||
IRIDIUM_MAX_BURSTS = _get_env_int('IRIDIUM_MAX_BURSTS', 100)
|
||||
|
||||
|
||||
def configure_logging() -> None:
|
||||
"""Configure application logging."""
|
||||
|
||||
@@ -41,7 +41,6 @@ Complete feature list for all modules.
|
||||
- **Celestrak integration** - fetch by category (Amateur, Weather, ISS, Starlink, etc.)
|
||||
- **Next pass countdown** - time remaining, visibility duration, max elevation
|
||||
- **Telemetry panel** - real-time azimuth, elevation, range, velocity
|
||||
- **Iridium burst detection** monitoring (demo mode)
|
||||
- **Multiple satellite tracking** simultaneously
|
||||
|
||||
## WiFi Reconnaissance
|
||||
|
||||
@@ -90,7 +90,6 @@ The system highlights aircraft transmitting emergency squawks:
|
||||
4. **View Sky Plot** - Polar plot shows satellite positions in real-time
|
||||
5. **Ground Track** - Map displays satellite orbit path and current position
|
||||
6. **Full Dashboard** - Click "Full Screen Dashboard" for dedicated satellite view
|
||||
7. **Iridium Mode** - Switch tabs to monitor for Iridium burst transmissions
|
||||
|
||||
### Adding Satellites from Celestrak
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ A comprehensive signal intelligence tool featuring:
|
||||
- Pager decoding (POCSAG/FLEX)
|
||||
- 433MHz sensor monitoring
|
||||
- ADS-B aircraft tracking with WarGames-style display
|
||||
- Satellite pass prediction and Iridium burst detection
|
||||
- Satellite pass prediction
|
||||
- WiFi reconnaissance and drone detection
|
||||
- Bluetooth scanning
|
||||
|
||||
@@ -25,6 +25,12 @@ if sys.version_info < (3, 9):
|
||||
print(" - Or use pyenv to install a newer version")
|
||||
sys.exit(1)
|
||||
|
||||
# Handle --version early before other imports
|
||||
if '--version' in sys.argv or '-V' in sys.argv:
|
||||
from config import VERSION
|
||||
print(f"INTERCEPT v{VERSION}")
|
||||
sys.exit(0)
|
||||
|
||||
import site
|
||||
|
||||
# Ensure user site-packages is available (may be disabled when running as root/sudo)
|
||||
|
||||
@@ -8,7 +8,6 @@ def register_blueprints(app):
|
||||
from .bluetooth import bluetooth_bp
|
||||
from .adsb import adsb_bp
|
||||
from .satellite import satellite_bp
|
||||
from .iridium import iridium_bp
|
||||
from .gps import gps_bp
|
||||
|
||||
app.register_blueprint(pager_bp)
|
||||
@@ -17,5 +16,4 @@ def register_blueprints(app):
|
||||
app.register_blueprint(bluetooth_bp)
|
||||
app.register_blueprint(adsb_bp)
|
||||
app.register_blueprint(satellite_bp)
|
||||
app.register_blueprint(iridium_bp)
|
||||
app.register_blueprint(gps_bp)
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
"""Iridium monitoring routes.
|
||||
|
||||
NOTE: This module is currently in DEMO MODE. The burst detection generates
|
||||
simulated data for demonstration purposes. Real Iridium decoding requires
|
||||
gr-iridium or iridium-toolkit which are not yet integrated.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import queue
|
||||
import random
|
||||
import shutil
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Any, Generator
|
||||
|
||||
from flask import Blueprint, jsonify, request, Response
|
||||
|
||||
import app as app_module
|
||||
from utils.logging import iridium_logger as logger
|
||||
from utils.validation import validate_frequency, validate_device_index, validate_gain
|
||||
from utils.sse import format_sse
|
||||
from utils.sdr import SDRFactory, SDRType
|
||||
|
||||
iridium_bp = Blueprint('iridium', __name__, url_prefix='/iridium')
|
||||
|
||||
# Flag indicating this is demo mode (simulated data)
|
||||
DEMO_MODE = True
|
||||
|
||||
|
||||
def monitor_iridium(process):
|
||||
"""
|
||||
Monitor Iridium capture and detect bursts.
|
||||
|
||||
NOTE: Currently generates SIMULATED data for demonstration.
|
||||
Real Iridium decoding is not yet implemented.
|
||||
"""
|
||||
try:
|
||||
burst_count = 0
|
||||
# Send initial demo mode warning
|
||||
app_module.satellite_queue.put({
|
||||
'type': 'info',
|
||||
'message': '⚠️ DEMO MODE: Generating simulated Iridium bursts for demonstration'
|
||||
})
|
||||
|
||||
while process.poll() is None:
|
||||
data = process.stdout.read(1024)
|
||||
if data:
|
||||
if len(data) > 0 and burst_count < 100:
|
||||
# DEMO: Generate simulated bursts (1% chance per read)
|
||||
if random.random() < 0.01:
|
||||
burst = {
|
||||
'type': 'burst',
|
||||
'demo': True, # Flag as demo data
|
||||
'time': datetime.now().strftime('%H:%M:%S.%f')[:-3],
|
||||
'frequency': f"{1616 + random.random() * 10:.3f}",
|
||||
'data': f"[SIMULATED] Frame data - Burst #{burst_count + 1}"
|
||||
}
|
||||
app_module.satellite_queue.put(burst)
|
||||
app_module.iridium_bursts.append(burst)
|
||||
burst_count += 1
|
||||
|
||||
time.sleep(0.1)
|
||||
except Exception as e:
|
||||
logger.error(f"Monitor error: {e}")
|
||||
|
||||
|
||||
@iridium_bp.route('/tools')
|
||||
def check_iridium_tools():
|
||||
"""Check for Iridium decoding tools."""
|
||||
has_iridium = shutil.which('iridium-extractor') is not None or shutil.which('iridium-parser') is not None
|
||||
has_rtl = shutil.which('rtl_fm') is not None
|
||||
return jsonify({
|
||||
'available': has_iridium or has_rtl,
|
||||
'demo_mode': DEMO_MODE,
|
||||
'message': 'Demo mode active - generating simulated data' if DEMO_MODE else None
|
||||
})
|
||||
|
||||
|
||||
@iridium_bp.route('/start', methods=['POST'])
|
||||
def start_iridium():
|
||||
"""Start Iridium burst capture (DEMO MODE - simulated data)."""
|
||||
with app_module.satellite_lock:
|
||||
if app_module.satellite_process and app_module.satellite_process.poll() is None:
|
||||
return jsonify({'status': 'error', 'message': 'Iridium capture already running'}), 409
|
||||
|
||||
data = request.json or {}
|
||||
|
||||
# Validate inputs
|
||||
try:
|
||||
freq = validate_frequency(data.get('freq', '1626.0'), min_mhz=1610.0, max_mhz=1650.0)
|
||||
gain = validate_gain(data.get('gain', '40'))
|
||||
device = validate_device_index(data.get('device', '0'))
|
||||
except ValueError as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
||||
|
||||
sample_rate = data.get('sampleRate', '2.048e6')
|
||||
# Validate sample rate format
|
||||
try:
|
||||
float(sample_rate.replace('e', 'E'))
|
||||
except (ValueError, AttributeError):
|
||||
return jsonify({'status': 'error', 'message': 'Invalid sample rate format'}), 400
|
||||
|
||||
# Get SDR type from request
|
||||
sdr_type_str = data.get('sdr_type', 'rtlsdr')
|
||||
try:
|
||||
sdr_type = SDRType(sdr_type_str)
|
||||
except ValueError:
|
||||
sdr_type = SDRType.RTL_SDR
|
||||
|
||||
# Check for required tools based on SDR type
|
||||
if sdr_type == SDRType.RTL_SDR:
|
||||
if not shutil.which('iridium-extractor') and not shutil.which('rtl_fm'):
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': 'Iridium tools not found. Requires rtl_fm or iridium-extractor.'
|
||||
}), 503
|
||||
else:
|
||||
if not shutil.which('rx_fm'):
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': f'rx_fm not found for {sdr_type.value}. Install SoapySDR tools.'
|
||||
}), 503
|
||||
|
||||
try:
|
||||
# Create device object and build command via abstraction layer
|
||||
sdr_device = SDRFactory.create_default_device(sdr_type, index=device)
|
||||
builder = SDRFactory.get_builder(sdr_type)
|
||||
|
||||
# Parse sample rate
|
||||
sample_rate_hz = int(float(sample_rate))
|
||||
|
||||
# Build FM demodulation command
|
||||
cmd = builder.build_fm_demod_command(
|
||||
device=sdr_device,
|
||||
frequency_mhz=float(freq),
|
||||
sample_rate=sample_rate_hz,
|
||||
gain=float(gain),
|
||||
ppm=None,
|
||||
modulation='fm',
|
||||
squelch=None
|
||||
)
|
||||
|
||||
app_module.satellite_process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
thread = threading.Thread(target=monitor_iridium, args=(app_module.satellite_process,), daemon=True)
|
||||
thread.start()
|
||||
|
||||
return jsonify({
|
||||
'status': 'started',
|
||||
'demo_mode': DEMO_MODE,
|
||||
'message': 'Demo mode active - data is simulated' if DEMO_MODE else None
|
||||
})
|
||||
except FileNotFoundError as e:
|
||||
logger.error(f"Tool not found: {e}")
|
||||
return jsonify({'status': 'error', 'message': f'Tool not found: {e.filename}'}), 503
|
||||
except Exception as e:
|
||||
logger.error(f"Start error: {e}")
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
|
||||
@iridium_bp.route('/stop', methods=['POST'])
|
||||
def stop_iridium():
|
||||
"""Stop Iridium capture."""
|
||||
with app_module.satellite_lock:
|
||||
if app_module.satellite_process:
|
||||
app_module.satellite_process.terminate()
|
||||
try:
|
||||
app_module.satellite_process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
app_module.satellite_process.kill()
|
||||
app_module.satellite_process = None
|
||||
|
||||
return jsonify({'status': 'stopped'})
|
||||
|
||||
|
||||
@iridium_bp.route('/stream')
|
||||
def stream_iridium():
|
||||
"""SSE stream for Iridium bursts."""
|
||||
def generate():
|
||||
last_keepalive = time.time()
|
||||
keepalive_interval = 30.0
|
||||
|
||||
while True:
|
||||
try:
|
||||
msg = app_module.satellite_queue.get(timeout=1)
|
||||
last_keepalive = time.time()
|
||||
yield format_sse(msg)
|
||||
except queue.Empty:
|
||||
now = time.time()
|
||||
if now - last_keepalive >= keepalive_interval:
|
||||
yield format_sse({'type': 'keepalive'})
|
||||
last_keepalive = now
|
||||
|
||||
response = Response(generate(), mimetype='text/event-stream')
|
||||
response.headers['Cache-Control'] = 'no-cache'
|
||||
response.headers['X-Accel-Buffering'] = 'no'
|
||||
return response
|
||||
@@ -96,6 +96,16 @@ header h1 {
|
||||
text-shadow: 0 0 30px var(--accent-cyan-dim);
|
||||
}
|
||||
|
||||
.version-badge {
|
||||
font-size: 0.35em;
|
||||
font-weight: 400;
|
||||
letter-spacing: 1px;
|
||||
color: var(--text-muted);
|
||||
vertical-align: middle;
|
||||
margin-left: 5px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
header p {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
@@ -2059,46 +2069,6 @@ header p {
|
||||
color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
/* Iridium Burst Styles */
|
||||
.iridium-warning {
|
||||
padding: 12px;
|
||||
margin-bottom: 15px;
|
||||
background: rgba(255, 102, 0, 0.1);
|
||||
border: 1px solid var(--accent-orange);
|
||||
border-radius: 4px;
|
||||
color: var(--accent-orange);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.iridium-warning strong {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.burst-card {
|
||||
padding: 10px;
|
||||
margin-bottom: 6px;
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-left: 3px solid #9370DB;
|
||||
font-family: monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.burst-time {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.burst-freq {
|
||||
color: #9370DB;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.burst-data {
|
||||
color: var(--text-primary);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Popout window styles */
|
||||
.popout-container {
|
||||
position: fixed;
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<path d="M50 88 L45 83 L50 83 Z" fill="#00d4ff"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1>INTERCEPT</h1>
|
||||
<h1>INTERCEPT <span class="version-badge">v{{ version }}</span></h1>
|
||||
<p>Signal Intelligence // by smittix <span class="active-mode-indicator" id="activeModeIndicator"><span class="pulse-dot"></span>PAGER</span></p>
|
||||
|
||||
<!-- Header Stats (mode-specific) -->
|
||||
@@ -814,8 +814,7 @@
|
||||
<div id="satelliteMode" class="mode-content">
|
||||
<a href="/satellite/dashboard" target="_blank" class="run-btn" style="display: block; text-align: center; text-decoration: none; margin-bottom: 15px;">Full Screen Dashboard</a>
|
||||
<div class="satellite-tabs">
|
||||
<button class="satellite-tab active" onclick="switchSatelliteTab('predictor')">🛰️ Pass Predictor</button>
|
||||
<button class="satellite-tab" onclick="switchSatelliteTab('iridium')">📡 Iridium</button>
|
||||
<button class="satellite-tab active">🛰️ Pass Predictor</button>
|
||||
</div>
|
||||
|
||||
<!-- Pass Predictor Sub-tab -->
|
||||
@@ -919,47 +918,6 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Iridium Sub-tab -->
|
||||
<div id="iridiumTab" class="satellite-content">
|
||||
<div class="iridium-warning">
|
||||
<strong>⚠️ Hardware Required</strong>
|
||||
Iridium burst detection requires:<br>
|
||||
• RTL-SDR dongle<br>
|
||||
• L-band patch antenna (1616-1626 MHz)<br>
|
||||
• Low Noise Amplifier (LNA)<br>
|
||||
• Clear view of sky
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Iridium Settings</h3>
|
||||
<div class="form-group">
|
||||
<label>Center Frequency (MHz)</label>
|
||||
<input type="text" id="iridiumFreq" value="1626.0" placeholder="1626.0">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Gain (dB)</label>
|
||||
<input type="text" id="iridiumGain" value="40" placeholder="40">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Sample Rate</label>
|
||||
<select id="iridiumSampleRate">
|
||||
<option value="2.4e6">2.4 MSPS</option>
|
||||
<option value="2.048e6" selected>2.048 MSPS</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-text" style="margin-bottom: 10px;" id="iridiumToolStatus">
|
||||
<span>iridium-extractor:</span> <span class="tool-status" id="iridiumExtractorStatus">Checking...</span>
|
||||
</div>
|
||||
|
||||
<button class="run-btn" id="startIridiumBtn" onclick="startIridiumCapture()">
|
||||
Start Capture
|
||||
</button>
|
||||
<button class="stop-btn" id="stopIridiumBtn" onclick="stopIridiumCapture()" style="display: none;">
|
||||
Stop Capture
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="preset-btn" onclick="killAll()" style="width: 100%; margin-top: 10px; border-color: #ff3366; color: #ff3366;">
|
||||
@@ -1005,7 +963,6 @@
|
||||
</div>
|
||||
<div class="stats" id="satelliteStats" style="display: none;">
|
||||
<div title="Upcoming Passes">🛰️ <span id="passCount">0</span></div>
|
||||
<div title="Iridium Bursts">📡 <span id="burstCount">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1248,20 +1205,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Iridium Burst Log -->
|
||||
<div id="iridiumBurstLog" style="display: none; margin-top: 15px;">
|
||||
<div class="pass-list-container">
|
||||
<div class="pass-list-header">
|
||||
<span>Iridium Burst Log</span>
|
||||
<button class="preset-btn" onclick="clearIridiumLog()" style="padding: 2px 8px; font-size: 10px;">Clear</button>
|
||||
</div>
|
||||
<div id="burstList">
|
||||
<div style="color: #666; text-align: center; padding: 30px; font-size: 11px;">
|
||||
Iridium bursts will appear here when detected.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Satellite Popout Container -->
|
||||
@@ -1435,7 +1378,6 @@
|
||||
let isRunning = false;
|
||||
let isSensorRunning = false;
|
||||
let isAdsbRunning = false;
|
||||
let isIridiumRunning = false;
|
||||
let isWifiRunning = false;
|
||||
let isBtRunning = false;
|
||||
let currentMode = 'pager';
|
||||
@@ -1492,7 +1434,6 @@
|
||||
|
||||
// Satellite stats
|
||||
document.getElementById('headerPassCount').textContent = document.getElementById('passCount')?.textContent || '0';
|
||||
document.getElementById('headerBurstCount').textContent = document.getElementById('burstCount')?.textContent || '0';
|
||||
}
|
||||
// Sync stats periodically
|
||||
setInterval(syncHeaderStats, 500);
|
||||
@@ -1717,8 +1658,6 @@
|
||||
let satellitePasses = [];
|
||||
let selectedPass = null;
|
||||
let selectedPassIndex = 0;
|
||||
let iridiumBursts = [];
|
||||
let iridiumEventSource = null;
|
||||
let countdownInterval = null;
|
||||
|
||||
// Start satellite countdown timer
|
||||
@@ -1857,7 +1796,6 @@
|
||||
if (isWifiRunning) stopWifiScan();
|
||||
if (isBtRunning) stopBtScan();
|
||||
if (isAdsbRunning) stopAdsbScan();
|
||||
if (isIridiumRunning) stopIridiumCapture();
|
||||
|
||||
currentMode = mode;
|
||||
document.querySelectorAll('.mode-tab').forEach(tab => {
|
||||
@@ -1958,7 +1896,6 @@
|
||||
} else if (mode === 'satellite') {
|
||||
initPolarPlot();
|
||||
initSatelliteList();
|
||||
checkIridiumTools();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6234,16 +6171,6 @@
|
||||
// SATELLITE MODE FUNCTIONS
|
||||
// ============================================
|
||||
|
||||
function switchSatelliteTab(tab) {
|
||||
document.querySelectorAll('.satellite-tab').forEach(t => t.classList.remove('active'));
|
||||
document.querySelectorAll('.satellite-content').forEach(c => c.classList.remove('active'));
|
||||
document.querySelector(`.satellite-tab:nth-child(${tab === 'predictor' ? 1 : 2})`).classList.add('active');
|
||||
document.getElementById(tab === 'predictor' ? 'predictorTab' : 'iridiumTab').classList.add('active');
|
||||
|
||||
// Toggle Iridium burst log visibility
|
||||
document.getElementById('iridiumBurstLog').style.display = tab === 'iridium' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function getLocation() {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
@@ -7277,99 +7204,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Iridium functions
|
||||
function checkIridiumTools() {
|
||||
fetch('/iridium/tools')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
const status = document.getElementById('iridiumExtractorStatus');
|
||||
status.textContent = data.available ? 'OK' : 'Not found';
|
||||
status.className = 'tool-status ' + (data.available ? 'ok' : 'missing');
|
||||
});
|
||||
}
|
||||
|
||||
function startIridiumCapture() {
|
||||
const freq = document.getElementById('iridiumFreq').value;
|
||||
const gain = document.getElementById('iridiumGain').value;
|
||||
const sampleRate = document.getElementById('iridiumSampleRate').value;
|
||||
const device = getSelectedDevice();
|
||||
const sdr_type = getSelectedSDRType();
|
||||
|
||||
fetch('/iridium/start', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ freq, gain, sampleRate, device, sdr_type })
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.status === 'started') {
|
||||
isIridiumRunning = true;
|
||||
document.getElementById('startIridiumBtn').style.display = 'none';
|
||||
document.getElementById('stopIridiumBtn').style.display = 'block';
|
||||
document.getElementById('statusDot').className = 'status-dot active';
|
||||
document.getElementById('statusText').textContent = 'Iridium Capture';
|
||||
startIridiumStream();
|
||||
} else {
|
||||
alert('Error: ' + data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function stopIridiumCapture() {
|
||||
fetch('/iridium/stop', { method: 'POST' })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
isIridiumRunning = false;
|
||||
document.getElementById('startIridiumBtn').style.display = 'block';
|
||||
document.getElementById('stopIridiumBtn').style.display = 'none';
|
||||
document.getElementById('statusDot').className = 'status-dot';
|
||||
document.getElementById('statusText').textContent = 'Idle';
|
||||
if (iridiumEventSource) {
|
||||
iridiumEventSource.close();
|
||||
iridiumEventSource = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startIridiumStream() {
|
||||
if (iridiumEventSource) iridiumEventSource.close();
|
||||
iridiumEventSource = new EventSource('/iridium/stream');
|
||||
|
||||
iridiumEventSource.onmessage = function(e) {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.type === 'burst') {
|
||||
iridiumBursts.unshift(data);
|
||||
document.getElementById('burstCount').textContent = iridiumBursts.length;
|
||||
addBurstToLog(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function addBurstToLog(burst) {
|
||||
const container = document.getElementById('burstList');
|
||||
const placeholder = container.querySelector('div[style*="color: #666"]');
|
||||
if (placeholder) placeholder.remove();
|
||||
|
||||
const card = document.createElement('div');
|
||||
card.className = 'burst-card';
|
||||
card.innerHTML = `
|
||||
<div class="burst-time">${burst.time}</div>
|
||||
<div class="burst-freq">${burst.frequency} MHz</div>
|
||||
<div class="burst-data">${burst.data || 'No payload data'}</div>
|
||||
`;
|
||||
container.insertBefore(card, container.firstChild);
|
||||
|
||||
while (container.children.length > 100) {
|
||||
container.removeChild(container.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
function clearIridiumLog() {
|
||||
iridiumBursts = [];
|
||||
document.getElementById('burstCount').textContent = '0';
|
||||
document.getElementById('burstList').innerHTML = '<div style="color: #666; text-align: center; padding: 30px; font-size: 11px;">Iridium bursts will appear here when detected.</div>';
|
||||
}
|
||||
|
||||
// Utility function
|
||||
function showInfo(message) {
|
||||
// Simple notification - could be enhanced
|
||||
@@ -7513,7 +7347,6 @@
|
||||
<li>Add satellites manually or fetch from Celestrak by category</li>
|
||||
<li>Categories: Amateur, Weather, ISS, Starlink, GPS, and more</li>
|
||||
<li>View next pass predictions with elevation and duration</li>
|
||||
<li>Monitor for Iridium satellite bursts</li>
|
||||
</ul>
|
||||
|
||||
<h3>📶 WiFi Mode</h3>
|
||||
|
||||
@@ -19,7 +19,6 @@ from .logging import (
|
||||
bluetooth_logger,
|
||||
adsb_logger,
|
||||
satellite_logger,
|
||||
iridium_logger,
|
||||
)
|
||||
from .validation import (
|
||||
escape_html,
|
||||
|
||||
@@ -189,18 +189,6 @@ TOOL_DEPENDENCIES = {
|
||||
}
|
||||
}
|
||||
},
|
||||
'iridium': {
|
||||
'name': 'Iridium Monitoring',
|
||||
'tools': {
|
||||
'iridium-extractor': {
|
||||
'required': False,
|
||||
'description': 'Iridium burst extractor',
|
||||
'install': {
|
||||
'manual': 'https://github.com/muccc/gr-iridium'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'sdr_hardware': {
|
||||
'name': 'SDR Hardware Support',
|
||||
'tools': {
|
||||
|
||||
@@ -27,4 +27,3 @@ wifi_logger = get_logger('intercept.wifi')
|
||||
bluetooth_logger = get_logger('intercept.bluetooth')
|
||||
adsb_logger = get_logger('intercept.adsb')
|
||||
satellite_logger = get_logger('intercept.satellite')
|
||||
iridium_logger = get_logger('intercept.iridium')
|
||||
|
||||
@@ -83,7 +83,7 @@ class CommandBuilder(ABC):
|
||||
squelch: Optional[int] = None
|
||||
) -> list[str]:
|
||||
"""
|
||||
Build FM demodulation command (for pager, iridium).
|
||||
Build FM demodulation command (for pager decoding).
|
||||
|
||||
Args:
|
||||
device: The SDR device to use
|
||||
|
||||
@@ -65,7 +65,7 @@ class HackRFCommandBuilder(CommandBuilder):
|
||||
"""
|
||||
Build SoapySDR rx_fm command for FM demodulation.
|
||||
|
||||
For pager decoding and iridium capture with HackRF.
|
||||
For pager decoding with HackRF.
|
||||
"""
|
||||
device_str = self._build_device_string(device)
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class LimeSDRCommandBuilder(CommandBuilder):
|
||||
"""
|
||||
Build SoapySDR rx_fm command for FM demodulation.
|
||||
|
||||
For pager decoding and iridium capture with LimeSDR.
|
||||
For pager decoding with LimeSDR.
|
||||
"""
|
||||
device_str = self._build_device_string(device)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class RTLSDRCommandBuilder(CommandBuilder):
|
||||
"""
|
||||
Build rtl_fm command for FM demodulation.
|
||||
|
||||
Used for pager decoding and iridium capture.
|
||||
Used for pager decoding.
|
||||
"""
|
||||
cmd = [
|
||||
'rtl_fm',
|
||||
|
||||
Reference in New Issue
Block a user