- session.{hpp,cpp}: state machine (idle/registering/online/recovering/
offline/key_error); httpd-обработчики key_exchange (200/426/412, re-key
прозрачно), commands (одна команда, 206/200, envelope, глобальный seq_no),
datapoint (unpack -> PropertyEvent / 401+тишина 50с для re-key-восстановления);
сессионный поток: local_reg POST?dsn/PUT (local_ip_for), keep-alive, backoff
x1.6->60с, 503->offline/NoSlot, activation-timeout->recovering, delete_session
с ожиданием выдачи; очередь с coalescing + batch; телеметрия; колбэки из
двух потоков с задокументированным контрактом; буферы datapoint-пути в Impl.
- platform: local_ip_for (UDP-connect) posix+esp-idf; стек httpd 24576
(переполнение 16КБ поймано gdb на Release).
- mock_ac.py: мок-модуль, stdlib-only чистый python AES-256 (свёрстан с
pycryptodome); сценарии: 503, no-poll, rekey-every, stale-gap (эмуляция
'вернувшегося' приложения), fail-pushes (битая подпись), garbage-pushes
(обрыв блока), break-outbound (исходящий десинк -> модуль ре-кает на
local_reg, как probe1-3), push-every, fail-first-ke.
- session_runner + test_session_mock.py: 9 сценариев через ctest, включая
самосинхронизацию CBC и восстановление после исходящего десинка.
- Прибор AP-WC1E: активация <=1с; re-key семантика ИСПРАВЛЕНА по живым
тестам: re-key при зазоре local_reg >= ~44-50с (не по возрасту сессии!);
при честном keep-alive 15с сессия стабильна без re-key; PROTOCOL/LEGACY/
PLAN обновлены; восстановление = тишина >порога + возврат.
- CI: 7/7 x3 (gcc-Rel, gcc-ASan/UBSan, clang); ESP-IDF esp32 build complete.
Ревью под-агентом: 2 круга (стек httpd, залипание состояний, dangling cfg,
физика десинка) — APPROVED.
aircon / FGLair local control
Реконструкция LAN-протокола FGLair (Fujitsu General, платформа Ayla) и планы монорепозитория стека локального управления кондиционером: базовая C++ библиотека + интеграции ESPHome и Home Assistant.
Состав репозитория (целевая структура)
CMakeLists.txt # базовая библиотека (корень)
include/fgl-aircon/ # публичный API (уровень aircon: конверсии, шаблоны)
src/ayla/ # протокол Ayla LAN + главный цикл сообщений
platform/{posix,esp-idf}/ # платформенный слой
src/aircon/ # конверсии, шаблоны A/B/F, реализация API
third_party/jsmn/ # вендоренный JSON-парсер (MIT)
components/fglair/ # ESPHome external component
custom_components/fglair/ # Home Assistant custom component
tests/{ayla,aircon}/ # тесты протокола / конверсий и шаблонов
tests/acceptance/ # полуавтоматическая приёмка ESPHome<->HA
tools/ # probe_reference.py, probe_mdns.py, fglair-discover
docs/ # документация (ниже) + материалы анализа
Документация
| Файл | Назначение |
|---|---|
PROTOCOL.md |
Спецификация LAN-протокола: шифрование, эндпоинты, машина состояний, тайминги, свойства FGLair. Для людей и агентов. Факты помечены [APK] / [LEGACY] / [ПРОВЕРЕНО НА ПРИБОРЕ] / [HYP]. |
LEGACY_ANALYSIS.md |
Разбор legacy-скрипта: что верно, баги, причины «рассинхронизации ключей» и перегрузки модуля. |
PLAN_CORE_LIBRARY.md |
План C++20-библиотеки fgl-aircon (Linux + ESP-IDF): слои ayla/aircon, конверсии, оценка httpd/json-библиотек, монорепо-структура. |
PLAN_HOME_ASSISTANT.md |
План HA-интеграции: pyfglair (cffi wheel), config flow с превью шаблона, HACS-README со скриншотами. |
PLAN_ESPHOME.md |
План ESPHome-компонента: host+DNS, секреты, кастомные конверсии-лямбды, advanced-пример, приёмка. |
legacy/ |
Изменённый legacy-скрипт (форк gyro-labs/AirCon / hisense_ac): main.py + пакет aircon/. Локальный config_kata.json не версионируется (содержит lanip_key). |
apk/ |
Материалы анализа APK FGLair 3.4.3 (manifest.json; .apk-бинарники лежат локально, не версионируются). |
Краткая выжимка протокола
- Модуль кондиционера (порт 80) сам подключается к серверу приложения (порт 10275):
local_reg.json(keep-alive/notify) →key_exchange.json→ pollcommands.json+ pushproperty/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.
Ключевые решения (по уточнениям владельца)
- Монорепозиторий: библиотека в корне,
components/fglair(ESPHome),custom_components/fglair(HA); тесты зеркалят слои (tests/ayla,tests/aircon); библиотека логически разделена наsrc/ayla(протокол) иsrc/aircon(конверсии/шаблоны/API), публичный интерфейс —include/fgl-aircon/. - Конверсии свойств задаются шаблоном по умолчанию, коэффициентами
(linear) или функцией-указателем (ESPHome — лямбды, HA — коэффициенты
- превью рассчитанных значений при настройке).
lanip_keyстатичен (зашит в модуль; за 5 лет ротаций не было). Облако — только provisioning (HA config flow, CLIfglair-discover); для ESPHome ключ копируется из диагностики HA или CLI. При несовпаденииkey_id— устойчивая ошибка, лечение правкой конфига вручную.- ESPHome: везде ESP-IDF framework, подключение по
host(DNS/mDNS), все чувствительные значения — через!secret. - HTTP/JSON: собственный мини-httpd/httpc на BSD-сокетах (одна реализация для lwip/posix) + вендоренный jsmn; esp_http_server/cJSON/ArduinoJson отвергнуты (обоснование — PLAN_CORE §7). Conan не нужен.
- Приёмка: полуавтоматический скрипт
tests/acceptance/(HA long-lived token + REST, ESPHome через aioesphomeapi; quick/burst и 24-часовой режимы).
Порядок реализации
fgl-aircon(M0–M4) — ядро (ayla → aircon), mock-тесты; эталонtools/probe_reference.pyуже проверен на приборе.pyfglair+ HA-интеграция (H1–H5) — параллельно с E1–E2.- ESPHome-компонент (E1–E4).
- Приёмочные прогоны (quick + 24 ч), README компонентов.
- Уточнение оставшихся неизвестных (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/) — изменённый форк gyro-labs/AirCon (hisense_ac). - Живые эксперименты на AP-WC1E (сентябрь 2026): сессии, re-key, 401/400,
слоты/503, delete_session, записи, mDNS. Рабочие артефакты —
tools/.
Description
Languages
C++
72%
Python
24.7%
CMake
2.7%
Shell
0.6%