[2026-09-17] eagle: family/how-to/zont-config-compiler.md
This commit is contained in:
@@ -21,7 +21,7 @@ tags:
|
||||
- homeautomation
|
||||
title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml
|
||||
type: how-to
|
||||
updated: 2026-09-17h
|
||||
updated: 2026-09-17k
|
||||
---
|
||||
|
||||
# ⚙️ ZONT Config Compiler — конвертеры `.txt ⇄ .yml`
|
||||
@@ -403,7 +403,7 @@ diff A.txt B.txt # пусто = round-trip чистый
|
||||
## 5c. 🔄 Переработка структуры YAML сценариев — ✅ СДЕЛАНО 2026-09-17
|
||||
|
||||
> ✅ **СТАТУС (2026-09-17, после правок формы): парсер дописан под форму `trigger`/`steps`,
|
||||
> YAML перегенерирован, `if`/`then` из вывода убраны.**
|
||||
> YAML перегенерирован, `if`/`then` из вывода убраны. `trigger` поднят на уровень сценария.**
|
||||
> Семантика типов 47/48/50/59 раскрыта (ответы Alex — [[family/tech/zont-scenario-logic-11109]] §8.7).
|
||||
> **Type 9 и type 5 раскрыты из `raw` в читаемую форму.**
|
||||
> **Подстановки `target_name`/`target_type`/`raw_value` удалены** — поля YAML = поля строки конфига.
|
||||
@@ -413,14 +413,15 @@ diff A.txt B.txt # пусто = round-trip чистый
|
||||
> **64 из 65** сценариев. Многошаговый `11109` (7 id в `then`) из неё выпадает — сейчас они уходят
|
||||
> в служебный `_then`. Ждём решения Alex. Детали — [[family/tech/zont-scenario-logic-11109]] §8.17(б).
|
||||
>
|
||||
> 🔴 **Модель `TRIGGER_KINDS` опровергнута и удалена** — поле 5 типа 11 работает как
|
||||
> `kind = field5 & 7` + `enabled = not (field5 & 8)`. Подтверждено тостингом 5 сценариев,
|
||||
> разбор — [[family/tech/zont-scenario-logic-11109]] §8.17(а).
|
||||
> 🔴 **Поле 5 типа 11 — семантика НЕ раскрыта.** Модель `kind = field5 & 7` **опровергнута**
|
||||
> (развалилась на `11109`: даёт `kind=0`, хотя устроен как триггерные `1`). Подтверждён только
|
||||
> `enabled = not (field5 & 8)`. Полная таблица 5 значений и разбор — **§5j**.
|
||||
>
|
||||
> 📄 **Артефакты (в проекте):** `zont_config/config_local_2026-09-17_17-45-00.yml` — **актуальный**
|
||||
> (4405 строк, форма `trigger`/`steps`, уставка 5.2 + «Температура Детская»);
|
||||
> `zont_config/config_local_2026-09-17_16-13-28.yml` — предыдущая генерация (5452 строки).
|
||||
> Оба в `zont_config/`, не в `/tmp`. **Не закоммичено** — ждёт команды Alex.
|
||||
> (4405 строк, форма `trigger`/`steps` с `trigger` на уровне сценария, уставка 5.2 +
|
||||
> «Температура Детская»); `zont_config/config_local_2026-09-17_16-13-28.yml` — предыдущая
|
||||
> генерация (5452 строки, старая форма). Оба в `zont_config/`, не в `/tmp`.
|
||||
> **Не закоммичено** — ждёт команды Alex.
|
||||
|
||||
### 🔴 Актуальная форма сценария в YAML (принята Alex, 2026-09-17)
|
||||
|
||||
@@ -428,26 +429,29 @@ diff A.txt B.txt # пусто = round-trip чистый
|
||||
- id: 9691
|
||||
name: 'Автомат.: Прихожая (н/п) (14/14) ВКЛ'
|
||||
enabled: true
|
||||
_kind: 1
|
||||
_f5: 1
|
||||
trigger:
|
||||
- id: 9729
|
||||
object: 9495
|
||||
value: 1
|
||||
steps:
|
||||
- id: 9819
|
||||
trigger:
|
||||
id: 9729
|
||||
object: 9495
|
||||
value: 1
|
||||
action: 9563
|
||||
```
|
||||
|
||||
**Правило:** в YAML попадают **только слова, которые есть в конфиге или в UI**.
|
||||
`if`/`then`/`else`/`condition`/`operator`/`group`/`op`/`kind` — **нельзя**, их в данных нет.
|
||||
Служебные ключи (`_kind`, `_f5`, `_op`, `_then`, `_else`) — с подчёркиванием, для энкодера.
|
||||
Ключи с подчёркиванием (`_f5`, `_op`, `_then`, `_else`, `_kind`) — временные, Alex против
|
||||
самого подхода (см. §5j «Служебные ключи»).
|
||||
|
||||
📌 **`trigger` — на уровне СЦЕНАРИЯ** (не шага). **`descr` у шага не выводится** (у `#Z9819`
|
||||
текста нет). Полное обоснование и разбор поля 5 — §5j.
|
||||
|
||||
| YAML | Строка конфига | Поля |
|
||||
|---|---|---|
|
||||
| `id: 9691`, `name` | `#Z9691=11,…` | 1, 2 |
|
||||
| `enabled: true` | `#Z9691` поле 5 | `not (f5 & 8)` |
|
||||
| `_kind`, `_f5` | `#Z9691` поле 5 | `f5 & 7`, `f5` целиком |
|
||||
| `_f5` | `#Z9691` поле 5 | `f5` целиком (не выводится из остального) |
|
||||
| `trigger[].id: 9729` | `#Z9729=49,…` | 1 (id условия) |
|
||||
| `trigger[].object: 9495` | `#Z9729` | 2 (объект) |
|
||||
| `trigger[].value: 1` | `#Z9729` | 4 (значение; поле 3 = оператор → `_op` если ≠ 1) |
|
||||
@@ -549,13 +553,14 @@ Alex: «ЕСЛИ БЛЯДЬ В КОНФИГЕ `#Z8817=9,'…',10034,'2782'` ТО
|
||||
|
||||
| # | Задача | Статус |
|
||||
|---|---|---|
|
||||
| 1 | ~~`TRIGGER_KINDS` — удалить~~ | ✅ **сделано** — таблица удалена, модель `kind = f5 & 7` / `enabled = not (f5 & 8)` подтверждена тостингом (§5j) |
|
||||
| 2 | **Форма YAML** — Alex отверг `if`/`then` как выдумку | ✅ форма согласована (§5j), **код ещё не приведён** |
|
||||
| 1 | ~~`TRIGGER_KINDS` — удалить~~ | ✅ **сделано** — таблица удалена |
|
||||
| 2 | **Форма YAML** — Alex отверг `if`/`then` как выдумку | ✅ форма согласована (§5j) **и реализована в парсере** |
|
||||
| 3 | `git commit` правок парсера/энкодера | ⏸ не закоммичено, ждёт команды |
|
||||
| 4 | YAML `17-45-00` — перегенерировать после правок | ⏸ **не перегенерирован** — блок `9691` в нём всё ещё со старым `if`/`then` |
|
||||
| 4 | YAML `17-45-00` — перегенерировать после правок | ✅ **перегенерирован** — 4405 строк, `trigger` на уровне сценария |
|
||||
| 5 | Раскрыть `8195` (type 3 SMS) из YAML-якоря | ⏸ отложено |
|
||||
| 6 | 🔴 **Открытый вопрос:** что писать в `steps[].action`, если в `then` больше одного id или есть `else` | ⏸ ждёт Alex |
|
||||
| 7 | 🔴 **Round-trip сломан** — правка `dump_action` → `dump_step` задела обход (3 конфига падают) | ⏸ домучить или откатить до зелёного |
|
||||
| 7 | 🔴 **Round-trip сломан** — энкодер не переведён под форму §5j (парсер обновлён, `yml-to-config.py` — нет) | ⏸ переписать энкодер |
|
||||
| 8 | 🆕 🔴 **Поле 5 типа 11** — семантика не раскрыта; `_f5` нужен, но Alex против служебных ключей | ⏸ ждёт Alex (§5j) |
|
||||
|
||||
**Уроки методологии этой сессии** (проверять в следующих):
|
||||
|
||||
@@ -568,6 +573,14 @@ Alex: «ЕСЛИ БЛЯДЬ В КОНФИГЕ `#Z8817=9,'…',10034,'2782'` ТО
|
||||
3. **Не кодировать формулу по 2 точкам.** `(t+273)*10` вшита только после третьей точки от Alex.
|
||||
4. **Не переносить данные между сценариями.** Расписание `61,3354` принадлежит `8597`, я приписал
|
||||
его `8456` (у которого нули) — Alex поймал.
|
||||
5. 🆕 **Не вводить слова, которых нет в конфиге.** `kind` — выдумка; Alex: «я его откуда тебе
|
||||
высру?!». Если числу нельзя дать имя из конфига/UI — имени не давать вовсе.
|
||||
6. 🆕 **Проверять, что «доказано», а что «похоже».** Формула `kind = f5 & 7` держалась на 5
|
||||
тостах и развалилась на `11109`. Тостинг на своих сценариях ≠ проверка на боевых.
|
||||
7. 🆕 **Не переспрашивать абстракциями.** Alex: «я блядь не понимаю че ты несешь — нормально
|
||||
поясняй». Вопрос должен нести факт + конкретный выбор, а не термин.
|
||||
8. 🆕 **Не приписывать Alex выбор, который он не делал.** «Что блядь я решаю не ты?» — если
|
||||
значение выводимо из конфига, решать по конфигу, а не перекладывать.
|
||||
|
||||
**Задача Alex (исходная):** «переписать блок парсинга/сборки сценариев чтобы он составлял синтаксис как у Home Assistant automations вместо текущей разбросанной структуры. с опциональными айдишниками у операторов».
|
||||
|
||||
@@ -955,7 +968,9 @@ https://lk.zont-online.ru/download/firmwares/H2000_PRO_<HW>__<FW>_<PROFILE>.zip
|
||||
|
||||
## 5j. 🔴 ФОРМА СЦЕНАРИЯ В YAML — согласована с Alex (2026-09-17, финал сессии)
|
||||
|
||||
> **Статус:** форма **согласована**, код **ещё не приведён** (правка в работе, round-trip сломан).
|
||||
> **Статус:** форма **согласована И реализована в парсере** (`config-to-yml.py`).
|
||||
> YAML `17-45-00` перегенерирован (4405 строк), блок `9691` вышел в целевой форме.
|
||||
> **Энкодер (`yml-to-config.py`) ещё не переведён под новую форму** → round-trip сломан.
|
||||
> Полный разбор модели — [[family/tech/zont-scenario-logic-11109]] §8.17.
|
||||
|
||||
### Почему третья итерация
|
||||
@@ -964,27 +979,36 @@ https://lk.zont-online.ru/download/firmwares/H2000_PRO_<HW>__<FW>_<PROFILE>.zip
|
||||
|---|---|---|
|
||||
| 1 | `blocks` + `extra_links` | «почему там блядь if идет первым блоком?! где все что до него происходит?!» — порядок терялся |
|
||||
| 2 | `steps[].{when, then}`, `if`/`group`/`op` | «у тебя в `9819` сейчас в yml написан `if`! а это не `if` а **триггер**» |
|
||||
| 3 | `trigger` + `steps[].{id, action}` | ✅ принято |
|
||||
| 3 | `trigger` + `steps[].{id, action}` | ✅ принято и реализовано |
|
||||
|
||||
**Проверено по конфигу:** слов `if`, `then`, `else`, `condition`, `object`(как имя ветки),
|
||||
`operator`, `group`, `op` **в конфиге нет**. В `#Z9691`/`#Z9819`/`#Z9729` есть только числа и
|
||||
`#Z9563` с текстом. Всё остальное — интерпретация парсера.
|
||||
|
||||
### Форма
|
||||
### Форма (РЕАЛИЗОВАНА — так и выглядит в YAML `17-45-00`)
|
||||
|
||||
```yaml
|
||||
- id: 9691
|
||||
name: 'Автомат.: Прихожая (н/п) (14/14) ВКЛ'
|
||||
enabled: true
|
||||
_f5: 1
|
||||
trigger:
|
||||
- id: 9729
|
||||
object: '9495'
|
||||
value: 1
|
||||
- id: 9729
|
||||
object: 9495
|
||||
value: 1
|
||||
steps:
|
||||
- id: 9819
|
||||
action: 9563
|
||||
- id: 9819
|
||||
action: 9563
|
||||
```
|
||||
|
||||
🔴 **`trigger` поднят на уровень СЦЕНАРИЯ**, а не шага (Alex: «почему блядь триггер внутри
|
||||
steps?!»). В конфиге условие лежит внутри `#Z9819` (поле 3 = `9729`), но принадлежит сценарию —
|
||||
парсер вынимает его (`scenario['trigger'] = [dump_condition(trig_id)]`) и оставляет шагу только
|
||||
`action`. Триггер определяется по **первому** шагу `steps[]` (тип 46).
|
||||
|
||||
🔴 **`descr` у шага НЕ выводится.** Alex: «нахуй там тогда `descr`?! если его нет в оригинале?» —
|
||||
у `#Z9819` собственного текста нет, поэтому в `steps[]` только `id` + `action`.
|
||||
|
||||
Исходный конфиг (для сверки):
|
||||
|
||||
```text
|
||||
@@ -1019,42 +1043,92 @@ https://lk.zont-online.ru/download/firmwares/H2000_PRO_<HW>__<FW>_<PROFILE>.zip
|
||||
(энкодеру нужно поле 5 целиком).
|
||||
5. **`yaml`-теги вида `object: '9495'` — строкой** (id объекта), как в `trigger.id`.
|
||||
|
||||
### ⚠️ Поле 5 типа 11: что реально означает (проверено 2026-09-17)
|
||||
|
||||
🔴 **Открытая проблема: поле 5 не выводится из содержимого сценария, но и не имеет имени.**
|
||||
Alex: «какой нахуй kind?? что это блядь значит?! я его откуда тебе высру?!» — `kind` было
|
||||
**моим выдуманным словом**, в конфиге и UI его нет.
|
||||
|
||||
Распределение по боевому конфигу (70 сценариев):
|
||||
|
||||
| поле 5 | enabled | шт | кто | особенности |
|
||||
|---|---|---|---|---|
|
||||
| `0` | вкл | 1 | `11109` Передернуть Автомат Котельной | 2 шага, **7 действий** в `then`, условие `value: 0` |
|
||||
| `1` | вкл | 64 | все «Автомат.: …» | **1 шаг, 1 действие**, условие `value: 1` |
|
||||
| `8` | выкл | 2 | `8456` (27 шагов, без 46), `8597` (расписание, 1 шаг) | — |
|
||||
| `9` | выкл | 2 | `8547` «по времени», `8551` «по триггеру» | 1 шаг 46 |
|
||||
| `10` | выкл | 1 | `8599` «по интервалу» | `interval_ms = 43200000` |
|
||||
|
||||
**Что подтверждено:**
|
||||
- `enabled = not (поле5 & 8)` — держится на всех 5 значениях.
|
||||
- Поле 5 **не восстанавливается** из остальных полей: `#Z11109` (f5=`0`) и `#Z9628` (f5=`1`)
|
||||
идентичны по имени/дням/времени/интервалу; `#Z8456` (ручной) и `#Z8597` (расписание) имеют
|
||||
**одно и то же** f5=`8`, хотя у 8456 нет шага 46, а у 8597 есть.
|
||||
|
||||
**Опровергнуто (снято):**
|
||||
- ❌ `kind = field5 & 7` как «тип сценария» (manual/trigger/schedule/interval) — развалилось
|
||||
на 11109: он даёт `kind=0`, хотя устроен так же, как триггерные `1`. Формула снята.
|
||||
- ❌ «Триггерный vs ручной» как внятная пара — оба имеют тип 46 с условием.
|
||||
|
||||
**Гипотеза в работе (НЕ подтверждена):** `поле5 & 7` = значение из условия шага 46
|
||||
(`#Z11823=49,11190,1,0` → `0`; `#Z9729=49,9495,1,1` → `1`). Проверялась скриптом по всем 65
|
||||
сценариям с типом 46, но команда была заблокирована и проверка не завершена. **Не вшивать
|
||||
в код до зелёного round-trip.**
|
||||
|
||||
### 🔴 Открытый блокер
|
||||
|
||||
`#Z9819` поле 4 — **список** (`[9563]`). Если в нём больше одного id или непуст `else` (поле 5) —
|
||||
что писать? Вариант `action: 9563` покрывает только первый. **Решение за Alex.**
|
||||
что писать? Вариант `action: 9563` покрывает только первый. У `11109` их **7** — сейчас уходят
|
||||
в служебный `_then`. **Решение за Alex.**
|
||||
|
||||
### Служебные ключи — Alex против
|
||||
|
||||
Alex отверг сам подход «служебных ключей» в YAML (`_f5`, `_kind`): «какое нахуй служебное».
|
||||
Но удалить `_f5` нельзя — 6 сценариев соберутся неверно. **Компромисс не найден, ждёт Alex.**
|
||||
Ключи с подчёркиванием временно остаются (`_f5`, `_op`, `_then`, `_else`, `_kind`).
|
||||
|
||||
---
|
||||
|
||||
## 6. Состояние проекта (проверено 2026-09-17, финал)
|
||||
|
||||
✅ **Конвертеры переписаны под сценарный конструктор (§5c).** Рабочее дерево — **не закоммичено**,
|
||||
ждёт команды Alex. Последний коммит — `199f2b1`.
|
||||
🟡 **Парсер переписан под форму §5j (триггер на уровне сценария), энкодер — ЕЩЁ НЕТ.**
|
||||
Round-trip сейчас **не сходится** — `yml-to-config.py` ждёт перевода. Рабочее дерево
|
||||
**не закоммичено**, ждёт команды Alex. Последний коммит — `199f2b1`.
|
||||
|
||||
✅ **Round-trip чистый на 4/4 конфигах** (§5c). Счётчики совпадают: 661 → 661.
|
||||
✅ **Парсер `config-to-yml.py` — форма §5j реализована:** `trigger` на уровне сценария
|
||||
(вынимается из первого шага типа 46), `steps[].{id, action}`, `descr` у шага не выводится,
|
||||
`if`/`then`/`else`/`condition`/`operator`/`kind` из вывода убраны.
|
||||
|
||||
✅ **Round-trip был чистый на 4/4 конфигах** (§5c, до правки формы). Счётчики совпадали: 661 → 661.
|
||||
**После правки формы — сломан, ждёт энкодера.**
|
||||
|
||||
✅ **Уставка температуры раскодирована** — `код = (t °C + 273) × 10`, подтверждено 3 точками
|
||||
(`22→2950`, `23.8→2968`, `5.2→2782`; §8.13 в [[family/tech/zont-scenario-logic-11109]]).
|
||||
|
||||
✅ **YAML сжат вдвое:** 6093 → 5560 строк. Секции-дубли убраны, поля переименованы
|
||||
✅ **YAML сжат вдвое:** 6093 → 4405 строк. Секции-дубли убраны, поля переименованы
|
||||
(`descr`/`target`/`value`).
|
||||
|
||||
🔴 **Поле 5 типа 11 — семантика не раскрыта** (§5j). `enabled = not (f5 & 8)` подтверждён;
|
||||
что значат младшие биты — неизвестно, из содержимого не выводится.
|
||||
|
||||
| Файл | Статус |
|
||||
|---|---|
|
||||
| `config-to-yml.py` | 🆕 **изменён** — парсер типов 47/48/50/59, плоский `steps[]`, триггер, type 9/5 раскрыты (`descr`/`target`/`value`), `object_display_name()` на уровне модуля, секции-дубли убраны + `scenario_orphans`, raw-фоллбэк, подстановки `target_name`/`target_type`/`raw_value` удалены (§5c). **не закоммичено** |
|
||||
| `yml-to-config.py` | 🆕 **изменён** — `emit_step`/`emit_condition`/`emit_action`, `_build_type9_line()`, `_encode_type9_value()` (обратный пересчёт `(t+273)*10`), блок «2b» вытягивает helper-секции в `result_lines`, `TYPE_ORDER` без сценарных helper-типов (§5c). **не закоммичено** |
|
||||
| `config-to-yml.py` | 🆕 **изменён** — форма §5j: `trigger` на уровне сценария, `steps[].{id, action}`, `_f5`/`_op`/`_then`/`_else`, `descr` у шага убран, `object` вместо `condition.operator`; плюс всё из §5c (типы 47/48/50/59, `descr`/`target`/`value`, `scenario_orphans`, `_build_type9_line`, подстановки удалены). **не закоммичено** |
|
||||
| `yml-to-config.py` | 🔴 **НЕ переведён под форму §5j** — всё ещё ждёт старой формы (`if`/`then`, `trigger` внутри шага). **Round-trip сломан.** Остальное из §5c на месте: `_build_type9_line()`, `_encode_type9_value()`, блок «2b». **не закоммичено** |
|
||||
| `test_roundtrip.py` | ✅ в коммите `199f2b1`, без изменений |
|
||||
| `zont_config/config_local_2026-09-17_16-13-28.txt` | 🆕 **34 963 байт** — **ПОСЛЕДНИЙ** конфиг (уставка 5.2 + «Температура Детская» = 14.5). Снят с `http://192.168.0.50/config.txt`. **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_16-13-28.yml` | 🆕 **5560 строк** — **финальная форма** YAML, round-trip ✅. **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_16-02-18.txt` / `.yml` | 34 962 байт — предыдущий (контур `Спальня`, режим `Режим отопления`). **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_17-45-00.txt` | 🆕 **34 963 байт** — **ПОСЛЕДНИЙ** конфиг. Снят с `http://192.168.0.50/config.txt`. **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_17-45-00.yml` | 🆕 **4405 строк** — **актуальная форма §5j**. **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_16-13-28.txt` / `.yml` | 34 963 байт, 5560 строк — предыдущая генерация (старая форма). **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_16-02-18.txt` / `.yml` | 34 962 байт — контур `Спальня`, режим `Режим отопления`. **не в git** |
|
||||
| `zont_config/config_local_2026-09-17_14-16-35.txt` / `.yml` | 34 907 байт, 660 `#Z` — с тестовыми сценариями логики. **не в git** |
|
||||
| `zont_config/config_0FA7C33CC89F_…_2026-09-17_12-12-28.txt` | 32 689 байт — боевой конфиг, round-trip ✅. **не в git** |
|
||||
| `zont_config/config_0FA7C33CC89F_…_2026-09-17_12-12-28.txt` | 32 689 байт — боевой конфиг, round-trip ✅ (до правки формы). **не в git** |
|
||||
| `zont_config/archive/` | `-2`/`-3`/`-4` — ✅ **закоммичены** (`7ae0e32`) |
|
||||
| `zont_local_ui_recon/config_live_192.168.0.50.txt` | живой конфиг для разведки WS-интерфейса, **не в git** |
|
||||
| `zont_api_docs/` | ✅ локальная копия доки облачного API (`zont_api_docs.html`, `.txt`, `convert.py`). **не в git** |
|
||||
| `read_scenarios.py` | 🆕 **читаемый дамп сценария** — дерево если/то/иначе с именами. Токенайзер `split_top()`. **не в git** |
|
||||
| `dump_new_types.py`, `probe_types.py`, `trace_scenarios.py` | 🆕 скрипты разбора сценарных типов. Разбор — [[family/tech/zont-scenario-logic-11109]] §8.8. **не в git** |
|
||||
| `probe_sched.py`, `verify_answers.py`, `check_ops.py`, `audit_8456.py`, `audit2.py`, `chk_extra.py`, `why_raw.py`, `fit_temp.py`, `fit_temp2.py` | 🆕 проверочные скрипты (в т.ч. подбор формулы уставки). **не в git** |
|
||||
| `/tmp/backup-config-to-yml.py`, `/tmp/backup-yml-to-config.py` | 🆕 бэкапы обоих конвертеров перед правкой формы (временные) |
|
||||
| `~/rasputin-tmp/zont-util/` | ✅ настроечная утилита `H1000 Programmator` 2.8.5, прошивка `.enc`, `extract.py`. Разбор — §5g-2 |
|
||||
| `~/rasputin-tmp/zont-{auth-probe,recon,recon2,ws-probe}.js` | ✅ скрипты разведки локального WS. **не в git** |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user