Skip to content

Releases: Yggdrasil-AI-labs/adsb-to-wdgwars

v2.0.11 — wigle v1.2.0 piped-stdin + smoke portability back-port

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 03 Jun 04:31
f9f279c

What's Changed

  • v2.0.11: back-port wigle v1.2.0 piped-stdin + smoke portability fixes by @HiroAlleyCat in #19

Full Changelog: v2.0.10...v2.0.11

v2.0.10 — --preview flag (parser dry-run, Heimdall-aligned)

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 01 Jun 19:45
2bf2769

Adds `--preview` to Muninn. Parses the input, prints up to 6 normalised records as JSON-lines on stdout, then exits. No file write, no upload.

Mirrors Heimdall's `--preview` exactly so muscle memory transfers across the feeder family.

Use

```bash
./run.sh /path/to/your-capture.ndjson.gz --preview
```

Output is one JSON record per line — same shape as Heimdall's preview output. Easy to pipe into `jq`, `head`, etc.

When to use each dry-run mode

Question Flag
Did the parser understand my decoder's output? `--preview`
What does the full converted payload look like? `--stdout`
Does the upload pipeline work end-to-end without POSTing? `--upload --dry-run`

Added

  • `--preview` flag.
  • 6 new tests in `tests/test_preview.py` covering: zero exit, no file written, exactly-6 cap, JSON validity, fewer-than-6 padding, CLI help visibility.
  • README section on confirming parser output before wiring `--upload` or `--schedule`.

Verified

57/57 tests pass. README linter clean. CI green across Python 3.10/3.11/3.12.

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.9 — Scheduling in --setup (watch + periodic, dry-run)

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 01 Jun 17:11
062a10f

muninn.py --setup now offers a second optional step after the API key is saved: install a scheduled task that uploads new captures automatically.

Modes

Mode What it does When to pick
Watch Long-running daemon, uploads new files as they appear Decoder writes a new file per capture (tar1090 chunks, NDJSON sessions)
Periodic Runs every N minutes (1–60) against the current state Decoder rewrites one rolling file in place (dump1090-fa, readsb, VRS)

Per-platform mechanism (all user-scope, no sudo)

Platform Mechanism
Linux + systemd ~/.config/systemd/user/muninn-upload.{service,timer}
macOS / Linux without systemd user crontab with managed-by-muninn marker
Windows schtasks /Create at user scope

Safety net: --schedule-dry-run

Interactive flow defaults dry-run to yes — the installed task runs --dry-run, decoding and writing JSON locally without posting to wdgwars.pl. Re-run --schedule and answer No to flip to live uploads. Headless equivalent: --schedule-dry-run flag.

This catches the case where a user's host already has a configured API key and a bare --schedule install would start uploading from tick one.

Mode-switch hygiene

Switching from periodic → watch removes the orphan .timer so the stale timer doesn't keep firing into the long-lived watch service. Symmetric on watch → periodic.

Friendlier error for the post-v2.0.8 venv footgun

python3 muninn.py ... (system Python) after setup.sh installed deps into .venv/ now prints:

[muninn] missing dependency: gungnir.
[muninn] deps live in the project venv, not system Python.
[muninn] re-run with the venv interpreter, or use the run.sh wrapper:
[muninn]   /path/.venv/bin/python muninn.py ...
[muninn]   ./run.sh ...

instead of the bare ModuleNotFoundError: No module named 'gungnir' traceback.

Added CLI flags

  • --schedule (interactive, or headless with the flags below)
  • --unschedule (idempotent — removes only entries marked managed-by-muninn)
  • --schedule-mode {watch,periodic}
  • --schedule-input DIR
  • --schedule-glob PATTERN
  • --schedule-interval MINUTES
  • --schedule-dry-run

Verified live on Ubuntu 24.04 (systemd)

  • ✓ Periodic install: .service + .timer written, daemon-reloaded, enabled, active.
  • ✓ Watch install: long-running Type=simple service with Restart=on-failure, active.
  • ✓ Periodic → watch switch: orphan .timer removed cleanly.
  • ✓ Dry-run install with configured key: /api/upload-history newest timestamp unchanged before/after.
  • ✓ Uninstall: both modes removed cleanly, no orphan unit files.
  • ✓ 51/51 tests pass (19 existing + 32 new in tests/test_scheduler.py).

