ГлавнаяАкадемияСценарии умного дома: режимы, состояния, приоритеты → Режим 'Гость': ограниченные сценарии, упрощенное управление

Режим 'Гость': ограниченные сценарии, упрощенное управление

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

Введение в режим 'Гость': цели и ключевые принципы

ведение в режим 'Гость': цели и ключевые принципы

Режим 'Гость' — это предопределенное состояние системы умного дома, предназначенное для временных пользователей (гостей, арендаторов, обслуживающего персонала). Его главная задача

Архитектура режима 'Гость' в среде Node-RED

Для корректной и надежной реализации гостевого режима на платформе HI необходимо спроектировать четкую архитектуру, которая будет централизованно управлять этим состоянием и распространять его по всем подсистемам. Основой этой архитектуры служат контекстные переменные Node-RED и протокол MQTT.

Использование глобального контекста для хранения состояния

Состояние режима 'Гость' является глобальным для всей системы автоматизации. Это означает, что любой поток (flow), будь то управление светом, климатом или мультимедиа, должен "знать" о том, активен ли в данный момент гостевой режим. Идеальным инструментом для этого является глобальный контекст (global context) Node-RED.

Для активации режима используется команда:

global.set('guest_mode', true);

Для деактивации:

global.set('guest_mode', false);

> 💡 Подсказка: Чтобы состояние режима сохранялось между перезагрузками контроллера (например, после сбоя питания), необходимо настроить персистентное хранилище контекста. В настройках Node-RED (`settings.js` на контроллере HI) вы можете указать хранение контекста в файловой системе, что является обязательным требованием для надежных систем.

Роль MQTT в синхронизации состояния

Хотя глобальный контекст отлично работает в рамках одного экземпляра Node-RED, для полной синхронизации (например, с панелями визуализации HMI, мобильными приложениями или другими контроллерами в сети) необходимо использовать MQTT как единую шину состояний.

При каждом изменении состояния режима 'Гость' система должна публиковать это состояние в специальный MQTT-топик. Важно использовать флаг `retained` (сохраняемый). Это гарантирует, что любое устройство, подписавшееся на этот топик, немедленно получит последнее актуальное состояние, даже если оно было опубликовано давно.

Стандартный топик для управления режимами: `hi/system/modes/guest`

