petr.polezhaev
|
fa1718f405
|
core(M3): aircon-слой — шаблоны A/B/F, конверсии+override, публичный API + C-API
- include/fgl-aircon: types.hpp (Prop/State/Error/Value/Template/
Conversion-linear-custom/PropOverride/Config с задокументированными
lifetime-контрактами), templates.hpp (PropInfo-таблицы, интроспекция,
конверсии c контрактом Linear num/den!=0), session.hpp (Session:
set_int/bool/string, get_prop, batch, cached, set_log_sink с контрактом),
c_api.h (extern "C" для cffi/pyfglair).
- src/aircon: tables.cpp (шаблоны A=33/B=20/F=34 по PROTOCOL §8.2,
template_detect + template_is_known; конверсии: default тождественно,
DisplayTemperature raw 0.01°C(+5000)→API 0.1°C; linear с инверсией
raw=(api-offset)*den/num и насыщением __builtin_*_overflow; custom fn;
af_*_swing base_type integer, kind bool), session.cpp (маппинг имя↔Prop,
коэрсинг int-push к kBool по таблице, кэш со спинлоком, оптимистичный кэш,
валидация overrides: терминатор/linear/custom_fn), c_api.cpp (шейм,
static_assert'ы на все enum-значения, fgl_template_detect -1 для
неизвестных).
- ayla: set_property_string (Command.str_value, coalescing копирует строку
в т.ч. в batch-ветке); kMaxQueue 48 + static_assert (полный батч A=33);
commit_batch всегда ставит notify; oversized-строка дропает событие
(кэш не затирается); max_queue default 40.
- tests/aircon: test_tables (составы/атрибуты/дубли/template_detect/
swings-integer), test_convert (default/linear/custom/диапазоны/насыщение
в обе стороны/UB-экстремумы), aircon_runner + test_aircon_mock
(маппинг+конверсии+batch=1-notify с ожиданием async REG; SET+кэш+
RO/не-шаблон отказы+клэмпинг raw 450 на модуле; C-API smoke).
- Прибор AP-WC1E: полный батч шаблона A одним notify — 28 int/bool свойств
(DisplayTemperature 7000→200=20.0°C, DeviceCapabilities=5119), boolean SET
(JSON true) принят, RO/клэмп/NOTMPL отказы корректны.
- CI: 10/10 ×3 стабильно (3 полных прогона); ESP-IDF esp32 build complete.
Ревью независимым агентом: 3 круга — B1 kMaxQueue<батча, B2 linear div/0,
B3 c_api контракт -1, B4 batch-строки, BL1 INT64_MIN negation UB,
BL2 DisplayTemperature экстремумы, flake aircon_mock — всё закрыто;
APPROVED (условие круга 3: фикс + зелёный CI ×3).
|
2026-09-28 20:16:54 +03:00 |
|
petr.polezhaev
|
17bea87fdf
|
core(M2): машина состояний сессии Ayla LAN + mock-модуль + интеграционные сценарии
- 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.
|
2026-09-27 14:56:47 +03:00 |
|