Hello.I am an Automation Engineer.I find the Node-Red very useful for industrial automation.However, It has not modern and beatiful visual library.How can you handle this issue?
Thank you.
Hello.I am an Automation Engineer.I find the Node-Red very useful for industrial automation.However, It has not modern and beatiful visual library.How can you handle this issue?
Thank you.
Beauty is in the eye of the beholder.
You can use
thank you very much for response.I have been using Dashboard 2.0.
Can you give us some examples of what you consider modern and beautiful?
That way we could help guide your thinking.
Here is something extremely simple, built using UIBUILDER:
Do you have Json data of this dashboard?
No. It doesn't work like that. It is part of a larger home dashboard. Here is the flow that produces and updates that page. Section 1 of the flow is run only when the list of things to monitor changes. Section 2 is only run once to kick-start the monitor, after that the MQTT topic listener does all of the update triggers.
But the input data is specific to my system.
You also need the static base files. Here is the index.html file:
<!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>Home Panel</title>
<meta name="description" content="Home Panel">
<!-- 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" logLevel="0"></script>
<script defer src="../uibuilder/utils/uibrouter.iife.min.js"></script>
<script defer src="./index.js"></script>
<!-- #endregion -->
</head><body>
<header>
<h1 class="with-subtitle">Home Panel: <uib-var variable="uibrouter_CurrentTitle"></uib-var></h1>
<div role="doc-subtitle">Using the UIBUILDER IIFE & router libraries</div>
<nav id="main-menu" class="horizontal" aria-labelledby="primary-navigation">
<h2 id="primary-navigation">Menu</h2>:
<ul id="routemenu" role="menubar" aria-describedby="main-menu">
<li data-route="route01" tabindex="0" role="menuitem"><a href="#route01">Home Summary</a></li>
<li data-route="lights" tabindex="0" role="menuitem"><a href="#lights">Lighting</a></li>
<li data-route="status01" tabindex="0" role="menuitem"><a href="#status01">System Status</a></li>
<li data-route="wanted" tabindex="0" role="menuitem"><a href="#wanted">To Do List</a></li>
</ul>
</nav>
</header>
<main>
<div id="more"><!-- '#more' is used as a parent for dynamic HTML content in examples --></div>
<div id="uibroutecontainer"><!-- router content will appear here --></div>
</main>
</body></html>
You only need that if you are creating a multi-route SPA as I have.
While that is fixed. The actual "route" that I shared is created by the light-yellow lower section of the flow. If you update the input data that defines what you want to monitor and how, you simply re-trigger that part of the flow and it updates the static route file.
So you continue to get the benefits of a static web site for all of the structure of the page (local caching of resources, etc) and only need to pass minimal data from Node-RED to connected clients. Indeed, the main part of the flow includes a uib-cache node in front of the uibuilder node and this ensures that newly connecting clients always get the latest data.
This is a quite extreme example of the use of uibuilder. In most cases, you wouldn't bother to have such a complex flow but this was partly an example of:
UIBUILDER, of course, lets you use a mix of no-code, low-code and full-code to produce data-driven web UI's. You could simplify the flow, for example, by making use of more dynamic features in the browser - especially if using a front-end framework like Vue. So you get to choose where you want to invest the time and effort for defining the structure and process the data.
Sorry, I should have said that the whole thing is perfectly reusable by someone else. You really only need to create the input JSON which looks like this:
[
{
"group": "Network",
"view": "open",
"checks": [
{
"id": "router",
"name": "Router",
"type": "Network",
"link": "https://192.168.1.1/",
"description": "192.168.1.1",
"statusTopic": "telegraf/ping/router.knightnet.co.uk",
"show": [
"status",
"bookmark"
]
},
// .....
]
},
{
"group": "Services",
"view": "open",
"checks": [
// ....
{
"id": "Mosquitto",
"name": "MQTT Broker",
"type": "Service",
"description": "Mosquitto MQTT Broker",
"statusTopic": "telegraf/procstat_lookup/mosquitto.service",
"show": [
"status"
]
},
{
"id": "Docker",
"name": "Docker",
"type": "Service",
"description": "Docker",
"statusTopic": "telegraf/procstat_lookup/docker.service",
"show": [
"status"
]
},
// .....
]
},
{
"group": "IoT Devices",
"view": "open",
"checks": [
{
"id": "shelly_rgbw2_01",
"name": "Shelly RGB",
"type": "IoT",
"link": "http://192.168.1.175/",
"description": "192.168.1.175",
"statusTopic": "shellies/shelly_rgbw2_01/online",
"show": [
"status",
"bookmark"
]
},
// ........
]
},
// ....
{
"group": "Websites",
"view": "collapsed",
"checks": [
{
"id": "bbc",
"name": "BBC",
"type": "Web",
"link": "https://bbc.co.uk/",
"description": "bbc.co.uk",
"statusTopic": "telegraf/ping/bbc.co.uk",
"show": [
"status",
"bookmark"
]
},
// .......
]
}
]
So it lets you define any number of groups, sets the default as to whether the group is open or closed on initial load, defines the MQTT topic that has the status and also allows you, for any entry, to optionally use a clickable link (bookmark) to open the monitored services web page.
Like I say, somewhat over-complex really but I wanted to push the boundaries and see how easy it might be to create something like this.