Предисловие
Добрый день, уже выложили множество статей для новичков про Node-Red. Я так же хочу дополнить эту нишу и описать основы для построения автоматизаций. К каждому примеру будет прикреплен flow, который вы можете импортировать себе и проверить. Давайте начнем.
P.S. рекомендую ознакомиться со статьями:
Node-RED - пошаговая инструкция для новичков. Часть 1Азы Node Red: Глобальные переменные (Global) - для чего они, как правильно использовать и пример автоматизации с нодой AND (логического И)
Термины
Нода (node) – "кубик", набор которых позволяет вам исполнить ваши желания. Вы можете их найти в правой части веб интерфейса.
Флоу (flow) – "вкладка" в веб интерфейсе Node-Red. Вы можете разнести логические части по разным флоу. Так, у меня, например, есть флоу с Deconz, Z-Way, Roborock.
Дебаг (debug) – термин из программирования, что значит отладка. С помощью дебага мы находим ошибки в нашем флоу.
Сообщение (message, msg) – набор данных, которые ноды принимают для обработки и отдают на выходе.
Пейлоад (payload) – термин, означающий полезную нагрузку. Сообщение может содержать в себе множество данных, но основные (наиболее полезные) передаются в объекте payload.
Деплой (deploy) – применение изменений.
Inject & Debug
Это две наиболее часто используемые ноды.
Давайте выведем в дебаг "Hello, sprut.ai!". Для этого нам необходимо настроить ноду inject так, чтобы она отсылала строку и нажать на кнопку (слева от ноды).
Работы с данными:
К примеру, нам нужно изменить какие-то данные из сообщения или перенести их в в другое место. Для этого нам поможет нода change.
Настройки этой ноды позволяют нам оперировать данными в соответствии с заданными нами правилами. Мы можем удалять данные по ключу, переносить из одного ключа в другой, изменять данные по ключу, устанавливать данные в новый ключ. Для примера, давайте заменим в строке из предыдущего примера подстроку "Hello," на "Welcome to". Для этого, в ноде change мы указываем, что данные нужно изменить (Change) в msg.payload, указываем необходимую строку для поиска и значение, на которые ее надо заменить.
[{"id":"1cd1d2cb.5b5fdd","type":"debug","z":"78eed68b.1d9708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":566,"y":160,"wires":[]},{"id":"792fc03a.a8bd","type":"inject","z":"78eed68b.1d9708","name":"","topic":"","payload":"Hello, sprut.ai","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":154,"y":160,"wires":[["b4af3668.df4068"]]},{"id":"b4af3668.df4068","type":"change","z":"78eed68b.1d9708","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"Hello,","fromt":"str","to":"Welcome to","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":356,"y":160,"wires":[["1cd1d2cb.5b5fdd"]]}]
Своя логика:
Мы можем написать логику на языке javascript внутри ноды Function. Давайте с помощью Function выведем в дебаг знакомую нам строку "Hello, sprut.ai". Для этого в объект msg.payload запишем желаемое значение и отдадим на выход Function наше сообщение. Что посылает Inject нам значения не имеет, мы все равно перепишем это.
Настройки ноды Function:
[{"id":"c9e14b6b.790ca8","type":"function","z":"78eed68b.1d9708","name":"Hello","func":"msg.payload = \"Hello, sprut.ai\";\nreturn msg;","outputs":1,"noerr":0,"x":274,"y":544,"wires":[["f8ff175e.9f0f58"]]},{"id":"9e5270f7.ecfc6","type":"inject","z":"78eed68b.1d9708","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":112,"y":544,"wires":[["c9e14b6b.790ca8"]]},{"id":"f8ff175e.9f0f58","type":"debug","z":"78eed68b.1d9708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":438,"y":544,"wires":[]}]
Разделяем логически данные:
Если нам нужно разделить данные логически, например, у нас есть текущее время и нужно определить, это день или ночь. Если значение часовой стрелки в интервале с 7 до 23, то мы считаем это за день, иначе – ночь. В этом нам поможет нода Switch. В примере ниже мы будем инжектить значение часовой стрелки вручную и проверять входит ли оно в интервал дня или ночи и выводить соответствующее слово в дебаг.
Настройки Switch:
[{"id":"9bba306c.4b5d9","type":"inject","z":"78eed68b.1d9708","name":"","topic":"","payload":"12","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":304,"wires":[["81a1c52b.cecc88"]]},{"id":"81a1c52b.cecc88","type":"switch","z":"78eed68b.1d9708","name":"","property":"payload","propertyType":"msg","rules":[{"t":"btwn","v":"7","vt":"num","v2":"23","v2t":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":274,"y":336,"wires":[["7f0bdad4.352764"],["426756fe.57f708"]]},{"id":"bc35674c.a108d8","type":"debug","z":"78eed68b.1d9708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":336,"wires":[]},{"id":"92c17226.82811","type":"inject","z":"78eed68b.1d9708","name":"","topic":"","payload":"3","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":368,"wires":[["81a1c52b.cecc88"]]},{"id":"7f0bdad4.352764","type":"function","z":"78eed68b.1d9708","name":"Day","func":"msg.payload = \"Day\";\nreturn msg;","outputs":1,"noerr":0,"x":402,"y":304,"wires":[["bc35674c.a108d8"]]},{"id":"426756fe.57f708","type":"function","z":"78eed68b.1d9708","name":"Night","func":"msg.payload = \"Night\";\nreturn msg;","outputs":1,"noerr":0,"x":402,"y":368,"wires":[["bc35674c.a108d8"]]}]
Тригер:
Разберем последнюю ноду для нашей автоматизации – Trigger. Документация говорит нам следующее: "При срабатывании может отправить сообщение, а затем дополнительно второе сообщение, если оно не было расширено или сброшено." Давайте разберем на примере. Мы включили свет и через 30 секунд нам нужно его выключить.
С помощью Inject пошлем на вход строку "on", далее настроим триггер таким образом:
- Пропускает дальше входящее сообщение без изменений.
- Ждет 30 секунд.
- В случае получения еще одного сообщения, сбрасывает и начинает отсчет 30 секунд сначала.
- После окончания 30 секунд отсылает сообщение "off".
[{"id":"b62f13af.c90a7","type":"inject","z":"78eed68b.1d9708","name":"","topic":"","payload":"on","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":102,"y":720,"wires":[["a24b1ca0.f28a"]]},{"id":"a24b1ca0.f28a","type":"trigger","z":"78eed68b.1d9708","op1":"","op2":"off","op1type":"pay","op2type":"str","duration":"30","extend":true,"units":"s","reset":"","bytopic":"all","name":"","x":278,"y":720,"wires":[["d1d0958b.975098"]]},{"id":"d1d0958b.975098","type":"debug","z":"78eed68b.1d9708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":470,"y":720,"wires":[]}]
Автоматизация:
Самое время применить наши знания и написать автоматизацию со следующими условиями:
- Есть датчик движения Z-Wave и лампа ZigBee.
- При срабатывании датчика движения мы включаем свет. Причем если это ночь, включаем на минимальную яркость, днем - на максимальную.
- Через 30 секунд выключить свет.
- При срабатывании движения, сбросить таймер и начать отсчет снова.
- Значения датчика движения прокинуть в HomeKit.
Будем использовать плагины node-red-contrib-deconz, node-red-contrib-zway, node-red-contrib-homekit-bridged.
Логика проста:
- Берем значение из ноды Z-Way In и пропускаем с помощью Switch только сообщения, сигнализирующие о срабатывании датчика движения. Конец движения нас не интересует. Так же с нижнего выхода пробрасываем датчик в HomeKit.
- Далее берем в Function текущее время и нас интересуют конкретно часы. Записываем значение в msg.payload.hours.
- С помощью Switch разделяем день и ночь и задаем соответствующую яркость для лампы и команду включения.
- Срабатывает Trigger и отсылает команды ноде Deconz Out. Свет включается.
- Через 30 секунд Trigger шлет команду выключения света (если, конечно, он не был сброшен новым движением).
По своему желанию вы можете взять датчик движения с Deconz или же выключатель Z-Way и внести изменения во флоу самостоятельно. Вам поможет использование Debug, чтобы узнать, какие данные шлются и что фильтровать. С вопросами не стесняйтесь писать мне в телеграме.
[{"id":"b236678b.3ad3c8","type":"homekit-service","z":"78eed68b.1d9708","isParent":true,"bridge":"1584ebf8.19cfb4","parentService":"","name":"Прихожая Движение","serviceName":"MotionSensor","topic":"","filter":false,"manufacturer":"IKEA","model":"E1525","serialNo":"343","characteristicProperties":"{}","x":548,"y":1024,"wires":[[]]},{"id":"1ea951aa.83c1ee","type":"deconz-output","z":"78eed68b.1d9708","name":"","server":"3c5efaa8.983d86","device":"00:0d:6f:ff:fe:44:f5:3d-01","device_name":"Hallway : Dimmable light","command":"json","commandType":"object","payload":"payload","payloadType":"msg","transitionTime":"","x":1326,"y":960,"wires":[]},{"id":"b49ca030.52e41","type":"switch","z":"78eed68b.1d9708","name":"Day\\Night","property":"payload.hours","propertyType":"msg","rules":[{"t":"btwn","v":"6","vt":"num","v2":"22","v2t":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":824,"y":960,"wires":[["8601f12d.7679c"],["4c3bf201.fa7dec"]]},{"id":"c8012ec4.a113a","type":"function","z":"78eed68b.1d9708","name":"Get time","func":"var date = new Date();\n// Hours part from the timestamp\nvar hours = date.getHours();\n\nmsg.payload.hours = hours;\n\nreturn msg;","outputs":1,"noerr":0,"x":664,"y":960,"wires":[["b49ca030.52e41"]]},{"id":"dae6bd4d.1b34c","type":"switch","z":"78eed68b.1d9708","name":"Presence","property":"payload.level","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":504,"y":960,"wires":[["c8012ec4.a113a"]]},{"id":"ca9979b1.332d78","type":"trigger","z":"78eed68b.1d9708","op1":"","op2":"{ \"on\" : false } ","op1type":"pay","op2type":"json","duration":"30","extend":true,"units":"s","reset":"","bytopic":"all","name":"","x":1126,"y":960,"wires":[["1ea951aa.83c1ee"]]},{"id":"8601f12d.7679c","type":"function","z":"78eed68b.1d9708","name":"Day","func":"msg.payload.on = true;\nmsg.payload.bri = 255;\nreturn msg;","outputs":1,"noerr":0,"x":978,"y":928,"wires":[["ca9979b1.332d78"]]},{"id":"4c3bf201.fa7dec","type":"function","z":"78eed68b.1d9708","name":"Night","func":"msg.payload.on = true;\nmsg.payload.bri = 10;\nreturn msg;","outputs":1,"noerr":0,"x":978,"y":992,"wires":[["ca9979b1.332d78"]]},{"id":"da89386e.b9a488","type":"zway-input","z":"78eed68b.1d9708","name":"","server":"264bd5f1.3ef27a","device":"ZWayVDev_zway_7-0-113-7-8-A","device_name":"Fibaro Motion","x":342,"y":992,"wires":[["dae6bd4d.1b34c"],["b236678b.3ad3c8"]]},{"id":"1584ebf8.19cfb4","type":"homekit-bridge","z":"","bridgeName":"Node-Red","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"Node-Red","model":"Default Model","serialNo":"Default Serial Number","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true},{"id":"3c5efaa8.983d86","type":"deconz-server","z":"","name":"Phoscon-GW","ip":"192.168.31.191","port":"80","apikey":"FDCB8BC824","ws_port":"8080","secure":false},{"id":"264bd5f1.3ef27a","type":"zway-server","z":"","name":"Z-Way","ip":"127.0.0.1","port":"80","login":"admin","pass":"3551640"}]
Заключение:
Все ноды с базового набора полезны. Их описание можете почитать в документации и также различные практические примеры можно посмотреть здесь.
Отличная статья, когда закончим обзор всех базовых нод, накидаем примеров автоматизаций, допишем нужные плагины.. Можно считать - жизнь в Ноде Рэд удалась.😀
Для молодых стараемся. 😀
Продолжайте....
Ребят, нужна помощь)
я уже извелся
беру ноду change, делаю как на картинке
https://sprut.ai/static/media/cache/00/42/05/5/2267182/47772/1000x_image.png?1576514407" alt="1000x_image.png?1576514407" />на входе у меня json от датчика затопления сяоми, включенного на mqtt
после этого ченджа ставлю switch
https://sprut.ai/static/media/cache/00/42/05/5/2267182/47773/1000x_image.png?1576514527" alt="1000x_image.png?1576514527" />на дебаге тишина.
после change в дебаг приезжает только msg.payload с данными от датчика.
flow не показывается и switch ничего не отдает.
во всех дебагах выбран "complete msg object"
что я делаю не так?
я хочу затолкать ответ датчика в массив или отдельные переменные, так как данные мне нужны в других вкладках
уже третий день пробую разные варианты, ощущаю себя идиотом