Metadata-Version: 2.4
Name: aiohomematic-contract
Version: 2026.6.1
Summary: Cross-implementation contracts (golden fixtures + reference algorithms) shared by aiohomematic and py-openccu-loom-client.
Author-email: SukramJ <sukramj@icloud.com>
License: MIT License
Project-URL: Homepage, https://github.com/sukramj/aiohomematic-contract
Project-URL: Source Code, https://github.com/sukramj/aiohomematic-contract
Project-URL: Bug Reports, https://github.com/sukramj/aiohomematic-contract/issues
Keywords: homematic,aiohomematic,openccu,contract,fixtures,golden
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Home Automation
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: python-slugify>=8.0.0
Provides-Extra: test
Requires-Dist: pytest>=8.0.0; extra == "test"
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: ruff>=0.9.0; extra == "dev"
Requires-Dist: mypy>=1.14.0; extra == "dev"
Requires-Dist: build>=1.2.0; extra == "dev"
Dynamic: license-file

# aiohomematic-contract

Cross-implementation **contracts** shared by
[`aiohomematic`](https://github.com/sukramj/aiohomematic) and
`py-openccu-loom-client`.

When more than one backend has to reproduce the same behaviour bit-for-bit, a
prose description in one repo drifts the moment a rule changes. This package is
the single source of truth for those shared behaviours, so the contract lives
in exactly one place and every consumer runs it.

Each contract ships as:

- a **golden fixture** (`data/<name>_golden.json`) — the canonical
  `input -> expected` cases, the authoritative artifact every consumer runs;
- a dependency-free **reference implementation** that the package's own tests
  validate against that fixture.

## Contracts

### `unique_id` — Home Assistant value-change routing key

The `unique_id` is the routing key for every Home Assistant value-change
subscription. `aiohomematic` derives it from device/channel addresses
(`aiohomematic/model/support.py:generate_unique_id`); `py-openccu-loom-client`
rebuilds it independently. The two must produce **bit-identical** output, or
events route to the wrong (or no) entity.

Format rules:

- `:` and `-` both fold to `_`.
- An optional `parameter` is appended as `_{parameter}`.
- An optional `prefix` is prepended as `{prefix}_` (events, buttons).
- Hub-like addresses (`hub`, `install_mode`, `program`, `sysvar`), internal
  addresses (`INT000*`) and virtual-remote addresses are prefixed with the
  `central_id`; all other addresses are not.
- The whole result is lowercased last (note: `-`/`:` folding applies to the
  _address_ only — a `-` inside the `parameter` survives, e.g.
  `ccu3_sysvar_aussen-temperatur`).

See `aiohomematic_contract/unique_id.py` for the reference implementation and
`aiohomematic/docs/drop-in-optimizations.md` for the background.

### `hub_slug` — hub data-point name slug rule

Hub data points (system variables, programs, connectivity, metrics) build their
`unique_id` as `generate_unique_id(parameter=hub_slug(legacy_name))`, where
`hub_slug` is **python-slugify with default settings** (dash separator, Unicode
transliteration, lowercased). A naive `replace()`-based cleaner diverges on
non-ASCII names — `"Außen Temperatur"` → `aussen-temperatur` (ä→a, ß→ss), not
`außen_temperatur` — producing a different `unique_id` and lost HA entities on
cutover. Reference: `aiohomematic_contract/slug.py`; golden: `data/hub_slug_golden.json`.

### `generate_channel_unique_id` — channel/device routing key

aiohomematic's second routing key (`Channel._unique_id`). No `parameter`, and
the `central_id` is prepended **only** for virtual-remote addresses (not for
hub/internal). Reference: `aiohomematic_contract/unique_id.py`; golden:
`data/channel_unique_id_golden.json`.

### `DataPointCategory` / `DataPointType` / `CommandPriority` enums

The enums HA filters on (and the command-priority levels). aiohomematic imports
them from this package; an alternative client keeps its own copy. The
`data/category_golden.json` and `data/command_golden.json` fixtures pin the
`name → value` maps so both sides can assert against them and cannot drift.

## Usage

```python
from aiohomematic_contract import generate_unique_id, load_golden_cases

# Reference algorithm:
generate_unique_id(central_id="ccu3", address="VCU1234567:1", parameter="STATE")
# -> "vcu1234567_1_state"

# Drive your own implementation against the canonical cases:
for case in load_golden_cases("unique_id"):
    assert my_impl(case) == case["expected"]
```

A consumer that vendors a copy of `data/unique_id_golden.json` should keep it
byte-identical to the canonical file here and pin the `aiohomematic-contract`
version it was copied from.

## Development

```bash
pip install -e ".[dev]"
pytest
```

## Versioning & releasing

This is a **foundational runtime package**: `aiohomematic` (and
`homematicip_local`, `py-openccu-loom-client`) import its symbols, so it must be
released **before** the consumers that use a new symbol.

- Version scheme: `YYYY.MM.NN`. Single source of truth:
  `aiohomematic_contract/const.py:VERSION`; `pyproject.toml` reads it via
  setuptools dynamic `attr`. Bump it on every published change to the shared
  surface.
- This package must never import `aiohomematic` (it is the bottom of the stack).

The full **contract-first** release order, pinning rules and local-dev workflow
live in the aiohomematic repo:
[`docs/contributor/contract_release_process.md`](https://github.com/sukramj/aiohomematic/blob/devel/docs/contributor/contract_release_process.md).

## License

MIT — see [LICENSE](LICENSE).
