Extracting data from weather station

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)

Hi, welcome to the forum @JdeV987.
You are much more likely to get a response to your question if your flow (above) did not contain nodes that are not included in a default node-RED install, because forum members would need to install & config them before importing your flow.
For example, replace the influxdb node with a debug node and title it 'influxdb' so we understand how your flow works.

Ok you can set the mqtt node to output a parse json object
then you only need to extract the raw data and parse it.
here is an example

[{"id":"c773303.7246cd","type":"function","z":"e40961b1.ad649","name":"Parse message","func":"msg.payload.raw = msg.payload.raw.split(\";\"); // split raw data\nfor(let i=3; i < msg.payload.raw.length-1; i++){ // loop through split data fro index 3 to end-1\n    let part = msg.payload.raw[i].split(\"=\"); //split each item at =\n    msg.payload[part[0].toLowerCase()] = part[1]; //creat payload values\n}\nmsg.payload.humidity = Number(msg.payload.hum); // convert from string\nmsg.payload.name = msg.payload.raw[2];\nmsg.payload.p1=msg.payload.raw[0];\nmsg.payload.p2=msg.payload.raw[1];\n\n\nvar global_name = \"rainstat\";   // Name of the global variable\n\n// your code for rain data not sure this works\nvar rainstat = global.get(global_name) || 0;\n\nmsg.payload.RAINRATE = 0;\n\nif (msg.payload.rain!==undefined) {\n    msg.payload.rain = parseInt(((msg.payload.rain, 16) /10)-1);\n    msg.payload.RAINRATE = msg.payload.rain - rainstat;\n    global.set(global_name,msg.payload.rain);\n} else {\n    msg.payload.rain=0;\n}\n\nreturn msg;\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":322,"y":105,"wires":[["d98925d6.7c552","508256b3.31cd68"]]},{"id":"d98925d6.7c552","type":"debug","z":"e40961b1.ad649","name":"Parse","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":600,"y":120,"wires":[]},{"id":"508256b3.31cd68","type":"function","z":"e40961b1.ad649","name":"Weather Station","func":"msg.payload = {\n    name: msg.payload.name,\n    temp: msg.payload.TEMP,\n    wind: msg.payload.WINSP,\n    gust: msg.payload.WINGS,\n    direction: msg.payload.WINDIR,\n    rain: msg.payload.RAIN,\n    rainrate: msg.payload.RAINRATE,\n    humidity: msg.payload.humidity,\n    battery: msg.payload.BAT\n}\nmsg.topic=\"rflink\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":560,"y":240,"wires":[["f11090af.68455"]]},{"id":"fe1dcc9.31ead3","type":"inject","z":"e40961b1.ad649","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":"json","x":97,"y":142,"wires":[["c773303.7246cd","f9901742.eef988"]]},{"id":"a8e28186.510a6","type":"mqtt in","z":"e40961b1.ad649","name":"RF","topic":"RF/#","qos":"0","datatype":"json","broker":"3feb27f3.671af8","x":76,"y":81,"wires":[["c773303.7246cd","f9901742.eef988"]]},{"id":"f11090af.68455","type":"debug","z":"e40961b1.ad649","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":760,"y":240,"wires":[]},{"id":"f9901742.eef988","type":"debug","z":"e40961b1.ad649","name":"RF-info","active":false,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":302,"y":55,"wires":[]},{"id":"3feb27f3.671af8","type":"mqtt-broker","name":"Local MQTT","broker":"localhost","port":"1883","clientid":"","usetls":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","willTopic":"","willQos":"0","willPayload":""}]

Good tip, I updated my posted flow without Influxdb.

Thank you E1cid, that is the part I did not know about, to set the mqtt node to output a parse json object. Lesson 1 learned . :wink:

Now it makes sense. :+1:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.