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"}]