From 4083e14247d8a15be2ef0315786cb3dd58f3247f Mon Sep 17 00:00:00 2001 From: Matysh Date: Wed, 29 Jul 2026 15:51:07 +0300 Subject: [PATCH] docs: everything caught up with v1.51.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A sweep of every document against the shipped behaviour: - README en+ru: the space dialog no longer claims a background is mandatory (draw-by-hand and the saved-plans picker exist; the canvas is square); 'Show all devices' sections rewritten for the hide-flag world — the checkbox, 'Show hidden' ghosts, LQI-yes/light-no; troubleshooting updated. - ARCHITECTURE: the config schema block still described v1.3 — aspect/device_overrides/virtual_devices/1000x1000-per-aspect/legacy-bundle fallback, all long gone. Rewritten to the current shape (square canvas, markers with hidden, filter_seeded, quotas, signed urls). The WS table dropped houseplan/file/set (removed in v1.10.0) and gained geometry/repair, layout/delete, files/migrate, files/cleanup, content/sign, the plans/list cap. - UX-MODES: the Devices-tab tool list names the checkbox and the local 'Show hidden' instead of the retired shared show-all. - ROADMAP: repair-issues, system_health, floors import, data icon rules, click actions, theming and JSON i18n were done releases ago — checked off with their versions; the HACS pointer is #9004 (bot closed #8995). - STATUS: SSH port is 22222 and the HA config root is /mnt/data/supervisor/homeassistant (/config does not exist there); the key lives in houseplan/.secrets; the PAT note reflects the fine-grained token; the feature surface gained the v1.42-v1.51 era. - DEVELOPMENT: deploy instructions with the real port, path and cache busting. - The owner's product description (user folder) refreshed the same way: square canvas, hide flags, the yellow principle. --- README.md | 6 +++--- README.ru.md | 6 +++--- docs/ARCHITECTURE.md | 48 +++++++++++++++++++++++++++++++------------- docs/DEVELOPMENT.md | 9 +++++++-- docs/ROADMAP.md | 26 +++++++++++++----------- docs/STATUS.md | 35 +++++++++++++++++++++++++------- docs/UX-MODES.md | 8 +++++--- 7 files changed, 94 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 2ff71b0..8cb20d8 100755 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ for each floor (names prefilled, a plan image is asked for one by one; any floor ![Empty plan — prompt to add a space](docs/images/02-onboarding-empty.png) -In the dialog, set a **name** (for example, "1st floor") and **upload a background** — a floor-plan image in SVG, PNG or JPG format. Both fields are required: without a plan the "Save" button stays disabled. +In the dialog, set a **name** (for example, "1st floor") and pick the background: **upload** a floor-plan image (SVG, PNG, JPG, WebP), **choose one already uploaded** to the server earlier, or select **"no background, I'll draw the rooms"** for a hand-drawn space. The canvas is always square; an image keeps its own proportions and is centred inside it. ![Space creation dialog](docs/images/03-space-dialog.png) @@ -204,7 +204,7 @@ walls** (it slides around corners too), and a **double click opens its propertie As soon as you save a room bound to an area, **the devices of that area are automatically laid out inside the outline**. These are the same devices shown on the **Settings → Devices → (filtered by the room)** page — only the meaningful ones, without service records, bridges and duplicates. -By default only meaningful devices make it onto the plan — service records, bridges and duplicates are filtered out. If you need to see **absolutely all** devices of the area, enable the **👁 "Show all devices"** button in the header. +By default only meaningful devices make it onto the plan: non-physical ones (service records, bridges, scenes, individual lamps folded into a light group) arrive with the **"Hide device from plan"** checkbox already ticked. The checkbox is yours from then on — every device dialog has it, virtual devices included. To see and un-hide them, open the device editor and press **"Show hidden"**: hidden devices appear as translucent blue ghosts, a click opens the dialog. Hidden devices still count toward the room's Zigbee signal, but cast no light. From here on you can just use the plan: clicking an icon opens the device card with the model, link and a button to jump into Home Assistant. @@ -286,7 +286,7 @@ Services → House Plan**. **Do I need to write anything in YAML?** No. The only line is adding the card to the dashboard; everything else is done with the mouse. -**My devices did not appear on the plan.** A device appears only if its Home Assistant area is bound to a drawn room. Check that the device has a room assigned (Settings → Devices) and that the room is outlined and bound to that area. If the device exists but is hidden by filtering (bridges, service records, duplicates) — enable the **👁 "Show all devices"** button in the header. +**My devices did not appear on the plan.** A device appears only if its Home Assistant area is bound to a drawn room. Check that the device has a room assigned (Settings → Devices) and that the room is outlined and bound to that area. If the device exists but is hidden (the "Hide device from plan" checkbox — set automatically for bridges, scenes and other non-physical records) — open the device editor, press **"Show hidden"** and untick the box in its dialog. **Can I hide an unwanted device or rename it?** Yes — click the device on the plan and press "Edit" in its card: there you can change the name, icon, model or hide the icon. diff --git a/README.ru.md b/README.ru.md index 5e13775..24501ce 100644 --- a/README.ru.md +++ b/README.ru.md @@ -162,7 +162,7 @@ title: План дома ![Пустой план — предложение добавить пространство](docs/images/02-onboarding-empty.png) -В диалоге задайте **название** (например, «1 этаж») и **загрузите подложку** — картинку плана этажа в формате SVG, PNG или JPG. Оба поля обязательны: без плана кнопка «Сохранить» неактивна. +В диалоге задайте **название** (например, «1 этаж») и выберите подложку: **загрузите** картинку плана (SVG, PNG, JPG, WebP), **возьмите уже загруженную** на сервер ранее или отметьте **«без подложки, нарисую комнаты сам»**. Холст всегда квадратный; картинка сохраняет свои пропорции и центрируется внутри него. ![Диалог создания пространства](docs/images/03-space-dialog.png) @@ -205,7 +205,7 @@ title: План дома Как только вы сохранили комнату с привязкой к зоне, **устройства этой зоны автоматически расставляются внутри контура**. Берутся те же устройства, что показаны на странице **Настройки → Устройства → (фильтр по нужной комнате)** — только осмысленные, без служебных записей, мостов и дубликатов. -По умолчанию на план попадают только осмысленные устройства — служебные записи, мосты и дубликаты отфильтрованы. Если нужно видеть **вообще все** устройства зоны, включите в шапке кнопку **👁 «Показать все устройства»**. +По умолчанию на план попадают только осмысленные устройства: нефизические (служебные записи, мосты, сцены, лампы, свёрнутые в световую группу) приходят с уже установленной галкой **«Скрыть устройство с плана»**. Дальше галка принадлежит вам — она есть в диалоге каждого устройства, включая виртуальные. Чтобы увидеть и вернуть скрытые, откройте редактор устройств и нажмите **«Показать скрытые»**: скрытые отобразятся полупрозрачными синими призраками, клик открывает диалог. Скрытые устройства учитываются в Zigbee-сигнале комнаты, но света не дают. Дальше можно просто пользоваться планом: клик по иконке открывает карточку устройства с моделью, ссылкой и кнопкой перехода в Home Assistant. @@ -288,7 +288,7 @@ title: План дома **Нужно ли что-то писать в YAML?** Нет. Единственная строчка — это добавление карточки на дашборд; всё остальное делается мышкой. -**Мои устройства не появились на плане.** Устройство появляется, только если его зона в Home Assistant привязана к нарисованной комнате. Проверьте, что у устройства задана комната (Настройки → Устройства), а комната обведена и привязана к этой зоне. Если устройство есть, но скрыто курированием (мосты, служебные, дубликаты) — включите в шапке кнопку **👁 «Показать все устройства»**. +**Мои устройства не появились на плане.** Устройство появляется, только если его зона в Home Assistant привязана к нарисованной комнате. Проверьте, что у устройства задана комната (Настройки → Устройства), а комната обведена и привязана к этой зоне. Если устройство есть, но скрыто (галка «Скрыть устройство с плана» — для мостов, сцен и прочих нефизических записей она ставится автоматически) — откройте редактор устройств, нажмите **«Показать скрытые»** и снимите галку в его диалоге. **Можно ли скрыть лишнее устройство или переименовать его?** Да — кликните по устройству на плане и в его карточке нажмите «Редактировать»: там можно сменить имя, иконку, модель или скрыть значок. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index a9d1982..3e3f3aa 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -100,23 +100,36 @@ name?, icon?, model?, link?, description?, pdfs:[{name,url}]}`. A hybrid: auto-d appear on their own; a marker with `binding=device:` overrides them (metadata/rebinding/hiding), `entity:` — for groups/helpers, `virtual` — a manual icon without HA. The marker id = device_id / `lg_` / `v_` (preserves the position in the layout). The binding picker excludes already-placed -references and duplicates by name|area. Manual files: `houseplan/file/set` → `/config/houseplan/files//`, -served from `/houseplan_files/files/`. +references and duplicates by name|area. Manual files: transactional HTTP upload into `/houseplan/files//` +(staging `up_*` folders promoted on save), served via signed +`/api/houseplan/content/files/…` urls. -## Server-side configuration (v1.3.0+) +## Server-side configuration (current shape, v1.51+) `.storage/houseplan.config` (Store): ```json -{ "spaces": [{ "id","title","plan_url","aspect","view_box":[4],"rooms":[{"id","name","area","x","y","w","h"}] }], - "device_overrides": {"": {"hidden","icon","name"}}, - "virtual_devices": [{"id","space","name","icon","x","y","note?","entity_id?"}], - "settings": {"exclude_integrations":[],"group_lights":true} } +{ "spaces": [{ "id","title","plan_url","plan_aspect","view_box":[4], + "rooms":[{"id","name","area","poly|x/y/w/h","open_to","settings"}], + "openings":[…], "decor":[…], "settings":{…} }], + "markers": [{ "id","binding":"device:|entity:|virtual","hidden", + "name","icon","display","controls","is_light","tap_action", + "room_id","pdfs",… }], + "settings": { "exclude_integrations":[], "group_lights":true, + "filter_seeded":true, "fill_colors":{…}, "icon_rules":[…], + "known_devices":[…], "new_device_ids":[…] } } ``` -All coordinates are **normalized (0..1 of the space plan)**; the render space is -1000 × 1000/aspect. Layout v2: `{device_id: {"s": space, "x", "y"}}` (normalized). -Plan files: `/houseplan/plans/.` → URL `/houseplan_files/plans/…`. -If the server config is empty, the card falls back to the legacy bundle (the dacha) and shows a -"To server" migration button in edit mode. The dacha was migrated on 2026-07-04. +All coordinates are **normalized (0..1 of the canvas)**; the canvas is always +**square** (v1.48.0), render space `NORM_W × NORM_W` (1000×1000). A space has no +proportions of its own — `plan_aspect` is the IMAGE's ratio, used to letterbox +it centred on the square. The schema bounds geometry to ±4 with strictly +positive sizes (HP-1501/1502). `device_overrides`/`virtual_devices` are long +gone — markers carry everything, `marker.hidden` is the explicit +"hide from plan" flag seeded once by the old filter (docs/FILTERING.md). +Layout v2: `{device_id | rl_: {"s": space, "x", "y"}}` (normalized, +bounded ±4). Plan files: `/houseplan/plans/..` +(copy-on-write, never overwritten), served via signed +`/api/houseplan/content/plans/_/` urls; growth is bounded by store +quotas, nothing is ever deleted for being old (docs/SCOPE.md). ## Room geometry rules (v1.19–v1.21) @@ -178,9 +191,16 @@ double click → properties dialog. In markup mode the "Opening" tool handles cl | `houseplan/config/get` | — | `{config, rev}` | | `houseplan/config/set` | `config`, `expected_rev?` | `{ok, rev}` / err `conflict`; event `houseplan_config_updated` | | `houseplan/plan/set` | `space_id`, `ext` (svg/png/jpg/webp), `data` (b64, ≤8 MB) | `{ok, url}` — writes `..`, deletes nothing | -| `houseplan/plans/list` | — | `{plans: [{name, url, size, modified, used_by}]}` | +| `houseplan/plans/list` | — | `{plans: [{name, url, size, modified, used_by}], total}` (newest 60) | | `houseplan/plans/delete` | `name` | `{ok, removed}` / err `in_use` | -| `houseplan/file/set` | `marker_id`, `filename`, `data` (b64) | `{ok,url,name}` (legacy, WS limit) | +| `houseplan/layout/delete` | `device_id` | `{ok, rev}`; event `houseplan_layout_updated` | +| `houseplan/geometry/repair` | `space_id`, `aspect`, `dry_run?`, `undo?` | preview / `{ok, rev, moved}` / `{restored}`; errs `nothing_to_repair`, `no_backup` | +| `houseplan/files/migrate` | `from_id`, `to_id` | `{mapping}` — COPY, never move | +| `houseplan/files/cleanup` | `marker_id`, `keep?` | replacement-only collection | +| `houseplan/content/sign` | `paths[]` | `{urls}` — authSig for ``/`` fetches | + +Manual attachments upload over HTTP (streaming, transactional staging), not WS — +the old `houseplan/file/set` was removed in v1.10.0. **If the v1.48 migration crashed halfway** (HP-1500-01): the config write landed, the layout write did not, and both triggers are gone — markers of that diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index c063b49..ee1aa9d 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -49,8 +49,13 @@ cp dist/houseplan-card.js custom_components/houseplan/frontend/ ## Deployment to the dacha (ha.jbstudio.pro) -- SSH: port **323**, root, key `ha_jb` (the user uploads it to the chat; in the sandbox /tmp/ha_jb, chmod 600). -- JS: `scp -P 323 -i /tmp/ha_jb dist/houseplan-card.js root@ha.jbstudio.pro:/config/custom_components/houseplan/frontend/` +- SSH: port **22222**, root, key `ha_jb` (lives in the user folder `houseplan/.secrets/ha_jb`, + outside git; copy into the sandbox with chmod 600 — only ask the user if it is gone). +- **The HA config root is `/mnt/data/supervisor/homeassistant`** — in this SSH + environment `/config` does not exist; a deploy aimed at `/config/...` fails + with "No such file or directory". +- JS: `scp -P 22222 -i dist/houseplan-card.js root@ha.jbstudio.pro:/mnt/data/supervisor/homeassistant/custom_components/houseplan/frontend/` +- Cache busting: `sed` the `?v=` version in `.storage/lovelace_resources`, then restart HA. - **The `frontend/` subfolder is not optional.** `__init__.py` registers `Path(__file__).parent / "frontend" / "houseplan-card.js"` as the static path. A copy dropped next to `__init__.py` (…/houseplan/houseplan-card.js) is served diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index acdba4d..f69b0e9 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -35,12 +35,12 @@ Track progress in `custom_components/houseplan/quality_scale.yaml` (done/exempt - [ ] `test-coverage` ≥95% backend; frontend: extract remaining pure logic (view math, marker resolution) into `logic.ts`/`devices.ts` and cover with node:test. - [x] `diagnostics.py`: config + layout dump with `async_redact_data` (redact names/links/PDF paths). -- [ ] `reconfiguration-flow` + richer **options flow**: admin_only, curation defaults +- [ ] `reconfiguration-flow` + richer **options flow**: admin_only, filtering defaults (exclude domains — UI editable, replacing the hardcoded EXCLUDED_DOMAINS fallback), LQI thresholds, group_lights default. -- [ ] `repair-issues`: broken plan file references, orphaned layout entries, storage - migration failures → Repairs UI instead of silent logs. -- [ ] `system_health.py`: config rev, spaces/markers count, storage sizes. +- [x] `repair-issues`: broken plan references in Repairs (repairs.py, re-checked on + every config save); geometry/repair WS command for stranded migrations (v1.50.1). +- [x] `system_health.py` (v1.12.0). - [ ] `exception-translations` + `icon-translations` where applicable. - [ ] Frontend resource registration: adopt the community-consensus embedded-card pattern end-to-end (we already do StaticPathConfig + storage-mode resource + `?v=` busting; @@ -48,26 +48,28 @@ Track progress in `custom_components/houseplan/quality_scale.yaml` (done/exempt ## Phase 9 — Universality & flexibility (product depth) -- [ ] **Areas/floors registry integration**: import HA floors as spaces, suggest area +- [x] **Areas/floors registry integration**: floors-import wizard (v1.13.0); further: suggest area bindings from the registry, sync names (HA is moving this way — native Areas/Home dashboard; riding the registry is our moat). -- [ ] **Curation without hardcode**: icon rules (`iconFor`) become data — user-editable +- [x] **Filtering without hardcode**: icon rules became data (v1.13.0); the runtime + filter itself became explicit per-device hide flags in v1.51.0 (docs/FILTERING.md); + icon rules are user-editable mapping (regex/domain/device_class → mdi icon) stored in config, shipping EN+RU defaults; drop dacha-specific patterns from code. -- [ ] **Click actions** per device/domain: toggle / more-info / navigate / custom service - call (configurable, like standard card `tap_action`). -- [ ] **Theming**: respect light themes (currently dark-leaning), use HA theme variables +- [x] **Click actions** per device (v1.13.0, simplified v1.38.1): card / more-info / + toggle, with the lock/alarm safety model. +- [x] **Theming**: light-theme pass done in v1.13.0; HA theme variables everywhere, optional per-space background color. - [ ] Multi-instance question: keep single-instance (one house) but support **multiple cards** with different default spaces (already works) — document as a decision. - [ ] Plan formats: keep SVG/PNG/JPG/WebP; add max dimensions guidance; optional auto-downscale on upload. -- [ ] More locales: extract i18n dictionaries to JSON so contributors can add languages - without touching TS. +- [x] More locales: i18n dictionaries are JSON since v1.13.0 (src/i18n/*.json). ## Phase 10 — Community & distribution -- [ ] hacs/default PR #8995 through moderation (expect drafting for fixes). +- [ ] hacs/default PR **#9004** through moderation (#8995 was bot-closed for a + non-template body; #9004 is queued with the label since 2026-07-22). - [ ] Demo GIF/video for README (the single biggest driver of adoption for dashboard cards). - [ ] Forum post in the Floorplan category + Reddit r/homeassistant showcase once the demo assets exist. diff --git a/docs/STATUS.md b/docs/STATUS.md index 2e3200e..987f8ce 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -11,7 +11,7 @@ > (versions, publication, infrastructure), DEVELOPMENT.md for new gotchas, > ARCHITECTURE.md for design changes, ROADMAP.md when plans move. -## Snapshot (2026-07-28) +## Snapshot (2026-07-29) | Item | State | |---|---| @@ -20,7 +20,7 @@ | GitHub | https://github.com/Matysh/houseplan-card — **`main` carries every published release, the latest tag is the current version above**; `dev` is where work lands and is merged into `main` at release time (so `dev` is normally equal to or ahead of `main`, never behind). Push via SSH key `ha_jb` (remote git@github.com:…); API releases via the fine-grained PAT in `~/.git-credentials` (Contents R/W, issued 2026-07-23) | | CI | validate.yml (hacs + hassfest + frontend + backend) green; release.yml attaches the bundle on release publish | | HACS | Custom repository works. **Inclusion PR: hacs/default#9004** — open, valid, labeled; ~864 older open PRs but merge rate ≈180/mo; realistic ETA 1–3 months (checked 2026-07-24) | -| Home instance | ha.jbstudio.pro (SSH port 323, key `ha_jb`), deployed **v1.51.1** via direct copy (HACS custom repo also installed) | +| Home instance | ha.jbstudio.pro (SSH port **22222**, key `ha_jb`; HA config root is `/mnt/data/supervisor/homeassistant` — `/config` does NOT exist in this SSH environment), deployed **v1.51.1** via direct copy (HACS custom repo also installed) | | Localization | UI en/ru (src/i18n/*.json), everything user-visible localized incl. kiosk popover | | Tests | Four layers: frontend unit (`npm test`, node:test over `test-build/`), pure backend (`pytest tests_backend`, runs anywhere), HA-harness backend (same folder, CI only — needs py3.13 + pytest-homeassistant-custom-component), and browser smokes (`demo/smoke_*.mjs`, headless chromium). **Counts are not written down here** — they went stale within two releases while the version line beside them was kept current, which reads as less coverage than exists (review R5-2). Run `npm run inventory` for the current numbers, or read them off the last CI run | | Community | **Telegram chat: https://t.me/ha_houseplan** (created 2026-07-27) — the primary user-facing support channel; GitHub issues stay for bugs/features. Link it from any new release notes and posts | @@ -48,6 +48,24 @@ - **Dialog UX**: binding radios + entities checkbox + search dropdown (v1.38.0); tap actions simplified to Device card / more-info / Toggle, right-click → more-info (v1.38.1); Esc closes every dialog (v1.30.4). +- **Room settings, tier 3** (v1.42.0): per-room fill/temp-source/label sizes; + the settings button sits at the room's VISUAL centre (inscribed circle + + centroid pull), icon-derived size, zooms with the plan (v1.51.0). +- **Files & plans** (v1.44–v1.50): signed content urls with sandbox CSP, + copy-on-write plan files, "already uploaded" picker + explicit delete + (v1.47.0), store quotas instead of any age-based deletion (v1.49.0), + nothing is ever deleted on an inference (docs/SCOPE.md rule). +- **Square canvas** (v1.48.0) with a crash-safe two-store migration + (geom_pending, v1.50.0) and an explicit geometry/repair command (v1.50.1); + content-fit default zoom with devices as content, zoom out to 0.4×, + measured stage height (v1.49–v1.50.2). +- **Explicit hide flags** (v1.51.0, docs/FILTERING.md): per-device + "Hide from plan" checkbox seeded once from the old filter; local + "Show hidden" ghosts; hidden counts toward room LQI on both cards, casts + no light (v1.51.1). +- **Yellow = working right now** (v1.51.0): climate by hvac_action, service + switches can no longer become primary, glow pool and icon share one + condition. Editor gestures on touch (pinch/pan) landed the same release. ## Recent milestones (details in CHANGELOG.md) @@ -129,8 +147,9 @@ 1. **hacs/default PR #9004** — accepted by the bot into the review queue ('New default repository' label). Minor issues ⇒ the bot drafts the PR (fix and re-ready). -2. GitHub PAT `houseplan-card-publish` (repo+workflow) expires ~2026-07-12; in sandbox - `~/.git-credentials`. Revoke after the HACS queue clears, or re-issue when needed. +2. GitHub auth: fine-grained PAT (Contents R/W, issued 2026-07-23) in the sandbox + `~/.git-credentials`; pushes go over SSH with the `ha_jb` key. The old classic PAT + expired and is gone. 3. Privacy: legacy real-house plan sources (`assets/`) removed from the tree in v1.13.3, but they persist in git history and old release archives; 8 README screenshots in docs/images are still from the real house (replacement with @@ -150,12 +169,14 @@ 2. Restore the repo: `git clone /houseplan-card.git.bundle hpcN` in `/tmp` (files from *previous* sandbox sessions in `/tmp` belong to `nobody` and are unreadable — always clone into a fresh directory; `npm ci` again). -3. Deployment needs the `ha_jb` SSH key — ask the user to upload it (uploads are readable - only in the session they were uploaded in). +3. Deployment needs the `ha_jb` SSH key — it lives in the user folder at + `houseplan/.secrets/ha_jb` (outside git) and often survives in the sandbox home + `~/.ssh/ha_jb`; copy with chmod 600. Only ask the user if both are gone. 4. Build only in `/tmp` (never on the mount), `npm run build` (starts with `tsc --noEmit`), md5-verify after every deploy, restart HA via `nohup ha core restart >/dev/null 2>&1