Словарь автоматизаций

Единый контролируемый словарь: канонический термин ↔ wire/код ↔ UI-лейбл ↔ определение. Снимает путаницу «сценарий/автоматизация/расписание» и «условие/сравнение/выражение».

Канон — «автоматизация». «Сценарий» — исторический алиас (код Scenario*, scenarios-worker-db.md — легаси-имена; переименование символов — отдельный follow-up).

Канон (RU)

wire / код

UI-лейбл

Определение

Автоматизация

automation

«Автоматизация»

Сущность: name, triggers, condition_blocks, is_active, schema_version.

Включена / Выключена

is_active

«Включена» (переключатель), «Включена» / «Выключена» (метка), фильтр «Включённые» / «Выключенные»

Состояние автоматизации. Не путать с шагом «Пауза» и с прогоном: выключенная автоматизация не запускается, а идущий прогон обрывает «Прервать».

Прогон

automation_runs

«прогон», «Последний прогон», «Продолжить / Закончить прогон»

Одно исполнение цепочки от срабатывания до конца. «Сценарий» в подписях не используется.

Триггер

trigger.kind = time | device | group_message | task

«Когда:»; в логике группы — вкладки «Запись» / «Чтение» / «Событие устройства»

Что запускает вычисление. Write-path принимает ровно эти четыре (AutomationValidation); manual и снятый group_expose остались кейсами энума ради старых строк журнала и на запись не принимаются. В логике группы триггер — вкладка редактора (ADR 0054): «Запись» и «Чтение» — group_message с direction set/get, «Событие устройства» — device по источнику («Добавить источник»); маппер выводит их из блоков. Список триггеров и «Добавить триггер» (ADR 0053) сняты.

Расписание

триггер kind:"time" (schedule_type, time_mode)

«Когда:» → вкладка «Расписание»

Time-триггер (cron/one_time, fixed/solar). НЕ отдельная сущность.

Предварительный запуск (готовность к времени)

lead_seconds на АВТОМАТИЗАЦИИ

«Нужно время на подготовку»

Пользователь задаёт целевое время T (one_time_at расписания) и длительность подготовки у самой автоматизации; запуск = clamp(now, T − lead_seconds) (менее чем за lead → немедленно). Наследуют все её разовые расписания с фиксированным временем, включая добавленные из окна автоматизации; cron/солнечные игнорируют — у повторяющегося расписания опережение задаётся его собственным временем. Для процессов с прогревом (баня, тёплый пол).

Событие устройства

триггер kind:"device"

«Когда:» → вкладка «Событие»

Триггер по MQTT-сообщению устройства.

Блок условия

элемент condition_blocks[]

«Если → Тогда»

Пара {condition, then_actions}. Исполняется первый истинный. У расписания блок ровно один и condition: null; развилка — шаг «Ветвление» (branch).

Условие

condition (JSON-AST, null = всегда истина)

«Если»

Булева формула. Ранее — строка if_expression.

Источник условия

событие: свойство без адреса; дождавшееся: {"var": "<device_id>.путь"} (v38); адрес: {var, device_id} (v22)

селектор перед полем свойства: «<устройство> — в момент срабатывания» / «— после ожидания»

Чьё свойство сравнивает условие. Обычная автоматизация (без владельца) читает событие своего триггера и — только в условии ветвления — статус, которого ДОЖДАЛОСЬ «Ожидание» выше (таймаут — «неизвестно»). Адрес «любого прибора» — только у логики группы и её задачи. Селектор показывается, только когда есть выбор.

Поле «текст + список»

TokenValueField (только UI; провод не меняется)

иконка списка в поле

Одно поле на все источники значения: набранное — значение (слева в условии — имя свойства), выбранное из списка — сырой токен {{prop:…}} / {{arg:Подпись}} / {{expose:…}} / {{now:…}}. Переключателя источника нет — вид выводится из текста. Параметр в поле — подписью, на провод уходит ключ; {{now:…}} — синтаксис только интерфейса (на проводе {now, tz}).

Действие

