diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 index 54a5eb9a..e7942d2d --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added Added UK Met Office Datapoint feed as a provider in the default weather module. - added new provider class -- added suncalc.js dependency to calculate sun times (not provided in datapoint feed) -- added "ukunits": temp in degrees C, wind speed in MPH, precipitation in % +- added suncalc.js dependency to calculate sun times (not provided in UK Met Office feed) +- added "tempUnits" and "windUnits" to allow, for example, temp in metric (i.e. celsius) and wind in imperial (i.e. mph). These will override "units" if specified, otherwise the "units" value will be used. - use Feels Like temp from feed if present -- optionally display precipitation in current weather +- optionally display probability of precipitation (PoP) in current weather (UK Met Office data) ### Updated diff --git a/modules/default/weather/README.md b/modules/default/weather/README.md index 8b4de452..3e6905a7 100755 --- a/modules/default/weather/README.md +++ b/modules/default/weather/README.md @@ -1,6 +1,6 @@ # Weather Module -This module is aimed to be the replacement for the current `currentweather` and `weatherforcast` modules. The module will be configurable to be used as a current weather view, or to show the forecast. This way the module can be used twice to fullfil both purposes. +This module is aimed to be the replacement for the current `currentweather` and `weatherforcast` modules. The module will be configurable to be used as a current weather view, or to show the forecast. This way the module can be used twice to fullfil both purposes. The biggest change is the use of weather providers. This way we are not bound to one API source. And users can choose which API they want to use as their source. @@ -37,7 +37,9 @@ The following properties can be configured: | ---------------------------- | ----------- | `weatherProvider` | Which weather provider should be used.

**Possible values:** `openweathermap` , `darksky` , `weathergov` or `ukmetoffice`
**Default value:** `openweathermap` | `type` | Which type of weather data should be displayed.

**Possible values:** `current` or `forecast`
**Default value:** `current` -| `units` | What units to use. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit, `ukunits` = Celsius (wind speed mph)
**Default value:** `config.units` +| `units` | What units to use. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit
**Default value:** `config.units` +| `tempUnits` | What units to use for temperature. If specified overrides `units` setting. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit
**Default value:** `units` +| `windUnits` | What units to use for wind speed. If specified overrides `units` setting. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit
**Default value:** `units` | `roundTemp` | Round temperature value to nearest integer.

**Possible values:** `true` (round to integer) or `false` (display exact value with decimal point)
**Default value:** `false` | `degreeLabel` | Show the degree label for your chosen units (Metric = C, Imperial = F, Kelvin = K).

