Metadata-Version: 2.4
Name: pyfglair
Version: 1.0.0
Summary: Local control of Fujitsu General (FGLair/Ayla) air conditioners: cffi bindings to the fgl-aircon C++ core
License-Expression: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Home Automation
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cffi>=1.15
Requires-Dist: aiohttp>=3.9
Dynamic: license-file

# 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 <config.json> 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
для несовпадения ключа и диагностика. Установка: HACS (нужно публичное
GitHub-зеркало) или ручное копирование `custom_components/fglair/`.
Инструкция: [`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

MIT — see [`LICENSE`](LICENSE). Protocol documentation and code reconstructed
from the FGLair 3.4.3 APK for interoperability; vendored `third_party/jsmn`
is MIT.