then_actions[].type = pause | device_command | message | wait_until | set_group_expose | control | branch | wait_join

«Тогда»

Что выполнить. apply_default и reply сняты в v39 (422), остались кейсами энума ради старых прогонов.

Название шага

then_actions[].alias (и blocks[].alias у ветви)

«Название»

Необязательное имя шага вместо его номера. Показывается: главной подписью в строке шага (вместо технической сводки, но рядом с маркерами поведения), третьим сегментом в окне идущего прогона («шаг 2 из 7 · Насыщение»), строкой «Сейчас: …» у идущего прогона в истории и чипом «Выполняется · …» в списке автоматизаций. У ветви заменяет служебную подпись «Ветка N»/«Иначе». Пустое значение удаляет ключ; плейсхолдеры внутри не подставляются; на хаб не уезжает, а у хабовых прогонов считается из определения в узком коридоре.

Описание

description у автоматизации, шага, регистра группы и параметра

«Описание», значок (i)

Необязательное пояснение автора «почему сделано так». У автоматизации и регистра — своя колонка, у шага — ключ в then_actions[], у параметра — поле его определения. Показывается подсказкой под полем либо значком (i) там, где поля нет. У ветви описания нет.

Ожидание

действие type:"wait_until"

«Ожидание»

Блокирует run, пока condition по свойству целевого устройства (device_id) не станет истинным ЛИБО не истечёт таймаут (timeout_seconds — секунды, приоритетнее; либо timeout_minutes). Условие можно не задавать: тогда прогон продолжится, как только устройство пришлёт любой новый статус — этот статус доступен следующим шагам ({{prop:<device_id>.*}}). send_get (best-effort) провоцирует свежую публикацию статуса. Секундный таймаут и ожидание «любого статуса» требуют schema_version=7. Целевое устройство выбирается каскадом Помещение → Устройство; группы в списке нет — у неё нет своего MQTT-адреса, и ожидание на ней досидело бы до таймаута. С v19 в обоих режимах засчитывается только статус, полученный после входа в шаг; опция «Принимать последний полученный статус» (last_status_max_age_seconds, стампит schema_version=19) явно допускает и уже полученный, если он не старше заданного окна, — редактор предлагает её устройствам без обратной связи. NB: не путать с location_local_runners.last_status — это хартбит хаба, к окну свежести отношения не имеет.

Параллельное ожидание

wait_until.async: true; шаг type:"wait_join" (device_ids, mode = all | any)

«Не задерживать цепочку»; «Дождаться» («Кого дождаться»: «Все» / «Любое»)

Модель Promise (v40, ADR 0055): ожидание стартует и отпускает цепочку, «Дождаться» собирает исходы как Promise.all / Promise.any. Без сбора цепочка ждёт ожидание на первом шаге, читающем данные его устройства, иначе — перед концом прогона. Ожидание называется своим устройством: второе ожидание того же устройства до закрытия первого — 422. См. Параллельное ожидание (async и wait_join, v40).

Регистр (exposes)

set_group_expose (expose_kind, expose_name); device_expose_states (expose_kind / expose_name / value / origin / published / externally_writable)

«Регистр»

Именованное значение состояния устройства — аналог exposes в zigbee2mqtt (state, brightness…). Адресуется ПАРОЙ (вид, имя): умение и датчик с одним именем — два регистра. Регистр объявляется заранее (ADR 0045): умение и датчик — в редакторе устройства, внутренний регистр и параметр — в разделе «Регистры» логики; запись в незнакомое имя — 422 на сохранении. Входящее сообщение регистров не заводит. Пишется действием set_group_expose (value; desired_value при этом гасится), читается как сигнал условия (value / state_gen). Требует schema_version=3; запись датчика (expose_kind: property) — schema_version=33.

Происхождение регистра

device_expose_states.origin = declared | virtual | parameter

Раздел «Регистры» редактора логики показывает только объявленные автором строки; происхождение не выбирается — его задаёт ступень доступа (две нижние — состояние прибора, две верхние — настройка). Умения и датчики — в редакторе устройства

