Files
fgl-aircon/docs/PLAN_HOME_ASSISTANT.md
Petr Polezhaev b21817ab9f docs: корректировки планов — монорепо, слои ayla/aircon, конверсии, приёмка
- PLAN_CORE: монорепозиторий (CMakeLists в корне; components/fglair,
  custom_components/fglair, include/fgl-aircon, src/{ayla,aircon},
  src/ayla/platform); логическое разделение ay­la (протокол+цикл) /
  aircon (конверсии+шаблоны+API); тесты зеркалят слои (tests/{ayla,aircon});
  конверсии: шаблон / линейные коэффициенты / функция-указатель
  (лямбды ESPHome); оценка httpd/json (jsmn вендор, свой мини-httpd на
  BSD-сокетах, conan не нужен); README библиотеки в M4.
- PLAN_ESPHOME: host вместо ip_address (DNS + Ayla-mDNS :10276),
  секреты в примерах, кастомные конверсии через !lambda, advanced-пример
  (триггеры режимов + LVGL с пропусками), README-план, скрипт приёмки
  (aioesphomeapi + HA REST).
- PLAN_HOME_ASSISTANT: шаг config flow с превью рассчитанных значений
  шаблона (через cffi в C-ядро, без дублей), README с HACS-инструкцией
  и заглушками под скриншоты с описаниями, приёмка (long-lived token).
- Убраны реальные dsn/ip/lanip_key/key_id из примеров; probe_mdns.py
  принимает DSN аргументом.
2026-09-21 13:20:29 +03:00

