How to preserve the data of a chart node across a restart of Node Red?

I visualize in a Chart Node the data of a climate sensor over a longer period of time.
Unfortunately, every time Node Red is restarted, all data recorded up to that point is lost.
Has anyone already solved this problem and can give me a corresponding example flow?
Many thanks in advance!
Harald

The obvious answer is to use a database.

I do this with Mariadb and the basic Node-red dashboard charts.

Many others use influxdb and grafana to draw the graphs.

If you search the forum you should find many examples.

A simple way to persist the graph info is to use the node-red-contrib-persist nodes.

The output of the chart node is connected to the input of the ā€˜persist inā€™ node.

The ā€˜persist outā€™ node connects to the input of the chart node.
(Along with whatever feeds data to your chart)

Before shutdown, the data will be saved to a file.

or you could use the cache node from uibuilder along with a persistent context store.

Many thanks, this is what I was looking for.

Unfortunately, however, I have now destroyed my Node Red installation: Since the file was not saved in the desired folder, I deleted the configuration of the file and performed a deploy. Now Node Red does not start anymore, because the persistence nodes produce an uncaught exception:

1 Aug 15:25:36 - [red] Uncaught Exception:
1 Aug 15:25:36 - [error] TypeError: Cannot read properties of null (reading 'getMessage')
    at EventEmitter.PersistOutNode.node.restore (/root/.node-red/node_modules/node-red-contrib-persist/persist.js:159:40)
    at EventEmitter.emit (node:events:539:35)
    at Object.start [as startFlows] (/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/flows/index.js:407:12)
nodered.service: Main process exited, code=exited, status=1/FAILURE
nodered.service: Failed with result 'exit-code'.

Do you have any idea how I can get my installation working again?

I have found it: node-red --safe

This flow shows you to save and restore a chart.
https://flows.nodered.org/flow/92920b4fd450bf92a3035e061947daa0

Many thanks. I think I will build on this example as the persistence nodes also throw some other warnings (use of deprecated function).

I have now designed a subflow that solves the problem using SQLite:

Example flow:

[{"id":"0cb6bf1c544ebd85","type":"subflow","name":"Chart Persistence","info":"","category":"","in":[{"x":60,"y":80,"wires":[{"id":"ef3ff83b.aa5008"}]}],"out":[{"x":840,"y":280,"wires":[{"id":"4f8411277831e52e","port":0}]}],"env":[{"name":"Node","type":"str","value":""}],"meta":{},"color":"#DDAA99","status":{"x":840,"y":80,"wires":[{"id":"fa4020ebfee2ed9a","port":0}]}},{"id":"ef3ff83b.aa5008","type":"json","z":"0cb6bf1c544ebd85","name":"","x":170,"y":80,"wires":[["26de10021a1548a7"]]},{"id":"7a999f0bb3f4d802","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"prepared","sql":"INSERT OR REPLACE INTO Node_Data VALUES($Node,$Data)","name":"Write","x":510,"y":80,"wires":[["fa4020ebfee2ed9a"]]},{"id":"26de10021a1548a7","type":"function","z":"0cb6bf1c544ebd85","name":"Set msg.params","func":"if (flow.get(\"initialized\") === true) {\n    msg.params = { \n        \"$Node\": env.get(\"Node\"),\n        \"$Data\": msg.payload \n    }\n    return msg;\n}\nelse\n    return null;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":80,"wires":[["7a999f0bb3f4d802"]]},{"id":"4f8411277831e52e","type":"json","z":"0cb6bf1c544ebd85","name":"","x":730,"y":280,"wires":[[]]},{"id":"6c4202929fcc9b69","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"prepared","sql":"SELECT DATA FROM Node_Data WHERE(NODE=$Node)","name":"Read","x":510,"y":220,"wires":[["cf17623e6f0e211b"]]},{"id":"cf17623e6f0e211b","type":"change","z":"0cb6bf1c544ebd85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0].DATA","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":220,"wires":[["4f8411277831e52e"]]},{"id":"037ab12c9bca1d22","type":"function","z":"0cb6bf1c544ebd85","name":"Set msg.params","func":"msg.params = { \n    \"$Node\": env.get(\"Node\")\n}\nflow.set(\"initialized\",true)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":220,"wires":[["6c4202929fcc9b69"]]},{"id":"fd11c6e044c9d6ce","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"fixed","sql":"CREATE TABLE IF NOT EXISTS Node_Data(NODE TEXT PRIMARY KEY NOT NULL,DATA TEXT NOT NULL)","name":"Create Table","x":330,"y":160,"wires":[["037ab12c9bca1d22"]]},{"id":"fa4020ebfee2ed9a","type":"function","z":"0cb6bf1c544ebd85","name":"Status \"dot\"","func":"msg.payload = {fill:\"green\",shape:\"dot\",text:env.get(\"Node\")}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":80,"wires":[[]]},{"id":"bd3b56346aacbcf1","type":"inject","z":"0cb6bf1c544ebd85","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.1","topic":"","payload":"true","payloadType":"bool","x":170,"y":160,"wires":[["fd11c6e044c9d6ce"]]},{"id":"d98f5a8b0d088b01","type":"sqlitedb","db":"/home/node-red/persistence.sql","mode":"RWC"},{"id":"0b6404af633acaac","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"cd9313eba6a1ec1a","type":"subflow:0cb6bf1c544ebd85","z":"0b6404af633acaac","name":"Chart Persistence Demo","env":[{"name":"Node","value":"Chart Persistence Demo","type":"str"}],"x":630,"y":120,"wires":[["7e36c3ccf9ce0072"]]},{"id":"b045f9e321fcc5b3","type":"inject","z":"0b6404af633acaac","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":0.1,"topic":"random","payload":"true","payloadType":"bool","x":110,"y":120,"wires":[["a50c50c540272816"]]},{"id":"7e36c3ccf9ce0072","type":"ui_chart","z":"0b6404af633acaac","name":"","group":"884daaba08bae0a4","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","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,"className":"","x":430,"y":120,"wires":[["cd9313eba6a1ec1a"]]},{"id":"a50c50c540272816","type":"function","z":"0b6404af633acaac","name":"Random","func":"msg.payload = Math.random()\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":120,"wires":[["7e36c3ccf9ce0072"]]},{"id":"884daaba08bae0a4","type":"ui_group","name":"Chart Persistence Demo","tab":"5dd649e34ebbd68e","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"5dd649e34ebbd68e","type":"ui_tab","name":"Persistence Demo","icon":"dashboard","disabled":false,"hidden":false}]
1 Like

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