Умение и датчик объявлены через справочник в редакторе устройства: типизированы, валидируются по метаданным, видны в панели и Алисе. Датчик — показание, которое пишет само устройство (шагом с видом property); на проводе лежит под ключом property:<имя>. Внутренний регистр объявляет автор: имя, тип (словарным именем), значение; пишут его логика прибора и автор полем «Текущее значение», снаружи — никогда; здесь живут фаза сеанса и счётчик кругов. Параметр объявляет автор — как параметр автоматизации: тип, подпись, умолчание, ограничения; его пишут снаружи. В arguments автоматизаций устройства ({{arg:имя}}) попадают только параметры ступени «спрашивать при запуске» (ADR 0043 → 0045). Смена ступени через границу переобъявляет регистр: у настройки умолчание и голос, у состояния — живое значение (ADR 0052).

Доступ к регистру снаружи

access = internal | shown | settable | asked (колонки published / externally_writable / ask_on_start)

«Только внутри устройства» / «Показывать в статусе» / «Принимает команды» / «Спрашивать при запуске»

Одна монотонная ШКАЛА (ADR 0045): «пишется ⇒ виден», «спрашивается ⇒ пишется». Умение — settable, датчик — shown, оба фиксированно; internal | shown делают регистр внутренним, settable | asked — параметром, ступень правится вместе с происхождением (ADR 0052). Граница публикации действует на ПРОВОД (шина, панель, Алиса), а не на движок: своя логика и задачи видят все регистры — иначе условие по скрытому регистру читало бы «неизвестно», а у задач это ложь. Входящее сообщение меняет в состоянии условий только ключи ступени settable и выше.

Запись (логика группы)

condition_blocks[].direction = "set"; schema_version=39

вкладка «Запись», «Описать запись»

Блоки «Если / Тогда» над ВСЕЙ командой группе, работает первый подошедший; регистр выбирается условием («свойство есть в сообщении»). Не подошёл ни один — проверенная команда пишется сразу (умолчание). Подошёл — эхо после шагов: при completed дописываются ключи, которых шаги не записали сами; прогон не доработал — ничего. Новая команда отменяет идущий прогон (end_reason: superseded, «Прервано: заменён новой командой»). Обработчик регистра (expose_name блока, v27) снят в v39 — 422 (ADR 0054).

Чтение (логика группы)

condition_blocks[].direction = "get"; schema_version=39

вкладка «Чтение», «Описать чтение», «Перед ответом:»

Ровно один блок без условия (иначе 422): шаги подготовки, затем группа сама отвечает состоянием при любом исходе. Логика занята — ответ сразу. Query Алисы «Чтение» не запускает.

Событие устройства

condition_blocks[].direction = "event", source_device_id; schema_version=36

«Событие устройства»

Ветка логики группы, отвечающая на статус НАЗВАННОГО устройства (источника), а не на обращение к самой группе: так группа узнаёт, что клавишу нажали на стене, даже когда выключена. Исполняется сразу, без прогона; шаги — только запись регистров и команда не-группе; блок не командует своим источником.

Выдержка записи

then_actions[].stable_seconds; schema_version=37

«Записать, если держится»

Запись регистра в блоке «Событие устройства», которая идёт, только если статус устройства продержался указанное время. Так клавиши на стене меняют запомненный режим, а промежуточное «горит одна клавиша» при выключении — нет.

Исход ожидания

then_actions[].on_timeout и timeout_actions у wait_until

«Ожидание → если не дождались»

Что делает шаг, если статуса так и не было: continue (дальше по цепочке — дефолт и поведение до v23) либо cancel (прогон кончается, detail начинается с wait_timed_out:). Различить «дождались» и «истёк» иначе нечем: шаг завершается одинаково в обоих случаях. Словарь общий с ждущим сообщением. У фоновой задачи cancel завершает сеанс, то есть уводит в on_stop. Требует schema_version=23.

