SCN-CLIMATE-008: 'Проветривание' (отключение отопления при открытом окне)
Введение в сценарий "Проветривание": логика и компоненты
Данный урок посвящен разработке одного из самых востребованных и эффективных сценариев энергосбережения в системах умного дома и автоматизации зданий — "Проветривание".
Цель сценария — автоматически отключать систему отопления в конкретной зоне, когда в ней открывается окно. Это простое действие позволяет добиться значительной экономии энергоресурсов, предотвращая бессмысленную работу отопительных приборов, пытающихся "обогреть улицу". Помимо экономической выгоды, сценарий повышает общий комфорт, избавляя от резких перепадов температуры и сквозняков, которые могут возникнуть при одновременной работе радиатора и открытом окне.Базовая логика и компоненты
В основе сценария лежит простая и понятная логическая связка, управляемая событиями:
ЕСЛИ `статус окна изменился на "открыто"` ТОГДА `перевести систему отопления в режим "Выключено (Проветривание)"` ИНАЧЕ ЕСЛИ `статус окна изменился на "закрыто"` ТОГДА `вернуть систему отопления в ее предыдущий рабочий режим`Для физической реализации этого сценария на объекте требуется минимальный набор аппаратных компонентов:
* Термоэлектрический сервопривод на клапане радиатора.
* Реле, управляющее электрическим конвектором.
* Клапан на коллекторе водяного теплого пола.
* Клапан фанкойла.
Эти устройства подключаются к релейным выходам контроллера HI или управляются по цифровым шинам, таким как Modbus или KNX.
Коммуникационная модель
Для обеспечения максимальной гибкости, масштабируемости и слабой связанности компонентов системы мы будем использовать протокол MQTT в качестве основного транспортного уровня. Это означает, что и датчик открытия, и исполнительное устройство отопления взаимодействуют с ядром логики в Node-RED не напрямую, а через публикацию и подписку на сообщения в MQTT-брокере.
Такой подход дает несколько ключевых преимуществ:
- Абстракция: Логика в Node-RED оперирует не физическими входами/выходами, а абстрактными MQTT-топиками. Это позволяет легко заменять аппаратные компоненты без изменения самого сценария.
- Масштабируемость: Можно легко добавить новые окна или зоны отопления, просто настроив их на публикацию/подписку на соответствующие топики.
- Интеграция: Любая другая система (HMI-панель, мобильное приложение, голосовой ассистент) может легко получить статус окна или управлять отоплением, просто работая с тем же MQTT API.
В следующих разделах мы пошагово реализуем этот сценарий на платформе HI с использованием Node-RED.
---
Шаг 1: Получение статуса окна по MQTT
Первым шагом в реализации нашего сценария является получение данных от датчика открытия окна. Мы настроим в Node-RED узел, который будет "слушать" MQTT-брокер и реагировать на сообщения об изменении состояния окна.
Проектирование структуры топиков MQTT
Правильное проектирование иерархии топиков — залог создания поддерживаемой и легко расширяемой системы.
> 💡 Подсказка: Используйте единую и предсказуемую конвенцию именования топиков во всем проекте. Это значительно упрощает отладку, масштабирование и интеграцию с системами верхнего уровня (например, HMI-панелями).
Рекомендуемая структура топика для устройств:
`hi/
- `hi`: корневой префикс проекта.
- `
`: физическое расположение (например, `living_room`, `office`, `floor1`). - `
`: тип устройства (например, `sensors`, `lights`, `climate`). - `
`: уникальный идентификатор устройства (например, `main_window`, `radiator_1`). - `
`: конкретный параметр устройства (`contact`, `temperature`, `state`).
Для нашего датчика открытия окна в гостиной топик будет выглядеть так:
`hi/living_room/sensors/main_window/contact`
Стандартизация формата сообщений
Чтобы избежать путаницы со строками типа `"open"`, `"closed"`, `1`, `0`, мы будем использовать стандартизированный JSON-контракт для всех сообщений. Это делает сообщения самодокументируемыми и легко расширяемыми в будущем.
Для датчика контакта мы будем использовать следующий формат `msg.payload`:
- Окно закрыто (контакт замкнут): `{ "contact": true }`
- Окно открыто (контакт разомкнут): `{ "contact": false }`
Настройка потока в Node-RED
Теперь создадим поток, который будет получать и обрабатывать эти сообщения.
* Server: Выберите ваш предварительно настроенный MQTT-брокер.
* Topic: Укажите топик нашего датчика: `hi/living_room/sensors/main_window/contact`.
* Output: Установите `a parsed JSON object`. Это заставит Node-RED автоматически разбирать входящую JSON-строку в объект JavaScript.
* Name: Дайте узлу осмысленное имя, например, `Статус окна (гостиная)`.
+--------------------------+ +-----------------------+
(MQTT Broker) --> | mqtt in | --> | debug |
| Статус окна (гостиная) | | (complete msg object) |
+--------------------------+ +-----------------------+
Теперь, когда вы будете открывать и закрывать окно, в панели отладки (Debug) вы будете видеть входящие сообщения.
Пример сообщения при открытии окна:{
"_msgid": "a1b2c3d4.e5f6g7",
"topic": "hi/living_room/sensors/main_window/contact",
"payload": {
"contact": false
},
"qos": 1,
"retain": false
}
Мы успешно настроили получение данных. Следующим шагом будет добавление логики, которая будет реагировать на эти данные.
---
Шаг 2: Реализация логики в Node-RED с сохранением состояния
аг 2: Реализация логики в Node-RED с сохранением состояния
Получив статус окна, нам необходимо реализовать основную логику сценария: выключить отопление при открытом окне и включить его обратно при закрытом. Ключевой аспект здесь — "stateful" логика, то есть логика, зависящая от состояния. Нам нужно не просто включить отопление, а восстановить его предыдущее состояние (режим, уставку температуры).
Маршрутизация потока с помощью узла `switch`
Узел `switch` идеально подходит для направления потока сообщений в зависимости от содержимого `msg.payload`.
* Property: `msg.payload.contact` (мы проверяем значение поля `contact` внутри объекта `payload`).
* Правило 1: `is false` (логическое `false`). Это соответствует открытому окну.
* Правило 2: `is true` (логическое `true`). Это соответствует закрытому окну.
* Name: `Окно открыто/закрыто?`
Теперь узел `switch` имеет два выхода: первый сработает, когда окно откроется, второй — когда закроется.
Сохранение состояния отопления с помощью `global context`
Перед тем как выключить отопление, мы должны сохранить его текущие настройки. Согласно архитектурному стандарту нашего курса, для хранения состояний, которые могут потребоваться разным сценариям (например, климату и защите от протечек), мы используем глобальный контекст (`global context`).
Предположим, что текущее состояние нашего термостата транслируется в глобальную переменную `global.climate_living_room_state`. Этот объект может выглядеть так:
{
"mode": "auto",
"target_temperature": 22.5,
"current_state": "HEATING"
}
> 💡 Важно: Использование `global context` позволяет другим потокам (flow) учитывать, что отопление было выключено именно сценарием проветривания, а не вручную пользователем.
Логика при открытии окна (выход 1 узла `switch`):[switch: выход 1] --> [change: Сохранить состояние] --> [change: Команда ВЫКЛ] --> [mqtt out: Упр. радиатором]
- Настройка узла `change: Сохранить состояние`:
* Name: `Сохранить состояние климата`.
- Настройка узла `change: Команда ВЫКЛ`:
* Name: `Сформировать команду OFF`.
Восстановление состояния при закрытии окна
Когда окно закрывается, нам нужно выполнить обратное действие: извлечь сохраненное состояние из `global.saved_heating_state` и отправить его термостату или исполнительному устройству.
Логика при закрытии окна (выход 2 узла `switch`):[switch: выход 2] --> [change: Восстановить состояние] --> [mqtt out: Упр. радиатором]
- Настройка узла `change: Восстановить состояние`:
* Name: `Восстановить состояние климата`.
Таким образом, мы создали логику, которая не просто вкл/выкл устройство, а аккуратно сохраняет и восстанавливает его рабочие параметры через глобальное хранилище данных.
Шаг 3: Интеграция со сценарием термостата и управление приоритетами
Просто отправить команду `OFF` исполнительному устройству недостаточно. Если в системе одновременно работает другой сценарий, например, базовый термостат, который поддерживает заданную температуру, он может через несколько секунд снова включить отопление, отменяя наши действия.
Для решения этой проблемы мы применим архитектурный паттерн блокировки через глобальное состояние. Вместо прямого "конфликта" со сценарием термостата, наш сценарий "Проветривание" установит специальный флаг, сигнализирующий о своем высшем приоритете.
> 💡 Что такое флаг блокировки?
> Это переменная в глобальном контексте Node-RED (`global`), которая показывает, какой сценарий в данный момент обладает эксклюзивным правом на управление устройством. Другие сценарии обязаны проверять этот флаг перед отправкой своих команд.
Механизм управления через флаг блокировки
Наш сценарий "Проветривание", помимо отправки команды, будет управлять флагом в глобальном объекте состояния `HI_STATE`.
При открытии окна (ветка 1 узла `switch`):Мы устанавливаем флаг блокировки, а затем отправляем команду на выключение.
- Добавим еще один узел `change` в ветку "Окно открыто":
- Name: `Установить флаг 'Airing'`
- Правила:
Мы должны снять флаг блокировки, чтобы другие сценарии (например, термостат) смогли возобновить управление.
- Добавим еще один узел `change` в ветку "Окно закрыто":
- Name: `Снять флаг блокировки`
- Правила:
Как это работает для других сценариев?
Теперь сценарий термостата для гостиной, прежде чем отправить команду на управление радиатором, должен будет выполнить простую проверку. Это делается в узле `function`.
Пример логики для сценария термостата:// Получаем текущее значение флага блокировки
const override = global.get('HI_STATE.zones.living_room.climate.override') || '';
// Если флаг установлен и установлен не нами, прекращаем работу
if (override !== '' && override !== 'thermostat') {
// Возвращаем null, чтобы остановить поток сообщений
// Термостат временно "заморожен"
return null;
}
// ... остальная логика термостата ...
return msg;
Почему этот подход эффективнее?
Это ключевой архитектурный момент, обеспечивающий слабую связанность и масштабируемость системы.
- Явное управление: Сценарий "Проветривание" не знает о существовании термостата. Он просто заявляет о своем "праве" на управление, устанавливая флаг.
- Централизация состояния: Все правила приоритетов сводятся к проверке одного поля в глобальном объекте состояния. Это упрощает отладку.
- Гибкость: Когда мы снимаем флаг, мы не включаем отопление принудительно. Сценарий термостата сам при следующем запуске увидит, что блокировка снята, и примет решение о включении или выключении отопления на основе текущей температуры. Это гарантирует возврат к корректной работе.
- Надежность: Глобальный контекст может быть сделан персистентным (сохраняемым при перезагрузке). Даже после сбоя питания контроллер "вспомнит", что был активен режим проветривания, и не включит отопление, пока окно открыто.
---
Итоги, тайм-ауты и лучшие практики
Мы успешно спроектировали и реализовали полнофункциональный сценарий "Проветривание", который корректно интегрируется с другими системами автоматизации.
Обзор полного потока данных
Расширение сценария: защита от "дребезга" и тайм-ауты
В реальных условиях возможны ложные или быстрые срабатывания.
🔗 Связанный материал: Студент может легко перейти к базовым урокам по антифлаппингу для повторения — COURSE-07-M04-L02 и COURSE-07-M04-L03.
📋 Ключевые понятия для улучшения:
- Защита от дребезга (Debouncing): Если окно быстро открыли и закрыли (например, на 5 секунд), нет смысла запускать всю логику выключения отопления. Для этого после узла `mqtt in` можно поставить узел `trigger`. Его можно настроить так, чтобы он отправлял сигнал "окно открыто" только в том случае, если оно остается в этом состоянии непрерывно, например, 60 секунд. Это предотвращает ненужные переключения и износ оборудования.
- Тайм-аут на открытое окно: Длительное проветривание, особенно зимой, может привести к сильному выхолаживанию помещения. Можно добавить таймер, который сработает, если окно открыто более 30 минут.
Важность абстракции через MQTT API
Этот урок наглядно демонстрирует мощь подхода, основанного на абстрагировании устройств. Наша логика в Node-RED не имеет ни малейшего представления о том, какой именно датчик стоит на окне (проводной геркон, беспроводной Zigbee-датчик) или чем управляется отопление (реле, Modbus-привод). Она оперирует исключительно логическими MQTT-сообщениями. Это и есть основа построения по-настоящему гибких, масштабируемых и независимых от конкретного "железа" систем автоматизации.
Что дальше
В следующем уроке мы рассмотрим более сложные климатические сценарии, которые учитывают несколько факторов одновременно, например, управление вентиляцией с учетом не только уровня CO2, но и времени суток, и присутствия людей в помещении. Вы научитесь комбинировать данные из разных источников для принятия более интеллектуальных решений.