This blog entry is now HISTORICAL as DarkSky have pulled a fast one on everyone except Apple users. A later blog entry here has more information on alternatives.
One of the many things that Node-Red makes easy to capture – is the weather – and until recently, all credit was due to the people who put the DARKSKY API together.
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
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.
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.
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
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..
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]
Here’s my findings and some updates 🙂
– The original SkyCons lib is indeed monochrome only. If you want the colored version, get the file from here : https://github.com/maxdow/skycons
– Also, the source for the autorunning function can be simplified to this:
(function(scope) {
scope.$watch(‘msg.payload’, function(data) {
if (data !== undefined){
skycons.set(“icon1”, data);
skycons.play();
}
});
})(scope);
Note that this is naive. Assumed here is that msg.payload always contains a valid string!
– the lines :
skycons.add(“icon1”, Skycons.PARTLY_CLOUDY_DAY);
skycons.play();
can be safely removed.
– Instead of saving the js file in your local install, you can also directly point to the version in the github repo. To do so, add a ui-template containing just this line:
and make sure its template type is set to ‘add to site head section’
after copying your function and doing a bit of research i found that the precipIntensity was amount of rain per hour so I multiplied that by 24 to get the expected rainfall for the day
try {
msg.payload=global.get(“DarkSky”).daily.data[1].precipIntensity*24;
node.send(msg);
}
catch(e) {}
return msg;
No problems there all working fine but the resulting number is to four decimal points I.e 0.1234 so my question is is there a way to reduce the output to only one decimal place?
never mind got it sorted in the guage node
..well I did post a chunk of JSON here but unfortunately it broke the internet so Pete had to delete it. Anyone interested can find my take on this flow here: https://gist.github.com/jjssoftware/28470985cbd30caeb299eb2aa7104c7d
Put elsewhere please – screwing up blog – deleting.
comments page completely screwed up…
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. 🙂
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..
Fruit-based product and everything is in color(Safari web browser).
all looking ok here (apart from the weather being a bit cack)
I had this working beautifully. However, I’ve just noticed that the icons are now in black & white – not Pete’s lovely colours.
Is anyone else seeing the same?
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é
This is the line from the template.
Maybe a stupid question, but are there actual icon files that are accessed by the script that should be on my computer?
The hyperlink you provided http://ip-node-red:1880/myjs/skycons.js gave me an error “server not found”.
answer in first comments here, by Adam, and Peter…
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.
line goes in settings.js
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
if you use latest script version, that line is already active
Herve,
Do you know how to get the icons to spread out evenly? Above the dates/temps?
Hello Peter
Thank you for sharing.
Sorry for my bad English, a little difficult to write english for me.
I play with templates and add two little templates to your Node Red Weather stuff :
– one with dynamic day of week
– one with temperatures min/max
If someone interested, flow is enabled here :
https://github.com/coyotte14/node-red/blob/master/flow_meteo2_en.txt
You have to change key and coordinates in Darksky url.
A+
Hervé
thanks Herve,
I must be cursed, as I copied your dashboard into my node-red and I can only get what you see in the attached image.
JAY – you any ideas on this?
Hello Herve
I think in function Day-week is mistake. I think that msg.d0 should be:
new Date().addDays(1).getDayName() because in DarkSky daily.data[2] is day after tomorrow. In your flow you have current conditions and forecast for day after tomorrow. You don’t have forecast for tomorrow. In this case names of days are not correct.
Hello Jacek
you’re right, the function has an error.
Thank you for bringing the solution, I will correct this function.
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
Did you use the dashboard controls? Clicked deploy? Publish your flow…
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.
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
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?
Yes, clearly grouped in dashboard menu on the left
Don’t see how the skycon icons will fit into those nodes.
need Peter’s help here…
thanks for your help. I played with this all weekend and I get absolutely nothing on the dashboard, other than the name of the dashboard. Can’t be that complicated, can it?
mmm… just saying… did you hit DEPLOY???
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.
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?
wondering why I can’t place script in the template node under dashboard. clicking on the word template does nothing. See attached image
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.
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.
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,
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.
I’m not sure but I don’t think you’ve told us what’s wrong.
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.
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”?
The blue one is a Node-Red Dashboard template. The code is shown in the blog entry.
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.
Basically, no Dashboard nodes.
Sounds to me like you’ve not installed Dashboard – and so you’re not using my script as that has it included.
Yes but did you INSTALL Dashboard
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.
What is the purpose of line 18 of the template please Pete.
skycons.add(“icon1”, Skycons.PARTLY_CLOUDY_DAY);
Paul
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.
You know – looking back at this – I have no idea how that crept in . It is probably useless.
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.
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
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.
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
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!
I’m using the default path. Make sure you’ve made the relevant change to .node-red/settings.js
Hello Pete,
Very clever. I’m just trying it now.
To change the default units, you can add ?unit=XX to the URL as per API instructions
https://darksky.net/dev/docs/forecast
Cheers,
alex