В редакторе это ОДИН селектор из четырёх пунктов: «Продолжить прогон», «Закончить прогон» и те же два с приставкой «Выполнить шаги и…». Второе слагаемое пункта — timeout_actions: шаги обработчика (v32), которые играются вместе с исходом: при «продолжить» — сразу, при «закончить» у фоновой задачи — после ветки гашения, чтобы записанная ими причина не затёрлась. Такой прогон в истории — «Таймаут ожидания». Пункт со шагами показывает обычный список шагов редактора с суженным набором типов — команда, регистр устройства, уведомление.

Ветвление внутри цепочки

then_actions[].type = "branch"

«Ветвление» (шаг цепочки)

Развилка, которая проверяется в тот момент, когда цепочка до неё ДОШЛА, — этим она и отличается от блоков «Если» самой автоматизации: те выбраны один раз, при срабатывании. После получасовой паузы или ожидания обстановка уже другая. Тело — те же блоки: работает первый подошедший, блок без условия это «иначе». Не подошёл ни один — шаг ничего не делает. Пустая ветка законна и означает «в этом случае — ничего»: ветвление последним шагом с пустой веткой и есть обрыв цепочки по условию, который вернули вместо снятого шага «Завершение». Внутри нельзя ветвление (глубина одна), регулятор и вопрос; в условии ветки нельзя операторы перехода. В журнале прогона цепочка видна развёрнутой. Требует schema_version=23.

Фоновая задача группы

автоматизация с group_role = 'task' + automation_task_triggers

«Фоновые задачи» (карточка группы)

Цикл: блоки означают «Пока верно», и пока держится хоть одно условие, задача крутит круги. Перестали держаться все — сеанс кончается веткой остановки и гасит выключатель своей группы. Заменила снятый примитив «циклический переключатель»: тот умел «одно устройство, два состояния, круг», задача — произвольную циклограмму, регулятор и осмысленное окончание. Окно исполнения одно на все задачи — минута, от начала круга: настроек темпа у входа нет, более редкий цикл держит пауза внутри цепочки. Ветка остановки — on_stop (только команды). Требует schema_version=29.

Задача-взводчик

фоновая задача, пишущая выключатель ДРУГОЙ группы

обычные блоки «Если → Тогда» в окне фоновой задачи

Так выражается «работай, пока держится условие», когда нагрузка должна остаться переиспользуемой: выключатель самого взводчика значит «я разрешаю», а его блоки включают и выключают выключатель РАБОЧЕЙ группы. Мёртвая зона пишется блоком с условием и ПУСТЫМ списком действий («держись, ничего не делай»); показания нет — не держится ни одно условие, и сеанс кончается сам. Заменил снятое поле triggers[].while («Пока выполняется», ADR 0031 → ADR 0037), а с волной 29 условие продолжения несут и сами блоки задачи. Форма со взводчиком вдобавок делает рабочую группу переиспользуемой — она видна в панели своим выключателем и уезжает в Алису.

Исход отказа шага

then_actions[].on_failure

«Если не вышло» (у шага)

Что делать с СЕАНСОМ, когда этот шаг не удался: команда не ушла, регистр не записался, длина паузы не взялась из пустого источника. Закончить и погасить (умолчание) — ветка остановки отрабатывает, выключатель гаснет, прогон закрывается completed; сломанной автоматизация не помечается. Идти дальше — со следующего шага; круг при этом всё равно считается неудачным для предохранителя, иначе задача с навсегда сломанной публикацией крутилась бы вечно, выглядя здоровой. Цена отказа у шагов разная — «не включилась печь» и «не зажёгся свет» стоят разного, — и прежний общий на всю задачу исход (triggers[].on_failure, v28) такой разницы выразить не мог; он снят. Требует schema_version=29.

Момент сверки условия

condition_blocks[].check

«Проверять: перед кругом / после первого круга»

У блока задачи. После первого круга — блок держится, пока сам ни разу не отработал: свой круг он получит обязательно, даже если первый достался соседу. Так пишется «в конце обязательно продуть». Долг принадлежит блоку, а не сеансу. Дальше блок сверяется как обычный, поэтому без условия он держится вечно — такое сочетание отвергается (422); «однажды в начале» пишется условием, которое сам круг и опровергает. Требует schema_version=29.

