Agent improvements: - Add process verification (0.5s delay + poll check) for sensor, pager, APRS, DSC modes - Prevents silent failures when SDR is busy or tools fail to start - Returns clear error messages when subprocess exits immediately Frontend agent integration: - Add agent routing to all SDR modes (pager, sensor, RTLAMR, APRS, listening post, TSCM) - Add agent routing to WiFi and Bluetooth modes with polling fallback - Add agent routing to AIS and DSC dashboards - Implement "Show All Agents" toggle for Bluetooth mode - Add agent badges to device/network lists - Handle controller proxy response format (nested 'result' field) Controller enhancements: - Add running_modes_detail endpoint showing device info per mode - Support SDR conflict detection across modes Documentation: - Expand DISTRIBUTED_AGENTS.md with complete API reference - Add troubleshooting guide and security considerations - Document all supported modes with tools and data formats UI/CSS: - Add agent badge styling for remote vs local sources - Add WiFi and Bluetooth table agent columns
16 KiB
Intercept Distributed Agent System
This document describes the distributed agent architecture that allows multiple remote sensor nodes to feed data into a central Intercept controller.
Overview
The agent system uses a hub-and-spoke architecture where:
- Controller: The main Intercept instance that aggregates data from multiple agents
- Agents: Lightweight sensor nodes running on remote devices with SDR hardware
┌─────────────────────────────────┐
│ INTERCEPT CONTROLLER │
│ (port 5050) │
│ │
│ - Web UI with agent selector │
│ - /controller/manage page │
│ - Multi-agent SSE stream │
│ - Push data storage │
└─────────────────────────────────┘
▲ ▲ ▲
│ │ │
Push/Pull │ │ │ Push/Pull
│ │ │
┌────┴───┐ ┌────┴───┐ ┌────┴───┐
│ Agent │ │ Agent │ │ Agent │
│ :8020 │ │ :8020 │ │ :8020 │
│ │ │ │ │ │
│[RTL-SDR] │[HackRF] │ │[LimeSDR]
└────────┘ └────────┘ └────────┘
Quick Start
1. Start the Controller
The controller is the main Intercept application:
cd intercept
python app.py
# Runs on http://localhost:5050
2. Configure an Agent
Create a config file on the remote machine:
# intercept_agent.cfg
[agent]
name = sensor-node-1
port = 8020
allowed_ips =
allow_cors = false
[controller]
url = http://192.168.1.100:5050
api_key = your-secret-key-here
push_enabled = true
push_interval = 5
[modes]
pager = true
sensor = true
adsb = true
wifi = true
bluetooth = true
3. Start the Agent
python intercept_agent.py --config intercept_agent.cfg
# Runs on http://localhost:8020
4. Register the Agent
Go to http://controller:5050/controller/manage and add the agent:
- Name: sensor-node-1 (must match config)
- Base URL: http://agent-ip:8020
- API Key: your-secret-key-here (must match config)
Architecture
Data Flow
The system supports two data flow patterns:
Push (Agent → Controller)
Agents automatically push captured data to the controller:
- Agent captures data (e.g., rtl_433 sensor readings)
- Data is queued in the
ControllerPushClient - Agent POSTs to
http://controller/controller/api/ingest - Controller validates API key and stores in
push_payloadstable - Data is available via SSE stream at
/controller/stream/all
Agent Controller
│ │
│ POST /controller/api/ingest │
│ Header: X-API-Key: secret │
│ Body: {agent_name, scan_type, │
│ payload, timestamp} │
│ ──────────────────────────────► │
│ │
│ 200 OK │
│ ◄────────────────────────────── │
Pull (Controller → Agent)
The controller can also pull data on-demand:
- User selects agent in UI dropdown
- User clicks "Start Listening"
- Controller proxies request to agent
- Agent starts the mode and returns status
- Controller polls agent for data
Browser Controller Agent
│ │ │
│ POST /controller/ │ │
│ agents/1/sensor/start│ │
│ ─────────────────────► │ │
│ │ POST /sensor/start │
│ │ ────────────────────────► │
│ │ │
│ │ {status: started} │
│ │ ◄──────────────────────── │
│ {status: success} │ │
│ ◄───────────────────── │ │
Authentication
API key authentication secures the push mechanism:
- Agent config specifies
api_keyin[controller]section - Agent sends
X-API-Keyheader with each push request - Controller looks up agent by name in database
- Controller compares provided key with stored key
- Mismatched keys return 401 Unauthorized
Database Schema
Two tables support the agent system:
-- Registered agents
CREATE TABLE agents (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
base_url TEXT NOT NULL,
api_key TEXT,
capabilities TEXT, -- JSON: {pager: true, sensor: true, ...}
interfaces TEXT, -- JSON: {devices: [...]}
gps_coords TEXT, -- JSON: {lat, lon}
last_seen TIMESTAMP,
is_active BOOLEAN
);
-- Pushed data from agents
CREATE TABLE push_payloads (
id INTEGER PRIMARY KEY,
agent_id INTEGER,
scan_type TEXT, -- pager, sensor, adsb, wifi, etc.
payload TEXT, -- JSON data
received_at TIMESTAMP,
FOREIGN KEY (agent_id) REFERENCES agents(id)
);
Agent REST API
The agent exposes these endpoints:
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check (returns {status: "healthy"}) |
/capabilities |
GET | Available modes, devices, GPS status |
/status |
GET | Running modes, uptime, push status |
/{mode}/start |
POST | Start a mode (pager, sensor, adsb, etc.) |
/{mode}/stop |
POST | Stop a mode |
/{mode}/status |
GET | Mode-specific status |
/{mode}/data |
GET | Current data snapshot |
Example: Start Sensor Mode
curl -X POST http://agent:8020/sensor/start \
-H "Content-Type: application/json" \
-d '{"frequency": 433.92, "device_index": 0}'
Response:
{
"status": "started",
"mode": "sensor",
"command": "/usr/local/bin/rtl_433 -d 0 -f 433.92M -F json",
"gps_enabled": true
}
Example: Get Capabilities
curl http://agent:8020/capabilities
Response:
{
"modes": {
"pager": true,
"sensor": true,
"adsb": true,
"wifi": true,
"bluetooth": true
},
"devices": [
{
"index": 0,
"name": "RTLSDRBlog, Blog V4",
"sdr_type": "rtlsdr",
"capabilities": {
"freq_min_mhz": 24.0,
"freq_max_mhz": 1766.0
}
}
],
"gps": true,
"gps_position": {
"lat": 33.543,
"lon": -82.194,
"altitude": 70.0
},
"tool_details": {
"sensor": {
"name": "433MHz Sensors",
"ready": true,
"tools": {
"rtl_433": {"installed": true, "required": true}
}
}
}
}
Supported Modes
All modes are fully implemented in the agent with the following tools and data formats:
| Mode | Tool(s) | Data Format | Notes |
|---|---|---|---|
sensor |
rtl_433 | JSON readings | ISM band devices (433/868/915 MHz) |
pager |
rtl_fm + multimon-ng | POCSAG/FLEX messages | Address, function, message content |
adsb |
dump1090 | SBS-format aircraft | ICAO, callsign, position, altitude |
ais |
AIS-catcher | JSON vessels | MMSI, position, speed, vessel info |
acars |
acarsdec | JSON messages | Aircraft tail, label, message text |
aprs |
rtl_fm + direwolf | APRS packets | Callsign, position, path |
wifi |
airodump-ng | Networks + clients | BSSID, ESSID, signal, clients |
bluetooth |
bluetoothctl | Device list | MAC, name, RSSI |
rtlamr |
rtl_tcp + rtlamr | Meter readings | Meter ID, consumption data |
dsc |
rtl_fm (+ dsc-decoder) | DSC messages | MMSI, distress category, position |
tscm |
WiFi/BT analysis | Anomaly reports | New/rogue devices detected |
satellite |
skyfield (TLE) | Pass predictions | No SDR required |
listening_post |
rtl_fm scanner | Signal detections | Frequency, modulation |
Mode-Specific Notes
Listening Post: Full FFT streaming isn't practical over HTTP. Instead, the agent provides:
- Signal detection events when activity is found
- Current scanning frequency
- Activity log of detected signals
TSCM: Analyzes WiFi and Bluetooth data for anomalies:
- Builds baseline of known devices
- Reports new/unknown devices as anomalies
- No SDR required (uses WiFi/BT data)
Satellite: Pure computational mode:
- Calculates pass predictions from TLE data
- Requires observer location (lat/lon)
- No SDR required
Audio Modes: Modes requiring real-time audio (airband, listening_post audio) are limited via agents. Use rtl_tcp for remote audio streaming instead.
Controller API
Agent Management
| Endpoint | Method | Description |
|---|---|---|
/controller/agents |
GET | List all agents |
/controller/agents |
POST | Register new agent |
/controller/agents/{id} |
GET | Get agent details |
/controller/agents/{id} |
DELETE | Remove agent |
/controller/agents/{id}?refresh=true |
GET | Refresh agent capabilities |
Proxy Operations
| Endpoint | Method | Description |
|---|---|---|
/controller/agents/{id}/{mode}/start |
POST | Start mode on agent |
/controller/agents/{id}/{mode}/stop |
POST | Stop mode on agent |
/controller/agents/{id}/{mode}/data |
GET | Get data from agent |
Push Ingestion
| Endpoint | Method | Description |
|---|---|---|
/controller/api/ingest |
POST | Receive pushed data from agents |
SSE Streams
| Endpoint | Description |
|---|---|
/controller/stream/all |
Combined stream from all agents |
Frontend Integration
Agent Selector
The main UI includes an agent dropdown in supported modes:
<select id="agentSelect">
<option value="local">Local (This Device)</option>
<option value="1">● sensor-node-1</option>
</select>
When an agent is selected:
- Device list updates to show agent's SDR devices
- Start/Stop commands route through controller proxy
- Data displays with agent name badge
Multi-Agent Mode
Enable "Show All Agents" checkbox to:
- Connect to
/controller/stream/allSSE - Display combined data from all agents
- Show agent name badge on each data item
GPS Integration
Agents can include GPS coordinates with captured data:
- Agent connects to local
gpsddaemon - GPS position included in
/capabilitiesand/status - Each data snapshot includes
agent_gpsfield - Controller can use GPS for trilateration (multiple agents)
Configuration Reference
Agent Config (intercept_agent.cfg)
[agent]
# Agent identity (must be unique across all agents)
name = sensor-node-1
# Port to listen on
port = 8020
# Restrict connections to specific IPs (comma-separated, empty = all)
allowed_ips =
# Enable CORS headers
allow_cors = false
[controller]
# Controller URL (required for push)
url = http://192.168.1.100:5050
# API key for authentication
api_key = your-secret-key
# Enable automatic data push
push_enabled = true
# Push interval in seconds
push_interval = 5
[modes]
# Enable/disable specific modes
pager = true
sensor = true
adsb = true
ais = true
wifi = true
bluetooth = true
Troubleshooting
Agent not appearing in controller
- Check agent is running:
curl http://agent:8020/health - Verify agent is registered in
/controller/manage - Check API key matches between agent config and controller registration
- Check network connectivity between agent and controller
Push data not arriving
- Check agent status:
curl http://agent:8020/status- Verify
push_enabled: trueandpush_connected: true
- Verify
- Check controller logs for authentication errors
- Verify API key matches
- Check if mode is running and producing data
Mode won't start on agent
- Check capabilities:
curl http://agent:8020/capabilities - Verify required tools are installed (check
tool_details) - Check if SDR device is available (not in use by another process)
No data from sensor mode
- Verify rtl_433 is running:
ps aux | grep rtl_433 - Check sensor status:
curl http://agent:8020/sensor/status - Note: Empty data is normal if no 433MHz devices are transmitting nearby
Security Considerations
- API Keys: Always use strong, unique API keys for each agent
- Network: Consider running agents on a private network or VPN
- HTTPS: For production, use HTTPS between agents and controller
- Firewall: Restrict agent ports to controller IP only
- allowed_ips: Use this config option to restrict agent connections
Dashboard Integration
Agent support has been integrated into the following specialized dashboards:
ADS-B Dashboard (/adsb/dashboard)
- Agent selector in header bar
- Routes tracking start/stop through agent proxy when remote agent selected
- Connects to multi-agent stream for data from remote agents
- Displays agent badge on aircraft from remote sources
- Updates observer location from agent's GPS coordinates
AIS Dashboard (/ais/dashboard)
- Agent selector in header bar
- Routes AIS and DSC mode operations through agent proxy
- Connects to multi-agent stream for vessel data
- Displays agent badge on vessels from remote sources
- Updates observer location from agent's GPS coordinates
Main Dashboard (/)
- Agent selector in sidebar
- Supports sensor, pager, WiFi, Bluetooth modes via agents
- SDR conflict detection with device-aware warnings
- Real-time sync with agent's running mode state
Multi-SDR Agent Support
For agents with multiple SDR devices, the system now tracks which device each mode is using:
{
"running_modes": ["sensor", "adsb"],
"running_modes_detail": {
"sensor": {"device": 0, "started_at": "2024-01-15T10:30:00Z"},
"adsb": {"device": 1, "started_at": "2024-01-15T10:35:00Z"}
}
}
This allows:
- Smart conflict detection (only warns if same device is in use)
- Display of which device each mode is using
- Parallel operation of multiple SDR modes on multi-SDR agents
Agent Mode Warnings
When an agent has SDR modes running, the UI displays:
- Warning banner showing active modes with device numbers
- Stop buttons for each running mode
- Refresh button to re-sync with agent state
Pages Without Agent Support
The following pages don't require SDR-based agent support:
- Satellite Dashboard (
/satellite/dashboard) - Uses TLE orbital calculations, no SDR - History pages - Display stored data, not live SDR streams
Files
| File | Description |
|---|---|
intercept_agent.py |
Standalone agent server |
intercept_agent.cfg |
Agent configuration template |
routes/controller.py |
Controller API blueprint |
utils/agent_client.py |
HTTP client for agents |
utils/database.py |
Agent CRUD operations |
static/js/core/agents.js |
Frontend agent management |
templates/agents.html |
Agent management page |
templates/adsb_dashboard.html |
ADS-B page with agent integration |
templates/ais_dashboard.html |
AIS page with agent integration |