Metadata-Version: 2.5
Name: proflame
Version: 0.1.0
Summary: SIT Proflame 2 fireplace remote protocol: OOK frame encoder, decoder, and per-remote checksum derivation
Project-URL: Homepage, https://github.com/Aetf/proflame
Project-URL: Repository, https://github.com/Aetf/proflame
Project-URL: Issues, https://github.com/Aetf/proflame/issues
Project-URL: Changelog, https://github.com/Aetf/proflame/blob/main/CHANGELOG.md
Author-email: Aetf <aetf@unlimited-code.works>
License-Expression: MIT OR Apache-2.0
License-File: COPYRIGHT
License-File: LICENSE-APACHE
License-File: LICENSE-MIT
Keywords: fireplace,ook,proflame,remote,rf,sit-group
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Communications
Classifier: Topic :: Home Automation
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# proflame

[![CI](https://github.com/Aetf/proflame/actions/workflows/ci.yml/badge.svg)](https://github.com/Aetf/proflame/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/proflame)](https://pypi.org/project/proflame/)

The SIT Proflame 2 fireplace remote protocol, in Python: encode a complete
appliance state into OOK timings, decode received timings back into a state
and the identity of the handset that sent them, and derive the per-remote
checksum constants from a single captured frame.

Transceiver-agnostic by design: this library deals in signed-microsecond
timing lists, and a radio is whatever turns those into RF and back. The
first consumers are the [hass-proflame](https://github.com/Aetf/hass-proflame)
Home Assistant integration and the
[hackrf-proxy](https://github.com/Aetf/hackrf-proxy) daemon ecosystem, but
nothing here depends on either.

```python
from proflame import Remote, State, encode_timings, decode_frame

# One captured frame is enough to learn a handset, checksum constants and all.
heard = decode_frame(received_timings)
remote = heard.remote

# A frame always carries the complete appliance state, never a delta.
timings = encode_timings(remote, State(power=True, flame=4, light=2))
```

Two things worth knowing before building on it:

- **The checksum constants are per handset.** They fall out of any one valid
  frame (`Remote.from_frame`, `derive_key`); hardcoding one remote's
  constants produces frames every other receiver rejects.
- **The appliance is stateless and answers no questions.** Every frame
  carries the whole state, so a consumer must hold its own belief; nothing in
  the protocol confirms what the appliance did.

## Documentation and data

- The protocol derivation — physical layer, framing, field layout, checksum
  model, open questions, acknowledgments — lives in
  [docs/PROTOCOL.md](https://github.com/Aetf/proflame/blob/main/docs/PROTOCOL.md).
- The field-confirmation procedure and its results live in
  [docs/MAPPING.md](https://github.com/Aetf/proflame/blob/main/docs/MAPPING.md).
- Real captures — a community five-remote packet table (aggregated from
  [rtl_433#1905](https://github.com/merbanan/rtl_433/issues/1905)) and frames recorded
  off the air, used as golden test data — live in
  [tests/](https://github.com/Aetf/proflame/tree/main/tests).
- Bench scripts — the standalone reference decoder and the checksum analysis
  that first solved the relation — live in
  [tools/](https://github.com/Aetf/proflame/tree/main/tools).
- Related work — smartfire, rtl_433's decoder, HACS-Proflame2 — is compared
  and credited at the end of
  [docs/PROTOCOL.md](https://github.com/Aetf/proflame/blob/main/docs/PROTOCOL.md).

## License

MIT OR Apache-2.0, at your option.
