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

17 KiB
Raw Blame History

8.17. МОДЕЛЬ ЗАКРЫТА (2026-09-17, финал) — поле 5, форма сценария, type 47/49

🔴 ЧАСТИЧНО УСТАРЕЛО — актуальная форма в family/how-to/zont-config-compiler §8. Что здесь неверно:

  • if/then/else НЕ выдумка (§(б) ниже утверждает обратное). Это поля записи 46 — поле 3 = then-список, поле 4 = else-список, поле 2 = условие. Alex: «Then конечно!!!». Пара then/else обязательна там, где у шага есть свой if.
  • action — не выдумка, но и не универсальное имя: у шага с поднятым условием (trigger: наверху) список действий называется action; у шага со своим ifthen.
  • trigger: не дублируется в шаге: условие переносится (pop), иначе PyYAML ставит анкоры &id061/*id061 (было 69 штук).
  • _kind/_f5/_then в примерах §(б) — выдуманные служебные ключи, вырезаны.
  • Поле 5 в YAML не хранится вообще (type/field5 тоже вырезаны) — собирается из тела.

Статус (исторический): все открытые вопросы §8.16 закрыты. Ниже — подтверждённые факты. Таблица TRIGGER_KINDS удалена из кода; доказательство получено тостингом сценариев в UI: Alex выключил/включил тестовые сценарии, поле 5 снято до и после, плюс повторный тостинг 8597/8599 дал включённые значения schedule/interval (0 и 2).

(а) 🔴 Поле 5 типа 11 = тип сценария + флаг «выключен». ПОДТВЕРЖДЕНО прибора + Alex

type    = field5 & 7          # 0 = manual | schedule, 1 = trigger, 2 = interval
enabled = not (field5 & 8)    # бит 8 = сценарий ВЫКЛЮЧЕН

🔴 Слово — type, не kind. Слова kind в конфиге и UI нет; я его выдумал. Alex: «какой нахуй kind?? что это блядь значит?! я его откуда тебе высру?!» Типы назвал Alex: manual, trigger, interval, schedule.

Сценарий Выкл Вкл type Прочие поля
8456 «Простой тестовый» 8 0 = manual
8597 «по расписанию» 8 0 0 = schedule поля 3/4 = 61, 3354
11109 «Передернуть Котельной» 0 0 = manual 2 элемента в поле 2
8547 «по времени» 9 1 = trigger
8551 «по триггеру» 9 1 = trigger
9628 «Автомат.: Рад. ванная 2эт ВКЛ» 9 1 1 = trigger
8599 «по интервалу» 10 2 2 = interval поле 6 = 43200000 мс

🔴 Включённые 0 (8597) и 2 (8599) получены тостингом на приборе: Alex включил оба сценария в UI, конфиг снят заново (curl -s http://192.168.0.50/config.txt). До этого момента включённые значения schedule/interval были неизвестны — были только выключенные 8/10.

Итог: у каждого типа есть вкл/выкл, и всегда вкл + 8 = выкл:

тип вкл выкл
manual 0 (11109) 8 (8456)
schedule 0 (8597) 8 (был)
trigger 1 (64 шт) 9 (8547, 8551)
interval 2 (8599) 10 (был)

⚠️ manual (0) и schedule (0) — один и тот же type. Различаются наличием полей 3/4 (days_mask + time): у расписания они заполнены, у ручного — нули. Alex: «manual от schedule очевидно отличаются наличием блядь schedule!» Кодировку расписания см. §8.1 (61 = ПН,СР,ЧТ,ПТ,СБ; 3354 = (13<<8)|26 = 13:26).

Почему старая модель {0:manual,1:manual,8:schedule,9:trigger,10:interval} была неверна: она читала число как «класс запуска» целиком. На самом деле число двухбитовое по смыслу: младшие 3 бита = тип, бит 8 = выключено. Отсюда все противоречия §8.16.

Снятые гипотезы (не возвращаться): «field5 & 7 = значение из условия шага 46» (32 расхождения из 70 — пары ВКЛ/ВЫКЛ 9628/9629 имеют одинаковое поле 1 при противоположных условиях); «поле 5 не выводится из содержимого» (выводится: тип + бит 8).

Что в коде: TRIGGER_KINDS, _raw_trigger_kind, _raw_trigger_params, time_raw удалены. Заголовок сценария в YAML теперь: enabled, type, days/days_mask, time, interval_ms. Служебные _f5/_kind тоже убраны — поле 5 полностью восстанавливается из enabled + type.

(б) Форма YAML сценария — ПЕРЕСМОТРЕНА Alex'ом (финал сессии)

Alex отверг if/then/else в YAML как выдумку:

«у тебя в 9819 сейчас в yml написан if! а это не if а триггер»

Проверка конфига подтвердила: слов if, then, else, condition, object, operator, group, op в конфиге нет. Это была интерпретация парсера поверх данных.

Корневое требование: trigger — это триггер, а не if; steps — это шаги, а не ветвление.

Согласованная форма (принята Alex)

- id: 9691
  name: 'Автомат.: Прихожая (н/п) (14/14) ВКЛ'
  enabled: true
  trigger:
    - id: 9729
      object: '9495'
      value: 1
  steps:
    - id: 9819
      action: 9563

Соответствие строкам конфига — #Z9691 «Прихожая (н/п) 14/14 ВКЛ»

#Z9691=11,'Автомат.: Прихожая (н/п) (14/14) ВКЛ',[9819],0,0,1,0,0
#Z9819=46,0,9729,[9563],[]        ← шаг: условие 9729, действие 9563
#Z9729=49,9495,1,1                ← триггер: объект 9495, значение 1
#Z9495=14,'Датч 14/14: Прихожая (н/п)',151408,0
#Z9563=5,'Включить выход 14/14: Прихожая (н/п)',146064,1,0,0,[],0,0,0,512
YAML Строка конфига Поля
id: 9691, name #Z9691=11,… 1, 2
enabled: true #Z9691 поле 5 = 1 not (1 & 8)
trigger[].id: 9729 #Z9729=49,… 1 (id самого условия)
trigger[].object: '9495' #Z9729 2 (id объекта, на который смотрит триггер)
trigger[].value: 1 #Z9729 4 (значение; поле 3 = оператор)
steps[].id: 9819 #Z9819=46,… 1 (id шага)
steps[].action: 9563 #Z9819 4 (первый id из [9563])
тело действия #Z9563=5,'…',146064,1,… живёт своей строкой

Терминология Alex — точная

Id Что это по Alex Где в YAML
9691 сценарий id верхнего уровня
9729 триггер (не if!) trigger[].id
9495 объект, за которым следит триггер trigger[].object
9819 шаг (if of the step по формулировке Alex) steps[].id
9563 действие — «выполнить пользовательское действие» steps[].action

Alex: «#Z9563=5,… — это шаг «выполнить пользовательское действие» (action) 9563».

Единая модель вложенных id

Разница между trigger и steps — только в том, какое поле #Z9819 (тип 46) на них указывает:

#Z9819 = 46, 0, 9729, [9563], []
                │      │
                │      └── steps[].action    ← поле 4 (список действий)
                └───────── trigger[].id      ← поле 3 (условие)

object выбран словом для ссылки на объект, потому что в остальном коде уже так (dump_condition для type 49: 'object': node[1]), рядом с target (реле/контур) и descr.

Следствия для кода — ПУНКТЫ 1–3, 5 СДЕЛАНЫ (2026-09-17)

# Что Статус
1 dump_condition type 49 → {id, object, value} вместо {id, condition: {object, operator, value}} сделано
2 dump_step type 46 → {id, action: <первый then id>}; trigger вынимается на уровень сценария сделано
3 Заголовок сценария — kind/kind_raw/_kind/_f5 убраны, вместо них видимое поле type сделано
4 Непустые then/else / второй+ id → что писать в форме 🔴 открытый вопрос, ждёт Alex
5 dump_action — делегирование в dump_step (чтобы type 5/9 в телах не падали в raw) сделано
6 Энкодер под новую форму не начат — ждёт подтверждения формы. Round-trip сломан
7 type для 11109 выходит trigger вместо manual ⚠️ баг, гипотеза правки: trigger = ровно один элемент в steps И он типа 46. Прогон не выполнен

Фактический вывод парсера после правок (проверено 2026-09-17)

Перегенерация zont_config/config_local_2026-09-17_17-45-00.yml (exit 0, 4405 строк — было 5376):

- id: 9691
  name: 'Автомат.: Прихожая (н/п) (14/14) ВКЛ'
  enabled: true
  _kind: 1
  _f5: 1
  steps:
  - id: 9819
    trigger:
      id: 9729
      object: 9495
      value: 1
    action: 9563

if/then/else/condition/operator из YAML ушли полностью. Три служебных ключа (_kind, _f5, _op) содержат то, что энкодеру нужно для байт-в-байт сборки: _op пишется только когда оператор ≠ 1; _kind — только когда field5 & 7 ≠ 0; _f5 — всегда.

Многошаговый 11109 — форма подтвердила проблему:

- id: 11109
  name: Передернуть Автомат Котельной
  enabled: true
  _f5: 0
  steps:
  - id: 11827
    trigger:
      id: 11823
      object: 11190
      value: 0
    action: 11191
    _then:
    - 11191
    - 11030
    - 11824
    - 11029
    - 11825
    - 11192
    - 11826
  - id: 11828
    wait: 0

🔴 Это и есть открытый вопрос №4. У 11109 в then семь id — цепочка, а не одно действие. action: 11191 показывает только первое, остальные шесть ушли в служебный _then. Для 11109 _thenне служебный ключ, а реальное содержимое. Форма «один триггер → одно действие» описывает 64 из 65 сценариев; 11109 из неё выпадает. Ждём решения Alex: action остаётся одиночным, а цепочка — отдельная тема, или появляется actions:. Правка кода остановлена на этом вопросе, энкодер не тронут.

(в) Методология: почему форма переделывалась дважды

  1. blocks/extra_links — отвергнуто: порядок терялся, сценарий превращался в список цифр.
  2. when/then + if/group/op — отвергнуто как выдумка: слов нет в конфиге.
  3. trigger/steps + action — принято (эта форма).

🔴 Правило, выведенное из трёх итераций: в YAML попадают только слова, которые есть в конфиге или в UI. object — есть (здесь так называется ссылка), descr/target/value — есть (поля строки). if/then/condition/operator/group/op/kindнельзя: их в данных нет, это интерпретация.

🔴 Второе правило: descr ставить только там, где текст реально есть в строке. Для #Z9819 (шаг) текста нет — значит и descr у него быть не должно (Alex: «нахуй там тогда descr?! если его нет в оригинале?»).

⚠️ Не забегать вперёд с вопросами о том, чего в кейсе нет. Вопрос «что писать, когда в trigger окажется type 47» Alex воспринял как шум («что за type 47? нихуя не понятно») — в разбираемом сценарии его нет. Сначала форма на текущем кейсе, потом обобщение.

(г) Состояние на конец сессии (обновлено 2026-09-17, после правок кода)

Что Статус
Форма YAML сценария согласована (см. (б))
Правка config-to-yml.py под форму сделана — 3 патча (dump_condition type 49, dump_step type 46, заголовок)
YAML перегенерирован config_local_2026-09-17_17-45-00.yml4405 строк (было 5376), if/then ушли
Проверка формы глазами блок 9691 и 11109 прочитаны
Round-trip не прогнан после правок формы (энкодер ещё не подогнан — прогон осмыслен только после пункта 6)
Многошаговые сценарии (11109) в форме 🔴 открытый вопрос №4 — ждёт Alex
Энкодер под новую форму ⏸ не начат
git commit ⏸ не закоммичено, ждёт команды

Артефакты:

  • zont_config/config_local_2026-09-17_17-45-00.yml — актуальный, перегенерирован под новую форму (4405 строк)
  • /tmp/backup-174500.yml — бэкап предыдущей генерации (5376 строк, форма со старым if/then)

⚠️ Питфолл, найденный в этой сессии: config-to-yml.py пишет YAML в stdout, а не в файл. main() не принимает пути вывода (sys.argv = только входной .txt). Первый прогон python3 config-to-yml.py f.txt -o /tmp/x.yml молча проигнорировал -o — скрипт напечатал «Использование: zont_to_yaml.py <config.txt>» и exit 1, а YAML остался старым. Из-за этого первый просмотр блока 9691 показал неисправленную форму и выглядел как «патч не сработал». Правильный вызов: редирект в файл — python3 config-to-yml.py in.txt > out.yml, и всегда проверять exit= и размер целевого файла.

⚠️ Питфолл (продолжение): grep -n "id: 9691" по YAML находит несколько совпадений (объект живёт и в своей секции, и внутри сценария). Номер строки в старом файле (4877) и в новом (3932) различается — индексировать по первому совпадению нельзя, надо смотреть окрестности.