Help in Installing UIBuilder

3: Pick up a chart library like uPlot or whatever favourite takes you fancy.
4. hotnipi's fancy gauge is available as a component - pretty comprehensive, you use it as a custom web component. GitHub - TotallyInformation/gauge-hotnipi: A nice looking gauge W3C component gifted by hotnipi for use with Node-RED, uibuilder and other uses - most chart libraries also have gauges if you want something simpler.
5. Everything is possible with uibuilder! I had thought it was on my backlog but apparently not. I'd build it as a web component for use anywhere. With enough persuasion, that might become my next piece of work :slight_smile: The source-code from hotnipi doesn't look too complex so should be feasible to do in not too much time. Of course, you may also find an existing external library.

Where I mention external libraries, remember that uibuilder has its library manager so that you can install libraries/packages from the npm catalogue, GitHub, local or anywhere that the npm utility recognises. When added, their folders get added to the Node-RED web server (or the separate custom one that uibuilder can provide if you want to use that) so that it is easy to reference them from your front end code.

You can see in that example that I've got chart.js available along with markdown and other useful libraries all of which I can use in the front-end pages.

I Like Apex Chart and have actually a working graph i use extensively in my dashboard-1.

my project here

Apex Chart with Customization

so how do I proceed ? I have no knowledge of how to install libraries. in my template node in db-1 i have just given below as the first line and other function copied from internet. i really dont know how it works. but it works.

<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>

