mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
Use fetch instead of XMLHttpRequest in weatherprovider (#2935)
small update to the fetchData method to use the fetch helper instead of the old XCMLHttpRequest. Also fixes some typos :-) Co-authored-by: veeck <michael@veeck.de>
This commit is contained in:
parent
a86e27a12c
commit
d5e855dd6d
@ -22,6 +22,8 @@ Special thanks to: @rejas, @sdetweil
|
|||||||
|
|
||||||
- Updated e2e tests (moved `done()` in helper functions) and use es6 syntax in all tests
|
- Updated e2e tests (moved `done()` in helper functions) and use es6 syntax in all tests
|
||||||
- Updated da translation
|
- Updated da translation
|
||||||
|
- Rework weather module
|
||||||
|
- Use fetch instead of XMLHttpRequest in weatherprovider
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @param {object} options object e.g. for headers
|
* @param {object} options object e.g. for headers
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
async function fetch(url, options) {
|
async function fetch(url, options = {}) {
|
||||||
const nodeVersion = process.version.match(/^v(\d+)\.*/)[1];
|
const nodeVersion = process.version.match(/^v(\d+)\.*/)[1];
|
||||||
if (nodeVersion >= 18) {
|
if (nodeVersion >= 18) {
|
||||||
// node version >= 18
|
// node version >= 18
|
||||||
|
@ -74,7 +74,7 @@ WeatherProvider.register("envcanada", {
|
|||||||
// Override the fetchCurrentWeather method to query EC and construct a Current weather object
|
// Override the fetchCurrentWeather method to query EC and construct a Current weather object
|
||||||
//
|
//
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl(), "GET", "xml")
|
this.fetchData(this.getUrl(), "xml")
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
@ -94,7 +94,7 @@ WeatherProvider.register("envcanada", {
|
|||||||
// Override the fetchWeatherForecast method to query EC and construct Forecast weather objects
|
// Override the fetchWeatherForecast method to query EC and construct Forecast weather objects
|
||||||
//
|
//
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl(), "GET", "xml")
|
this.fetchData(this.getUrl(), "xml")
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
@ -114,7 +114,7 @@ WeatherProvider.register("envcanada", {
|
|||||||
// Override the fetchWeatherHourly method to query EC and construct Forecast weather objects
|
// Override the fetchWeatherHourly method to query EC and construct Forecast weather objects
|
||||||
//
|
//
|
||||||
fetchWeatherHourly() {
|
fetchWeatherHourly() {
|
||||||
this.fetchData(this.getUrl(), "GET", "xml")
|
this.fetchData(this.getUrl(), "xml")
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
@ -137,8 +137,8 @@ WeatherProvider.register("envcanada", {
|
|||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//
|
//
|
||||||
// Build the EC URL based on the Site Code and Province Code specified in the config parms. Note that the
|
// Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the
|
||||||
// URL defaults to the Englsih version simply because there is no language dependancy in the data
|
// URL defaults to the English version simply because there is no language dependency in the data
|
||||||
// being accessed. This is only pertinent when using the EC data elements that contain a textual forecast.
|
// being accessed. This is only pertinent when using the EC data elements that contain a textual forecast.
|
||||||
//
|
//
|
||||||
getUrl() {
|
getUrl() {
|
||||||
|
@ -21,7 +21,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
weatherEndpoint: "", // can be "onecall", "forecast" or "weather" (for current)
|
weatherEndpoint: "", // can be "onecall", "forecast" or "weather" (for current)
|
||||||
locationID: false,
|
locationID: false,
|
||||||
location: false,
|
location: false,
|
||||||
lat: 0, // the onecall endpoint needs lat / lon values, it doesn'T support the locationId
|
lat: 0, // the onecall endpoint needs lat / lon values, it doesn't support the locationId
|
||||||
lon: 0,
|
lon: 0,
|
||||||
apiKey: ""
|
apiKey: ""
|
||||||
},
|
},
|
||||||
@ -147,8 +147,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
return this.fetchForecastDaily(forecasts);
|
return this.fetchForecastDaily(forecasts);
|
||||||
}
|
}
|
||||||
// if weatherEndpoint does not match forecast or forecast/daily, what should be returned?
|
// if weatherEndpoint does not match forecast or forecast/daily, what should be returned?
|
||||||
const days = [new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh)];
|
return [new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh)];
|
||||||
return days;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -159,8 +158,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
return this.fetchOnecall(data);
|
return this.fetchOnecall(data);
|
||||||
}
|
}
|
||||||
// if weatherEndpoint does not match onecall, what should be returned?
|
// if weatherEndpoint does not match onecall, what should be returned?
|
||||||
const weatherData = { current: new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh), hours: [], days: [] };
|
return { current: new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh), hours: [], days: [] };
|
||||||
return weatherData;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,7 +174,7 @@ WeatherProvider.register("smhi", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes all of the data points and converts it to one WeatherObject per day.
|
* Takes all the data points and converts it to one WeatherObject per day.
|
||||||
*
|
*
|
||||||
* @param {object[]} allWeatherData Array of weatherdata
|
* @param {object[]} allWeatherData Array of weatherdata
|
||||||
* @param {object} coordinates Coordinates of the locations of the weather
|
* @param {object} coordinates Coordinates of the locations of the weather
|
||||||
@ -203,7 +203,7 @@ WeatherProvider.register("smhi", {
|
|||||||
result.push(currentWeather);
|
result.push(currentWeather);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Keep track of what icons has been used for each hour of daytime and use the middle one for the forecast
|
//Keep track of what icons have been used for each hour of daytime and use the middle one for the forecast
|
||||||
if (weatherObject.isDayTime()) {
|
if (weatherObject.isDayTime()) {
|
||||||
dayWeatherTypes.push(weatherObject.weatherType);
|
dayWeatherTypes.push(weatherObject.weatherType);
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ WeatherProvider.register("smhi", {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Map the icon value from SMHI to an icon that MagicMirror² understands.
|
* Map the icon value from SMHI to an icon that MagicMirror² understands.
|
||||||
* Uses different icons depending if its daytime or nighttime.
|
* Uses different icons depending on if its daytime or nighttime.
|
||||||
* SMHI's description of what the numeric value means is the comment after the case.
|
* SMHI's description of what the numeric value means is the comment after the case.
|
||||||
*
|
*
|
||||||
* @param {number} input The SMHI icon value
|
* @param {number} input The SMHI icon value
|
||||||
|
@ -89,7 +89,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchWeather(this.getUrl("hourly"), this.getHeaders())
|
this.fetchWeather(this.getUrl("hourly"), this.getHeaders())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
// Check data is useable
|
// Check data is usable
|
||||||
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
|
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
@ -109,7 +109,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
// Catch any error(s)
|
// Catch any error(s)
|
||||||
.catch((error) => Log.error("Could not load data: " + error.message))
|
.catch((error) => Log.error("Could not load data: " + error.message))
|
||||||
|
|
||||||
// Let the module know there're new data available
|
// Let the module know there is data available
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
currentWeather.precipitation = forecastDataHours[hour].probOfPrecipitation;
|
currentWeather.precipitation = forecastDataHours[hour].probOfPrecipitation;
|
||||||
currentWeather.feelsLikeTemp = this.convertTemp(forecastDataHours[hour].feelsLikeTemperature);
|
currentWeather.feelsLikeTemp = this.convertTemp(forecastDataHours[hour].feelsLikeTemperature);
|
||||||
|
|
||||||
// Pass on full details so they can be used in custom templates
|
// Pass on full details, so they can be used in custom templates
|
||||||
// Note the units of the supplied data when using this (see top of file)
|
// Note the units of the supplied data when using this (see top of file)
|
||||||
currentWeather.rawData = forecastDataHours[hour];
|
currentWeather.rawData = forecastDataHours[hour];
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
|
|
||||||
// Determine the sunrise/sunset times - (still) not supplied in UK Met Office data
|
// Determine the sunrise/sunset times - (still) not supplied in UK Met Office data
|
||||||
// Passes {longitude, latitude} to SunCalc, could pass height to, but
|
// Passes {longitude, latitude} to SunCalc, could pass height to, but
|
||||||
// SunCalc.getTimes doesnt take that into account
|
// SunCalc.getTimes doesn't take that into account
|
||||||
currentWeather.updateSunTime(this.config.lat, this.config.lon);
|
currentWeather.updateSunTime(this.config.lat, this.config.lon);
|
||||||
|
|
||||||
return currentWeather;
|
return currentWeather;
|
||||||
@ -158,7 +158,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchWeather(this.getUrl("daily"), this.getHeaders())
|
this.fetchWeather(this.getUrl("daily"), this.getHeaders())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
// Check data is useable
|
// Check data is usable
|
||||||
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
|
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
@ -178,7 +178,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
// Catch any error(s)
|
// Catch any error(s)
|
||||||
.catch((error) => Log.error("Could not load data: " + error.message))
|
.catch((error) => Log.error("Could not load data: " + error.message))
|
||||||
|
|
||||||
// Let the module know there're new data available
|
// Let the module know there is new data available
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow;
|
forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow;
|
||||||
forecastWeather.feelsLikeTemp = this.convertTemp(forecastDataDays[day].dayMaxFeelsLikeTemp);
|
forecastWeather.feelsLikeTemp = this.convertTemp(forecastDataDays[day].dayMaxFeelsLikeTemp);
|
||||||
|
|
||||||
// Pass on full details so they can be used in custom templates
|
// Pass on full details, so they can be used in custom templates
|
||||||
// Note the units of the supplied data when using this (see top of file)
|
// Note the units of the supplied data when using this (see top of file)
|
||||||
forecastWeather.rawData = forecastDataDays[day];
|
forecastWeather.rawData = forecastDataDays[day];
|
||||||
|
|
||||||
|
@ -134,15 +134,15 @@ class WeatherObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the sunrise / sunset time depending on the location. This can be
|
* Update the sunrise / sunset time depending on the location. This can be
|
||||||
* used if your provider doesnt provide that data by itself. Then SunCalc
|
* used if your provider doesn't provide that data by itself. Then SunCalc
|
||||||
* is used here to calculate them according to the location.
|
* is used here to calculate them according to the location.
|
||||||
*
|
*
|
||||||
* @param {number} lat latitude
|
* @param {number} lat latitude
|
||||||
* @param {number} lon longitude
|
* @param {number} lon longitude
|
||||||
*/
|
*/
|
||||||
updateSunTime(lat, lon) {
|
updateSunTime(lat, lon) {
|
||||||
let now = !this.date ? new Date() : this.date.toDate();
|
const now = !this.date ? new Date() : this.date.toDate();
|
||||||
let times = SunCalc.getTimes(now, lat, lon);
|
const times = SunCalc.getTimes(now, lat, lon);
|
||||||
this.sunrise = moment(times.sunrise, "X");
|
this.sunrise = moment(times.sunrise, "X");
|
||||||
this.sunset = moment(times.sunset, "X");
|
this.sunset = moment(times.sunset, "X");
|
||||||
}
|
}
|
||||||
|
@ -119,37 +119,28 @@ const WeatherProvider = Class.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// A convenience function to make requests. It returns a promise.
|
/**
|
||||||
fetchData: function (url, method = "GET", type = "json") {
|
* A convenience function to make requests.
|
||||||
|
*
|
||||||
|
* @param {string} url the url to fetch from
|
||||||
|
* @param {string} type what contenttype to expect in the response, can be "json" or "xml"
|
||||||
|
* @returns {Promise} resolved when the fetch is done
|
||||||
|
*/
|
||||||
|
fetchData: async function (url, type = "json") {
|
||||||
url = this.getCorsUrl() + url;
|
url = this.getCorsUrl() + url;
|
||||||
const getData = function (mockData) {
|
const mockData = this.config.mockData;
|
||||||
return new Promise(function (resolve, reject) {
|
if (mockData) {
|
||||||
if (mockData) {
|
const data = mockData.substring(1, mockData.length - 1);
|
||||||
let data = mockData;
|
return JSON.parse(data);
|
||||||
data = data.substring(1, data.length - 1);
|
} else {
|
||||||
resolve(JSON.parse(data));
|
const response = await fetch(url);
|
||||||
} else {
|
const data = await response.text();
|
||||||
const request = new XMLHttpRequest();
|
if (type === "xml") {
|
||||||
request.open(method, url, true);
|
return new DOMParser().parseFromString(data, "text/html");
|
||||||
request.onreadystatechange = function () {
|
} else {
|
||||||
if (this.readyState === 4) {
|
return JSON.parse(data);
|
||||||
if (this.status === 200) {
|
}
|
||||||
if (type === "xml") {
|
}
|
||||||
resolve(this.responseXML);
|
|
||||||
} else {
|
|
||||||
resolve(JSON.parse(this.response));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.send();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return getData(this.config.mockData);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user