ha(H5): исправления по ревью — GitHub/HACS, рабочий ESPHome-канал, restore, manylinux
- critical: README честно описывает HACS (только публичный GitHub-зеркало)
+ ручная установка копированием; RELEASE_HA — шаг зеркала и codeowners
- critical: ESPHome-канал приёмки реализован реально (aioesphomeapi:
connect/list_entities/climate_command для режима и уставки; fan/swing —
только HA); unit-тест на фейковом модуле
- major: quick/long восстанавливают исходное состояние в finally даже при
сбое; quick ждёт восстановления; ошибки шага пишутся в результат (rc 1),
а не фаталят (rc 2)
- major: RELEASE_HA — manylinux через auditwheel repair (PyPI отклоняет
linux_x86_64), build/twine, aarch64, корректные проверки .so, тег/версия
- major: полный ключ для ESPHome теперь реально виден в options flow
(«Настройка» на карточке интеграции, поле LAN IP key, можно заменить) —
README/diagnostics синхронизированы
- minor: non-JSON ответ → rc 2; CSV quick+long и инкрементальная запись;
допуск _matches в long; --settle-timeout; hacs.json homeassistant=2025.1;
brand/{icon,logo}.png заглушки; план §6/§7 уточнён
- тесты: acceptance self-test 11 (restore-after-failure, long fail, non-JSON,
esphome channel), options flow (2), всего 28+11+49
This commit is contained in:
@@ -17,9 +17,15 @@
|
||||
* Модуль кондиционера в той же LAN. Модуль поддерживает **2 LAN-сессии**:
|
||||
телефон с FGLair и HA уживаются; третья (например, ESPHome) получит 503.
|
||||
|
||||
## Установка через HACS
|
||||
## Установка
|
||||
|
||||
1. HACS → ⋮ → **Custom repositories** → URL репозитория, категория
|
||||
### Вариант A: HACS (нужно GitHub-зеркало)
|
||||
|
||||
HACS работает только с публичными репозиториями на **GitHub**; GitLab/Gitea
|
||||
(включая текущий хостинг проекта) напрямую не поддерживаются. Зеркалируйте
|
||||
репозиторий на GitHub и добавьте зеркало в HACS:
|
||||
|
||||
1. HACS → ⋮ → **Custom repositories** → URL GitHub-зеркала, категория
|
||||
**Integration** → **Add**.
|
||||
|
||||

|
||||
@@ -34,6 +40,13 @@
|
||||
*Должно быть видно: страница загрузки интеграции с кнопкой Download и
|
||||
версией.*
|
||||
|
||||
### Вариант B: вручную (любой хостинг)
|
||||
|
||||
Скопируйте каталог `custom_components/fglair/` в
|
||||
`<config>/custom_components/fglair/` вашего HA и перезапустите Home
|
||||
Assistant. Убедитесь, что `pyfglair` установлен в python-окружение HA
|
||||
(см. «Требования»).
|
||||
|
||||
## Добавление устройства
|
||||
|
||||
3. Settings → Devices & Services → **Add Integration** → «FGLair».
|
||||
@@ -43,7 +56,7 @@
|
||||
*Должно быть видно: диалог поиска интеграции с введённым «FGLair» и
|
||||
выделенным результатом.*
|
||||
|
||||
4. **Вход в облако** (шаг 1A): e-mail/пароль FGLair и регион. Облако
|
||||
4. **Вход в облако**: e-mail/пароль FGLair и регион. Облако
|
||||
используется один раз — получить статический LAN-ключ модуля.
|
||||
|
||||

