/* global WeatherProvider, WeatherObject */ /* Magic Mirror * Module: Weather * Provider: Weatherbit * * By Andrew Pometti * MIT Licensed * * This class is a provider for Weatherbit, based on Nicholas Hubbard's class * for Dark Sky & Vince Peri's class for Weather.gov. */ WeatherProvider.register("weatherbit", { // Set the name of the provider. // Not strictly required, but helps for debugging. providerName: "Weatherbit", // Set the default config properties that is specific to this provider defaults: { apiBase: "https://api.weatherbit.io/v2.0", weatherEndpoint: "/current", apiKey: "", lat: 0, lon: 0 }, units: { imperial: "I", metric: "M" }, fetchedLocation: function () { return this.fetchedLocationName || ""; }, fetchCurrentWeather() { this.fetchData(this.getUrl()) .then((data) => { if (!data || !data.data[0] || typeof data.data[0].temp === "undefined") { // No usable data? return; } const currentWeather = this.generateWeatherDayFromCurrentWeather(data); this.setCurrentWeather(currentWeather); }) .catch(function (request) { Log.error("Could not load data ... ", request); }) .finally(() => this.updateAvailable()); }, fetchWeatherForecast() { this.fetchData(this.getUrl()) .then((data) => { if (!data || !data.data) { // No usable data? return; } const forecast = this.generateWeatherObjectsFromForecast(data.data); this.setWeatherForecast(forecast); this.fetchedLocationName = data.city_name + ", " + data.state_code; }) .catch(function (request) { Log.error("Could not load data ... ", request); }) .finally(() => this.updateAvailable()); }, // Create a URL from the config and base URL. getUrl() { const units = this.units[this.config.units] || "auto"; return `${this.config.apiBase}${this.config.weatherEndpoint}?lat=${this.config.lat}&lon=${this.config.lon}&units=${units}&key=${this.config.apiKey}`; }, // Implement WeatherDay generator. generateWeatherDayFromCurrentWeather(currentWeatherData) { //Calculate TZ Offset and invert to convert Sunrise/Sunset times to Local const d = new Date(); let tzOffset = d.getTimezoneOffset(); tzOffset = tzOffset * -1; const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); currentWeather.date = moment(currentWeatherData.data[0].ts, "X"); currentWeather.humidity = parseFloat(currentWeatherData.data[0].rh); currentWeather.temperature = parseFloat(currentWeatherData.data[0].temp); currentWeather.windSpeed = parseFloat(currentWeatherData.data[0].wind_spd); currentWeather.windDirection = currentWeatherData.data[0].wind_dir; currentWeather.weatherType = this.convertWeatherType(currentWeatherData.data[0].weather.icon); currentWeather.sunrise = moment(currentWeatherData.data[0].sunrise, "HH:mm").add(tzOffset, "m"); currentWeather.sunset = moment(currentWeatherData.data[0].sunset, "HH:mm").add(tzOffset, "m"); this.fetchedLocationName = currentWeatherData.data[0].city_name + ", " + currentWeatherData.data[0].state_code; return currentWeather; }, generateWeatherObjectsFromForecast(forecasts) { const days = []; for (const forecast of forecasts) { const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); weather.date = moment(forecast.datetime, "YYYY-MM-DD"); weather.minTemperature = forecast.min_temp; weather.maxTemperature = forecast.max_temp; weather.precipitation = forecast.precip; weather.weatherType = this.convertWeatherType(forecast.weather.icon); days.push(weather); } return days; }, // Map icons from Dark Sky to our icons. convertWeatherType(weatherType) { const weatherTypes = { t01d: "day-thunderstorm", t01n: "night-alt-thunderstorm", t02d: "day-thunderstorm", t02n: "night-alt-thunderstorm", t03d: "thunderstorm", t03n: "thunderstorm", t04d: "day-thunderstorm", t04n: "night-alt-thunderstorm", t05d: "day-sleet-storm", t05n: "night-alt-sleet-storm", d01d: "day-sprinkle", d01n: "night-alt-sprinkle", d02d: "day-sprinkle", d02n: "night-alt-sprinkle", d03d: "day-shower", d03n: "night-alt-shower", r01d: "day-shower", r01n: "night-alt-shower", r02d: "day-rain", r02n: "night-alt-rain", r03d: "day-rain", r03n: "night-alt-rain", r04d: "day-sprinkle", r04n: "night-alt-sprinkle", r05d: "day-shower", r05n: "night-alt-shower", r06d: "day-shower", r06n: "night-alt-shower", f01d: "day-sleet", f01n: "night-alt-sleet", s01d: "day-snow", s01n: "night-alt-snow", s02d: "day-snow-wind", s02n: "night-alt-snow-wind", s03d: "snowflake-cold", s03n: "snowflake-cold", s04d: "day-rain-mix", s04n: "night-alt-rain-mix", s05d: "day-sleet", s05n: "night-alt-sleet", s06d: "day-snow", s06n: "night-alt-snow", a01d: "day-haze", a01n: "dust", a02d: "smoke", a02n: "smoke", a03d: "day-haze", a03n: "dust", a04d: "dust", a04n: "dust", a05d: "day-fog", a05n: "night-fog", a06d: "fog", a06n: "fog", c01d: "day-sunny", c01n: "night-clear", c02d: "day-sunny-overcast", c02n: "night-alt-partly-cloudy", c03d: "day-cloudy", c03n: "night-alt-cloudy", c04d: "cloudy", c04n: "cloudy", u00d: "rain-mix", u00n: "rain-mix" }; return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; } });