So, if anybody is interested to play with flexdash / plotly here's another messy flow Thanks again Thorsten for your help.
- The plot data is being stored in an array (context of Node-RED) and it does not get lost after closing the browser tab. Also, one data line (CH3) receives random values every second
- sometimes refresh (F5) fails, which I still need to figure out why (probably because of the delayed
idle event
I am (ab)using
[{"id":"bad040845be2efb7","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"9bcce05f35579a45","type":"flexdash custom","z":"bad040845be2efb7","fd_container":"a96ede31d15e8fcc","fd_cols":"5","fd_rows":"5","fd_array":false,"fd_array_max":10,"fd_output_topic":"","fd_loopback":false,"name":"Plotly","title":"Plotly ESM","sfc_source":"<template>\n <div class=\"w-100 h-100\" ref=\"plotly\">\n </div>\n</template>\n\n<script>\n import Plotly from \"plotly.js/dist/plotly.js\"\n\nexport default { \n props: {\n payload: { default: null, type: Array },\n options: { default: {}, type: Object },\n \n },\n emits: ['send'],\n\n data() { return {\n plot: null,\n }},\n\n computed: {\n columnar() {\n if (!this.payload || !Array.isArray(this.payload)) return null\n return this.transpose(this.payload)\n }\n },\n\n // mounted happens after props and data are init'd\n mounted() { \n console.log(\"mounted\") \n this.create_plot() \n },\n\n watch: {\n payload(v) { this.plot_data(v) },\n // options(v) { this.create_plot() },\n \n },\n\n methods: {\n create_plot() {\n // rko: init empty plot\n this.plot = Plotly.newPlot(this.$refs.plotly, [], {title: \"\", xaxis: {type: 'date'} }, { displaylogo: false, displayModeBar: true,\n scrollZoom: true, autosize: true});\n\n console.log(\"plot init done\")\n this.$emit(\"send\", {\"plot_init_done\": true})\n \n //this.plot = Plotly.newPlot(this.$refs.plotly, data, this.options)\n //console.log(\"PLOT:\", Object.keys(this.plot))\n //console.log(\"payload: \", this.payload);\n },\n\n plot_data(payload){\n \n console.log(\"msg: \", payload);\n if(payload.topic == \"measurement data\"){\n Plotly.addTraces(this.$refs.plotly, {\n type: \"scattergl\",\n //mode: \"line\",\n mode: \"spline\",\n x: payload.data[0],\n y: payload.data[1],\n name: payload.data[2].name,\n marker: {color: typeof payload.data[2].color == \"string\" ? payload.data[2].color : undefined },\n visible: typeof payload.data[2].visible != \"undefiend\" ? payload.data[2].visible : true\n }, payload.channel_nbr); // first trace is 0\n \n }else if(payload.topic == \"live data\"){\n Plotly.extendTraces(this.$refs.plotly, {\n x: [[payload.timestamp]],\n y: [[payload.value]]\n },\n \n [payload.channel_nbr]); // channel number, has to be an index!\n }\n \n\n }\n\n },\n \n}\n</script>","import_map":{"plotly.js/dist/plotly.js":"https://ga.jspm.io/npm:plotly.js@2.7.0/dist/plotly.js"},"x":1030,"y":280,"wires":[["809cfcb5c0b64c91","b222d159488d5db8"]]},{"id":"da66d305d754fd91","type":"split","z":"bad040845be2efb7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":630,"y":280,"wires":[["ba05af71821ffa99"]]},{"id":"809cfcb5c0b64c91","type":"change","z":"bad040845be2efb7","name":"","rules":[{"t":"set","p":"plot_init_done","pt":"flow","to":"true","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"measurement_data","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":535,"y":280,"wires":[["da66d305d754fd91"]],"l":false},{"id":"ba05af71821ffa99","type":"change","z":"bad040845be2efb7","name":"","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.data","tot":"msg"},{"t":"set","p":"payload.topic","pt":"msg","to":"measurement data","tot":"str"},{"t":"set","p":"payload.channel_nbr","pt":"msg","to":"parts.index","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":280,"wires":[["9bcce05f35579a45"]]},{"id":"e4ef603517a1654a","type":"function","z":"bad040845be2efb7","name":"live data","func":"let measurement_data = flow.get(\"measurement_data\", \"default\");\n\n// check if channel was initialized (channel_nbr equals index of array element)\n/*if (msg.channel_nbr > measurement_data.length - 1) {\n\n measurement_data.push([[], [], { name: msg.channel_name }]);\n}*/\n\n// store current measurement in memory\nmsg.timestamp = new Date().toISOString().replace(\"T\", \" \").replace(\"Z\", \"\");\n\n\nmsg.payload = Math.random()*10;\nmeasurement_data[msg.channel_nbr][0].push(msg.timestamp);\nmeasurement_data[msg.channel_nbr][1].push(msg.payload);\n\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":420,"wires":[["f2927159ceec149d"]]},{"id":"d90d6df6f9190c92","type":"inject","z":"bad040845be2efb7","name":"live data CH1","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"channel_nbr","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"","payload":"","payloadType":"num","x":150,"y":380,"wires":[["e4ef603517a1654a"]]},{"id":"a5150785cb42641f","type":"change","z":"bad040845be2efb7","name":"prepare msg for frontend","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.value","tot":"msg"},{"t":"set","p":"payload.timestamp","pt":"msg","to":"timestamp","tot":"msg"},{"t":"set","p":"payload.channel_nbr","pt":"msg","to":"channel_nbr","tot":"msg"},{"t":"set","p":"payload.topic","pt":"msg","to":"live data","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":830,"y":420,"wires":[["9bcce05f35579a45"]]},{"id":"3510082adf3fcb5b","type":"inject","z":"bad040845be2efb7","name":"live data CH2","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"channel_nbr","v":"2","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"","payload":"","payloadType":"num","x":150,"y":420,"wires":[["e4ef603517a1654a"]]},{"id":"c94301117ce1bf05","type":"flexdash ctrl","z":"bad040845be2efb7","name":"","fd":"8c6540ab2d9a3573","weak_fd":"","fd_output_topic":"","x":110,"y":160,"wires":[["0477a14e03f1401d","02ef6307327ee710"]]},{"id":"0477a14e03f1401d","type":"debug","z":"bad040845be2efb7","name":"debug 99","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":280,"y":200,"wires":[]},{"id":"02ef6307327ee710","type":"switch","z":"bad040845be2efb7","name":"","property":"payload.type","propertyType":"msg","rules":[{"t":"eq","v":"idle client","vt":"str"},{"t":"eq","v":"new client","vt":"str"},{"t":"eq","v":"change tab","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":570,"y":160,"wires":[["9e1cb1232ed3889e"],["9bcce05f35579a45"],[]]},{"id":"9e1cb1232ed3889e","type":"change","z":"bad040845be2efb7","name":"close","rules":[{"t":"set","p":"plot_init_done","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":140,"wires":[[]]},{"id":"6748e1622121e9f3","type":"inject","z":"bad040845be2efb7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":100,"wires":[["45dc46e1fd0f3669"]]},{"id":"45dc46e1fd0f3669","type":"function","z":"bad040845be2efb7","name":"init context","func":"// todo: allow dynamic channel name configuration \n\nlet nbr_of_channels = 14 - 1; \ntmp_array = [];\nfor (let c = 0; c <= nbr_of_channels; c++) {\n tmp_array.push([[], [], { name: \"CH\" + c }]);\n}\n\n\n\ntmp_array[0][2].name = \"Set Point\";\ntmp_array[1][2].name = \"TC1\";\ntmp_array[2][2].name = \"TC2\";\ntmp_array[3][2].name = \"TC3\";\ntmp_array[4][2].name = \"TC4\";\ntmp_array[5][2].name = \"TC5\";\ntmp_array[6][2].name = \"TC6\";\ntmp_array[7][2].name = \"TC7\";\ntmp_array[8][2].name = \"TC8\";\ntmp_array[9][2].name = \"TC9\";\ntmp_array[10][2].name = \"TC10\";\ntmp_array[11][2].name = \"TC11\";\ntmp_array[12][2].name = \"TC12\";\ntmp_array[13][2].name = \"Hidden Line\"; \ntmp_array[13][2].visible = \"legendonly\"; \ntmp_array[13][2].color = \"pink\"; \n\nflow.set(\"measurement_data\", tmp_array, \"default\");\n\nflow.set(\"plot_init_done\", false, \"default\")\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":100,"wires":[[]]},{"id":"b222d159488d5db8","type":"debug","z":"bad040845be2efb7","name":"debug 101","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1190,"y":280,"wires":[]},{"id":"d68d9f82c245a89e","type":"inject","z":"bad040845be2efb7","name":"live data CH3","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"channel_nbr","v":"3","vt":"num"}],"repeat":"1","crontab":"","once":false,"onceDelay":"5","topic":"","payload":"","payloadType":"num","x":160,"y":460,"wires":[["e4ef603517a1654a"]]},{"id":"f2927159ceec149d","type":"switch","z":"bad040845be2efb7","name":"","property":"plot_init_done","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":650,"y":420,"wires":[["a5150785cb42641f"]]},{"id":"784bb3ac040bfd41","type":"comment","z":"bad040845be2efb7","name":"do some inits after startup / deploy","info":"","x":200,"y":60,"wires":[]},{"id":"8aa9674a8dd22f27","type":"comment","z":"bad040845be2efb7","name":"send data to the frontend / plotly","info":"CH3 sends a random value to the plot every second","x":190,"y":340,"wires":[]},{"id":"480aad50f022c835","type":"comment","z":"bad040845be2efb7","name":"handle ui events (open, close)","info":"","x":640,"y":100,"wires":[]},{"id":"74d1bafad2336a06","type":"comment","z":"bad040845be2efb7","name":"init load data from memory (context)","info":"","x":660,"y":240,"wires":[]},{"id":"a96ede31d15e8fcc","type":"flexdash container","name":"NFDC","kind":"StdGrid","fd_children":",7d8110bad209c9b4,e7c4f917522b9e07,73d471ead270d371,21933cee466bf173,9bcce05f35579a45,a2422671d593b0ee,585ad6165adfc57b,862ff94b5a829c55","title":"NFDC","tab":"1e908252f3517797","min_cols":"6","max_cols":"20","unicast":"ignore","parent":"","solid":false,"cols":"1","rows":"1"},{"id":"1e908252f3517797","type":"flexdash tab","name":"","icon":"mdi-view-dashboard","title":"plotly tab","fd_children":",a96ede31d15e8fcc","fd":"8c6540ab2d9a3573"}]
@tve this is more of a general question regarding FD ctrl
: are you planning to implement a close
event?