docs+publish prep: docs/ (architecture, development, changelog, roadmap), CI validate (hacs action + hassfest + build sync check), brand icon, LICENSE

This commit is contained in:
JB
2026-07-04 10:30:40 +03:00
parent 40540e8673
commit 1d576164f4
8 changed files with 311 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
name: Validate
on:
push:
pull_request:
schedule:
- cron: "0 4 * * 1"
jobs:
hacs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: HACS validation
uses: hacs/action@main
with:
category: integration
hassfest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Hassfest validation
uses: home-assistant/actions/hassfest@master
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci && npm run build
- name: Card bundle in sync with integration
run: cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 JB (justbusiness)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+7
View File
@@ -55,6 +55,13 @@ live_states: true
ha-floorplan потребовал бы генератор SVG+конфига и всё равно не дал бы редактирование из UI.
Своя карточка (~1 файл) оказалась дешевле и полностью повторяет прототип. Решение: **свой card**.
## Документация
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — устройство карточки и интеграции, координаты, WS API
- [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — сборка, деплой, грабли окружения (обязательно к прочтению)
- [docs/CHANGELOG.md](docs/CHANGELOG.md) — история версий
- [docs/ROADMAP.md](docs/ROADMAP.md) — план до публикации в HACS (универсализация, редактор разметки, виртуальные устройства)
## Разработка
```bash
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

+92
View File
@@ -0,0 +1,92 @@
# Архитектура House Plan
Обновлено: 2026-07-04 (v1.2.2). Репозиторий = HACS-интеграция (категория **Integration**),
которая содержит и бэкенд (`custom_components/houseplan`), и Lovelace-карточку (`src/``dist/`).
## Состав
```
houseplan-card/
├─ src/ # исходники карточки (TypeScript + Lit 3)
│ ├─ houseplan-card.ts # карточка: рендер, состояния, drag, tooltip, sticky-шапка
│ ├─ editor.ts # GUI-редактор конфига (ha-form + селекторы)
│ ├─ rules.ts # правила иконок (iconFor), курирование, группы, приоритет доменов
│ └─ data/
│ ├─ house.ts # геометрия: ROOMS (комнаты→area), FLOOR_VB (viewBox), названия
│ └─ backgrounds.ts # ВЕКТОРНЫЕ планы (SVG base64) + FLOOR_BG_RECT (позиционирование)
├─ dist/houseplan-card.js # сборка (rollup+terser), ~290 КБ, планы внутри
├─ custom_components/houseplan/ # интеграция HA
│ ├─ __init__.py # setup: Store, WS-команды, раздача JS (add_extra_js_url)
│ ├─ websocket_api.py # houseplan/layout/get|set|update
│ ├─ config_flow.py # одна запись; опция admin_only (правка только админам)
│ ├─ const.py # DOMAIN, STORAGE_KEY, VERSION, FRONTEND_URL
│ └─ frontend/houseplan-card.js # копия dist, раздаётся как /houseplan_files/houseplan-card.js
├─ assets/ # исходники планов: f1_plan.svg, f2_plan.svg (РЕМПЛАННЕР), *_bg.png (старые растровые)
├─ hacs.json # манифест HACS
└─ docs/ # эта документация
```
## Ключевые решения
1. **Один репозиторий — интеграция + карточка.** Интеграция сама раздаёт JS
(`hass.http.async_register_static_paths` + `frontend.add_extra_js_url`), пользователю не
нужно прописывать ресурс Lovelace. Паттерн как у browser_mod/xiaomi_vacuum_map.
2. **Раскладка иконок — на сервере.** `helpers.storage.Store(1, "houseplan.layout")`
`.storage/houseplan.layout`. Карточка читает/пишет через `hass.callWS`
(`houseplan/layout/get|set|update`). Fallback — localStorage (если интеграции нет).
3. **Без токена.** Всё из объекта `hass` фронтенда: `hass.states` (реактивно),
`hass.devices/entities/areas` (реестры). Никаких прямых WS-подключений.
4. **Реактивность.** Каждое изменение состояния в HA приводит к set hass → re-render.
Температуры/LQI/вкл-выкл live по определению (проверено подменой state).
## Координатная система
- Базовое пространство: **1489×1053** («пиксели» старого PNG-рендера, 1 ед. = 1 px).
Все комнаты, позиции иконок и viewBox этажей — в нём. НЕ менять без миграции раскладки.
- Векторные планы вставляются `<image href=svg>` в прямоугольник `FLOOR_BG_RECT`:
- f1: scale **0.647**, offset **(490, 27)** → rect [490, 27, 774.2, 949.3]
- f2: scale **0.896**, offset **(351, 21)** → rect [351, 21, 1048.4, 961.4]
- вычислено растровой корреляцией (cv2.matchTemplate по бинаризованным картам темноты)
рендера SVG с эталонным PNG; точность ~1 px. Скрипты воспроизводимы (docs/DEVELOPMENT.md).
- Комнаты (`ROOMS`) сняппены к внутренним граням стен (полуавто: поиск ближайшей «тёмной линии»
по профилю + ручная доводка по overlay-рендерам).
## Модель данных карточки (runtime)
`DevItem`: id (device_id), name, model, area, floor, icon, entities[], primary (сущность для
more-info по приоритету доменов), temp, members[] (группа ламп), link/linkPrimary (Z2M-группа).
Построение из реестров (`_buildDevices`), правила 1-в-1 из прототипа:
- показываются только устройства с area из списка комнат;
- скрываются: entry_type=service, интеграции из EXCLUDED_DOMAINS, model=Group, сцены, мосты,
под-устройства myheat, дубли по «имя|area»;
- **устройство с сущностью `lock.*` всегда получает `mdi:lock`** (TTLock-замки в реестре
называются «Дом»/«Терраса»/«Кладовка» — по имени не распознать);
- лампы (mdi:lightbulb) ≥2 в комнате схлопываются в группу `mdi:lightbulb-group`
(клик → меню: вся группа + отдельные).
## Живые данные
- Температура: сущность с device_class=temperature / °C / `_temperature$` → метка справа.
- LQI (zigbee): среднее по `*_linkquality`-сущностям → метка под иконкой; цвет
`lqiColor()`: ≤40 красный → ≥180 зелёный (hsl-градиент). Среднее по комнате — в тултипе комнаты.
- Классы состояния иконки: on (жёлтый), open (оранжевый: cover/valve/lock/binary_sensor
проблемных классов), unavail (прозрачность).
## Размеры
`icon_size` в конфиге = **% ширины видимой области плана** (дефолт 2.5). Реализация:
`.stage { container-type: inline-size }` + размеры в `cqw`. Легаси px-значения (>8) игнорируются.
## Sticky-шапка
`.head { position: sticky; top: var(--header-height, 56px) }`; ОБЯЗАТЕЛЬНО
`ha-card { overflow: visible }``overflow: hidden` ломает sticky.
## WS API интеграции
| Команда | Параметры | Ответ |
|---|---|---|
| `houseplan/layout/get` | — | `{layout: {device_id: {x,y}}}` |
| `houseplan/layout/set` | `layout` | `{ok}` (admin_only опционально) |
| `houseplan/layout/update` | `device_id`, `pos` | `{ok}` |
+30
View File
@@ -0,0 +1,30 @@
# Changelog
## v1.2.2 — 2026-07-04
- Тулбар карточки (вкладки этажей) закрепляется при скролле под шапкой HA
(`position: sticky; top: var(--header-height)`; ha-card overflow: visible).
- Инцидент: промежуточная сборка на нестабильном mount дала битый бандл, роняющий рендер
дашбордов; правило «собирать только в /tmp + md5-контроль» закреплено в DEVELOPMENT.md.
## v1.2.1 — 2026-07-04
- Иконки не увеличиваются при наведении/перетаскивании (убран transform: scale).
## v1.2.0 — 2026-07-03
- Границы комнат сняппены к стенам векторного плана.
- Zigbee LQI: значение под иконкой, среднее по комнате в тултипе, градиент красный→зелёный,
опция show_signal.
- `mdi:lock` для любых устройств с сущностью lock.* (TTLock).
- Выключатель прихожей: исправлена зона устройства в реестре HA (был в detskaia_elina).
## v1.1.0 — 2026-07-03
- Векторные подложки (SVG РЕМПЛАННЕР), автосовмещение масштаба/сдвига растровой корреляцией.
- Размер иконок в % ширины плана (container queries, дефолт 2.5%).
## v1.0.1 — 2026-07-03
- fix: вложенные SVG-фрагменты через lit svg`` (подложка/комнаты не рендерились).
- fix: версия из const вместо блокирующего чтения manifest.json в event loop.
## v1.0.0 — 2026-07-03
- Первый релиз: Lovelace-карточка (TS+Lit, без токена, от hass) + интеграция houseplan
(WS-хранилище раскладки, раздача JS). Перенос модели прототипа: курирование, группы ламп,
iconFor, температура, more-info, навигация в зоны, drag-раскладка.
+58
View File
@@ -0,0 +1,58 @@
# Разработка и деплой
## Окружение (cowork-сессии)
- Эталон кода — **git-репозиторий** (в сессии живёт в `/tmp/hpc`, восстанавливается из
`houseplan-card.git.bundle`: `git clone houseplan-card.git.bundle hpc`).
- Папка пользователя `houseplan/houseplan-card/` — зеркало репо (rsync после каждого коммита)
+ актуальный `houseplan-card.git.bundle`.
### ⚠️ Грабли файловой синхронизации (критично)
1. Сетевой mount иногда отдаёт файлы **обрезанными/перемешанными** — правки через Edit-tool
с Windows-стороны ненадёжны. Правило: **править python-патчами по чистой копии в /tmp,
писать через bash**, assert на count(old)==1.
2. **Сборку rollup вести ТОЛЬКО в /tmp/hpc** (`npm ci` уже сделан). Сборка на mount однажды
дала синтаксически валидный, но битый бандл («wi is not defined»), который валил рендер
ВСЕХ дашбордов HA (карточка грузится как extra_module на каждой странице!).
3. `.git` на mount не создаётся («Operation not permitted» на dot-каталогах) — поэтому bundle.
## Сборка
```bash
cd /tmp/hpc && npm ci # один раз
npx rollup -c # → dist/houseplan-card.js
node --check dist/houseplan-card.js
cp dist/houseplan-card.js custom_components/houseplan/frontend/
```
## Деплой на дачу (ha.jbstudio.pro)
- SSH: порт **323**, root, ключ `ha_jb` (пользователь загружает в чат; в песочнице /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/`
- Интеграция целиком: tar c custom_components/houseplan (--exclude __pycache__) → tar x на сервере.
- **Проверка обязательна**: `md5sum` локально == на сервере == `curl http://homeassistant:8123/houseplan_files/houseplan-card.js | md5sum`
(внутри SSH-аддона `localhost` — НЕ HA, использовать хост `homeassistant`).
- Изменения Python требуют рестарта HA (`ha core restart`, держит соединение до конца, HTTP
поднимается через 1–3 мин). Изменения JS — только обновление страницы (static path отдаётся
с no-cache).
- После деплоя JS — проверить в браузере (Ctrl+F5) и console (не должно быть ошибок из
houseplan-card.js; битый бандл роняет все дашборды).
## Релиз
Тег `vX.Y.Z` + GitHub Release → workflow `.github/workflows/release.yml` собирает и прикладывает
`houseplan-card.js`. Версию бампать синхронно: `src/houseplan-card.ts` (CARD_VERSION),
`package.json`, `custom_components/houseplan/manifest.json`, `custom_components/houseplan/const.py`.
## Воспроизводимые скрипты (данные)
- Извлечение геометрии/подложек из прототипа и генерация `src/data/*` — см. историю коммитов
и docs/ARCHITECTURE.md (трансформации SVG→базовое пространство: f1 0.647/(490,27), f2 0.896/(351,21)).
- Подгонка комнат: рендер плана с прямоугольниками поверх (cv2) → снап к стенам → ручная доводка.
## Прод-объекты в HA (дача)
- Дашборд `plan-doma`, панельный вид, карточка `custom:houseplan-card` (icon_size 2.5).
- Интеграция houseplan: entry загружен, `.storage/houseplan.layout` — раскладка (сервер).
- Старый прототип `/config/www/houseplan/` (iframe) сохранён как запасной, не трогать.
- Бэкапы configuration.yaml: `.bak-avgtemp` (до правки среднего датчика).
+73
View File
@@ -0,0 +1,73 @@
# Роадмап: от «карты дачи» к публикуемой универсальной интеграции
Цель: опубликовать в HACS (сначала custom repository, затем PR в default) универсальную
интеграцию «интерактивный план дома»: свои планы на пространство, ручная разметка комнат,
полуавтоматическое размещение устройств, скрытие/переименование/смена иконок, виртуальные
устройства. Никакого хардкода конкретного дома в коде.
## Принципы (зафиксировано)
- Пишем полноценный компонент по паттернам HA dev docs, не захардкоженную фичу.
- Все данные конкретного дома — это **конфигурация инстанса** (server-side Store),
а не код/бандл. Текущие данные дачи станут первым мигрированным инстансом.
- Документировать всё сразу в docs/ (контекст сессий теряется).
- Версионирование хранилищ (Store minor_version + async_migrate) с первого дня.
## Фаза 0 — Гигиена публикации (быстро, без новых фич)
- [x] hacs.json, manifest с обязательными ключами, структура custom_components/*
- [x] CI: hacs/action + hassfest (workflow validate.yml) — добавлено, проверить на GitHub
- [x] brand/icon.png
- [ ] Публичный GitHub-репозиторий: description, topics, issues on; первый Release v1.2.x
- [ ] README EN (основной) + README.ru.md; скриншоты/GIF (обязательны для витрины HACS)
- [ ] Заменить codeowners/documentation/issue_tracker на реальные URL после создания репо
## Фаза 1 — Конфиг на сервере (декаплинг от дачи) ← ФУНДАМЕНТ
Новое хранилище `houseplan.config` (Store v1):
```json
{ "spaces": [ { "id": "f1", "title": "1 этаж", "plan": {"media_id": "...", "type": "svg"},
"view_box": [x,y,w,h], "rooms": [{"id","name","area_id","x","y","w","h"}] } ],
"device_overrides": { "<device_id>": {"hidden":bool,"icon":str,"name":str} },
"virtual_devices": [ {"id","space","name","icon","x","y","note"?, "entity_id"?} ],
"settings": {"exclude_integrations": [...], "group_lights": bool, ...} }
```
- WS API v2: `houseplan/config/get|set`, `houseplan/plan/upload` (файл плана →
`<config>/houseplan/` через process-executor, отдача через static path), layout как сейчас.
- Карточка: при наличии server-config использует его; бандл-данные дачи становятся
**fallback-примером** и затем выпиливаются (миграционный скрипт зальёт их в Store).
- Единицы координат: нормированные (0..1 от плана) для новых конфигов — независимость от
разрешения исходника; миграция дачи пересчитает 1489×1053 → нормированные.
## Фаза 2 — Редактор разметки в карточке
- Режим «Настройка» (отдельно от drag-раскладки): рисование/ресайз прямоугольников комнат
поверх плана, привязка к area (селектор ha-area-picker), редактирование viewBox (кадр).
- Позже: полигональные комнаты (SVG path), повороты планов.
- Загрузка плана из UI (file upload → WS) + выбор существующего media.
## Фаза 3 — Управление устройствами
- Панель устройств в режиме настройки: список неразмещённых (с фильтрами), drag из панели
на план; авто-раскладка «сеткой по комнате» кнопкой.
- Оверрайды per-device: скрыть, своя иконка (ha-icon-picker), своё имя. Хранение в config.
- Настраиваемое курирование: исключения интеграций/доменов в options flow вместо хардкода.
## Фаза 4 — Виртуальные устройства
- CRUD виртуальных маркеров (имя, иконка, координаты, заметка; опционально ссылка на
entity/URL): септик, кран, счётчик без датчика и т.п. Рендер как обычные иконки,
клик → карточка с заметкой или more-info привязанной сущности.
## Фаза 5 — Полировка UX/фич
- Клик-действия по настройке: toggle для света/розеток, long-press → more-info.
- Тюнинг live-индикации (цвета по теме, badge-и), light-тема.
- Тултипы на тач-устройствах (long-press), доступность (клавиатура, aria).
- Опция LQI: порог «плохого» сигнала, скрытие меток на не-zigbee инстансах.
## Фаза 6 — Качество и публикация
- Тесты: pytest (config_flow, websocket_api, миграции Store) + hassfest/hacs action в CI;
фронт: vitest на rules/geometry-утилиты.
- Типизация: strict TS-интерфейсы hass (custom-card-helpers или свои), mypy для python.
- Переводы integration+card: en + ru (translations/, локализация строк карточки).
- Quality scale bronze → silver чек-лист; PR в hacs/default; опционально PR в
home-assistant/brands (пока хватает brand/ в репо).
## Открытые вопросы
- Имя для публикации: «House Plan Card»? домен `houseplan` не занят в HACS default — проверить.
- Лицензия MIT (в package.json уже MIT) — добавить LICENSE файл.
- Формат планов: SVG предпочтителен (вектор, вес), PNG поддержать обязательно.