159 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План: интеграция Home Assistant (`custom_components/fglair`)
Аудитория — агенты-реализаторы. Протокол — `docs/PROTOCOL.md`; ядро —
`docs/PLAN_CORE_LIBRARY.md` (`fgl-aircon`, C++20, монорепо: библиотека в
корне, компонент HA здесь).
## 1. Архитектура
```
Home Assistant (custom component `fglair`)
│ использует python-пакет pyfglair (cffi-bindings к libfgl-aircon.so)
▼
pyfglair (wheel: linux x86_64/aarch64; cffi; собирает библиотеку из корня
репозитория через cmake)
│
▼
fgl-aircon (C++, корень монорепо) ←—— тот же код, что и на ESP32 (ESP-IDF)
```
Компонент — тонкий: переводит API библиотеки в сущности HA. Вся протокольная
логика (сессия, шифрование, pacing, re-key, восстановление) — в C-ядре.
Обоснование: переиспользование библиотеки (требование владельца); cffi-wheel
— рабочий путь (HA-контейнеры x86_64/aarch64 debian; cibuildwheel).
Fallback, если сборка wheel станет блокером: сборка .so при старте в docker
(dev-режим). Чисто-Python повторная реализация протокола — запрещена.
## 2. Состав
1. **`pyfglair`** (python-пакет):
* `pyfglair/_corebuild.py` — cmake-сборка при упаковке wheel;
* `pyfglair/_cffi.py` — cffi-декларации поверх `include/fgl-aircon/c_api.h`;
* `pyfglair/session.py` — обёртка `Session(cfg)`; колбэки ядра → asyncio
через `loop.call_soon_threadsafe`;
* `pyfglair/templates.py` — интроспекция шаблонов через cffi-вызовы
`fgl_template_info_get` / `fgl_convert_to_display` (для превью в
config flow; единый источник данных — C-таблицы, дублей нет);
* `pyfglair/provision.py` — облачный discovery (перенос логики
`docs/legacy/aircon/discovery.py` на современный aiohttp): e-mail/
пароль/регион → dsn, host/ip, oem_model, lanip_key, lanip_key_id;
* CLI: `python -m pyfglair discover` / `monitor` / `--output esphome-secrets`
(печать блока для secrets.yaml ESPHome).
2. **`custom_components/fglair/`**:
```
manifest.json # requirements: ["pyfglair>=1.0.0"], config_flow: true
config_flow.py # flow + options + repair
fglair_client.py # фоновый поток с FglSession
coordinator.py # push-driven coordinator
climate.py sensor.py switch.py select.py binary_sensor.py
diagnostics.py # lanip_key/key_id/dsn видны для копирования в ESPHome
translations/{en,ru}.json
```
## 3. Config flow
Шаг 1 — **подключение** (один из вариантов):
* A (облачный): e-mail/пароль FGLair + регион → список устройств
(name, model, host) → выбор.
* B (ручной): host/dsn/lanip_key/lanip_key_id по полям, либо импорт
`config_*.json` (миграция с legacy).
Шаг 2 — **пробное подключение**: старт сессии, ожидание ONLINE ≤10 с,
чтение базовых свойств. Ошибка → назад с сообщением.
Шаг 3 — **выбор шаблона С ПРЕВЬЮ РЕЗУЛЬТАТОВ** (требование): после выбора
шаблона (обычно определён по oem_model автоматически) — форма-предпросмотр
рассчитанных значений через `pyfglair.templates` (вызовы в C-ядро):
| Поле превью | Пример значения |
|---|---|
| hvac-режимы | off, cool, dry, fan, heat, auto (operation_mode 0–6) |
| fan-режимы | quiet/low/medium/high/auto (0–4) |
| Диапазон уставки | 16.0–30.0 °C, шаг 0.5 (adjust_temperature raw 160–300, ×0.1) |
| Текущая температура | display_temperature 7000 → 20.0 °C |
| Заслонки | vertical 0–4 (af_vertical_num_dir), horizontal 0–6 |
| Битмаска capabilities | heat, cool, economy, powerful, min_heat, swing … |
Пользователь оценивает корректность (сверяет с приложением FGLair) и
подтверждает → создаётся `ConfigEntry`. При расхождении — возможность
выбрать другой шаблон или задать конверсию коэффициентами (linear:
num/den/offset) и диапазон вручную на этом же шаге.
Repair (теоретический): `key_error` → «Ключ устройства изменён —
перепровижинируйте» (повторный облако-вход по требованию). Облако в рантайме
не используется, ключ статичен.
**Диагностика**: device-страница показывает `dsn`, `lanip_key`, `lanip_key_id`,
`host` — источник для копирования в secrets ESPHome. В redacted-дампе ключ
маскируется.
## 4. Сущности
Как раньше (climate: hvac/fan/swing/preset ECO-BOOST; current_temperature ←
display_temperature; sensors: room temp, error_code, op_status-флаги;
switch: economy/powerful/coil_dry/min_heat/outdoor_low_noise/
human_det_auto_save/wifi_led/indoor_fan_control; select: заслонки,
demand_control; binary_sensor: connectivity). capabilities фильтруют
режимы/пресеты. Записи — один `batch_commit()` на действие пользователя.
## 5. Runtime
Один `FglairClient` на `ConfigEntry` (daemon-thread, сессия ядра); колбэки →
asyncio → push-coordinator. Состояния: `online` → available;
`recovering` → доступны (последние значения) + diagnostic-сенсор;
`offline` → unavailable; `key_error` → unavailable + repair. Keep-alive 15 с
(самолечение десинхрона ≤15 с). Выгрузка: `stop()` (delete_session).
## 6. README компонента (после реализации; для людей, коротко)
Структура (`screenshots/step-N.png` — заглушки-плейсхолдеры, владелец заменит
реальными скриншотами; рядом с каждой — описание что должно быть видно):
1. **Установка через HACS**:
* HACS → ⋮ → Custom repositories → URL репозитория, категория
Integration → Add. Скриншот: диалог добавления custom repository с
заполненным URL и выбранной категорией Integration.
* FGLair → Download → перезапуск HA. Скриншот: страница загрузки
интеграции с кнопкой Download (версия видна).
2. **Добавление устройства**: Settings → Devices & Services → Add
Integration → «FGLair». Скриншот: диалог поиска интеграции с введённым
«FGLair» и выделенным результатом.
3. **Вход в облако** (шаг 1A): e-mail/пароль/регион. Скриншот: форма с
заполненными регионом EU и e-mail (пароль скрыт).
4. **Выбор устройства**: список найденных кондиционеров. Скриншот: список
с одним устройством (имя, модель, host).
5. **Проверка шаблона с превью** (шаг 3): Скриншот: форма превью — таблица
рассчитанных значений (режимы, диапазон температур, пример конверсии
температуры), кнопки Confirm/Change template.
6. **Готово**: карточка устройства со списком сущностей. Скриншот: страница
устройства с созданными climate/sensor/switch сущностями.
7. **Где взять ключ для ESPHome**: диагностика устройства. Скриншот: страница
Diagnostics с полями dsn/lanip_key/lanip_key_id.
8. Troubleshooting: 503 (оба слота заняты — телефон+ESP?), key_error,
недоступность.
## 7. Приёмка (полуавтоматическая, `tests/acceptance/test_esphome_ha.py`)
Совместно с ESPHome-компонентом (топология и детали — PLAN_ESPHOME §8).
Со стороны HA скрипт использует **long-lived access token** (профиль →
Security → Long-lived access tokens) и REST API: вызов сервисов
`/api/services/climate/set_temperature|set_hvac_mode|set_fan_mode|set_swing_mode`
и чтение `/api/states/<entity_id>`. Возможность подтверждена: это
стандартный документированный механизм HA REST API, отдельная авторизация
(OAuth-флоу) не нужна — пользователь просто создаёт токен и передаёт
скрипту (`--ha-url`, `--ha-token`).
Режимы: quick (матрица burst/не-burst, обе стороны, с возвратом) и `--long`
(24 ч, ежечасное изменение с проверкой и возвратом, CSV-отчёт). Скрипт НЕ
открывает собственную сессию к кондиционеру (оба слота заняты HA+ESP).
## 8. Этапы
| # | Содержимое |
|---|-----------|
| H1 | wheel `pyfglair` (сборка из корня монорепо), cffi-обёртки, CLI discover/monitor |
| H2 | компонент: manifest, config flow (облако/ручной/импорт) + пробное подключение |
| H3 | шаг «превью шаблона» с ручными конверсиями; climate + сущности |
| H4 | repair, диагностика (ключ для ESPHome), translations |
| H5 | README с HACS-инструкцией и заглушками скриншотов (§6), скрипт приёмки (§7), HACS-релиз |