this is screengrab of my working db-1 (yes it has hotNipi 's gauges as well)

You absolutely can do that with uibuilder as well if you are happy to run things from the Internet. Start there anyway, we can always tweak it later, I often do that myself.

Slight tweak on that code for uibuilder though - just for maxumum performance - the default template index.html has this in the head:

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
    <script defer src="../uibuilder/uibuilder.iife.min.js"></script>
    <!-- <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script> -->
    <!-- #endregion -->

So adjust that to look like:

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
    <script defer src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <script defer src="../uibuilder/uibuilder.iife.min.js"></script>
    <script defer src="./index.js"></script>
    <!-- #endregion -->

That loads the external library as efficiently as possible and puts in the default index.js which is where you can then add any front-end JavaScript for the chart library should you need any.

I started work on a state-trail equivalent as a web component if anyone is interested.

No SVG needed, simple use of CSS flexbox.

Still needs some work but this has generated some neat ideas for my web components including simplifying data entry for uibuilder users (most of my components do not need uibuilder but are progressively enhanced by it).

Need to add in time and number limits, some stats, labels, etc. But the basics are there.

I'll be adding some "standard" features to all my components because of this:

  • inherit-style attribute (to pass external styles into the component).
  • topic and var attributes mainly for uibuilder users to automate both data entry and attribute/slot content updates.
  • A standardised configuration function
  • A standardised version string.

If anyone wants this kind of thing, let me know so I don't just keep playing with them but actually realease them!

The other component that is vaguely usable is the visible-console component.

1 Like

A bit of fun with that ...
-- User: "We have quite many states so they are pain to configure by hand. Can you make states configurable via msg.ui_control?"
-- Me: "For sure. Wait for next release. Just curious - how many is quite many?
-- User: "We have about 130 states, they dont happen all in one series but ..."

So you know :smiley:

And if you hit the invisible state problem (too short so the browser just doesn render it) I'd love to hear about the solution.

:rofl:

So I don't even have any of these programmed in yet:

  • Start/end state times
  • multi-entries (e.g. send cache)
  • multi-timelines
  • State labels
  • axis labels
  • limits: number of entries & time

So I've quite a ways to go. :slight_smile:

But I wanted to have a go at creating a state-timeline component with no dependencies and no SVG - just CSS flexbox. So the basics are there - that was the easy bit of course.

However, pre-programmed states will be easy as they are already in a component config variable that can be externally changed very easily.

Yes, that is the issue with any timeline of course. I'll be adding the limits so people can control things manually. For automatic use, possibly the best bet would be an overflow onto a new line with previous lines simply frozen.

You could, with my approach - not sure about an SVG approach - allow x-axis overflow to allow scrolling I suppose. Not sure how easy that would be though.

I'm watching my test page slowly click up every 3s at present, up to nearly 1,900 entries. Performance and memory all seem under control so that's good anyway.

Really, once you reach a certain level of complexity, people should switch to a more appropriate tool such as Grafana or a dedicated library. Keep simple things simple.

Screen recording:

Animation1

The invisible state can occur even if you limit the amount of records or timeframe.
If the data is something like this:
false - minute
true - 5 hours
false - 1 millisecond
true - 5 hours
false - minute

Then depending on total size of widget it is highly possible that that millisecond is too small to render.

As it is not too long period and the count of records is not high - not much excuses to provide why that display can't be taken as source of truth.
I tried to find solution by introducing dot's in case the math based prediction said that the invisible state may occur. But that wasn't accurate so I can't say it is solution.

Hmm, possibly the option of a minimum width?

Does the Grafana state-timeline widget cope with this issue?

With min width you affect position of other states thus result is not accurate. Maybe it is fine. I don't remember why I didn't take that option. But 1px in those conditions is very big thing. Relatively thinking. And for sure the 1px is not smallest you can go.

Edit: the situation above is with one such entry only. But if there is more the accuracy goes worse and one moment if you have tickmarks for reference, it goes too much off. That I think was reason why I didn't take it.

Don't know what Grafana does but for most setups it offers quit fancy queries and optimizes data before renderings so options are wider. For live data and no optimization like this situation, the toolset is tiny.

I guess I've not considered such a timeline as needing extreme accuracy. So maybe a niche requirement? More of an indicator for me, especially as the number of status changes racks up.

I suspect that people need to use it a bit more realistically. :grinning:

For my use case, the minimum resolution is one minute and Max duration I would plot is 480 minutes.
This is for recording uptime and downtime (only two states) of a machine. I understand the larger scope may be different for different users. :grinning:

1 Like

:person_raising_hand:

2 Likes

No progress till now, I am chasing my tail and could not get it to work. this is may not be as easy as HTML table.
if possible a little more help in getting the below done.

[{"id":"f5facf6a3c587b3f","type":"inject","z":"be6d7a036125d1ad","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1575,"y":700,"wires":[["d0f78283b65252c1"]]},{"id":"f7f42222392270d0","type":"ui_template","z":"be6d7a036125d1ad","group":"5b5ee9f169c93ecf","name":"Apex-Chart","order":12,"width":"32","height":"15","format":"<script src=\"https://cdn.jsdelivr.net/npm/apexcharts\"></script>\n<div id=\"chart\"></div>\n\n<script>\n\n(function(scope)\n                {scope.$watch('msg', function(msg)\n                    {if (msg){var options =\n                        {series: msg.payload,\n                        chart:{type: 'line',stacked: false,height: 355,background:'#000',zoom:\n                                {type: 'x',enabled: true,autoScaleYaxis: true},\n                            toolbar:{autoSelected: 'zoom'}},\n                        dataLabels:{enabled: false},\n                        markers:{size: 0,},\n                        theme: {mode: 'dark'},\n                        colors: ['#FA2E2E', '#FAFA23', '#546E7A', ,'#FFFFFF','#E91E63', '#FF9800'],\n                \n                title: {text: msg.charttitle,align: 'center',margin: 10,offsetX: 0,offsetY: 0,floating: false,style: {fontSize:30,fontWeight: 'bold',fontFamily: undefined,color: 'yellow'},},\n                stroke:{width: [2,2,2,1,2,1],curve: 'smooth'},\n                yaxis:[\n                {labels:{formatter: function (val){return val.toFixed(1);},},min:msg.ymin1,max:msg.ymax1,title: { text: msg.axistitle1, style: {color: \"#FA2E2E\"}},},\n                {labels:{formatter: function (val){return val.toFixed(0);},},min:msg.ymin2,max:msg.ymax2,title: { text: msg.axistitle2, style: {color: \"#FAFA23\"}},},\n                {labels:{formatter: function (val){return val.toFixed(1);},},min:msg.ymin3,max:msg.ymax3,title: { text: msg.axistitle3, style: {color: \"#546E7A\"}},},\n                {labels:{formatter: function (val){return val.toFixed(1);},},min:msg.ymin4,max:msg.ymax4,title: { text: msg.axistitle4, style: {color: \"#FFFFFF\"}},},\n                ],\n\n            xaxis: {lines: {show: false,},type: 'datetime',datetimeUTC: false,labels: {format: 'dd/MMM HH:mm',},},\n            tooltip: {enabled: true,style: {fontSize: '12px',fontFamily: undefined},x: {show: true,format: 'dd/MMM HH:mm',},  row: {colors: undefined,opacity: 0.5},\n                column: {colors: undefined,opacity: 0.5},\n                padding: {top: 0,right: 0,bottom: 0,left: 0},},\n                    grid: {show: true,borderColor: '#ffffff',strokeDashArray: 0,position: 'back',\n                    xaxis: {lines: {show: false}},   \n                    yaxis: {lines: {show: false}},\n                    row: {colors: undefined,opacity: 0.5},  \n                    column: {colors: undefined,opacity: 0.5},  \n                    padding: {top: 0,right: 0,bottom: 0,left: 0},}};\n\n\nsetTimeout( ()=> {if(scope.chart){scope.chart.updateOptions(options)}else {scope.chart = new ApexCharts(document.querySelector(\"#chart\"), options);scope.chart.render();}}, 1000)}});})(scope);\n\n</script>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","className":"","x":1920,"y":700,"wires":[[]]},{"id":"d0f78283b65252c1","type":"change","z":"be6d7a036125d1ad","name":"Prepare Chart Data","rules":[{"t":"set","p":"charttitle","pt":"msg","to":"HRS Holding Temp/Flow rate / Divert valve status","tot":"str"},{"t":"set","p":"msg.axistitle1","pt":"msg","to":"Holding Temp","tot":"str"},{"t":"set","p":"msg.axistitle2","pt":"msg","to":"Flow Rate","tot":"str"},{"t":"set","p":"msg.axistitle3","pt":"msg","to":"Divert Status","tot":"str"},{"t":"set","p":"msg.axistitle4","pt":"msg","to":"Divert Temp","tot":"str"},{"t":"set","p":"ymin3","pt":"msg","to":"-5","tot":"num"},{"t":"set","p":"ymax3","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"ymin2","pt":"msg","to":"600","tot":"num"},{"t":"set","p":"ymax2","pt":"msg","to":"3000","tot":"num"},{"t":"set","p":"ymin1","pt":"msg","to":"20","tot":"num"},{"t":"set","p":"ymax1","pt":"msg","to":"150","tot":"num"},{"t":"set","p":"ymax4","pt":"msg","to":"150","tot":"num"},{"t":"set","p":"ymin4","pt":"msg","to":"20","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"[{\"name\":\"Holding temperature (°C)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":103},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":102},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":101},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":105},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":101},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":88},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":91},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":94},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":94},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":95},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":96},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":96},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":98},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":102},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":105},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":106},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":107},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":108},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":108},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":106},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":98},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":78},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":58},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":46}]},{\"name\":\"Flow Rate (LPH)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":1256},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":1185},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":1256},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":1090},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":948},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":0}]},{\"name\":\"Divert Status (Fwd/Div)\",\"type\":\"area\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":-0.5}]},{\"name\":\"Divert Temp (Deg)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":99}]}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1735,"y":700,"wires":[["f7f42222392270d0"]]},{"id":"5b5ee9f169c93ecf","type":"ui_group","name":"demo","tab":"195948bb680041dd","order":1,"disp":false,"width":"32","collapse":false,"className":""},{"id":"195948bb680041dd","type":"ui_tab","name":"Demo","icon":"dashboard","disabled":false,"hidden":false}]

