- PROTOCOL.md: полная спецификация (KDF, envelope/CBC-цепочка, local_reg, key exchange, commands.json 206/200, datapoint push, тайминги, таблицы свойств шаблонов A/B/F, облачный provisioning). Факты из APK помечены [APK], проверенные живыми экспериментами на AP-WC1E — [ПРОВЕРЕНО НА ПРИБОРЕ]: mDNS только :10276; лимит 2 LAN-сессии (3-я -> 503); принудительный re-key при возрасте сессии >= ~44с (единственный механизм самолечения десинхрона — 400/401 модуль игнорирует); записи не эхируются; delete_session освобождает слот. - LEGACY_ANALYSIS.md: причины рассинхрона (keep-alive 1200с вместо 10-15с + seq_no-фильтр) и перегрузки модуля; требования к новой реализации. - PLAN_CORE_LIBRARY.md: план C++20-библиотеки fglair-core (Linux + ESP-IDF), ключ lanip_key считается статичным, ротация — только ошибка + ручной перепровижининг. - PLAN_HOME_ASSISTANT.md: pyfglair (cffi wheel) + custom component, облачный provisioning только в config flow, ключ виден в диагностике для копирования в ESPHome. - PLAN_ESPHOME.md: external component, только ESP-IDF framework. - tools/probe_reference.py: эталонный клиент протокола (проверен на приборе end-to-end); tools/probe_mdns.py — mDNS-проба. - legacy/: снимок скрипта (апстрим gyro-labs/AirCon, вложенный клон не версионируется); apk/*.apk исключены из версионирования.
67 lines
5.1 KiB
Markdown
67 lines
5.1 KiB
Markdown
# aircon / FGLair local control — документация
|
||
|
||
Реконструкция LAN-протокола FGLair (Fujitsu General, платформа Ayla) и планы
|
||
реализации стека локального управления кондиционером.
|
||
|
||
## Состав
|
||
|
||
| Файл | Назначение |
|
||
|------|-----------|
|
||
| `PROTOCOL.md` | Спецификация LAN-протокола: шифрование, эндпоинты, машина состояний, тайминги, свойства FGLair. Для людей и агентов. Факты помечены `[APK]` / `[LEGACY]` / `[ПРОВЕРЕНО НА ПРИБОРЕ]` / `[HYP]`. |
|
||
| `LEGACY_ANALYSIS.md` | Разбор legacy-скрипта: что верно, баги, причины «рассинхронизации ключей» и перегрузки модуля. |
|
||
| `PLAN_CORE_LIBRARY.md` | План C++20-библиотеки `fglair-core` (Linux + ESP-IDF). |
|
||
| `PLAN_HOME_ASSISTANT.md` | План HA-интеграции (`pyfglair` wheel + custom component). |
|
||
| `PLAN_ESPHOME.md` | План external component для ESPHome (только ESP-IDF framework). |
|
||
| `../tools/probe_reference.py` | Эталонный клиент протокола (проверен на приборе). |
|
||
| `../tools/probe_mdns.py` | mDNS-проба (`<DSN>.local`, порт 10276). |
|
||
|
||
## Краткая выжимка протокола
|
||
|
||
* Модуль кондиционера (порт 80) сам подключается к серверу приложения (порт 10275):
|
||
`local_reg.json` (keep-alive/notify) → `key_exchange.json` → poll
|
||
`commands.json` + push `property/datapoint.json`.
|
||
* Шифрование: AES-256-CBC (no-padding, zero-pad) + HMAC-SHA256; ключи выводятся
|
||
из облачного `lanip_key` и двух пар (random, time). **CBC-цепочка непрерывна
|
||
в рамках сессии**.
|
||
* **Ключевая механика надёжности** (проверено на приборе): модуль игнорирует
|
||
400/401-ответы; единственное самолечение — принудительный re-key, который
|
||
модуль делает при получении `local_reg` для сессии старше ≈44 с. Поэтому
|
||
keep-alive должен быть 10–15 с — тогда любая рассинхронизация живет секунды,
|
||
а не 20 минут (как в legacy-скрипте с интервалом 1200 с).
|
||
* Максимум 2 LAN-сессии (телефон + сервер уживаются), третья — HTTP 503.
|
||
* Записи свойств не эхируются — состояние обновляется оптимистично,
|
||
подтверждение через GET.
|
||
* Свойства FGLair (шаблоны A/B/F по oem_model): `operation_mode` (0..6),
|
||
`fan_speed` (0..4), `adjust_temperature` (×0.1 °C), `display_temperature`
|
||
((v−5000)/100 °C), swing/заслонки, флаги economy/powerful/…, битмаски
|
||
`op_status`, `device_capabilities`. Полные таблицы — в PROTOCOL.md §8.
|
||
|
||
## Ключевые решения (по уточнениям владельца)
|
||
|
||
* `lanip_key` **статичен** (зашит в модуль; за 5 лет ротаций не было).
|
||
Облако используется только для первового provisioning'а (HA config flow или
|
||
CLI `fglair-discover`); при несовпадении `key_id` — устойчивая ошибка,
|
||
лечение правкой конфига вручную. Для ESPHome ключ копируется из диагностики
|
||
HA или получается CLI-той.
|
||
* ESP-IDF везде (Arduino-фреймворк ESPHome не поддерживаем), язык ядра — C++20
|
||
(без исключений/RTTI/heap после init), public API — C++-классы + extern "C"
|
||
шейм для cffi-bindings HA.
|
||
|
||
## Порядок реализации
|
||
|
||
1. `fglair-core` (M0–M5) — ядро, mock-тесты, эталон уже проверен на приборе.
|
||
2. `pyfglair` + HA-интеграция (H1–H4) — параллельно с E1–E2.
|
||
3. ESPHome-компонент (E1–E4).
|
||
4. Уточнение оставшихся неизвестных (PROTOCOL.md §10) по мере эксплуатации.
|
||
|
||
## Источники
|
||
|
||
* APK FGLair 3.4.3 (`apk/com.fujitsu.fglair.apk`): классы
|
||
`com.aylanetworks.aylasdk.lan.*`, `com.fujitsugeneral.aylasdk.*`,
|
||
`com.cafbit.netlib.dns.NetThread`, JS-бандл `assets/www/dist/build.js`.
|
||
* Legacy-скрипт (`legacy/`) — форк hisense_ac; вложенный клон апстрима:
|
||
https://github.com/gyro-labs/AirCon (лежит в `legacy/aircon/`, не версионируется).
|
||
* Живые эксперименты на AP-WC1E (сентябрь 2026): сессии, re-key, 401/400,
|
||
слоты/503, delete_session, записи, mDNS. Пробы: `tools/probe_*.py`
|
||
(история — сессия анализа; рабочие артефакты оставлены в tools/).
|