Module.register('MMM-YrNow', { defaults: { yrApiUrl: "https://www.yr.no/api/v0/locations/%s/forecast", updateInterval: 10000 }, getTranslations: function() { return { no: "translations/no.json", } }, getScripts: function() { return [ 'printf.js', 'readTextFile.js' ]; }, getStyles: function() { return ['mmm-yrnow.css']; }, start: function() { this.list = null; this.loaded = false; var forecastUrl = printf(printf('%s', this.config.yrApiUrl),this.config.locationId); this.getForecast(forecastUrl); var self = this; setInterval(function() { self.updateDom(1000); }, 60000); }, socketNotificationReceived: function(notification, payload) { if(notification === 'YR_FORECAST_DATA') { if(payload.nowcast.points != null) { this.processNowcast(payload.nowcast); if(this.config.showWeatherForecast) this.processForecast(payload.forecast); } this.updateDom(1000); } }, getForecast: function(url) { this.sendSocketNotification('GET_YR_FORECAST', { forecastUrl: url, config: this.config }); }, getNextPrecipStart: function() { return this.list.points.filter((item) => item.precipitation.intensity > 0 && Date.parse(item.time) >= new Date().valueOf())[0]; }, getNextPrecipStop: function() { return this.list.points.filter((item) => item.precipitation.intensity === 0 && Date.parse(item.time) >= new Date().valueOf())[0]; }, getMinutesTill: function(nextItemTime) { return Math.abs(Date.parse(nextItemTime) - new Date().valueOf()) / (1000 * 60); }, getDom: function() { var wrapper = document.createElement('div'); var animationWrapper = document.createElement('div'); animationWrapper.className = 'animation'; if (!this.loaded) { wrapper.innerHTML = this.translate('loading'); wrapper.className = 'dimmed light small'; return wrapper; } var nowCast = this.translate('no_precip_next_90'); var precipitationStart = this.getNextPrecipStart(); var precipitationStop = this.getNextPrecipStop(); var forecast = document.createElement('div'); forecast.className = 'forecast'; if(precipitationStart != null) { //Precip some time during the next 90 minutes var precipitationStartsIn = this.getMinutesTill(precipitationStart.time); forecast.appendChild(animationWrapper); //Precip now if(precipitationStartsIn < 7) { this.createAnimation(animationWrapper); forecast.appendChild(this.getUmbrella()); if(precipitationStop) { precipitationStopsIn = this.getMinutesTill(precipitationStop.time); nowCast = printf(this.translate("precipitation_ends"), precipitationStopsIn.toFixed(0)); } else nowCast = this.translate("precip_next_90"); } else { //Precip in n minutes forecast.appendChild(this.getUmbrella()); nowCast = printf(this.translate("precip_in"), precipitationStartsIn.toFixed(0)); } } if(nowCast == this.translate('no_precip_next_90') && this.config.showWeatherForecast) { forecast.appendChild(this.getWeatherSymbol()); } wrapper.appendChild(forecast); wrapper.appendChild(this.getTemperature()); wrapper.appendChild(this.createNowcastText(nowCast)); return wrapper; }, createNowcastText: function(nowCast) { var nowCastText = document.createElement('p'); nowCastText.className = 'medium precipText'; nowCastText.innerHTML = nowCast; return nowCastText }, createAnimation: function(testElement) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { testElement.appendChild(xhr.responseXML.documentElement); } }; xhr.open('GET', this.file('images/rain.svg'), true); xhr.send(''); }, getUmbrella: function() { var umbrella = document.createElement('img'); umbrella.className = 'umbrella'; umbrella.src = this.file('images/umbrella.svg'); return umbrella; }, getWeatherSymbol: function() { var symbol = document.createElement('img'); symbol.className = 'weatherSymbol'; symbol.src = this.file(printf('images/%s.svg', this.weatherSymbol)); return symbol; }, getTemperature: function() { var temp = document.createElement('div'); temp.className = 'temperature light large bright'; temp.innerHTML = printf('%s°', Math.round(this.temperature)); return temp; }, processNowcast: function(obj) { if(obj.points) { this.list = obj; this.loaded = true; } }, calculateWeatherSymbolId: function(data) { if (!data) return ''; let id = data.n < 10 ? printf('0%s', data.n) : data.n; switch (data.var) { case 'Sun': id += 'd'; break; case 'PolarNight': id += 'm'; break; case 'Moon': id += 'n'; break; } return id; }, processForecast: function(obj) { if(obj.shortIntervals) { this.weatherSymbol = this.calculateWeatherSymbolId(obj.shortIntervals[0].symbol); this.temperature = obj.shortIntervals[0].temperature.value; this.loaded = true; } } });