Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

airdress-home

Link a home hub such as Home Assistant to an airdress, so that functions running on your airdress's operator can operate and observe exactly the entities you chose to share — and nothing else.

This is the protocol library the Home Assistant integration uses. It has no Home Assistant dependency: it is plain asyncio on aiohttp and cryptography, strictly typed.

Status: beta (0.1.0b1). Both channel transports stay and are negotiated; 0.1.0 follows once their default order and fallback thresholds are measured, and the API may change until then.

What it does

  • Enrollment as a machine. The hub generates an Ed25519 key and asks the operator to enroll it. The owner compares a confirmation code and approves on the operator. The hub never receives a bearer or a secret: it signs each request with its own key (RFC 9421, airdress-machine tag).
  • A pinned operator key. The operator signs its enrollment answer; the hub verifies it, and from then on accepts a frame only if it verifies under that same key.
  • One held channel, dialled by the hub. The hub is behind NAT and the operator cannot dial it. The hub keeps a channel open, and the operator sends it signed frames: call and read, which the hub answers, features (what the operator's Home declares) and emit (an event for the hub).
  • Multi-transport. Every transport carries the same signed frames, seq and session, and each stays:
    • channel.WsChannel — a WebSocket;
    • channel.PollChannel — a streaming long-poll, rotated before a relay's idle timeout, with batched upstream requests;
    • channel.NegotiatingChannel — what channel.for_client returns: it tries the preferred transport first, falls back when its establishment is refused on the way or it keeps dropping early, remembers per network what worked (a HintStore; FileHintStore keeps it in one small file, holding no address), and probes the preferred transport again after a while.
  • The rendezvous. "Sign in with Airdress": the hub (account.airdress.co) introduces the hub to the owner's operator without anyone typing an address. It never approves and never sees a key.

Every operator frame carries a session, a strictly increasing seq and a notAfter; a repeated seq is dropped and a gap is counted.

Using it

import aiohttp
from airdress_home import MachineKey, MachineClient, HomeSession, start_enrollment, poll_until_decided
from airdress_home.channel import FileHintStore, for_client

async with aiohttp.ClientSession() as http:
    key = MachineKey.generate()
    started = await start_enrollment(http, "https://<your airdress>", key, "Home Assistant")
    print("Confirm on your operator:", started.user_code, started.confirmation_code)
    enrollment = await poll_until_decided(http, "https://<your airdress>", key, started)

    client = MachineClient(http, key, enrollment)
    channel = for_client(client, hints=FileHintStore("transport-hints.json"))
    session = HomeSession(channel, handler, enrollment.pinned_key)
    await session.run()

handler implements airdress_home.Handler: call, read, shared, features and emit. The session keeps the hub's own ceilings whatever the operator sends (60 calls and 60 emits a minute by default), and airdress_home.is_sensitive names the entities — locks, alarm panels, and entry-point or unclassified covers — that the hub must refuse to operate unless its user opted each one in. Applications hold channel.for_client(client) rather than naming a transport; channel.name is the transport in use.

The airdress package

The PyPI project airdress is built from airdress/ in this repository: a small meta-package that installs airdress-home and makes import airdress.home that package.

Development

uv sync
uv run pytest
uv run mypy
prek install   # the same checks CI runs, and the commit-msg hook

tests/vectors/vectors.json is shared with the operator: every value in it is recomputed by both implementations.

Commits and releases

Commit messages and PR titles are conventional commits (fix: …, feat: …, docs: …, feat!: … for a breaking change). The commit-msg hook checks each commit, and CI checks a PR's title and commits. PRs are merged by rebase (merge commits are off): the PR's own commits are the history release-please reads, so each one should say what it changes.

Releases are made by release-please, never by hand:

  1. Every push to main updates one open release PR, chore(main): release <version>, with the next version in pyproject.toml and .release-please-manifest.json, uv.lock re-locked, and the new CHANGELOG.md entry. A fix: or feat: commit makes one; docs:, chore:, ci: and the like do not on their own.
  2. Merging that PR tags vX.Y.Z-bN and creates a draft GitHub release.
  3. The tag starts release.yml: it checks the tag against the version, tests, builds and publishes both packages to PyPI by trusted publishing, then publishes the draft release.

Until 0.1.0 every version is a beta: fix:, feat: and even a breaking change all move 0.1.0-b3 to 0.1.0-b4. release-please spells it with a hyphen; every Python tool reads it as the PEP 440 version 0.1.0b4, which is what PyPI shows. To leave the betas, put Release-As: 0.1.0 in the body of a commit on main, and remove versioning, prerelease and prerelease-type from release-please-config.json.

The airdress meta-package is not part of this cycle. It keeps its own version (0.0.0), which changes only when its own API does: bump it by hand in airdress/pyproject.toml in an ordinary PR, and the next release tag publishes it with airdress-home. A release that leaves it alone skips it.

Licence

Apache License 2.0.

Metadata

Release files for airdress-home 0.1.0b4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for airdress-home 0.1.0b4
File Size Uploaded
airdress_home-0.1.0b4.tar.gz 129.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for airdress-home 0.1.0b4
File Interpreter ABI Platform
airdress_home-0.1.0b4-py3-none-any.whl Python 3 none any Details

Total release size: 176.6 kB

Release files / airdress_home-0.1.0b4.tar.gz

Download URL airdress_home-0.1.0b4.tar.gz
Size 129.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3d23768b7acd5bba08cd062fe6ae04614571ead6f81e8ab0a5330629f7e170f6
BLAKE2b-256 checksum
How to use checksums
b41aa4aad4efb5de14896cc9ad9b9b9cae00198b099f9f819c1f171ca3415c0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / airdress_home-0.1.0b4-py3-none-any.whl

Download URL airdress_home-0.1.0b4-py3-none-any.whl
Size 46.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
47740063883b2e4d0b1eec178f8db598a6c43ab2d35bd6c6cd59a0ddb46315f1
BLAKE2b-256 checksum
How to use checksums
dd6de472e74120d3dba589a5017b3191f923db53c820ea476202635444214138
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0b4 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page