Full changelog

https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.8 — setup.sh: PEP 668 / Bookworm fix

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 01 Jun 15:31
3f75543

setup.sh, run.sh, and update.sh now install Muninn into a project-local .venv/ instead of the system Python.

On Raspberry Pi OS Bookworm, Debian 12+, Ubuntu 23.04+, and Homebrew Python, the previous python3 -m pip install -r requirements.txt line errored out with error: externally-managed-environment (PEP 668). The script crashed before saving the API key. Reported by a Pi24 user in the WDGoWars Discord.

Fixed

  • setup.sh no longer fails with externally-managed-environment on PEP 668 distros. Creates .venv/ on first run and uses .venv/bin/python for the install + --setup.
  • run.sh and update.sh detect .venv/bin/python and use it; fall back to python3 if no venv is present (older installs keep working).
  • If python3 -m venv itself fails (the python3-venv apt package is missing on some Pi images), the script prints the exact sudo apt install -y python3-venv python3-full line and exits cleanly instead of leaving a half-installed state.

Changed

  • README "Option B — clone with git" now shows the venv-aware manual sequence to match what setup.sh does automatically.

Unchanged

  • setup.bat — Windows Python has no PEP 668 enforcement, so python -m pip install still works there.
  • Everything else: parsing, upload, gungnir transport, web build.

Verified

  • Reproduced the original externally-managed-environment error on Ubuntu 24.04 with main.
  • Ran the new setup.sh on the same box: .venv/ created, gungnir 0.1.2 + pyModeS 3.3.0 installed inside it, import muninn succeeds against the venv interpreter.

Workaround for existing installs (no upgrade needed)

cd ~/adsb-to-wdgwars
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python muninn.py --setup

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.7 — Web build: parse_sqb no longer hangs on Pyodide

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 31 May 21:06

v2.0.6 made import sqlite3 work in the Pyodide build. Parsing still hung silently. Root cause: parse_sqb used sqlite3.connect("file:...?mode=ro", uri=True). On Pyodide's WASM sqlite3, the URI form against the virtual filesystem silently hangs — connect() never returns and never raises.

Fixed

  • parse_sqb detects sys.platform == "emscripten" and uses plain sqlite3.connect(str(path)) on the web build
  • Falls back to URI-mode connect on every other platform (CLI users keep the live-DB safety)
  • Applied to both CLI muninn.py and Pyodide web/muninn.py

Verified

  • CLI regression: sbs1_real / stratux / mayhem still 10 / 12 / 6
  • CLI SQB still 1146 records from the same fixture (win32 takes URI-mode branch, identical output to v2.0.5)

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.6 — Web build: .sqb parsing fixed in-browser

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 31 May 20:43

The web (Pyodide) build advertises .sqb in the drop zone but dropped files produced [ERR] Couldn't parse BaseStation.sqb. Pyodide unvendors sqlite3 from stdlib into a separately-loadable package; without an explicit loadPackage("sqlite3") muninn's parse_sqb raises ModuleNotFoundError at parse time.

CLI was never affected — real CPython has sqlite3 baked into stdlib. SQB support has worked on CLI since v2.0.0; this brings the web build in line.

Fixed

  • web/app.jspyodide.loadPackage(["micropip", "ssl", "sqlite3"])

