Category Archives: weather

Node Red Weather

One of the many things that Node-Red makes easy to capture – is the weather – and all credit is due to the people who put the DARKSKY API together.

Animated weather

What you are seeing above is a 6 day forecast in ANIMATED, COLOUR images (I appreciate it does not look animated here). It is LOVELY. This is running on my Raspberry Pi and of course the display, being a web page can be displayed on a tablet, a PC screen, a phone or an integrated touch-screen. Don’t go using old browsers though – this makes use of HTML5 and vector graphics so you should be reasonably up to date.

To get a nice pretty weather forecast for your home control display or whatever you plan to use it for, you need:

a. information

b. A display mechanism

In this case the information comes from DarkSky via a simple API

DarkSky

If you wish to “call” the DarkSky API you may do this up to 1000 times a day for free. Reader Jay and I felt that grabbing the information every 5 minutes might be a good start. Once the novelty wears off you might consider every 15 minutes or so. A timestamp node is simply used as a trigger – to get the information when Node-Red powers up and every 5 minutes from there on.

An HTTP request gets you a massive object with just about everything you could ever want to know about the weather and finally a function attempts to read that object with minimal error checking. I say this because in the past I’ve had the very odd bad package from DarkSky using the NODE that is available (I suggest you avoid that at least for now) which does not harm but looks bad in the logs!

The “http request” node in the middle requires little information – just your unique code which you get when you sign up (for free) with DarkSky – and your longitude and latitude.

DarkSky details

Here is the full URL I used with a fictional key – and my own coordinates.

https://api.darksky.net/forecast/xxxxxxxxxxxx/55.130575,-2.2534091?units=uk2

Now you COULD read all the information from the new object and make a whole boatload of MQTT messages – some of which you might never use. If you were to do this – your flow might look like this.. and my thanks to reader Jay for saving me all that work.

massive flow

i think you’ll agree that is slightly over the top – but it does give you an idea of how much info you can get out of this and that is NOT a complete list.

On the other hand it was good fun for a bit, checking out all the info

info from DarkSky

So, instead, what we’re going to do is simply pull out of the object what we need… See below. When this is called, the function I’ve dropped in after that simply contains…

try {
var weathertest=msg.payload.currently;
global.set("DarkSky",msg.payload);
node.send (msg);
}
catch(e) {}

"weathertest" is used purely to provoke an error if there is something wrong with the data and can be ignored from now on. So now with luck we have an object called “DarkSky” out of which we can pull all manner of things as needed – and of course being global we can access this from any flow at any time.

So – here’s a EXAMPLE function to get the current weather summary

try {
msg.payload=global.get("DarkSky").currently.summary;
node.send(msg);
}
catch(e) {}

What’s with the “try—catch”? Well, this is new for me – that comment I made above about accessing anything at any time - I got sick of seeing harmless complains about undefined objects in my logs due to using something before it has been defined – or bad data coming through etc.,  so my new thing is to actually check that a variable exists before using it. If you call this function BEFORE you’ve grabbed the weather for the very first time – nothing will output – simple!

So – how far can we go with this? VERY far – it’s a BIG object but for what we need here – it is all very simple.

global.get(“DarkSky”).when.what

where “when” is one of the following:

  • minutely
  • hourly
  • currently
  • daily.data[x] where x starts at 1 for today and goes to 7 days,

msg.payload=global.get("DarkSky").daily.data[2].humidity;  // humidity for tomorrow !!

“what” can be one of the following:

  • summary
  • nearestStormDistance
  • precipIntensity
  • precipProbability
  • temperature
  • apparentTemperature
  • humidity
  • windSpeed
  • visibility
  • cloudCover
  • pressure
  • icon

I’m sure you’ll  agree that’s a pretty damned comprehensive selection, nicely hidden away in an object for you to pick out what you need. cloudCover and humidity you might want to multiply by 100 to make them useful – and temperature is in degrees C though you can no doubt change that to anything you want – read the API docs.

