mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-21 12:55:22 +00:00
add additional URLs per API
This commit is contained in:
@@ -3,13 +3,14 @@
|
|||||||
/* Magic Mirror
|
/* Magic Mirror
|
||||||
* Module: Weather
|
* Module: Weather
|
||||||
* Provider: weather.gov
|
* Provider: weather.gov
|
||||||
|
* https://weather-gov.github.io/api/general-faqs
|
||||||
*
|
*
|
||||||
* By Vince Peri
|
* Original by Vince Peri
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*
|
*
|
||||||
* This class is a provider for weather.gov.
|
* This class is a provider for weather.gov.
|
||||||
* Note that this is only for US locations (lat and lon) and does not require an API key
|
* Note that this is only for US locations (lat and lon) and does not require an API key
|
||||||
* Since it is free, there are some items missing - like sunrise, sunset, humidity, etc.
|
* Since it is free, there are some items missing - like sunrise, sunset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WeatherProvider.register("weathergov", {
|
WeatherProvider.register("weathergov", {
|
||||||
@@ -18,10 +19,10 @@ WeatherProvider.register("weathergov", {
|
|||||||
// But for debugging (and future alerts) it would be nice to have the real name.
|
// But for debugging (and future alerts) it would be nice to have the real name.
|
||||||
providerName: "Weather.gov",
|
providerName: "Weather.gov",
|
||||||
|
|
||||||
// need setConfig URLs status
|
// Flag all needed URLs availability
|
||||||
configURLs: false,
|
configURLs: false,
|
||||||
|
|
||||||
//multiple urls involved
|
//This API has multiple urls involved
|
||||||
forecastURL: "tbd",
|
forecastURL: "tbd",
|
||||||
forecastHourlyURL: "tbd",
|
forecastHourlyURL: "tbd",
|
||||||
forecastGridDataURL: "tbd",
|
forecastGridDataURL: "tbd",
|
||||||
@@ -31,9 +32,7 @@ WeatherProvider.register("weathergov", {
|
|||||||
// Called to set the config, this config is the same as the weather module's config.
|
// Called to set the config, this config is the same as the weather module's config.
|
||||||
setConfig: function (config) {
|
setConfig: function (config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
Log.info(`Weather provider: ${this.providerName} config set.`, this.config);
|
(this.config.apiBase = "https://api.weather.gov"), this.fetchWxGovURLs(this.config);
|
||||||
// URLs needed from weather.gov
|
|
||||||
this.fetchWxGovURLs(this.config);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called when the weather provider is about to start.
|
// Called when the weather provider is about to start.
|
||||||
@@ -41,26 +40,28 @@ WeatherProvider.register("weathergov", {
|
|||||||
Log.info(`Weather provider: ${this.providerName} started.`);
|
Log.info(`Weather provider: ${this.providerName} started.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// This returns the name of the fetched location or an empty string.
|
||||||
|
fetchedLocation: function () {
|
||||||
|
return this.fetchedLocationName || "";
|
||||||
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
if (!this.configURLs) {
|
if (!this.configURLs) {
|
||||||
Log.info("fetch wx waiting on config URLs");
|
Log.info("fetch wx waiting on config URLs");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// this.fetchData(this.getUrl())
|
this.fetchData(this.stationObsURL)
|
||||||
this.fetchData(this.forecastURL)
|
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
if (!data || !data.properties) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties);
|
||||||
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties.periods[0]);
|
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
})
|
})
|
||||||
.catch(function (request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load station obs data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
@@ -71,20 +72,17 @@ WeatherProvider.register("weathergov", {
|
|||||||
Log.info("fetch wx waiting on config URLs");
|
Log.info("fetch wx waiting on config URLs");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//this.fetchData(this.getUrl())
|
this.fetchData(this.forecastURL)
|
||||||
this.fetchData(this.forecastHourlyURL)
|
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods);
|
const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
})
|
})
|
||||||
.catch(function (request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load forecast hourly data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
@@ -95,21 +93,20 @@ WeatherProvider.register("weathergov", {
|
|||||||
* Get specific URLs
|
* Get specific URLs
|
||||||
*/
|
*/
|
||||||
fetchWxGovURLs(config) {
|
fetchWxGovURLs(config) {
|
||||||
// wxCtl.initialLoadDelay here ?
|
|
||||||
this.fetchData(`${config.apiBase}/points/${config.lat},${config.lon}`)
|
this.fetchData(`${config.apiBase}/points/${config.lat},${config.lon}`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data || !data.properties) {
|
if (!data || !data.properties) {
|
||||||
// points URL did not respond with usable data.
|
// points URL did not respond with usable data.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.fetchedLocationName = data.properties.relativeLocation.properties.city + ", " + data.properties.relativeLocation.properties.state;
|
||||||
|
Log.log("Forecast location is " + this.fetchedLocationName);
|
||||||
this.forecastURL = data.properties.forecast;
|
this.forecastURL = data.properties.forecast;
|
||||||
Log.log(this.forecastURL);
|
|
||||||
this.forecastHourlyURL = data.properties.forecastHourly;
|
this.forecastHourlyURL = data.properties.forecastHourly;
|
||||||
this.forecastGridDataURL = data.properties.forecastGridData;
|
this.forecastGridDataURL = data.properties.forecastGridData;
|
||||||
this.observationStationsURL = data.properties.observationStations;
|
this.observationStationsURL = data.properties.observationStations;
|
||||||
// with this URL, we chain another promise for the station obs URL
|
// with this URL, we chain another promise for the station obs URL
|
||||||
return this.fetchData(data.properties.observationStations);
|
return this.fetchData(data.properties.observationStations);
|
||||||
//const wxStations = await this.fetchData(wxPoints.properties.observationStationsURL);
|
|
||||||
})
|
})
|
||||||
.then((obsData) => {
|
.then((obsData) => {
|
||||||
if (!obsData || !obsData.features) {
|
if (!obsData || !obsData.features) {
|
||||||
@@ -117,34 +114,44 @@ WeatherProvider.register("weathergov", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.stationObsURL = obsData.features[0].id + "/observations/latest";
|
this.stationObsURL = obsData.features[0].id + "/observations/latest";
|
||||||
Log.log(this.stationObsURL);
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
Log.error(err);
|
Log.error(err);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
// excellent, let's fetch some actual wx data
|
||||||
this.configURLs = true;
|
this.configURLs = true;
|
||||||
this.fetchCurrentWeather();
|
this.fetchCurrentWeather();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
|
||||||
* Gets the complete url for the request
|
|
||||||
*/
|
|
||||||
getUrl() {
|
|
||||||
return this.config.apiBase + this.config.lat + "," + this.config.lon + this.config.weatherEndpoint;
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a WeatherObject based on currentWeatherInformation
|
* Generate a WeatherObject based on currentWeatherInformation
|
||||||
|
* Weather.gov API uses specific units; API does not include choice of units
|
||||||
|
* ... object needs data in units based on config!
|
||||||
*/
|
*/
|
||||||
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
|
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
|
||||||
const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
|
const currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
|
||||||
|
|
||||||
currentWeather.temperature = currentWeatherData.temperature;
|
currentWeather.date = moment(currentWeatherData.timestamp);
|
||||||
currentWeather.windSpeed = currentWeatherData.windSpeed.split(" ", 1);
|
currentWeather.temperature = this.convertTemp(currentWeatherData.temperature.value);
|
||||||
currentWeather.windDirection = this.convertWindDirection(currentWeatherData.windDirection);
|
currentWeather.windSpeed = this.covertSpeed(currentWeatherData.windSpeed.value);
|
||||||
currentWeather.weatherType = this.convertWeatherType(currentWeatherData.shortForecast, currentWeatherData.isDaytime);
|
currentWeather.windDirection = currentWeatherData.windDirection.value;
|
||||||
|
currentWeather.minTemperature = this.convertTemp(currentWeatherData.minTemperatureLast24Hours.value);
|
||||||
|
currentWeather.maxTemperature = this.convertTemp(currentWeatherData.maxTemperatureLast24Hours.value);
|
||||||
|
currentWeather.humidity = Math.round(currentWeatherData.relativeHumidity.value);
|
||||||
|
currentWeather.rain = null;
|
||||||
|
currentWeather.snow = null;
|
||||||
|
currentWeather.precipitation = this.convertLength(currentWeatherData.precipitationLastHour.value);
|
||||||
|
currentWeather.feelsLikeTemp = this.convertTemp(currentWeatherData.heatIndex.value);
|
||||||
|
|
||||||
|
let isDaytime = true;
|
||||||
|
if (currentWeatherData.icon.includes("day")) {
|
||||||
|
isDaytime = true;
|
||||||
|
} else {
|
||||||
|
isDaytime = false;
|
||||||
|
}
|
||||||
|
currentWeather.weatherType = this.convertWeatherType(currentWeatherData.textDescription, isDaytime);
|
||||||
|
|
||||||
// determine the sunrise/sunset times - not supplied in weather.gov data
|
// determine the sunrise/sunset times - not supplied in weather.gov data
|
||||||
let times = this.calcAstroData(this.config.lat, this.config.lon);
|
let times = this.calcAstroData(this.config.lat, this.config.lon);
|
||||||
@@ -220,6 +227,34 @@ WeatherProvider.register("weathergov", {
|
|||||||
return days.slice(1);
|
return days.slice(1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unit conversions
|
||||||
|
*/
|
||||||
|
// conversion to fahrenheit
|
||||||
|
convertTemp(temp) {
|
||||||
|
if (this.config.tempUnits === "imperial") {
|
||||||
|
return (9 / 5) * temp + 32;
|
||||||
|
} else {
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// conversion to mph
|
||||||
|
covertSpeed(metSec) {
|
||||||
|
if (this.config.windUnits === "imperial") {
|
||||||
|
return metSec * 2.23694;
|
||||||
|
} else {
|
||||||
|
return metSec;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// conversion to inches
|
||||||
|
convertLength(meters) {
|
||||||
|
if (this.config.units === "imperial") {
|
||||||
|
return meters * 39.3701;
|
||||||
|
} else {
|
||||||
|
return meters;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the astronomical data
|
* Calculate the astronomical data
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user