Read the statement by Michael Teeuw here.
Changing icons of the modules Current Weather and Weather Forecast
-
@aecandroid - I’m not seeing anything obviously incorrect with your config. What behavior are you seeing that you wish to fix? Are you getting the module to display at all? Are you getting any modules to display at all? Are you just not getting the icons that you wish?
-
You are missing a comma in line
appid
forcurrentweather
modulelocationID: "xxx", //ID from http://www.openweathermap.org/help/city_list.txt appid: "xxx", iconTable: {
-
@bhepler when I add the iconTable it gives me the screen saying I need to add a config.js file or if one is already added, then to use the javascript line checker. If I delete the icon table, everything works fine.
-
@yawns too right you are my friend!! The smallest oversight messes up the whole game. Thank you!!
-
Hello everyone,
I was looking for some animated icons for weather forecast, however I did not find it very easily to change them. However I spent few hours of digging up to code and here is my approach for now. I know it’s definitely not the best or cleanest solution, but hey, Its working.
It uses CSS animations, I triet some tests with CPU usage and it looks usable for me on Raspi 3 b+. There are of course missing some of actual weather conditions, maybe I will try to mix some of them to create more variations.To install these you need to add this code to custom.css
.icon { position: relative; display: inline-block; width: 14em; height: 0px; font-size: 0.8rem; } .cloud { position: absolute; z-index: 1; top: 50%; left: 50%; width: 3.6875em; height: 3.6875em; margin: -1.84375em; background: currentColor; border-radius: 50%; box-shadow: -2.1875em 0.6875em 0 -0.6875em, 2.0625em 0.9375em 0 -0.9375em, 0 0 0 0.375em #fff, -2.1875em 0.6875em 0 -0.3125em #fff, 2.0625em 0.9375em 0 -0.5625em #fff; } .cloud:after { content: ''; position: absolute; bottom: 0; left: -0.5em; display: block; width: 4.5625em; height: 1em; background: currentColor; box-shadow: 0 0.375em #fff; } .cloud:nth-child(2) { z-index: 0; background: #fff; box-shadow: -2.1875em 0.6875em 0 -0.6875em #fff, 2.0625em 0.9375em 0 -0.9375em #fff, 0 0 0 0.375em #fff, -2.1875em 0.6875em 0 -0.3125em #fff, 2.0625em 0.9375em 0 -0.5625em #fff; opacity: 0.3; transform: scale(0.5) translate(6em, -3em); animation: cloud 4s linear infinite; } .cloud:nth-child(2):after { background: #fff; } .sun { position: absolute; top: 50%; left: 50%; width: 2.5em; height: 2.5em; margin: -1.25em; background: currentColor; border-radius: 50%; box-shadow: 0 0 0 0.375em #fff; animation: spin 12s infinite linear; } .rays { position: absolute; top: -2em; left: 50%; display: block; width: 0.375em; height: 1.125em; margin-left: -0.1875em; background: #fff; border-radius: 0.25em; box-shadow: 0 5.375em #fff; } .rays:before, .rays:after { content: ''; position: absolute; top: 0em; left: 0em; display: block; width: 0.375em; height: 1.125em; transform: rotate(60deg); transform-origin: 50% 3.25em; background: #fff; border-radius: 0.25em; box-shadow: 0 5.375em #fff; } .rays:before { transform: rotate(120deg); } .cloud + .sun { margin: -2em 1em; } .rain, .lightning, .snow { position: absolute; z-index: 2; top: 50%; left: 50%; width: 3.75em; height: 3.75em; margin: 0.375em 0 0 -2em; background: currentColor; } .rain:after { content: ''; position: absolute; z-index: 2; top: 50%; left: 50%; width: 1.125em; height: 1.125em; margin: -1em 0 0 -0.25em; background: #0cf; border-radius: 100% 0 60% 50% / 60% 0 100% 50%; box-shadow: 0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2), -0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2), -1.375em -0.125em 0 rgba(255,255,255,0.2); transform: rotate(-28deg); animation: rain 3s linear infinite; } .bolt { position: absolute; top: 50%; left: 50%; margin: -0.25em 0 0 -0.125em; color: #fff; opacity: 0.3; animation: lightning 2s linear infinite; } .bolt:nth-child(2) { width: 0.5em; height: 0.25em; margin: -1.75em 0 0 -1.875em; transform: translate(2.5em, 2.25em); opacity: 0.2; animation: lightning 1.5s linear infinite; } .bolt:before, .bolt:after { content: ''; position: absolute; z-index: 2; top: 50%; left: 50%; margin: -1.625em 0 0 -1.0125em; border-top: 1.25em solid transparent; border-right: 0.75em solid; border-bottom: 0.75em solid; border-left: 0.5em solid transparent; transform: skewX(-10deg); } .bolt:after { margin: -0.25em 0 0 -0.25em; border-top: 0.75em solid; border-right: 0.5em solid transparent; border-bottom: 1.25em solid transparent; border-left: 0.75em solid; transform: skewX(-10deg); } .bolt:nth-child(2):before { margin: -0.75em 0 0 -0.5em; border-top: 0.625em solid transparent; border-right: 0.375em solid; border-bottom: 0.375em solid; border-left: 0.25em solid transparent; } .bolt:nth-child(2):after { margin: -0.125em 0 0 -0.125em; border-top: 0.375em solid; border-right: 0.25em solid transparent; border-bottom: 0.625em solid transparent; border-left: 0.375em solid; } .flake:before, .flake:after { content: '\2744'; position: absolute; top: 50%; left: 50%; margin: -1.025em 0 0 -1.0125em; color: #fff; list-height: 1em; opacity: 0.2; animation: spin 8s linear infinite reverse; } .flake:after { margin: 0.125em 0 0 -1em; font-size: 1.5em; opacity: 0.4; animation: spin 14s linear infinite; } .flake:nth-child(2):before { margin: -0.5em 0 0 0.25em; font-size: 1.25em; opacity: 0.2; animation: spin 10s linear infinite; } .flake:nth-child(2):after { margin: 0.375em 0 0 0.125em; font-size: 2em; opacity: 0.4; animation: spin 16s linear infinite reverse; } /* Animations */ @keyframes spin { 100% { transform: rotate(360deg); } } @keyframes cloud { 0% { opacity: 0; } 50% { opacity: 0.3; } 100% { opacity: 0; transform: scale(0.5) translate(-200%, -3em); } } @keyframes rain { 0% { background: #0cf; box-shadow: 0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2), -0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2), -1.375em -0.125em 0 #0cf; } 25% { box-shadow: 0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2), -0.875em 1.125em 0 -0.125em #0cf, -1.375em -0.125em 0 rgba(255,255,255,0.2); } 50% { background: rgba(255,255,255,0.3); box-shadow: 0.625em 0.875em 0 -0.125em #0cf, -0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2), -1.375em -0.125em 0 rgba(255,255,255,0.2); } 100% { box-shadow: 0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2), -0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2), -1.375em -0.125em 0 #0cf; } } @keyframes lightning { 45% { color: #fff; background: #fff; opacity: 0.2; } 50% { color: #0cf; background: #0cf; opacity: 1; } 55% { color: #fff; background: #fff; opacity: 0.2; } }
and change this file ~\MagicMirror\modules\default\currentweather\currentweather.js
/* global Module */ /* Magic Mirror * Module: CurrentWeather * * By Michael Teeuw http://michaelteeuw.nl * MIT Licensed. */ Module.register("currentweather",{ // Default module config. defaults: { location: false, locationID: false, appid: "", units: config.units, updateInterval: 10 * 60 * 1000, // every 10 minutes animationSpeed: 1000, timeFormat: config.timeFormat, showPeriod: true, showPeriodUpper: false, showWindDirection: true, showWindDirectionAsArrow: false, useBeaufort: true, appendLocationNameToHeader: false, useKMPHwind: false, lang: config.language, decimalSymbol: ".", showHumidity: false, degreeLabel: false, showIndoorTemperature: false, showIndoorHumidity: false, showFeelsLike: true, initialLoadDelay: 0, // 0 seconds delay retryDelay: 2500, apiVersion: "2.5", apiBase: "https://api.openweathermap.org/data/", weatherEndpoint: "weather", appendLocationNameToHeader: true, calendarClass: "calendar", onlyTemp: false, roundTemp: false, iconTable: { "01d": "wi-day-sunny", "02d": "wi-day-cloudy", "03d": "wi-cloudy", "04d": "wi-cloudy-windy", "09d": "wi-showers", "10d": "wi-rain", "11d": "wi-thunderstorm", "13d": "wi-snow", "50d": "wi-fog", "01n": "wi-night-clear", "02n": "wi-night-cloudy", "03n": "wi-night-cloudy", "04n": "wi-night-cloudy", "09n": "wi-night-showers", "10n": "wi-night-rain", "11n": "wi-night-thunderstorm", "13n": "wi-night-snow", "50n": "wi-night-alt-cloudy-windy" }, AnimatedIconTable: { "01d": "sunny", "02d": "cloudy", "03d": "cloudy", "04d": "cloudy", "09d": "sun-showers", "10d": "rain", "11d": "thunder-storm", "13d": "flurries", "50d": "cloudy", "01n": "sunny", "02n": "cloudy", "03n": "cloudy", "04n": "cloudy", "09n": "rainy", "10n": "rainy", "11n": "thunder-storm", "13n": "flurries", "50n": "cloudy" }, AnimatedIconTableInnerHTML: { "01d": '<div class="sun"><div class="rays"></div></div>', "02d": '<div class="cloud"></div><div class="cloud"></div>', "03d": '<div class="cloud"></div><div class="cloud"></div>', "04d": '<div class="cloud"></div><div class="cloud"></div>', "09d": '<div class="cloud"></div><div class="sun"><div class="rays"></div></div><div class="rain"></div>', "10d": '<div class="cloud"></div><div class="rain"></div>', "11d": '<div class="cloud"></div><div class="lightning"><div class="bolt"></div><div class="bolt"></div></div>', "13d": '<div class="cloud"></div><div class="snow"><div class="flake"></div><div class="flake"></div></div>', "50d": '<div class="cloud"></div><div class="cloud"></div>', "01n": '<div class="sun"><div class="rays"></div></div>', "02n": '<div class="cloud"></div><div class="cloud"></div>', "03n": '<div class="cloud"></div><div class="cloud"></div>', "04n": '<div class="cloud"></div><div class="cloud"></div>', "09n": '<div class="cloud"></div><div class="rain"></div>', "10n": '<div class="cloud"></div><div class="rain"></div>', "11n": '<div class="cloud"></div><div class="lightning"><div class="bolt"></div><div class="bolt"></div></div>', "13n": '<div class="cloud"></div><div class="snow"><div class="flake"></div><div class="flake"></div></div>', "50n": '<div class="cloud"></div><div class="cloud"></div>' }, }, // create a variable for the first upcoming calendar event. Used if no location is specified. firstEvent: false, // create a variable to hold the location name based on the API result. fetchedLocationName: "", // Define required scripts. getScripts: function() { return ["moment.js"]; }, // Define required scripts. getStyles: function() { return ["weather-icons.css", "currentweather.css"]; }, // Define required translations. getTranslations: function() { // The translations for the default modules are defined in the core translation files. // Therefor we can just return false. Otherwise we should have returned a dictionary. // If you're trying to build your own module including translations, check out the documentation. return false; }, // Define start sequence. start: function() { Log.info("Starting module: " + this.name); // Set locale. moment.locale(config.language); this.windSpeed = null; this.windDirection = null; this.windDeg = null; this.sunriseSunsetTime = null; this.sunriseSunsetIcon = null; this.temperature = null; this.indoorTemperature = null; this.indoorHumidity = null; this.weatherType = null; this.weatherTypeAnimated = null; this.weatherTypeAnimatedInnerHTML = null; this.feelsLike = null; this.loaded = false; this.scheduleUpdate(this.config.initialLoadDelay); }, // add extra information of current weather // windDirection, humidity, sunrise and sunset addExtraInfoWeather: function(wrapper) { var small = document.createElement("div"); small.className = "normal medium"; var windIcon = document.createElement("span"); windIcon.className = "wi wi-strong-wind dimmed"; small.appendChild(windIcon); var windSpeed = document.createElement("span"); windSpeed.innerHTML = " " + this.windSpeed; small.appendChild(windSpeed); if (this.config.showWindDirection) { var windDirection = document.createElement("sup"); if (this.config.showWindDirectionAsArrow) { if(this.windDeg !== null) { windDirection.innerHTML = " <i class=\"fa fa-long-arrow-down\" style=\"transform:rotate("+this.windDeg+"deg);\"></i> "; } } else { windDirection.innerHTML = " " + this.translate(this.windDirection); } small.appendChild(windDirection); } var spacer = document.createElement("span"); spacer.innerHTML = " "; small.appendChild(spacer); if (this.config.showHumidity) { var humidity = document.createElement("span"); humidity.innerHTML = this.humidity; var spacer = document.createElement("sup"); spacer.innerHTML = " "; var humidityIcon = document.createElement("sup"); humidityIcon.className = "wi wi-humidity humidityIcon"; humidityIcon.innerHTML = " "; small.appendChild(humidity); small.appendChild(spacer); small.appendChild(humidityIcon); } var sunriseSunsetIcon = document.createElement("span"); sunriseSunsetIcon.className = "wi dimmed " + this.sunriseSunsetIcon; small.appendChild(sunriseSunsetIcon); var sunriseSunsetTime = document.createElement("span"); sunriseSunsetTime.innerHTML = " " + this.sunriseSunsetTime; small.appendChild(sunriseSunsetTime); wrapper.appendChild(small); }, // Override dom generator. getDom: function() { var wrapper = document.createElement("div"); if (this.config.appid === "") { wrapper.innerHTML = "Please set the correct openweather <i>appid</i> in the config for module: " + this.name + "."; wrapper.className = "dimmed light small"; return wrapper; } if (!this.loaded) { wrapper.innerHTML = this.translate("LOADING"); wrapper.className = "dimmed light small"; return wrapper; } if (this.config.onlyTemp === false) { this.addExtraInfoWeather(wrapper); } var large = document.createElement("div"); large.className = "large light"; var weatherIcon = document.createElement("div"); weatherIcon.className = "icon " + this.weatherTypeAnimated; weatherIcon.innerHTML = this.weatherTypeAnimatedInnerHTML; large.appendChild(weatherIcon); //var weatherIconInside = document.createElement("div"); var degreeLabel = ""; if (this.config.units === "metric" || this.config.units === "imperial") { degreeLabel += "°"; } if(this.config.degreeLabel) { switch(this.config.units) { case "metric": degreeLabel += "C"; break; case "imperial": degreeLabel += "F"; break; case "default": degreeLabel += "K"; break; } } if (this.config.decimalSymbol === "") { this.config.decimalSymbol = "."; } var temperature = document.createElement("span"); temperature.className = "bright"; temperature.innerHTML = " " + this.temperature.replace(".", this.config.decimalSymbol) + degreeLabel; large.appendChild(temperature); if (this.config.showIndoorTemperature && this.indoorTemperature) { var indoorIcon = document.createElement("span"); indoorIcon.className = "fa fa-home"; large.appendChild(indoorIcon); var indoorTemperatureElem = document.createElement("span"); indoorTemperatureElem.className = "bright"; indoorTemperatureElem.innerHTML = " " + this.indoorTemperature.replace(".", this.config.decimalSymbol) + degreeLabel; large.appendChild(indoorTemperatureElem); } if (this.config.showIndoorHumidity && this.indoorHumidity) { var indoorHumidityIcon = document.createElement("span"); indoorHumidityIcon.className = "fa fa-tint"; large.appendChild(indoorHumidityIcon); var indoorHumidityElem = document.createElement("span"); indoorHumidityElem.className = "bright"; indoorHumidityElem.innerHTML = " " + this.indoorHumidity + "%"; large.appendChild(indoorHumidityElem); } wrapper.appendChild(large); if (this.config.showFeelsLike && this.config.onlyTemp === false){ var small = document.createElement("div"); small.className = "normal medium"; var feelsLike = document.createElement("span"); feelsLike.className = "dimmed"; feelsLike.innerHTML = this.translate("FEELS") + " " + this.feelsLike + degreeLabel; small.appendChild(feelsLike); wrapper.appendChild(small); } return wrapper; }, // Override getHeader method. getHeader: function() { if (this.config.appendLocationNameToHeader && this.data.header !== undefined) { return this.data.header + " " + this.fetchedLocationName; } if (this.config.useLocationAsHeader && this.config.location !== false) { return this.config.location; } return this.data.header; }, // Override notification handler. notificationReceived: function(notification, payload, sender) { if (notification === "DOM_OBJECTS_CREATED") { if (this.config.appendLocationNameToHeader) { this.hide(0, {lockString: this.identifier}); } } if (notification === "CALENDAR_EVENTS") { var senderClasses = sender.data.classes.toLowerCase().split(" "); if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) { this.firstEvent = false; for (var e in payload) { var event = payload[e]; if (event.location || event.geo) { this.firstEvent = event; //Log.log("First upcoming event with location: ", event); break; } } } } if (notification === "INDOOR_TEMPERATURE") { this.indoorTemperature = this.roundValue(payload); this.updateDom(this.config.animationSpeed); } if (notification === "INDOOR_HUMIDITY") { this.indoorHumidity = this.roundValue(payload); this.updateDom(this.config.animationSpeed); } }, /* updateWeather(compliments) * Requests new data from openweather.org. * Calls processWeather on succesfull response. */ updateWeather: function() { if (this.config.appid === "") { Log.error("CurrentWeather: APPID not set!"); return; } var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + this.getParams(); var self = this; var retry = true; var weatherRequest = new XMLHttpRequest(); weatherRequest.open("GET", url, true); weatherRequest.onreadystatechange = function() { if (this.readyState === 4) { if (this.status === 200) { self.processWeather(JSON.parse(this.response)); } else if (this.status === 401) { self.updateDom(self.config.animationSpeed); Log.error(self.name + ": Incorrect APPID."); retry = true; } else { Log.error(self.name + ": Could not load weather."); } if (retry) { self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay); } } }; weatherRequest.send(); }, /* getParams(compliments) * Generates an url with api parameters based on the config. * * return String - URL params. */ getParams: function() { var params = "?"; if(this.config.locationID) { params += "id=" + this.config.locationID; } else if(this.config.location) { params += "q=" + this.config.location; } else if (this.firstEvent && this.firstEvent.geo) { params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon; } else if (this.firstEvent && this.firstEvent.location) { params += "q=" + this.firstEvent.location; } else { this.hide(this.config.animationSpeed, {lockString:this.identifier}); return; } params += "&units=" + this.config.units; params += "&lang=" + this.config.lang; params += "&APPID=" + this.config.appid; return params; }, /* processWeather(data) * Uses the received data to set the various values. * * argument data object - Weather information received form openweather.org. */ processWeather: function(data) { if (!data || !data.main || typeof data.main.temp === "undefined") { // Did not receive usable new data. // Maybe this needs a better check? return; } this.humidity = parseFloat(data.main.humidity); this.temperature = this.roundValue(data.main.temp); this.fetchedLocationName = data.name; this.feelsLike = 0; if (this.config.useBeaufort){ this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed)); } else if (this.config.useKMPHwind) { this.windSpeed = parseFloat((data.wind.speed * 60 * 60) / 1000).toFixed(0); } else { this.windSpeed = parseFloat(data.wind.speed).toFixed(0); } // ONLY WORKS IF TEMP IN C // var windInMph = parseFloat(data.wind.speed * 2.23694); var tempInF = 0; switch (this.config.units){ case "metric": tempInF = 1.8 * this.temperature + 32; break; case "imperial": tempInF = this.temperature; break; case "default": var tc = this.temperature - 273.15; tempInF = 1.8 * tc + 32; break; } if (windInMph > 3 && tempInF < 50){ // windchill var windChillInF = Math.round(35.74+0.6215*tempInF-35.75*Math.pow(windInMph,0.16)+0.4275*tempInF*Math.pow(windInMph,0.16)); var windChillInC = (windChillInF - 32) * (5/9); // this.feelsLike = windChillInC.toFixed(0); switch (this.config.units){ case "metric": this.feelsLike = windChillInC.toFixed(0); break; case "imperial": this.feelsLike = windChillInF.toFixed(0); break; case "default": var tc = windChillInC + 273.15; this.feelsLike = tc.toFixed(0); break; } } else if (tempInF > 80 && this.humidity > 40){ // heat index var Hindex = -42.379 + 2.04901523*tempInF + 10.14333127*this.humidity - 0.22475541*tempInF*this.humidity - 6.83783*Math.pow(10,-3)*tempInF*tempInF - 5.481717*Math.pow(10,-2)*this.humidity*this.humidity + 1.22874*Math.pow(10,-3)*tempInF*tempInF*this.humidity + 8.5282*Math.pow(10,-4)*tempInF*this.humidity*this.humidity - 1.99*Math.pow(10,-6)*tempInF*tempInF*this.humidity*this.humidity; switch (this.config.units){ case "metric": this.feelsLike = parseFloat((Hindex - 32) / 1.8).toFixed(0); break; case "imperial": this.feelsLike = Hindex.toFixed(0); break; case "default": var tc = parseFloat((Hindex - 32) / 1.8) + 273.15; this.feelsLike = tc.toFixed(0); break; } } else { this.feelsLike = parseFloat(this.temperature).toFixed(0); } this.windDirection = this.deg2Cardinal(data.wind.deg); this.windDeg = data.wind.deg; this.weatherType = this.config.iconTable[data.weather[0].icon]; this.weatherTypeAnimated = this.config.AnimatedIconTable[data.weather[0].icon]; this.weatherTypeAnimatedInnerHTML = this.config.AnimatedIconTableInnerHTML[data.weather[0].icon]; var now = new Date(); var sunrise = new Date(data.sys.sunrise * 1000); var sunset = new Date(data.sys.sunset * 1000); // The moment().format('h') method has a bug on the Raspberry Pi. // So we need to generate the timestring manually. // See issue: https://github.com/MichMich/MagicMirror/issues/181 var sunriseSunsetDateObject = (sunrise < now && sunset > now) ? sunset : sunrise; var timeString = moment(sunriseSunsetDateObject).format("HH:mm"); if (this.config.timeFormat !== 24) { //var hours = sunriseSunsetDateObject.getHours() % 12 || 12; if (this.config.showPeriod) { if (this.config.showPeriodUpper) { //timeString = hours + moment(sunriseSunsetDateObject).format(':mm A'); timeString = moment(sunriseSunsetDateObject).format("h:mm A"); } else { //timeString = hours + moment(sunriseSunsetDateObject).format(':mm a'); timeString = moment(sunriseSunsetDateObject).format("h:mm a"); } } else { //timeString = hours + moment(sunriseSunsetDateObject).format(':mm'); timeString = moment(sunriseSunsetDateObject).format("h:mm"); } } this.sunriseSunsetTime = timeString; this.sunriseSunsetIcon = (sunrise < now && sunset > now) ? "wi-sunset" : "wi-sunrise"; this.show(this.config.animationSpeed, {lockString:this.identifier}); this.loaded = true; this.updateDom(this.config.animationSpeed); this.sendNotification("CURRENTWEATHER_DATA", {data: data}); }, /* scheduleUpdate() * Schedule next update. * * argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used. */ scheduleUpdate: function(delay) { var nextLoad = this.config.updateInterval; if (typeof delay !== "undefined" && delay >= 0) { nextLoad = delay; } var self = this; setTimeout(function() { self.updateWeather(); }, nextLoad); }, /* ms2Beaufort(ms) * Converts m2 to beaufort (windspeed). * * see: * http://www.spc.noaa.gov/faq/tornado/beaufort.html * https://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale * * argument ms number - Windspeed in m/s. * * return number - Windspeed in beaufort. */ ms2Beaufort: function(ms) { var kmh = ms * 60 * 60 / 1000; var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000]; for (var beaufort in speeds) { var speed = speeds[beaufort]; if (speed > kmh) { return beaufort; } } return 12; }, deg2Cardinal: function(deg) { if (deg>11.25 && deg<=33.75){ return "NNE"; } else if (deg > 33.75 && deg <= 56.25) { return "NE"; } else if (deg > 56.25 && deg <= 78.75) { return "ENE"; } else if (deg > 78.75 && deg <= 101.25) { return "E"; } else if (deg > 101.25 && deg <= 123.75) { return "ESE"; } else if (deg > 123.75 && deg <= 146.25) { return "SE"; } else if (deg > 146.25 && deg <= 168.75) { return "SSE"; } else if (deg > 168.75 && deg <= 191.25) { return "S"; } else if (deg > 191.25 && deg <= 213.75) { return "SSW"; } else if (deg > 213.75 && deg <= 236.25) { return "SW"; } else if (deg > 236.25 && deg <= 258.75) { return "WSW"; } else if (deg > 258.75 && deg <= 281.25) { return "W"; } else if (deg > 281.25 && deg <= 303.75) { return "WNW"; } else if (deg > 303.75 && deg <= 326.25) { return "NW"; } else if (deg > 326.25 && deg <= 348.75) { return "NNW"; } else { return "N"; } }, /* function(temperature) * Rounds a temperature to 1 decimal or integer (depending on config.roundTemp). * * argument temperature number - Temperature. * * return string - Rounded Temperature. */ roundValue: function(temperature) { var decimals = this.config.roundTemp ? 0 : 1; return parseFloat(temperature).toFixed(decimals); } });
-
@santiago5 oooooh I have the same question, is there a way to implement the .mov icons? If yes, how? THX
-
Here is a perfect collection of https://templatefor.net/free-weather-icons-sets/
-
Nice set up here, tried out the code and worked the first time. My only issue is I am only getting 3 days showing in the forecast. I tried adding “maxNumberOfDays: 5,” but nothing happened… Any idea what it could be?
{ module: "currentweather", position: "top_right", config: { onlyTemp:true, maxNumberOfDays: 5, location: "Swissvale", locationID: "5215064", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city appid: "appid" } }, { module: "weatherforecast", position: "top_right", header: "Weather Forecast", config: { maxNumberOfDays: 5, location: "Swissvale", locationID: "5215064", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city appid: "appid" } },
Still new here, so let me know if you need me to provide any thing else.
Skol
-
@Genosphere try the fix that @oemel09 mentioned here and see if that fixes the number of days issue
-
@Wenike Perfect fix! Well it does what it needs to anyway. haha
Skol!