ADS-B / 978 Integration
April 17, 2026 · View on GitHub
DragonSync can ingest aircraft data from a local readsb instance via HTTP and convert it to CoT for TAK/ATAK.
Status: Experimental. This is currently a multi-step and somewhat manual process.
Overview
readsb (SDR → 1090/978 MHz) → HTTP API → DragonSync → CoT
DragonSync polls the readsb HTTP API and builds CoT messages per aircraft with:
- Position, altitude (geometric/barometric), speed, track
- Richer remarks (hex, callsign, squawk, registration, category, on-ground flag)
- CE/LE accuracy derived from NACp/NACv when available
SDR Considerations
At the moment, only one SDR-driven role can use the same RF front-end at once:
| Configuration | Use Case |
|---|---|
| Single SDR (DragonSDR) | Either drone detection OR ADS-B, not both simultaneously |
| Multiple SDRs | Dedicated SDR for drones + separate SDR for ADS-B |
Single SDR
You can either:
- Run DJI/FPV-related tasks, or
- Run
readsbfor ADS-B / 978
Switching roles means stopping one and starting the other. This is best used for demo/experiment modes.
Multiple SDRs (Recommended)
For continuous drone + aircraft coverage:
- One SDR path for drone detection (DJI / RID)
- Another SDR (RTL-SDR, second DragonSDR, etc.) for ADS-B / 978 with its own
readsbinstance
You can run readsb with a different device selection and still point DragonSync at its API.
Setup
1. Start readsb
Pluto / DragonSDR Example
Using the DragonSDR in Pluto-compatible mode via SoapySDR:
sudo readsb \
--device-type soapysdr \
--soapy-device="driver=plutosdr" \
--freq=1090000000 \
--no-interactive \
--write-json=/run/readsb \
--write-json-every=1 \
--json-location-accuracy=2 \
--net-bind-address=0.0.0.0 \
--net-api-port=8080 \
--soapy-enable-agc \
--sdr-buffer-size=128
RTL-SDR Example
sudo readsb \
--device-type rtlsdr \
--freq=1090000000 \
--no-interactive \
--write-json=/run/readsb \
--write-json-every=1 \
--json-location-accuracy=2 \
--net-bind-address=0.0.0.0 \
--net-api-port=8080
Key Options
| Option | Description |
|---|---|
--freq=1090000000 | 1090 MHz for standard ADS-B |
--freq=978000000 | 978 MHz for UAT (US only) |
--net-api-port=8080 | HTTP API port |
--device-type | soapysdr, rtlsdr, etc. |
--soapy-device | SoapySDR device string |
2. Verify readsb
Test the HTTP API:
curl -s http://127.0.0.1:8080/?all_with_pos | jq '.aircraft | length'
You should see a count of aircraft with positions. If you see 0 or an error, readsb isn't receiving data.
3. Configure DragonSync
Add to your config.ini:
[SETTINGS]
# ADS-B / UAT aircraft ingestion
adsb_enabled = true
adsb_json_url = http://127.0.0.1:8080/?all_with_pos
# Optional altitude gates (feet). 0 = disabled.
adsb_min_alt = 0
adsb_max_alt = 0
Altitude Filtering
You can filter aircraft by altitude:
# Only show aircraft below 10,000 feet
adsb_max_alt = 10000
# Only show aircraft above 1,000 feet (ignore ground traffic)
adsb_min_alt = 1000
# Both: 1,000 to 10,000 feet
adsb_min_alt = 1000
adsb_max_alt = 10000
Set to 0 to disable filtering.
How It Works
- DragonSync polls
adsb_json_urlonce perpoll_interval - Expects readsb-style JSON with an
aircraftarray - For each aircraft with a valid position:
- Builds a CoT message with position, altitude, speed, track
- Includes hex code, callsign, squawk, registration, category
- Derives accuracy (CE/LE) from NACp/NACv when available
- Outputs CoT via configured TAK server or multicast
CoT Mapping
| readsb Field | CoT Element |
|---|---|
hex | UID suffix |
lat, lon | Point position |
alt_geom or alt_baro | HAE (converted to meters) |
gs | Speed (converted to m/s) |
track | Course |
flight | Callsign in remarks |
squawk | Squawk in remarks |
category | Aircraft category in remarks |
nac_p, nac_v | CE/LE accuracy |
MQTT Output
To publish aircraft data to MQTT, you must enable both MQTT and aircraft publishing in config.ini:
mqtt_enabled = true
mqtt_aircraft_enabled = true
mqtt_aircraft_topic = wardragon/aircraft
Aircraft are then published to the configured topic (default: wardragon/aircraft):
{
"icao": "A12345",
"callsign": "UAL123",
"registration": "N12345",
"lat": 39.1234,
"lon": -77.5678,
"alt": 35000,
"speed": 450,
"track": 270,
"squawk": "1200",
"category": "A3",
"on_ground": false,
"rssi": -8.5,
"track_type": "aircraft"
}
See mqtt-schema.md for the complete field reference.
Signal Strength (RSSI)
The rssi field contains signal strength from readsb, measured in dBFS (decibels relative to full scale), not dBm.
| Value | Meaning |
|---|---|
| 0 dBFS | Maximum signal (ADC saturation) |
| -10 dBFS | Very strong signal |
| -20 dBFS | Good signal |
| -30 dBFS | Weak signal |
Important notes:
- dBFS is relative to the SDR's ADC, not absolute power
- Values depend on SDR gain settings
- For multi-kit triangulation, all kits should use similar gain settings
rssimay benullif readsb doesn't provide it (older versions or certain configurations)
Troubleshooting
| Issue | Solution |
|---|---|
| No aircraft in ATAK | Verify curl http://127.0.0.1:8080/?all_with_pos returns aircraft |
| readsb not starting | Check SDR device permissions, antenna connection |
| Only some aircraft appear | Enable /?all_with_pos not just /? which requires positions |
| High CPU usage | Increase poll_interval in config |
Common readsb Issues
Permission denied on SDR:
# Add udev rules for RTL-SDR
sudo cp rtl-sdr.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
SoapySDR device not found:
# List available devices
SoapySDRUtil --find
Frequency Reference
| Frequency | Service | Region |
|---|---|---|
| 1090 MHz | ADS-B (Mode S) | Worldwide |
| 978 MHz | UAT (ADS-B) | United States only |
Note: 978 MHz UAT is only used in the US below 18,000 feet. International flights and high-altitude traffic use 1090 MHz exclusively.