JSON Data From Soil Moisture to Chart

Hi,

I have a soil mositure data logger, I am able to extract JSON data via an API function which returns the following format:

[{"t":"2020-06-10T13:20:16.000Z","v":8.776,"ch":5},
{"t":"2020-06-10T13:18:00.000Z","v":0.508,"ch":3},
{"t":"2020-06-10T13:18:00.000Z","v":2.293,"ch":2},
{"t":"2020-06-10T13:18:00.000Z","v":0.45,"ch":4},
{"t":"2020-06-10T13:18:00.000Z","v":0.322,"ch":1},
{"t":"2020-06-10T12:20:16.000Z","v":8.794,"ch":5},
{"t":"2020-06-10T12:18:00.000Z","v":2.297,"ch":2},
{"t":"2020-06-10T12:18:00.000Z","v":0.443,"ch":4},
{"t":"2020-06-10T12:18:00.000Z","v":0.321,"ch":1},
{"t":"2020-06-10T12:18:00.000Z","v":0.501,"ch":3},
{"t":"2020-06-10T11:20:17.000Z","v":8.794,"ch":5},
{"t":"2020-06-10T11:18:00.000Z","v":2.298,"ch":2},
{"t":"2020-06-10T11:18:00.000Z","v":0.434,"ch":4},
{"t":"2020-06-10T11:18:00.000Z","v":0.318,"ch":1},
{"t":"2020-06-10T11:18:00.000Z","v":0.49,"ch":3},
{"t":"2020-06-10T10:20:16.000Z","v":8.794,"ch":5},
{"t":"2020-06-10T10:18:00.000Z","v":2.297,"ch":2},
{"t":"2020-06-10T10:18:00.000Z","v":0.437,"ch":4},
{"t":"2020-06-10T10:18:00.000Z","v":0.319,"ch":1},
{"t":"2020-06-10T10:18:00.000Z","v":0.486,"ch":3},
{"t":"2020-06-10T09:20:16.000Z","v":8.811,"ch":5},
{"t":"2020-06-10T09:18:00.000Z","v":0.458,"ch":4},
{"t":"2020-06-10T09:18:00.000Z","v":0.321,"ch":1},
{"t":"2020-06-10T09:18:00.000Z","v":0.502,"ch":3},
{"t":"2020-06-10T09:18:00.000Z","v":2.296,"ch":2},
{"t":"2020-06-10T08:20:16.000Z","v":8.811,"ch":5},
{"t":"2020-06-10T08:18:00.000Z","v":0.501,"ch":4},
{"t":"2020-06-10T08:18:00.000Z","v":0.327,"ch":1},
{"t":"2020-06-10T08:18:00.000Z","v":0.539,"ch":3},
{"t":"2020-06-10T08:18:00.000Z","v":2.294,"ch":2}]

I would like to chart the "v" value (voltage) against the time, "t". Each "ch" is a sperate moisture sensor and I would like to show these all the same chart. I am just struggling to get the data structure correct to flow into the chart node, can anyone give me some pointers?

Thanks Very Much

The simplest way is just to split the data then move the properties around a little to look like "live" data being injected.

