NODE-RED Development

While I’m sitting in a hotel in Birmingham waiting to do my bit in this month’s #FSBCONF I thought I’d drop down a few notes about Node-Red which is definitely my new toy of choice when it comes to a central hub for home control. I say toy, sitting on a Raspberry Pi 2 it is definitely NOT a toy.

nodes

So what you see above is one tiny part of what I’m working on for the home controller. The boards mentioned a couple of articles ago need to know what time it is as they don’t have a clock or battery. So when you plug them in – they need to know the time – and as they are also aware of dusk and dawn which clearly changes from time to time, there’s a whole package goes to them on a regular basis, once a day.

There is a “sunrise” node available to Node-Red, but my requirements are slightly different to that which the standard unit allows – so using the Sunrise node as a base I made my own node.

It turns out that as an absolute mininum you need a .JS file and an HTML file. You put them in a suitable named directory under your pi/node-red/nodes directory and that’s about it – provided you’ve not made any mistakes – it just appears as a block in Node-Red.

So what I wanted was a block which would respond to incoming requests from individual WIFI units with their ID and return time info to the individual nodes, usually after a power up or reset – but also send a message to ALL nodes on a regular basis, say, once a day. The WIFI units are programmed to request info at regular intervals until they get an answer – though I’ve yet to see this miss a beat.

The Boards Login block is an MQTT subscribe block – standard. The Daily Update is a standard inject block – and the Send to Boards is an MQTT publish – against standard.

The bit in the middle is a heavily modified Sunshine block – called duskdawn. I made a directory for it – I put the JS and HTML files in there and started gutting them. So now if you click the block you get…

duskdawn

So here are the two files….

The first is as you can see VERY similar to the suncalc node and uses the same functions – but it does not use it’s own timer – it uses an input.  Also it does not generate simple yes/no outputs but generates a message suitable for MQTT.  If a message comes in that says “fromesp” – it sends out the new message to all. If it comes in from a particular unit, it sends that info back to that unit. The info comprises the time in seconds since 1970, the number of minutes after midnight we call DUSK and the number of minutes past midnight we call DUSK.

module.exports = function(RED) {
    "use strict";
    var SunCalc = require('suncalc');

    function SunNode(n) {
        RED.nodes.createNode(this,n);
        this.lat = n.lat;
        this.lon = n.lon;
        this.start = n.start;
        this.end = n.end;

        var node = this;

        this.on("input", function (msg2) {
            var now = new Date();
            var times = SunCalc.getTimes(now, node.lat, node.lon);
            var nowMillis = Date.UTC(now.getUTCFullYear(),now.getUTCMonth(),now.getUTCDate(),now.getUTCHours(),now.getUTCMinutes(), now.getUTCSeconds());
            var midnightMillis = Date.UTC(now.getUTCFullYear(),now.getUTCMonth(),now.getUTCDate(),0,1);
            var startMillis = Date.UTC(times[node.start].getUTCFullYear(),times[node.start].getUTCMonth(),times[node.start].getUTCDate(),times[node.start].getUTCHours(),times[node.start].getUTCMinutes());
            var endMillis = Date.UTC(times[node.end].getUTCFullYear(),times[node.end].getUTCMonth(),times[node.end].getUTCDate(),times[node.end].getUTCHours(),times[node.end].getUTCMinutes());
            var moon = parseInt(SunCalc.getMoonIllumination(now).fraction*100+0.5)/100;
            var msg = { payload:0, topic:"sun", moon:moon };
            var dawn = (startMillis - midnightMillis);
            var dusk = (endMillis - midnightMillis);
           

           
            if ((nowMillis>dawn)&& (nowMillis<dusk)) { node.status({fill:"yellow",shape:"dot",text:"day"}); }
            else { node.status({fill:"blue",shape:"dot",text:"night"}); }

            msg.topic = msg2.payload + 'toesp';
            msg.payload = '{time:' + nowMillis/1000 + ';dusk:' + dusk/60000 + ';dawn:' + dawn/60000 + '}';
            node.send(msg);

});

    }
    RED.nodes.registerType("duskdawn",SunNode);
}

 

