Building an interactive floorplan using uibuilder

This post is an extract from a long thread (Floor plan suggestions) which documented my journey in building an interactive floor plan using uibuilder. The project is a work in progress, however all will be explained in the post below.

Good bye uncomplied uibuilder

So if you have tried out the dashboard nodes and, like me, have either found that you want more out of your dashboards e.g. more precision in placement of UI nodes, more sexy interactive options, and/or you have found some limits on lower powered hardware with slow load times or sometimes no loads at all, then you would have probably stumbled across alternatives to the dashboard nodes like uibuilder written by @totallyinformation.

Out of the box uibuilder it is amazing, it opens up a world of possibilities to design and develop almost anything you can imagine, however if you don’t know anything about front end web page development then it will be a steep-ish learning curve. To this end I am hoping the following code will help you along the way.

It is important to note that this setup does not require compiling code. You simply have to save the files in the right place, do quite a bit of config for your individual setup and plumb in node-red to populate the working web-page.

What I have shared here is a working and interactive floor plan, assuming its setup properly. The code is almost stand-alone in that you still need a source of data to populate the nodes. The point however isn’t to provide a fully working model that you can implement out of the box, as you will ultimately need to modify and configure the floorplan to your personal needs, naming conventions, devices etc.

These flows and uibuilder files are there to show you how I have made node-red and uibuilder work. I do this in the hope that it saves you many countless hours that I spent bashing my head against the syntax errors wall and tediously searching google to find out how to get things done in Node-RED, JavaScript, CSS, HTML, VueJS etc.

Drawing your floorplan image
EDITED: Please note updates below

If you want to personalise this you will need to draw your own floorplan. I used www.floorplanner.com. It’s actually very easy to use and in an afternoon you can have a basic floor plan drawn up, in fact probably something good enough to work with going forward. I used paint.net to add materials to snazzy up the image.

EDIT:Ok, now that I know what I know, I would suggest you do not go down the route I did. When I started this project I got all these exciting ideas about building a floorplan like this:

However I quickly realised that if I started building it as per the video, as of today I would still not have anything near a working product as I would have spent far too much time getting the layout and lighting graphics working completed, plus I knew absolutely nothing about VueJS, HTML and CSS, so it was too complex a task to make it work in the first instance, however as of today I am confident that I can get it to work, so I would suggest you use something like Sweet Home 3D to draw your floorplan as it gives you the option to add amazing lighting effects (with shadows) at a later date. I say this on the basis that I couldn't find lighting effects of that nature in floorplanner.com, however I stand to be corrected. TBH, I got in and out of floorplanner.com as quick as possible as I wanted to build the app, not spend weeks drawing layouts.

You may still want to follow the same path of building a basic floorplan first, as I have done, and then upgrading to add lighting effects (beyond the simple lighting glow effects I have already implemented). This way you will have a product to play with while you embark on the next phase of your project.

Node-Red: Contrib-Fibaro-Devices

The following code is my node-red flows. It works off the excellent and reliable node-red-contrib-fibaro-devices node that @10der has written, hence the flows are based on you having a Fibaro Home Centre 2 setup, however it shouldn’t take a great deal of effort to modify the flows to work for any home automation system.

If you have a basic knowledge of node-red then you can work your way through the code and see how to copy / modify it for your purposes.

Node-RED Flows

Node-red floorplan flows image:
image

Node-red flows code. You can get this from the github repository here:

https://github.com/amilanov75/floorplan-uncompiled
file: 2020-09-26 floor plan uncompiled - last release.json

Considerations in implementing this for yourself

Next there are the 3x key uibuilder files. I haven’t necessarily tidied these up, you can see some commented out sections showing thermometers and temp values and other snippets, however if this code is plumbed correctly it will work. There are a few things to take into account:

  1. You will need to drop your own uibuilder node on a canvas, name it and then deploy it, so that you can get the correct “src” and “dist” folder structures on your local c: drive. These will be located in the same place as your “.node-red” install folder, and found under the uibuilder folder, followed by the folder of your webpage name e.g. in my case “floorplan2”:

This will define the url that you need to go to in order to see the floorplan e.g.

http://[ipaddress of pc hosting node-red]:1880/floorplan2/
  1. You will then need to copy the 3x key floorplan files into the correct uibuilder folder, my project/web page folder is called “floorplanner2”. In this folder you will find the “src” folder in which you will see the 3x key files. I found the info in default 3x files that you get, when you first drop and deploy a default uibuilder node, somewhat overwhelming when I started out with uibuilder, but I had zero experience in web development, so it was all new to me. If you already have some past experience it will be a lot easier to understand. I would take some time to review the default code and try to understand what is going on, however that said, to get a floor plan going you don’t necessarily need to understand what’s in the default files – I still don’t. To get the floorplan working you will need to overwrite the default files with the 3x floorplan files below.

  2. You will need to create an “images” folder in your “src” folder and drop your floor plan image in it. I saved my file as a .png and made sure the resolution of the image fit the desired screen I was going to use it on. You can work dynamically with image sizes, however I have not looked into it. My floorplan is designed to work on a single touchscreen with a specific 1080x resolution. In the index.html file on row 51 you will need to change the hardcoded resolution and file name of the image to suit your needs i.e. this line here:

div id="floorplan" style="position:relative; left: -272px; width: 1720px; top:66px; height:34em; background:url(./images/groundfloor.PNG);">

  1. In the Index. HTML file, you will need to get your own font awesome code from here: https://fontawesome.com/start and update this line of code with your own unique key:
