Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 da translation
- Rework weather module
- Use fetch instead of XMLHttpRequest in weatherprovider

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion js/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @param {object} options object e.g. for headers
* @class
*/
async function fetch(url, options) {
async function fetch(url, options = {}) {
const nodeVersion = process.version.match(/^v(\d+)\.*/)[1];
if (nodeVersion >= 18) {
// node version >= 18
Expand Down
10 changes: 5 additions & 5 deletions modules/default/weather/providers/envcanada.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ WeatherProvider.register("envcanada", {
// Override the fetchCurrentWeather method to query EC and construct a Current weather object
//
fetchCurrentWeather() {
this.fetchData(this.getUrl(), "GET", "xml")
this.fetchData(this.getUrl(), "xml")
.then((data) => {
if (!data) {
// Did not receive usable new data.
Expand All @@ -94,7 +94,7 @@ WeatherProvider.register("envcanada", {
// Override the fetchWeatherForecast method to query EC and construct Forecast weather objects
//
fetchWeatherForecast() {
this.fetchData(this.getUrl(), "GET", "xml")
this.fetchData(this.getUrl(), "xml")
.then((data) => {
if (!data) {
// Did not receive usable new data.
Expand All @@ -114,7 +114,7 @@ WeatherProvider.register("envcanada", {
// Override the fetchWeatherHourly method to query EC and construct Forecast weather objects
//
fetchWeatherHourly() {
this.fetchData(this.getUrl(), "GET", "xml")
this.fetchData(this.getUrl(), "xml")
.then((data) => {
if (!data) {
// Did not receive usable new data.
Expand All @@ -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
// URL defaults to the Englsih version simply because there is no language dependancy in the data
// Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the
// 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.
//
getUrl() {
Expand Down
8 changes: 3 additions & 5 deletions modules/default/weather/providers/openweathermap.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ WeatherProvider.register("openweathermap", {
weatherEndpoint: "", // can be "onecall", "forecast" or "weather" (for current)
locationID: 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,
apiKey: ""
},
Expand Down Expand Up @@ -147,8 +147,7 @@ WeatherProvider.register("openweathermap", {
return this.fetchForecastDaily(forecasts);
}
// 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 days;
return [new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh)];
},

/*
Expand All @@ -159,8 +158,7 @@ WeatherProvider.register("openweathermap", {
return this.fetchOnecall(data);
}
// 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 weatherData;
return { current: new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh), hours: [], days: [] };
},

/*
Expand Down
6 changes: 3 additions & 3 deletions modules/default/weather/providers/smhi.js
Original file line number Diff line number Diff line change
Expand Up @@ -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} coordinates Coordinates of the locations of the weather
Expand Down Expand Up @@ -203,7 +203,7 @@ WeatherProvider.register("smhi", {
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()) {
dayWeatherTypes.push(weatherObject.weatherType);
}
Expand Down Expand Up @@ -271,7 +271,7 @@ WeatherProvider.register("smhi", {

/**
* 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.
*
* @param {number} input The SMHI icon value
Expand Down
14 changes: 7 additions & 7 deletions modules/default/weather/providers/ukmetofficedatahub.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ WeatherProvider.register("ukmetofficedatahub", {
fetchCurrentWeather() {
this.fetchWeather(this.getUrl("hourly"), this.getHeaders())
.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) {
// Did not receive usable new data.
// Maybe this needs a better check?
Expand All @@ -109,7 +109,7 @@ WeatherProvider.register("ukmetofficedatahub", {
// Catch any error(s)
.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());
},

Expand Down Expand Up @@ -140,15 +140,15 @@ WeatherProvider.register("ukmetofficedatahub", {
currentWeather.precipitation = forecastDataHours[hour].probOfPrecipitation;
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)
currentWeather.rawData = forecastDataHours[hour];
}
}

// Determine the sunrise/sunset times - (still) not supplied in UK Met Office data
// 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);

return currentWeather;
Expand All @@ -158,7 +158,7 @@ WeatherProvider.register("ukmetofficedatahub", {
fetchWeatherForecast() {
this.fetchWeather(this.getUrl("daily"), this.getHeaders())
.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) {
// Did not receive usable new data.
// Maybe this needs a better check?
Expand All @@ -178,7 +178,7 @@ WeatherProvider.register("ukmetofficedatahub", {
// Catch any error(s)
.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());
},

Expand Down Expand Up @@ -216,7 +216,7 @@ WeatherProvider.register("ukmetofficedatahub", {
forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow;
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)
forecastWeather.rawData = forecastDataDays[day];

Expand Down
6 changes: 3 additions & 3 deletions modules/default/weather/weatherobject.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ class WeatherObject {

/**
* 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.
*
* @param {number} lat latitude
* @param {number} lon longitude
*/
updateSunTime(lat, lon) {
let now = !this.date ? new Date() : this.date.toDate();
let times = SunCalc.getTimes(now, lat, lon);
const now = !this.date ? new Date() : this.date.toDate();
const times = SunCalc.getTimes(now, lat, lon);
this.sunrise = moment(times.sunrise, "X");
this.sunset = moment(times.sunset, "X");
}
Expand Down
51 changes: 21 additions & 30 deletions modules/default/weather/weatherprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
const getData = function (mockData) {
return new Promise(function (resolve, reject) {
if (mockData) {
let data = mockData;
data = data.substring(1, data.length - 1);
resolve(JSON.parse(data));
} else {
const request = new XMLHttpRequest();
request.open(method, url, true);
request.onreadystatechange = function () {
if (this.readyState === 4) {
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);
const mockData = this.config.mockData;
if (mockData) {
const data = mockData.substring(1, mockData.length - 1);
return JSON.parse(data);
} else {
const response = await fetch(url);
const data = await response.text();
if (type === "xml") {
return new DOMParser().parseFromString(data, "text/html");
} else {
return JSON.parse(data);
}
}
}
});

Expand Down