[{"id":"14680093.15867f","type":"inject","z":"d1e29928.8fa058","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":1420,"wires":[["8bfdb1d0.cfe"]]},{"id":"8bfdb1d0.cfe","type":"function","z":"d1e29928.8fa058","name":"Example data","func":"msg.payload = [{\"t\":\"2020-06-10T13:20:16.000Z\",\"v\":8.776,\"ch\":5},\n{\"t\":\"2020-06-10T13:18:00.000Z\",\"v\":0.508,\"ch\":3},\n{\"t\":\"2020-06-10T13:18:00.000Z\",\"v\":2.293,\"ch\":2},\n{\"t\":\"2020-06-10T13:18:00.000Z\",\"v\":0.45,\"ch\":4},\n{\"t\":\"2020-06-10T13:18:00.000Z\",\"v\":0.322,\"ch\":1},\n{\"t\":\"2020-06-10T12:20:16.000Z\",\"v\":8.794,\"ch\":5},\n{\"t\":\"2020-06-10T12:18:00.000Z\",\"v\":2.297,\"ch\":2},\n{\"t\":\"2020-06-10T12:18:00.000Z\",\"v\":0.443,\"ch\":4},\n{\"t\":\"2020-06-10T12:18:00.000Z\",\"v\":0.321,\"ch\":1},\n{\"t\":\"2020-06-10T12:18:00.000Z\",\"v\":0.501,\"ch\":3},\n{\"t\":\"2020-06-10T11:20:17.000Z\",\"v\":8.794,\"ch\":5},\n{\"t\":\"2020-06-10T11:18:00.000Z\",\"v\":2.298,\"ch\":2},\n{\"t\":\"2020-06-10T11:18:00.000Z\",\"v\":0.434,\"ch\":4},\n{\"t\":\"2020-06-10T11:18:00.000Z\",\"v\":0.318,\"ch\":1},\n{\"t\":\"2020-06-10T11:18:00.000Z\",\"v\":0.49,\"ch\":3},\n{\"t\":\"2020-06-10T10:20:16.000Z\",\"v\":8.794,\"ch\":5},\n{\"t\":\"2020-06-10T10:18:00.000Z\",\"v\":2.297,\"ch\":2},\n{\"t\":\"2020-06-10T10:18:00.000Z\",\"v\":0.437,\"ch\":4},\n{\"t\":\"2020-06-10T10:18:00.000Z\",\"v\":0.319,\"ch\":1},\n{\"t\":\"2020-06-10T10:18:00.000Z\",\"v\":0.486,\"ch\":3},\n{\"t\":\"2020-06-10T09:20:16.000Z\",\"v\":8.811,\"ch\":5},\n{\"t\":\"2020-06-10T09:18:00.000Z\",\"v\":0.458,\"ch\":4},\n{\"t\":\"2020-06-10T09:18:00.000Z\",\"v\":0.321,\"ch\":1},\n{\"t\":\"2020-06-10T09:18:00.000Z\",\"v\":0.502,\"ch\":3},\n{\"t\":\"2020-06-10T09:18:00.000Z\",\"v\":2.296,\"ch\":2},\n{\"t\":\"2020-06-10T08:20:16.000Z\",\"v\":8.811,\"ch\":5},\n{\"t\":\"2020-06-10T08:18:00.000Z\",\"v\":0.501,\"ch\":4},\n{\"t\":\"2020-06-10T08:18:00.000Z\",\"v\":0.327,\"ch\":1},\n{\"t\":\"2020-06-10T08:18:00.000Z\",\"v\":0.539,\"ch\":3},\n{\"t\":\"2020-06-10T08:18:00.000Z\",\"v\":2.294,\"ch\":2}];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":320,"y":1420,"wires":[["c99c699d.b9dcc8"]]},{"id":"c99c699d.b9dcc8","type":"split","z":"d1e29928.8fa058","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":490,"y":1420,"wires":[["796742c6.3d432c"]]},{"id":"796742c6.3d432c","type":"change","z":"d1e29928.8fa058","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.ch","tot":"msg"},{"t":"set","p":"timestamp","pt":"msg","to":"payload.t","tot":"msg"},{"t":"move","p":"payload.v","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1420,"wires":[["29af209.92794e"]]},{"id":"29af209.92794e","type":"ui_chart","z":"d1e29928.8fa058","name":"","group":"6bbc8006.c17af","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":"86400","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":830,"y":1420,"wires":[[]]},{"id":"6bbc8006.c17af","type":"ui_group","z":"","name":"Switch","tab":"3f2ebb62.3fc404","order":1,"disp":true,"width":"6","collapse":false},{"id":"3f2ebb62.3fc404","type":"ui_tab","z":"d1e29928.8fa058","name":"Home","icon":"fa-tint","order":1,"disabled":false,"hidden":false}]

Thanks very much! If I wanted to pull out some topics and display these on a different chart would it be a case of using another split and a rule the specific "ch" numbers required?

Probably a switch node but yes.

Awesome thanks.

Might be pushing my luck, but what sort of methodology would you use to retrieve the same data format on a time basis and store this data for display and historical tracking?

I am thinking to store the data in a csv and publish that to a webpage chart, but maybe there is a better way?

Cheers

Hi
I have similar temperature data and use an InfluxDB node to store this in an InfluxDb database which is designed for time series data. You can then use Grafana as a multi user dashboard to view the data. It may sound complex, but there are plenty of resources and it can be installed on a pi or other hardware. I have a number of these and they work great

This is what I used to get started

Thanks for the suggestion, I'll check it out :+1:

Or you could just reformat the data from the chart into a csv file. Here is an example function that shoudl work

[{"id":"247ee957.a25736","type":"debug","z":"d1e29928.8fa058","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":1560,"wires":[]},{"id":"29269901.d23a06","type":"function","z":"d1e29928.8fa058","name":"Chart to CSV","func":"var d = msg.payload[0];\nvar cols = d.series;\nvar series = d.data;\nvar list = {};\n// iterate over all the series\nfor (var i=0; i<cols.length; i++) {\n    // and each data point\n    for (var j=0; j<series[i].length; j++) {\n        // create a new timestamped row if needed\n        if (!list[series[i][j].x]) { list[series[i][j].x] = new Array(d.series.length).fill('') }\n        // otherwise assign each datapoint to that timestamped row\n        list[series[i][j].x][i] = series[i][j].y; \n    }\n}\n\n// create a header line for csv\nvar res = [\"timestamp,\"+cols.join(',')];\n\nvar ordered = {};\n// sort the teimstamped rows into timestamp order\nObject.keys(list).sort().forEach(function(key) { \n    ordered[key] = list[key]; \n    // add the timestampt o the start of the row\n    ordered[key].unshift(parseInt(key));\n    // push them out as a comma separated string\n    res.push(ordered[key].join(','));\n});\n\n// finally join the rows as lines to complete the csv file\nmsg.payload = res.join(\"\\n\");\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":230,"y":1500,"wires":[["6da38900.fd0c48"]]},{"id":"6da38900.fd0c48","type":"trigger","z":"d1e29928.8fa058","name":"","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"250","extend":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":500,"y":1500,"wires":[["247ee957.a25736","3df76c65.9b73a4"]]},{"id":"3df76c65.9b73a4","type":"file","z":"d1e29928.8fa058","name":"","filename":"/tmp/mychart.csv","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":810,"y":1500,"wires":[[]]}]

Thanks very much, I'll take a look at it and see how I go :hugs: