ГлавнаяАкадемияСценарии умного дома: режимы, состояния, приоритеты → SCN-COMFORT-002: Управление шторами (восход/закат)

SCN-COMFORT-002: Управление шторами (восход/закат)

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

SCN-COMFORT-002-S01: Автоматизация по солнцу: введение

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

Преимущества данного подхода многогранны:

В основе сценария лежат астрономические события, которые служат триггерами для выполнения действий.

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

Постановка задачи урока:

Наша цель — спроектировать и реализовать в среде Node-RED на контроллере HI надежный и гибкий сценарий `SCN-COMFORT-002`. Этот сценарий должен в автоматическом режиме открывать шторы после восхода солнца и закрывать их перед закатом. Кроме того, он должен корректно интегрироваться с другими системами умного дома, в частности, учитывать ручное управление со стороны пользователя и глобальные режимы, такие как «Я ушел».

Необходимые компоненты:
  • Контроллер HI: Центральный узел системы, на котором исполняется логика в среде Node-RED.
  • Привод штор: Электрический карниз или рулонная штора с приводом, который поддерживает управление по протоколу MQTT. Привод должен сообщать свое текущее состояние (открыто, закрыто, положение в процентах) и принимать команды на изменение состояния.
  • Среда Node-RED: Программная платформа, установленная на контроллере HI, где мы будем визуально проектировать поток управления.
  • ---

    SCN-COMFORT-002-S02: Конфигурация узла расчета солнечных событий

    Для реализации автоматизации на основе астрономических событий нам потребуется специализированный узел, который будет выполнять расчеты и генерировать сообщения-триггеры. Одним из наиболее популярных и функциональных является `node-red-contrib-sun-position`.

    Установка узла

    Если узел еще не установлен на вашем контроллере HI, его можно добавить через интерфейс Node-RED:

  • Откройте меню (три горизонтальные полосы в правом верхнем углу).
  • Выберите «Manage palette» (Управление палитрой).
  • Перейдите на вкладку «Install» (Установка).
  • В строке поиска введите `node-red-contrib-sun-position` и нажмите «Install».
  • После установки в палитре узлов появится новый набор, включая узел `sun-position`.

    Настройка узла

    Точность работы всего сценария напрямую зависит от правильной конфигурации этого узла.

    > 💡 Подсказка: Для получения точных координат вашего объекта используйте онлайн-карты (например, Google Maps, Яндекс.Карты) или специализированные сервисы. Кликнув правой кнопкой мыши по нужной точке на карте, вы сможете скопировать широту и долготу. Ошибка даже в один градус широты может привести к смещению времени срабатывания на несколько минут.

    Перетащите узел `sun-position` на рабочее поле и откройте его настройки, дважды кликнув по нему.

    Основные параметры для конфигурации:

    Далее необходимо настроить правила генерации событий, которые и будут запускать наш сценарий. Узел позволяет создавать множество правил. Для нашей задачи нам понадобятся как минимум два: для восхода и для заката.

  • Нажмите кнопку «+add», чтобы создать новое правило.
  • Event (Событие): В выпадающем списке выберите `sunrise`.
  • Offset (Смещение): Укажите смещение в минутах относительно события. Положительное значение означает «после события», отрицательное — «до события». Например, для открытия штор через 15 минут после фактического восхода, введите `15`. Для начала оставим `0`.
  • Property (Свойство): Укажите, в какое свойство объекта `msg` будет записано имя события. Стандартное значение `topic` является хорошей практикой, так как позволяет легко маршрутизировать сообщения с помощью узла `switch`.
  • Создайте второе правило для события `sunset`. В качестве смещения можно задать отрицательное значение, например `-20`, чтобы шторы закрывались за 20 минут до заката, обеспечивая приватность с наступлением сумерек.
  • Анализ выходного сообщения

    Узел `sun-position` генерирует сообщения не только по настроенным событиям, но и периодически (по умолчанию каждую минуту), отправляя на свой первый выход подробную информацию о текущем положении солнца. Это сообщение соответствует "Контракту сообщения" и является основой для построения логики.

    Пример сообщения (`msg.payload`) от узла `sun-position`:

    {
    

    "azimuth": 240.5,

    "altitude": 15.2,

    "sunInSky": true,

    "astral": {

    "sunrise": 1678846800000,

    "sunset": 1678887600000,

    "solarNoon": 1678867200000,

    "dawn": 1678844400000,

    "dusk": 1678890000000

    }

    }

    Ключевые поля для нашего сценария:

    Когда наступает время, заданное правилом (например, `sunrise`), узел отправляет на свой второй выход сообщение, у которого `msg.topic` будет равен имени события (`sunrise`). Именно этот выход мы будем использовать как триггер.

    ---

    SCN-COMFORT-002-S03: Базовый сценарий: Открытие на восходе, закрытие на закате

    Теперь, когда у нас есть настроенный источник астрономических событий, мы можем построить базовый поток управления шторами в Node-RED.

    ASCII-схема потока `FLOW-COMFORT-SUN-001`:
                         +---------------------------+
    

    (Срабатывает по | sun-position |

    восходу/закату) --> | "Астро-таймер: Гостиная" | -- (2-й выход: События) --> [Switch: "Событие?"]

    +---------------------------+

                         +--------------------------+    +-----------------------+    +------------------------------------------+
    

    [Switch: "Событие?"] -- (msg.topic == "sunrise") --> | Change: "Payload=OPEN" | -> | mqtt out |

    | +-----------------------+ | Topic: hi/devices/curtain_living_room/set|

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

    +-- (msg.topic == "sunset") --> | Change: "Payload=CLOSE"| -> | mqtt out |

    +-----------------------+ | Topic: hi/devices/curtain_living_room/set|

    Шаги по созданию потока:

  • Узел-триггер: Используйте настроенный ранее узел `sun-position`. Нам нужен его второй выход, который генерирует сообщения только в момент наступления заданных событий.
  • Узел-логика `switch`: Добавьте узел `switch` и соедините его со вторым выходом узла `sun-position`. Настройте его для маршрутизации сообщений:
  • * Property (Свойство): `msg.topic`

    * Правило 1: `==` (строка) `sunrise` -> выход 1

    * Правило 2: `==` (строка) `sunset` -> выход 2

  • Узлы-действия `change` и `mqtt out`: Нам нужно сформировать и отправить команду приводу штор. Команда отправляется по протоколу MQTT. Сначала определим контракт сообщения для управления приводом шторы.
  • | Команда | `msg.payload` (JSON) | Описание |

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

    | Открыть | `{"state": "OPEN"}` | Полностью открыть штору. |

    | Закрыть | `{"state": "CLOSE"}` | Полностью закрыть штору. |

    | Остановить | `{"state": "STOP"}` | Немедленно остановить движение. |

    | Задать позицию| `{"position": 80}` | Установить положение в процентах (0-100). |

    * Для ветки "sunrise":

    1. Добавьте узел `change`.

    2. Настройте правило: `Set` `msg.payload` `to` (тип J: Expression) `{"state": "OPEN"}`.

    3. Соедините его с узлом `mqtt out`.

    4. В узле `mqtt out` укажите MQTT-топик для управления шторой, например, `hi/devices/curtain_living_room/set`. Настройте ваш MQTT-брокер.

    * Для ветки "sunset":

    1. Аналогично, добавьте узел `change`.

    2. Настройте правило: `Set` `msg.payload` `to` (тип J: Expression) `{"state": "CLOSE"}`.

    3. Соедините его с тем же узлом `mqtt out`.

    Использование смещений (offsets)

    Как мы упоминали, часто требуется, чтобы шторы закрывались не в момент заката, а немного раньше. Это легко настраивается в узле `sun-position`.

  • Откройте узел `sun-position`.
  • Найдите правило для события `sunset`.
  • В поле Offset введите `-20`. Это заставит узел сгенерировать событие `sunset` за 20 минут до реального заката.
  • Аналогично, если вы не хотите, чтобы шторы открывались слишком рано, можно задать для `sunrise` положительное смещение, например, `15`.
  • Для более сложной логики, например, если смещение зависит от дня недели или другого фактора, можно использовать узел `function`.

    // Пример узла function для динамического смещения
    

    // Этот узел должен стоять ПЕРЕД узлом sun-position,

    // чтобы динамически менять его конфигурацию.

    // Это продвинутая техника, но полезная для понимания.

    // Получаем текущую дату

    const now = new Date();

    const dayOfWeek = now.getDay(); // 0 = Воскресенье, 6 = Суббота

    let sunriseOffset = 15; // Стандартное смещение для восхода

    let sunsetOffset = -20; // Стандартное смещение для заката

    // В выходные дни открываем шторы позже

    if (dayOfWeek === 0 || dayOfWeek === 6) {

    sunriseOffset = 60; // Через час после восхода

    }

    // Формируем сообщение для изменения конфигурации узла sun-position

    msg.payload = {

    "config": {

    "rules": [

    { "event": "sunrise", "offset": sunriseOffset, "property": "topic" },

    { "event": "sunset", "offset": sunsetOffset, "property": "topic" }

    ]

    }

    };

    return msg;

    Этот код демонстрирует, как можно программно управлять конфигурацией узла `sun-position`, посылая на его вход специальное управляющее сообщение.

    ---

    SCN-COMFORT-002-S04: Интеграция и приоритеты

    Базовый сценарий работает, но в реальной жизни он будет конфликтовать с другими системами и действиями пользователя. Чтобы автоматизация была комфортной, а не назойливой, необходимо продумать систему приоритетов.

    Проблема «конфликта автоматики»

    Представьте ситуацию: на улице пасмурно, и пользователь вручную закрыл шторы, чтобы включить проектор и посмотреть кино. Через час наступает время, рассчитанное автоматикой для открытия штор. Шторы открываются, прерывая просмотр. Это плохой пользовательский опыт (UX).

    Для реализации ручного управления мы применим паттерн 'Блокировка по таймеру', который является частью более общей концепции конечных автоматов, подробно рассмотренной в уроке `COURSE-07-M01-L03`.

    > ⚠️ Внимание: При реализации логики ручного управления и возврата к автоматическому режиму убедитесь в отсутствии зацикливаний. Неправильно спроектированный поток может привести к тому, что команда от настенного выключателя будет немедленно отменена автоматикой, и наоборот.

    Интеграция с режимом «Я ушел»

    🔗 Связанный материал: Логика режима «Я ушел» была подробно рассмотрена в уроке `SCN-LIGHT-012`.

    Если в доме никого нет (`away_mode` == `true`), то открытие штор утром не имеет смысла с точки зрения комфорта, но полезно для эффекта присутствия. Закрытие на закате, наоборот, обязательно для безопасности.

    Логика должна быть следующей:

    Реализация шлюза приоритетов (Priority Gate)

    Создадим узел `function`, который будет стоять после узла `switch` и перед узлами `change`. Он будет решать, пропускать ли команду от астро-таймера.

    Имя узла: `Priority Gate: Curtains` Код:
    // Получаем глобальный режим 'Я ушел'
    

    // Предполагается, что он хранится в flow-контексте

    const awayMode = flow.get('away_mode') || false;

    // Проверяем, заблокирована ли автоматика ручным управлением

    const isLocked = flow.get('curtain_living_room_locked') || false;

    // Получаем событие от астро-таймера

    const event = msg.topic;

    // --- ЛОГИКА ПРИОРИТЕТОВ ---

    // 1. Проверяем блокировку по таймеру. Если флаг установлен, блокируем команду.

    if (isLocked === true) {

    node.status({ fill: "yellow", shape: "ring", text: "Locked by manual override" });

    return null; // Блокируем сообщение

    }

    // 2. Проверяем режим 'Я ушел'

    if (awayMode === true) {

    // Если мы в отъезде, на восход не реагируем, на закат - реагируем

    if (event === 'sunrise') {

    node.status({ fill: "grey", shape: "dot", text: "Away mode: ignoring sunrise" });

    return null; // Блокируем открытие

    }

    }

    // Если все проверки пройдены, пропускаем сообщение дальше в поток

    node.status({ fill: "green", shape: "dot", text: `AUTO: ${event}` });

    return msg;

    Этот узел, используя паттерн "Визуальный статус", наглядно показывает причину блокировки или выполнения команды, что критически важно для отладки. Чтобы эта схема работала, необходимо реализовать логику установки флага `curtain_living_room_locked` в соответствии с паттерном, рассмотренным в уроке `COURSE-07-M01-L03`.

    ---

    SCN-COMFORT-002-S05: Итоги и следующие шаги

    В рамках этого урока мы прошли полный цикл создания интеллектуального сценария автоматизации `SCN-COMFORT-002` на платформе HI.

    Резюме:

    Созданный нами сценарий является надежной основой, но его можно и нужно развивать дальше, адаптируя под конкретные нужды объекта и пользователя.

    Перспективы развития сценария

    Что дальше?

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