This article shows how to log sensor data to a file on the Raspberry PLC with Node-RED and the flogger node, then read that file and display the data as a chart in the Node-RED Dashboard. This two-step approach lets you capture data over a period of time and review it later without needing a remote database.
Requirements
- Raspberry PLC with Node-RED installed (installation guide)
- Paquete Node-RED Dashboard (
node-red-dashboard) - SSH access or a monitor and keyboard connected to the PLC (SSH guide)
Storing data with the flogger node
Install the flogger node from the Node-RED Manage Palette menu, or from the terminal:
npm install node-red-contrib-flogger
After installing it, drag a flogger node onto the flow. In the node settings, enter the absolute path of the log file in the Log Config field and the filename in the Logfile field. In the log section select "Select object > msg.payload". Each incoming value will be written to the file in this format:
{"time":"2022/09/09 08:52:19","level":"INFO","var":"msg.payload","message":24}Place before the flogger node whichever node produces the value you want to log (a pin node, a function node, or similar). In the example below, a function node increments a counter by 1 every second:
[{"id":"3a929739eb41cb12","type":"function","z":"9f1476fcd060809d","name":"","func":"var num = flow.get('num') | 0;\nmsg.payload = num;\nflow.set('num', num + 1);\nreturn msg;","outputs":1,"noerr":0,"initialize":"flow.set('num', 0);\n","finalize":"","libs":[],"x":600,"y":240,"wires":[[]]},{"id":"f4170ac623623680","type":"inject","z":"9f1476fcd060809d","name":"","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":450,"y":240,"wires":[["3a929739eb41cb12"]]}]Deploy the flow and let it run for a few minutes to collect data. Stop it when you have enough rows in the file.
Reading the file and building the chart
To display the logged data, create a second flow with the following nodes in order: inject > read file > function (parse) > join > function (format) > chart.
Configure the read file node with the absolute path of the log file and set Output to "a msg per line".
Add a function node next to parse each JSON line and extract x (time) and y (value):
try {
msg = JSON.parse(msg.payload);
msg.payload = {x: msg.time, y: msg.message};
return msg;
} catch (err) {
return msg;
}Add a join node configured to build an array from all incoming messages (mode: manual, build: array, count: leave blank to collect all).
Add a second function node to format the array for the chart node:
msg.payload = [{
"series": ["Counter"],
"data": [msg.payload],
"labels": [""]
}];
return msg;Finally, connect a node-red-dashboard chart node and configure it to your preferences. Deploy the flow and trigger the inject node. The Dashboard will display the logged values as a line chart.
The complete flow JSON ready to import:
[{"id":"9778be14.2a9f4","type":"file in","z":"9f1476fcd060809d","name":"Read file","filename":"path/to/file","filenameType":"str","format":"lines","chunk":false,"sendError":false,"allProps":false,"x":360,"y":380,"wires":[["15397051.3f513"]]},{"id":"15397051.3f513","type":"function","z":"9f1476fcd060809d","name":"","func":"try {\n msg = JSON.parse(msg.payload);\n msg.payload = { x: msg.time, y: msg.message };\n return msg;\n} catch (err) {\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":380,"wires":[["b8953dea.692a5"]]},{"id":"b8953dea.692a5","type":"join","z":"9f1476fcd060809d","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"x":670,"y":380,"wires":[["37a6c7e0.ee0df8"]]},{"id":"37a6c7e0.ee0df8","type":"function","z":"9f1476fcd060809d","name":"","func":"msg.payload = [{\n \"series\": [\"Counter\"],\n \"data\": [msg.payload],\n \"labels\": [\"\"]\n}];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":800,"y":380,"wires":[["e0bb31c9.d2379"]]},{"id":"e0bb31c9.d2379","type":"ui_chart","z":"9f1476fcd060809d","name":"","group":"d4c392ad32a37c94","order":1,"width":0,"height":0,"label":"Chart","chartType":"line","legend":"true","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":true,"ymin":"0","ymax":"40","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"x":950,"y":380,"wires":[[]]},{"id":"e4243650d81af7d5","type":"inject","z":"9f1476fcd060809d","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":380,"wires":[["9778be14.2a9f4"]]},{"id":"d4c392ad32a37c94","type":"ui_group","name":"Chart","tab":"bce747bd77dec32e","order":1,"disp":true,"width":19,"collapse":false},{"id":"bce747bd77dec32e","type":"ui_tab","name":"Logs","icon":"dashboard","disabled":false,"hidden":false}]
Store data and display it on Node-RED Dashboard with Raspberry PLC