More Chart questions - sorry folks

Ok, so Nick has REALLY helped me with my silly mistakes.

I've been reading from these sites:
Site 1
Site 2

So if I want MULTIPLE lines on a chart I need to set the TOPIC as well.

Ok. Not too difficult, and I have one of their examples working.

[{"id":"65db74d2.6d7004","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":"5","removeOlderPoints":"200","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":940,"y":710,"wires":[[],[]]},{"id":"5d86049d.a0c794","type":"function","z":"6472f474.da7424","name":"","func":"var msg = {};\n//var msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 1\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":710,"wires":[["65db74d2.6d7004","71929d4b.a6c3c4"]]},{"id":"4f17d026.9fa32","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":240,"y":710,"wires":[["5d86049d.a0c794","63894700.915b48"]]},{"id":"71929d4b.a6c3c4","type":"debug","z":"6472f474.da7424","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":900,"y":780,"wires":[]},{"id":"63894700.915b48","type":"function","z":"6472f474.da7424","name":"","func":"var msg = {};\n//var msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 2\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":770,"wires":[["65db74d2.6d7004"]]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

Though I have TWO random number generators, rather than one, that is because of the "next" thing which has me stuck.

So, what I can see:
These two nodes generate numbers and send them to the CHART and it displays them quite happily. Partly (I'm guessing) because they are both time stamped at the same (or near enough) time.

So it begs the question:
If I have two "data files" which were created at (around) the same time, can I put them both on the same chart?

Ok, but how?

Well, reading Nick's flow, it shows the data is formatted with the:

msg.payload = [{
  "series": ["A"],
  "data": [msg.payload],
  "labels": [""]
}];
msg.topic = "Data set 1";  //  ok, this is my adding.
return msg;

code.

So if I duplicate that for the next/other file and change the topic and Series names that satisfies what was mentioned in the example on the link way above. this one,

But it doesn't seem to. When I inject the first lot of data it is displayed but then when I inject the second, the first is wiped.

So: I either have to open/read and process ALL the files and format them, or there is another way which I am as yet unaware.

Correct - when sending a full chart's worth of data, you must have ALL the data in one msg.payload, with an array of series names, a corresponding array of labels for those series (optional), and an array of arrays of data points (essentially, an array of the two arrays of payload data).

Thanks Steve.

I am trying to get my head around HOW that is done.

Nick's flow works for one file. Not that that is his fault. I didn't specify that ultimately I was going to do multiple files.

So I'm GUESSING I would use something like the JOIN, BATCH, BATCHER, or something like that to "merge" all the file data streams into one.

I am still not up to speed with how that would be done, so that is why I am saying those node names. But that is more from a perceived function name basis.

This is what I have learned since posting:

It would seem that reading from multiple source files is maybe going to be problematic.
So, if I have ONE file with all the data amalgamated it would (should?) be easier.

This is what I have to make a test file for now:

[{"id":"8b87e02a.66542","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":2370,"wires":[["456dfcaf.4a274c"]]},{"id":"456dfcaf.4a274c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":340,"y":2370,"wires":[["974e1c8e.b37a1"]]},{"id":"b4acbbc5.35a89","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2260,"wires":[["456dfcaf.4a274c"]]},{"id":"c65da2a0.13dc58","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2300,"wires":[["456dfcaf.4a274c"]]},{"id":"aeecff59.e1095","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '1';\n//msg.topic = \"Data flow 1\";\nreturn msg;","outputs":1,"noerr":0,"x":700,"y":2370,"wires":[["c44407bc.a6691"]]},{"id":"3815dffc.7b14a","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '2';\n//msg.topic = \"Data flow 2\";\nreturn msg;","outputs":1,"noerr":0,"x":700,"y":2570,"wires":[["c44407bc.a6691"]]},{"id":"5bc909ac.938fc","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":2570,"wires":[["2240ec30.2b0a3c"]]},{"id":"2240ec30.2b0a3c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":340,"y":2570,"wires":[["b5c920ae.c2d5"]]},{"id":"2e5a5c30.212324","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2460,"wires":[["2240ec30.2b0a3c"]]},{"id":"1764df6b.288779","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2500,"wires":[["2240ec30.2b0a3c"]]},{"id":"c44407bc.a6691","type":"file","z":"6472f474.da7424","name":"","filename":"","appendNewline":true,"createDir":false,"overwriteFile":"false","x":970,"y":2450,"wires":[]},{"id":"974e1c8e.b37a1","type":"function","z":"6472f474.da7424","name":"","func":"var msg = {};\n//var msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 1\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n    \nreturn msg;\n","outputs":1,"noerr":0,"x":490,"y":2370,"wires":[["aeecff59.e1095"]]},{"id":"b5c920ae.c2d5","type":"function","z":"6472f474.da7424","name":"","func":"//var msg = {};\nvar msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 2\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n\nreturn msg;\n","outputs":1,"noerr":0,"x":490,"y":2570,"wires":[["3815dffc.7b14a"]]}]

This yields a file (extract) like this:

1532602214249 - 41 - 1
1532602217252 - 18 - 1
1532602217253 - 56 - 2
1532602220256 - 89 - 1
1532602220257 - 21 - 2
1532602223258 - 8 - 1
1532602223259 - 60 - 2

So that is better in that it also has identifiers so I know from whom each line of data came.

But then it falls over when I try to split the data as per Nick's initial flow.
Function node:

var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});
msg.payload = {x:parts[0], y:parts[1]};
return msg;

There will be THREE parts, and when I add the extra to the middle line, it gets upset with me.
I think that is obvious, as it is SPLITTING the payload. Not cutting it up to more than 2 parts.

So I need to find the command/process to give me three parameter thingies.

Folks, I am not posting here to waste people's time. I "need" to .... discuss the idea to help me better understand what is going on and what I am trying to do.

Also, if I am walking into a stupid place, it would be nice if someone mentions it or helps me when I really get stuck.

All these traps for new players. It really needs a better person than me to understand them all.

You are stuck in function to parse data but the problem is that you have been slightly forgotten the format of data your endpoint (chart) needs.
If you are creating line chart with more than one line - you must introduce that many SERIES and your data must be arranged into arrays representing those series.

Read carefully this document https://github.com/node-red/node-red-dashboard/blob/master/Charts.md#stored-data

Keeping this in mind you'll need to figure out what every part of source data means and how to manage it to be properly formatted as your endpoint expects

Yes, I have read that.

Alas "something" isn't jelling with me.

(This is going to be slightly annoying, but please indulge me.)

This works - from Nick.

[{"id":"69d670b1.8e8b3","type":"inject","z":"6472f474.da7424","name":"MusicPi","topic":"","payload":"/home/me/TEMP/Data/musicpi_temp.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":440,"wires":[["e2ef7cb.a26c48"]]},{"id":"e2ef7cb.a26c48","type":"function","z":"6472f474.da7424","name":"Set filename","func":"msg.filename = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":440,"wires":[["3512b71a.f19f78"]]},{"id":"3512b71a.f19f78","type":"file in","z":"6472f474.da7424","name":"Read file","filename":"","format":"lines","chunk":false,"sendError":false,"x":540,"y":440,"wires":[["fd27b39.50ba75"]]},{"id":"fd27b39.50ba75","type":"function","z":"6472f474.da7424","name":"","func":"var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nmsg.payload = {x:parts[0], y:parts[1]};\nreturn msg;\n","outputs":1,"noerr":0,"x":190,"y":510,"wires":[["6bf71402.79b2bc"]]},{"id":"6bf71402.79b2bc","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":320,"y":510,"wires":[["bd1d2642.b76e98"]]},{"id":"bd1d2642.b76e98","type":"function","z":"6472f474.da7424","name":"Format message for chart","func":"msg.payload = [{\n  \"series\": [\"B\"],\n  \"data\": [msg.payload],\n  \"labels\": [\"\"]\n}];\nmsg.topic = \"Data set 2\";\nreturn msg;","outputs":1,"noerr":0,"x":540,"y":510,"wires":[["57ec8591.403c3c","6397865d.a94918"]]},{"id":"6397865d.a94918","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"200","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":930,"y":340,"wires":[[],[]]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

From there I built this to "prove" the concept of how to have 2 sets of data on one graph.

[{"id":"69d670b1.8e8b3","type":"inject","z":"6472f474.da7424","name":"MusicPi","topic":"","payload":"/home/me/TEMP/Data/musicpi_temp.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":440,"wires":[["e2ef7cb.a26c48"]]},{"id":"e2ef7cb.a26c48","type":"function","z":"6472f474.da7424","name":"Set filename","func":"msg.filename = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":440,"wires":[["3512b71a.f19f78"]]},{"id":"3512b71a.f19f78","type":"file in","z":"6472f474.da7424","name":"Read file","filename":"","format":"lines","chunk":false,"sendError":false,"x":540,"y":440,"wires":[["fd27b39.50ba75"]]},{"id":"fd27b39.50ba75","type":"function","z":"6472f474.da7424","name":"","func":"var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nmsg.payload = {x:parts[0], y:parts[1]};\nreturn msg;\n","outputs":1,"noerr":0,"x":190,"y":510,"wires":[["6bf71402.79b2bc"]]},{"id":"6bf71402.79b2bc","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":320,"y":510,"wires":[["bd1d2642.b76e98"]]},{"id":"bd1d2642.b76e98","type":"function","z":"6472f474.da7424","name":"Format message for chart","func":"msg.payload = [{\n  \"series\": [\"B\"],\n  \"data\": [msg.payload],\n  \"labels\": [\"\"]\n}];\nmsg.topic = \"Data set 2\";\nreturn msg;","outputs":1,"noerr":0,"x":540,"y":510,"wires":[["57ec8591.403c3c","6397865d.a94918"]]},{"id":"6397865d.a94918","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"200","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":930,"y":340,"wires":[[],[]]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

Now, I know it is a poor representation, but it works.

I get two different colour lines on the graph. The delay is there only because ..... I wanted to make sure it was the OTHER data being shown.

The packets coming out of the two nodes look like this:

{"payload":89,"topic":"Line 1","_msgid":"eee576b9.45dc58"}
{"topic":"Line 2","payload":96,"_msgid":"eee576b9.45dc58"}

Which kind of concurs with what is said on the link.

So-o-o.....

If that works, it has TOPIC to distinguish between the data set it is showing on the chart.

That led me to the next stage:

Rather than having multiple databases, what would happen if I had ONE database and each line had an identifier which can be used to tell it which set of data it belongs to?

So I made this to generate a bit of pseudo random data from two devices.

[{"id":"8b87e02a.66542","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":2370,"wires":[["456dfcaf.4a274c"]]},{"id":"456dfcaf.4a274c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":340,"y":2370,"wires":[["974e1c8e.b37a1"]]},{"id":"b4acbbc5.35a89","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2260,"wires":[["456dfcaf.4a274c"]]},{"id":"c65da2a0.13dc58","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2300,"wires":[["456dfcaf.4a274c"]]},{"id":"aeecff59.e1095","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '1';\n//msg.topic = \"Data flow 1\";\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":2370,"wires":[["c44407bc.a6691"]]},{"id":"3815dffc.7b14a","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '2';\n//msg.topic = \"Data flow 2\";\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":2570,"wires":[["c44407bc.a6691"]]},{"id":"5bc909ac.938fc","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":2570,"wires":[["2240ec30.2b0a3c"]]},{"id":"2240ec30.2b0a3c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":340,"y":2570,"wires":[["b5c920ae.c2d5"]]},{"id":"2e5a5c30.212324","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2460,"wires":[["2240ec30.2b0a3c"]]},{"id":"1764df6b.288779","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":2500,"wires":[["2240ec30.2b0a3c"]]},{"id":"c44407bc.a6691","type":"file","z":"6472f474.da7424","name":"","filename":"","appendNewline":true,"createDir":false,"overwriteFile":"false","x":790,"y":2450,"wires":[]},{"id":"974e1c8e.b37a1","type":"function","z":"6472f474.da7424","name":"","func":"var msg = {};\n//var msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 1\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n    \nreturn msg;\n","outputs":1,"noerr":0,"x":490,"y":2370,"wires":[["aeecff59.e1095"]]},{"id":"b5c920ae.c2d5","type":"function","z":"6472f474.da7424","name":"","func":"//var msg = {};\nvar msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 2\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n\nreturn msg;\n","outputs":1,"noerr":0,"x":490,"y":2570,"wires":[["3815dffc.7b14a"]]}]

That sent out data which seemed to fit with what I have already seen.

But it seems that I can't "intermix" the two sets of data. That is:
dataset 1 must be concurrent as must dataset 2. Not a mishmash of lines.

So that seems to only complicate how I am going to get the (many) data sets from either one big database or many smaller ones and add them all together in one function node and format it to send to the chart.

Because NR is asynchronous, it is still unclear to me how to capture the stored data from multiple files and merge all that to an array, or read in ONE file with a mixture of data sources and format.

P.S.
Sorry, this just in.
To also confuse me, I have this flow:
I have two inject nodes with REAL data in them.
Granted pressing the button again only injects the same data, but if you press both buttons TWICE, you see TWO lines of data on the chart.
Given that, one of my earlier flows SHOULD (by my reasoning) work.

[{"id":"305a6e7f.43d60a","type":"inject","z":"6472f474.da7424","name":"Test1","topic":"","payload":"1532602229265 - 56 - 1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1100,"wires":[["ef1ce913.5f8e"]]},{"id":"22a0417b.0ec926","type":"inject","z":"6472f474.da7424","name":"Test","topic":"","payload":"1532602223259 - 60 - 2","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1150,"wires":[["ef1ce913.5f8e","164198bf.bfd2d7"]]},{"id":"ef1ce913.5f8e","type":"split","z":"6472f474.da7424","name":"","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":1150,"wires":[["f689827e.ba0108"]]},{"id":"f689827e.ba0108","type":"function","z":"6472f474.da7424","name":"","func":"// var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nvar x = msg.payload;\n//msg.payload = parseInt(x);\nmsg.payload = parseInt(x);\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":1150,"wires":[["81e35212.0d0008","39e90f7b.e2052"]]},{"id":"81e35212.0d0008","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":510,"y":1150,"wires":[["3af33427.7b587c","5f68eacb.47e034"]]},{"id":"3af33427.7b587c","type":"function","z":"6472f474.da7424","name":"","func":"node.warn(\"msg.payload[0] is\" + msg.payload[0]);\nnode.warn(\"msg.payload[1] is\" + msg.payload[1]);\nnode.warn(\"msg.payload[2] is\" + msg.payload[2]);\nvar value = msg.payload[1];\nvar topic = msg.payload[2];\nmsg.payload = value;\n//msg.payload = [{\n//  \"series\": [\"B\"],\n//  \"data\": value,\n//  \"labels\": [\"\"]\n//}];\nmsg.topic =  topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":670,"y":1150,"wires":[["8fdf2e9c.0a5618","65db74d2.6d7004"]]},{"id":"65db74d2.6d7004","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":"5","removeOlderPoints":"200","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":940,"y":910,"wires":[[],[]]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

Seems this is a very bigger cake than I originally thought it was.

I feel I am close, but am missing something - somewhere.

I knocked up a flow for you but in doing so found a bug in the Join node. I've now run out of time for the moment to spend on this, but I'll try to come back to it a little later with a flow that doesn't hit the join node bug I also have to fix.

1 Like

Nick,

Again, thanks.

This is a new development since my last post.
(New flow)
Excuse the TRAFFIC node, it is needed to help with all the alternatives I have for testing.
And the layout. There is a lot of other stuff on my screen which is not needed for this problem.

This NEARLY works!

[{"id":"20d2d659.8a55ca","type":"inject","z":"6472f474.da7424","name":"Random data","topic":"","payload":"/home/me/TEMP/random_data.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":300,"y":620,"wires":[["2bb4ce7f.00f132"]]},{"id":"2bb4ce7f.00f132","type":"function","z":"6472f474.da7424","name":"Set filename","func":"msg.filename = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":620,"wires":[["41e1c48c.eb4474"]]},{"id":"41e1c48c.eb4474","type":"file in","z":"6472f474.da7424","name":"Read file","filename":"","format":"lines","chunk":false,"sendError":false,"x":660,"y":620,"wires":[["6aeb7fca.7e4d4","f44a1040.cddba8"]]},{"id":"4640aac2.923adc","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":860,"wires":[["f44a1040.cddba8"]]},{"id":"9a244a36.411f7","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":900,"wires":[["f44a1040.cddba8"]]},{"id":"f44a1040.cddba8","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":300,"y":880,"wires":[["7b1057b9.2652a"]]},{"id":"7b1057b9.2652a","type":"split","z":"6472f474.da7424","name":"","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":440,"y":880,"wires":[["57d7cf80.5d527"]]},{"id":"57d7cf80.5d527","type":"function","z":"6472f474.da7424","name":"","func":"// var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nvar x = msg.payload;\n//msg.payload = parseInt(x);\nmsg.payload = parseInt(x);\nreturn msg;","outputs":1,"noerr":0,"x":570,"y":880,"wires":[["50255cfd.053bac"]]},{"id":"50255cfd.053bac","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":700,"y":880,"wires":[["b7975ef2.5092b"]]},{"id":"b7975ef2.5092b","type":"function","z":"6472f474.da7424","name":"","func":"node.warn(\"msg.payload[0] is\" + msg.payload[0]);\nnode.warn(\"msg.payload[1] is\" + msg.payload[1]);\nnode.warn(\"msg.payload[2] is\" + msg.payload[2]);\nvar value = msg.payload[1];\nvar topic = msg.payload[2];\nmsg.payload = value;\n//msg.payload = [{\n//  \"series\": [\"B\"],\n//  \"data\": value,\n//  \"labels\": [\"\"]\n//}];\nmsg.topic =  topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":820,"y":880,"wires":[["77851581.20b5fc","6397865d.a94918"]]},{"id":"6397865d.a94918","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"200","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":1050,"y":340,"wires":[[],[]]},{"id":"77851581.20b5fc","type":"debug","z":"6472f474.da7424","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":920,"y":930,"wires":[]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

The problem?
TIME.
The database has time, reading and ID.
It spits out the data to the graph but at THIS time, not the logged time.

So to get THIS working, I need to look at how to get the chart to honour the timestamp and show it on the scale.

Getting there!
(And thanks to all who reply/replied.)

Well, it isn't as easy as I thought.

From my last post the LAST function node before the chart node.

As it is posted (last post last flow) it "works" in that all the data from the file is SPAT onto the chart with no X axis scale/size/calibration.
Not good.
As the file has timestamps, I think/thought that when formatting the packet/payload/what ever if the X axis has data given to it, it would work. (See below for why I think that.)
And so I modified the flow.

Back to the thought line for what I have read, believe and think is the right thing to do:

From the link mentioned to me, I see this and believe it relevant to what I am wanting to do.

[{
"series": ["A", "B", "C"],
"data": [
    [{ "x": 1504029632890, "y": 5 },
     { "x": 1504029636001, "y": 4 },
     { "x": 1504029638656, "y": 2 }
    ],
    [{ "x": 1504029633514, "y": 6 },
     { "x": 1504029636622, "y": 7 },
     { "x": 1504029639539, "y": 6 }
    ],
    [{ "x": 1504029634400, "y": 7 },
     { "x": 1504029637959, "y": 7 },
     { "x": 1504029640317, "y": 7 }
    ]
],
"labels": [""]
}]

To help with things and format of text, my variables will be UPPERCASE

So breaking it down the format is:
[{"series": [ TOPIC], "data": [ [{"x":TIMESTAMP, "y":VALUE} ] ],"labels: [""] }]

Though I am worried that what is written there isn't right, as my tests with it are failing.

This is what I have changed the flow to:

[{"id":"20d2d659.8a55ca","type":"inject","z":"6472f474.da7424","name":"Random data","topic":"","payload":"/home/me/TEMP/random_data.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":620,"wires":[["6481a892.d97dd8"]]},{"id":"6481a892.d97dd8","type":"delay","z":"6472f474.da7424","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":310,"y":620,"wires":[["2bb4ce7f.00f132"]]},{"id":"2bb4ce7f.00f132","type":"function","z":"6472f474.da7424","name":"Set filename","func":"msg.filename = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":480,"y":620,"wires":[["41e1c48c.eb4474"]]},{"id":"41e1c48c.eb4474","type":"file in","z":"6472f474.da7424","name":"Read file","filename":"","format":"lines","chunk":false,"sendError":false,"x":670,"y":620,"wires":[["6aeb7fca.7e4d4","f44a1040.cddba8"]]},{"id":"4640aac2.923adc","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":860,"wires":[["f44a1040.cddba8"]]},{"id":"f44a1040.cddba8","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":300,"y":880,"wires":[["7b1057b9.2652a"]]},{"id":"7b1057b9.2652a","type":"split","z":"6472f474.da7424","name":"","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":440,"y":880,"wires":[["57d7cf80.5d527"]]},{"id":"57d7cf80.5d527","type":"function","z":"6472f474.da7424","name":"","func":"// var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nvar x = msg.payload;\n//msg.payload = parseInt(x);\nmsg.payload = parseInt(x);\nreturn msg;","outputs":1,"noerr":0,"x":570,"y":880,"wires":[["50255cfd.053bac"]]},{"id":"50255cfd.053bac","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":700,"y":880,"wires":[["b7975ef2.5092b"]]},{"id":"b7975ef2.5092b","type":"function","z":"6472f474.da7424","name":"","func":"node.warn(\"msg.payload[0] is\" + msg.payload[0]);\nnode.warn(\"msg.payload[1] is\" + msg.payload[1]);\nnode.warn(\"msg.payload[2] is\" + msg.payload[2]);\nvar value = msg.payload[1];\nvar topic = msg.payload[2];\nvar time = msg.payload[0];\n//msg.payload = value;\nmsg.payload = [{\n  \"series\": [topic],\n  \"data\": [\n    [{\"x\": time, \"y\": value},]\n  ],\n  \"labels\": [\"\"]\n}];\n//msg.topic =  topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":820,"y":880,"wires":[["77851581.20b5fc","6397865d.a94918"]]},{"id":"77851581.20b5fc","type":"debug","z":"6472f474.da7424","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":920,"y":930,"wires":[]},{"id":"6397865d.a94918","type":"ui_chart","z":"6472f474.da7424","name":"","group":"f25bb428.e9272","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"200","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":1050,"y":340,"wires":[[],[]]},{"id":"f25bb428.e9272","type":"ui_group","z":"","name":"Graph","tab":"91f90dd2.4c30b8","order":1,"disp":true,"width":"10","collapse":false},{"id":"91f90dd2.4c30b8","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]

With this as the data file:

1532602214249 - 41 - 1
1532602217252 - 18 - 1
1532602217253 - 56 - 2
1532602220256 - 89 - 1
1532602220257 - 21 - 2
1532602223258 - 8 - 1
1532602223259 - 60 - 2
1532602226261 - 68 - 1
1532602226262 - 94 - 2
1532602229265 - 56 - 1
1532602229266 - 14 - 2

Enabling the "Traffic light" and pressing the INJECT node, nothing exciting happens.

:frowning:

Update:
Modifying the last FUNCTION node before the graph to this gets sort of results but still doesn't quite seem to be the right way.

node.warn("msg.payload[0] is" + msg.payload[0]);
node.warn("msg.payload[1] is" + msg.payload[1]);
node.warn("msg.payload[2] is" + msg.payload[2]);
var value = msg.payload[1];
var topic = msg.payload[2];
var time = msg.payload[0];

msg.payload = {time,value};
msg.topic =  topic;
return msg;

Format of data for chart has to be followed correctly.
You can ignore first couple nodes in my flow. I just created data to replicate your data structure. Meaningful part starts from "parse to parts -> create object" node.

[{"id":"f9e4310.c2e5bd","type":"inject","z":"cb887fb5.a0b15","name":"Random data","topic":"","payload":"/home/me/TEMP/random_data.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":620,"wires":[["d9a13b0e.5174a8"]]},{"id":"8a309a80.edb588","type":"function","z":"cb887fb5.a0b15","name":"parse to parts -> create object","func":"var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\n\nvar o = {x:parts[0],y:parts[1],s:parts[2]};\n\nmsg.payload = o\n\nreturn msg;\n","outputs":1,"noerr":0,"x":310,"y":480,"wires":[["8e0f21a3.1252"]]},{"id":"cf2402a3.3b0cd","type":"function","z":"cb887fb5.a0b15","name":"parse array into series","func":"var data = msg.payload;\n\nfunction generateDataForSeries(values,series){    \n    var a = [];\n    var o = {};\n    for(var i=0;i<values.length;i++){\n        o = {};\n        if(series === values[i].s){\n            o.y = values[i].y;\n            o.x = values[i].x;\n            a.push(o);  \n        }\n            \n    }\n    return a;\n}\n\nvar series1 = generateDataForSeries(data,1);\nvar series2 = generateDataForSeries(data,2);\n\nmsg.payload = [{\n \"series\": [\"S1\",\"S2\"],\n \"data\": [series1,series2],\n \"labels\": [\"\"]\n}];\n\nreturn msg;\n","outputs":1,"noerr":0,"x":420,"y":600,"wires":[["a93cdf05.0bbbd","fa7619ce.977868"]]},{"id":"fa7619ce.977868","type":"ui_chart","z":"cb887fb5.a0b15","name":"","group":"e250c38c.04261","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"auto","interpolate":"bezier","nodata":"N/C","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":630,"y":600,"wires":[[],[]]},{"id":"d9a13b0e.5174a8","type":"function","z":"cb887fb5.a0b15","name":"","func":"msg.payload = \"1532602214249 - 41 - 1,\"+\n\"1532602217252 - 18 - 1,\"+\n\"1532602217253 - 56 - 2,\"+\n\"1532602220256 - 89 - 1,\"+\n\"1532602220257 - 21 - 2,\"+\n\"1532602223258 - 8 - 1,\"+\n\"1532602223259 - 60 - 2\"\nreturn msg;","outputs":1,"noerr":0,"x":150,"y":360,"wires":[["915ee873.8817e8"]]},{"id":"915ee873.8817e8","type":"split","z":"cb887fb5.a0b15","name":"","splt":",","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":190,"y":400,"wires":[["8a309a80.edb588"]]},{"id":"a93cdf05.0bbbd","type":"debug","z":"cb887fb5.a0b15","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":650,"y":540,"wires":[]},{"id":"8e0f21a3.1252","type":"join","z":"cb887fb5.a0b15","name":"join created objects to array","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":380,"y":540,"wires":[["cf2402a3.3b0cd"]]},{"id":"e250c38c.04261","type":"ui_group","z":"","name":"Graph","tab":"669c363b.343a18","order":1,"disp":true,"width":"10","collapse":false},{"id":"669c363b.343a18","type":"ui_tab","z":"","name":"Charts","icon":"dashboard","order":19}]
1 Like

That seems a complex way to produce formatted chart data... has Nick come back with an example yet?

No, Nick is busy at the moment.

Complexity is relative. And yes, I agree - writing javascript functions is a bit against of main goal of Node-RED - "getting things working with minimal coding". But sometimes those little lines just work
out better than long trains of the nodes. Many many cases can be done without using the Function node but at some point it may go "out of space"
But certainly - as it is clear now, how the final data structure should look like - just take it as a challenge and try to achieve it from source data. As easy as you can. :wink:

2 Likes

If you have control over the format of the data in the file you could write it in JSON format and then you can just read it in, feed it through a JSON node to convert it to a js object, and send it to the chart.

1 Like

OK, more developments on my part:

Given: Nick says there is a bug with the JOIN node. Ok. I can't do anything about that just now.

But I want to take a step back and look at the problem again with fresh eyes.

This flow works in that if you double press one of the INJECT nodes, you get a trace on the chart.
Double press the other one and you get a new trace with a different colour. That is what is wanted.

So if it works in that respect, I SHOULD be able to build on it. Which is what I was/am trying to do.

This is the flow:
With no graph.

[{"id":"22a0417b.0ec926","type":"inject","z":"6472f474.da7424","name":"Test","topic":"","payload":"1532602223259 - 60 - 2","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1170,"y":3060,"wires":[["ef1ce913.5f8e","164198bf.bfd2d7"]]},{"id":"ef1ce913.5f8e","type":"split","z":"6472f474.da7424","name":"","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":1330,"y":3060,"wires":[["f689827e.ba0108"]]},{"id":"8fdf2e9c.0a5618","type":"debug","z":"6472f474.da7424","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1900,"y":3060,"wires":[]},{"id":"164198bf.bfd2d7","type":"debug","z":"6472f474.da7424","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1350,"y":3010,"wires":[]},{"id":"f689827e.ba0108","type":"function","z":"6472f474.da7424","name":"","func":"// var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nvar x = msg.payload;\n//msg.payload = parseInt(x);\nmsg.payload = parseInt(x);\nreturn msg;","outputs":1,"noerr":0,"x":1460,"y":3060,"wires":[["81e35212.0d0008","39e90f7b.e2052"]]},{"id":"81e35212.0d0008","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1590,"y":3060,"wires":[["3af33427.7b587c","5f68eacb.47e034"]]},{"id":"3af33427.7b587c","type":"function","z":"6472f474.da7424","name":"","func":"node.warn(\"msg.payload[0] is\" + msg.payload[0]);\nnode.warn(\"msg.payload[1] is\" + msg.payload[1]);\nnode.warn(\"msg.payload[2] is\" + msg.payload[2]);\nvar value = msg.payload[1];\nvar topic = msg.payload[2];\nmsg.payload = value;\n//msg.payload = [{\n//  \"series\": [\"B\"],\n//  \"data\": value,\n//  \"labels\": [\"\"]\n//}];\nmsg.topic =  topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":1750,"y":3060,"wires":[["8fdf2e9c.0a5618","61d4aefd.93f72"]]},{"id":"5f68eacb.47e034","type":"debug","z":"6472f474.da7424","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1750,"y":3120,"wires":[]},{"id":"39e90f7b.e2052","type":"debug","z":"6472f474.da7424","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1580,"y":3110,"wires":[]},{"id":"305a6e7f.43d60a","type":"inject","z":"6472f474.da7424","name":"Test1","topic":"","payload":"1532602229265 - 56 - 1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1170,"y":3010,"wires":[["ef1ce913.5f8e","164198bf.bfd2d7"]]},{"id":"61d4aefd.93f72","type":"link out","z":"6472f474.da7424","name":"Chart TX","links":["3db58362.7e0054"],"x":1915,"y":3020,"wires":[]}]

Forgive the comments in the last FUNCTION node.
But that is where the "magic happens" to get the message compatible with the chart.
And I was importing sample lines that had the format I thought I needed.

This is what is sent to the chart:

{"topic":1,"payload":56,"_msgid":"6d821f06.92184"}

Observations:
the TOPIC and PAYLOAD are numbers.

Reading the link: This one and it says:
You can also insert extra data points by specifying the timestamp property. This must be in either epoch time (millisecs since Jan 1 1970), or ISO8601 format.

{topic:"temperature", payload:22, timestamp:1520527095000}

So, if I add the TIMESTAMP field, it should use that as the X axis scale. Right?

I can't do that here with the above flow.
But the database/file has the TIMESTAMP saved in it.

So if I modify the last node on my other working flow - which displays the two traces in different colours, but just now time scale - it SHOULD work. Right?

So this is the last function node in the flow:

node.warn("msg.payload[0] is" + msg.payload[0]);  //  Time
node.warn("msg.payload[1] is" + msg.payload[1]);  //  data
node.warn("msg.payload[2] is" + msg.payload[2]);  //  series
var value = parseInt(msg.payload[1]);
var topic = parseInt(msg.payload[2]);
var time = parseInt(msg.payload[0]);

msg.payload = {topic:topic,payload:value, timestamp:time};

return msg;

This is what is spat out of the node to the chart:

{"payload":{"topic":1,"payload":41,"timestamp":1532602214249},"topic":"","filename":"/home/me/TEMP/random_data.db","parts":{"index":0,"ch":"\n","type":"string","id":"ef2bfb07.a8cb08"},"_msgid":"5c9cfbd7.aead84"}

So, as they aren't quite the same, I accept it still doesn't work.

But I am at wit's end trying to get the formatting right to construct the message in the second case to be the same (but with the timestamp field) as the first one.

Anyone?

REALLY GOOD NEWS!

I got it working!!!

BUT! (And that seems to be a problem)

Ok, here's the big picture - needed to put things in context:
I am saving data to log files for future analysis. (Note 1)

I want to load the data and display it on a chart. There are many sources and so many traces.

I made a few short examples and am/was playing with that data.

The "problem" was getting the TIMESTAMP to work on said chart/s.

I got a chart working displaying two traces at time NOW. When I tried to display the data from the files it didn't seem to work. (Note 2)

Everything seemed to be right, but the graphs weren't "working". Sometimes the traces would be scrunched up one end, or just not displayed (or visible).

Note 1 and 2:
Now, future and past, are very different.
If in case 1 I was wanting to look at it in the future, when the future arrives, the data is from the past.
Getting the chart scale right was/is a big problem.

I re-saved some fake data and tried the latest attempt, and it works!

So, here is the flow:
I will need help with how to scale the chart if the data is from a fair while ago, or for certain time periods.
But anyway, for now it is working.

[{"id":"3c062447.3c6394","type":"inject","z":"6472f474.da7424","name":"Random data","topic":"","payload":"/home/me/TEMP/random_data.db","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":2420,"wires":[["b56c88e7.d26248"]]},{"id":"b56c88e7.d26248","type":"delay","z":"6472f474.da7424","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":290,"y":2420,"wires":[["3c10f95f.027406"]]},{"id":"3c10f95f.027406","type":"function","z":"6472f474.da7424","name":"Set filename","func":"msg.filename = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":460,"y":2420,"wires":[["b297f274.86db6"]]},{"id":"b297f274.86db6","type":"file in","z":"6472f474.da7424","name":"Read file","filename":"","format":"lines","chunk":false,"sendError":false,"x":650,"y":2420,"wires":[["96fb4dad.7366"]]},{"id":"96fb4dad.7366","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":310,"y":2510,"wires":[["1e9adab2.a87895"]]},{"id":"bcbf0638.544e3","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":2490,"wires":[["96fb4dad.7366"]]},{"id":"b1beddf1.b36d","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":2530,"wires":[["96fb4dad.7366"]]},{"id":"1e9adab2.a87895","type":"split","z":"6472f474.da7424","name":"","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":450,"y":2510,"wires":[["9820f871.a29438"]]},{"id":"9820f871.a29438","type":"function","z":"6472f474.da7424","name":"","func":"// var parts = msg.payload.split(/ - /).map(function(v) { return parseInt(v)});\nvar x = msg.payload;\n//msg.payload = parseInt(x);\nmsg.payload = parseInt(x);\nreturn msg;","outputs":1,"noerr":0,"x":580,"y":2510,"wires":[["cc25a671.69358"]]},{"id":"cc25a671.69358","type":"join","z":"6472f474.da7424","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":710,"y":2510,"wires":[["a26f63.eecdb8a"]]},{"id":"a26f63.eecdb8a","type":"function","z":"6472f474.da7424","name":"","func":"node.warn(\"msg.payload[0] is\" + msg.payload[0]);  //  Time\nnode.warn(\"msg.payload[1] is\" + msg.payload[1]);  //  data\nnode.warn(\"msg.payload[2] is\" + msg.payload[2]);  //  series\nvar value = parseInt(msg.payload[1]);\nvar topic = parseInt(msg.payload[2]);\nvar time = parseInt(msg.payload[0]);\n\nmsg.payload = value;\nmsg.timestamp = time;\nmsg.topic = topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":830,"y":2510,"wires":[["de39af28.80295","61720c50.e01184"]]},{"id":"de39af28.80295","type":"debug","z":"6472f474.da7424","name":"This is the one I want to work","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":840,"y":2640,"wires":[]},{"id":"61720c50.e01184","type":"link out","z":"6472f474.da7424","name":"Chart TX","links":["3db58362.7e0054"],"x":1005,"y":2440,"wires":[]}]

If you are interested (and still reading) here is the flow to make the file.
(You may have to edit the path)

[{"id":"8b87e02a.66542","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":1370,"y":2350,"wires":[["456dfcaf.4a274c"]]},{"id":"456dfcaf.4a274c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":1560,"y":2350,"wires":[["974e1c8e.b37a1"]]},{"id":"b4acbbc5.35a89","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1360,"y":2240,"wires":[["456dfcaf.4a274c"]]},{"id":"c65da2a0.13dc58","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1360,"y":2280,"wires":[["456dfcaf.4a274c"]]},{"id":"aeecff59.e1095","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '1';\n//msg.topic = \"Data flow 1\";\nreturn msg;","outputs":1,"noerr":0,"x":1840,"y":2350,"wires":[["c44407bc.a6691"]]},{"id":"3815dffc.7b14a","type":"function","z":"6472f474.da7424","name":"","func":"msg.filename = \"/home/me/TEMP/random_data.db\";\nvar time = Date.now();\nvar x = msg.payload;\nmsg.payload = time + ' - ' + x + ' - ' + '2';\n//msg.topic = \"Data flow 2\";\nreturn msg;","outputs":1,"noerr":0,"x":1840,"y":2550,"wires":[["c44407bc.a6691"]]},{"id":"5bc909ac.938fc","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"","payloadType":"date","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":1370,"y":2550,"wires":[["2240ec30.2b0a3c"]]},{"id":"2240ec30.2b0a3c","type":"traffic","z":"6472f474.da7424","name":"","property_allow":"payload","filter_allow":"GO","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"STOP","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":1560,"y":2550,"wires":[["b5c920ae.c2d5"]]},{"id":"2e5a5c30.212324","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"GO","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1360,"y":2440,"wires":[["2240ec30.2b0a3c"]]},{"id":"1764df6b.288779","type":"inject","z":"6472f474.da7424","name":"","topic":"","payload":"STOP","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1360,"y":2480,"wires":[["2240ec30.2b0a3c"]]},{"id":"c44407bc.a6691","type":"file","z":"6472f474.da7424","name":"","filename":"","appendNewline":true,"createDir":false,"overwriteFile":"false","x":2010,"y":2430,"wires":[]},{"id":"974e1c8e.b37a1","type":"function","z":"6472f474.da7424","name":"","func":"var msg = {};\n//var msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 1\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n    \nreturn msg;\n","outputs":1,"noerr":0,"x":1710,"y":2350,"wires":[["aeecff59.e1095"]]},{"id":"b5c920ae.c2d5","type":"function","z":"6472f474.da7424","name":"","func":"//var msg = {};\nvar msg1 = {};\n\nmsg.payload = Math.round(Math.random()*100);\nmsg.topic = \"Line 2\";\n\n//msg1.payload = Math.round(Math.random()*100);\n//msg1.topic = \"Line 2\";\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1710,"y":2550,"wires":[["3815dffc.7b14a"]]}]

and turn on the two traffic lights.

I was reading your latest post couple of times and everything went more complicated in every next try. :rofl: no offence
But anyway, to help you out a little bit I created another example of chart with tweaking timestamps (or as you call it ~ chart scaling). It may bring you a bit closer to understanding the charts in general and why not the final goal of your project.

[{"id":"77dcc0e3.494ed","type":"function","z":"cb887fb5.a0b15","name":"generate data","func":"var t;\nvar d;\nvar today = [];\nvar yesterday = [];\nvar data;\n\nfor(var i=0; i<24 ;i++){\n data = 5 + Math.sqrt(i);\n d = new Date();\n d.setHours(i,0,0,0);\n t = d.getTime();\n today.push({\"x\":t,\"y\":data});\n d.setDate(d.getDate()-1);\n t = d.getTime();\n yesterday.push({\"x\":t,\"y\":data});\n}\n\nglobal.set(\"today\",today);\nglobal.set(\"yesterday\",yesterday);\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":520,"wires":[["608b3aeb.726db4","7a223cd8.0cca14"]]},{"id":"a3e939b1.8e7ef8","type":"inject","z":"cb887fb5.a0b15","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":"","x":130,"y":420,"wires":[["77dcc0e3.494ed"]]},{"id":"608b3aeb.726db4","type":"function","z":"cb887fb5.a0b15","name":"or","func":"var a = global.get(\"today\");\nvar b = global.get(\"yesterday\");\n\nmsg.payload = [{\n \"series\": [\"Today\",\"Yesterday\"],\n \"data\": [a,b],\n \"labels\": [\"\"]\n}];\n\nreturn msg;","outputs":1,"noerr":0,"x":463,"y":545,"wires":[["6fdc7697.347ac8"]]},{"id":"6fdc7697.347ac8","type":"ui_chart","z":"cb887fb5.a0b15","name":"","group":"de3ef089.0e5a1","order":0,"width":0,"height":0,"label":"ORIGINAL","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#ff0000","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":643,"y":544,"wires":[[],[]]},{"id":"7a223cd8.0cca14","type":"ui_slider","z":"cb887fb5.a0b15","name":"","label":"slider","group":"de3ef089.0e5a1","order":0,"width":0,"height":0,"passthru":true,"topic":"","min":0,"max":"24","step":1,"x":290,"y":660,"wires":[["b57cdfc.ee7332"]]},{"id":"b57cdfc.ee7332","type":"function","z":"cb887fb5.a0b15","name":"tw","func":"var a = global.get(\"today\");\nvar b = global.get(\"yesterday\");\nvar c = [];\nvar tweak = msg.payload;\nvar hours = (tweak * 60) * 60 * 1000;\nfor(var i=0;i<24;i++){\n var x = b[i].x + hours;\n var y = b[i].y;\n c.push({\"x\":x,\"y\":y});\n}\n\nmsg.payload = [{\n \"series\": [\"Today\",\"Yesterday\"],\n \"data\": [a,c],\n \"labels\": [\"\"]\n}];\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":660,"wires":[["84742a15.c4d0e8"]]},{"id":"84742a15.c4d0e8","type":"ui_chart","z":"cb887fb5.a0b15","name":"","group":"de3ef089.0e5a1","order":0,"width":0,"height":0,"label":"TWEAKED","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#ff0000","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":670,"y":660,"wires":[[],[]]},{"id":"de3ef089.0e5a1","type":"ui_group","z":"","name":"Charts","tab":"e635eb13.e8f1c8","disp":true,"width":"6"},{"id":"e635eb13.e8f1c8","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}]

1 Like

Hotnipi

Thanks very much.

I shall have to look at it a few times.

My head is about to explode! Sinus problems. :(:sob: Sucks.

Just a quick question:

I was reading your latest post couple of times and everything went more complicated in every next try. :rofl: no offence

You lost me.

I was trying to keep the question simple - though that was difficult as I didn't quite get it all myself.

So although I may have made the question more complicated every time I posted/asked, that was because either I learnt something and the problem persisted, or I was trying to re-explain it a different way.

Colin,

Sorry for the long delay in replying.

Sinus problems and my head feels like it is about to explode. Not nice.

I have had a lot of down time the last few days.

That is something I shall look at/into.

I've been working on something I think is similar (sorry I'm a newb so could be wrong). My flow uses a home assistant history node (non-flattened array type) and a javascript node to plot an arbitrary number of series of arbitrary lengths on one chart. So far the charts are working as expected, but I'm struggling with getting legends to display.

Based on the nodered chart docs, it seems like the legend should be populated from the "series" array:

That's not working like it should (and I'm 99% sure my payload is the correct format). I even tried populating "labels" with friendly names as well, but of course that didn't work. I'm not sure what I'm missing to get legends to display. In case anyone wants to take a poke at it, here is the javascript out of my function node (for now, you have to manually enter hardcoded entity_id's at the top... fancy plans later, but legends first):

// Add the entity_id's to be charted in the list below
const entities = [
    "sensor.samjin_multi",
    "sensor.visonic_mct_340_sma"
];

var seriesArray = [];
var labelArray = [""];
//var labelArray = [];
var dataArray = [[0],[0]];

for(let i=0; i<msg.payload.length; i++)  { //loop input entities
    for(let j=0; j<entities.length; j++)  { //loop desired entities
        if(msg.payload[i][0].entity_id == entities[j])  {  //check matching entity
            seriesArray[j] = msg.payload[i][0].attributes.friendly_name;
            //labelArray[j] = msg.payload[i][0].attributes.friendly_name;
            for(let k=0; k<msg.payload[i].length; k++)  {
                dataArray[j][k] = {"x": Date.parse(msg.payload[i][k].last_updated),"y": parseFloat(msg.payload[i][k].state)};
            }
        }
    }
}

var output = [{
"series": seriesArray,
"data": dataArray,
"labels": labelArray
}];

var chartMsg = {payload: output};
return chartMsg;

Any ideas if/how I could make nodered chart legends work with this?

Cheers,
Kev