Skip to content

Releases: junzis/pyModeS

v3.3.0

19 Apr 18:54

Choose a tag to compare

Highlights

PipeDecoder: reject CRC-lucky phantoms

CRC-24 alone isn't enough — ~1-in-16M random 1090 MHz FRUIT survives
CRC with a plausible ICAO but garbage payload. This release adds four
plausibility cross-checks layered on top of CRC, each reusing a
per-ICAO anchor updated only from CRC-valid frames that pass their
own check:

  • DF17/18 BDS 0,5 (airborne position) — altitude vs ADS-B anchor.
  • DF17/18 TC=19 (airborne velocity) — groundspeed/track vs anchor,
    plus a |VR| > 10 000 fpm guard that fires even without an anchor.
  • DF20/21 BDS 5,0 (track & turn) — groundspeed/true-track vs the
    ADS-B velocity anchor.
  • DF20/21 BDS 6,0 (heading & speed) — magnetic_heading vs ADS-B
    track (wider tolerance to absorb magnetic variation + wind-correction
    angle).

Rejected frames keep their header fields so callers can see what
happened, but the velocity / position fields are scrubbed and the
anchor isn't updated. A new velocity_mismatch stats counter joins
the existing altitude_mismatch.

PipeDecoder: preserve paired frames

Two structural fixes to stop legitimate positions from being dropped:

  • _pending_even / _pending_odd are now per-parity deques so two
    same-parity frames arriving before an opposite don't silently
    discard the earlier one — orphan halves pair against the arriving
    frame and each gets its own resolved position.
  • Bootstrap entries hold a list of result dicts so both halves
    of a resolved CPR pair get their latitude/longitude retroactively
    filled when the bootstrap cluster locks.

Docs

  • New Interesting messages
    reference page — a growing catalogue of real-world messages
    exhibiting edge cases (CRC-lucky phantoms, FRUIT, BDS ambiguity,
    malformed payloads) to use when debugging or writing new checks.

Dev

  • Repo now ships a pre-commit config running ruff-format + ruff-check.
    After cloning: uv sync && uv run pre-commit install.

Full Changelog: v3.2.0...v3.3.0

v3.2.0

17 Apr 12:03

Choose a tag to compare

Full Changelog: v3.1.0...v3.2.0

v3.1.0

16 Apr 16:50

Choose a tag to compare

What's Changed

  • build(deps-dev): bump pytest from 9.0.2 to 9.0.3 by @dependabot[bot] in #198

Full Changelog: v3.0.0...v3.1.0

v3.0.0

13 Apr 08:19

Choose a tag to compare

First release of the v3 ground-up rewrite. Not backwards-compatible with pyModeS 2.x. See the migration guide before upgrading.

pip install "pyModeS>=3"

Python 3.11+ required.

Highlights

  • One unified decode() function. Returns a Decoded dict with every decodable field populated in a single call. Handles single hex strings or batched lists with per-message timestamps; errors become error-dicts instead of exceptions.
  • Stateful streaming via PipeDecoder. Per-ICAO state, automatic even/odd CPR pair matching, TTL eviction, and DF20/21 icao_verified promotion from a trusted-address set populated off clean DF17/18 frames.
  • Reference-assisted Comm-B disambiguation. BDS 5,0 vs 6,0 ambiguity is resolved by scoring candidates against cached groundspeed / track / heading / mach when passed via known=, or automatically in PipeDecoder.
  • New modes CLI with two subcommands:
    • modes decode — one-shot, inline-batch, or file-based hex→JSON
    • modes live --network HOST:PORT — streaming TCP → JSON lines, with sub-microsecond timestamps derived from the Mode-S Beast MLAT counter (tick rate auto-calibrated, so dump1090 and radarcape/AirSquitter both work without config)
    • modes live --tui — interactive textual-based aircraft table with keyboard navigation, live incremental search, sort cycling, and diff-update cell redraws (requires pyModeS[tui] extra)
  • Pure Python. Dropped the Cython c_common extension and the numpy hard dependency. Internal representation is Python int + bit-shift primitives; no wheel build per Python version.
  • Airport database for surface CPR: surface_ref="EHAM" or surface_ref=(lat, lon).
  • Optional full_dict=True populates every key in the 123-field canonical schema for pandas / parquet workflows.

Breaking changes

  • Legacy function-per-field API removed (pms.adsb.callsign, pms.commb.bds, pms.common.hex2bin, etc.). The old submodule paths are intercepted by a meta-path finder that raises V2APIRemovedError (ImportError subclass) with a migration hint. pyModeS.common helpers are restored as pyModeS.util (hex2bin, bin2int, hex2int, crc, df, icao, typecode, altcode, idcode, cprNL).
  • Python 3.11+ minimum (was 3.9+).
  • numpy is no longer a dependency.
  • modeslive CLI entry point replaced by modes live / modes decode. The old modeslive script prints a migration hint and exits code 2 instead of vanishing.
  • CPR resolution API: reference=(lat, lon) for airborne (180 NM tolerance), surface_ref="EHAM" or surface_ref=(lat, lon) for surface (45 NM tolerance).

Staying on v2

pip install "pyModeS<3"

v2 and v3 share the same PyPI distribution slot; pinning <3 keeps you on the 2.x line indefinitely.

Full changelog

See CHANGELOG.md for the complete list of added / fixed / changed / removed items.

Full diff: v2.22.0...v3.0.0

v2.22.0

09 Apr 09:55

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v2.21.1...v2.22.0

v2.21.1

09 Jul 15:52
0a1c403

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v2.21...v2.21.1

v2.21

03 Jul 15:52

Choose a tag to compare

What's Changed

Full Changelog: v2.20...v2.21

v2.20

19 Mar 23:40

Choose a tag to compare

What's Changed

  • Fixed C code build process, now they can be built with uv build
  • Fixed error when receiving NICv1 in example decoder due to mismatch in output by @kestr31 in #180
  • Fix for a corner-case numerical problem and corresponding unit test. by @EdFuentetaja in #181
  • Fix floating point display on terminal output by @jbencina in #183
  • Explicitly set multiprocessing start method to fork for OSX support by @jbencina in #182

New Contributors

Full Changelog: v2.19...v2.20

v2.19

26 Nov 14:42

Choose a tag to compare

Fixes:

  • BDS50: track angle when bits are all zeros or ones
  • BDS50: vertical rates when bits are all zeros or ones

Changed from poetry to uv for package management.

v2.18

25 Aug 11:38

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v2.17...v2.18