-
Notifications
You must be signed in to change notification settings - Fork 158
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from Raminios/weather-node-dev
Added weather nodes
- Loading branch information
Showing
3 changed files
with
389 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
<script type="text/x-red" data-template-name="openweathermap"> | ||
<div class="form-row"> | ||
<label for="node-input-name"><i class="icon-tag"></i> Name</label> | ||
<input type="text" id="node-input-name" placeholder="Name"> | ||
</div> | ||
<div class="form-row"> | ||
<label for="weather-location-type-select"><i class="fa fa-globe"></i> Location</label> | ||
<select id="weather-location-type-select" style="width: 288px"><option value="city">City</option><option value="coordinates">Coordinates</option></select> | ||
</div> | ||
<div class="form-row weather-location-type" id="weather-location-type-city"> | ||
<label for=""><i class="weather-location-type"></i> City</label> | ||
<input type="text" class="weather-location-input" style="width: 180px; margin-bottom:7px" id="node-input-city" placeholder="City"></input> | ||
</br> | ||
<label for=""><i class="weather-location-type"></i> Country</label> | ||
<input type="text" class="weather-location-input" style="width: 180px; margin-bottom:7px" id="node-input-country" placeholder="Country"></input> | ||
</div> | ||
<div class="form-row weather-location-type hidden" id="weather-location-type-coordinates"> | ||
<label for=""><i class="weather-location-type"></i> Latitude</label><input type="text" class="weather-location-input" id="node-input-lat" style="width: 180px; margin-bottom:7px" placeholder="Latitude"> | ||
</br> | ||
<label for=""><i class="weather-location-type"></i> Longitude</label><input type="text" class="weather-location-input" id="node-input-lon" style="width: 180px; margin-bottom:7px" placeholder="Longitude"> | ||
</div> | ||
</script> | ||
|
||
<script type="text/javascript"> | ||
RED.nodes.registerType('openweathermap',{ | ||
category: 'weather', | ||
color: '#FFCC66', | ||
defaults: { | ||
name: {value:""}, | ||
lon: {value:"", validate:function(v) {return ((v>=-180) && (v<=180));} }, | ||
lat: {value:"", validate:function(v) {return ((v>=-90) && (v<=90));} }, | ||
city: {value:""}, | ||
country: {value:""}, | ||
}, | ||
inputs:1, | ||
outputs:1, | ||
icon: "weather.png", | ||
label: function() { | ||
return this.name||"openweathermap"; | ||
}, | ||
oneditprepare: function() { | ||
$("#weather-location-type-select").change(function() { | ||
var id = $("#weather-location-type-select option:selected").val(); | ||
$(".weather-location-type").hide(); | ||
$("#weather-location-type-"+id).show(); | ||
}); | ||
if(this.lon !== ""||this.lat !== ""){ | ||
$("#weather-location-type-select").val("coordinates"); | ||
} else { | ||
$("#weather-location-type-select").val("city"); | ||
} | ||
var id = $("#weather-location-type-select option:selected").val(); | ||
$(".weather-location-type").hide(); | ||
$("#weather-location-type-"+id).show(); | ||
}, | ||
oneditsave: function() { | ||
var type = $("#weather-location-type-select option:selected").val(); | ||
if(type == "coordinates"){ | ||
$("#node-input-city").val(""); | ||
$("#node-input-country").val(""); | ||
} else if (type == "city") { | ||
$("#node-input-lon").val(""); | ||
$("#node-input-lat").val(""); | ||
} | ||
}, | ||
labelStyle: function() { | ||
return this.name?"node_label_italic":""; | ||
} | ||
}); | ||
</script> | ||
|
||
<script type="text/x-red" data-help-name="openweathermap"> | ||
<p>A node which polls a server for current weather data when an input is received.</p> | ||
|
||
<p> This is done using either:</p> | ||
<ul> | ||
<li> a city and the country in which that city lies</li> | ||
<li> a latitude and longitude set of coordinates </li> | ||
</ul> | ||
<p>These can be passed in as settings on the node, or as the:</p> | ||
<ul> | ||
<li> <b>msg.payload.lat</b> and <b>msg.payload.lon</b>, or </li> | ||
<li> <b>msg.payload.city</b> and <b>msg.payload.country</b> </li> | ||
</ul> | ||
<p>of the message input. </p> | ||
<p>The node will always prioritise the parameters passed in when both of <b>lat/lon</b> or <b>country/city</b> are present.</p> | ||
|
||
<p>The node sets the following properties of <b>msg.payload</b>:</p> | ||
<ul> | ||
<li><b>description</b> - a brief verbal description of the current weather for human reading.</li><br> | ||
<li><b>weather</b> - a short description of the current weather.</li><br> | ||
<li><b>detail</b> - a more detailed expansion on <b>weather</b>.</li><br> | ||
<li><b>tempk</b> - the current gorund temperature at that location in Kelvin.</li><br> | ||
<li><b>humidity</b> - the current humidity at the location in percent.</li><br> | ||
<li><b>maxtemp</b> - the current maximum temperature at the location in Kelvin.</li><br> | ||
<li><b>mintemp</b> - the current minimum temperature at the location in Kelvin.</li><br> | ||
<li><b>windspeed</b> - the current wind speed at the location in Metres per second.</li><br> | ||
<li><b>winddirection</b> - the current wind direction at the location in meteorological degrees.</li><br> | ||
<li><b>town</b> - the name of the location from which the data was sourced.</li><br> | ||
<li><b>lon</b> - the longitude of the location from which the data was sourced.</li><br> | ||
<li><b>lat</b> - to the latitude of the location from which the data was sourced.</li><br> | ||
<li><b>sunrise</b> - the time at which the sun rose in Unix UTC format.</li><br> | ||
<li><b>sunset</b> - the time at which the sun will set in Unix UTC format.</li><br> | ||
<li><b>clouds</b> - the current cloud coverage of the location in percent.</li><br> | ||
</ul> | ||
<p>Weather data provided by <a href="http://openweathermap.org/" target="_blank">openweathermap.org/</a></p> | ||
</script> | ||
|
||
|
||
|
||
<script type="text/x-red" data-template-name="openweathermap in"> | ||
<div class="form-row"> | ||
<label for="node-input-name"><i class="icon-tag"></i> Name</label> | ||
<input type="text" id="node-input-name" placeholder="Name"> | ||
</div> | ||
<div class="form-row"> | ||
<label for="weather-location-type-select"><i class="fa fa-globe"></i> Location</label> | ||
<select id="weather-location-type-select" style="width: 288px"><option value="city">City</option><option value="coordinates">Coordinates</option></select> | ||
</div> | ||
<div class="form-row weather-location-type" id="weather-location-type-city"> | ||
<label for=""><i class="weather-location-type"></i> City</label> | ||
<input type="text" class="weather-location-input" style="width: 180px; margin-bottom:7px" id="node-input-city" placeholder="City"></input> | ||
</br> | ||
<label for=""><i class="weather-location-type"></i> Country</label> | ||
<input type="text" class="weather-location-input" style="width: 180px; margin-bottom:7px" id="node-input-country" placeholder="Country"></input> | ||
</div> | ||
<div class="form-row weather-location-type hidden" id="weather-location-type-coordinates"> | ||
<label for=""><i class="weather-location-type"></i> Latitude</label><input type="text" class="weather-location-input" id="node-input-lat" style="width: 180px; margin-bottom:7px" placeholder="Latitude"> | ||
</br> | ||
<label for=""><i class="weather-location-type"></i> Longitude</label><input type="text" class="weather-location-input" id="node-input-lon" style="width: 180px; margin-bottom:7px" placeholder="Longitude"> | ||
</div> | ||
</script> | ||
|
||
<script type="text/javascript"> | ||
RED.nodes.registerType('openweathermap in',{ | ||
category: 'weather', | ||
color: '#FFCC66', | ||
defaults: { | ||
name: {value:""}, | ||
lon: {value:"", validate:function(v) {return ((v>=-180) && (v<=180));} }, | ||
lat: {value:"", validate:function(v) {return ((v>=-90) && (v<=90));} }, | ||
city: {value:""}, | ||
country: {value:""}, | ||
}, | ||
inputs:0, | ||
outputs:1, | ||
icon: "weather.png", | ||
label: function() { | ||
return this.name||"openweathermap"; | ||
}, | ||
oneditprepare: function() { | ||
$("#weather-location-type-select").change(function() { | ||
var id = $("#weather-location-type-select option:selected").val(); | ||
$(".weather-location-type").hide(); | ||
$("#weather-location-type-"+id).show(); | ||
}); | ||
if(this.lon !== ""||this.lat !== ""){ | ||
$("#weather-location-type-select").val("coordinates"); | ||
} else { | ||
$("#weather-location-type-select").val("city"); | ||
} | ||
var id = $("#weather-location-type-select option:selected").val(); | ||
$(".weather-location-type").hide(); | ||
$("#weather-location-type-"+id).show(); | ||
|
||
|
||
}, | ||
oneditsave: function() { | ||
var type = $("#weather-location-type-select option:selected").val(); | ||
if(type == "coordinates"){ | ||
$("#node-input-city").val(""); | ||
$("#node-input-country").val(""); | ||
} else if (type == "city") { | ||
$("#node-input-lon").val(""); | ||
$("#node-input-lat").val(""); | ||
} | ||
}, | ||
labelStyle: function() { | ||
return this.name?"node_label_italic":""; | ||
} | ||
}); | ||
</script> | ||
|
||
<script type="text/x-red" data-help-name="openweathermap in"> | ||
<p>A node which polls a server for current weather data periodically and returns when a change is detected.</p> | ||
|
||
<p> This is done using either:</p> | ||
<ul> | ||
<li> a city and the country in which that city lies</li> | ||
<li> a latitude and longitude set of coordinates </li> | ||
</ul> | ||
|
||
<p>The node sets the following properties of <b>msg.payload</b>:</p> | ||
<ul> | ||
<li><b>description</b> - a brief verbal description of the current weather for human reading.</li><br> | ||
<li><b>weather</b> - a short description of the current weather.</li><br> | ||
<li><b>detail</b> - a more detailed expansion on <b>weather</b>.</li><br> | ||
<li><b>tempk</b> - the current gorund temperature at that location in Kelvin.</li><br> | ||
<li><b>humidity</b> - the current humidity at the location in percent.</li><br> | ||
<li><b>maxtemp</b> - the current maximum temperature at the location in Kelvin.</li><br> | ||
<li><b>mintemp</b> - the current minimum temperature at the location in Kelvin.</li><br> | ||
<li><b>windspeed</b> - the current wind speed at the location in Metres per second.</li><br> | ||
<li><b>winddirection</b> - the current wind direction at the location in meteorological degrees.</li><br> | ||
<li><b>town</b> - the name of the location from which the data was sourced.</li><br> | ||
<li><b>lon</b> - the longitude of the location from which the data was sourced.</li><br> | ||
<li><b>lat</b> - to the latitude of the location from which the data was sourced.</li><br> | ||
<li><b>sunrise</b> - the time at which the sun rose in Unix UTC format.</li><br> | ||
<li><b>sunset</b> - the time at which the sun will set in Unix UTC format.</li><br> | ||
<li><b>clouds</b> - the current cloud coverage of the location in percent.</li><br> | ||
</ul> | ||
<p>Weather data provided by <a href="http://openweathermap.org/" target="_blank">openweathermap.org/</a></p> | ||
</script> | ||
|
||
<style> | ||
.weather-location-type { | ||
padding-left: 110px; | ||
} | ||
|
||
.weather-data-credit { | ||
font-size: 70%; | ||
font-color: gray; | ||
text-align: right; | ||
} | ||
|
||
.weather-location-input{ | ||
margin-bottom: 10px; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
module.exports = function(RED) { | ||
"use strict"; | ||
var http = require("http"); | ||
|
||
function weatherPoll(node, n, msg, callback) { | ||
var url; | ||
var lat; | ||
var lon; | ||
var city; | ||
var country; | ||
|
||
if (n.city !== "" || n.country !== "") { | ||
city = n.city; | ||
country = n.country; | ||
} else if (n.lat !== "" || n.lon !== "") { | ||
lat = n.lat; | ||
lon = n.lon; | ||
} | ||
|
||
//if there is data in the message input, it overwrites the node setting values. | ||
//If the data is erroneous or not there, the values remain the node settings. | ||
if(msg.payload){ | ||
//query node code to check the input for information. | ||
if (msg.payload.city && msg.payload.country) { | ||
city = msg.payload.city; | ||
country = msg.payload.country; | ||
lat = ""; | ||
lon = ""; | ||
} | ||
if (msg.payload.lat && msg.payload.lon){ | ||
if(90 >= msg.payload.lat && 180 >= msg.payload.lon && msg.payload.lat >= -90 && msg.payload.lon >= -180){ | ||
lat = msg.payload.lat; | ||
lon = msg.payload.lon; | ||
city = ""; | ||
country = ""; | ||
} else { | ||
node.warn("Invalid lat/lon in input payload"); | ||
} | ||
} | ||
} | ||
//wipe clear the payload if it exists, or create it if it doesn't | ||
msg.payload = {}; | ||
|
||
//If there is a value missing, the URL is not initialised. | ||
if (lat && lon){ | ||
url = "http://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon; | ||
} else if (city && country) { | ||
url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + country; | ||
} | ||
|
||
//If the URL is not initialised, there has been an error with the input data, | ||
//and a node.error is reported. | ||
if(url){ | ||
http.get(url, function(res) { | ||
var weather = ""; | ||
|
||
res.on('data', function(d) { | ||
weather += d; | ||
}); | ||
|
||
res.on('end', function() { | ||
var jsun = JSON.parse(weather); | ||
if(jsun.weather){ | ||
msg.payload.weather = jsun.weather[0].main; | ||
msg.payload.detail = jsun.weather[0].description; | ||
msg.payload.tempk = jsun.main.temp; | ||
msg.payload.humidity = jsun.main.humidity; | ||
msg.payload.maxtemp = jsun.main.temp_max; | ||
msg.payload.mintemp = jsun.main.temp_min; | ||
msg.payload.windspeed = jsun.wind.speed; | ||
msg.payload.winddirection = jsun.wind.deg; | ||
msg.payload.location = jsun.name; | ||
msg.payload.lon = jsun.coord.lon; | ||
msg.payload.lat = jsun.coord.lat; | ||
msg.payload.sunrise = jsun.sys.sunrise; | ||
msg.payload.sunset = jsun.sys.sunset; | ||
msg.payload.clouds = jsun.clouds.all; | ||
msg.payload.description = ("The weather in " + jsun.name + " at coordinates: " + jsun.coord.lat + ", " + jsun.coord.lon + " is " + jsun.weather[0].main + " (" + jsun.weather[0].description + ")." ); | ||
callback(); | ||
} else { | ||
if (jsun.message === "Not found city"){ | ||
if (n.city && n.country && country != n.country && city != n.city){ | ||
node.warn("Invalid city/country in input payload, trying node city/country"); | ||
msg.payload.country = n.country; | ||
msg.payload.city = n.city; | ||
weatherPoll(node, n, msg, function(){ | ||
node.send(msg); | ||
}); | ||
} else if (n.lat && n.lon) { | ||
node.warn("Invalid city/country in input payload, trying node lat/lon"); | ||
msg.payload.lat = n.lat; | ||
msg.payload.lon = n.lon; | ||
weatherPoll(node, n, msg, function(){ | ||
node.send(msg); | ||
}); | ||
} else { | ||
if(!n.city && !n.country){ | ||
node.error("Invalid city/country in input payload"); | ||
} else { | ||
node.error("Invalid city/country in node settings"); | ||
} | ||
} | ||
} else { | ||
node.error(jsun.cod + " " + jsun.message); | ||
} | ||
} | ||
}); | ||
}).on('error', function(e) { | ||
node.error(e); | ||
}); | ||
} else { | ||
node.error("Invalid location information provided"); | ||
} | ||
} | ||
|
||
function OpenWeatherMapInputNode(n) { | ||
RED.nodes.createNode(this, n); | ||
var node = this; | ||
this.repeat = 300000; | ||
this.interval_id = null; | ||
var previousdata = null; | ||
|
||
this.interval_id = setInterval( function() { | ||
node.emit("input",{}); | ||
}, this.repeat ); | ||
|
||
this.on('input', function(msg) { | ||
weatherPoll(node, n, msg, function(){ | ||
var msgString = JSON.stringify(msg); | ||
if(msgString !== previousdata){ | ||
previousdata = msgString; | ||
node.send(msg); | ||
} | ||
|
||
}); | ||
}); | ||
|
||
this.on("close", function() { | ||
if (this.interval_id !== null) { | ||
clearInterval(this.interval_id); | ||
} | ||
}); | ||
|
||
node.emit("input",{}); | ||
} | ||
|
||
function OpenWeatherMapQueryNode(n) { | ||
RED.nodes.createNode(this,n); | ||
var node = this; | ||
|
||
this.on ('input', function(msg) { | ||
weatherPoll(node, n, msg, function(){ | ||
node.send(msg); | ||
}); | ||
}); | ||
} | ||
|
||
RED.nodes.registerType("openweathermap",OpenWeatherMapQueryNode); | ||
RED.nodes.registerType("openweathermap in",OpenWeatherMapInputNode); | ||
|
||
}; |