From 77640714cc47295de7ca39fbb57ef5cb13e4c322 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sat, 5 Jan 2019 16:54:45 +0100 Subject: [PATCH 1/9] adjusted openweathermap module to work with /forecast and forecast/daily --- .../weather/providers/openweathermap.js | 71 ++++++++++++++++--- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 64df4104..53eca7df 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -56,8 +56,6 @@ WeatherProvider.register("openweathermap", { }) }, - - /** OpenWeatherMap Specific Methods - These are not part of the default provider methods */ /* * Gets the complete url for the request @@ -87,6 +85,21 @@ WeatherProvider.register("openweathermap", { * Generate WeatherObjects based on forecast information */ generateWeatherObjectsFromForecast(forecasts) { + + if (this.config.weatherEndpoint == "/forecast") { + return this.fetchForecastHourly(forecasts); + } else if (this.config.weatherEndpoint == "/forecast/daily") { + return this.fetchForecastDaily(forecasts); + } + // if weatherEndpoint does not match forecast or forecast/daily, what should be returned? + const days = [new WeatherObject(this.config.units)]; + return days; + }, + + /* + * fetch forecast information for 3-hourly forecast (available for free subscription). + */ + fetchForecastHourly(forecasts) { // initial variable declaration const days = []; // variables for temperature range and rain @@ -96,7 +109,7 @@ WeatherProvider.register("openweathermap", { // variable for date let date = ""; var weather = new WeatherObject(this.config.units); - + for (const forecast of forecasts) { if (date === moment(forecast.dt, "X").format("YYYY-MM-DD")) { @@ -104,10 +117,17 @@ WeatherProvider.register("openweathermap", { // add values from forecast to corresponding variables minTemp.push(forecast.main.temp_min); maxTemp.push(forecast.main.temp_max); - if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { - rain += forecast.rain["3h"] / 25.4; + + if (forecast.hasOwnProperty("rain")) { + if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { + rain += forecast.rain["3h"] / 25.4; + } else if (!isNaN(forecast.rain["3h"])){ + rain += forecast.rain["3h"]; + } else { + rain += 0; + } } else { - rain += forecast.rain["3h"]; + rain += 0; } } else { // a new day @@ -122,7 +142,7 @@ WeatherProvider.register("openweathermap", { minTemp = []; maxTemp = []; - rain *= 0; + rain = 0; // set new date date = moment(forecast.dt, "X").format("YYYY-MM-DD"); @@ -138,15 +158,48 @@ WeatherProvider.register("openweathermap", { maxTemp.push(forecast.main.temp_max); if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { rain += forecast.rain["3h"] / 25.4; - } else { + } else if (!isNaN(forecast.rain["3h"])){ rain += forecast.rain["3h"]; } } } - return days.slice(1); }, + + /* + * fetch forecast information for daily forecast (available for paid subscription or old apiKey). + */ + fetchForecastDaily(forecasts) { + // initial variable declaration + const days = []; + for (const forecast of forecasts) { + const weather = new WeatherObject(this.config.units); + + weather.date = moment(forecast.dt, "X"); + weather.minTemperature = forecast.temp.min; + weather.maxTemperature = forecast.temp.max; + weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); + + // forecast.rain not available if amount is zero + if (forecast.hasOwnProperty("rain")) { + if (this.config.units === "imperial" && !isNaN(forecast.rain)) { + weather.rain = forecast.rain / 25.4; + } else if (!isNaN(forecast.rain["3h"])){ + weather.rain = forecast.rain; + } else { + weather.rain = 0; + } + } else { + weather.rain = 0; + } + + days.push(weather); + } + + return days; + }, + /* * Convert the OpenWeatherMap icons to a more usable name. */ From 9cbf33153365001b11c16868e4a91682973c8f13 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sat, 5 Jan 2019 16:56:47 +0100 Subject: [PATCH 2/9] fixed typo in daily data fetcher --- modules/default/weather/providers/openweathermap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 53eca7df..f5d931c5 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -185,7 +185,7 @@ WeatherProvider.register("openweathermap", { if (forecast.hasOwnProperty("rain")) { if (this.config.units === "imperial" && !isNaN(forecast.rain)) { weather.rain = forecast.rain / 25.4; - } else if (!isNaN(forecast.rain["3h"])){ + } else if (!isNaN(forecast.rain)){ weather.rain = forecast.rain; } else { weather.rain = 0; From bdcc0c5373202056d5df445a9433ca39147913e0 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sat, 5 Jan 2019 17:16:19 +0100 Subject: [PATCH 3/9] another typo fix --- .../weather/providers/openweathermap.js | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index f5d931c5..b39da760 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -5,7 +5,7 @@ * * By Michael Teeuw http://michaelteeuw.nl * MIT Licensed. - * + * * This class is the blueprint for a weather provider. */ @@ -64,7 +64,7 @@ WeatherProvider.register("openweathermap", { return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams(); }, - /* + /* * Generate a WeatherObject based on currentWeatherInformation */ generateWeatherObjectFromCurrentWeather(currentWeatherData) { @@ -85,7 +85,7 @@ WeatherProvider.register("openweathermap", { * Generate WeatherObjects based on forecast information */ generateWeatherObjectsFromForecast(forecasts) { - + if (this.config.weatherEndpoint == "/forecast") { return this.fetchForecastHourly(forecasts); } else if (this.config.weatherEndpoint == "/forecast/daily") { @@ -95,7 +95,7 @@ WeatherProvider.register("openweathermap", { const days = [new WeatherObject(this.config.units)]; return days; }, - + /* * fetch forecast information for 3-hourly forecast (available for free subscription). */ @@ -109,15 +109,15 @@ WeatherProvider.register("openweathermap", { // variable for date let date = ""; var weather = new WeatherObject(this.config.units); - + for (const forecast of forecasts) { - + if (date === moment(forecast.dt, "X").format("YYYY-MM-DD")) { // the same day as before // add values from forecast to corresponding variables minTemp.push(forecast.main.temp_min); maxTemp.push(forecast.main.temp_max); - + if (forecast.hasOwnProperty("rain")) { if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { rain += forecast.rain["3h"] / 25.4; @@ -139,33 +139,40 @@ WeatherProvider.register("openweathermap", { days.push(weather); // create new weather-object weather = new WeatherObject(this.config.units); - + minTemp = []; maxTemp = []; rain = 0; - + // set new date date = moment(forecast.dt, "X").format("YYYY-MM-DD"); - + // specify date weather.date = moment(forecast.dt, "X"); - + // select weather type by first forecast value of a day, is this reasonable? weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); - + // add values from first forecast of this day to corresponding variables minTemp.push(forecast.main.temp_min); maxTemp.push(forecast.main.temp_max); - if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { - rain += forecast.rain["3h"] / 25.4; - } else if (!isNaN(forecast.rain["3h"])){ - rain += forecast.rain["3h"]; + + if (forecast.hasOwnProperty("rain")) { + if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { + rain += forecast.rain["3h"] / 25.4; + } else if (!isNaN(forecast.rain["3h"])){ + rain += forecast.rain["3h"]; + } else { + rain += 0; + } + } else { + rain += 0; } } } return days.slice(1); }, - + /* * fetch forecast information for daily forecast (available for paid subscription or old apiKey). */ @@ -180,7 +187,7 @@ WeatherProvider.register("openweathermap", { weather.minTemperature = forecast.temp.min; weather.maxTemperature = forecast.temp.max; weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); - + // forecast.rain not available if amount is zero if (forecast.hasOwnProperty("rain")) { if (this.config.units === "imperial" && !isNaN(forecast.rain)) { @@ -199,7 +206,7 @@ WeatherProvider.register("openweathermap", { return days; }, - + /* * Convert the OpenWeatherMap icons to a more usable name. */ From 8431ebf2e81cc0a7a34bacbc8065924c8a2daa31 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sat, 5 Jan 2019 17:16:37 +0100 Subject: [PATCH 4/9] adjusted README --- modules/default/weather/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/default/weather/README.md b/modules/default/weather/README.md index d10297d1..47c5387d 100644 --- a/modules/default/weather/README.md +++ b/modules/default/weather/README.md @@ -78,17 +78,17 @@ The following properties can be configured: | ---------------------------- | ----------- | `apiVersion` | The OpenWeatherMap API version to use.

**Default value:** `2.5` | `apiBase` | The OpenWeatherMap base URL.

**Default value:** `'http://api.openweathermap.org/data/'` -| `weatherEndpoint` | The OpenWeatherMap API endPoint.

**Possible values:** `/weather`, `/forecast` or `/forecast/daily` (paying users only)
**Default value:** `'/weather'` +| `weatherEndpoint` | The OpenWeatherMap API endPoint.

**Possible values:** `/weather`, `/forecast` (free users) or `/forecast/daily` (paying users or old apiKey only)
**Default value:** `'/weather'` | `locationID` | Location ID from [OpenWeatherMap](https://openweathermap.org/find) **This will override anything you put in location.**
Leave blank if you want to use location.
**Example:** `1234567`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. | `location` | The location used for weather information.

**Example:** `'Amsterdam,Netherlands'`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. -| `apiKey` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account.

This value is **REQUIRED** +| `apiKey` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account.

This value is **REQUIRED** ### Darksky options | Option | Description | ---------------------------- | ----------- | `apiBase` | The DarkSky base URL. The darksky api has disabled [cors](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), therefore a proxy is required.

**Possible value:** `'https://cors-anywhere.herokuapp.com/https://api.darksky.net'`
This value is **REQUIRED** -| `weatherEndpoint` | The DarkSky API endPoint.

**Possible values:** `/forecast`
This value is **REQUIRED** +| `weatherEndpoint` | The DarkSky API endPoint.

**Possible values:** `/forecast`
This value is **REQUIRED** | `apiKey` | The [DarkSky](https://darksky.net/dev/register) API key, which can be obtained by creating an DarkSky account.

This value is **REQUIRED** | `lat` | The geo coordinate latitude.

This value is **REQUIRED** | `lon` | The geo coordinate longitude.

This value is **REQUIRED** From 40a65eec51a8b9acee62afa72260dba28d8591b7 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sat, 5 Jan 2019 17:16:50 +0100 Subject: [PATCH 5/9] adjusted CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75a849a2..1fce3724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503). - Fixed unhandled error on bad git data in updatenotiifcation module [#1285](https://github.com/MichMich/MagicMirror/issues/1285). -- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504). ### New weather module - Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499). @@ -28,6 +27,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Aligned indoor values in current weather vertical [#1499](https://github.com/MichMich/MagicMirror/issues/1499). - Added humidity support to nunjuck unit filter. - Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MichMich/MagicMirror/issues/1503). +- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MichMich/MagicMirror/issues/1504), [#1513](https://github.com/MichMich/MagicMirror/issues/1513). ## [2.6.0] - 2019-01-01 From 409939360f0608f7330f06828f368d4230bb2f95 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sun, 6 Jan 2019 10:23:15 +0100 Subject: [PATCH 6/9] do not show 0 mm rain value --- modules/default/weather/weather.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 52e9cfee..e8898c64 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -198,7 +198,7 @@ Module.register("weather",{ } } } else if (type === "rain") { - if (isNaN(value)) { + if (isNaN(value) || value === 0) { value = ""; } else { value = `${value.toFixed(2)} ${this.config.units === "imperial" ? "in" : "mm"}`; From d6046d2422e6b0a26c5cff77e23d4794b27fc217 Mon Sep 17 00:00:00 2001 From: fwitte Date: Sun, 6 Jan 2019 10:24:16 +0100 Subject: [PATCH 7/9] simplified fetchForecastHourly function --- .../weather/providers/openweathermap.js | 45 +++++++------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index b39da760..3d257cee 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -112,24 +112,7 @@ WeatherProvider.register("openweathermap", { for (const forecast of forecasts) { - if (date === moment(forecast.dt, "X").format("YYYY-MM-DD")) { - // the same day as before - // add values from forecast to corresponding variables - minTemp.push(forecast.main.temp_min); - maxTemp.push(forecast.main.temp_max); - - if (forecast.hasOwnProperty("rain")) { - if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { - rain += forecast.rain["3h"] / 25.4; - } else if (!isNaN(forecast.rain["3h"])){ - rain += forecast.rain["3h"]; - } else { - rain += 0; - } - } else { - rain += 0; - } - } else { + if (date !== moment(forecast.dt, "X").format("YYYY-MM-DD")) { // a new day // calculate minimum/maximum temperature, specify rain amount weather.minTemperature = Math.min.apply(null, minTemp); @@ -152,22 +135,24 @@ WeatherProvider.register("openweathermap", { // select weather type by first forecast value of a day, is this reasonable? weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); + + } + + // the same day as before + // add values from forecast to corresponding variables + minTemp.push(forecast.main.temp_min); + maxTemp.push(forecast.main.temp_max); - // add values from first forecast of this day to corresponding variables - minTemp.push(forecast.main.temp_min); - maxTemp.push(forecast.main.temp_max); - - if (forecast.hasOwnProperty("rain")) { - if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { - rain += forecast.rain["3h"] / 25.4; - } else if (!isNaN(forecast.rain["3h"])){ - rain += forecast.rain["3h"]; - } else { - rain += 0; - } + if (forecast.hasOwnProperty("rain")) { + if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) { + rain += forecast.rain["3h"] / 25.4; + } else if (!isNaN(forecast.rain["3h"])){ + rain += forecast.rain["3h"]; } else { rain += 0; } + } else { + rain += 0; } } return days.slice(1); From 2dfb349609244aec9c37ca787e106e0388bfc959 Mon Sep 17 00:00:00 2001 From: fwitte Date: Mon, 7 Jan 2019 08:19:50 +0100 Subject: [PATCH 8/9] fixed missing last day display in forecast/hourly --- modules/default/weather/providers/openweathermap.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 3d257cee..9ae7cbd4 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -113,7 +113,6 @@ WeatherProvider.register("openweathermap", { for (const forecast of forecasts) { if (date !== moment(forecast.dt, "X").format("YYYY-MM-DD")) { - // a new day // calculate minimum/maximum temperature, specify rain amount weather.minTemperature = Math.min.apply(null, minTemp); weather.maxTemperature = Math.max.apply(null, maxTemp); @@ -135,9 +134,9 @@ WeatherProvider.register("openweathermap", { // select weather type by first forecast value of a day, is this reasonable? weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); - + } - + // the same day as before // add values from forecast to corresponding variables minTemp.push(forecast.main.temp_min); @@ -155,6 +154,13 @@ WeatherProvider.register("openweathermap", { rain += 0; } } + // last day + // calculate minimum/maximum temperature, specify rain amount + weather.minTemperature = Math.min.apply(null, minTemp); + weather.maxTemperature = Math.max.apply(null, maxTemp); + weather.rain = rain; + // push weather information to days array + days.push(weather); return days.slice(1); }, From d6a6a5362338e15b84cc1cddb27b6fa29321083a Mon Sep 17 00:00:00 2001 From: fwitte Date: Thu, 14 Feb 2019 16:48:45 +0100 Subject: [PATCH 9/9] updated weather icon display --- modules/default/weather/providers/openweathermap.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 9ae7cbd4..856a52c1 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -132,10 +132,14 @@ WeatherProvider.register("openweathermap", { // specify date weather.date = moment(forecast.dt, "X"); - // select weather type by first forecast value of a day, is this reasonable? + // If the first value of today is later than 17:00, we have an icon at least! 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); + } // the same day as before // add values from forecast to corresponding variables