Add Home Assistant integration
Token-authenticated custom component exposing live per-club member counts as sensors under a single "West Wood Club" device, fed by one coordinator polling `/v1/Clubs/WhoIsInCount`. Packaged via `buildHomeAssistantComponent` with a flake package + overlay so it can be used in `services.home-assistant.customComponents`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,8 @@ Groundwork for a **Home Assistant integration for West Wood Club** (an Irish gym
|
||||
chain). The West Wood app is a white-label build of **PerfectGym Go**, so the
|
||||
integration targets PerfectGym's hosted backend at `https://goapi2.perfectgym.com`.
|
||||
|
||||
The integration itself isn't written yet — the repo currently holds a
|
||||
reverse-engineering capture, the API docs derived from it, and a login helper.
|
||||
The repo holds the reverse-engineering capture, the API docs derived from it, a
|
||||
token helper, and the Home Assistant custom component itself (see Integration).
|
||||
|
||||
## Layout
|
||||
|
||||
@@ -15,6 +15,7 @@ reverse-engineering capture, the API docs derived from it, and a login helper.
|
||||
secrets redacted. The source of truth for API behaviour; extend it as more
|
||||
endpoints are mapped.
|
||||
- `get-token.py` — logs in and prints a bearer token to stdout (stdlib only).
|
||||
- `custom_components/west_wood_club/` — the Home Assistant integration.
|
||||
- `android-flows.mitm` — mitmproxy capture of the app's traffic. **Gitignored and
|
||||
untracked**: it contains real credentials and a bearer token in cleartext. Never
|
||||
commit it or copy its secrets into tracked files.
|
||||
@@ -33,6 +34,12 @@ Gotchas:
|
||||
- `nix develop --command` may change cwd — use **absolute paths** when a script
|
||||
opens `android-flows.mitm`.
|
||||
|
||||
## Code style
|
||||
|
||||
Python uses **single-quoted strings** (`'...'`). Reformat with
|
||||
`ruff format --config "format.quote-style='single'" <paths>` (ruff is available via
|
||||
`nix run nixpkgs#ruff`). Docstrings stay triple-double-quoted (`"""`).
|
||||
|
||||
## Working with the capture
|
||||
|
||||
Read flows with the mitmproxy Python API:
|
||||
@@ -64,6 +71,29 @@ Full detail in `api.md`. Quick reference:
|
||||
- **Live occupancy:** `GET /v1/Clubs/WhoIsInCount` → `count` per `clubId` (the main
|
||||
sensor signal). `clubId` maps to `id` from `GET /v1/Clubs/Clubs`.
|
||||
|
||||
## Integration
|
||||
|
||||
`custom_components/west_wood_club/` is a UI-configured (config-flow) integration.
|
||||
|
||||
- **Auth model:** the user pastes a long-lived bearer token (from `get-token.py`);
|
||||
no credentials are stored. A rejected token (`WestWoodAuthError` → coordinator
|
||||
raises `ConfigEntryAuthFailed`) triggers HA's reauth flow to paste a fresh one.
|
||||
- **One device, N sensors:** a single `DataUpdateCoordinator` polls
|
||||
`WhoIsInCount` once per interval for all clubs; one `SensorEntity` per selected
|
||||
club reads its `club_id` out of `coordinator.data`. All sensors share one
|
||||
device (`identifiers={(DOMAIN, entry.entry_id)}`) named "West Wood Club".
|
||||
- **Config flow steps:** `user` and `reauth` are HA-fixed names (dispatched by the
|
||||
flow *source*); `clubs` and `reauth_confirm` are reached because a form was shown
|
||||
with that `step_id` (HA calls `async_step_<step_id>` on submit). Every step name
|
||||
must also have a matching key under `config.step` in `strings.json`.
|
||||
- **Nix:** `flake.nix` exposes `packages.west_wood_club` (built with
|
||||
`buildHomeAssistantComponent`) and `overlays.default`, which adds it to
|
||||
`pkgs.home-assistant-custom-components`. On a NixOS host, apply the overlay and
|
||||
list it in `services.home-assistant.customComponents`; it must be built against
|
||||
the same Python as the host's `home-assistant`. Bump `version` in both
|
||||
`manifest.json` and the flake on code changes. The integration has **no**
|
||||
external `requirements`, so no extra Nix packaging is needed.
|
||||
|
||||
## Security
|
||||
|
||||
The capture and `token.txt` hold live credentials/tokens. Keep them gitignored,
|
||||
|
||||
Reference in New Issue
Block a user