Files
obsidian-vault/family/tech/zont-scenario-logic-11109.md
T

37 KiB
Raw Blame History

aliases, created, namespace, related, tags, title, type, updated
aliases created namespace related tags title type updated
ZONT сценарий 11109
Передернуть Автомат Котельной
ZONT тип 45 задержка
ZONT сценарная логика
ZONT поле 2 сценария
2026-09-17 family
family/how-to/zont-config-compiler
family/tech/zont-config-object-types
family/how-to/home-automation
family
tech
zont
modbus
homeautomation
🔁 ZONT — сценарная логика и конструктор (11/46/47/48/49/50/59/45) tech 2026-09-17g

🔁 ZONT — сценарная логика и конструктор логики

🔴 ВНИМАНИЕ: раздел §1 ниже содержит УСТАРЕВШУЮ модель. Поле 5 типа 11 — НЕ «enabled», это тип запуска сценария (0/1 ручной, 8 расписание, 9 триггер, 10 интервал). Исправление и полная модель — §8. Раздел §1 оставлен как история разбора; актуальная семантика в §8.

Как устроены сценарии в конфиге ZONT и что именно разобрано в боевом конфиге config_0FA7C33CC89F_0FA7C33CC89F_2026-09-17_12-12-28.txt (598 #Z, 25 #S, 65 сценариев). Контекст конвертеров — family/how-to/zont-config-compiler.


1. Структура сценария

Сценарий — это 4 связанных типа объектов:

#Z<sid>=11,'Имя',[<шаг>,<шаг>,…],0,0,<enabled>,0,0     ← сценарий
#Z<step>=46,<prio>,<cond>,[<действие>,…],[]            ← шаг
#Z<cond>=49,<relay_id>,<operator>,<value>              ← условие
#Z<act>=…                                              ← действие (тип 5, 9 или 45)
Тип Роль Формат Поля
11 Сценарий [11, name, [step_ids], 0, 0, enabled, 0, 0] 8 полей. enabled — поле v[5] (0/1)
46 Шаг [46, prio, cond_id, [action_ids], []] 5 полей. prio и последнее поле — всегда 0/[]
49 Условие [49, relay_id, operator, value] 4 поля. operator: 1=equals, иначе not_equals
45 Задержка [45, <миллисекунды>] 2 поля

Каноническая форма (99% конфига): 1 сценарий → 1 шаг → 1 условие → 1 действие.


2. Действия в шаге — три разных типа

Список действий шага (46 поле 3) может содержать объекты трёх типов:

Тип Что это Формат Декодирование
5 Действие над выходом контроллера [5, name, output_ref, 1, delay, impulse_dur, [], sched_bmp, sched_time, impulse_period, value] 11 полей. output_ref >> 4 = id выхода; delay — поле 4 (мс)
9 Команда реле [9, name, target_relay, '1'/'0'] 4 поля. valueстрока '1'/'0', не число
45 Пауза между действиями [45, ms] 2 поля

⚠️ Тип 45 ≠ delay_ms типа 5. delay_ms — задержка внутри действия перед его выполнением. Тип 45 — отдельный объект-пауза в последовательности. Их часто путают при чтении конфига.


3. Разобранный кейс: #Z11109 «Передернуть Автомат Котельной»

Единственный сценарий в конфиге с нестандартной формой — 7 действий в шаге и задержка (45) прямо в поле 2 сценария (11828) вместо второго шага. См. §5 «Уточнение семантики поля 2».

#Z11109=11,'Передернуть Автомат Котельной',[11827,11828],0,0,0,0,0
#Z11823=49,11190,1,0                                    ← условие
#Z11827=46,0,11823,[11191,11030,11824,11029,11825,11192,11826],[]
#Z11828=45,0                                            ← шаг 2
#Z11824=45,20000   #Z11825=45,60000   #Z11826=45,0
#Z11029=9,'Включить реле «20/1 Автомат Котельная»',11028,'1'
#Z11030=9,'Выключить реле «20/1 Автомат Котельная»',11028,'0'
#Z11191=9,'Включить реле «virt. Запретить передергивание»',11190,'1'
#Z11192=9,'Выключить реле «virt. Запретить передергивание»',11190,'0'
#Z11028=14,'20/1 Автомат Котельная',175728,0
#Z11190=14,'virt. Запретить передергивание',179904,0

Что происходит по шагам

Условие: relay 11190 ('virt. Запретить передергивание') == 0 — т.е. передёргивание не запрещено.

Шаг 1 (11827) — 7 действий подряд:

# Объект Действие Пауза после
1 11191 (type 9) включить virt. Запретить передергивание
2 11030 (type 9) выключить 20/1 Автомат Котельная
3 11824 (type 45) пауза 20 000 мс
4 11029 (type 9) включить 20/1 Автомат Котельная
5 11825 (type 45) пауза 60 000 мс
6 11192 (type 9) выключить virt. Запретить передергивание
7 11826 (type 45) пауза 0

Шаг 2 (11828) — на деле это не шаг, а задержка [45, 0] прямо в поле 2 сценария: пустая пауза-заглушка. Оставлена планировщиком ZONT, функциональной нагрузки не несёт.

Смысл логики

Это защита от повторного передёргивания:

  1. Виртуальное реле virt. Запретить передергивание (id 11190) ставится в 1 первым действием.
  2. Условие сценария (11823) требует == 0 → пока реле в 1, сценарий повторно не запустится.
  3. Снимается реле только после 20 с + 60 с пауз (действие 6), т.е. через 80 секунд после старта → минимальный интервал между передёргиваниями автомата = 80 с.

🔴 Проблема

#Z11109 поле v[5] = 0сценарий выключен в контроллере. Защита и сама функция передёргивания не работают.


4. Полные счётчики по конфигу (для сверки после правок)

Тип Кол-во Комментарий
11 / 46 65 / 65 все одношаговые, кроме 11109
49 65 все ровно 4 поля, op=1 (equals) у всех
45 4 11824, 11825, 11826, 11828 — только в 11109
9 42 21 пара ВКЛ/ВЫКЛ, value — строка '1'/'0'
5 66 действия над выходами
14 40 реле
10 22 GUI-переключатели
0 / 36 13 / 13 дискретные датчики + вложенные конфиги
52 / 51 / 53 93 / 11 / 64 Modbus-регистры / устройства / ещё один слой
16 / 20 10 / 1 контуры и режимы отопления
Всего #Z 598

Проверка после любой правки: grep -c '^#Z' <файл> должен дать 598.


5. Статус разбора конвертером

Что Статус
Многошаговый сценарий ([11827,11828]) разбирается с 2026-09-17
7 действий в шаге 11827 разбирается с 2026-09-17
Тип 45 (4 объекта) парсер + эмиттер, секция YAML delays
Round-trip всех 4 конфигов чисто (test_roundtrip.py, коммит 199f2b1)
Сценарий enabled=0 факт, не баг конвертера

🔴 Уточнение семантики поля 2 (важно)

Поле 2 сценария — не «список шагов», а последовательность ссылок, куда попадают объекты разных типов. Полный список: шаг (46) и задержка (45).

В #Z11109 поле 2 = [11827, 11828], где:

  • 11827 — настоящий шаг (46) с условием и 7 действиями;
  • 11828задержка (45,0), т.е. «шаг-ожидание» без условия.

Поэтому формулировка «2 шага» неточна: шаг один, вторым элементом идёт задержка-заглушка. Отсюда же — extra_links в YAML (см. family/how-to/zont-config-compiler §2.1): не-46 ссылки сохраняются дословно, чтобы round-trip остался байт-точным.

⚠️ Не путать с типом 45 внутри шага. В 11827 задержки 11824/11825/11826 — это действия внутри шага. 11828ссылка в поле 2 сценария, т.е. элемент верхнего уровня.


6. План переработки YAML-структуры (2026-09-17, ждёт апрува)

Сценарии в YAML переписываются в нативную ZONT-форму вложенных инструкций «если … то …»без HA-синтаксиса (triggers, platform: state). Alex: «нет структура должна быть как в zont. триггеров нет.»

Предлагаемая форма для 11109:

scenarios:
  - id: 11109
    name: 'Передернуть Автомат Котельной'
    enabled: false
    blocks:
      - id: 11827
        if: {id: 11823, relay: 11190, operator: equals, value: 0}
        then:
          - {id: 11191, action: relay_on,  relay: 11190}
          - {id: 11030, action: relay_off, relay: 11028}
          - {id: 11824, action: wait, ms: 20000}
          - {id: 11029, action: relay_on,  relay: 11028}
          - {id: 11825, action: wait, ms: 60000}
          - {id: 11192, action: relay_off, relay: 11190}
          - {id: 11826, action: wait, ms: 0}
    tail:
      - {id: 11828, action: wait, ms: 0}   # задержка из поля 2 сценария

Полный план — family/how-to/zont-config-compiler §5c.

РАБОТА ПО §5c ПРИОСТАНОВЛЕНА (2026-09-17). Alex дал «стоп» и запросил исследование облачного API ZONT — есть ли альтернатива конвертеру. Ответ: API конфиг не поддерживает (сценарии/реле/ 11/14/46/49 в API отсутствуют). Переписывать с 0 не на что, конвертер остаётся единственным путём. Разбор — family/tech/zont-api. Форма blocks/if/then выше — предложение, в коде не реализовано.


7. Связанные заметки


8. 🔴 КОНСТРУКТОР ЛОГИКИ ZONT — типы 47 / 48 / 50 / 59 (разобрано 2026-09-17)

Источник: локальный конфиг с контроллера, снят с http://192.168.0.50/config.txt (без авторизации, см. family/tech/zont-api §6bis): zont_config/config_local_2026-09-17_14-16-35.txt34 907 байт, 660 #Z, 25 #S.

Alex создал тестовые сценарии в UI, «постарался использовать все доступные триггеры и варианты логики». Это позволило вскрыть полноценный визуальный конструктор логики со скриптовым движком.

8.1. 🔴 ИСПРАВЛЕНИЕ: поле 5 типа 11 — ТИП ЗАПУСКА, а не enabled

Прежняя модель (§1, строка [11, name, [step_ids], 0, 0, enabled, 0, 0]) неверна. Поле 5 (индекс 5) — тип запуска сценария:

Значение Что это Доказательство из тестовых сценариев
0 / 1 ручной запуск (кнопка), вкл/выкл 64 старых сценария = 1; 11109 = 0
8 по расписанию #Z8597 — поле 4 = 61, поле 6 = 3354 расшифровано
9 по триггеру (условию) #Z8547, #Z8551 — оба триггерные (подтверждено Alex)
10 по интервалу #Z8599 — поле 6 = 43200000 мс = 12 ч

Поле 6 — параметр запуска (для 10 — интервал в мс; для 8 — время запуска).

🔴 Поле 4 + поле 6 при запуске по расписанию — РАСШИФРОВАНО (2026-09-17)

#Z8597 «Тестовый сценарий по расписанию», Alex: ПН, СР, ЧТ, ПТ, СБ, в 13:26.

Поле Значение Расшифровка
поле 4 61 = 0b00111101 битовая маска дней недели: бит 0=ПН, 1=ВТ, …, 6=ВС. Установлены биты 0,2,3,4,5 = ПН, СР, ЧТ, ПТ, СБ
поле 6 3354 = 0x0D1A время: старший байт 0x0D = 13 (час), младший 0x1A = 26 (минута) → 13:26
#Z8597 = 11, 'Тестовый сценарий по расписанию', [8598], 61, 3354, 8, 0, 0
                                                  ^годнедели ^время  ^тип

Формула времени: поле6 = (час << 8) | минута. Начало недели — ПН (бит 0), не ВС. Проверка: 61 >> 0 & 1 = 1 (ПН есть), 61 >> 1 & 1 = 0 (ВТ нет — у Alex ВТ не отмечен) .

#Z8456=11,'Простой тестовый сценарий',[<26 ссылок>],0,0, 8,0,0
#Z8547=11,'тестовый сценарий по времени',  [8550],0,0, 9,0,0
#Z8551=11,'Тестовый сценарий по триггеру',[8555],0,0, 9,0,0
#Z8597=11,'Тестовый сценарий по расписанию',[8598],61,3354, 8,0,0
#Z8599=11,'Тестовый сценарий по интервалу',[8600,8601],0,0, 10,43200000,0

⚠️ Следствие для конвертера: enabled в YAML сейчас выводится из поля 5 как булево — это потеря информации для значений 8/9/10. Конвертер на новом конфиге падает (Ошибка: Условие 8496: не type 49) — новые типы не поддержаны.

8.2. Новые типы объектов (УТОЧНЕНО ответами Alex 2026-09-17)

Тип Что Формат Пример
47 лист дерева условий (сравнение) [47, <оператор>, <левый>, <правый_или_0>, <константа>] [47, 3, 8552, 0, -5] — «погода <= -5»
48 группа условий [48, <логика>, [<id условий>]] [48, 0, [8493,8495]]
50 объект-триггер запуска (внешний/системный) [50, 1, 0, 0, <ext_id>] [50, 1, 0, 0, 109]
59 мини-скрипт ZONT [59, '<код>', <арг1>, <арг2>, <флаг>] [59, 'expr "%0 + %1"', 8459, 8460, 0]

Type 47 — модель полей. [47, op, LEFT, RIGHT, K]:

  • LEFT — объект/скрипт-выражение слева;
  • если RIGHT != 0второй объект, сравнение двух объектов (8495: var1 >= objstate 9838, RIGHT = 8494);
  • если RIGHT = 0 — сравнение с константой из поля 4 (8493: OBJECT < 3).

Type 47, операторы — ПОДТВЕРЖДЕНО Alex (порядок пунктов UI: <, >, =, <=, >=):

Поле 1 Оператор Доказательство (формулировка Alex)
0 < 8493 «значение элемента управления < 3»; 8497 «var1 < 2»
1 > 8499 «Pickle(2) > 3»
2 = в тестовом блоке нет; следует из порядка UI
3 <= 8553 «погода из интернета <= -5»
4 >= 8495 «var1 >= значение 13/9 рад. ванная 2эт»

🔴 Ловушка: порядок пунктов UI (<,>,=,<=,>=) не логически упорядочен. = стоит третьим (код 2), между > и <=. Не «додумывать» порядок как «сначала все меньше, потом все больше» — это даёт неверные коды.

Type 48, логика группы — ПОДТВЕРЖДЕНО Alex (по описанию теста 8456):

Поле 1 Логика Доказательство
0 И (все условия) 8496 = [48,0,[8493,8495]] — «условие И: ...»
1 ИЛИ (любое) 8501 = [48,1,[8497,8500]] — «ИЛИ: ...»
2 НЕ (отрицание) 8500 = [48,2,[8499]] — «НЕ (...)»

Type 50 — триггер запуска. [50, 1, 0, 0, <ext_id>], где <ext_id>внешний/системный объект, которого нет среди #Z (напр. 109 — «погода из интернета»). Сценарий «по времени» (8547, шаг 8550) ссылается на 109 — в UI это тоже триггер-условие запуска (поле 5 типа 11 = 9).

8.3. Type 59 — встроенный скриптовый язык

Найденные команды (в поле 1, в кавычках — аргументы):

Команда Пример Смысл (предположительно)
objcmd <id> "<args>" objcmd 8700 "1 %0" команда объекту с подстановкой %0, %1
objstate <id> <n> <n> objstate 9838 0 0 чтение состояния объекта
expr "<формула>" expr "%0 + %1", expr "%0 - %1" арифметика
set <var> set var1 присваивание переменной
puts "текст" puts "Отладка", puts "test" вывод (отладка)
storeev I "z" / storeev A "asdf" запись события (I = integer?, A = alert/array?)
просто число/строка 3, 2 ;#p константа; суффиксы ;#a, ;#h, ;#p

Есть переменные (var1), подстановки %0/%1 (аргументы из полей 2/3), суффиксы ;#a/;#h/;#p. Это объясняет всё: у ZONT есть полноценный визуальный конструктор логики поверх скриптового движка.

8.4. Дерево условий — рабочий пример (#Z8505, #Z8506)

Вложенная логика читается так:

#Z8506 = [46, 0, 8496, [8505], []]            ← шаг: условие 8496, действие 8505
#Z8496 = [48, 0, [8493, 8495]]                ← группа: 8493 И 8495
#Z8493 = [47, 0, 8492, 0, 3]                  ← лист: объект 8492, значение 0, порог 3
#Z8492 = [59, 'objstate 9838 0 0', 0, 0, 0]   ← объект = скрипт!
#Z8495 = [47, 4, 8472, 8494, 0]
#Z8494 = [59, 'objstate 9838 0 0', 0, 0, 0]

#Z8505 = [46, 1, 8501, [8502, 8503], [8504]]  ← шаг: приоритет 1, доп. список [8504]
#Z8501 = [48, 1, [8497, 8500]]                ← группа: 8497 ИЛИ 8500
#Z8497 = [47, 0, 8472, 0, 2]
#Z8500 = [48, 2, [8499]]                      ← группа: логика 2 над [8499]
#Z8499 = [47, 1, 8498, 0, 3]
#Z8498 = [59, '2 ;#p', 0, 0, 0]

📌 В #Z8505 поле 1 (приоритет) = 1, и поле 4 (последнее) = непустой список [8504] — в отличие от «канонических» шагов, где там всегда []. Конвертер это отвергает (require(step[4] == [])). Семантика поля 4 — не подтверждена.

8.5. Контейнер-сценарий #Z8456 (поле 2 = смесь типов)

#Z8456 = [11, 'Простой тестовый сценарий', [<26 ссылок>], 0, 0, 8, 0, 0] — поле 2 содержит объекты разных типов, а не только шаги:

Тип Кол-во Примеры
9 (команда реле) 2 8457 «Установить целевую температуру 23.8…», 8470 «Активировать режим…»
59 (скрипт) 17 84588504
11 (другой сценарий!) 1 11109 «Передернуть Автомат Котельной»
3 (SMS) 1 8195 «CMC оповещение»
5 (действие) 1 9500 «Вкл. Рад. ванная 2эт»
45 (задержка) 1 8489 = 432 000 000 мс = 5 суток
46 (шаг) 1 8506

🔴 Сценарий может ссылаться на другой сценарий (11109 внутри 8456). Это не дерево, а плоский список ссылок.

8.6. Сводка тестового блока (id 84508601)

Типы в блоке: {9: 2, 11: 3, 14: 1, 16: 1, 27: 1, 45: 1, 46: 4, 47: 5, 48: 3, 49: 11, 50: 3, 59: 26}.

Сценарий Имя Поле 5 (запуск)
8456 Простой тестовый сценарий 8 (расписание)
8547 тестовый сценарий по времени 9 (триггер)
8551 Тестовый сценарий по триггеру 9 (триггер)
8597 Тестовый сценарий по расписанию 8 (расписание)
8599 Тестовый сценарий по интервалу 10 (интервал, 12 ч)

8.7. ВОПРОСЫ ЗАКРЫТЫ — ответы Alex (2026-09-17)

Alex создал тестовые сценарии и описал, что видно в UI. Все пять вопросов закрыты:

# Вопрос Ответ Проверка по конфигу
1 Type 47, оператор Операнды в UI: <, >, =, <=, >= → коды 0..4 все 5 листов сошлись
2 Type 48, логика 0=И, 1=ИЛИ, 2=НЕ по описанию теста 8456
3 Type 50 Объект-триггер запуска (внешний, напр. 109 «погода из интернета»)
4 Type 11, поле 4 Маска дней недели (61 = ПН,СР,ЧТ,ПТ,СБ), поле 6 = `(час<<8) мин`
5 ;#a/;#h/;#p (не переспрашивал; остаются гипотезой)

Разбор тестовых сценариев Alex (ответы дословно → факты конфига):

Сценарий Что сказал Alex Что в конфиге
8597 расписание «пн, ср, чт, пт, сб, в 13:26» поле 4=61, поле 6=3354=13:26
8547 «по времени» «по триггеру, триггер на день недели: пн,ср,чт,сб,вс» поле 5=9, шаг 8550[50,1,0,0,109]
8551 «по триггеру» «триггер сравнение: погода из интернета <= -5, действие вывод в терминал» 8553=[47,3,8552,0,-5], 8552=[49,8254,0,4], 8254=«Погода из интернета», then 8554=puts "Температура упала ниже -5"
8547 шаг 8550 «только одно действие: вывод "test" в терминал» 8549=[59,'puts "test"',0,0,0]
8456 (26 ссылок) «set var много, у каждого разный тип значения» 7× set var1 + 7 разных типов объектов

Type 46 — модель полей ПОДТВЕРЖДЕНА (5 полей = если/то/иначе):

#Z<step> = [46, <вид>, <id_условия_или_0>, [<ТОГДА>...], [<ИНАЧЕ>...]]

Alex по тесту 8456 описал: «если (условие И: …) То: … Иначе: Сохранить событие» — и это точно соответствует 8506 = [46, 0, 8496, [8505], []] + 8505 = [46, 1, 8501, [8502,8503], [8504]], где [8504] = ветка ИНАЧЕ. Поле 4 = список ИНАЧЕ (ранее помечено «семантика не подтверждена» — теперь подтверждена).

⚠️ Поле 1 шага: 0 у внешнего, 1 у вложенного (8505) — вероятно «уровень вложенности» или признак вложенного блока. Точная семантика не подтверждена, но round-trip требует сохранять как есть.

8.8. Скрипты разбора (в проекте)

Файл Назначение
read_scenarios.py 🆕 читаемый дамп любого сценария — дерево если/то/иначе с именами объектов. python3 read_scenarios.py <config> <id>
dump_new_types.py дамп типов 11/45/46/47/48/49/50/59 целиком
probe_types.py распределение поля 5 у type 11; тело контейнера; блок 8450–8560
trace_scenarios.py трассировка сценарных графов, поиск сценариев с новыми типами
probe_sched.py 🆕 проверка расписания: маска дней + время
verify_answers.py 🆕 кросс-проверка ответов Alex против фактов конфига
check_ops.py 🆕 проверка таблицы операторов type 47
audit_8456.py, audit2.py 🆕 аудит прозрачности элементов сценария 8456
cd /Users/admin/Automation/HA-ZONT-Modbus
python3 read_scenarios.py zont_config/config_local_2026-09-17_14-16-35.txt 8456   # дерево сценария
python3 read_scenarios.py zont_config/config_local_2026-09-17_14-16-35.txt        # все сценарии
python3 probe_types.py        # семантика поля 5, тестовый блок
python3 dump_new_types.py     # все сценарные объекты

Токенайзер починен. Старый read_scenarios.py рвал строки со скриптами на запятых внутри кавычек (objcmd 9102 "6,%0";#a разваливалось). Новый split_top() учитывает кавычки, экранирование \ и вложенные [] — теперь скрипты печатаются как есть.

8.10. НЕПРОЗРАЧНЫЕ ЭЛЕМЕНТЫ СЦЕНАРИЯ 8456 ( разблокированы raw-стратегией)

Alex спросил: «а по всем действиям в "Простой тестовый сценарий" — тебе всё кристально прозрачно?» Ответ был — нет. Ниже ровно то, что не выводится из конфига.

Разблокировано 2026-09-17. Alex решил: «допиливаешь парсер с известными типами, а неизвестные — пусть в yml будут raw values, и тогда я доразберу». После этого конвертер дописан, round-trip чистый, эти вопросы больше не блокируют работу (§8.9). Семантику доразбирает Alex в YAML через raw-поля. Гипотезы по-прежнему не строить — открытые пункты остаются открытыми.

# Элемент Что неясно
1 #Z8456 поле 5 = 8 (расписание), но поле 4 = 0, поле 6 = 0 Как запускается 8456? Расписание не задано. Что значит 8 без маски/времени? Ручной запуск?
2 #Z8458 = [59, 'objcmd 8700 "1 %0"', 10.5, 0, 1] Единственный скрипт с нецелым %0 (10.5) и флагом 1 в поле 4 (у всех остальных 0). Что за инструкция в UI?
3 #Z8463 = [59, 'objcmd 9102 "6,%0";#a', 8462, 0, 0], где 8462 = скрипт expr "%0 + %1" Аргумент = ссылка на другой скрипт. Что за суффикс ;#a?
4 #Z8465 = [59, 'objcmd 11907 ",,,%0";#h', 8464, 0, 0], где 8464 = [49, 4099, 0, 8] (условие) Аргумент = условие. Что за ;#h?
5 #Z8467 = [59, '3', 0, 0, 0] Скрипт = просто цифра 3. Константа? Зачем отдельным действием?
6 #Z8486/#Z8488 = set var1, arg1 = 8485/8487type 50 Type 50 стоит как источник значения для var1, а не как триггер. Это то же самое, что триггер?
7 #Z9500 = [5,'Вкл. Рад. ванная 2эт',145728,1,0,0,[],0,0,0,512] Объект выхода 145728 отсутствует в конфиге. Поле 10 = 512 — что это?
8 #Z8457 = [9,'Установить целевую температуру 23.8...',8669,'2968'], #Z8470 = [9,...,8669,'8574'] Значение '2968'отсутствующий объект. Это «установить температуру»/«активировать режим»?

Что уже прозрачно (не переспрашивать):

  • 7× set var1 и их источники: 8450(Температура подачи, тип 27), 9864(Статус 13/9, тип 0), 8560(Контур газ котла, тип 16), 9263(Реле 1 конвектор, тип 14), 8254(Погода из интернета, тип 1), 4098(Адаптер газ. котла, тип 6), 8382(Температура Zigbee, тип 1)
  • #8466 puts "Отладка", #8468 storeev I "z", #8469 storeev A "asdf" — вывод/события
  • #8489 пауза 5 суток (432000000 мс), дерево #8506#8505 (И/ИЛИ/НЕ + ИНАЧЕ)
  • #8195 SMS CMC оповещение8192 (2 номера)
  • #11109 как вложенный сценарий внутри 8456
  • #8507 — ссылка на отсутствующий объект (хвост поля 2)

Почему неясные элементы не блокируют парсер: стратегия — сохранять их дословно (type 59 как сырые строки с arg1..arg3, отсутствующие id — как есть). Round-trip останется байт-точным независимо от того, понята семантика или нет.

8.9. Состояние: конвертер новый конфиг РАЗБИРАЕТ (2026-09-17)

ИСПРАВЛЕНО. Все пять пунктов ниже реализованы в конвертерах (§5c в family/how-to/zont-config-compiler). Round-trip чистый на 6/6 конфигах. Ранее падал с Ошибка: Условие 8496: не type 49 (exit 2) — больше не падает.

Что было нужно — ВСЁ СДЕЛАНО:

# Было нужно Статус
1 Парсер типов 47/48/50/59 + рекурсивное дерево условий dump_condition/dump_leaf/dump_action
2 Поле 5 типа 11 — тип запуска (0/1/8/9/10), не enabled trigger: {type, days, time, interval_ms}
3 Поле 4 шага — принимать непустые списки elsesteps[])
4 Ссылки в поле 2 — допускать не-46 типы (45, 11, 3, 5, 9) плоский steps[] — каждый элемент по порядку, тело инлайн
5 Round-trip всех 5 конфигов 6/6 (боевой + 3 архива + новый локальный + live)

Счётчики нового конфига (для сверки): 660 #Z, 25 #S, байт — 34 907.

Тип Кол-во Тип Кол-во
11 70 49 76
46 69 47 5
45 5 48 3
9 44 50 3
59 28 0/36 13/13

8.11. ФИНАЛЬНАЯ YAML-форма сценария — плоский steps[] (2026-09-17)

🔴 Урок, который стоит запомнить. Первая реализация делила поле 2 на blocks (шаги 46) + extra_links (голые id). Round-trip был чистый (байты сходились), но сценарий читался как список цифр: blocks выводился первым, а всё «до него» — 25 элементов «установка температуры, puts, set var1, пауза 5 суток» — лежало в extra_links без тел. Alex: «почему там блядь if идет первым блоком?! где все что до него происходит?!» Вывод: round-trip ≠ читаемость. Артефакт надо читать глазами до отдачи.

Правильная форма — одно поле steps, плоский список = поле 2 сценария как есть:

scenarios:
  - id: 8456
    name: Простой тестовый сценарий
    trigger: {type: schedule}
    _raw_trigger_kind: 8
    steps:
      - {id: 8457, raw: [9, 'Установить целевую температуру 23.8 …', 8669, '2968']}
      - {id: 8458, script: 'objcmd 8700 "1 %0"', args: [10.5, 0, 1]}
      - {id: 8463, script: 'objcmd 9102 "6,%0";#a', args: [8462, 0, 0]}
      - {id: 11109, run_scenario: Передернуть Автомат Котельной}
      - {id: 8466, script: 'puts "Отладка"', args: [0, 0, 0]}
      - {id: 8473, script: 'set var1', args: [8471, 0, 0]}     # + ещё 6 × set var1
      - {id: 8489, wait: 432000000}                            # пауза 5 суток
      - id: 8506                                               # шаг с условием — тоже элемент
        if: {id: 8496, group: and, children: [
              {id: 8493, op: '<',  left: 8492, value: 3},
              {id: 8495, op: '>=', left: 8472, right: 8494}]}
        then: [{id: 8505, kind: 1, if: {…}, then: [{id: 8502, script: 'puts "then-text"'}], else: [{id: 8504, script: 'storeev A "alert"'}]}]
      - {id: 8507, unresolved: true}

Диспетчер dump_step() — по типу элемента: 46if/then/else, 59script+args, 47/48/49→дерево условий, 45wait, 50trigger_object (raw), 11run_scenario, 5/9/3raw-тело. Мелкая деталь: тела объектов чужих секций (sms_notifications, actions) рендерятся как YAML-якоря *id00N (8195, 9500 в 8456) — читается хуже, но байт-точно.

Артефакт: zont_config/config_local_2026-09-17_14-16-35.yml (6110 строк) — в проекте, не в /tmp.