mirror of
https://github.com/smittix/intercept.git
synced 2026-07-05 08:08:14 -07:00
Refactor into modular structure with improvements
- Split monolithic intercept.py (15k lines) into modular structure: - routes/ - Flask blueprints for each feature - templates/ - Jinja2 HTML templates - data/ - OUI database, satellite TLEs, detection patterns - utils/ - dependencies, process management, logging - config.py - centralized configuration with env var support - Add type hints to function signatures - Replace bare except clauses with specific exceptions - Add proper logging module (replaces print statements) - Add environment variable support (INTERCEPT_* prefix) - Add test suite with pytest - Add Dockerfile for containerized deployment - Add pyproject.toml with ruff/black/mypy config - Add requirements-dev.txt for development dependencies 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
"""Iridium monitoring routes."""
|
||||
|
||||
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
|
||||
|
||||
iridium_bp = Blueprint('iridium', __name__, url_prefix='/iridium')
|
||||
|
||||
|
||||
def monitor_iridium(process):
|
||||
"""Monitor Iridium capture and detect bursts."""
|
||||
try:
|
||||
burst_count = 0
|
||||
while process.poll() is None:
|
||||
data = process.stdout.read(1024)
|
||||
if data:
|
||||
if len(data) > 0 and burst_count < 100:
|
||||
if random.random() < 0.01:
|
||||
burst = {
|
||||
'type': 'burst',
|
||||
'time': datetime.now().strftime('%H:%M:%S.%f')[:-3],
|
||||
'frequency': f"{1616 + random.random() * 10:.3f}",
|
||||
'data': f"Frame data (simulated) - 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_tool = shutil.which('iridium-extractor') is not None or shutil.which('iridium-parser') is not None
|
||||
return jsonify({'available': has_tool})
|
||||
|
||||
|
||||
@iridium_bp.route('/start', methods=['POST'])
|
||||
def start_iridium():
|
||||
"""Start Iridium burst capture."""
|
||||
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'})
|
||||
|
||||
data = request.json
|
||||
freq = data.get('freq', '1626.0')
|
||||
gain = data.get('gain', '40')
|
||||
sample_rate = data.get('sampleRate', '2.048e6')
|
||||
device = data.get('device', '0')
|
||||
|
||||
if not shutil.which('iridium-extractor') and not shutil.which('rtl_fm'):
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': 'Iridium tools not found.'
|
||||
})
|
||||
|
||||
try:
|
||||
cmd = [
|
||||
'rtl_fm',
|
||||
'-f', f'{float(freq)}M',
|
||||
'-g', str(gain),
|
||||
'-s', sample_rate,
|
||||
'-d', str(device),
|
||||
'-'
|
||||
]
|
||||
|
||||
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'})
|
||||
except Exception as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)})
|
||||
|
||||
|
||||
@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():
|
||||
while True:
|
||||
try:
|
||||
msg = app_module.satellite_queue.get(timeout=1)
|
||||
yield f"data: {json.dumps(msg)}\n\n"
|
||||
except queue.Empty:
|
||||
yield f"data: {json.dumps({'type': 'keepalive'})}\n\n"
|
||||
|
||||
response = Response(generate(), mimetype='text/event-stream')
|
||||
response.headers['Cache-Control'] = 'no-cache'
|
||||
response.headers['X-Accel-Buffering'] = 'no'
|
||||
return response
|
||||
Reference in New Issue
Block a user