Releases: junzis/pyModeS
v3.3.0
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 fpmguard 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_oddare 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 theirlatitude/longituderetroactively
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
Full Changelog: v3.1.0...v3.2.0
v3.1.0
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
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 aDecodeddict 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/21icao_verifiedpromotion 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 inPipeDecoder. - New
modesCLI with two subcommands:modes decode— one-shot, inline-batch, or file-based hex→JSONmodes 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 (requirespyModeS[tui]extra)
- Pure Python. Dropped the Cython
c_commonextension and the numpy hard dependency. Internal representation is Pythonint+ bit-shift primitives; no wheel build per Python version. - Airport database for surface CPR:
surface_ref="EHAM"orsurface_ref=(lat, lon). - Optional
full_dict=Truepopulates 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 raisesV2APIRemovedError(ImportErrorsubclass) with a migration hint.pyModeS.commonhelpers are restored aspyModeS.util(hex2bin,bin2int,hex2int,crc,df,icao,typecode,altcode,idcode,cprNL). - Python 3.11+ minimum (was 3.9+).
- numpy is no longer a dependency.
modesliveCLI entry point replaced bymodes live/modes decode. The oldmodeslivescript 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"orsurface_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
v2.21.1
What's Changed
- fix type hints for temp44() by @Job-Heersink in #188
New Contributors
- @Job-Heersink made their first contribution in #188
Full Changelog: v2.21...v2.21.1
v2.21
v2.20
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
- @kestr31 made their first contribution in #180
- @EdFuentetaja made their first contribution in #181
- @jbencina made their first contribution in #183
Full Changelog: v2.19...v2.20
v2.19
v2.18
What's Changed
- Bump snok/install-poetry from 1.3.3 to 1.3.4 by @dependabot in #156
- Bump actions/checkout from 3 to 4 by @dependabot in #158
- Properly return None if altitude could not be decoded by @paulmadejong in #162
- Update allcall.py by @Flyer350 in #161
- DI = 1 correction for uplink messages by @Flyer350 in #157
- Bump actions/setup-python from 4 to 5 by @dependabot in #163
- Bump codecov/codecov-action from 3 to 4 by @dependabot in #165
- Bump actions/cache from 3 to 4 by @dependabot in #166
- Added a function that retrieves RSSI values from Mode-S messages received by PiAware devices by @kirth123 in #172
- Bump snok/install-poetry from 1.3.4 to 1.4.0 by @dependabot in #171
- Fixed "Megnatic" typo by @chrislanzara in #170
- Some annotations for physical quantities by @xoolive in #151
- Mods20230421a by @gituser283 in #146
New Contributors
- @kirth123 made their first contribution in #172
- @chrislanzara made their first contribution in #170
- @gituser283 made their first contribution in #146
Full Changelog: v2.17...v2.18