I will have a look.

OK, so a bit quick and dirty but should give you a decent starting point.

Slightly adjusted input data to fix a couple of minor issues:

[{"id":"63f33dbd08d64d26","type":"inject","z":"30fdd9a9702231b0","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":575,"y":7640,"wires":[["41786b71f450a806"]],"l":false},{"id":"41786b71f450a806","type":"change","z":"30fdd9a9702231b0","name":"Prepare Chart Data","rules":[{"t":"set","p":"charttitle","pt":"msg","to":"HRS Holding Temp/Flow rate / Divert valve status","tot":"str"},{"t":"set","p":"axistitle1","pt":"msg","to":"Holding Temp","tot":"str"},{"t":"set","p":"axistitle2","pt":"msg","to":"Flow Rate","tot":"str"},{"t":"set","p":"axistitle3","pt":"msg","to":"Divert Status","tot":"str"},{"t":"set","p":"axistitle4","pt":"msg","to":"Divert Temp","tot":"str"},{"t":"set","p":"ymin3","pt":"msg","to":"-5","tot":"num"},{"t":"set","p":"ymax3","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"ymin2","pt":"msg","to":"600","tot":"num"},{"t":"set","p":"ymax2","pt":"msg","to":"3000","tot":"num"},{"t":"set","p":"ymin1","pt":"msg","to":"20","tot":"num"},{"t":"set","p":"ymax1","pt":"msg","to":"150","tot":"num"},{"t":"set","p":"ymax4","pt":"msg","to":"150","tot":"num"},{"t":"set","p":"ymin4","pt":"msg","to":"20","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"[{\"name\":\"Holding temperature (°C)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":103},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":102},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":101},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":105},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":101},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":88},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":91},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":94},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":94},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":95},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":96},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":96},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":98},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":97},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":102},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":104},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":105},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":106},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":107},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":108},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":108},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":106},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":98},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":78},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":58},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":46},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":46}]},{\"name\":\"Flow Rate (LPH)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":1256},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":1185},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":1232},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":1256},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":1090},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":948},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":0}]},{\"name\":\"Divert Status (Fwd/Div)\",\"type\":\"area\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":0},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":-0.5},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":-0.5}]},{\"name\":\"Divert Temp (Deg)\",\"type\":\"line\",\"data\":[{\"x\":\"2024-09-16T11:59:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:58:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:57:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:56:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:55:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:54:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:53:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:52:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:51:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:50:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:49:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:48:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:47:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:46:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:45:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:44:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:43:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:42:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:41:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:40:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:39:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:38:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:37:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:36:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:35:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:34:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:33:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:32:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:31:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:30:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:29:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:28:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:27:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:26:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:25:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:24:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:23:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:22:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:21:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:20:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:19:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:18:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:17:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:16:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:15:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:14:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:13:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:12:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:11:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:10:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:09:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:08:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:07:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:06:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:05:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:04:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:03:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:02:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:01:00.000Z\",\"y\":99},{\"x\":\"2024-09-16T11:00:00.000Z\",\"y\":99}]}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":7640,"wires":[["332dda0a4d7c47ca"]]}]

