I just started with Node-Red and Grafana.
My 1st project is to intercept the radio signals from a Maplin 433MHz weather station and then to display it in Grafana via Node-Red.
I use a RFlink gateway to intercept the signals and transmit it via Wi-Fi for a Raspberry Pi to receive it.
The raw data that comes into Node-Red looks like this:
{"raw":"20;31;DKW2012;ID=0086;TEMP=0071;HUM=74;WINSP=0031;WINGS=0049;RAIN=4ac1;WINDIR=0014;BAT=OK;\r","TEMP":11.3,"WINSP":4.9,"WINGS":7.3,"RAIN":1913.7,"WINDIR":"NW","BAT":"OK"}
My complete flow looks like this:
[
{
"id": "c705d17.53c6bb",
"type": "function",
"z": "ae91e478.8a40b",
"name": "Parse message",
"func": "\n\nvar msg433 = {};\nmsg.payload = msg.payload.replace(/(\\r\\n|\\n|\\r)/gm,\"\");\nvar parts433 = msg.payload.split(\";\");\n\nmsg433.p1 = parts433[0];\nmsg433.p2 = parts433[1];\nmsg433.name = parts433[2];\nfor (var i=3; i<parts433.length; i++) {\n var keyvalue = parts433[i].split(\"=\");\n if (keyvalue.length===2) {\n msg433[keyvalue[0]] = keyvalue[1];\n }\n}\n\nmsg.msg433 = msg433;\nmsg.topic=\"rflink\";\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 340,
"y": 140,
"wires": [
[
"2aac7767.31dc68",
"3941a343.c334b4"
]
]
},
{
"id": "2aac7767.31dc68",
"type": "function",
"z": "ae91e478.8a40b",
"name": "TEMP conversion",
"func": "if (msg.msg433.TEMP!==undefined) {\n if (parseInt(msg.msg433.TEMP, 16) >= 0x8000) {\n msg.msg433.TEMP = (parseInt(msg.msg433.TEMP, 16) & 0x7FFF) / 10 * -1;\n } else {\n msg.msg433.TEMP = parseInt(msg.msg433.TEMP, 16) / 10;\n }\n} else msg.msg433.TEMP=0.0;\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.TEMP });\nreturn msg;\n\n// {\"raw\":\"20;31;DKW2012;ID=0086;TEMP=0071;HUM=74;WINSP=0031;WINGS=0049;RAIN=4ac1;WINDIR=0014;BAT=OK;\n// \\r\",\"TEMP\":11.3,\"WINSP\":4.9,\"WINGS\":7.3,\"RAIN\":1913.7,\"WINDIR\":\"NW\",\"BAT\":\"OK\"}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 347,
"y": 213,
"wires": [
[
"8125f9c2.29a0f8"
]
]
},
{
"id": "8125f9c2.29a0f8",
"type": "function",
"z": "ae91e478.8a40b",
"name": "HUM conversion",
"func": "if (msg.msg433.HUM!==undefined) {\n msg.msg433.HUM = parseInt(msg.msg433.HUM, 10);\n}\nelse msg.msg433.HUM=0;\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.HUM });\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 298,
"y": 415,
"wires": [
[
"a5315cf7.21785"
]
]
},
{
"id": "a5315cf7.21785",
"type": "function",
"z": "ae91e478.8a40b",
"name": "ID conversion",
"func": "if (msg.msg433.ID!==undefined) {\n msg.msg433.ID = parseInt(msg.msg433.ID, 16);\n}\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 299,
"y": 474,
"wires": [
[
"42fc68ca.e4c"
]
]
},
{
"id": "42fc68ca.e4c",
"type": "function",
"z": "ae91e478.8a40b",
"name": "RAIN conversion",
"func": "var global_name = \"rainstat\"; // Name of the global variable\n\nvar rainstat = global.get(global_name);\n\n msg.msg433.RAINRATE = 0;\n\nif (msg.msg433.RAIN!==undefined) {\n msg.msg433.RAIN = parseInt(((msg.msg433.RAIN, 16) /10)-1);\n msg.msg433.RAINRATE = msg.msg433.RAIN - rainstat;\n global.set(global_name,msg.msg433.RAIN);\n} else msg.msg433.RAIN=0;\nnode.status({fill:\"blue\",shape:\"ring\",text: rainstat });\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 310,
"y": 527,
"wires": [
[
"198ed92d.df94e7"
]
]
},
{
"id": "198ed92d.df94e7",
"type": "function",
"z": "ae91e478.8a40b",
"name": "WINSP conversion",
"func": "if (msg.msg433.WINSP!==undefined) {\n msg.msg433.WINSP = parseInt(msg.msg433.WINSP, 16) /10;\n} else msg.msg433.WINSP=0;\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.WINSP });\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 311,
"y": 589,
"wires": [
[
"ab68499c.d97d4"
]
]
},
{
"id": "ab68499c.d97d4",
"type": "function",
"z": "ae91e478.8a40b",
"name": "WINGS conversion",
"func": "if (msg.msg433.WINGS!==undefined) {\n msg.msg433.WINGS = parseInt(msg.msg433.WINGS , 16)/10;\n}\nelse msg.msg433.WINGS=0;\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.WINGS });\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 311,
"y": 659,
"wires": [
[
"12e2916f.b29a2f"
]
]
},
{
"id": "12e2916f.b29a2f",
"type": "function",
"z": "ae91e478.8a40b",
"name": "WINDIR conversion",
"func": "\nif (msg.msg433.WINDIR!==undefined) {\n msg.msg433.WINDIR = parseInt(msg.msg433.WINDIR , 10) * 22.5;\n}\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.WINDIR });\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 314,
"y": 725,
"wires": [
[
"31a5e697.a66362",
"f296423f.cce838"
]
]
},
{
"id": "d3bf32e5.fea75",
"type": "change",
"z": "ae91e478.8a40b",
"name": "Set Topic",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "rflink",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 480,
"y": 816,
"wires": [
[
"74a03456.6204fc",
"9ce7f346.a88c4"
]
]
},
{
"id": "74a03456.6204fc",
"type": "function",
"z": "ae91e478.8a40b",
"name": "Weather Station",
"func": "msg.payload = {\n name: msg.msg433.name,\n temp: msg.msg433.TEMP,\n wind: msg.msg433.WINSP,\n gust: msg.msg433.WINGS,\n direction: msg.msg433.WINDIR,\n rain: msg.msg433.RAIN,\n rainrate: msg.msg433.RAINRATE,\n humidity: msg.msg433.HUM,\n battery: msg.msg433.BAT\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 656.3671875,
"y": 815.6953125,
"wires": [
[
"76c413cc.e2211c"
]
]
},
{
"id": "31a5e697.a66362",
"type": "function",
"z": "ae91e478.8a40b",
"name": "BAT conversion",
"func": "if (msg.msg433.BAT === undefined) msg.msg433.BAT=\"\";\nnode.status({fill:\"blue\",shape:\"ring\",text: msg.msg433.BAT });\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 299.3671875,
"y": 813.6953125,
"wires": [
[
"d3bf32e5.fea75"
]
]
},
{
"id": "15a492a8.68926d",
"type": "inject",
"z": "ae91e478.8a40b",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"raw\":\"20;35;DKW2012;ID=0086;TEMP=0071;HUM=74;WINSP=0031;WINGS=0049;RAIN=4ac1;WINDIR=0014;BAT=LOW;\\r\",\"TEMP\":11.3,\"WINSP\":4.9,\"WINGS\":7.3,\"RAIN\":1913.7,\"WINDIR\":\"NW\",\"BAT\":\"LOW\"}",
"payloadType": "str",
"x": 115,
"y": 177,
"wires": [
[
"c705d17.53c6bb"
]
]
},
{
"id": "9ce7f346.a88c4",
"type": "debug",
"z": "ae91e478.8a40b",
"name": "RF-info-1",
"active": false,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "payload",
"statusType": "auto",
"x": 650,
"y": 876,
"wires": []
},
{
"id": "3c631c25.04cb94",
"type": "mqtt in",
"z": "ae91e478.8a40b",
"name": "RF",
"topic": "RF/#",
"qos": "0",
"datatype": "auto",
"broker": "3feb27f3.671af8",
"nl": false,
"rap": false,
"x": 94,
"y": 116,
"wires": [
[
"c705d17.53c6bb",
"82dc4967.bd515"
]
]
},
{
"id": "82dc4967.bd515",
"type": "debug",
"z": "ae91e478.8a40b",
"name": "RF-info",
"active": false,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 320,
"y": 90,
"wires": []
},
{
"id": "3941a343.c334b4",
"type": "debug",
"z": "ae91e478.8a40b",
"name": "Parse",
"active": false,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 618,
"y": 155,
"wires": []
},
{
"id": "f296423f.cce838",
"type": "debug",
"z": "ae91e478.8a40b",
"name": "Wind",
"active": false,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 540,
"y": 716,
"wires": []
},
{
"id": "76c413cc.e2211c",
"type": "debug",
"z": "ae91e478.8a40b",
"name": "ws",
"active": true,
"tosidebar": true,
"console": true,
"tostatus": true,
"complete": "true",
"targetType": "full",
"statusVal": "payload",
"statusType": "auto",
"x": 870,
"y": 820,
"wires": []
},
{
"id": "3feb27f3.671af8",
"type": "mqtt-broker",
"name": "Local MQTT",
"broker": "localhost",
"port": "1883",
"clientid": "",
"usetls": false,
"protocolVersion": 4,
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
}
]
I can leave everything as it is, but I want to learn more about Node-Red (java script) and for me the best way is to learn from examples.
Thank you for any advice.
(Original flow designed by Csongor Varga: His YT channel)