Hi all,
First of all, what a great forum this is. a lot of helpfull people. I lost count of the number of times I have found my solutions here. Awesome.
Now I face some an issue which I have yet to solve or find a good working solution for here. Hopefully this changes after this first post My first post.
What am I trying to do.
I am trying to visualize some data in bar charts. To process the data correctly, I am making use of this contrib >> bar-chart-data <<
It generates an array of data, with label, series, data.
I have 2 of these nodes which produces 2 separate arrays (different data). In a function I combine the two results and plot them into 1 chart. This works quite nice.
The problem I am facing:
When I reboot, chart empty. Ofcourse, I expected this.
The output / result of the chart I feed into a global variable which I store in "file".
Normally this function works fine. I use it in different places with no issues.
But the problem I face:
- when I reboot, after injecting the stored data into the chart (this works), then the BarChart node is starting to produce new values again into the Chart. But the bar chart node is not aware of the history, so the history is then wiped again and the chart starts new from that moment.
- when I reboot, after injecting the stored data into the BarChart node, the output of the bar chart is not as expected. It puts "NaN" at the current time(label) in the data field. After this the bar chart does not recover anymore.
I have been experimenting with JSON to get rid of the NaN by replacing it with '0', but without succes. You can still see this in the flow directly below. But this part is WIP.
This is the code for the combined array chart. It DOES work, only the store/restore function does not.
[
{
"id": "1c223a510a8ec72d",
"type": "group",
"z": "ed155b604642d354",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"cff31036dc296d8d",
"d8e8398aee81f6d9",
"abb3add343d1bea2",
"41bc927c7f5116b1",
"757d35eee93ec9e7",
"2391637fadbbf190",
"7629b6d3d87712ff",
"e9d6a960b09e05b8",
"04b73283ee604dc3",
"9863257fecbb7ee9",
"2e566db9a4542376",
"11df84f0b8499381",
"ab16835d95c2c933",
"5f083401791b752a",
"8564c26fce347ddc",
"39f46b5fe56dc0a6",
"e48537c319b7f2ca",
"5e60c25489fc6f98",
"74f840e183c2ca78",
"e6ea853dc5ace9bb"
],
"x": 54,
"y": 819,
"w": 1672,
"h": 402
},
{
"id": "cff31036dc296d8d",
"type": "bar-chart-data",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "bar-chart-data degreedays-31d",
"x_interval": "days",
"x_size": "31",
"unit": "",
"precision": "2",
"is_meter_reading": "False",
"agg_by": "avg",
"x": 630,
"y": 940,
"wires": [
[
"ab16835d95c2c933"
]
]
},
{
"id": "d8e8398aee81f6d9",
"type": "bar-chart-data",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "bar-chart-data kwh-31d",
"x_interval": "days",
"x_size": "31",
"unit": "",
"precision": 2,
"is_meter_reading": "False",
"agg_by": "sum",
"x": 610,
"y": 900,
"wires": [
[
"e48537c319b7f2ca"
]
]
},
{
"id": "abb3add343d1bea2",
"type": "ui_chart",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"group": "87be08e6a82ef6a0",
"order": 8,
"width": 0,
"height": 0,
"label": "DegreeDays vs Power consumption",
"chartType": "bar",
"legend": "true",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": 1,
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#d62728",
"#aec7e8",
"#98df8a",
"#d62728",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"className": "",
"x": 1360,
"y": 1100,
"wires": [
[
"9863257fecbb7ee9"
]
]
},
{
"id": "41bc927c7f5116b1",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Store information kwh_31d",
"func": "var myArray4 = msg.payload;\nglobal.set(\"kwh_31d\", myArray4,\"file\");\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1580,
"y": 900,
"wires": [
[]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "757d35eee93ec9e7",
"type": "inject",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"props": [
{
"p": "topic",
"vt": "str"
}
],
"repeat": "900",
"crontab": "",
"once": false,
"onceDelay": "0.1",
"topic": "trigger",
"x": 180,
"y": 1080,
"wires": [
[
"2391637fadbbf190"
]
]
},
{
"id": "2391637fadbbf190",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "DATA (kWh + DegreeDays) Chart Creation",
"func": "var myArray1 = global.get(\"kwh_31d\",\"file\");\nvar myArray2 = global.get(\"degreedays_31d\",\"file\");\nlet msg1={}, msg2={};\nmsg1.payload = myArray1;\nmsg2.payload = myArray2;\n\nvar varlabels = msg1.payload[0].labels;\nvar varkwh_data = msg1.payload[0].data[0];\nvar vargraaddagen_data = msg2.payload[0].data[0];\nvar m={};\n m.labels = varlabels;\n m.series = ['DegreeDays (°C)', 'Energy consumption HEAT (kWh)'];\n m.data = [vargraaddagen_data, varkwh_data];\n\nreturn {payload:[m]};\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 430,
"y": 1080,
"wires": [
[
"5f083401791b752a"
]
],
"outputLabels": [
"graaddagen_calc"
]
},
{
"id": "7629b6d3d87712ff",
"type": "link in",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"links": [
"2064b5a11ffc43b3"
],
"x": 115,
"y": 940,
"wires": [
[
"cff31036dc296d8d"
]
]
},
{
"id": "e9d6a960b09e05b8",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Store information degreedays_31d",
"func": "var myArray5 = msg.payload;\nglobal.set(\"degreedays_31d\", myArray5,\"file\");\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1560,
"y": 940,
"wires": [
[]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "04b73283ee604dc3",
"type": "inject",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "RESET",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "[ ]",
"payloadType": "json",
"x": 150,
"y": 1180,
"wires": [
[
"abb3add343d1bea2"
]
]
},
{
"id": "9863257fecbb7ee9",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Store information",
"func": "\nvar myArray6 = msg.payload;\nglobal.set(\"barchart_kwh_degreedays_31d\", myArray6,\"file\");\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1610,
"y": 1100,
"wires": [
[]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "2e566db9a4542376",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Load information",
"func": "var myArray6 = global.get(\"barchart_kwh_degreedays_31d\",\"file\");\n\nmsg.payload = myArray6;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 1120,
"wires": [
[
"7014e347bfa57006"
]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "11df84f0b8499381",
"type": "inject",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"props": [
{
"p": "topic",
"vt": "str"
}
],
"repeat": "300",
"crontab": "",
"once": true,
"onceDelay": "1",
"topic": "trigger",
"x": 160,
"y": 900,
"wires": [
[
"8564c26fce347ddc"
]
]
},
{
"id": "ab16835d95c2c933",
"type": "delay",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 860,
"y": 940,
"wires": [
[
"e9d6a960b09e05b8"
]
]
},
{
"id": "5f083401791b752a",
"type": "delay",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 680,
"y": 1080,
"wires": [
[
"7014e347bfa57006"
]
]
},
{
"id": "8564c26fce347ddc",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Load information",
"func": "var myArray4 = global.get(\"kwh_31d\",\"file\");\n\nmsg.payload = myArray4;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 370,
"y": 900,
"wires": [
[
"d8e8398aee81f6d9"
]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "39f46b5fe56dc0a6",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Load information",
"func": "var myArray5 = global.get(\"degreedays_31d\",\"file\");\n\nmsg.payload = myArray5;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 370,
"y": 980,
"wires": [
[
"cff31036dc296d8d"
]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "e48537c319b7f2ca",
"type": "delay",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 860,
"y": 900,
"wires": [
[
"41bc927c7f5116b1"
]
]
},
{
"id": "5e60c25489fc6f98",
"type": "inject",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "Load on boot",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "0.1",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 170,
"y": 1120,
"wires": [
[
"2e566db9a4542376"
]
]
},
{
"id": "74f840e183c2ca78",
"type": "function",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "W to kWh conversion",
"func": "msg1 = {};\nmsg2 = {};\nmsg3 = {};\nmsg4 = {};\nmsg5 = {};\n\nvar CurrentTime = new Date().getTime();\nvar PreviousTime = flow.get(\"PreviousTime\");\nvar PreviousMessage = flow.get(\"PreviousMessage\");\nvar PreviousTopic = flow.get(\"PreviousTopic\");\nvar LastMessage = msg.payload;\nvar LastTopic= msg.topic;\n\n if (PreviousTime === \"undefined\") {\nflow.set('PreviousTime',CurrentTime);\n\n \n}\n\nelse {\nTimeElapsed = ((CurrentTime - PreviousTime)/1000);\nflow.set('PreviousTime',CurrentTime);\nflow.set('PreviousMessage',msg.payload);\nflow.set('PreviousTopic',msg.topic);\nmsg3.last = {\"lastTime\":CurrentTime,\"LastMessage\":LastMessage,\"LastTopic\":LastTopic};\nmsg3.Previous = {\"PreviousTime\":PreviousTime,\"PreviousMessage\":PreviousMessage,\"PreviousTopic\":PreviousTopic};\n\n\nmsg1.payload = (TimeElapsed + \" Seconds\");\ntemp = parseFloat(TimeElapsed.toFixed(0));\nmsg2.payload = temp;\nmsg3.payload = {\"Count\":temp,\"Units\":\"Seconds\"}; \nmsg5.payload = (PreviousMessage * ( temp / 3600000 )); // Calculation to Wh portion\nNumber(msg5.payload).toFixed(2);\nmsg5.topic = 'Energy_Consumption_HEAT_kWh';\n }\n \nreturn msg5;\n \n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 360,
"y": 860,
"wires": [
[
"d8e8398aee81f6d9"
]
],
"outputLabels": [
"Energy_Consumption_HEAT_kWh"
],
"icon": "node-red/timer.png"
},
{
"id": "e6ea853dc5ace9bb",
"type": "link in",
"z": "ed155b604642d354",
"g": "1c223a510a8ec72d",
"name": "",
"links": [
"9de1bde370b68508"
],
"x": 125,
"y": 860,
"wires": [
[
"74f840e183c2ca78"
]
]
},
{
"id": "87be08e6a82ef6a0",
"type": "ui_group",
"name": "Degree days information",
"tab": "a681244e6db9a6a7",
"order": 1,
"disp": true,
"width": "15",
"collapse": false,
"className": ""
},
{
"id": "a681244e6db9a6a7",
"type": "ui_tab",
"name": "Degree Days",
"icon": "dashboard",
"order": 11,
"disabled": false,
"hidden": false
}
]
As an other example on the minimalistic approach I had, see the flow below.
[
{
"id": "332197c8279cef3a",
"type": "group",
"z": "ed155b604642d354",
"g": "8a294a78bd96d1ac",
"name": "Chart Past month + Store variables",
"style": {
"label": true
},
"nodes": [
"e7b37912a947c1c3",
"c335ac3c4a8f1e0c",
"6e6937d8bda7e168",
"50e098756084f59a",
"2cc78bac6057732d",
"e64edede4c04268f",
"fdcbec7c08cde234"
],
"x": 104,
"y": 239,
"w": 1622,
"h": 122
},
{
"id": "e7b37912a947c1c3",
"type": "bar-chart-data",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "bar-chart-data2",
"x_interval": "days",
"x_size": "31",
"unit": "",
"precision": "1",
"is_meter_reading": "False",
"agg_by": "avg",
"x": 620,
"y": 280,
"wires": [
[
"2cc78bac6057732d"
]
]
},
{
"id": "c335ac3c4a8f1e0c",
"type": "function",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "Load information",
"func": "var myArray1 = global.get(\"chart_month\",\"file\");\n\nmsg.payload = myArray1;\nmsg.topic = \"graaddagen_calc\";\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 410,
"y": 320,
"wires": [
[
"e7b37912a947c1c3"
]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "6e6937d8bda7e168",
"type": "inject",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "Load on boot",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "2",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 220,
"y": 320,
"wires": [
[
"c335ac3c4a8f1e0c"
]
]
},
{
"id": "50e098756084f59a",
"type": "function",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "Store information",
"func": "\nvar myArray1 = msg.payload;\nglobal.set(\"chart_month\", myArray1,\"file\");\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1610,
"y": 280,
"wires": [
[]
],
"outputLabels": [
"graaddagen 24h"
]
},
{
"id": "2cc78bac6057732d",
"type": "ui_chart",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "",
"group": "87be08e6a82ef6a0",
"order": 5,
"width": 15,
"height": 5,
"label": "Past 31 days",
"chartType": "bar",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "0",
"ymax": "20",
"removeOlder": 1,
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": true,
"useUTC": false,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"className": "",
"x": 1410,
"y": 280,
"wires": [
[
"50e098756084f59a"
]
]
},
{
"id": "e64edede4c04268f",
"type": "link in",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "",
"links": [
"2064b5a11ffc43b3"
],
"x": 165,
"y": 280,
"wires": [
[
"fdcbec7c08cde234"
]
]
},
{
"id": "fdcbec7c08cde234",
"type": "delay",
"z": "ed155b604642d354",
"g": "332197c8279cef3a",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 380,
"y": 280,
"wires": [
[
"e7b37912a947c1c3"
]
]
},
{
"id": "87be08e6a82ef6a0",
"type": "ui_group",
"name": "Degree days information",
"tab": "a681244e6db9a6a7",
"order": 1,
"disp": true,
"width": "15",
"collapse": false,
"className": ""
},
{
"id": "a681244e6db9a6a7",
"type": "ui_tab",
"name": "Degree Days",
"icon": "dashboard",
"order": 11,
"disabled": false,
"hidden": false
}
]
An example of how the data looks like, fed to the chart, see code below:
[{"labels":["03-13","03-14","03-15","03-16","03-17","03-18","03-19","03-20","03-21","03-22","03-23","03-24","03-25","03-26","03-27","03-28","03-29","03-30","03-31","04-01","04-02","04-03","04-04","04-05","04-06","04-07","04-08","04-09","04-10","04-11","04-12"],"series":["DegreeDays (°C)","Energy consumption HEAT (kWh)"],"data":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11.98,8.79,6.93],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.13,4.62,3.18]]}]
I know the difference between time based measurement points, and a complete array.
I fear this is what is throwing me off here.
A chart with plain lines (time based values) can easilly be restored.
A chart with an array can be restored as well. But the combination BarChart node > Chart is the current challenge in this case.
To motivate why I use the BarChart node;
I really like the function to calculate the average per x-category, minute/hour/day. Also in kWh calculations I can use the sum function in it to add all partial kWh measurements so it adds up to a correct value per day.
If I need to get rid of this node, I need to create a function which does this calculation on a collection of datapoints in each time cagetory (x-axis).
Also in this node, the logic suits my goal, that the x-category is like a bucket that gets filled. This is different to default chart/logic. The start and cut-off per bucket is often not how I require it.
Does anybody have a good suggestion? or am I missing something that I am doing wrong
I read in the barchart contrib faq there is a restore function as well, but I dont understand it, or got it to work.
Many thanks in advance for any help.