index.html

<!doctype html>
<html lang="en"><head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="../uibuilder/images/node-blue.ico">

    <title>Examples for smanjunath211 - Node-RED uibuilder</title>
    <meta name="description" content="Node-RED uibuilder - Examples for smanjunath211">

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <script defer src="../uibuilder/uibuilder.iife.min.js"></script>
    <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script>
    <!-- #endregion -->

</head><body class="uib">
    
    <h1 class="with-subtitle">Examples for smanjunath211</h1>
    <div role="doc-subtitle">Using the uibuilder IIFE library.</div>

    <div id="more"><!-- '#more' is used as a parent for dynamic HTML content in examples --></div>

    <div id="chart"></div>
    
</body></html>

index.js


let charttitle = 'HRS Holding Temp/Flow rate / Divert valve status'

let ymin1 = 20
let ymin2 = 600
let ymin3 = -5
let ymin4 = 20

let ymax1 = 150
let ymax2 = 3000
let ymax3 = 0
let ymax4 = 150

let axistitle1 = 'Holding Temp'
let axistitle2 = 'Flow Rate'
let axistitle3 = 'Divert Status'
let axistitle4 = 'Divert Temp'

let data = [
    {
        "name": "Holding temperature (°C)",
        "type": "line",
        "data": [
        ]
    },
    {
        "name": "Flow Rate (LPH)",
        "type": "line",
        "data": [
        ]
    },
    {
        "name": "Divert Status (Fwd/Div)",
        "type": "area",
        "data": [
        ]
    },
    {
        "name": "Divert Temp (Deg)",
        "type": "line",
        "data": [
        ]
    }
]