Регулятор

then_actions[].type = "control"

«Регулятор»

Считает выход по измерению и уставке (П/ПИ/ПИД — по тому, какие времена заданы) и кладёт его в переменную прогона output.var. Настройка размерная: полоса band в единицах показания — отклонение, при котором выход выходит на потолок целиком, — плюс времена ti_seconds и td_seconds; пустое время означает, что члена нет. Только внутри фоновой задачи. Мёртвая зона обязательна, сглаживание производной обязательно при заданном td_seconds, а такт без нового измерения ничего не считает и не пишет. Устаревшее измерение → публикуется fail_safe. Требует schema_version=35.

Зазор (двухпозиционное поддержание)

Разность порогов в условиях блоков задачи

«Зазор»

Насколько показание должно уйти за цель, чтобы нагрузка переключилась. Отдельного поля в грамматике у зазора НЕТ: заготовка превращает его в два порога — уставка ∓ зазор/2 — и кладёт их в условия двух блоков, а третий блок (коридор) остаётся с пустым списком действий. Внутри зазора не подходит ни один из первых двух блоков, поэтому нагрузка держит своё состояние; зазор и ЕСТЬ гистерезис. Не путать с полосой регулятора: полоса задаёт, как быстро растёт ПЛАВНЫЙ выход, зазор — когда щёлкает двухпозиционный.

Длительность из значения (ШИМ)

pause.duration_from

«Пауза → Переменная»

Длина паузы берётся из переменной прогона (выход регулятора) или регистра группы — так выход становится скважностью медленного ШИМ. Вырожденный сегмент (длина меньше секунды) пропускается целиком вместе с открывающей его командой; порог min_seconds, которым это задавалось раньше, снят. Пустой источник значит «сегмента нет» — «мощности нет, не включать», отказом шага это не считается.

Длина паузы прямо в секундах

duration_from с одинаковыми диапазонами

«Пауза → Регистр, как есть»

Когда в источнике лежат секунды, а не проценты, диапазоны делают одинаковыми: in=[0,43200] scale=[0,43200]. Потолок 43200 — потолок самой паузы, обрезать такому отображению нечего. Так задаётся длина, которую называет человек («сколько парить»). Отдельный режим mode = "seconds" для этого был и снят: у него были обратные запреты и обратное поведение на пустом источнике, а в редакторе его было не выбрать.

Коридор поддержания

device-триггер + два condition_blocks (пороги </>)

«Если датчик < низ → ВКЛ» / «> верх → ВЫКЛ»

Не отдельный примитив, а композиция: одна device-триггерная автоматизация с двумя блоками (датчик < low → актуатор ON, датчик > high → OFF; между — держит, гистерезис = зазор). Гейтится неявно по on_off-регистру owner-группы (фаерит, пока группа ON). Прежний start_reading_reconciler (schema_version=5) декоммиссирован. Fail-safe по пропаже датчика нет.

Канал сообщения

channel = email | push | tg | max

—

Транспорт действия message.

Узел (условия)

AST-узел

—

группа | сравнение | именованный оператор | exists.

Группа условий

op = and | or (+``not``)

«Группа условий», И / ИЛИ

Логическое объединение узлов.

Оператор

op (символьный =,``<… | именованный ``crosses_up,``changed_to``…)

код (display SCREAMING)

Сравнение/переход. Не переводится.

Функция

fn = round | bool | upper | lower

код (display SCREAMING)

Обёртка операнда-свойства.

Операнд

{var} | скаляр | {var, fn} | {arg}

—

Левая/правая часть сравнения.

Свойство

{"var":"temperature"}

имя свойства

Ссылка на сигнал устройства (dotted-path).

Константа

JSON 24 / "ON"

значение

Число (typed) или строка.

Параметр

определение automation.arguments[]; ссылка {"arg":"name"} / {{arg:name}}

«Параметр»