Verified

  • CLI regression: sbs1_real / stratux / mayhem still 10 / 12 / 6
  • Real BaseStation SQB (637 aircraft, 788 flights) parses to 1146 records on CLI — same output now flows through the web build

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.5 — gungnir bump (upstream the /endpoint/* default)

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 31 May 20:15

Companion release to v2.0.4. v2.0.4 hotfix-flipped DEFAULT_API_URL locally to bypass Cloudflare's per-IP L7 DDoS rate-limit on /api/*. gungnir v0.1.2 now ships the same flip at the library level; this release re-points Muninn at gungnir's default so the source of truth lives upstream again.

Changed

  • requirements.txt gungnir pin: v0.1.1 → v0.1.2
  • Vendored web/gungnir/{__init__,__version__}.py synced to v0.1.2
  • muninn.py + web/muninn.py revert local DEFAULT_API_URL string back to gungnir.DEFAULT_API_URL

Unchanged

  • web/serve.py upstream and web/app.js localStorage default (already on /endpoint/upload/ from v2.0.4)
  • --api-url flag, /api/me (--whoami)
  • All parser behaviour (regression baselines hit on first try)

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.4 — Default upload URL bypasses Cloudflare L7 rate-limit

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 31 May 19:59

WDGoWars portal sits behind Cloudflare. Free-tier L7 DDoS protection per-IP-rate-limits bursts of /api/* with HTTP 429 + error code 1027 BEFORE reaching the origin's PHP, and at Muninn's batch scale (cron-driven RTL-SDR rig bulk-uploading) this surfaces as intermittent 429s that gungnir's cooldown logic deepens into a back-off cycle.

Portal-side fix: /endpoint/* is a one-line PHP alias of /api/*. Same router, same HMAC envelope, same response. URL doesn't match CF's pattern; request reaches origin.

Changed

  • DEFAULT_API_URL (CLI + Pyodide flavours) flipped from https://wdgwars.pl/api/upload/ to https://wdgwars.pl/endpoint/upload/
  • web/app.js localStorage default for the Endpoint setting updated
  • web/serve.py proxy upstream defaults to /endpoint/upload/
  • Docstrings, README, --upload help text updated

Notes

  • gungnir.DEFAULT_API_URL unchanged — other consumers keep the /api/* default until they bump independently
  • --api-url flag unchanged; force /api/upload/ with --api-url https://wdgwars.pl/api/upload/ if needed
  • /api/me (used by --whoami) unchanged. Single-call, not affected by burst rate-limiting

Smoke-tested against fixtures: sbs1_real / stratux / mayhem parse to 10 / 12 / 6 aircraft as documented.

Full changelog: https://github.com/HiroAlleyCat/adsb-to-wdgwars/blob/main/CHANGELOG.md

v2.0.1 — update-checker semver fix

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 29 May 03:45

Patch release.

Fixed

  • _check_for_update was comparing the GitHub releases tag against __version__ with != instead of >. On v2.0.0 (ahead of the published release at the time), it falsely reported v1.11.1 is available and suggested downgrading. Now uses a small inline semver parser and reports only when the latest tag is strictly newer.

Added

  • _version_tuple() helper — tolerates a leading v and pre-release / build suffixes. Unparseable versions skip the check gracefully.

Verification

Live muninn --whoami against wdgwars.pl after the fix: no more bogus update-suggestion line.

v2.0.0 — extract transport to gungnir

Choose a tag to compare

@HiroAlleyCat HiroAlleyCat released this 29 May 03:40

Highlights

Muninn's HMAC envelope, signed POST, key handling, cooldown, silent-drop detection, and SSL context now live in gungnir — a shared transport library that Heimdall and wigle-to-wdgwars will also sit on in subsequent releases. Muninn becomes a focused ADS-B layer over the shared transport.

Wire-protocol byte-identical to v1.11.1. Verified by a parity test and by a live upload of 12 real aircraft from a Lorain, OH dump1090 feed to your wdgwars.pl account. Existing v1.x cron jobs, API keys, and config paths keep working unchanged.

Free behavior wins

Behavior v1.11.1 v2.0.0
Transient 5xx + network errors fail immediately retry 3× with exponential backoff (2s / 4s)
429 mid-batch keep POSTing more chunks stop batch, persist deadline, next cron tick respects it
Silent drop (HTTP 200 ok:true, zero counters) log warning, rc=0 log warning, rc=1 — surfaces to cron
Inter-chunk delay back-to-back 1s default
User-Agent muninn/1.11.1 muninn/2.0.0 (+https://github.com/HiroAlleyCat/adsb-to-wdgwars)
API-key redaction required len(key) > 8 (leaked short keys) always redacts on non-empty match

Migration

pip install -r requirements.txt   # pulls gungnir from the pinned commit
  • No config-file changes. ~/.config/muninn/api.key and %APPDATA%\muninn\api.key read in place.
  • No cron-stanza changes. Same invocation, same exit codes.
  • Function signatures preserved as thin shims (upload, load_key, save_key, check_whoami, etc.) so any external script importing from muninn keeps working.

Compatibility note

gungnir is currently installed from a pinned commit URL in requirements.txt. When gungnir publishes to PyPI, that line will become a normal gungnir>=X.Y pin.

Full diff

PR #4