core(M4): fglctl, fglair-discover, README библиотеки; M5 — вне скоупа core-релиза
- README.md (корень): сборка POSIX/ESP-IDF-компонентом, тесты, получение
ключа (fglair-discover), примеры fglctl; planned-компоненты помечены.
- examples/cli/fglctl.cpp: monitor/get/set/status на публичном API
(batch GET шаблона, конверсии, wait_online, логи в stderr, exit-коды;
сборка с -Wall -Wextra -Werror).
- tools/fglair-discover: облачный provisioning (eu/us/cn, endpoints и
app_id/secret из PROTOCOL §7), --format json|esphome-secrets, --out 0600,
обработка URLError/KeyError; stdlib-only.
- tests/tools/test_fglair_discover.py: мок-облако (http.server), 4 теста,
ctest tools_fglair_discover.
- docs/reports/M4_SOAK.md: 60-мин soak на AP-WC1E — 0 рассинхронов,
33/33 свойства (вкл. строковые), 273 опроса модуля, pushes_bad=0;
24-ч прогон — приёмочный шаг перед релизом.
- План: M4 ✅; M5 (FglHub/mDNS) — ВНЕ СКОУПА core-релиза.
- Гигиена: config_kata.json (корень+docs/legacy) в .gitignore; MQTT-креды
из docs/legacy/run.sh заменены плейсхолдером (история чистится отдельно).
- Фиксы ревью: mock арм fail-pushes после активации (флейк san-сборки);
fglctl: валидация strtoll (abc/99 — отказ, exit!=0), чтение config с
предупреждением об обрезке, Config{} вместо memset; discover: 0600.
CI: 11/11 ×3 (gcc-Rel, gcc-ASan/UBSan, clang); ESP-IDF esp32 build complete.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# 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
|
||||
components/ ESPHome external component (planned, docs/PLAN_ESPHOME.md)
|
||||
custom_components/ Home Assistant custom component (planned, docs/PLAN_HOME_ASSISTANT.md)
|
||||
tests/ ayla (protocol), aircon (conversions), 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.
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user