Практика: Симуляция 'Датчик-Реле'
Введение: Логическая связка "Датчик-Реле" и цели урока
В основе практически любой системы автоматизации лежит простой, но мощный принцип: условие-действие. Это фундаментальная логическая связка, которая описывает реакцию системы на события во внешней среде. Когда выполняется определенное условие (сигнал от датчика), система выполняет запрограммированное действие (команду на исполнительное устройство).
Этот принцип окружает нас повсюду:
- Датчик движения и свет: Когда датчик движения (условие) обнаруживает присутствие человека, система подает команду на включение света (действие).
- Термостат и котел отопления: Когда температура в комнате опускается ниже заданной уставки (условие), термостат отправляет команду на запуск котла (действие).
- Датчик протечки и клапан: При обнаружении воды на полу (условие), система немедленно перекрывает подачу воды с помощью электромагнитного клапана (действие).
Понимание этой базовой модели «Вход → Обработка → Выход» является ключом к проектированию как простых, так и сложных сценариев автоматизации на платформе HI.
Цель этого урока — собрать в среде Node-RED простую, но полнофункциональную виртуальную схему, которая имитирует логику "Датчик-Реле". Мы не будем использовать физические входы и выходы контроллера. Вместо этого мы создадим их симуляцию с помощью стандартных узлов Node-RED. Это позволит нам полностью сосредоточиться на логике потока данных и обработке сообщений, не отвлекаясь на аппаратную часть.Для достижения этой цели мы будем использовать следующие "виртуальные" компоненты:
- Узел `Inject` в роли виртуального датчика. Он будет генерировать сообщения, имитирующие сигналы "включено" и "выключено".
- Узел `Switch` в роли логического центра. Он будет анализировать входящие сигналы и направлять поток данных по разным веткам в зависимости от условия.
- Узел `Change` в роли форматировщика команд. Он будет преобразовывать внутренний логический сигнал в команду, понятную для исполнительного устройства.
- Узел `Debug` в роли виртуального исполнителя (или его индикатора). Он будет отображать финальную команду, как если бы она была отправлена на реальное реле.
> 💡 Подсказка: На этом уроке мы работаем с виртуальными узлами, чтобы сфокусироваться на логике. В последующих модулях, например, в курсе `COURSE-03` по работе с протоколом MQTT, мы научимся заменять эти симуляторы на узлы, которые получают данные от реальных беспроводных датчиков и отправляют команды на настоящие исполнительные устройства.
К концу этого урока вы создадите свой первый интерактивный сценарий и получите практическое понимание того, как сообщения `msg` проходят через поток, изменяются и управляют логикой системы.
---
Шаг 1: Создание симулятора датчика
Начнем с создания нашего "виртуального датчика". Как мы уже знаем из предыдущих уроков, узел `Inject` идеально подходит для этой задачи, так как он позволяет вручную или автоматически генерировать сообщения `msg` с заданным содержимым. Мы создадим два таких узла: один будет имитировать сигнал датчика "обнаружено движение" (состояние `true`), а другой — "движение отсутствует" (состояние `false`).
Настройка узла "Датчик: Включено"
После настройки узел будет выглядеть так на панели конфигурации:
| Параметр | Тип значения | Значение | Пояснение |
| :------- | :----------- | :------------------------- | :-------------------------------------- |
| Payload | boolean | `true` | Состояние датчика "обнаружено" |
| Topic | string | `sensor/motion/livingroom` | Уникальный идентификатор источника |
| Name | - | `Датчик: Движение ЕСТЬ` | Человекочитаемое имя на схеме |
Настройка узла "Датчик: Выключено"
Теперь создадим второй узел, который будет имитировать сигнал об отсутствии движения.
Теперь у вас на рабочем пространстве находятся два узла, которые полностью имитируют поведение одного датчика, способного отправлять два состояния. При нажатии на первый будет сгенерировано сообщение:
{
"payload": true,
"topic": "sensor/motion/livingroom",
"_msgid": "..."
}
А при нажатии на второй:
{
"payload": false,
"topic": "sensor/motion/livingroom",
"_msgid": "..."
}
Мы успешно создали симулятор входа данных в нашу систему. Следующий шаг — научить систему реагировать на эти данные.
---
Шаг 2: Реализация логического ветвления с узлом Switch
Получив сигнал от датчика, система должна принять решение: что делать дальше? Для этого в Node-RED существует узел `Switch`. Он работает как железнодорожная стрелка для сообщений: проверяет `msg` по одному или нескольким правилам и отправляет его на тот выход, который соответствует первому сработавшему условию.
> ⚠️ Внимание: Узел `Switch` проверяет условия последовательно, сверху вниз, и по умолчанию отправляет сообщение на первый же совпавший выход. Для оптимизации производительности на сложных потоках размещайте наиболее частые или критичные условия выше в списке правил, чтобы уменьшить задержку обработки.
Наша задача — настроить узел `Switch` так, чтобы он направлял сообщения со значением `true` на один выход, а со значением `false` — на другой.
Настройка узла `Switch`
* В первой строке правил оставьте условие `==` (is equal to).
* Рядом в поле выберите тип `boolean`.
* Установите значение `true`.
* Таким образом, первое правило звучит как: "Если `msg.payload` равен `true`".
* Нажмите на кнопку `+add` внизу, чтобы добавить второе правило.
* Аналогично первому, установите условие `==` `boolean` `false`.
* Второе правило теперь звучит как: "Если `msg.payload` равен `false`".
Теперь узел `Switch` на рабочем пространстве имеет два выхода. Верхний (выход 1) будет активироваться, когда `msg.payload` равно `true`. Нижний (выход 2) — когда `msg.payload` равно `false`.
Если бы мы сейчас подключили к этим выходам узлы `Debug`, то увидели бы, что при нажатии на `Датчик: Движение ЕСТЬ` сообщение появляется на выходе 1, а при нажатии на `Датчик: Движения НЕТ` — на выходе 2. Мы создали логическое ветвление.
Схема потока на данном этапе:[Датчик: Движение ЕСТЬ] ---+
|---> [Проверка состояния датчика] ---(выход 1, if true)
[Датчик: Движения НЕТ] ----+ |
+--(выход 2, if false)
Мы разделили поток на две логические ветки. Теперь на каждой из них нам нужно сформировать конкретную команду для нашего гипотетического исполнителя.
---
Шаг 3: Формирование команд для исполнителя
Наш "датчик" отправляет логические `true` и `false`. Это удобно для внутренней логики, но реальные исполнительные устройства часто ожидают команды в ином формате.
- Релейный модуль, управляемый по Modbus, может ожидать число `1` для включения и `0` для выключения, записываемое в определенный регистр.
- Устройство, управляемое через HTTP API, может требовать отправки JSON-объекта вида `{"state": "ON"}`.
- Светильник KNX может ожидать команду определенного типа данных в групповом адресе.
Для преобразования наших внутренних логических сигналов в команды нужного формата используется узел `Change`. Этот узел позволяет гибко изменять различные части объекта `msg`. Мы будем использовать его, чтобы заменить `msg.payload`.
Создадим два узла `Change`: один для формирования команды "ВКЛЮЧИТЬ", другой для команды "ВЫКЛЮЧИТЬ".
Настройка узла "Команда: ON"
* В поле `Set` выберите `msg.payload`.
* В поле `to` (в) выберите тип `string` (строка).
* Впишите в текстовое поле значение `ON`.
Теперь, когда сообщение с `payload: true` пройдет через этот узел, его `payload` изменится на `"ON"`.
Трансформация сообщения:- До узла `Change`:
{
"payload": true,
"topic": "sensor/motion/livingroom",
"_msgid": "..."
}
- После узла `Change`:
{
"payload": "ON",
"topic": "sensor/motion/livingroom",
"_msgid": "..."
}
Настройка узла "Команда: OFF"
Теперь наш поток полностью реализует логику: получить сигнал, принять решение в зависимости от его значения и сформировать соответствующую команду. Остался последний шаг: увидеть результат нашей работы.
---
Шаг 4: Визуализация и отладка
Мы подошли к финальному этапу сборки нашей схемы — визуализации результата. Для этого мы будем использовать узел `Debug`, который, как мы знаем из урока `COURSE-01-M01-L05`, является незаменимым инструментом для отладки и просмотра содержимого сообщений `msg` в любой точке потока. Мы используем его как индикатор состояния нашего "виртуального реле".
Настройка узлов `Debug`
* В поле `Output` по умолчанию стоит `msg.payload`. Это то, что нам нужно.
* Для удобства вывода можно изменить значение `to` на `debug tab and console` (вкладка отладки и консоль), чтобы видеть результат и там, и там.
* В поле `Name` можно написать `ИНДИКАТОР РЕЛЕ: ON`.
* Нажмите Done.
Теперь наш поток полностью собран и готов к тестированию.
Полная схема потока (ASCII-диаграмма):[Датчик: Движение ЕСТЬ] ---+ +---> [Сформировать команду ON] ---> [ИНДИКАТОР РЕЛЕ: ON]
|---> [Проверка состояния] --|
[Датчик: Движения НЕТ] ----+ +---> [Сформировать команду OFF] --> [ИНДИКАТОР РЕЛЕ: OFF]
Тестирование потока
Поздравляем! Вы только что создали и протестировали свой первый полноценный сценарий автоматизации, реализующий логику "Датчик-Реле".
Экспорт потока
Каждый созданный вами поток можно экспортировать в виде JSON-кода. Это позволяет делиться наработками, сохранять резервные копии и переносить логику между разными контроллерами.
Вот как выглядит JSON-код для нашего потока. Вы можете импортировать его на своем контроллере через меню `Import`, чтобы сразу получить готовую схему.
[
{
"id": "a1b2c3d4.123456",
"type": "inject",
"z": "...",
"name": "Датчик: Движение ЕСТЬ",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "sensor/motion/livingroom",
"payload": "true",
"payloadType": "bool",
"x": 150,
"y": 100,
"wires": [
[
"e5f6g7h8.789012"
]
]
},
{
"id": "e5f6g7h8.789012",
"type": "switch",
"z": "...",
"name": "Проверка состояния датчика",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 400,
"y": 120,
"wires": [
[
"i9j0k1l2.345678"
],
[
"m3n4o5p6.901234"
]
]
},
{
"id": "b1c2d3e4.567890",
"type": "inject",
"z": "...",
"name": "Датчик: Движения НЕТ",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "sensor/motion/livingroom",
"payload": "false",
"payloadType": "bool",
"x": 140,
"y": 160,
"wires": [
[
"e5f6g7h8.789012"
]
]
},
{
"id": "i9j0k1l2.345678",
"type": "change",
"z": "...",
"name": "Сформировать команду ON",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "ON",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 650,
"y": 100,
"wires": [
[
"q7r8s9t0.123456"
]
]
},
{
"id": "m3n4o5p6.901234",
"type": "change",
"z": "...",
"name": "Сформировать команду OFF",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "OFF",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 650,
"y": 160,
"wires": [
[
"u1v2w3x4.789012"
]
]
},
{
"id": "q7r8s9t0.123456",
"type": "debug",
"z": "...",
"name": "ИНДИКАТОР РЕЛЕ: ON",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 900,
"y": 100,
"wires": []
},
{
"id": "u1v2w3x4.789012",
"type": "debug",
"z": "...",
"name": "ИНДИКАТОР РЕЛЕ: OFF",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 900,
"y": 160,
"wires": []
}
]
---
Итоги урока и дальнейшие шаги
На этом практическом занятии мы сделали важный шаг от теории к практике. Мы разобрали и реализовали краеугольный камень любой автоматизации — логическую связку "Датчик-Реле".
Давайте кратко повторим, что мы сделали:Главная концепция, которую вы должны были усвоить, — это универсальная модель потока данных: Вход → Обработка → Выход. Эта простая трехэтапная модель лежит в основе 90% всех задач, которые вы будете решать с помощью контроллера HI и Node-RED. Сегодняшний поток — это ее идеальная иллюстрация.
> 🔗 Связанный материал: В следующем уроке, `COURSE-01-M01-L08: Работа с MQTT-протоколом`, мы сделаем эту схему гораздо более реалистичной. Мы заменим наш виртуальный датчик (`Inject`) на узел `MQTT In`, который будет получать данные от настоящего (или симулированного) устройства по сети. Это станет вашим первым шагом в мир распределенных систем и Интернета вещей (IoT).