<script src="https://kit.fontawesome.com/[youe unique code].js"></script>

This will give you access to all of the free font-awesome icons via what I guess is a CDN i.e. a live internet connection, which is how uibuilder works if you do not compile your code.

  1. You will want decent development software to work with. I ended up using Visual Studio Code, which is free and does the trick, but there are lots of packages out there.

3x uibuilder files:

So here is the code. Copy each section and save it into a file named as follows:

Index.css.
You can get this from the github repository here:

https://github.com/amilanov75/floorplan-uncompiled
file: index.css

Index.html
The body of the html file can be improved drastically by making it data driven rather than having each element hard-coded.
This is something that I plan to do one day, but it was easier for me to write it the way it has been written as it is the first web page I've ever built.
You can get this from the github repository here:

https://github.com/amilanov75/floorplan-uncompiled
file: index.html

Index.js

https://github.com/amilanov75/floorplan-uncompiled
file: index.js

Things to consider:

I have intentionally excluded all of the other specific config you will need to do to transform the code to work for you, but if there is something you find that is technically incorrect in what I’ve said or a missed step, please shout out and I’ll mod the post.

I have modified caching in the “data caching” node with my own funky version of the code for handling the caching of messages when any user refreshes a webpage pointing to the floorplan, as with all my code, there are probably (most likely/definitely) better ways to do it. I have been coding JavaScript for about 4 weeks intensively and independently of uibuilder, and I have been working with uibuilder for just over 5 weeks, however on a light basis, so I am still learning A LOT. That said, the floorplaner works fine on my touchscreen tablet and I’m happy with the progress so far.

You may wonder why I’m uploading a still “work in progress” floorplan, well the work in progress is mainly limited to audio that has not been integrated yet and nice-to-have feature upgrades.

The reason is mainly, thanks to a monumental effort of support from @unborn, I have made the big move to compiling my code using Parcel.
This means that the version you see here is pretty much the last version that I will work on with where the code is uncompelled. This does not mean that you can’t take the files I use within my compiler and revert them back to uncompiled versions, it’s just that it’s a bit of hard work to do that when you are trying to learn so many new things all at once.

If you decide to move to compiling code, as I have, on the basis that it opens up a world of components that aren’t available or aren’t readily available when not compiling, then I have written up a post on how to migrate from uibuilder uncompiled to uibuilder compiled using Visual Studio Code and Parcel. You can read it here: https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Using-Parcel-to-compile-your-code

Oh, last thing, this is all built on Vue 2.0. The core code set for Vue 3.0 has been released, however the whole of Vue has not been released yet on Vue 3.0. By the time you read this Vue 3.0 will probably already be old hat, so will most likely have to change line 488 of the index.html to a new path to download Vue 2.0, cross that bridge when you get to it:

<script src="../uibuilder/vendor/vue/dist/vue.js"></script> <!-- dev version with component compiler -->

EDIT: of course, if you have any questions about what I have done please shout out and I'll get back to help out.

A pic of the floorplan itself:

11 Likes

There are a few lessons learnt that I want to share with anyone that is going to embark on a uibuilder webpage and/or has just had a look at the code I uploaded.

1. Data Caching
I have since learnt that there is a much better way to manage data and data caching. What I have done for the audio card in the floorplan version I am working on now is the following:

a) Store data in as few variables as possible
I have a node that handles incoming data from my source, in this case it’s my Sonos players, however it doesn’t matter what the source is, it could be your home automation system, or any other data coming in via an API. This node stores all of the incoming data into as few as possible, logical flow variables. For my audio I have two variables 1) the playlist queue data 2) all of the data about all of my players.

b) RBE’s and Data Caching Node
Next is feeding the webpage. Now how this works will vary by data type. With my home automation feed I would work it one way, with Sonos it’s another way. The reason is that my HA system sends individual messages which I can allow to flow straight into uibuilder, whereas I have to poll all my Sonos players every second to find their status…. this is until someone writes a Sonos push node or a better pull node that does batch gets, but that’s another topic for discussion.

I’ll explain the Sonos version here…. I then inject the variables into uibuilber via an RBE node (what a cool idea, thank you @dceejay @knolleary for building this, if not for you I was about to embark on building my own inside my workspace) for each variable having given them each a unique msg.[name] e.g. msg.sonos_queue, msg.sonos_data. This means only changes to data are fed to uibuilder considerably decreasing traffic.

Then I have one more function which is plugged into the bottom output of uibuilder to identify when a data cache request has been made and this node pumps the entirety of variables into uibuilder outside of the rbe flows, so when someone reloads the page it gets all the data it needs.

This may sound like a lot of steps, but it’s a much more elegant version of storing and caching data than I built the first time around. This is an image of the inbound data nodes into uibuilder… the “inject sonos data” node is handling pulling my variable data from the flow.variables.

image

2. Do not develop your uibuilder webpages whilst other users are connected to the web page – sounds obvious doesn’t it
The short of it is that if you are developing in uibuilder you should make sure other users are not connected to the web page. That’s it.

The long of it, is that you will eventually come across inexplicable errors, like the one I posted here https://discourse.nodered.org/t/uibuilder-websocket-performance-issue/34370/7which will only go away when you have shut down the “other” page and refreshed the one you are using to view your development on.

Suffice to say, I’ve had 2x “incidents” now, both of which have wasted hours of painstaking debugging, until I realised what was going on. Doh!