Hi all, just a quick post to share something I've been messing with for the last couple of days. Posted the flow to the flows site because it is too long for Discourse. That flow is very likely to get updated as it gets improved.
Looks like I'll also be publishing a package of VueJS components at some point as well which will be designed to work seamlessly with uibuilder though will likely work standalone as well.
This one was inspired by Steve and Bart's SVG addon for Dashboard. It made me wonder how hard it would be to combine an SVG floorplan with SVG icons showing things like whether lights are on or off and even being able to control them.
Well, turns out that it is crazy simple!
So I created a simple VueJS component which means that all you have to do is write a couple of lines of HTML & a few lines of JavaScript then you have a fully dynamic visual floorplan with IoT overlays.
In this case, just the 1 light is turned on, notice that it is a different colour and glowing
The flow to drive this is also trivial:
It is too long to post here because of the embedded SVG data so I've created an entry on the flows site. Note that the html and js files seem a bit long as well but that is only because the component is embedded, normally that would be in a separate file.
https://flows.nodered.org/flow/02eb3716157db586f3f5b8a85c241009#
The flow contains the html and javascript as well as the SVG floorplan used for the background. Just copy the content of the SVG to a file called background.svg
then copy/paste the html and javascript to the appropriate files.
Here is the relevant part of the HTML:
<div id="floorplan" style="position:relative; width:100%; height:50em; background:url(./images/serveimage.svg);">
<bulb id="a" :color="isona ? 'red' : 'grey'" :glow="isona" :clickable="false" x="100" y="100" @bulbclicked="myClick" title="A: This one does not respond to clicks"><desc>Here we use a component slot to insert some more custom svg</desc></bulb>
<bulb id="b" :color="isonb ? 'red' : 'grey'" :glow="isonb" :clickable="true" x="270" y="120" @bulbclicked="myClick" title="B"><circle cx="50" cy="50" r="50"/></bulb>
<bulb id="c" :ison="isonc" :clickable="true" x="650" y="120" @bulbclicked="myClick" title="C"></bulb>
<bulb id="d" :ison="isond" :clickable="true" x="250" y="270" @bulbclicked="myClick" :title="'D: ' + (isond ? 'ON' : 'off')"></bulb>
</div>
I will be simplifying that still further I think, really the last 2 of the 4 examples are the style you would mainly want to use, the first 2 show just how versatile a component can be.
Here is the relevant part of the JavaScript:
var app1 = new Vue({
el: '#app',
data: {
isonb: false,
isona: false,
isonc: false,
isond: false,
}, // --- End of data --- //
methods: {
// Called if one of the bulb icons is clicked
myClick: function(returnedData) {
// returnedData.srcId contains the element id, returnedData.event contains the click event object
console.log('Somebody clicked the ' + returnedData.srcId + ' icon!', returnedData)
var out
if ( returnedData.srcId === 'a' ) {
out = this.isona = !this.isona
}
if ( returnedData.srcId === 'b' ) {
out = this.isonb = !this.isonb
}
if ( returnedData.srcId === 'c' ) {
out = this.isonc = !this.isonc
}
if ( returnedData.srcId === 'd' ) {
out = this.isond = !this.isond
}
// Lets tell Node-RED
uibuilder.send({
'topic': returnedData.srcId.toUpperCase(),
'payload': out,
})
}, // -- End of myClick -- //
}, // --- End of methods --- //
// Get things started
mounted: function(){
/** **REQUIRED** Start uibuilder comms with Node-RED */
uibuilder.start()
// msg is updated when a standard msg is received from Node-RED
uibuilder.onChange('msg', function(msg){
if ( msg.payload.hasOwnProperty('A') ) {
app1.isona = msg.payload.A
}
if ( msg.payload.hasOwnProperty('B') ) {
app1.isonb = msg.payload.B
}
if ( msg.payload.hasOwnProperty('C') ) {
app1.isonc = msg.payload.C
}
if ( msg.payload.hasOwnProperty('D') ) {
app1.isond = msg.payload.D
}
console.log('incoming msg', app1.isona, app1.isonb, app1.isonc, app1.isond, msg)
})
} // --- End of mounted hook --- //
}) // --- End of app1 --- //
You may be able to see how this could be improved with further automation so that you don't have to specify the bulb entries manually but instead can get the data from Node-RED and let VueJS build the icons for you.