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.

[pcsh lang="js" tab_size="4" message="" hl_lines="" provider="manual"]

<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>

[/pcsh]

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 .

[pcsh lang="js" tab_size="4" message="" hl_lines="" provider="manual"]

<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>

[/pcsh]

Facebooktwittergoogle_pluspinterestlinkedin

54 thoughts on “Node Red Weather

  1. Hi Pete,

    I've tried to get this working but I've hit a stumbling block, I haven't got a clue how to reference the "myjs" folder inside settings.js, I've added:

    nodesDir: '~/.node-red/myjs/skycons/'

    But I'm not getting anything in the Dashboard.

    Any clues?

    Thanks

    Adam

    ps, yes I updated the Template code to include the folder path as shown above.

    1. Ok so I managed to find in another of your posts that you use:

      httpStatic: '/home/pi/.node-red/public',

      So I have tried this making sure everything else is correct but it also didn't work, then I noticed the description for httpStatic:

      "// When httpAdminRoot is used to move the UI to a different root path, the
      // following property can be used to identify a directory of static content
      // that should be served at http://localhost:1880/."

      Problem is I'm using the default root path for the UI.

      Any ideas?

      Cheers

      1. No, because I'm still using the default path for the UI too and it works - but the address you originally used was not quite the same as mine - I used as you have above but under /home/pi/.node-red/public I put a directory myjs and put the js in there.

        1. Pete,

          I also created a folder with a myjs folder which held the .js file and set it all up but that also didn't work.

          I even changed the address of the skycons.js in the template to https://cdnjs.cloudflare.com/ajax/libs/skycons/1396634940/skycons.js but that also didn't work.

          I'm now starting to think this is a system issue as this is running in bash on Windows 10 (just for my testing at work) so even though Node-Red is fully working/functional etc something must be amiss.

          As a side note the subscriptions for replies to comments doesn't appear to work.

          Thanks

          1. Hi Adam,

            Did you manage to solve this? Are you running node-red on Windows? This is what happened to me. I installed node red on Windows 8, with npm. The relevant files where installed under C:\Users\MyUSER\AppData\Roaming\npm\node_modules\node-red. There is where the setting.js file was. There also was a "public" folder. I put the canvas gauges library on "C:\Users\JAVIER\AppData\Roaming\npm\node_modules\node-red\publib\myjs

            And modified the "setting.js" file as Pete told, then everything worked OK.

            Hope to have helped!

    1. I believe if you read the SKYCONS page - all will be revealed. I think this is just to add the info to an array (or similar) to be acted on - because clearly to keep the animation going - something has to be aware in the background of which items to manipulate.

  2. I'm new the the Node programming, and to programming in general. In your one image that shows the "timestamp", "Function', to "weather1", etc, what is the node that is used for the " weather"?

      1. Thanks, for some reason, I don't have blue Dashboard template. I see on the FRED website the template, but not on my Pi. Using 0.15.2 version of Node-RED.

          1. Thanks for the replies. I now have the Dashboard installed plus an whole lot more.

            Now I just need to figure things out and put it all together.

  3. Looking for a little help. Played with the entire day and not getting very far. I have the Timestamp set to run every 15 minutes, then to the Darksky information. The function is set up with the "try and catch" code. The "weather1" has the other 2 scripts in your post in it. Click on deploy, then the button on the left of the Timestamp.

    Caveat, Running on a Linux tablet, trying to get this working before I go to the Raspberry Pi.

      1. I guess I wasn't seeing anything going to the debug area, but a Timestamp. I placed the debug node at the end and now I see some results.

        The results are not in Celsius, and tried to place info at the end of the Darksky url, but again received a json error. Used /ca12/en, units=si and unts=auto.

        The out put in the image is Fahrenheit.

        So, I guess my question is now, how do I get the output to display on the screen, showing the icons and data?

        Thanks for the assistance.

    1. There is something very wrong with that picture - why are you trying to click on the word template.The screensize there is way too small to see what's going on the area you want to be working in is way below that arrow.

      1. The cursor changes to the hand/finger when hovered over the word "template", so I thought t may expand or open the text box. This is on the Raspberry Pi 7' LCD screen. There is nothing below the arrow to expand into, anything.

        1. Connect the Pi to the large TV and all is OK with the text box. I guess the 7" screen is too small.

          I may try to change the resolution of the screen to see if this will help show more.

          Still have not found out how to send the results to the LCD in a graphical, form,

  4. Node-RED functions, I'm getting the follow:

    24 Dec 08:25:36 - [info] Node-RED version: v0.15.2
    24 Dec 08:25:36 - [info] Node.js version: v4.7.0
    24 Dec 08:25:36 - [info] Linux 4.4.38-v7+ arm LE
    24 Dec 08:25:37 - [info] Loading palette nodes
    24 Dec 08:25:41 - [info] Dashboard up and running
    24 Dec 08:25:44 - [info] Dashboard version 2.2.1 started at /ui
    24 Dec 08:25:47 - [info] Settings file : /home/pi/.node-red/settings.js
    24 Dec 08:25:47 - [info] User directory : /home/pi/.node-red
    24 Dec 08:25:47 - [info] Flows file : /home/pi/.node-red/flows_raspberrypi.json
    24 Dec 08:25:47 - [red] Uncaught Exception:
    24 Dec 08:25:47 - Error: listen EADDRINUSE 0.0.0.0:1880
    at Object.exports._errnoException (util.js:907:11)
    at exports._exceptionWithHostPort (util.js:930:20)
    at Server._listen2 (net.js:1250:14)
    at listen (net.js:1286:10)
    at net.js:1395:9
    at nextTickCallbackWith3Args (node.js:469:9)
    at process._tickDomainCallback (node.js:416:17)

    I realize Node-RED uses the 1880 port so why the error?

  5. OK, I'm baffled. I can't get anything to show up in the Dashboard except the name of it. Probably something simple, but I'm at a loss. I get all the information in the debug area, but no icons on the dashboard.

    Any HELP much appreciated.

    Thanks,

    Scott

      1. Thanks for the reply. Attached is an image of the flow. I click on the red button "deploy" and all of the debug nodes send out the weather info on the debug tab. I then switch tabs to the Dashboard one and click on the small button next to the words "Node-RED Dashboard". A new browser tab opens with the words of the Dashboard which is empty.

        Hope this is what you are asking.

        1. you haven't used a single dashboard item 🙂
          to have menu and buttons in dashboard, you need to use ITS items... they're in the left menu, just scroll down... and you need to output what you want into one of them, or use them to feed input to other stuff

      2. Noob to Node-RED and from this blog, I thought the template node from the Dashboard section was enough to get the icons from skycons to display. Silly me.

        When you speak of ITS items, are you talking about the chart, guage, etc?

                  1. Yes deploy was hit.

                    I followed numerous tutorials, even the new Thermostat one, and I was able to see charts, sliders, graphs and everything else, but this weather one has me baffled. Must be the where and how I have the code.

  6. Hello Scott,
    It's very cold at home! I do not have any place to display all this !!
    I see 2 problems :
    - you don't see Skycon icons : you need to verify you can access skycons.js with
    http://ip-node-red:1880/myjs/skycons.js, and verify your configuration

    - Presentation : in flow, there is a template TPL to format data, I don't understand where I need to put this TPL, Pete say in blog it must be the first template, for me, it doesnt work, I put it in last place in dashboard UI group, you can move this template to test.
    Hervé

        1. I looked at that, but Adam didn't seem to solve his problem. The following might as well be in a foreign language.

          So I have tried this making sure everything else is correct but it also didn't work, then I noticed the description for httpStatic:

          "// When httpAdminRoot is used to move the UI to a different root path, the
          // following property can be used to identify a directory of static content
          // that should be served at http://localhost:1880/."

          Problem is I'm using the default root path for the UI.

          I have placed the line in the skycons.js file, but nothing happens.

          1. Uncommented the line

            httpStatic: '/home/nol/node-red/static

            and changed to

            httpStatic: '/home/mx1/.node-red/public

            restarted node-red and the localhost and I now have icons!

            Thanks for the assistance.

            Scott

  7. Thanks Joe,

    I'm not sure what is wrong. I'm going back to check all of Pete's notes & the reader's comments.

    I'm sure that Pete will says it's because I'm using a fruit-based product. 🙂

    1. I guess it could be an apple / safari related issue. It could also be a JS code problem. In fact it could be a combination of both of these because browsers interpret JS in different ways 😉

      The icon parts are supposed to be colored by the colors option passed to the Skycons constructor i.e.
      "colors": {
      "main": "#779966",
      "moon":"#666666",
      "fog": "#555522",
      "fogbank": "#884488",
      "cloud": "#999999",
      "snow": "#aaaaaa",
      "leaf":"#00ff00",
      "rain": "#0000ff",
      "sun": "#ff3300"
      }
      This is supposed to be done in each template for each icon so imo that's the first thing to check.

      Another thing that could potentially cause a problem is JS scope. If all of the Skycons instances have the same variable name in each template then we've created a scenario where there are basically multiple JS variables all with the same name in global scope in the page. This may or may not work as expected depending on how a given browser JS engine works.

      imo the safest most robust way to implement this in multiple node-red template nodes is to use separated variable names for each of the Skycons instances i.e.
      var skycons0 = new Skycons(.. in template 0
      var skycons1 = new Skycons(.. in template 1

      I'll post my flow json up next..

Leave a Reply

Your email address will not be published. Required fields are marked *