# fglair-core Local-control library for Fujitsu General air conditioners (FGLair / Ayla LAN protocol). One C++20 codebase — Linux and ESP-IDF (ESP32) — with the full protocol reconstructed from the official APK and verified on real hardware. See [`docs/PROTOCOL.md`](docs/PROTOCOL.md) for the protocol reference and [`docs/PLAN_CORE_LIBRARY.md`](docs/PLAN_CORE_LIBRARY.md) for the design. ## Layout ``` include/fgl-aircon/ public API (types, templates, session, C API for cffi) src/ayla/ Ayla LAN protocol: crypto, envelope, HTTP, session loop src/aircon/ property templates A/B/F, conversions, API implementation pyfglair/ Python bindings (cffi) for Home Assistant (docs/PLAN_HOME_ASSISTANT.md) components/ ESPHome external component (planned, docs/PLAN_ESPHOME.md) custom_components/ Home Assistant custom component (docs/PLAN_HOME_ASSISTANT.md) tests/ ayla (protocol), aircon (conversions), pyfglair, tools examples/cli/ fglctl — sample CLI tools/ fglair-discover, protocol probes ``` ## Build (Linux / POSIX) Requirements: CMake ≥ 3.16, Ninja (or Make), g++/clang with C++20, Mbed TLS (system `libmbedcrypto`; otherwise it is fetched and built automatically). ```sh cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release cmake --build build # CLI: ./build/fglctl status ``` ## Build (ESP-IDF component) The repository root is an ESP-IDF component. Put it on `EXTRA_COMPONENT_DIRS` (or copy into your project's `components/`): ```cmake set(EXTRA_COMPONENT_DIRS "/path/to/aircon") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(my_app) ``` ```cmake # main/CMakeLists.txt idf_component_register(SRCS "main.cpp" PRIV_REQUIRES aircon) ``` ```cpp #include "fgl-aircon/session.hpp" extern "C" void app_main() { fgl::aircon::Config cfg{}; cfg.host = "ac.local"; // DNS name or IP cfg.dsn = "..."; // from fglair-discover cfg.lanip_key = "..."; // from fglair-discover (static per module) cfg.lanip_key_id = 12345; cfg.tmpl = fgl::aircon::template_detect("AP-WC1E"); fgl::aircon::Callbacks cbs{}; auto* s = fgl::aircon::Session::create(cfg, cbs); s->start(); } ``` Tested with ESP-IDF v5.5 (esp32); no Arduino support. ## Tests ```sh ./scripts/ci.sh # Release + ASan/UBSan + clang builds, all tests # or: ctest --test-dir build --output-on-failure ``` `tests/ayla` covers the protocol (KDF vectors from the APK, envelope, HTTP, session scenarios against a Python mock of the module). `tests/aircon` covers template tables and conversions. No hardware needed. ## pyfglair (Home Assistant) `pyfglair/` — python-пакет (cffi, ABI-режим) поверх того же C-ядра: сессия с доставкой событий в asyncio, интроспекция шаблонов и облачный discovery. ```sh pip install . # wheel: cmake собирает libfgl-aircon.so python -m pyfglair discover --region eu --email you@example.com python -m pyfglair monitor --config config_home.json --duration 60 ``` Тесты (без железа: mock-модуль + мок-облако): `scripts/py-ci.sh --setup && scripts/py-ci.sh` (или `pytest tests/pyfglair`). ## Home Assistant Компонент `custom_components/fglair/` (HACS custom repository) — climate, switch/select/sensor/binary_sensor, config flow с превью шаблона, repair для несовпадения ключа и диагностика. Инструкция: [`custom_components/fglair/README.md`](custom_components/fglair/README.md); приёмка на живом стенде — `tests/acceptance/test_esphome_ha.py`. ## Getting the key (`lanip_key`) The key is static (baked into the AC module; only served by the Ayla cloud): ```sh tools/fglair-discover --region eu --email you@example.com # prints one config JSON per device, or a secrets block: tools/fglair-discover --region eu --email you@example.com --format esphome-secrets ``` ## fglctl ```sh fglctl config.json status # session check + cached temperature fglctl config.json monitor 60 # follow all events for 60 s fglctl config.json get OperationMode FanSpeed fglctl config.json set AdjustTemperature 220 # 22.0 °C (unit 0.1 °C) ``` Values are in API units: temperatures in 0.1 °C, `DisplayTemperature` converted from the module's 0.01 °C+5000 format. ## License / provenance Protocol documentation and code reconstructed from the FGLair 3.4.3 APK for interoperability; `third_party/jsmn` is MIT.