ГлавнаяАкадемияСценарии умного дома: режимы, состояния, приоритеты → Практика: Создание базового Flow для управления состоянием (инициализация)

Практика: Создание базового Flow для управления состоянием (инициализация)

Урок 5 · Сценарии умного дома: режимы, состояния, приоритеты · 30 мин · theory

Введение: Цели и задачи урока

> 🔗 Связанный материал: Этот урок является практическим применением концепций, изложенных в уроках по конечным автоматам (COURSE-07-M01-L01) и архитектуре сценарного слоя (COURSE-07-M01-L02). Убедитесь, что вы усвоили материал о конечных автоматах и архитектуре, прежде чем продолжить.

В предыдущих уроках мы заложили теоретический фундамент для создания продвинутых и надежных систем автоматизации. Мы определили, что в основе любой сложной логики лежит сценарный слой, который оперирует не отдельными датчиками и реле, а целостными понятиями — режимами и состояниями. Для управления этими состояниями мы выбрали модель конечного автомата (State Machine), где система может находиться только в одном из предопределенных состояний и переходить между ними под воздействием внешних или внутренних событий.

Однако любая сложная система должна с чего-то начинаться. Что происходит в момент включения контроллера или перезагрузки службы Node-RED? В какое состояние переходит дом? Если этот начальный момент не определен, вся последующая логика становится хаотичной и непредсказуемой. Система может "вспомнить" состояние до перезагрузки, а может и нет. Сценарии, запущенные в неправильном порядке, могут конфликтовать друг с другом.

Цель этого практического урока — создать краеугольный камень нашей архитектуры: Flow инициализации глобального состояния. Этот поток будет выполнять одну, но критически важную задачу: при каждом старте системы приводить ее в известное, безопасное и предсказуемое состояние по умолчанию.

📋 Ключевые понятия:

Мы шаг за шагом построим Flow, который будет автоматически запускаться при старте, формировать структурированный объект состояния, сохранять его в глобальном контексте и транслировать всем остальным компонентам системы через MQTT. Этот, на первый взгляд, простой механизм является фундаментом, на котором будут строиться все последующие сложные сценарии, обеспечивая их стабильность и предсказуемость.

---

Секция 1: Точка входа: Запуск Flow при старте системы

Первый шаг в создании нашего инициализационного потока — определить, как он будет запускаться. Нам нужен механизм, который гарантированно сработает один раз при каждом запуске или развертывании (deploy) Node-RED. Для этой цели идеально подходит узел `inject`.

Использование узла `inject`

Узел `inject` является одним из самых базовых, но в то же время мощных инструментов в палитре Node-RED. Его основная функция — инициировать поток, отправляя в него сообщение. Он может делать это по нажатию кнопки, по расписанию или, что нам и нужно, один раз при старте.

Пошаговая настройка:
  • Перетащите узел `inject` на рабочую область новой вкладки, которую можно назвать "SYSTEM: State Machine" или "СИСТЕМА: Управление состоянием".
  • Дважды щелкните по узлу, чтобы открыть его настройки.
  • В поле Payload оставьте значение по умолчанию `timestamp` (текущее время). Содержимое этого первого сообщения не так важно, как сам факт его отправки.
  • В поле Topic задайте осмысленное значение, которое поможет в отладке. Это первое событие в жизни нашей системы после запуска, поэтому оно должно быть идентифицируемым.
  •     system/init/start

  • Найдите и активируйте галочку Inject once after ... second(s), then. Этот параметр — ключ к надежному запуску.
  • Установите задержку в 2-5 секунд.
  • > 💡 Подсказка: Установка задержки в узле `inject` — критически важный шаг. Это предотвращает "гонку состояний" (race condition), когда ваш Flow пытается обратиться к сервисам (например, к MQTT-брокеру или базе данных MySQL), которые еще не успели полностью запуститься после старта контроллера. Задержка в несколько секунд дает системе время "прийти в себя" и подготовить все необходимые службы к работе.

  • Убедитесь, что опция `repeat` установлена в `none`. Нам нужен только один запуск.
  • В поле Name дайте узлу понятное имя, например, "Запуск при старте".
  • Вот как должны выглядеть финальные настройки узла:

    | Параметр | Значение | Обоснование |

    | ------------------------------------------ | ----------------------- | ------------------------------------------------------------------------ |

    | `Name` | Запуск при старте | Четко описывает функцию узла. |

    | `Payload` | `timestamp` | Стандартное значение, достаточное для инициации. |

    | `Topic` | `system/init/start` | Позволяет отслеживать событие инициализации в логах и отладчике. |

    | `Inject once after [...] seconds, then` | `checked`, `2` seconds | Гарантирует, что все системные сервисы Node-RED успеют запуститься. |

    | `Repeat` | `none` | Инициализация должна произойти только один раз при старте. |

    Почему важна единая точка входа?

    Использование одного-единственного узла `inject` в качестве стартовой точки для всей логики инициализации является фундаментально правильным архитектурным решением. Это:

    После настройки этот узел станет триггером, запускающим всю цепочку создания и публикации состояния по умолчанию.

    ---

    Секция 2: Формирование объекта состояния в 'change'

    екция 2: Формирование объекта состояния в 'change'

    После того как узел `inject` отправил стартовое сообщение, наша задача — создать и заполнить главный объект, который будет хранить все состояния системы. Этот объект будет жить в глобальном контексте Node-RED

    Секция 3: Публикация состояния в MQTT для всей системы

    екция 3: Публикация состояния в MQTT для всей системы

    Создание базовой структуры объекта состояния в `global.HI_STATE` (которую мы подробно разобрали в [уроке M01-L05](../M01-L05/

    Секция 4: Верификация и отладка

    екция 4: Верификация и отладка

    Создать Flow — это половина дела. Вторая, не менее важная половина — убедиться, что он работает именно так, как задумано. Процесс верификации должен быть многоуров

    Резюме и следующие шаги

    езюме и следующие шаги

  • С помощью узла `change` мы сформировали и сохранили в глобальный контекст структурированный объект `global.HI_STATE`, который