For now what we’re interested in is the icon – the name of an icon to represent the weather for seven days. The icon can be one of the following:

  • clear-day
  • clear-night
  • partly-cloudy-day
  • partly-cloudy-night
  • cloudy
  • rain
  • sleet
  • snow
  • wind
  • fog

It JUST so happens that there is a set of animated icons called SKYCONS which match up with this exactly – and they are in technicolour – you have control over the colour of various bits of them including:

  • main
  • moon
  • fog
  • fogbank
  • snow
  • leaf
  • rain
  • sun

So putting this all together – you can make a full colour set of icons which adjust for each of several days. As I am using Node-Red Dashboard, 6 icons fit nicely onto my phone so I simply picked the next 6 days.

You might want to satisfy yourself that you can grab this data before moving onto the next stage. Get yourself a DarkSky account, punch in the details and maybe go and grab today’s weather. Of course without these icons you still have lots of info you can use for wall displays or maybe calculating what to do with your heating system – for example in cold weather, if it is damp I like to ramp the heating up just a little more.

And now, onto the imagery.

You will need to be comfortable with creating a folder to put JavaScript libraries for use with Node-Red. In the Node-Red settings file you can define such a directory – just make sure you don’t call it “js” as Node-Red already has one of those and you’ll end up in trouble. I call mine “myjs”.  Go and grab the skycons.js file and put it on your system. You’ll find a lot of information in that link I’ve just given you.

For 6 days your flow will look like this..

weather flow

So – every 5 minutes or however often you choose, grab the relevant icon from the global object you are populating and inject it into one of these templates.

Here is the code for template 1.

<script src="/myjs/skycons.js"></script>

<canvas id="icon1"  width="50" height="50"></canvas>

<script>
var skycons = new Skycons({"monochrome": false, 
                "colors": { 
                      "main": "#779966", 
                      "moon":"#666666",
                      "fog": "#555522",
                      "fogbank": "#884488",
                      "cloud": "#999999",
                      "snow": "#aaaaaa",
                      "leaf":"#00ff00",
                      "rain": "#0000ff",
                      "sun": "#ff3300"
                    } });
skycons.add("icon1", Skycons.PARTLY_CLOUDY_DAY);
skycons.play();

    (function(scope) {
        scope.$watch('msg.payload', function(data) {
           if (data=="clear-day") skycons.set("icon1", Skycons.CLEAR_DAY);
           if (data=="clear-night") skycons.set("icon1", Skycons.CLEAR_NIGHT);
           if (data=="partly-cloudy-day") skycons.set("icon1", Skycons.PARTLY_CLOUDY_DAY);
           if (data=="partly-cloudy-night") skycons.set("icon1", Skycons.PARTLY_CLOUDY_NIGHT);
           if (data=="cloudy") skycons.set("icon1", Skycons.CLOUDY);
           if (data=="rain") skycons.set("icon1", Skycons.RAIN);
           if (data=="sleet") skycons.set("icon1", Skycons.SLEET);
           if (data=="snow") skycons.set("icon1", Skycons.SNOW);
           if (data=="wind") skycons.set("icon1", Skycons.WIND);
           if (data=="fog") skycons.set("icon1", Skycons.FOG);
        });
    })(scope);

</script>

The other templates are identical EXCEPT that: they don’t need the include – and they don’t need the definition of skycons. Also – wherever you see “icon1” – change that to “icon2” etc.. up to “icon6” assuming you want 6 days. “icon7” if you want to go all the way to 7 days.

If this does not work smoothly – check out that you ARE pointing to the javascript library and that you’ve made no mistakes – check that the data is actually going into the template node and make sure you have an up to date Node-Red and Node-Red Dashboard.  That will serve well later as I’m no-where NEAR finished making use of templates… just the thorny matter of getting data into and out of them to get to grips with.