|
||||
@@ -57,7 +70,7 @@
|
||||
|
||||
*Должно быть видно: список с одним устройством (имя, модель, host).*
|
||||
|
||||
6. **Проверка шаблона с превью** (шаг 3): форма-предпросмотр рассчитанных
|
||||
6. **Проверка шаблона с превью**: форма-предпросмотр рассчитанных
|
||||
значений (режимы, диапазон температур, пример конверсии) и, при
|
||||
необходимости, ручные коэффициенты/диапазон уставки. Сверьте с
|
||||
приложением FGLair и подтвердите.
|
||||
@@ -80,8 +93,11 @@ Download diagnostics на странице устройства показыва
|
||||
`lanip_key_id`, `host` и **маску** ключа. Полный ключ (для
|
||||
`secrets.yaml` ESPHome) получите явным действием:
|
||||
|
||||
* **Настроить заново** (Reconfigure) на карточке интеграции — вход в
|
||||
облако FGLair покажет/сохранит актуальный ключ; либо
|
||||
* **Настройка** (шестерёнка → Configure) на карточке интеграции: поле
|
||||
«LAN IP key» содержит полный ключ — скопируйте его (там же можно
|
||||
заменить ключ без облака); либо
|
||||
* **Настроить заново** (Reconfigure) — повторный вход в облако FGLair
|
||||
обновит ключ; либо
|
||||
* `python -m pyfglair discover --region eu --email you@example.com
|
||||
--format esphome-secrets` на хосте HA.
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 607 B |
Binary file not shown.
|
After Width: | Height: | Size: 832 B |
@@ -8,7 +8,12 @@ from functools import partial
|
||||
from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.config_entries import (
|
||||
ConfigEntry,
|
||||
ConfigFlow,
|
||||
ConfigFlowResult,
|
||||
OptionsFlow,
|
||||
)
|
||||
from homeassistant.helpers import selector
|
||||
|
||||
import pyfglair
|
||||
@@ -547,3 +552,40 @@ class FglairConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self._reconfigure_entry, title=title, data=data
|
||||
)
|
||||
return self.async_create_entry(title=title, data=data)
|
||||
|
||||
@staticmethod
|
||||
def async_get_options_flow(config_entry: ConfigEntry) -> "FglairOptionsFlow":
|
||||
return FglairOptionsFlow()
|
||||
|
||||
|
||||
class FglairOptionsFlow(OptionsFlow):
|
||||
"""Показывает полный LAN-ключ (для secrets.yaml ESPHome) и позволяет
|
||||
обновить его без облака."""
|
||||
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
entry = self.config_entry
|
||||
if user_input is not None:
|
||||
key = str(user_input[CONF_LANIP_KEY]).strip()
|
||||
if key and key != entry.data.get(CONF_LANIP_KEY):
|
||||
self.hass.config_entries.async_update_entry(
|
||||
entry, data={**entry.data, CONF_LANIP_KEY: key}
|
||||
)
|
||||
self.hass.config_entries.async_schedule_reload(entry.entry_id)
|
||||
return self.async_create_entry(title="", data={})
|
||||
schema = vol.Schema(
|
||||
{vol.Required(CONF_LANIP_KEY): selector.TextSelector()}
|
||||
)
|
||||
schema = self.add_suggested_values_to_schema(
|
||||
schema, {CONF_LANIP_KEY: entry.data.get(CONF_LANIP_KEY, "")}
|
||||
)
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
data_schema=schema,
|
||||
description_placeholders={
|
||||
"dsn": str(entry.data.get(CONF_DSN, "")),
|
||||
"lanip_key_id": str(entry.data.get(CONF_LANIP_KEY_ID, "")),
|
||||
"host": str(entry.data.get(CONF_HOST, "")),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Дамп redacted: lanip_key маскируется (HA-конвенция; дампы прикладывают в
|
||||
issues). Полный ключ для secrets.yaml ESPHome берётся явным действием:
|
||||
«Настроить заново» (reconfigure) на карточке интеграции или CLI
|
||||
«Настройка» (шестерёнка, options flow) на карточке интеграции —
|
||||
одноимённое поле содержит полный ключ; либо CLI
|
||||
``python -m pyfglair discover`` на хосте HA.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -189,5 +189,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "FGLair LAN key",
|
||||
"description": "Full LAN key (for ESPHome secrets.yaml). Copy it, or paste a new one to replace the stored key. DSN: {dsn}; key ID: {lanip_key_id}; host: {host}. Saving a changed key reloads the device.",
|
||||
"data": {
|
||||
"lanip_key": "LAN IP key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,5 +189,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "FGLair LAN key",
|
||||
"description": "Full LAN key (for ESPHome secrets.yaml). Copy it, or paste a new one to replace the stored key. DSN: {dsn}; key ID: {lanip_key_id}; host: {host}. Saving a changed key reloads the device.",
|
||||
"data": {
|
||||
"lanip_key": "LAN IP key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,5 +189,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "LAN-ключ FGLair",
|
||||
"description": "Полный LAN-ключ (для secrets.yaml ESPHome). Скопируйте его или вставьте новый, чтобы заменить сохранённый. DSN: {dsn}; key ID: {lanip_key_id}; host: {host}. Сохранение изменённого ключа перезагружает устройство.",
|
||||
"data": {
|
||||
"lanip_key": "LAN IP key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user