V tomto návodu si ukážeme jak pomocí Node-RED přečíst (1) teplotu z našich webových stránek, (2) měření provedená ethernetovým senzorem TH2E a (3) teploty ze dvou teploměrů TQS4 připojených pomocí RS485.
Seriál o Node-REDu |
1. čtení dat z teploměrů přes Ethernet a RS485 |
2. zápis dat do Google Tabulky |
3. automatizace s I/O moduly Quido - protokol Modbus |
4. I/O moduly Quido - protokol Spinel |
Node-RED je velmi schopný automatizační nástroj pro zpracování a zobrazení veličin a stavů. Může být "mozkem" malé automatizace nebo řízení. Umožňuje propojit nejrůznější zařízení a systémy a zpracovávat data z nich. Jde o tzv. programování řízené událostmi, takže je předurčeno proto, aby událost jako sepnutí kontaktu, dosažení teploty, přijetí zprávy nebo paketu apod. spustila jednu nebo několik dalších událostí, vyhodnocení, databázových operací atd.
Pomocí grafického rozhraní ve webovém prohlížeči si v uživatel může snadno nadefinovat celou automatizaci a pak sledovat jak pěkně vše funguje, nechat si posílat e-maily o mimořádnostech, apod. Node-RED je možné provozovat na různých systémech - na Windows, na Linuxu a tedy i na oblíbeném mini PC Raspberry Pi.
Node-RED v uvedených příkladech běží na Raspberry Pi 2B. V příkladech počítáme s tím, že Raspberry Pi je připojeno k počítačové síti Ethernet (resp. k WiFi, pokud máte Raspberry Pi Zero W, Raspberry Pi 3 nebo novější).
Pro instalaci Node-RED na Rapberry Pi 3 doporučujeme tento návod od tvůrců Node-RED. Případně pokud chcete vyzkoušet Node-RED na svém PC s Windows, návod je zde.
Po instalaci je Node-RED dostupný ve výchozím nastavení na adrese počítače a portu 1880. Tedy například na http://192.168.1.254:1880. Pokud jste nainstalovali Node-RED do Windows, můžete použít adresu http://localhost:1880.
Nejjednodušší způsob jak si vyzkoušet čtení teploty je sledovat teploměr na našem webu. Strojově čitelná hodnota je ve formátu XML na této adrese: https://cdn.papouch.com/temp.xml Skript generuje podobné XML, jako náš ethernetový teploměr TME. Obsah souboru vypadá takto:
<root xmlns="http://www.papouch.com/xml/TME/act"> <sns id="1" type="4" location="U Papoucha" status="0" hi="0" lo="0" unit="0" val="69" min="-9999" max="9999" /> <status location="U Papoucha" mac="" /> </root>
V tagu sns, v atributu val je aktuálně naměřená venkovní teplota vynásobená deseti. V příkladu je hodnota 69, což znamená teplotu 6,9 °C. Na následujícím obrázku je grafická podoba příkladu čtení teploty a výstupu do konzole v rozhraní Node-RED:
Základní příklad čtení teploty z dat ve formátu XML pomocí Node-RED
Příklad z obrázku (tzv. flow) si můžete velice snadno vyzkoušet i ve svém Node-RED. Stačí následující kód zkopírovat do schránky a vložit do Vašeho Node-RED pomocí Menu > Import > Clipboard.
[{"id":"1a949f52.085419","type":"inject","z":"4fb0c5c4.cb66cc","name":"Web","topic":"TH2E","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":"2","x":650,"y":340,"wires":[["2cc06013.ed74e"]]},{"id":"2cc06013.ed74e","type":"http request","z":"4fb0c5c4.cb66cc","name":"GET Pap","method":"GET","ret":"txt","url":"https://cdn.papouch.com/temp.xml","tls":"","x":800,"y":340,"wires":[["3a66564d.8296fa"]]},{"id":"3a66564d.8296fa","type":"xml","z":"4fb0c5c4.cb66cc","name":"to XML","property":"payload","attr":"","chr":"","x":950,"y":340,"wires":[["78ea4c6e.b541d4"]]},{"id":"78ea4c6e.b541d4","type":"function","z":"4fb0c5c4.cb66cc","name":"Get values","func":"msg.topic = \"WEB\";\nmsg.payload = parseFloat(msg.payload.root.sns[0].$.val) / 10;\n\nreturn msg;","outputs":1,"noerr":0,"x":810,"y":420,"wires":[["44984944.e3447"]]},{"id":"44984944.e3447","type":"debug","z":"4fb0c5c4.cb66cc","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":970,"y":420,"wires":[]}]
Jednotlivé nody mají každý svoje parametry, případně obsahují kód napsaný v programovacím jazyce JavaScript. Poklepáním na každý z nodů se otevře editace jeho parametrů.
Změny provedené na pracovní ploše Node-RED je potřeba uždy uložit červeným tlačítkem Deploy vpravo nahoře na pracovní ploše.
TH2E je ethernetový senzor, který umí měřit teplotu a vlhkost a počítat rosný bod. Aktuální údaje jsou k dispozici v XML souboru fresh.xml. My chceme pomocí Node-RED na řádcích sns přečíst atributy status (stav naměřené hodnoty) a val (naměřená hodnota).
<root xmlns="http://www.papouch.com/xml/th2e/act"> <sns id="1" type="1" status="0" unit="0" val="0.8" w-min="" w-max="" e-min-val="-14.9" e-max-val="37.0" e-min-dte="01/11/2017 07:30:35" e-max-dte="06/30/2019 17:10:59" /> <sns id="2" type="2" status="0" unit="3" val="77.5" w-min="" w-max="" e-min-val="17.3" e-max-val="100.0" e-min-dte="06/30/2019 17:20:34" e-max-dte="10/15/2015 22:15:22" /> <sns id="3" type="3" status="0" unit="0" val="-2.7" w-min="" w-max="" e-min-val="-16.5" e-max-val="22.2" e-min-dte="02/27/2018 15:02:52" e-max-dte="08/03/2017 18:49:53" /> <status frm="1" location="U Papoucha" time="12/30/2019 10:53:23" /> </root>
Na následujícím obrázku je grafická podoba příkladu čtení hodnot z TH2E a výstupu naměřených údajů do konzole (debug):
Příklad čtení hodnot ve formátu XML z TH2E pomocí Node-RED
Příklad si také můžete vyzkoušet vložením následujícího kódu do Vašeho Node-RED přes Menu > Import > Clipboard.
[{"id":"4fb0c5c4.cb66cc","type":"tab","label":"TH2E","disabled":false,"info":""},{"id":"1a949f52.085419","type":"inject","z":"4fb0c5c4.cb66cc","name":"Run!","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":"2","x":210,"y":80,"wires":[["2cc06013.ed74e"]]},{"id":"2cc06013.ed74e","type":"http request","z":"4fb0c5c4.cb66cc","name":"GET TH2E","method":"GET","ret":"txt","url":"http://192.168.1.123/fresh.xml","tls":"","x":370,"y":80,"wires":[["3a66564d.8296fa"]]},{"id":"3a66564d.8296fa","type":"xml","z":"4fb0c5c4.cb66cc","name":"to XML","property":"payload","attr":"","chr":"","x":530,"y":80,"wires":[["78ea4c6e.b541d4"]]},{"id":"78ea4c6e.b541d4","type":"function","z":"4fb0c5c4.cb66cc","name":"Get values","func":"// Nody sns z XML si vložíme do samostatné proměnné (pole)\n// Veličiny v poli jsou vždy v pořadí teplota, vlhkost, rosný bod\nlet sns = msg.payload.root.sns;\n\n// Pokud hodnota teploty není aktuální, vyhlásíme chybu a ukončíme zpracování. (Není-li dostupná teplota, nejsou dostupné ani ostatní veličiny.)\nif (sns[0].$.status != \"0\") {\n node.error(`Měření není dostupné!`);\n return;\n}\n\n// Vytvoříme si pracovní objekt values a vložíme do nej teplotu\nlet values = {};\nvalues.temperature = parseFloat(sns[0].$.val);\n\n// Pokud je dostupná vlhkost, vložíme ji do objektu values\nif (sns[1].$.status == \"0\") values.humidity = parseFloat(sns[1].$.val);\n\n// Pokud je dostupný rosný bod, vložíme jej do objektu values\nif (sns[2].$.status == \"0\") values.dewpoint = parseFloat(sns[2].$.val);\n\n// Naplníme výstupní objekt msg zjištěnými hodnotami a \"pošleme dál\"\nmsg.payload = values;\nmsg.topic = \"TH2E values\";\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":160,"wires":[["44984944.e3447"]]},{"id":"44984944.e3447","type":"debug","z":"4fb0c5c4.cb66cc","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":490,"y":160,"wires":[]}]
K vyzkoušení tohoto příkladu budete potřebovat vlastní senzor TH2E. Možná také budete potřebovat změnit IP adresu teploměru v nodu GET TH2E. Stačí na něj poklepat a změnit IP adresu v položce URL.
Tip: Chcete, aby se čtení provádělo automaticky v nastaveném intervalu? Poklepáním otevřete nastavení nodu Run!, zaškrtněte Inject once... a u položky Repeat vyberte požadovaný interval, podobně jako na následujícím obrázku. My máme na obrázku nastaveno opakování po deseti sekundách.
Řetězec za tímto nodem se provede dvě sekundy po spuštění Node-RED a pak každých deset sekund
Teploměr TQS4 komunikuje přes RS485. V případě Node-RED na Windows to není problém - stačí použít převodník USB-RS485 nebo převodník RS232-RS485 a můžeme komunikovat. Na Raspberry Pi sice průmyslová sběrnice RS485 není, ale také se to dá snadno vyřešit:
Mezi univerzálními digitálními piny na Raspberry je sériový port v úrovních TTL. Ten lze převést na sběrnici RS485 některým z následujících způsobů:
Zapojení tedy máme vyřešené. Jakým protokolem budeme hodnoty z teploměru číst? V případě teploměru TQS4 budeme používat ke čtení protokol Modbus RTU. Do tohoto protokolu je potřeba teploměr přepnout buď programem ModbusConfigurator (pro Windows) nebo snadněji zkratováním propojky CFG přímo na elektronice teploměru. Když je při zapnutí teploměru tato propojka zkratována, teploměr blikne po zapnutí červeně, což znamená, že očekává komunikaci v protokolu Modbus RTU.
Pokud budete chtít komunikovat s více teploměry najednou, je potřeba každému z nich nastavit jinou komunikační adresu (id) výše zmíněným programem ModbusConfigurator (pro Windows). Z výroby má totiž každý teploměr nastavenou adresu "1" (49 dekadicky, 0x31 hexadecimálně).
Node-RED ve výchozím stavu neobsahuje funkčnost pro komunikaci protokolem Modbus. Funkce (nody) pro komunikaci Modbusem jdou velice snadno doplnit. Postup je následující:
V následujícím příkladu si ukážeme jak pomocí Modbusu RTU číst teplotu ze dvou připojených teploměrů TQS4.
Teploměr TQS4 má teplotu k dispozici v Input Registeru ve druhém registru (adresa 1). To, zda je údaj v tomto registru platný jde poznat podle registru status (adresa 0). Budeme tedy číst dva registry od adresy 0. (Detailní popis Modbusu v TQS4 je uveden v dokumentaci.) Input Register budeme číst pomocí funkce Read input register s funkčním kódem 4.
Naše řešení je vidět na následujícím obrázku.
Flow s příkladem čtení více teploměrů TQS4 přes Modbus RTU pomocí modbus-flex-getter v Node-RED
Jak příklad funguje?
Zde je kód příkladu pro import do Vašeho Node-RED přes Menu > Import > Clipboard:
[{"id":"5646afe8.0dccc","type":"modbus-flex-getter","z":"4fb0c5c4.cb66cc","name":"RTU","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"3912e8f2.e5dad8","useIOFile":false,"ioFile":"","useIOForPayload":false,"x":650,"y":160,"wires":[["d5a2adc6.942fa","8aa25129.1df158"],[]]},{"id":"f502564b.b827a8","type":"function","z":"4fb0c5c4.cb66cc","name":"Prepare","func":"let unitid = 49; // Jako první budeme číst senzor s id 49 = 0x31 = \"1\"\n\nif (msg.input) { // Jde o další senzor v pořadí\n if (msg.input.queueUnitId) {\n unitid = parseInt(msg.input.queueUnitId) + 1;\n }\n}\n \nif (unitid > 50) return; // Poslední id, které chceme číst je 50\n\nmsg.payload = { \n 'fc': 4, // Čteme Input register\n 'unitid': unitid, // Modbus id senzoru, který chceme číst\n 'address': 0, // Chceme číst od registru s adresou 0 (první registr)\n 'quantity': 2 // Budeme číst dva registry (status a teplotu)\n};\n\nreturn msg;","outputs":1,"noerr":0,"x":500,"y":200,"wires":[["5646afe8.0dccc"]]},{"id":"b0fa8ba2.05eb18","type":"inject","z":"4fb0c5c4.cb66cc","name":"TQS4","topic":"TQS4","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":330,"y":200,"wires":[["f502564b.b827a8"]]},{"id":"d5a2adc6.942fa","type":"function","z":"4fb0c5c4.cb66cc","name":"Convert","func":"let TqsStatus = msg.payload[0]; // První čtený registr\nlet TqsTempValue = msg.payload[1]; // Druhý čtený registr\n\nmsg.topic = msg.input.payload.unitid;\n\n// Pokud je ve status registru 0, je vše ok a druhý registr obsahuje platnou teplotu\nif (TqsStatus === 0) {\n msg.payload = Int2Float(TqsTempValue);\n} else {\n node.error(`Měření není dostupné!`);\n return;\n}\n\nreturn msg;\n\n\n// Převede číslo z formátu signed integer na desetinné číslo\nfunction Int2Float(v) {\n \n let t;\n \n if (v > 32767) t = v - 65536;\n\telse t = v;\n\t\n\tt = t / 10;\n\t\n\treturn t;\n\t\n}","outputs":1,"noerr":0,"x":800,"y":140,"wires":[["b9c290cb.81cf38"]]},{"id":"8aa25129.1df158","type":"delay","z":"4fb0c5c4.cb66cc","name":"","pauseType":"delay","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":810,"y":200,"wires":[["f502564b.b827a8"]]},{"id":"b9c290cb.81cf38","type":"join","z":"4fb0c5c4.cb66cc","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":950,"y":140,"wires":[["40be4d5b.a2d624"]]},{"id":"40be4d5b.a2d624","type":"debug","z":"4fb0c5c4.cb66cc","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1090,"y":140,"wires":[]},{"id":"3912e8f2.e5dad8","type":"modbus-client","z":"","name":"","clienttype":"serial","bufferCommands":false,"stateLogEnabled":false,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyAMA0","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"1000","unit_id":"","commandDelay":1,"clientTimeout":1000,"reconnectTimeout":3000}]
V následující části si ukážeme jak naměřená data odeslat do Google Tabulky...
Seriál o Node-REDu |
1. čtení dat z teploměrů přes Ethernet a RS485 |
2. zápis dat do Google Tabulky |
3. automatizace s I/O moduly Quido - protokol Modbus |
4. I/O moduly Quido - protokol Spinel |