[2026-09-17] eagle: family/how-to/zont-config-compiler.md family/tech/zont-scenario-logic-11109.md

This commit is contained in:
Alexey Martemyanov
2026-09-17 17:40:19 +06:00
parent b23f164ba1
commit 6da719c0fe
2 changed files with 132 additions and 11 deletions
+31 -1
View File
@@ -21,7 +21,7 @@ tags:
- homeautomation
title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml
type: how-to
updated: 2026-09-17
updated: 2026-09-17g
---
# ⚙️ ZONT Config Compiler — конвертеры `.txt ⇄ .yml`
@@ -333,6 +333,8 @@ diff A.txt B.txt # пусто = round-trip чистый
| 28 | ⚠️ **`object_display_name` нужен и раньше по файлу, чем определён** | Вложенная функция видна только ниже места вызова → `NameError` в секции type 9. Вынести на **уровень модуля** `object_display_name()`, оставить shim для вложенных вызовов |
| 29 | ⚠️ **Удаление `raw_value` требует пересчёта кода в энкодере** | Если убрать сырьё, но оставить `value` (Цельсии), энкодер напечатает `5.2` вместо `'2782'` → round-trip падает. Нужен `_encode_type9_value()`: `True→'1'`, `False→'0'`, число → `str(round((v+273)*10))` |
| 30 | ⚠️ **Ветки type 5 / type 9 в энкодере различать по признаку, а не по наличию удалённого поля** | Различались через `'raw_value' not in step` — после удаления признак мёртв. Теперь: type 5 — есть `value` и `target > 255` (output_ref), type 9 — нет `args` |
| 31 | 🔴 **Один объект в двух секциях → два разных `value`** | Раскодировал `value` в `steps[]` (`5.2`), но забыл секцию `relay_commands` (осталось `'2782'`). **Round-trip зелёный** — он сравнивает строки конфига, а не смысл полей. Правило: правя декодирование, пройти **все** места, где объект отображается. Нашёл Alex глазами |
| 32 | 🔴🔴 **Поле 5 типа 11 — модель `TRIGGER_KINDS` ОШИБОЧНА (выдумка)** | Сопоставление `1=manual, 8=расписание, 9=триггер, 10=интервал` **опровергнуто** Alex: `9628` с `1` — по триггеру; `8456` с `8` — ручной+disabled; `8547`/`8551` оба `9`, но это «по времени» и «по триггеру». Разбор — [[family/tech/zont-scenario-logic-11109]] §8.16. **`TRIGGER_KINDS` подлежит удалению** |
### Ограничения конвертера (найдено 2026-09-17) — ВСЕ ЗАКРЫТЫ
@@ -403,6 +405,12 @@ diff A.txt B.txt # пусто = round-trip чистый
> **Подстановки `target_name`/`target_type`/`raw_value` удалены** — поля YAML = поля строки конфига.
> **YAML стал вдвое короче: 6093 → 5452 строки.** **Не закоммичено** — ждёт команды Alex.
>
> 🔴 **ОТКРЫТЫЙ БЛОКЕР (конец сессии):** модель `trigger` **опровергнута** Alex —
> `TRIGGER_KINDS` (`1=manual`, `8=расписание`, `9=триггер`) **выдумка**, поле 5 работает иначе.
> Подробности и факты — [[family/tech/zont-scenario-logic-11109]] §8.16(а).
> Также открыт вопрос Alex про саму форму YAML («не script editing language ли это») — §8.16(в).
> Код не тронут, ждём решения.
>
> 📄 **Артефакты (в проекте):** `zont_config/config_local_2026-09-17_16-13-28.yml` — **финальный**
> разобранный конфиг (5452 строки, уставка 5.2 + «Температура Детская»);
> `zont_config/config_local_2026-09-17_16-02-18.yml` — предыдущий.
@@ -499,6 +507,28 @@ Alex: «ЕСЛИ БЛЯДЬ В КОНФИГЕ `#Z8817=9,'…',10034,'2782'` ТО
> либо через явный проход. Убрать секцию из `TYPE_ORDER` ≠ «объект пропадёт» — он пропадёт
> **молча**, и это видно только по счётчику round-trip.
### 5d. 🔴 Незакрытые задачи конца сессии 2026-09-17 (ждать Alex)
| # | Задача | Статус |
|---|---|---|
| 1 | **`TRIGGER_KINDS` — удалить.** Модель поля 5 типа 11 опровергнута фактами | ⏸ код не тронут, нужен ответ Alex про UI |
| 2 | **Форма YAML** — Alex усомнился, что получился не конфиг, а «script editing language» | ⏸ решение не принято |
| 3 | `git commit` правок парсера/энкодера | ⏸ не закоммичено, ждёт команды |
| 4 | YAML `16-13-28` — перегенерировать после последней правки (`relay_commands` decode) | ⏸ на диске старая версия |
| 5 | Раскрыть `8195` (type 3 SMS) из YAML-якоря | ⏸ отложено |
**Уроки методологии этой сессии** (проверять в следующих):
1. **Round-trip ≠ корректность.** Зелёный round-trip уживается с:
- одним объектом с разными `value` в двух секциях (условие 31);
- выдуманной таблицей `trigger` (условие 32).
Он проверяет **байты**, не **смысл**. Главный кейс смотреть глазами (питфолл 21).
2. **Не подставлять производные поля.** `target_name`/`target_type` — дорисовка; Alex потребовал
убрать. В YAML должны быть **поля строки конфига**, ничего сверх.
3. **Не кодировать формулу по 2 точкам.** `(t+273)*10` вшита только после третьей точки от Alex.
4. **Не переносить данные между сценариями.** Расписание `61,3354` принадлежит `8597`, я приписал
его `8456` (у которого нули) — Alex поймал.
**Задача Alex (исходная):** «переписать блок парсинга/сборки сценариев чтобы он составлял синтаксис как у Home Assistant automations вместо текущей разбросанной структуры. с опциональными айдишниками у операторов».
### 🔴 Правка постановки Alex'ом (ключевое — не повторять ошибку)
+101 -10
View File
@@ -19,7 +19,7 @@ tags:
- homeautomation
title: 🔁 ZONT — сценарная логика и конструктор (11/46/47/48/49/50/59/45/9/5)
type: tech
updated: 2026-09-17f
updated: 2026-09-17g
---
# 🔁 ZONT — сценарная логика и конструктор логики
@@ -225,17 +225,24 @@ scenarios:
> Alex создал тестовые сценарии в UI, «постарался использовать все доступные триггеры и варианты
> логики». Это позволило вскрыть **полноценный визуальный конструктор логики** со скриптовым движком.
### 8.1. 🔴 ИСПРАВЛЕНИЕ: поле 5 типа 11 — ТИП ЗАПУСКА, а не `enabled`
### 8.1. 🔴🔴 ОТМЕНЕНО 2026-09-17: поле 5 типа 11 — НЕ тип запуска. Таблица ниже ОШИБОЧНА
Прежняя модель (§1, строка `[11, name, [step_ids], 0, 0, enabled, 0, 0]`) **неверна**.
Поле 5 (индекс 5) — **тип запуска сценария**:
> 🔴 **ЭТА МОДЕЛЬ ОТВЕРГНУТА ALEX (2026-09-17, конец сессии). Читать §8.16.**
>
> Alex: сценарий `9628` («Автомат.: Рад. ванная 2эт ВКЛ») — **по триггеру**, а поле 5 у него `1`,
> не `9`. Сценарий `8456` («Простой тестовый сценарий») — **такой же ручной, как остальные, но
> disabled**, а поле 5 у него `8`, не `1`. Оба противоречат таблице ниже.
>
> **Что осталось верным:** поле 5 — не просто `enabled` (§1 устарела тоже).
> **Что неверно:** сопоставление `8=расписание`, `9=триггер`, `0/1=ручной`.
> Актуальный разбор — **§8.16**. Таблица сохранена как история ошибки.
| Значение | Что это | Доказательство из тестовых сценариев |
| Значение | Что это (❌ ОШИБОЧНО) | Доказательство из тестовых сценариев |
|---|---|---|
| `0` / `1` | ручной запуск (кнопка), вкл/выкл | 64 старых сценария = `1`; `11109` = `0` |
| `8` | по **расписанию** | `#Z8597` — поле 4 = `61`, поле 6 = `3354` ✅ расшифровано |
| `9` | по **триггеру** (условию) | `#Z8547`, `#Z8551` — оба триггерные (подтверждено Alex) |
| `10` | по **интервалу** | `#Z8599` — поле 6 = `43200000` мс = **12 ч** |
| `0` / `1` | ручной запуск (кнопка), вкл/выкл | 64 старых сценария = `1`; `11109` = `0`**но `9628` с `1` триггерный** |
| `8` | по **расписанию** | `#Z8597` — поле 4 = `61`, поле 6 = `3354` ✅ расшифровано**но `8456` с `8` ручной+disabled** |
| `9` | по **триггеру** (условию) | `#Z8547` «по времени» и `#Z8551` «по триггеру» — **разные типы, а поле 5 у обоих `9`** |
| `10` | по **интервалу** | `#Z8599` — поле 6 = `43200000` мс = **12 ч** (не перепроверено) |
**Поле 6** — параметр запуска (для `10` — интервал в мс; для `8` — время запуска).
@@ -658,5 +665,89 @@ scenarios:
| YAML | `zont_config/config_local_2026-09-17_16-13-28.yml` | в проекте, round-trip ✅ |
Round-trip чистый на **6/6** конфигах (боевой, 3 архива, `14-16-35`, `16-13-28`).
Осталось два `raw`: `8195` (SMS, тело — YAML-якорь `*id002`) и `9500` (type 5, `params` содержит якорь).
> ⚠️ **УСТАРЕЛО после правок конца сессии** (см. §8.16): `target_name`/`target_type`/`raw_value`
> удалены, секции-дубли убраны, YAML = **5452 строки**. Актуальное состояние — §8.16.
### 8.16. 🔴 Разбор конца сессии 2026-09-17 — поле 5 и удаление подстановок
#### (а) Поле 5 типа 11 — модель §8.1 ОПРОВЕРГНУТА
Alex, разбирая YAML, наткнулся на сценарий `9628`:
```text
#Z9628=11,'Автомат.: Рад. ванная 2эт ВКЛ',[9756],0,0,1,0,0
```
> «сценарий `Автомат.: Рад. ванная 2эт ВКЛ`: там ахинея какая-то! это сценарий **по триггеру**.
> почему он **manual**?»
Парсер выводил `trigger: {type: manual}` — по таблице §8.1 (`1` = manual). Alex: неверно.
Дальше — прямое опровержение всей таблицы:
| Сценарий | Что сказал Alex | Поле 5 | Поля 3/4 |
|---|---|---|---|
| `9628` … 64 шт `Автомат.:*` | **по триггеру** | `1` | `0,0` |
| `8456` «Простой тестовый сценарий» | «**точно такой же manual как и другие два, но он disabled**» | `8` | `0,0` |
| `8547` «тестовый сценарий по времени» | по времени | `9` | `0,0` |
| `8551` «Тестовый сценарий по триггеру» | по триггеру | `9` | `0,0` |
| `8597` «Тестовый сценарий по расписанию» | расписание пн,ср,чт,пт,сб 13:26 | `8` | `61,3354` |
**Вывод: `8` и `9` не различают «расписание/триггер».** Два сценария с `9` — «по времени»
и «по триггеру» — Alex сделал специально как **разные типы**. `8456` с `8` — ручной.
`9628` с `1` — триггерный.
**Распределение поля 5 по 70 сценариям боевого конфига:**
| Код | Кол-во | Что известно |
|---|---|---|
| `1` | 64 | `Автомат.:*` — по триггеру (условие внутри шага) |
| `0` | 2 | `11109` и ещё один |
| `9` | 2 | `8547` (по времени), `8551` (по триггеру) |
| `8` | 1 | `8597` (расписание `61,3354`) + `8456` (disabled) |
| `10` | 1 | `8599` (интервал) |
> 🔴 **ЧЕГО Я НЕ ЗНАЮ (не выдумывать):**
> 1. Что означает `1` vs `9` — оба могут быть «включён и запускается по своему условию».
> 2. Как кодируется **disabled** (`8456` = `8` + нули, `8597` = `8` + заполненные поля —
> возможно, disabled = «тип есть, параметры сброшены»).
> 3. Где вообще хранится «по триггеру / по времени / ручной», если не в поле 5.
> Кандидаты: поле 4, поле 6, поле 7 — у `9628` и `8547`/`8551` все нули.
>
> **Статус: `TRIGGER_KINDS` в `config-to-yml.py` — ВЫДУМКА, подлежит удалению.**
> Ждём ответ Alex, что показано в UI у `9628` / `8547` / `8551` / `8456`.
#### (б) Структура YAML — работы конца сессии
| # | Что | Итог |
|---|---|---|
| 1 | Секции-дубли `delays`/`scenario_steps`/`scenario_conditions`/`scenario_scripts`/`scenario_raw_objects` | **удалены** из парсера, `TYPE_ORDER` и вывода. Осталась одна служебная — `scenario_orphans` (недостижимые объекты) |
| 2 | Переименование `command``descr`, `output`/`output_id``target`, `temp_c``value` | ✅ сделано, имена = поля строки конфига |
| 3 | `target_name` / `target_type` / `raw_value` | ✅ **удалены** (5 мест в парсере + энкодер) |
| 4 | Энкодер пересчитывает код из `value` | ✅ хелпер `_encode_type9_value()`: `True→'1'`, `False→'0'`, число → `str(round((v+273)*10))` |
| 5 | `object_display_name()` вынесен на уровень модуля | ✅ (был вложенной функцией ниже места вызова → `NameError`, питфолл 28) |
**Три питфолла, каждый ловил round-trip** (`Duplicate ID 8640/9826``потеряно 45``потеряно 189`)
подробно в [[family/how-to/zont-config-compiler]] §5c.
#### (в) Открытый вопрос Alex: «получается script editing language?»
Alex сформулировал **корневое** сомнение по форме YAML:
> «хуйня какая-то получается, не правда ли?» → «я говорю хуйня а не script editing language
> выходит какая-то»
Смысл: в YAML появились `if`/`then`/`else`/`group: and`/`op: '>'`/`wait`/`args` — **структура,
которой в конфиге нет**. Это не отображение данных, а интерпретация поверх них.
Отсюда же растут «две правды» (`'2782'` vs `5.2` в разных секциях) — симптом, не причина.
**Рассмотренный, но НЕ принятый вариант:** `steps` = те же плоские записи, что в `#Z`-строках,
плюс человеческие имена только для доказанных полей. Без `if`/`then`/`group`/`op`.
**Решение не принято — ждёт Alex.**
> 🔴 **Урок для методологии:** при правке одной секции проверять, не отображается ли тот же
> объект в другой. Раскодировал `value` в `steps[]`, но забыл про `relay_commands` → один объект,
> два разных `value`. Alex нашёл это глазами, round-trip был зелёным.
> **Round-trip не ловит смысловые расхождения между секциями.**