**Possible values:** `true` or `false`
**Default value:** `false` | `updateInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `600000` (10 minutes) diff --git a/modules/default/weather/providers/README.md b/modules/default/weather/providers/README.md index 5a8a2bbe..dad9ed49 100755 --- a/modules/default/weather/providers/README.md +++ b/modules/default/weather/providers/README.md @@ -18,9 +18,9 @@ This is the script in which the weather provider will be defined. In it's most s ````javascript WeatherProvider.register("yourprovider", { providerName: "YourProvider", - + fetchCurrentWeather() {}, - + fetchWeatherForecast() {} }); ```` @@ -91,9 +91,11 @@ A convenience function to make requests. It returns a promise. | Property | Type | Value/Unit | | --- | --- | --- | -| units | `string` | Gets initialized with the constructor.
Possible values: `metric`, `imperial` and `ukunits` | +| units | `string` | Gets initialized with the constructor.
Possible values: `metric`, `imperial` | +| tempUnits | `string` | Gets initialized with the constructor.
Possible values: `metric`, `imperial` | +| windUnits | `string` | Gets initialized with the constructor.
Possible values: `metric`, `imperial` | | date | `object` | [Moment.js](https://momentjs.com/) object of the time/date. | -| windSpeed |`number` | Metric: `meter/second`
Imperial: `miles/hour`
UKunits: `miles/hour` | +| windSpeed |`number` | Metric: `meter/second`
Imperial: `miles/hour` | | windDirection |`number` | Direction of the wind in degrees. | | sunrise |`object` | [Moment.js](https://momentjs.com/) object of sunrise. | | sunset |`object` | [Moment.js](https://momentjs.com/) object of sunset. | @@ -104,7 +106,7 @@ A convenience function to make requests. It returns a promise. | humidity | `number` | Percentage of humidity | | rain | `number` | Metric: `millimeters`
Imperial: `inches` | | snow | `number` | Metric: `millimeters`
Imperial: `inches` | -| precipitation | `number` | Metric: `millimeters`
Imperial: `inches`
Ukunits: `percent` | +| precipitation | `number` | Metric: `millimeters`
Imperial: `inches`
UK Met Office provider: `percent` | #### Current weather diff --git a/modules/default/weather/providers/darksky.js b/modules/default/weather/providers/darksky.js old mode 100644 new mode 100755 index 7bfc4c0f..56d2e5be --- a/modules/default/weather/providers/darksky.js +++ b/modules/default/weather/providers/darksky.js @@ -58,7 +58,7 @@ WeatherProvider.register("darksky", { // Implement WeatherDay generator. generateWeatherDayFromCurrentWeather(currentWeatherData) { - const currentWeather = new WeatherObject(this.config.units); + const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); currentWeather.date = moment(); currentWeather.humidity = parseFloat(currentWeatherData.currently.humidity); @@ -76,7 +76,7 @@ WeatherProvider.register("darksky", { const days = []; for (const forecast of forecasts) { - const weather = new WeatherObject(this.config.units); + const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); weather.date = moment(forecast.time, "X"); weather.minTemperature = forecast.temperatureMin; diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js old mode 100644 new mode 100755 index f7fe0edc..2e1681df --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -68,7 +68,7 @@ WeatherProvider.register("openweathermap", { * Generate a WeatherObject based on currentWeatherInformation */ generateWeatherObjectFromCurrentWeather(currentWeatherData) { - const currentWeather = new WeatherObject(this.config.units); + const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); currentWeather.humidity = currentWeatherData.main.humidity; currentWeather.temperature = currentWeatherData.main.temp; @@ -92,7 +92,7 @@ WeatherProvider.register("openweathermap", { return this.fetchForecastDaily(forecasts); } // if weatherEndpoint does not match forecast or forecast/daily, what should be returned? - const days = [new WeatherObject(this.config.units)]; + const days = [new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits)]; return days; }, @@ -109,7 +109,7 @@ WeatherProvider.register("openweathermap", { let snow = 0; // variable for date let date = ""; - let weather = new WeatherObject(this.config.units); + let weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); for (const forecast of forecasts) { @@ -123,7 +123,7 @@ WeatherProvider.register("openweathermap", { // push weather information to days array days.push(weather); // create new weather-object - weather = new WeatherObject(this.config.units); + weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); minTemp = []; maxTemp = []; @@ -140,7 +140,7 @@ WeatherProvider.register("openweathermap", { weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); } - + if (moment(forecast.dt, "X").format("H") >= 8 && moment(forecast.dt, "X").format("H") <= 17) { weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); } @@ -187,7 +187,7 @@ WeatherProvider.register("openweathermap", { const days = []; for (const forecast of forecasts) { - const weather = new WeatherObject(this.config.units); + const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); weather.date = moment(forecast.dt, "X"); weather.minTemperature = forecast.temp.min; diff --git a/modules/default/weather/providers/ukmetoffice.js b/modules/default/weather/providers/ukmetoffice.js index 69dbb481..2dde2ddc 100755 --- a/modules/default/weather/providers/ukmetoffice.js +++ b/modules/default/weather/providers/ukmetoffice.js @@ -19,8 +19,7 @@ WeatherProvider.register("ukmetoffice", { units: { imperial: "us", - metric: "si", - ukunits: "uk" + metric: "si" }, // Overwrite the fetchCurrentWeather method. @@ -79,7 +78,7 @@ WeatherProvider.register("ukmetoffice", { * Generate a WeatherObject based on currentWeatherInformation */ generateWeatherObjectFromCurrentWeather(currentWeatherData) { - const currentWeather = new WeatherObject(this.config.units); + const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); // data times are always UTC let nowUtc = moment.utc() @@ -132,7 +131,7 @@ WeatherProvider.register("ukmetoffice", { // loop round the (5) periods getting the data // for each period array, Day is [0], Night is [1] for (j in forecasts.SiteRep.DV.Location.Period) { - const weather = new WeatherObject(this.config.units); + const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); // data times are always UTC dateStr = forecasts.SiteRep.DV.Location.Period[j].value @@ -212,14 +211,14 @@ WeatherProvider.register("ukmetoffice", { * Convert temp (from degrees C) if required */ convertTemp(tempInC) { - return this.units === "imperial" ? tempInC * 9 / 5 + 32 : tempInC; + return this.tempUnits === "imperial" ? tempInC * 9 / 5 + 32 : tempInC; }, /* * Convert wind speed (from mph) if required */ convertWindSpeed(windInMph) { - return this.units === "metric" ? windInMph * 2.23694 : windInMph; + return this.windUnits === "metric" ? windInMph * 2.23694 : windInMph; }, /* diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js old mode 100644 new mode 100755 index 1110c68e..77b36f12 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -67,7 +67,7 @@ WeatherProvider.register("weathergov", { * Generate a WeatherObject based on currentWeatherInformation */ generateWeatherObjectFromCurrentWeather(currentWeatherData) { - const currentWeather = new WeatherObject(this.config.units); + const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); currentWeather.temperature = currentWeatherData.temperature; currentWeather.windSpeed = currentWeatherData.windSpeed.split(" ", 1); @@ -95,7 +95,7 @@ WeatherProvider.register("weathergov", { let maxTemp = []; // variable for date let date = ""; - let weather = new WeatherObject(this.config.units); + let weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); weather.precipitation = 0; for (const forecast of forecasts) { @@ -109,7 +109,7 @@ WeatherProvider.register("weathergov", { // push weather information to days array days.push(weather); // create new weather-object - weather = new WeatherObject(this.config.units); + weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); minTemp = []; maxTemp = []; @@ -134,7 +134,7 @@ WeatherProvider.register("weathergov", { minTemp.push(forecast.temperature); maxTemp.push(forecast.temperature); } - + // last day // calculate minimum/maximum temperature, specify rain amount weather.minTemperature = Math.min.apply(null, minTemp); @@ -202,7 +202,7 @@ WeatherProvider.register("weathergov", { } return "night-clear"; - } else if (weatherType.includes("Dust") || weatherType.includes("Sand")) { + } else if (weatherType.includes("Dust") || weatherType.includes("Sand")) { return "dust"; } else if (weatherType.includes("Fog")) { return "fog"; diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 075f531b..3a1f43e0 100755 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -19,6 +19,10 @@ Module.register("weather",{ locationID: false, appid: "", units: config.units, + + tempUnits: config.units, + windUnits: config.units, + updateInterval: 10 * 60 * 1000, // every 10 minutes animationSpeed: 1000, timeFormat: config.timeFormat, @@ -85,6 +89,7 @@ Module.register("weather",{ // Start the weather module. start: function () { moment.locale(this.config.lang); + // Initialize the weather provider. this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this); @@ -189,13 +194,13 @@ Module.register("weather",{ this.nunjucksEnvironment().addFilter("unit", function (value, type) { if (type === "temperature") { - if (this.config.units === "metric" || this.config.units === "imperial" || this.config.units === "ukunits") { + if (this.config.tempUnits === "metric" || this.config.tempUnits === "imperial") { value += "°"; } if (this.config.degreeLabel) { - if (this.config.units === "metric" || this.config.units === "ukunits") { + if (this.config.tempUnits === "metric") { value += "C"; - } else if (this.config.units === "imperial") { + } else if (this.config.tempUnits === "imperial") { value += "F"; } else { value += "K"; diff --git a/modules/default/weather/weatherobject.js b/modules/default/weather/weatherobject.js index 3f7e31ed..d2949ffd 100755 --- a/modules/default/weather/weatherobject.js +++ b/modules/default/weather/weatherobject.js @@ -13,8 +13,11 @@ // As soon as we start implementing the forecast, mode properties will be added. class WeatherObject { - constructor(units) { + constructor(units, tempUnits, windUnits) { + this.units = units; + this.tempUnits = tempUnits; + this.windUnits = windUnits; this.date = null; this.windSpeed = null; this.windDirection = null; @@ -69,7 +72,7 @@ class WeatherObject { } beaufortWindSpeed() { - const windInKmh = (this.units === "imperial" || this.units === "ukunits") ? this.windSpeed * 1.609344 : this.windSpeed * 60 * 60 / 1000; + const windInKmh = (this.windUnits === "imperial") ? this.windSpeed * 1.609344 : this.windSpeed * 60 * 60 / 1000; const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000]; for (const [index, speed] of speeds.entries()) { if (speed > windInKmh) { @@ -87,8 +90,8 @@ class WeatherObject { if (this.feelsLikeTemp) { return this.feelsLikeTemp } - const windInMph = (this.units === "imperial" || this.units === "ukunits") ? this.windSpeed : this.windSpeed * 2.23694; - const tempInF = this.units === "imperial" ? this.temperature : this.temperature * 9 / 5 + 32; + const windInMph = (this.windUnits === "imperial") ? this.windSpeed : this.windSpeed * 2.23694; + const tempInF = this.tempUnits === "imperial" ? this.temperature : this.temperature * 9 / 5 + 32; let feelsLike = tempInF; if (windInMph > 3 && tempInF < 50) { @@ -102,6 +105,6 @@ class WeatherObject { - 1.99 * Math.pow(10, -6) * tempInF * tempInF * this.humidity * this.humidity; } - return this.units === "imperial" ? feelsLike : (feelsLike - 32) * 5 / 9; + return this.tempUnits === "imperial" ? feelsLike : (feelsLike - 32) * 5 / 9; } }