const options = {
    series: data,
    // series: [],
    noData: {
        text: 'Loading...'
    },
    chart: {
        type: 'line', stacked: false, height: 355, background: '#000', zoom:
            { type: 'x', enabled: true, autoScaleYaxis: true },
        toolbar: { autoSelected: 'zoom' }
    },
    dataLabels: { enabled: false },
    markers: { size: 0, },
    theme: { mode: 'dark' },
    colors: ['#FA2E2E', '#FAFA23', '#546E7A', , '#FFFFFF', '#E91E63', '#FF9800'],

    title: {
        text: charttitle,
        align: 'center',
        margin: 10, offsetX: 0, offsetY: 0, floating: false,
        style: {
            fontSize: 30, fontWeight: 'bold', fontFamily: undefined, color: 'yellow'
        },
    },
    stroke: { width: [2, 2, 2, 1, 2, 1], curve: 'smooth' },
    yaxis: [
        { labels: { formatter: function (val) { return val.toFixed(1); }, }, min: ymin1, max: ymax1, title: { text: axistitle1, style: { color: "#FA2E2E" } }, },
        { labels: { formatter: function (val) { return val.toFixed(0); }, }, min: ymin2, max: ymax2, title: { text: axistitle2, style: { color: "#FAFA23" } }, },
        { labels: { formatter: function (val) { return val.toFixed(1); }, }, min: ymin3, max: ymax3, title: { text: axistitle3, style: { color: "#546E7A" } }, },
        { labels: { formatter: function (val) { return val.toFixed(1); }, }, min: ymin4, max: ymax4, title: { text: axistitle4, style: { color: "#FFFFFF" } }, },
    ],

    xaxis: { lines: { show: false, }, type: 'datetime', datetimeUTC: false, labels: { format: 'dd/MMM HH:mm', }, },
    tooltip: {
        enabled: true, style: { fontSize: '12px', fontFamily: undefined }, x: { show: true, format: 'dd/MMM HH:mm', }, row: { colors: undefined, opacity: 0.5 },
        column: { colors: undefined, opacity: 0.5 },
        padding: { top: 0, right: 0, bottom: 0, left: 0 },
    },
    grid: {
        show: true, borderColor: '#ffffff', strokeDashArray: 0, position: 'back',
        xaxis: { lines: { show: false } },
        yaxis: { lines: { show: false } },
        row: { colors: undefined, opacity: 0.5 },
        column: { colors: undefined, opacity: 0.5 },
        padding: { top: 0, right: 0, bottom: 0, left: 0 },
    }
}

const chart = new ApexCharts(document.querySelector("#chart"), options)
chart.render()

uibuilder.onChange('msg', (msg) => {
    if (msg.charttitle) charttitle = msg.charttitle

    if (msg.axistitle1) axistitle1 = msg.axistitle1
    if (msg.axistitle2) axistitle2 = msg.axistitle2
    if (msg.axistitle3) axistitle3 = msg.axistitle3
    if (msg.axistitle4) axistitle4 = msg.axistitle4

    if (msg.ymin1) ymin1 = msg.ymin1
    if (msg.ymin2) ymin2 = msg.ymin2
    if (msg.ymin3) ymin3 = msg.ymin3
    if (msg.ymin4) ymin4 = msg.ymin4

    if (msg.ymax1) ymax1 = msg.ymax1
    if (msg.ymax2) ymax2 = msg.ymax2
    if (msg.ymax3) ymax3 = msg.ymax3
    if (msg.ymax4) ymax4 = msg.ymax4

    chart.updateOptions(options)

    chart.updateSeries(msg.payload)
})

This gives you an empty chart on load and then updates the data from the input flow.

1 Like

OK, Got it. Rendered chart as expexted. Thanks for the help.
EDIT: the legend at the bottom is missing color index

Looking forward for the next step.

I noticed that. It is some interaction with the default CSS. If you remove the import of the brand css, it shows up. Don't have time to track that one down I'm afraid, just being dragged into doing assurance on a few hundred million £ programme of work unexpectedly. :rofl:

You have given me enough to cover two weekends. :grinning: Let me do the digging.

2 Likes

:smile:

There are certainly more optimisations you can do in there I'm sure.

1 Like