mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-28 12:12:20 +00:00
Merge pull request #1495 from fewieden/feature/weather-module-improvements
weather module feels like temperature
This commit is contained in:
commit
986337da0c
@ -48,7 +48,6 @@ The following properties can be configured:
|
|||||||
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
|
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
|
||||||
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`
|
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`
|
||||||
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
|
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
|
||||||
| `retryDelay` | The delay before retrying after a request failure. (Milliseconds) <br><br> **Possible values:** `1000` - `60000` <br> **Default value:** `2500`
|
|
||||||
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
|
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
|
||||||
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
||||||
|
|
||||||
@ -63,6 +62,7 @@ The following properties can be configured:
|
|||||||
| `showHumidity` | Show the current humidity <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
| `showHumidity` | Show the current humidity <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
| `showIndoorTemperature` | If you have another module that emits the `INDOOR_TEMPERATURE` notification, the indoor temperature will be displayed <br> **Default value:** `false`
|
| `showIndoorTemperature` | If you have another module that emits the `INDOOR_TEMPERATURE` notification, the indoor temperature will be displayed <br> **Default value:** `false`
|
||||||
| `showIndoorHumidity` | If you have another module that emits the `INDOOR_HUMIDITY` notification, the indoor humidity will be displayed <br> **Default value:** `false`
|
| `showIndoorHumidity` | If you have another module that emits the `INDOOR_HUMIDITY` notification, the indoor humidity will be displayed <br> **Default value:** `false`
|
||||||
|
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `true`
|
||||||
|
|
||||||
#### Weather forecast options
|
#### Weather forecast options
|
||||||
|
|
||||||
|
@ -51,6 +51,13 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% if config.showFeelsLike and not config.onlyTemp %}
|
||||||
|
<div class="normal medium">
|
||||||
|
<span class="dimmed">
|
||||||
|
{{ "FEELS" | translate }} {{ current.feelsLike() | roundValue | unit("temperature") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="dimmed light small">
|
<div class="dimmed light small">
|
||||||
{{"LOADING" | translate}}
|
{{"LOADING" | translate}}
|
||||||
|
@ -16,10 +16,10 @@ WeatherProvider.register("darksky", {
|
|||||||
|
|
||||||
units: {
|
units: {
|
||||||
imperial: 'us',
|
imperial: 'us',
|
||||||
metric: 'ca'
|
metric: 'si'
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchCurrentWeather: function() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if(!data || !data.currently || typeof data.currently.temperature === "undefined") {
|
if(!data || !data.currently || typeof data.currently.temperature === "undefined") {
|
||||||
@ -27,14 +27,14 @@ WeatherProvider.register("darksky", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentWeather = this.generateWeatherDayFromCurrentWeather(data);
|
const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
}).catch(function(request) {
|
}).catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchWeatherForecast: function() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if(!data || !data.daily || !data.daily.data.length) {
|
if(!data || !data.daily || !data.daily.data.length) {
|
||||||
@ -42,7 +42,7 @@ WeatherProvider.register("darksky", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
|
const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
}).catch(function(request) {
|
}).catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
@ -50,14 +50,14 @@ WeatherProvider.register("darksky", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Create a URL from the config and base URL.
|
// Create a URL from the config and base URL.
|
||||||
getUrl: function() {
|
getUrl() {
|
||||||
var units = this.units[this.config.units] || 'auto';
|
const units = this.units[this.config.units] || "auto";
|
||||||
return `${this.config.apiBase}${this.config.weatherEndpoint}/${this.config.apiKey}/${this.config.lat},${this.config.lon}?units=${units}&lang=${this.config.lang}`;
|
return `${this.config.apiBase}${this.config.weatherEndpoint}/${this.config.apiKey}/${this.config.lat},${this.config.lon}?units=${units}&lang=${this.config.lang}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Implement WeatherDay generator.
|
// Implement WeatherDay generator.
|
||||||
generateWeatherDayFromCurrentWeather: function(currentWeatherData) {
|
generateWeatherDayFromCurrentWeather(currentWeatherData) {
|
||||||
var currentWeather = new WeatherObject();
|
const currentWeather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
currentWeather.date = moment();
|
currentWeather.date = moment();
|
||||||
currentWeather.humidity = parseFloat(currentWeatherData.currently.humidity);
|
currentWeather.humidity = parseFloat(currentWeatherData.currently.humidity);
|
||||||
@ -71,11 +71,11 @@ WeatherProvider.register("darksky", {
|
|||||||
return currentWeather;
|
return currentWeather;
|
||||||
},
|
},
|
||||||
|
|
||||||
generateWeatherObjectsFromForecast: function(forecasts) {
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
var days = [];
|
const days = [];
|
||||||
|
|
||||||
for (var forecast of forecasts) {
|
for (const forecast of forecasts) {
|
||||||
var weather = new WeatherObject();
|
const weather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
weather.date = moment(forecast.time, "X");
|
weather.date = moment(forecast.time, "X");
|
||||||
weather.minTemperature = forecast.temperatureMin;
|
weather.minTemperature = forecast.temperatureMin;
|
||||||
@ -83,15 +83,15 @@ WeatherProvider.register("darksky", {
|
|||||||
weather.weatherType = this.convertWeatherType(forecast.icon);
|
weather.weatherType = this.convertWeatherType(forecast.icon);
|
||||||
weather.rain = forecast.precipAccumulation;
|
weather.rain = forecast.precipAccumulation;
|
||||||
|
|
||||||
days.push(weather)
|
days.push(weather);
|
||||||
}
|
}
|
||||||
|
|
||||||
return days
|
return days;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Map icons from Dark Sky to our icons.
|
// Map icons from Dark Sky to our icons.
|
||||||
convertWeatherType: function(weatherType) {
|
convertWeatherType(weatherType) {
|
||||||
var weatherTypes = {
|
const weatherTypes = {
|
||||||
"clear-day": "day-sunny",
|
"clear-day": "day-sunny",
|
||||||
"clear-night": "night-clear",
|
"clear-night": "night-clear",
|
||||||
"rain": "rain",
|
"rain": "rain",
|
||||||
@ -103,6 +103,7 @@ WeatherProvider.register("darksky", {
|
|||||||
"partly-cloudy-day": "day-cloudy",
|
"partly-cloudy-day": "day-cloudy",
|
||||||
"partly-cloudy-night": "night-cloudy"
|
"partly-cloudy-night": "night-cloudy"
|
||||||
};
|
};
|
||||||
|
|
||||||
return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null;
|
return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
providerName: "OpenWeatherMap",
|
providerName: "OpenWeatherMap",
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather: function() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
||||||
@ -28,7 +28,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
|
|
||||||
this.setFetchedLocation(`${data.name}, ${data.sys.country}`);
|
this.setFetchedLocation(`${data.name}, ${data.sys.country}`);
|
||||||
|
|
||||||
var currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
@ -37,7 +37,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchWeatherForecast: function() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (!data || !data.list || !data.list.length) {
|
if (!data || !data.list || !data.list.length) {
|
||||||
@ -48,7 +48,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
|
|
||||||
this.setFetchedLocation(`${data.city.name}, ${data.city.country}`);
|
this.setFetchedLocation(`${data.city.name}, ${data.city.country}`);
|
||||||
|
|
||||||
var forecast = this.generateWeatherObjectsFromForecast(data.list);
|
const forecast = this.generateWeatherObjectsFromForecast(data.list);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
@ -62,15 +62,15 @@ WeatherProvider.register("openweathermap", {
|
|||||||
/*
|
/*
|
||||||
* Gets the complete url for the request
|
* Gets the complete url for the request
|
||||||
*/
|
*/
|
||||||
getUrl: function() {
|
getUrl() {
|
||||||
return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams();
|
return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams();
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a WeatherObject based on currentWeatherInformation
|
* Generate a WeatherObject based on currentWeatherInformation
|
||||||
*/
|
*/
|
||||||
generateWeatherObjectFromCurrentWeather: function(currentWeatherData) {
|
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
|
||||||
var currentWeather = new WeatherObject();
|
const currentWeather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
currentWeather.humidity = currentWeatherData.main.humidity;
|
currentWeather.humidity = currentWeatherData.main.humidity;
|
||||||
currentWeather.temperature = currentWeatherData.main.temp;
|
currentWeather.temperature = currentWeatherData.main.temp;
|
||||||
@ -86,11 +86,11 @@ WeatherProvider.register("openweathermap", {
|
|||||||
/*
|
/*
|
||||||
* Generate WeatherObjects based on forecast information
|
* Generate WeatherObjects based on forecast information
|
||||||
*/
|
*/
|
||||||
generateWeatherObjectsFromForecast: function(forecasts) {
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
var days = [];
|
const days = [];
|
||||||
|
|
||||||
for (var forecast of forecasts) {
|
for (const forecast of forecasts) {
|
||||||
var weather = new WeatherObject();
|
const weather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
weather.date = moment(forecast.dt, "X");
|
weather.date = moment(forecast.dt, "X");
|
||||||
weather.minTemperature = forecast.temp.min;
|
weather.minTemperature = forecast.temp.min;
|
||||||
@ -107,8 +107,8 @@ WeatherProvider.register("openweathermap", {
|
|||||||
/*
|
/*
|
||||||
* Convert the OpenWeatherMap icons to a more usable name.
|
* Convert the OpenWeatherMap icons to a more usable name.
|
||||||
*/
|
*/
|
||||||
convertWeatherType: function(weatherType) {
|
convertWeatherType(weatherType) {
|
||||||
var weatherTypes = {
|
const weatherTypes = {
|
||||||
"01d": "day-sunny",
|
"01d": "day-sunny",
|
||||||
"02d": "day-cloudy",
|
"02d": "day-cloudy",
|
||||||
"03d": "cloudy",
|
"03d": "cloudy",
|
||||||
@ -137,8 +137,8 @@ WeatherProvider.register("openweathermap", {
|
|||||||
*
|
*
|
||||||
* return String - URL params.
|
* return String - URL params.
|
||||||
*/
|
*/
|
||||||
getParams: function() {
|
getParams() {
|
||||||
var params = "?";
|
let params = "?";
|
||||||
if(this.config.locationID) {
|
if(this.config.locationID) {
|
||||||
params += "id=" + this.config.locationID;
|
params += "id=" + this.config.locationID;
|
||||||
} else if(this.config.location) {
|
} else if(this.config.location) {
|
||||||
|
@ -46,7 +46,8 @@ Module.register("weather",{
|
|||||||
|
|
||||||
onlyTemp: false,
|
onlyTemp: false,
|
||||||
showRainAmount: true,
|
showRainAmount: true,
|
||||||
colored: false
|
colored: false,
|
||||||
|
showFeelsLike: true
|
||||||
},
|
},
|
||||||
|
|
||||||
// Module properties.
|
// Module properties.
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
// As soon as we start implementing the forecast, mode properties will be added.
|
// As soon as we start implementing the forecast, mode properties will be added.
|
||||||
|
|
||||||
class WeatherObject {
|
class WeatherObject {
|
||||||
constructor() {
|
constructor(units) {
|
||||||
|
this.units = units;
|
||||||
this.date = null;
|
this.date = null;
|
||||||
this.windSpeed = null;
|
this.windSpeed = null;
|
||||||
this.windDirection = null;
|
this.windDirection = null;
|
||||||
@ -63,19 +64,36 @@ class WeatherObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beaufortWindSpeed() {
|
beaufortWindSpeed() {
|
||||||
var kmh = this.windSpeed * 60 * 60 / 1000;
|
const windInKmh = this.units === "imperial" ? this.windSpeed * 1.609344 : this.windSpeed * 60 * 60 / 1000;
|
||||||
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||||
for (var beaufort in speeds) {
|
for (const [index, speed] of speeds.entries()) {
|
||||||
var speed = speeds[beaufort];
|
if (speed > windInKmh) {
|
||||||
if (speed > kmh) {
|
return index;
|
||||||
return beaufort;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSunAction() {
|
nextSunAction() {
|
||||||
var now = new Date();
|
return moment().isBetween(this.sunrise, this.sunset) ? "sunset" : "sunrise";
|
||||||
return (this.sunrise < now && this.sunset > now) ? "sunset" : "sunrise";
|
}
|
||||||
|
|
||||||
|
feelsLike() {
|
||||||
|
const windInMph = this.units === "imperial" ? this.windSpeed : this.windSpeed * 2.23694;
|
||||||
|
const tempInF = this.units === "imperial" ? this.temperature : this.temperature * 9 / 5 + 32;
|
||||||
|
let feelsLike = tempInF;
|
||||||
|
|
||||||
|
if (windInMph > 3 && tempInF < 50) {
|
||||||
|
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
|
||||||
|
} else if (tempInF > 80 && this.humidity > 40) {
|
||||||
|
feelsLike = -42.379 + 2.04901523 * tempInF + 10.14333127 * this.humidity
|
||||||
|
- 0.22475541 * tempInF * this.humidity - 6.83783 * Math.pow(10, -3) * tempInF * tempInF
|
||||||
|
- 5.481717 * Math.pow(10, -2) * this.humidity * this.humidity
|
||||||
|
+ 1.22874 * Math.pow(10, -3) * tempInF * tempInF * this.humidity
|
||||||
|
+ 8.5282 * Math.pow(10, -4) * tempInF * this.humidity * this.humidity
|
||||||
|
- 1.99 * Math.pow(10, -6) * tempInF * tempInF * this.humidity * this.humidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.units === "imperial" ? feelsLike : (feelsLike - 32) * 5 / 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user