Metadata-Version: 2.4
Name: pyobelix
Version: 0.1.0
Summary: Pure-Python decoder for EUROCONTROL ASTERIX surveillance data
Project-URL: repository, https://github.com/junzis/pyobelix
Project-URL: issues, https://github.com/junzis/pyobelix/issues
Author-email: Junzi Sun <git@junzis.com>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# pyobelix

Pure-Python decoder for EUROCONTROL ASTERIX surveillance data. Sibling library to [pyModeS](https://github.com/junzis/pyModeS) for Mode-S / ADS-B decoding.

[![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)

## Install

```sh
pip install "pyobelix>=0.1"
```

Python 3.11+ required. Zero runtime dependencies.

## Quick start

```python
from pyobelix import iter_records

for rec in iter_records("path/to/asterix.bin"):
    if rec.cat == 48 and "rho" in rec:
        print(rec["icao"], rec["rho"], rec["theta"])
```

Accepts file paths, `bytes`/`bytearray`, or any `BinaryIO` stream.

## Streaming from a socket

```python
from pyobelix import AsterixDecoder

dec = AsterixDecoder()
while True:
    chunk = sock.recv(4096)
    if not chunk:
        break
    dec.feed(chunk)
    for rec in dec.records():
        process(rec)
```

## Decoding Mode-S Comm-B (MB) with pyModeS

pyobelix emits CAT 048 I/250 MB payloads as opaque 14-char uppercase hex strings. To decode the Mode-S fields:

```python
import pyModeS
from pyobelix import iter_records

for rec in iter_records(path):
    if rec.cat != 48:
        continue
    for mb in rec.get("mode_s_mb", []):
        decoded = pyModeS.Message.from_payload(
            mb["mb"], df=20, icao=rec["icao"]
        ).decode()
        print(decoded)
```

See [`docs/pymodes-bridge.md`](./docs/pymodes-bridge.md) for the full recipe.

## Supported categories (v.0.1.0)

- **CAT 048** — Monoradar Target Reports (EUROCONTROL-SPEC-0149-4 Ed. 1.32)
- **CAT 034** — Monoradar Service Messages (EUROCONTROL-SPEC-0149-2B Ed. 1.29)

Additional categories (021, 062, …) planned for v.0.2.0. See the design spec for the full roadmap.

## License

MIT. See [LICENSE](./LICENSE).
