Hi All,
I've problem with my project to create line chart. This chart combine in fix circle data and real time data, but the real time data doesn't work each the input data is updated. It only moving point to point, not create the line chart. Here is my code:
[{"id":"7037e1c.362942","type":"inject","z":"8d8b4aff.20e398","name":"","topic":"","payload":"","payloadType":"date","repeat":"60","crontab":"","once":true,"onceDelay":0.1,"x":148,"y":1128,"wires":[["5a6d7f96.e1f8b"]]},{"id":"5a6d7f96.e1f8b","type":"function","z":"8d8b4aff.20e398","name":"","func":"rnd = Math.round (Math.random()*5);\nmsg.payload = rnd;\nreturn msg;","outputs":1,"noerr":0,"x":272,"y":1064,"wires":[["5d5569a5.1d5aa8"]]},{"id":"5d5569a5.1d5aa8","type":"function","z":"8d8b4aff.20e398","name":"Pre-load test data","func":"\n/* This function creates a two data sets, with different topics,\n the same x values and different y values*/\n\n// Change the scale factor each time.\nvar scale = context.get('scale') || 0;\nif (msg.topic == \"Reset\") {\n scale = 0;\n}\nscale++;\ncontext.set('scale', scale);\n\n// This will be an array of {topic, data} objects\nvar dataPoints1 = []; // These will be the first array of data points \nvar dataPoints2 = []; // These will be the second array of data points \nvar dataPoints3 = [];\nvar dataPoints4 = [];\nvar dataPoints5 = [];\nvar dataPoints6 = [];\nvar numPoints = 1440; // We will create one more than this.\nvar adh = msg.payload;\n// hours + minutes convertion\nvar min = new Date().getHours() *60 + new Date().getMinutes()\n//create degree for 1440 point\nvar deg = 360/ 1440 * min\n\n var adhdata = {x:adh * Math.sin(radians(deg)), y:adh * Math.cos(radians(deg))};\n // build the data array \n dataPoints6.push(adhdata);\n\nfunction radians (degrees) {\n return degrees * Math.PI / 180;\n}\n\nnode.warn(deg+ \" \"+ adh +\" \"+min+\" \"+adhdata)\n\n\n// For the first data set create a sine wave\nfor (var i=0; i<=numPoints; i++) {\n var point = {};\n point.x = 1 * Math.sin(radians(360/1440*i));\n point.y =1 * Math.cos(radians(360/1440*i));\n // build the data array \n dataPoints1.push(point);\n}\n\n// For the first data set create a sine wave\nfor (var i=0; i<=numPoints; i++) {\n var point = {};\n point.x = 2 * Math.sin(radians(360/1440*i));\n point.y = 2 * Math.cos(radians(360/1440*i));\n // build the data array \n dataPoints2.push(point);\n}\n\nfor (var i=0; i<=numPoints; i++) {\n var point = {};\n point.x = 3 * Math.sin(radians(360/1440*i));\n point.y = 3 * Math.cos(radians(360/1440*i));\n // build the data array \n dataPoints3.push(point);\n}\n\nfor (var i=0; i<=numPoints; i++) {\n var point = {};\n point.x = 4 * Math.sin(radians(360/1440*i));\n point.y = 4 * Math.cos(radians(360/1440*i));\n // build the data array \n dataPoints4.push(point);\n}\n\nfor (var i=0; i<=numPoints; i++) {\n var point = {};\n point.x = 5 * Math.sin(radians(360/1440*i));\n point.y = 5 * Math.cos(radians(360/1440*i));\n // build the data array \n dataPoints5.push(point);\n}\n\nmsg.action = \"load\"; // This instructs the chart node to paint the data\n\n// The payload is an array of two {topic, data} objects\nmsg.payload = [\n {topic: \"1\", data: dataPoints1},\n {topic: \"2\", data: dataPoints2},\n {topic: \"3\", data: dataPoints3},\n {topic: \"4\", data: dataPoints4},\n {topic: \"5\", data: dataPoints5},\n {topic: \"6\", data: dataPoints6},\n ];\n\nreturn msg;","outputs":1,"noerr":0,"x":473,"y":1075.5333251953125,"wires":[["5cddd7de.1425c8","34e75463.eeba9c"]]},{"id":"5cddd7de.1425c8","type":"ui_template","z":"8d8b4aff.20e398","group":"265b73d7.0bdf2c","name":"Chart.js example","order":9,"width":"8","height":"8","format":"<script src=\"/Chart.bundle.min.js\"></script>\n<canvas id=\"myChartSimple1\" width=\"300\" height=\"300\"></canvas>\n<script>\n(function() {\n var chartID = \"myChartSimple1\"; // set this to the id you have specified in the canvas tag above\n // setup the chart definition as defined in the chart.js documentation, in addition setting up the topic\n // for each channel\n var chartDef = {\n type: 'line',\n data: {\n datasets: [{\n topic: \"6\", // used here not by chart.js\n label: \"6\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 2,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 1,\n data: [] // data is written here later\n }, {\n topic: \"2\", // used here not by chart.js\n label: \"2\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 0.1,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 0.2,\n data: [] // dta is written here later\n },\n {\n topic: \"3\", // used here not by chart.js\n label: \"3\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 0.1,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 0.2,\n data: [] // data is written here later\n },{\n topic: \"4\", // used here not by chart.js\n label: \"4\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 0.1,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 0.2,\n data: [] // data is written here later\n },\n {\n topic: \"5\", // used here not by chart.js\n label: \"5\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 0.1,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 0.2,\n data: [] // data is written here later\n },\n {\n topic: \"1\", // used here not by chart.js\n label: \"1\",\n yAxisID: \"1\",\n fill: false,\n lineTension: 0,\n borderColor: \"#0000ff\",\n pointRadius: 0.1,\n pointHoverRadius: 2,\n pointBorderColor: \"#ff0000\",\n pointBackgroundColor: \"#ff0000\",\n backgroundColor: \"#ff0000\",\n borderWidth: 0.2,\n data: [] // data is written here later\n }]\n },\n options: {\n scales: {\n xAxes: [{\n type: 'linear',\n position: 'bottom',\n ticks:{\n min:-5,\n max:5\n }\n \n }\n ],\n yAxes: [{\n id: \"1\",\n ticks: {\n min:-5,\n max:5\n }\n \n }]\n },\n animation: {\n duration: 0\n }\n }\n }\n \n/***** You shouldn't normally need to change anything below here *****/ \n var myChart = null;\n var loaded = false; // indicates whether we have already had a load action\n var chartTimeSpan;\n var chartMaxPoints;\n\n function doChart(msg, scope) {\n if (!myChart) {\n // chart does not exist so load the data and create it\n var ctx = document.getElementById(chartID);\n myChart = new Chart(ctx, chartDef); \n }\n // chart already exists, update it\n var datasets = myChart.data.datasets;\n // is this a load or preload action?\n if (msg.action === \"load\" || msg.action === \"preload\") {\n // yes, do not allow preload if we have already had a load\n // so do it if this is a load or we have not previously had a load\n if (msg.action === \"load\" || !loaded) {\n // pick up chartTimeSpan and chartMaxPoints if they have been provided\n if (typeof msg.chartTimeSpan != 'undefined') {\n chartTimeSpan = msg.chartTimeSpan;\n }\n if (typeof msg.chartMaxPoints != 'undefined') {\n chartMaxPoints = msg.chartMaxPoints;\n }\n \n // replace existing data for matching topics\n for (var j = 0; j < msg.payload.length; j++) {\n var topic = msg.payload[j].topic;\n // find it in the chart\n for (var i = 0; i < datasets.length; i++) {\n if (datasets[i].topic == topic) {\n // if stripping old samples by time is required then ensure the x value is Date\n if (chartTimeSpan > 0 ) {\n var data = msg.payload[j].data;\n for (var k = 0; k < data.length; k++) {\n if (typeof data[k].x === \"string\") {\n data[k].x = new Date(data[k].x);\n }\n }\n }\n if (chartDef.type !== \"bar\") {\n datasets[i].data = msg.payload[j].data;\n } else {\n // bar chart so x values must go to labels and y values to dataset\n datasets[i].data = [];\n myChart.data.labels = [];\n var data = msg.payload[j].data;\n for (var k = 0; k < data.length; k++) {\n datasets[i].data.push(data[k].y);\n myChart.data.labels.push(data[k].x);\n }\n }\n break;\n }\n }\n }\n }\n if (msg.action === \"load\") loaded = true;\n myChart.update();\n } else {\n // does the topic match one of the datasets?\n for (var i = 0; i < datasets.length; i++) {\n if (datasets[i].topic == msg.topic) {\n // if stripping old samples by time is required then ensure the x value is Date\n if (chartTimeSpan > 0 && typeof msg.payload.x === \"string\") {\n msg.payload.x = new Date(msg.payload.x);\n }\n if (chartDef.type !== \"bar\") {\n datasets[i].data.push(msg.payload);\n } else {\n // bar chart so x value must go to labels and y value to dataset\n datasets[i].data.push(msg.payload.y);\n myChart.data.labels.push(msg.payload.x);\n }\n myChart.update();\n break;\n }\n }\n }\n // strip off samples older than now\n // charTimeSpan == 0 implies don't do it\n var shifted = false;\n if (chartTimeSpan > 0) {\n var now = new Date();\n var oldestTimeAllowed = now - chartTimeSpan;\n for (var i = 0; i < datasets.length; i++) {\n dataset = datasets[i];\n while(dataset.data[0] && getTime(dataset.data[0].x) < oldestTimeAllowed) {\n dataset.data.shift();\n shifted = true;\n }\n }\n }\n // strip samples off the front if there are now too many\n // charTimeSpan == 0 implies don't do it\n if (chartMaxPoints > 0) {\n for (var i = 0; i < datasets.length; i++) {\n dataset = datasets[i];\n while(dataset.data.length > chartMaxPoints) {\n dataset.data.shift();\n shifted = true;\n }\n }\n }\n if (shifted) {\n myChart.update();\n }\n };\n\n // gets the time of an x value, works for strings or Date types\n function getTime(x) {\n if (typeof x === \"string\") x = new Date(x);\n return x.getTime();\n }\n \n // builds the preload message for sending back to the chart helper\n function preloadMsg() {\n var preMsg = {action: \"preload\", payload: \"preload\"};\n // build array of topics in chart\n var topics = [];\n for (var i=0; i<chartDef.data.datasets.length; i++) {\n topics.push(chartDef.data.datasets[i].topic);\n }\n preMsg.topics = topics;\n // has the chart already been created\n if (myChart) {\n preMsg.lastXValue = 1;\n } else {\n preMsg.lastXValue = 0;\n }\n return preMsg;\n }\n(function(scope) {\n // this code gets run when the a view is opened on the node in the browser\n // send a preload message back to node red to ask it send\n // us a complete set of data. Pass down max points and time span to the helper node for it to use\n // plus an array of the topics of interest\n scope.send( preloadMsg() );\n \n scope.$watch('msg', function(msg) {\n if (msg) {\n doChart(msg, scope);\n }\n });\n })(scope);\n \n})();\n</script>\n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":714,"y":1074,"wires":[["fe4d5ef1.bb64f8"]]},{"id":"fe4d5ef1.bb64f8","type":"debug","z":"8d8b4aff.20e398","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":883,"y":1169,"wires":[]},{"id":"34e75463.eeba9c","type":"debug","z":"8d8b4aff.20e398","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":596,"y":1170,"wires":[]},{"id":"265b73d7.0bdf2c","type":"ui_group","z":"","name":"Chart ","tab":"7d401993.f8f3b","order":1,"disp":true,"width":"12","collapse":false},{"id":"7d401993.f8f3b","type":"ui_tab","z":"","name":"Chart.js example","icon":"dashboard","order":2}]