Unofficial test opkg feed for WIP packages destined for upstream openwrt/packages. Built once against OpenWrt 23.05.6 (Cortex-A53) and republished under multiple ABI-compatible arch labels so the same base URL works on mainline OpenWrt and on GL.iNet ApNos firmware.
Pick the snippet that matches your router's firmware. The opkg arch label is a literal-string match, so the right URL matters even though the binaries are identical across labels. Run this once; then install whichever package(s) you want from the section below.
echo 'src/gz blackoutsecure https://openwrt.blackoutsecure.dev/23.05-SNAPSHOT/packages/aarch64_cortex-a53/blackoutsecure' >> /etc/opkg/customfeeds.conf
opkg update
echo 'src/gz blackoutsecure https://openwrt.blackoutsecure.dev/23.05-SNAPSHOT/packages/aarch64_cortex-a53_neon-vfpv4/blackoutsecure' >> /etc/opkg/customfeeds.conf
opkg update
Pick a package for its install command, configuration, and uninstall steps. All packages live in the single feed configured above.
feat-add-pkg-readsb-wiedehopfAfter adding the feed above, install with:
opkg install readsb-wiedehopf
After adding the feed and installing the package, run the wizard:
opkg install readsb-wiedehopf
readsb-setup # guided first-boot: lat/lon, UUID, SDR, feeders, reload
The package is fully usable without readsb-setup — postinst enables and starts the daemon with safe defaults — but you need at minimum a station location (and, for most aggregators, a UUID) before it'll actually receive aircraft. Re-running the wizard is idempotent; every step is skippable.
This page documents only the OpenWrt-specific layer (UCI, init, hotplug, geoip, helper CLIs, presets). For the readsb daemon itself — every CLI flag, the autogain algorithm, BeastReduce, MLAT, pushing to aggregators, tar1090, the JSON/API outputs — see upstream:
UCI options map directly to upstream flags: each option in /etc/config/readsb becomes the same-named --flag on the daemon command line (underscores → dashes). So upstream's --net-connector=… is option net_connector '…' here, --net-beast-reduce-filter-dist=… is option net_beast_reduce_filter_dist '…', etc. Anything upstream supports but that the package doesn't surface as a UCI option goes through option extra_args verbatim.
readsb-wiedehopf but PROVIDES:=readsb / CONFLICTS:=readsb (likewise viewadsb-wiedehopf for viewadsb), so the binary is /usr/bin/readsb, the init script is /etc/init.d/readsb, and the UCI config is /etc/config/readsb. Either this package or upstream readsb can satisfy a readsb dependency — but not both at once.
readsb-setup — guided wizard. Five idempotent steps: lat/lon, UUID, SDR (gain/PPM/AGC/bias-T, auto-skipped on net-only units), at least one aggregator feeder, apply changes. Also: --status (rc 0 if essentials present, 1 if not — also reports missing/stopped companion packages per enabled feeder), --config (pretty-printed dump of /etc/config/readsb), --banner (re-print the post-install orientation card).readsb-feeder — feeder management CLI. Subcommands: list, show <name>, add, set, enable / disable / remove, wizard, probe, url [preset], presets, companions [preset], examples. Run readsb-feeder -h for the live list.readsb-uuid — generate or print the station UUID written to readsb.main.uuid. Idempotent; -p = print-only, -f = force regenerate (do NOT do this after registering with an aggregator).readsb-geoip — public-IP lat/lon auto-fill (ipapi.co with ip-api.com fallback). City-level accuracy. --force overwrites existing values; --self-test is a read-only PASS/FAIL diagnostic./etc/hotplug.d/usb/30-readsb, gated per section by option hotplug '1', default on). Recognises the full librtlsdr known-device list (Realtek 0bda:2832/2838, Hauppauge, Terratec, Compro, MyGica, Astrometa, Nooelec, RTL-SDR Blog v3/v4, etc.). On add it pins device=<USB serial>, sets device_type=rtlsdr, net_only=0, enabled=1, and restarts the service. On the last RTL-SDR being removed, the section reverts to net_only=1. Already-attached SDRs at boot are re-injected through the same handler so install-then-reboot behaves identically to hot-insert.rtl_eeprom -s <freq> (from the rtl-sdr package), then per-section option freq selects which dongle each section claims by exact serial == freq match. If no serial matches, the handler logs the available serials at warn and leaves device empty for you to set manually.geoip_wait_timeout (default 60 s, poll geoip_wait_interval = 10 s) blocks startup until readsb-geoip resolves coordinates — covers the cold-boot case where WAN isn't ready when START=90 fires. usb_wait_timeout (default 0 = off, poll usb_wait_interval = 2 s) optionally waits for a USB SDR to appear; honored only when option hotplug '1'. A no-USB reconciliation step normalizes a hotplug-managed section back to net_only=1 if no SDR is present, so a stale device=<serial> from an unplugged dongle can't block startup.config feeder <name> sections — define zero, one, or many. Each enabled section becomes one outbound --net-connector using a built-in preset (adsblol, airplaneslive, adsbfi, planespotters, theairtraffic, flyitaly, avdelphi, adsbexchange, flyrealtraffic) or a user-supplied custom host/port. Manage with readsb-feeder; details in Feeding aggregators below.readsb (and readsb-geoip for the geolocation helper): logread -e readsb -f. The periodic stats block (option stats '1', cadence stats_every = 120 s) is on by default; silence with option stats '0'./etc/config/readsb is declarative-only. Comments do not survive uci commit: every commit (from the hotplug handler, readsb-uuid, readsb-geoip, LuCI, or a plain uci set) rewrites the file in canonical form and strips every # line. Per-option documentation lives here on this page and in each helper's --help, not inside the conffile.
Mutating workflows in order of preference: (1) readsb-setup / readsb-feeder wizard; (2) non-interactive helpers (readsb-feeder add, readsb-uuid); (3) plain UCI; (4) hand-edit the conffile (always works, but any later commit from anything else strips your comments).
uci show readsb # current effective config
# cat /etc/config/readsb # raw file view
# Override the geoip-detected location with your real receiver coordinates.
uci set readsb.main.lat='12.3456'
uci set readsb.main.lon='-65.4321'
# Gain. 'auto' is upstream's ADS-B autogain (see upstream README § Autogain).
# With system log_level=debug the init script promotes this to 'auto-verbose'
# automatically. Or pin a manual dB value (0..50) from `readsb --help`.
uci set readsb.main.gain='auto'
uci set readsb.main.mlat='1' # emit MLAT timestamps in Beast OUT
# Multi-SDR pinning (only when more than one RTL-SDR is attached).
# Requires `rtl_eeprom -s 1090` / `-s 978` to label each dongle first.
# uci set readsb.main.freq='1090MHz'
# uci add readsb readsb # second section for 978 MHz UAT, etc.
# uci set readsb.@readsb[-1].freq='978MHz'
# Pass-through for upstream flags not surfaced as a UCI option
# (whitespace-separated, appended verbatim to the daemon command line).
# uci set readsb.main.extra_args='--write-binCraft-old --aggressive'
uci commit readsb # procd reload trigger picks it up
service readsb status
logread -e readsb -f
viewadsb # text UI of live aircraft
# readsb-geoip --force # re-run geoip lookup (overwrite lat/lon)
For the meaning of every option, search upstream readsb --help for the dash-form name (UCI net_beast_reduce_filter_dist → --net-beast-reduce-filter-dist).
As shipped in /etc/config/readsb:
| Port | UCI option | Direction | Notes |
|---|---|---|---|
30001 | net_ri_port | Raw IN | AVR-format raw input |
30002 | net_ro_port | Raw OUT | AVR-format raw output |
30003 | net_sbs_port | SBS BaseStation OUT | for Virtual Radar Server etc. |
30004,30104 | net_bi_port | Beast IN | feed raw Beast frames in |
30005 | net_bo_port | Beast OUT | for piaware / fr24feed / tar1090 |
30006 | net_beast_reduce_out_port | BeastReduce OUT | for aggregators (see upstream § BeastReduce) |
net_api_port, net_json_port, write_globe_history, heatmap, and the rest are unset by default — enable them in /etc/config/readsb as described upstream.
Outbound feeding is configured with config feeder <name> sections. Each enabled section becomes one outbound --net-connector; readsb shares the same decoded message stream across all of them with no priority or order between feeders.
net_bo_port (30005) etc. for LAN clients (tar1090, vendor feeders running on another host, …).The init script also accepts the legacy option net_connector / list net_connector form on the main section (one --net-connector=<host,port,proto[,uuid=…]> per item). Both forms coexist and readsb-feeder list / readsb-setup --status enumerate both, but the legacy form isn't manageable by readsb-feeder — prefer config feeder sections for new deployments.
Built-in presets. All ship the same protocol (beast_reduce_plus_out, BeastReduce-Plus over TCP). Pick a preset by name and the helper resolves host/port for you. Endpoints can change without notice — readsb-feeder presets always prints the live list.
| Preset | Endpoint | Site |
|---|---|---|
adsblol | in.adsb.lol:30004 | adsb.lol (per-station map at api.adsb.lol/0/my) |
airplaneslive | feed.airplanes.live:30004 | airplanes.live |
adsbfi | feed.adsb.fi:30004 | adsb.fi |
planespotters | feed.planespotters.net:30004 | planespotters.net |
theairtraffic | feed.theairtraffic.com:30004 | theairtraffic.com |
flyitaly | dati.flyitalyadsb.com:4905 | flyitalyadsb.com |
avdelphi | data.avdelphi.com:24999 | avdelphi.com |
adsbexchange | feed1.adsbexchange.com:30004 | adsbexchange.com — optional per-station ranking via the adsbexchange-stats companion package; readsb-feeder url adsbexchange prints the per-UUID page |
flyrealtraffic | feed.flyrealtraffic.com:30004 | flyrealtraffic.com |
custom | (user-supplied) | set host/port/protocol yourself |
Add a feeder. Interactive (recommended — prompts for everything, validates as you go, prints any companion-package install hints):
readsb-feeder wizard
service readsb reload
Non-interactive (scriptable):
# From a preset:
readsb-feeder add adsblol adsblol enabled=1 silent_fail=1
# Custom endpoint:
readsb-feeder add mycustom custom \
host=feed.example.com port=30004 \
protocol=beast_reduce_plus_out \
enabled=1 silent_fail=1
service readsb reload
Mute, disable, remove.
readsb-feeder disable adsbexchange # keep section, stop pushing
readsb-feeder enable adsbexchange # turn it back on
readsb-feeder remove adsbexchange # drop the section entirely
service readsb reload
Inspect and probe.
readsb-feeder list # all sections + resolved host/port/protocol
readsb-feeder show adsblol # one section in detail
readsb-feeder probe # TCP-probe each enabled feeder
readsb-feeder url [preset] # public stats URL (where one is published)
readsb-feeder presets # current preset list with endpoints
readsb-feeder companions # optional companion package(s) per enabled feeder
readsb-feeder examples # ready-to-paste UCI blocks for scripted setups
logread -e readsb # script-side + daemon log lines
Station UUID. Aggregators that authenticate or de-duplicate by UUID need a stable value. Generate one once in the main section and every config feeder inherits it:
readsb-uuid # generate (or print existing — idempotent)
# readsb-uuid -p # print only, never write
# readsb-uuid -f # force regenerate (do NOT do this after registering with an aggregator)
service readsb reload
Resolution order per section: option uuid on the section → option uuid in main → omitted (aggregator de-dupes by source IP only). Set a per-section UUID only when you registered separately with that aggregator under a different identity. As an alternative to option uuid in main, option uuid_file points at a file readsb reads at startup — useful if the UUID lives outside UCI.
silent_fail semantics. Every feeder section accepts option silent_fail '0'|'1', default '1'. When set, brief connection failures (DNS hiccup, aggregator restart, transient network drop) are retried silently. When unset, every failed connection attempt produces a log line. Keep the default unless you're actively debugging a feeder that won't stay connected.
Companion packages. opkg has no Recommends field, so optional companions aren't auto-installed. Currently the only one is adsbexchange-stats — the per-station ranking-dashboard uploader for ADSBx. readsb-feeder add / enable log the install hint to syslog when you turn on a preset that has a companion, and readsb-setup --status / readsb-feeder companions walk every enabled feeder and report whether each companion is installed (and, where applicable, running) with the exact fix command.
Aggregators NOT supported by this package. FlightAware (piaware), FlightRadar24 (fr24feed), RadarBox (rbfeeder), Planefinder (pfclient), and AussieADSB use closed-source vendor clients that do their own per-station enrolment and MLAT — none of which fits inside readsb. To feed them, leave them out of /etc/config/readsb, expose net_bo_port (default 30005, Beast OUT) on this device, and run the vendor's client on another host pointed at <router-ip>:30005. Each vendor client uses its own station ID — the option uuid here does NOT carry over to FlightAware's feeder-id, FR24's sharing-key, etc.
mlat-client process per aggregator. Each aggregator above advertises its own MLAT endpoint (commonly mlat.<host>:31090); consult the aggregator's own docs.
All script-side and daemon-side logging goes to syslog under tag readsb (and readsb-geoip for the geolocation helper). View with logread -e readsb; raise script-side verbosity with uci set system.@system[0].log_level='debug'; uci commit system && service log restart. To persist or forward, configure system-wide logging the standard OpenWrt way (system.@system[0].log_file / log_ip).
| Severity | What you'll see |
|---|---|
err | hard failure that aborted the operation (UCI commit failed, no UUID source, geoip self-test FAIL, hotplug commit/restart failure) |
warn | recoverable / degraded (feeder unreachable, geoip provider returned no coords, hotplug saw a blocking kernel module, no SDR matched freq, geoip wait timed out) |
notice | significant operator event (config mutation committed, service started, mode flip net-only ↔ SDR, UUID written, hotplug auto-pinned a dongle) |
info | routine progress (feeder probe summary OK, geoip lookup result, init waits) |
debug | trace; only visible with system.@system[0].log_level=debug. Per-feeder routing detail, UCI load traces, geoip fallback flow |
The daemon itself emits its periodic stats block on stderr; procd routes that to daemon.err on stock OpenWrt — convention matching dnsmasq/hostapd/ntpd, not a severity claim. Silence with option stats '0'.
Quick triage:
readsb-setup --status # at-a-glance state report (rc 0/1) + companion check
readsb-setup --config # pretty-printed /etc/config/readsb dump
readsb-feeder list # feeder sections + resolved endpoints
readsb-feeder probe # TCP-probe each enabled feeder
readsb-geoip --self-test # read-only PASS/FAIL diagnostic
service readsb status # procd status
Removes the package(s) installed for readsb-wiedehopf. The package's own prerm stops and disables its service for you, and its postrm cleans up /var/run/readsb:
opkg remove readsb-wiedehopf viewadsb-wiedehopf
Optional — also discard the conffile. opkg deliberately preserves your edits on remove (and saves the package default as *-opkg if it differs):
rm -f /etc/config/readsb /etc/config/readsb-opkg
feat-add-package-adsbexchange-statsAfter adding the feed above, install with:
opkg install adsbexchange-stats
The package is a periodic uploader that reads aircraft.json produced by readsb-wiedehopf, aggregates per-aircraft RSSI and counts, and POSTs the result to adsbexchange.com. It is a pure-shell bundle (Architecture: all) that ships an init script, helper functions, and the upstream json-status uploader.
readsb-wiedehopf. The uploader inherits its station UUID from readsb.main.uuid, finds aircraft.json via readsb.main.write_json, and reuses the readsb_is_uuid validator from /usr/lib/readsb/functions.sh. Generic upstream readsb ships none of those, which is why the OpenWrt DEPENDS line names readsb-wiedehopf specifically — and why the same single readsb-uuid command configures both packages' identity.
opkg install adsbexchange-stats # postinst enables the service.
# If readsb.main.uuid is already set
# (from readsb-setup or readsb-uuid),
# postinst also starts the uploader
# immediately. Otherwise — the common
# case on a fresh box — generate the
# shared UUID once and start manually:
readsb-uuid
service adsbexchange-stats start
# Once running:
service adsbexchange-stats showurl # public per-station stats URL
logread -e adsbexchange-stats -f # follow the uploader log
readsb-setup --status and readsb-feeder companions on the readsb-wiedehopf side both walk every enabled feeder and report whether the recommended companion package (this one, for the adsbexchange preset) is installed and running, with the exact fix command — so on headless setups the install hint also lands in logread -e readsb.
/etc/config/adsbexchange-stats)Single section, type adsbexchange-stats, name main:
| Option | Default | Notes |
|---|---|---|
enabled | '1' | Set '0' to keep the package installed but not run the uploader. |
json_paths_override | empty | Space-separated search list for aircraft.json. Empty = derive from readsb.main.write_json with /var/run/readsb, /run/adsbexchange-feed, /run/dump1090, /run/dump1090-fa as fallbacks. Path token charset is restricted to [A-Za-z0-9/_.+-]; unsafe tokens are dropped with a warning to syslog. |
log_level | '1' | 0 = errors only · 1 = + periodic upload summary · 2 = + one line per upload (aircraft, http, bytes, time) · 3 = + curl -v stream (request/response headers, TLS handshake). |
log_summary_interval | '300' | Seconds between the periodic summary at log_level=1. |
dns_cache | '0' | Enable the in-process DNS self-cache in json-status. Auto-disabled if a 127.0.0.0/8 resolver is in use or host/perl are missing (uploader falls back to curl). |
dns_ttl | '600' | TTL in seconds for cache entries when dns_cache=1. |
dns_ignore_local | '0' | When 1, ignore RFC1918 / loopback answers from DNS (forces public-IP resolution). |
After editing the file, commit and reload:
uci commit adsbexchange-stats
service adsbexchange-stats reload
The UUID lives in /etc/config/readsb at readsb.main.uuid. Both this uploader and readsb-wiedehopf's aggregator feeders read the same value, so registering the station with adsbexchange (via the public stats URL) ties to the same identity that shows up on adsb.lol, airplanes.live, etc.
readsb-uuid # generate (or print existing — idempotent)
# readsb-uuid -p # print only, never write
# readsb-uuid -f # force regenerate (do NOT do this after registering)
service adsbexchange-stats reload
service readsb reload
Once data is flowing, find your station's public page with:
service adsbexchange-stats showurl
# → https://www.adsbexchange.com/api/feeders/?feed=<your-uuid>
/var/run/adsbexchange-stats/env — shell-sourced config consumed by json-status; rewritten on every start/reload from the validated UCI values.uuid — copy of the active UUID with 0600 perms (the uploader reads it via UUID_FILE rather than re-querying UCI on every cycle, sidestepping the TOCTOU window with concurrent readsb-uuid).Both files are removed by stop_service and re-created by start_instance; the directory is tmpfs (/var/run → /tmp/run on stock OpenWrt) and survives only until reboot. The package's own helper sources live under /usr/lib/adsbexchange-stats/ (functions.sh, json-status-helpers.sh) and the upstream uploader payload at /usr/share/adsbexchange-stats/json-status.
logread -e adsbexchange-stats # all uploader log lines (script + json-status)
logread -e adsbexchange-stats -f # follow
# Common: missing UUID
uci -q get readsb.main.uuid && echo OK || readsb-uuid
# Common: aircraft.json not found anywhere
ls -l /var/run/readsb/aircraft.json /run/dump1090*/aircraft.json 2>/dev/null
uci show adsbexchange-stats.main.json_paths_override # check override
uci show readsb.main.write_json # check primary source
# Verbose one-shot debugging
uci set adsbexchange-stats.main.log_level='3'
uci commit adsbexchange-stats
service adsbexchange-stats reload
# (revert log_level to '1' once done — level 3 logs full HTTPS handshakes)
This package only handles ADSBexchange's statistics uploader. The actual ADS-B feed to ADSBexchange (BeastReduce-Plus over TCP to feed1.adsbexchange.com:30004) is a readsb-wiedehopf feeder section — see that package's Feeding aggregators docs. Likewise MLAT to ADSBexchange requires a separate mlat-client process and is out of scope here.
Removes the package(s) installed for adsbexchange-stats. The package's own prerm stops and disables its service for you, and its postrm cleans up /var/run/adsbexchange-stats:
opkg remove adsbexchange-stats
Optional — also discard the conffile. opkg deliberately preserves your edits on remove (and saves the package default as *-opkg if it differs):
rm -f /etc/config/adsbexchange-stats /etc/config/adsbexchange-stats-opkg
Each arch directory carries the same set of .ipk files plus a signed Packages index. The build is native for aarch64_cortex-a53; other labels are repacks (control.tar.gz rewritten with the new Architecture: line, data tarball untouched). Architecture-independent packages (PKGARCH:=all) are copied verbatim into every arch dir.
| Arch | Index | Compressed |
|---|---|---|
aarch64_cortex-a53 | Packages | Packages.gz |
aarch64_cortex-a53_neon-vfpv4 | Packages | Packages.gz |
blackoutsecure/packages — each package is built from its own branch, linked in the package's panel above.aarch64_cortex-a53_neon-vfpv4; mainline OpenWrt on the same SoC tags everything plain aarch64_cortex-a53. The two strings describe an identical ABI (NEON + VFPv4 are mandatory in ARMv8-A), but opkg's filter is a literal match. The workflow builds once and relabels.openwrt/packages. Once merged there, mainline OpenWrt users get them from downloads.openwrt.org automatically; this Cloudflare feed will keep serving GL.iNet ApNos owners until a firmware bundles them.