Именованное типизированное значение, которым пользователь влияет на автоматизацию, не правя её логику. Значения спрашиваются при ЗАПУСКЕ (automation.argument_values) и при добавлении запуска по расписанию (timeTrigger.arguments). Типы number/string/boolean/enum/datetime. В интерфейсе у параметра одно имя — название (label); ключ ссылки (name) редактор выдаёт сам и не показывает, поэтому переименование параметра ссылки не ломает.

Вариант списка

constraints.options[] = {"value", "label"?}

«Подпись» · «Значение»

Вариант параметра «Список» (enum) и регистра-перечня. Человек выбирает по подписи, в команды, условия и {{arg:…}} уходит значение. Без подписи показывается значение.

Обязательный параметр

automation.arguments[].required

галка «Обязательный», звёздочка у поля

Значение обязано быть заполнено при запуске (иначе сервер ответит 422). Автоматизация, у обязательного параметра которой нет ни значения, ни начального значения, выключается — значения спросят при включении.

Предустановленное значение

automation.arguments[].preset

«Начальное значение»

Чем предзаполняется диалог ввода и что подставится, если введённых значений нет. Необязательно: необязательный параметр можно оставить и без него — тогда значения при исполнении нет, и в местах вставки подставится пустое, а в сравнениях параметр считается пустой строкой; шаг, длительность которого он задаёт, пропускается. Прежнее default декоммишено (присланное → 422).

Разовый запуск

timeTrigger со schedule_type=one_time (+ свои arguments)

«Разовый запуск» (диалог «Расписания»)

Добавляется/взводится из списка автоматизаций, вне редактора; спрашивает время и значения параметров. Отработавший гаснет (is_active=false) и взводится заново новым временем.

Продолжительность

number + constraints.format=duration (max 43200)

«Продолжительность» (диалог часы/минуты)

Мета-формат параметра: целое число секунд, потолок 12 ч; ввод в UI через часы/минуты. Не отдельный тип — number с маркером формата.

Плейсхолдер свойства

{{prop:path}}

чип свойства

Текущее значение свойства устройства в строке действия (резолв при исполнении).

Порог / Гистерезис

threshold / hysteresis

—

Параметры crosses_* (детектор фронта).

wire / display

—

—

wire = хранимый JSON (lowercase); display = отображение (SCREAMING/инфикс).

Версия контракта

schema_version

—

Мажор доменного SemVer (см. Версионирование и расширяемость (SemVer)).

Действие

шаг device_command (с device_id или с голым topic)

«Действие» + подтип

Один пункт списка с двумя подтипами. «Устройство» — команда устройству из справочника (адрес считает сервер). «Публикация в топик» — свой MQTT-адрес внутри локации и свой payload; адрес пишется как есть, префикс дома брокер добавляет сам, шаблоны + и # недопустимы — публикуют в конкретный топик, а не в маску.

Продление шага

поле шага retrigger = skip | extend_while (у pause и wait_until)

«Продлевать при повторном срабатывании»

Что делает срабатывание триггера, пока прогон спит на ЭТОМ шаге: отбрасывается (по умолчанию) либо перевзводит его дедлайн на полную длительность. Продлевает только статус, проходящий «Если» того блока, из которого растёт прогон. Этим выражается «N минут после ПОСЛЕДНЕГО движения»: «движения нет» паузу не продлит. Настройка живёт в диалоге шага, а не у автоматизации: перевзвести можно только дедлайн, а он принадлежит конкретному ожиданию.

Отмена прогона

then_actions[].cancel_on = {device_id | topic, condition?, mode}, mode = finish | abort — поле ЖДУЩЕГО шага (пауза, ожидание, ждущее сообщение)

«Отменять по событию» в самом шаге