If you have problems formatting these images - I noted when moving them mine came out stretched - this is some js and css  I use for other purposes but I think you need the padding css in a template (make this the first template - auto size - it will not show up) - to remove padding around the edges .

<style>
  .filled { 
      height: 100% !important;

      padding: 0 !important;
      margin: 0 !important;
  }
  .nr-dashboard-template {
      padding: 0;
      margin: 0;
  }
  
  .rounded {
  border-radius: 12px 12px 12px 12px;
}
 
   .bigfont {
  font-size: 18px;
}

   .smallfont {
  font-size: 12px;
}
  
</style>

<script>
$('.vibrate').on('click', function() {
  navigator.vibrate(100);
});

function restore_bg(x) {
            $(this).css("background-color", x);
    };

$('.touched').on('mousedown', function() {
    var x= $(this).css("background-color");
    $(this).css("background-color", "yellow");
    
    setTimeout(restore_bg.bind(this,x),200);
    navigator.vibrate(80);
    });
    
</script>
Facebooktwittergoogle_pluspinterestlinkedin

To Weather or not to Weather

That’s it – I’m giving up with OpenWeatherMap. I’ve been having trouble recently with it accepting Hexham,UK some days and not others and it is getting worse – when you look at it’s search list it says Hexham,GB (despite the fact that I have to put in UK and not GB for it to work at all) – then sometimes it can’t find it at all. Someone is having a laugh. Secondly for 2 days it was MISERABLE here in Bellingham just a few miles North of Hexham – and OpenWeatherMap said it was “clear skies” – I’ve not seen blue sky since Thursday until today.

Meanwhile, forecast.io is spot on – see above. See this blog item for how to extract data - https://tech.scargill.net/the-weather/

So you will have noted that I’ve been messing with weather for some time and one of the issues I’ve had is debugging! The standard debug tool that comes with Node-Red is fine but has limited capacity and has no processing capability – for example if you fire a bunch of JSON at it, it looks HORRIBLE (for those not in the know, JSON is a standard, like XML but in most cases very simple, for sending data – simple text).

And it was with that in mind, when mindlessly trawling the web that I stumbled on a reference to a debugging FLOW for Node-Red which would treat text as text and would format JSON – but more’s the point – in a separate browser window – THAT caught my attention.

So – here is the article that started it all off for me this evening…  http://flows.nodered.org/flow/b0fcb7b72fc05a30e55b

Take PARTICULAR notice of Julian’s “Configuration” notes which came about as I completely messed things up and Julian very kindly helped me and then updated his documentation accordingly.

So what we’re doing here is sending debug info to a Node-Red web page – a great idea – but it involves having access to a static library…. /js/mqttws31.js and Julian in his debug notes now tells you how to ensure that Node-Red knows where to look – I would imagine that this info is also awfully useful for node-red-config-ui if you’re planning on adding libraries!!! Certainly added to my knowledge.

And so NOW when I fire out debug info from forecast.IO…..

 

Using the debugger

“Debugger” is the sub-flow that Julian has created (I just renamed it and stored it all in one sub-flow) and “readable debug” is this…

msg.topic="weather";
return msg;

The timestamp just triggers an action every 5 minutes and at power up – sensibly every 15 minutes is actually enough. Then there is the grabbing of data from forecast.io where xxxx  is your API key – freely supplied – and note I output as a “parsed JSON object”.

HTTP node setup

 

Then I bang the stuff into a global variable for later use.

global.set("weather",msg.payload);

and finally I add a topic for the new debug

msg.topic="weather";
return msg;

And so now instead of garbage coming out of the regular debug when I’m testing the weather I get….. wait for it – in the new debugger…. perfectly readable English!!!

Debugger output

Isn’t that wonderful – and as you have the source you could imagine all sorts of variations on this. I am SO chuffed about this – a genuine reason to buy MORE MONITORS!!

Here’s what the debugger sub-flow looks like…

Debugger subflow

Facebooktwittergoogle_pluspinterestlinkedin