This code is complemented by HTML which identifies what inputs are needed, how many outputs etc. This is even closer to but simpler than the Sunrise files. All of the copyright notices in the originals apply, my modifications are not serious enough to claim any ownership though I should say that when I started playing with this I knew nothing about creating these files and now it seems pretty straightforward.

 

<script type="text/x-red" data-template-name="duskdawn">
  <div class="form-row">
    <label for="node-input-lat"><i class="fa fa-globe"></i> Latitude</label>
    <input type="text" id="node-input-lat" placeholder="51.025">
  </div>
  <div class="form-row">
    <label for="node-input-lon"><i class="fa fa-globe"></i> Longitude</label>
    <input type="text" id="node-input-lon" placeholder="-1.4">
  </div>
 
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>
</script>

<script type="text/x-red" data-help-name="duskdawn">
    <p>Uses the suncalc module to generate an MQTT output which contains time, dusk and dawn on demand for a specified longitude and latitude.</p>

</script>

<script type="text/javascript">
    RED.nodes.registerType('duskdawn',{
        category: 'advanced-input',
        color:"#ffcc66",
        defaults: {
            name: {value:""},
            lat: {value:"", required:true, validate:RED.validators.number()},
            lon: {value:"", required:true, validate:RED.validators.number()},
            start: {value:"sunrise", required:true},
            end: {value:"sunset", required:true}
        },
        inputs:1,
        outputs:1,
        icon: "sun.png",
        label: function() {
            return this.name||"Sun rise/set";
        },
        labelStyle: function() {
            return this.name?"node_label_italic":"";
        },
        oneditprepare: function() {
            if (($("#node-input-lat").val() === "") && ($("#node-input-lon").val() === "")) {
                if ("geolocation" in navigator) {
                    navigator.geolocation.getCurrentPosition(function(position) {
                        $("#node-input-lat").val(Number(position.coords.latitude.toFixed(5)));
                        $("#node-input-lon").val(Number(position.coords.longitude.toFixed(5)));
                    });
                }
            }
        }
    });
</script>

 

So there you have it – with luck you should find this information useful. I AM told by a very kind reader that I should amend any copyright because of the substantial changes I’ve made – but then without the original I could not have gotten this far (I deal with business forums in another life and people are often very unhelpful – whereas in here I’m constantly amazed at the great feedback and help I get)  so I’ll ask merely this – if you find it useful, please somewhere put a link back to the https://tech.scargill.net blog so that more knowledgeable people will come back to me with potential improvements to everything I’m doing – something that we’ll all benefit from.

And if you happen to spot a Node-Red node that can create a nice web page to set up a central heating system – please DO let me know as that’s my next requirement…

Facebooktwittergoogle_pluspinterestlinkedin

6 thoughts on “NODE-RED Development

    1. Hi Hermann and Matt - great stuff - well I loaded up the VIS module - and the demo and followed the instructions - and it works - the yellow light turns on and off - but no matter what I do I cannot get anything to come out of the DEBUG module... any ideas?

      Pete.

      1. If you connect the DEBUG node directly to the VIS node you won't get an output. No idea why... So I added a FUNCTION node with the content: "return msg;" and attached the DEBUG node to that.

  1. Pete, I am following your blog for a while since I started playing with the ESP8266 modules.
    Thanks for the great contributions and for sharing your experience!

    A few weeks ago I found this great node. http://flows.nodered.org/node/node-red-vis
    Maybe this can help you visualize your central heating...

    Hermann

  2. Wow, just started having a look at this Node-Red stuff. Reminds me a lot of how #Slack can do integrations but just soo much better. I can see why you'd want to use it for home automation. It takes all that tedious messaging and squirrels it away. Now all that is needed is a front-end for the JSON and done. Can't wait for a release of your code & the board.

    Just a question, what do you use to do the 110/220V to 3.3V conversion?

Comments are closed.