diff --git a/.gitignore b/.gitignore index bcdac92..b1d11e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Первоисточник для анализа — бинарники APK не версионируем (файлы лежат локально) -apk/*.apk +docs/apk/*.apk # Python __pycache__/ @@ -7,5 +7,5 @@ __pycache__/ .venv/ venv/ -# Вложенный клон апстрима legacy-скрипта (https://github.com/gyro-labs/AirCon) -legacy/aircon/ +# Локальный конфиг устройства (содержит lanip_key) +docs/legacy/config_kata.json diff --git a/apk/icon.png b/apk/icon.png deleted file mode 100644 index 8ebed03..0000000 Binary files a/apk/icon.png and /dev/null differ diff --git a/docs/LEGACY_ANALYSIS.md b/docs/LEGACY_ANALYSIS.md index b5a50e0..d8b13b6 100644 --- a/docs/LEGACY_ANALYSIS.md +++ b/docs/LEGACY_ANALYSIS.md @@ -1,4 +1,4 @@ -# Анализ legacy-скрипта (`legacy/`): соответствие протоколу и найденные проблемы +# Анализ legacy-скрипта (`docs/legacy/`): соответствие протоколу и найденные проблемы Скрипт — форк проекта hisense_ac (deiger), адаптированный под FGLair. Общая логика протокола воспроизведена верно, но есть критические расхождения с APK и поведением diff --git a/docs/PLAN_HOME_ASSISTANT.md b/docs/PLAN_HOME_ASSISTANT.md index eab663f..35efb02 100644 --- a/docs/PLAN_HOME_ASSISTANT.md +++ b/docs/PLAN_HOME_ASSISTANT.md @@ -33,7 +33,7 @@ cffi-wheel — рабочий путь (HA-контейнеры: x86_64/aarch64 (extern "C"-шейм ядра); * `pyfglair/session.py` — pythonic-обёртка: `Session(cfg)`, колбэки ядра мостятся в `asyncio` через `loop.call_soon_threadsafe`; - * `pyfglair/provision.py` — облачный discovery (перенос `legacy/discovery.py` + * `pyfglair/provision.py` — облачный discovery (перенос `docs/legacy/aircon/discovery.py` на современный aiohttp): вход e-mail/пароль/регион → dsn, ip, oem_model, lanip_key, lanip_key_id; * CLI: `python -m pyfglair discover` / `python -m pyfglair monitor`. diff --git a/docs/PROTOCOL.md b/docs/PROTOCOL.md index 1959ecb..92f0c8f 100644 --- a/docs/PROTOCOL.md +++ b/docs/PROTOCOL.md @@ -3,7 +3,7 @@ Документ реконструирован по декомпилированному APK FGLair 3.4.3 (`com.fujitsu.fglair`, SDK `com.aylanetworks.aylasdk`, см. `AylaLanModule.java`, `AylaEncryption.java`, `AylaLanMessage.java`, `CreateDatapointCommand.java`, `AylaHttpServer.java`, -`com.cafbit.netlib.dns.NetThread`) и сверён с существующим скриптом `legacy/`. +`com.cafbit.netlib.dns.NetThread`) и сверён с существующим скриптом `docs/legacy/`. Всё, что помечено **[APK]**, подтверждено кодом приложения; **[LEGACY]** — известно только из скрипта; **[ПРОВЕРЕНО НА ПРИБОРЕ]** — проверено живыми экспериментами на AP-WC1E (сентябрь 2026, см. §10); **[HYP]** — правдоподобная гипотеза, @@ -100,7 +100,7 @@ key = HMAC_SHA256(K, HMAC_SHA256(K, msg) || msg) # 32 байта * **app-ключи** (приложение шифрует/подписывает, модуль проверяет) — из `msg_app`; * **dev-ключи** (модуль шифрует, приложение проверяет) — из `msg_dev`. -Совпадает с `legacy/config.py`. **[APK: AylaEncryption.generateSessionKeys]** +Совпадает с `docs/legacy/aircon/config.py`. **[APK: AylaEncryption.generateSessionKeys]** ### 3.3. Формат защищённого сообщения (envelope) @@ -347,7 +347,7 @@ data: {"id":"","ack_status":200,"ack_message":0,"dsn":"..."} * CN: `app_id=FGLairField-cn-id`, `app_secret=FGLairField-cn-zezg7Y60YpAvy3HPwxvWLnd4Oh4` `app_secret` = `-`; байты секрета — в -`legacy/app_mappings.py` (проверено: EU совпадает). +`docs/legacy/aircon/app_mappings.py` (проверено: EU совпадает). Endpoints: @@ -487,7 +487,7 @@ building_name, wifi_led_enable, service_contact_*, device_capabilities, refresh. ## 10. Проверено на приборе / осталось неизвестным -Проверено на AP-WC1E (fw 2.6.17-fgl2, ключ из `config_kata.json`), см. также §2, +Проверено на AP-WC1E (fw 2.6.17-fgl2, ключ из `docs/legacy/config_kata.json`), см. также §2, §4.1, §4.4, §5.1, §5.3, §6: полный цикл сессии, KDF/CBC-цепочка/подписи в обе стороны, GET/запись свойств, re-key, 401/400-игнорирование, 2 слота + 503, delete_session, mDNS :10276. Рабочий эталонный клиент: `tools/probe_reference.py`. diff --git a/docs/README.md b/docs/README.md index 33eaba1..4ba46f7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,8 +12,9 @@ | `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-проба (`.local`, порт 10276). | +| `legacy/` | Изменённый legacy-скрипт (форк [gyro-labs/AirCon](https://github.com/gyro-labs/AirCon) / hisense_ac): `main.py` + пакет `aircon/` + рабочий конфиг `config_kata.json`. | +| `apk/` | Материалы анализа APK FGLair 3.4.3 (`manifest.json`; сами .apk лежат локально, не версионируются). | ## Краткая выжимка протокола @@ -59,8 +60,7 @@ * 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/`, не версионируется). +* Legacy-скрипт (`legacy/`) — изменённый форк gyro-labs/AirCon (hisense_ac). * Живые эксперименты на AP-WC1E (сентябрь 2026): сессии, re-key, 401/400, слоты/503, delete_session, записи, mDNS. Пробы: `tools/probe_*.py` (история — сессия анализа; рабочие артефакты оставлены в tools/). diff --git a/apk/manifest.json b/docs/apk/manifest.json similarity index 100% rename from apk/manifest.json rename to docs/apk/manifest.json diff --git a/legacy/__init__.py b/docs/legacy/aircon/__init__.py similarity index 100% rename from legacy/__init__.py rename to docs/legacy/aircon/__init__.py diff --git a/legacy/aircon.py b/docs/legacy/aircon/aircon.py similarity index 100% rename from legacy/aircon.py rename to docs/legacy/aircon/aircon.py diff --git a/legacy/app_mappings.py b/docs/legacy/aircon/app_mappings.py similarity index 100% rename from legacy/app_mappings.py rename to docs/legacy/aircon/app_mappings.py diff --git a/legacy/config.py b/docs/legacy/aircon/config.py similarity index 100% rename from legacy/config.py rename to docs/legacy/aircon/config.py diff --git a/legacy/control_value.py b/docs/legacy/aircon/control_value.py similarity index 100% rename from legacy/control_value.py rename to docs/legacy/aircon/control_value.py diff --git a/legacy/discovery.py b/docs/legacy/aircon/discovery.py similarity index 100% rename from legacy/discovery.py rename to docs/legacy/aircon/discovery.py diff --git a/legacy/error.py b/docs/legacy/aircon/error.py similarity index 100% rename from legacy/error.py rename to docs/legacy/aircon/error.py diff --git a/legacy/mqtt_client.py b/docs/legacy/aircon/mqtt_client.py similarity index 100% rename from legacy/mqtt_client.py rename to docs/legacy/aircon/mqtt_client.py diff --git a/legacy/notifier.py b/docs/legacy/aircon/notifier.py similarity index 100% rename from legacy/notifier.py rename to docs/legacy/aircon/notifier.py diff --git a/legacy/properties.py b/docs/legacy/aircon/properties.py similarity index 100% rename from legacy/properties.py rename to docs/legacy/aircon/properties.py diff --git a/legacy/query_handlers.py b/docs/legacy/aircon/query_handlers.py similarity index 100% rename from legacy/query_handlers.py rename to docs/legacy/aircon/query_handlers.py diff --git a/legacy/main.py b/docs/legacy/main.py similarity index 100% rename from legacy/main.py rename to docs/legacy/main.py diff --git a/legacy/requirements.txt b/docs/legacy/requirements.txt similarity index 100% rename from legacy/requirements.txt rename to docs/legacy/requirements.txt diff --git a/legacy/run.sh b/docs/legacy/run.sh similarity index 100% rename from legacy/run.sh rename to docs/legacy/run.sh diff --git a/legacy/config_kata.json b/legacy/config_kata.json deleted file mode 100644 index 0f31caa..0000000 --- a/legacy/config_kata.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "AC000W002879281", - "app": "fglair-eu", - "model": "AP-WC1E", - "sw_version": "bc 2.6.17-fgl2 06/29/20 09:03:57 ID jre/mfg/2dfbf5d", - "dsn": "AC000W002879281", - "temp_type": "C", - "mac_address": "a0c9a00d61c9", - "ip_address": "192.168.88.3", - "lanip_key": "1uWOP3nGbSz2ysEfjJJVu+P0fxAQTg==", - "lanip_key_id": 62888 -} diff --git a/tools/probe_reference.py b/tools/probe_reference.py index dccc01b..3f02c9b 100644 --- a/tools/probe_reference.py +++ b/tools/probe_reference.py @@ -11,9 +11,9 @@ docs/PROTOCOL.md, включая поведение, подтверждённо - delete_session при выходе (освобождает один из 2 слотов модуля). Использование: - python probe_reference.py config_kata.json monitor 60 - python probe_reference.py config_kata.json get operation_mode fan_speed - python probe_reference.py config_kata.json set fan_speed 3 + python probe_reference.py docs/legacy/config_kata.json monitor 60 + python probe_reference.py docs/legacy/config_kata.json get operation_mode fan_speed + python probe_reference.py docs/legacy/config_kata.json set fan_speed 3 Зависимости: pycryptodome.""" import base64, hmac, json, random, socket, string, sys, threading, time import http.client