Rich data visualization

Hello
I am a neophyte Node-Red user but I have already built a flow to act as an instrument interface. The flow runs on an embedded system with Arm A53 micro-controller and FPGA logic. I have been able to get sensor data from the FPGA and into a Dashboard Chart node. The web interface has a switch to enable auto-trigger which updates the data in the Chart at a rapid rate. I use the Chart node in one-shot mode where I send it a complete vector of data all at once and it replaces the previous plot with the new one. It looks like a digital oscilloscope when it is running. Thanks for all the help.

This experiment succeeded as a proof of concept but our production instruments need richer data visualization like scatter plots, colorized heat maps and digital phosphor style rendering.

My question is whether Node-Red can be readily extended to use more sophisticated commercial javascript data visualization libraries?

My day job is FPGA programmer but I like the way Node-Red lets me hack together a quick interface for demonstration and testing. A professional web developer would responsible for the production interface.

1 Like

You may find uibuilder a better match for your requirements than the Node-red dashboard since as I understand it, you are free to use whatever libraries you like.

Hopefully you will be able to share whatever you create with the community

1 Like

Simple example using http-in/out + websocket nodes

open the webpage at <nodered ip:port>/chart and press the inject button.
The data generator generates a datapoint every millisecond for 5 seconds (a lot of data), it streams the chart (apache echarts) -

Example flow:

[{"id":"6353e1f90e6bf036","type":"http in","z":"fae101de87421f64","name":"","url":"/chart","method":"get","upload":false,"swaggerDoc":"","x":200,"y":120,"wires":[["516249feec1b3670"]]},{"id":"0befe11c2d87ac22","type":"http response","z":"fae101de87421f64","name":"","statusCode":"","headers":{},"x":510,"y":120,"wires":[]},{"id":"516249feec1b3670","type":"template","z":"fae101de87421f64","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n    <title>Real-Time ECharts Chart</title>\n    <script src=\"https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js\"></script>\n    <style>\n        #chart {\n            width: 100%;\n            height: 600px;\n        }\n    </style>\n</head>\n<body>\n    <div id=\"chart\"></div>\n    <script>\n        // Initialize ECharts\n        const chartDom = document.getElementById('chart');\n        const myChart = echarts.init(chartDom);\n        let dataPoints = [];\n        const MAX_POINTS = 1000;\n\n        // Initial chart configuration\n        let option = {\n            title: {\n                text: 'Real-Time Data Stream'\n            },\n            tooltip: {\n                trigger: 'axis'\n            },\n            dataZoom: [\n                {\n                type: 'inside'\n                },\n                {\n                type: 'slider'\n                }\n            ],\n            xAxis: {\n                type: 'time',\n                splitLine: {\n                    show: false\n                }\n            },\n            yAxis: {\n                type: 'value'\n            },\n            series: [{\n                name: 'Value',\n                type: 'line',\n                showSymbol: false,\n                data: dataPoints\n            }]\n        };\n        myChart.setOption(option);\n\n        const socket = new WebSocket(location.origin.replace(/^http/, 'ws') + '/ws/chart_data');\n\n        socket.onmessage = (event) => {\n            const newData = JSON.parse(event.data);\n            const timestamp = new Date().getTime();\n            \n            dataPoints.push({\n                name: timestamp,\n                value: [timestamp, newData.value]\n            });\n\n            if (dataPoints.length > MAX_POINTS) {\n                dataPoints.shift();\n            }\n\n            myChart.setOption({\n                series: [{\n                    data: dataPoints\n                }]\n            });\n        };\n\n        window.addEventListener('resize', () => {\n            myChart.resize();\n        });\n    </script>\n</body>\n\n</html>","output":"str","x":360,"y":120,"wires":[["0befe11c2d87ac22"]]},{"id":"6bef3acd4f7f9f0d","type":"websocket out","z":"fae101de87421f64","name":"","server":"0333b76e0face47c","client":"","x":570,"y":180,"wires":[]},{"id":"37f36e4b77ce0b46","type":"inject","z":"fae101de87421f64","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":180,"wires":[["5f5b4928cf73a7b7"]]},{"id":"5f5b4928cf73a7b7","type":"function","z":"fae101de87421f64","name":"data generator","func":"\nfunction generate(){\n    return {payload:{        value: Math.random() * 100}\n    }\n}\n\nconst timer = setInterval(() => {\n    node.send(generate())\n}, 1);\n\n\nsetTimeout(()=>{\n    clearInterval(timer)\n},5000)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":180,"wires":[["6bef3acd4f7f9f0d"]]},{"id":"0333b76e0face47c","type":"websocket-listener","path":"/ws/chart_data","wholemsg":"false"}]
1 Like

you can import a richer charting package, such as chart.js, into a dashboard template node

This is perfect for UIBUILDER. It is specifically designed to allow developers to be able to use existing web development tooling and workflows while providing a lightweight data interface to/from Node-RED using a simple client library.

1 Like