Been meaning to get round to this for a looooooong time. Christmas break seems like a good time to make a start.
Only started today so not a lot to show. But this new version uses UIBUILDER v6.7 (current live version) to make sure I'm finding any issues that others might also hit. Importantly, it uses the new front-end router library which really does make front-end development a lot easier I've discovered - who knew!
Will try to share progress as I go along.
Right now, not much to see:
Only 1 sensor platform currently showing (and the light sensor seems to have stopped working! That is a cached value). You can hover over the numbers to see the last update timestamp and you can collapse/expand each floor. The menu is rubbish of course, not yet formatted.
The flow to manage everything is this:
This is the function node:
function dp(inp, dp, int) {
if (!int) int = 'en-GB'
if (!dp) dp = 1
return inp.toLocaleString(int, { 'minimumFractionDigits': dp, 'maximumFractionDigits': dp })
}
// What output to change in the web page
switch (msg.topic) {
case 'ESP/m5basic01/BH1750/Lux': {
msg.outputId = '#office-lux'
break
}
case 'ESP/m5basic01/SHT30/Temperature': {
msg.outputId = '#office-temp'
break
}
case 'ESP/m5basic01/SHT30/Humidity': {
msg.outputId = '#office-hum'
break
}
default: {
return // no output
}
}
// Format the output
msg.payload = dp(msg.payload)
// Last update date/time
msg.update = new Date()
return msg
And this is the configuration of the uib-update
node:
So nice and efficient.
Minimal front-end code though currently the page is manually coded, there is automation that could be done but not much incentive right now as I've really only a few things to show. The router config, menu, floor and room layouts could all be data-driven from Node-RED for sure but I want to spend more time creating the display than messing with over-optimising this time.
Couple of hours work so far and nearly all of that was messing with the HTML and CSS to get the nested, collapsible grid working properly.
Doubtless much more to come
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>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"></script>
<script defer src="../uibuilder/utils/uibrouter.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">Home Panel</h1>
<div role="doc-subtitle">Using the UIBUILDER IIFE & router libraries</div>
<nav id="menu" aria-labelledby="primary-navigation">
<h2>Route Menu</h2>
<ul id="routemenu" aria-describedby="menu">
<li><a href="#route01">Home</a></li>
<li><a href="#wanted">Wanted</a></li>
</ul>
</nav>
<div id="more">
<!-- '#more' is used as a parent for dynamic HTML content in examples -->
</div>
</body></html>
index.js
'use strict'
const routerConfig = {
defaultRoute: 'route01',
// Stops routes with scripts having them re-run but may leave the page bigger in memory
hide: true,
routes: [
{ id: 'route01', src: './fe-routes/route01.html', type: 'url', description: 'Boom' },
{ id: 'wanted', src: './fe-routes/wanted.html', type: 'url', description: 'Bam' },
],
}
const router = new UibRouter(routerConfig)
fe-routes/route01.html
<style>
.house h3, .house h2 {
margin: 0;
}
.house summary {
/* list-style: none; */ /* OR display: block; */
grid-column: 1 / -1;
cursor: pointer;
}
/* .house summary::-webkit-details-marker { display: none } */
summary > h2 {
display:inline-block
}
.floor {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 0;
border: 1px solid hsl(60, 100%, 18%);
}
.floor > div {
border: 1px solid var(--text3);
border-radius: var(--border-radius);
margin: 0.5rem;
padding: 0.5rem;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
align-content: start;
}
.floor > div :first-child {
grid-column: 1 / -1;
border-bottom: 1px solid var(--text4);
}
.floor > div > div:nth-child(odd) {
text-align: right;
}
</style>
<div id="rooms" class="house">
<details id="floor0" open>
<summary role="heading" aria-level="2"><h2>Ground Floor</h2></summary>
<div id="floor0" class="floor">
<div id="dining">
<h3>Dining Room</h3>
<div>℃</div><div id="dining-temp">--</div>
<div>%H</div><div id="dining-hum">--</div>
</div>
<div id="living">
<h3>Living Room</h3>
<div>℃</div><div id="living-temp">--</div>
<div>%H</div><div id="living-hum">--</div>
</div>
<div id="kitchen">
<h3>Kitchen</h3>
<div>℃</div><div id="kitchen-temp">--</div>
<div>%H</div><div id="kitchen-hum">--</div>
</div>
<div id="fronthall">
<h3>Front Hall</h3>
<div>℃</div><div id="fronthall-temp">--</div>
<div>%H</div><div id="fronthall-hum">--</div>
</div>
<div id="rearhall">
<h3>Rear Hall</h3>
<div>℃</div><div id="rearhall-temp">--</div>
<div>%H</div><div id="rearhall-hum">--</div>
<div>Lux</div><div id="rearhall-lux">--</div>
</div>
</div>
</details>
<details id="floor1" open>
<summary role="heading" aria-level="2"><h2>First Floor</h2></summary>
<div class="floor">
<div id="masterbed">
<h3>Master Bedroom</h3>
<div>℃</div><div id="masterbed-temp">--</div>
<div>%H</div><div id="masterbed-hum">--</div>
</div>
<div id="bed2">
<h3>Bedroom 2</h3>
<div>℃</div><div id="bed2-temp">--</div>
<div>%H</div><div id="bed2-hum">--</div>
</div>
<div id="office">
<h3>Office</h3>
<div>℃</div><div id="office-temp">--</div>
<div>%H</div><div id="office-hum">--</div>
<div>Lux</div><div id="office-lux">--</div>
</div>
<div id="bath1">
<h3>Bathroom</h3>
<div>℃</div><div id="bath1-temp">--</div>
<div>%H</div><div id="bath1-hum">--</div>
</div>
</div>
</details>
</div>