Пример потока для синхронизации глобальной переменной и MQTT:

  • Поток, изменяющий режим, вызывает `global.set('guest_mode', true)`.
  • Сразу после этого он формирует сообщение `msg.payload = true` и `msg.retain = true`.
  • Это сообщение публикуется в топик `hi/system/modes/guest` через узел `mqtt out`.
  • На всех контроллерах существует поток, который подписан на `hi/system/modes/guest` через узел `mqtt in`. При получении сообщения он, в свою очередь, обновляет свою локальную глобальную переменную `global.set('guest_mode', msg.payload)`, обеспечивая полную синхронизацию.
  • Проектирование центрального потока-'маршрутизатора'

    Ключевой элемент архитектуры — создание центрального потока, который мы назовем «Шлюз Команд» (Command Gateway). Этот поток становится единой точкой входа для всех команд, поступающих от пользователя, будь то нажатие кнопки на настенной панели, команда из мобильного приложения или голосового ассистента.

    Архитектура шлюза:

  • Вход: Узел `mqtt in`, подписанный на все топики команд с использованием wildcard, например, `hi/devices/+/+/set`.
  • Проверка режима: Первый узел `switch` проверяет состояние `global.get('guest_mode')`.
  • Фильтрация: Если режим 'Гость' активен, команда направляется на дополнительную ветку фильтрации, которая пропускает только разрешенные («белый список») команды.
  • Исполнение: Если команда прошла проверку, она отправляется дальше на исполнение в соответствующие потоки управления устройствами (DALI, Modbus, Relay).
  • Такой подход позволяет изолировать логику контроля доступа в одном месте, что значительно упрощает дальнейшую поддержку и модификацию системы.

    Стандартизация контракта сообщения

    Для управления режимами, как и для управления устройствами, необходимо придерживаться контракта сообщений.

    Команда на изменение режима: Сообщение о состоянии режима (с флагом retained):

    Следование этим простым правилам обеспечивает предсказуемость и совместимость всех компонентов системы.

    ---

    Практическая реализация: Фильтрация команд на базе узла switch

    Рассмотрим создание «Шлюза Команд», который будет фильтровать все входящие команды управления устройствами в зависимости от состояния режима 'Гость'. Этот поток является основой безопасности и предотвращения нежелательных действий.

    > 💡 Подсказка: Для отладки логики фильтрации активно используйте узел `debug`. Настройте его на вывод полного объекта `msg` на каждом этапе проверки (до и после узлов `switch`), чтобы видеть, какие команды блокируются, а какие проходят дальше.

    Задача: Создать поток, который получает все команды управления, проверяет, активен ли режим 'Гость', и если да — пропускает только команды управления светом и розетками, блокируя все остальные (например, управление климатом или шторами). ASCII-схема потока:
                                            +----------------------------------+
    

    +------>| switch: Check msg.topic |

    | | (Whitelist for Guest Mode) |---+-----> [link out: To Device Control] (Разрешено)

    | +----------------------------------+ |

    | +-----> [debug: Blocked Command] (Заблокировано)

    [mqtt in: hi/devices/+/+/set] --+------>+----------------------------------+

    | | switch: global.get('guest_mode') |

    | | 1. if true (Guest Mode ON) |

    | | 2. if false (Guest Mode OFF) |

    | +----------------------------------+

    |

    +----------------------------------------------> [link out: To Device Control] (Стандартный режим, все разрешено)

    Пошаговая инструкция по созданию потока:
  • Создайте входную точку:
  • * Добавьте на поле узел `mqtt in`.

    * Настройте его на подключение к вашему MQTT-брокеру.

    * В поле `Topic` укажите `hi/devices/+/+/set`. Это позволит узлу ловить абсолютно все команды, предназначенные для устройств.

    * `QoS`: `1` или `2` для гарантированной доставки команд.

  • Создайте главный маршрутизатор режимов:
  • * Добавьте узел `switch` и соедините его с выходом узла `mqtt in`.

    * В настройках узла `switch` установите `Property` на `global.guest_mode` (тип `global`).

    * Добавьте два правила:

    1. `is true` -> это будет выход 1 (режим 'Гость' активен).

    2. `is false` -> это будет выход 2 (стандартный режим).

  • Настройте логику для стандартного режима:
  • * Соедините второй выход узла `switch` с узлом `link out`. Назовите его, например, «Исполнение команд». Этот узел будет передавать все сообщения без изменений в основные потоки управления.

  • Создайте фильтр для гостевого режима:
  • * Добавьте еще один узел `switch` и соедините его с первым выходом главного маршрутизатора. Это будет наш фильтр "белого списка".

    * В настройках этого узла установите `Property` на `msg.topic`.

    * Добавьте правила, которые определяют разрешенные команды. Используйте оператор `matches regex` (соответствует регулярному выражению) для гибкости:

    `matches regex`: `^hi/devices/light/.` (разрешает все команды для устройств типа `light`).

    `matches regex`: `^hi/devices/socket/.` (разрешает все команды для розеток).

    `matches regex`: `^hi/devices/media/.` (разрешает управление медиа).

    * Важно: внизу окна настроек узла `switch` измените `checking` на `all rules`, а `sending` на `the first matching rule`. Это создаст логику "ИЛИ". Если топик соответствует хотя бы одному правилу, сообщение пройдет на первый выход.

    * Соедините первый выход этого фильтрующего `switch` с тем же узлом `link out` («Исполнение команд»).

    * Соедините второй (otherwise) выход с узлом `debug`. Назовите его «Заблокированная команда». Это позволит вам видеть в отладке все команды, которые были заблокированы фильтром.

    Пример работы фильтра:

    Предположим, в режиме 'Гость' приходит сообщение:

    // msg.topic = "hi/devices/climate/thermostat_guestroom/set"
    

    // msg.payload = { "temperature": 28.0 }

  • Главный `switch` направит его на ветку гостевого режима.
  • Фильтрующий `switch` проверит топик `hi/devices/climate/thermostat_guestroom/set`.
  • Он не совпадет ни с одним из правил (`/light/`, `/socket/`, `/media/`).
  • Сообщение будет отправлено на второй выход и выведено в узел `debug` как заблокированное. Команда до исполнительного механизма (Modbus-термостата) не дойдет.
  • ---

    Упрощенный пользовательский интерфейс (UI) для гостей

    Ограничение команд "под капотом" — это половина задачи. Вторая половина — предоставить гостю такой интерфейс, в котором у него даже не возникнет возможности отправить запрещенную команду. Для этого идеально подходит `node-red-dashboard`.

    > ⚠️ Внимание: Никогда не выносите на гостевой интерфейс прямые элементы управления, позволяющие менять системные параметры, например, IP-адреса устройств, параметры COM-порта или Modbus-регистры. Это может привести к полной неработоспособности сегмента автоматизации и потребует вмешательства инженера.

    Разработка отдельной вкладки в Dashboard

  • В редакторе Node-RED откройте панель `dashboard` справа.
  • Создайте новую вкладку (Tab) и назовите ее, например, "Guest Control".
  • Создайте на этой вкладке несколько групп (Group), например: "Освещение", "Климат", "Медиа".
  • Перетаскивайте на эти группы только самые необходимые виджеты:
  • * Освещение: Несколько узлов `ui_button` или `ui_switch` для включения/выключения предопределенных групп света или световых сцен (например, "Вечер", "Чтение").

    * Климат: Один узел `ui_slider` или `ui_numeric` для управления температурой. Обязательно установите в его настройках `Min` и `Max` на безопасные значения (например, `Min: 20`, `Max: 24`). Это аппаратное ограничение на уровне UI.

    * Медиа: Несколько кнопок `ui_button` для простых действий: "Включить ТВ", "Плей/Пауза", "Громче/Тише".

    Автоматическое переключение на гостевой интерфейс

    Чтобы гость всегда видел только свой упрощенный интерфейс, можно использовать узел `ui_control`. Он позволяет программно управлять самим дашбордом, в том числе принудительно переключать активную вкладку.

    Логика:
  • Создайте поток, который отслеживает изменение состояния режима 'Гость' (подпиской на MQTT-топик `hi/system/modes/guest`).
  • Используйте узел `switch`, чтобы определить, был ли режим включен (`true`) или выключен (`false`).
  • При включении: отправьте на узел `ui_control` сообщение с `msg.payload`, равным имени гостевой вкладки.
  •     // В function-ноде после проверки, что режим включился

    msg.payload = { "tab": "Guest Control" }; // Укажите точное имя или ID вкладки

    return msg;

  • При выключении: аналогично можно вернуть пользователя на основную вкладку "Home".
  • Этот механизм гарантирует, что как только режим 'Гость' активируется (например, владелец нажал кнопку на своей панели), все открытые на объекте дашборды (планшет на стене, телефон гостя) автоматически переключатся на упрощенный интерфейс.

    ---

    Сценарии активации и деактивации режима

    Гибкость умного дома проявляется в разнообразии способов взаимодействия с ним. Режим 'Гость' не является исключением.

    Сценарии активации

  • Ручная активация:
  • * Реализация: Самый простой способ. На главной панели управления владельца (не гостевой!) размещается кнопка `ui_button` с надписью "Активировать режим 'Гость'". Нажатие на нее отправляет `true` в топик `hi/system/modes/guest/set`.

    * Применение: Когда гости уже пришли, и владелец хочет передать им управление.

  • Полуавтоматическая активация:
  • * Реализация:

    * Кодовая панель: Если на входе установлена кодовая панель, подключенная к контроллеру по RS-485, можно запрограммировать специальный гостевой код. Поток, слушающий `serial in` порт, при получении этого кода активирует режим.

    * Гостевая Wi-Fi сеть: Более продвинутый способ. Можно настроить скрипт на контроллере или роутере, который отслеживает подключение нового устройства к гостевой сети Wi-Fi и через MQTT-сообщение активирует режим 'Гость'.

    * Применение: Отели, апартаменты в аренду. Гость получает код доступа и, входя в номер, автоматически активирует нужный режим.

  • Полностью автоматическая активация:
  • * Реализация: Интеграция с внешними системами. Например, система бронирования отеля через API (с помощью узлов `http in/request`) может отправлять на контроллер информацию о заезде/выезде гостя. Или поток может парсить данные из Google Календаря, и если на текущий день запланировано событие "Прием гостей", режим активируется автоматически.

    * Применение: Максимально автоматизированные объекты, где требуется минимизировать ручные операции.

    Сценарии деактивации

    Логика деактивации зеркальна активации:

    Информирование владельца

    Крайне важно, чтобы владелец всегда знал о смене такого важного режима. Это легко реализуется с помощью потока уведомлений.

    Пример потока для Telegram-уведомлений:
  • Узел `mqtt in` подписывается на топик состояния `hi/system/modes/guest`.
  • Узел `function` форматирует сообщение для отправки:
  •     // Node: "Форматировать уведомление для Telegram"

    const isGuestMode = msg.payload === true;

    const statusText = isGuestMode ? "активирован" : "деактивирован";

    const timestamp = new Date().toLocaleString("ru-RU");

    // Формируем payload для узла node-red-contrib-telegrambot

    msg.payload = {

    chatId: 'YOUR_OWNER_CHAT_ID', // Замените на реальный ID чата владельца

    type: 'message',

    content: `🔔 Внимание!\nРежим 'Гость' был ${statusText}.\n\nВремя: ${timestamp}`

    };

    return msg;

  • Выход узла `function` соединяется с узлом `telegram sender`.
  • Теперь при каждом изменении состояния режима владелец получит мгновенное уведомление в свой Telegram.

    Что дальше

    В этом уроке мы спроектировали и реализовали надежную архитектуру для режима 'Гость', сфокусировавшись на безопасности и качестве пользовательского опыта. Мы научились фильтровать команды на уровне центрального шлюза и создавать упрощенные, контекстно-зависимые интерфейсы.

    В следующем уроке мы перейдем к еще более сложной теме: созданию составных сценариев, которые объединяют несколько подсистем (свет, климат, медиа) для создания комплексных атмосфер, таких как "Просмотр кино" или "Ужин", и научимся управлять приоритетами между ними.