Событие прерывает идущий прогон: finish снимает ожидание и доигрывает остальные действия («движение прекратилось — выключить сразу»), abort прерывает прогон целиком («протечку устранили — перестать звонить»). Действует, только пока прогон ждёт. Источник события выбирается вкладкой в диалоге: «Устройство» — то, что уже заведено в локации, выбирается каскадом Помещение → Устройство (смена помещения — фильтр списка, уже выбранное устройство и собранное условие она не сбрасывает); «Сообщение в топик» — адрес, который вы пишете сами (то, что стоит за чужим мостом, свой контроллер), хвостом без префикса локации. У адреса-топика условие необязательно: без него шаг отменит любое сообщение в этот адрес, включая вложенные уровни. Такой адрес — ваш: переименование устройства его не поправит, а автоматизация с адресом вне сети Zigbee этого хаба на хаб не переносится (сообщение видит только облако). Правило проверяется на каждом сообщении устройства, ещё до того как прогон найден, — поэтому сравнивать не с чем: ни с предыдущим значением (CHANGED_TO, CROSSES_*), ни со значениями параметров запуска.

Режим сообщения

mode = alert | confirm | prompt

«Что сделать»: «Сообщить» / «Запросить подтверждение» / «Запросить значения»

Что шаг «Сообщение» делает с человеком. «Сообщить» — односторонняя телеграмма: кнопок нет, автоматизация не ждёт. Два других режима ЖДУТ ответа: подтверждение спрашивает «да/нет», запрос значений добавляет к нему поля — например, на сколько минут включить. Пока ответа нет, автоматизация занята и повторно не срабатывает, поэтому ждать можно не дольше часа.

Подписи кнопок

confirm_label / decline_label

«Кнопка согласия» / «Кнопка отказа»

Что будет написано на кнопках у жильца. Пустые — подставится текст по умолчанию, причём у кнопки отказа он зависит от того, прерывает отказ прогон или нет: «Прервать автоматизацию» на кнопке, которая ничего не прерывает, вводила бы в заблуждение.

Таймаут вопроса

timeout_seconds + on_timeout = continue | cancel

«Ждать ответа, минут» + «Если ответа не будет»

Сколько ждать и что считать молчанием: продолжить прогон (параметры сохраняют прежние значения) или прервать его. Значения по умолчанию нет намеренно — «не дозвонились, значит не открываем ворота» и «не дозвонились, значит греем как обычно» одинаково законны.

Отказ на вопросе

on_decline = cancel | continue

«Если ответят отказом»

Что делает вторая кнопка: прерывает прогон целиком или лишь пропускает этот шаг, оставляя остальные действия. Значения по умолчанию нет намеренно — «спросил и всё равно сделал» и «спросил и не сделал» одинаково законны.

Ответ на вопрос

ссылка /p/{token}

подписи кнопок задаёт автор

Страница из текста вопроса. Токен в ссылке и есть право ответить — авторизации страница не требует, поэтому ссылку не пересылают: тот, у кого она есть, может подтвердить действие или прервать прогон. Отвечает первый: повторный переход ничего не переигрывает.

Место исполнения

execution_place

«Исполнение»: «Перенести на хаб» / «Вернуть в облако»

Где исполняется автоматизация: в облаке или на локальном сервере (хабе). Ровно одно место в любой момент. Локальная работает без интернета; расписания на хабе не навёрстывают пропущенное время простоя (выключенный хаб = пропуск срабатывания, облако не подстраховывает). Перенос в обе стороны — Без интернета, протокол — Локальное исполнение.

Адрес на шине

friendly_name → automations/{kind}/{name}

— (в редакторе не выводится; у логики группы — «Адрес на шине»)

Имя, по которому к автоматизации можно обратиться из MQTT. Выдаётся сервером как hex идентификатора и не выводится из названия: переименование автоматизации не рвёт чужую подписку. {kind} — tasks | logic | rules; отдельный сегмент существует ради подписки «только фоновые задачи» (automations/tasks/#).

Уровень телеметрии

telemetry_level = off | state | events | steps

«Что рассказывать на шине»

Сколько автоматизация сообщает о себе внешним подписчикам, накопительно. Уровень у КАЖДОЙ автоматизации, а не у дома: шумит конкретная задача, глушить нужно её. Ответ на прямой запрос состояния (/get) уровню не подчиняется — иначе отказ был бы неотличим от потери.

См. также: спецификация языка.