MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    1. Home
    2. Sp4M
    3. Best
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.
    S
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 0
    • Posts 7
    • Groups 0

    Posts

    Recent Best Controversial
    • RE: Problem with Weather forecast

      Hi,

      I made the module compatible for the “daily” api of openweather. It basically aggregate data of all “3h parts” of each day.
      The min/max are global min/max of each parts
      The icon shows the worst-case (you can reorder what is worse for you in config.iconTableOrdered)

      Hope that will help devs

      Here is the corresponding code of weatherforecast.js

      /* global Module */
      
      /* Magic Mirror
       * Module: WeatherForecast
       *
       * By Michael Teeuw http://michaelteeuw.nl
       * MIT Licensed.
       */
      
      Module.register("weatherforecast",{
      
      	// Default module config.
      	defaults: {
      		location: false,
      		locationID: false,
      		appid: "",
      		units: config.units,
      		maxNumberOfDays: 7,
      		showRainAmount: false,
      		updateInterval: 10 * 60 * 1000, // every 10 minutes
      		animationSpeed: 1000,
      		timeFormat: config.timeFormat,
      		lang: config.language,
      		fade: true,
      		fadePoint: 0.25, // Start on 1/4th of the list.
      		colored: false,
      
      		initialLoadDelay: 2500, // 2.5 seconds delay. This delay is used to keep the OpenWeather API happy.
      		retryDelay: 2500,
      
      		apiVersion: "2.5",
      		apiBase: "http://api.openweathermap.org/data/",
      		forecastEndpoint: "forecast", //forecast/daily
      
      		appendLocationNameToHeader: true,
      		calendarClass: "calendar",
      
      		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"
      		},
      
      		iconTableOrdered: [
      			"11d",
      			"09d",
      			"13d",
      			"10d",
      			"50d",
      			"04d",
      			"03d",
      			"02d",
      			"01d",
      			"11n",
      			"09n",
      			"13n",
      			"10n",
      			"50n",
      			"02n",
      			"03n",
      			"04n",
      			"01n"
      		],
      	},
      
      	// create a variable for the first upcoming calendaar 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", "weatherforecast.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 yiur 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.forecast = [];
      		this.loaded = false;
      		this.scheduleUpdate(this.config.initialLoadDelay);
      
      		this.updateTimer = null;
      
      	},
      
      	// 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;
      		}
      
      		var table = document.createElement("table");
      		table.className = "small";
      
      		for (var f in this.forecast) {
      			var forecast = this.forecast[f];
      
      			var row = document.createElement("tr");
      			if (this.config.colored) {
      				row.className = "colored";
      			}
      			table.appendChild(row);
      
      			var dayCell = document.createElement("td");
      			dayCell.className = "day";
      			dayCell.innerHTML = forecast.day;
      			row.appendChild(dayCell);
      
      			var iconCell = document.createElement("td");
      			iconCell.className = "bright weather-icon";
      			row.appendChild(iconCell);
      
      			var icon = document.createElement("span");
      			icon.className = "wi weathericon " + forecast.icon;
      			iconCell.appendChild(icon);
      
      			var maxTempCell = document.createElement("td");
      			maxTempCell.innerHTML = forecast.maxTemp;
      			maxTempCell.className = "align-right bright max-temp";
      			row.appendChild(maxTempCell);
      
      			var minTempCell = document.createElement("td");
      			minTempCell.innerHTML = forecast.minTemp;
      			minTempCell.className = "align-right min-temp";
      			row.appendChild(minTempCell);
      
      			if (this.config.showRainAmount) {
      				var rainCell = document.createElement("td");
      				if (isNaN(forecast.rain)) {
      					rainCell.innerHTML = "";
      				} else {
      					if(config.units !== "imperial") {
      						rainCell.innerHTML = forecast.rain + " mm";
      					} else {
      						rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2) + " in";
      					}
      				}
      				rainCell.className = "align-right bright rain";
      				row.appendChild(rainCell);
      			}
      
      			if (this.config.fade && this.config.fadePoint < 1) {
      				if (this.config.fadePoint < 0) {
      					this.config.fadePoint = 0;
      				}
      				var startingPoint = this.forecast.length * this.config.fadePoint;
      				var steps = this.forecast.length - startingPoint;
      				if (f >= startingPoint) {
      					var currentStep = f - startingPoint;
      					row.style.opacity = 1 - (1 / steps * currentStep);
      				}
      			}
      		}
      
      		return table;
      	},
      
      	// Override getHeader method.
      	getHeader: function() {
      		if (this.config.appendLocationNameToHeader) {
      			return this.data.header + " " + this.fetchedLocationName;
      		}
      
      		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;
      					}
      				}
      			}
      		}
      	},
      
      	/* updateWeather(compliments)
      	 * Requests new data from openweather.org.
      	 * Calls processWeather on succesfull response.
      	 */
      	updateWeather: function() {
      		if (this.config.appid === "") {
      			Log.error("WeatherForecast: APPID not set!");
      			return;
      		}
      
      		var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.forecastEndpoint + 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;
      		/*
      		 * Submit a specific number of days to forecast, between 1 to 16 days.
      		 * The OpenWeatherMap API properly handles values outside of the 1 - 16 range and returns 7 days by default.
      		 * This is simply being pedantic and doing it ourselves.
      		 */
      		params += "&cnt=" + (((this.config.maxNumberOfDays < 1) || (this.config.maxNumberOfDays > 121)) ? 40 : this.config.maxNumberOfDays);
      		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) {
      		this.fetchedLocationName = data.city.name + ", " + data.city.country;
      
      		var days_forecast = [];
      
      		for (var i = 0, count = data.list.length; i < count; i++) {
      			let forecast = data.list[i];
      			let day = forecast.dt_txt.split(" ")[0];
      
      			if (!(day in days_forecast)) 
      				days_forecast[day] = {"dt":[], "icon":[], "temp":[]};
      
      			days_forecast[day].dt.push(forecast.dt);
      			days_forecast[day].icon.push(forecast.weather[0].icon);
      			days_forecast[day].temp.push(forecast.main.temp_min);
      			days_forecast[day].temp.push(forecast.main.temp_max);
      		}
      
      		for (let i in days_forecast) {
      			let min = days_forecast[i].temp.reduce((previous, current) => current = previous < current ? previous : current);
      			let max = days_forecast[i].temp.reduce((previous, current) => current = previous > current ? previous : current);
      			let icon = days_forecast[i].icon.reduce((previous, current) => current = this.config.iconTableOrdered.indexOf(previous) < this.config.iconTableOrdered.indexOf(current) ? previous : current);
      
      			this.forecast.push({
      				day: moment(days_forecast[i].dt[0], "X").format("ddd"),
      				icon: this.config.iconTable[icon],
      				maxTemp: this.roundValue(min),
      				minTemp: this.roundValue(max)
      //				rain: this.roundValue(forecast.rain)
      			});
      		}
      
      		//Log.log(this.forecast);
      		this.show(this.config.animationSpeed, {lockString:this.identifier});
      		this.loaded = true;
      		this.updateDom(this.config.animationSpeed);
      	},
      
      	/* 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;
      		clearTimeout(this.updateTimer);
      		this.updateTimer = 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;
      	},
      
      	/* function(temperature)
      	 * Rounds a temperature to 1 decimal or integer (depending on config.roundTemp).
      	 *
      	 * argument temperature number - Temperature.
      	 *
      	 * return number - Rounded Temperature.
      	 */
      	roundValue: function(temperature) {
      		var decimals = this.config.roundTemp ? 0 : 1;
      		return parseFloat(temperature).toFixed(decimals);
      	}
      });
      
      
      posted in Troubleshooting
      S
      Sp4M
    • RE: Problem with Weather forecast

      @frank61BS
      This corrected version should works with the real maxNumberOfDays (=5 for example)

      /* global Module */
      
      /* Magic Mirror
       * Module: WeatherForecast
       *
       * By Michael Teeuw http://michaelteeuw.nl
       * MIT Licensed.
       */
      
      Module.register("weatherforecast",{
      
      	// Default module config.
      	defaults: {
      		location: false,
      		locationID: false,
      		appid: "",
      		units: config.units,
      		maxNumberOfDays: 5,
      		showRainAmount: false,
      		updateInterval: 10 * 60 * 1000, // every 10 minutes
      		animationSpeed: 1000,
      		timeFormat: config.timeFormat,
      		lang: config.language,
      		fade: true,
      		fadePoint: 0.25, // Start on 1/4th of the list.
      		colored: false,
      
      		initialLoadDelay: 2500, // 2.5 seconds delay. This delay is used to keep the OpenWeather API happy.
      		retryDelay: 2500,
      
      		apiVersion: "2.5",
      		apiBase: "http://api.openweathermap.org/data/",
      		forecastEndpoint: "forecast", //forecast/daily
      
      		appendLocationNameToHeader: true,
      		calendarClass: "calendar",
      
      		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"
      		},
      
      		iconTableOrdered: [
      			"11d",
      			"09d",
      			"13d",
      			"10d",
      			"50d",
      			"04d",
      			"03d",
      			"02d",
      			"01d",
      			"11n",
      			"09n",
      			"13n",
      			"10n",
      			"50n",
      			"02n",
      			"03n",
      			"04n",
      			"01n"
      		],
      	},
      
      	// create a variable for the first upcoming calendaar 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", "weatherforecast.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 yiur 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.forecast = [];
      		this.loaded = false;
      		this.scheduleUpdate(this.config.initialLoadDelay);
      
      		this.updateTimer = null;
      
      	},
      
      	// 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;
      		}
      
      		var table = document.createElement("table");
      		table.className = "small";
      
      		for (var f in this.forecast) {
      			var forecast = this.forecast[f];
      
      			var row = document.createElement("tr");
      			if (this.config.colored) {
      				row.className = "colored";
      			}
      			table.appendChild(row);
      
      			var dayCell = document.createElement("td");
      			dayCell.className = "day";
      			dayCell.innerHTML = forecast.day;
      			row.appendChild(dayCell);
      
      			var iconCell = document.createElement("td");
      			iconCell.className = "bright weather-icon";
      			row.appendChild(iconCell);
      
      			var icon = document.createElement("span");
      			icon.className = "wi weathericon " + forecast.icon;
      			iconCell.appendChild(icon);
      
      			var maxTempCell = document.createElement("td");
      			maxTempCell.innerHTML = forecast.maxTemp;
      			maxTempCell.className = "align-right bright max-temp";
      			row.appendChild(maxTempCell);
      
      			var minTempCell = document.createElement("td");
      			minTempCell.innerHTML = forecast.minTemp;
      			minTempCell.className = "align-right min-temp";
      			row.appendChild(minTempCell);
      
      			if (this.config.showRainAmount) {
      				var rainCell = document.createElement("td");
      				if (isNaN(forecast.rain)) {
      					rainCell.innerHTML = "";
      				} else {
      					if(config.units !== "imperial") {
      						rainCell.innerHTML = forecast.rain + " mm";
      					} else {
      						rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2) + " in";
      					}
      				}
      				rainCell.className = "align-right bright rain";
      				row.appendChild(rainCell);
      			}
      
      			if (this.config.fade && this.config.fadePoint < 1) {
      				if (this.config.fadePoint < 0) {
      					this.config.fadePoint = 0;
      				}
      				var startingPoint = this.forecast.length * this.config.fadePoint;
      				var steps = this.forecast.length - startingPoint;
      				if (f >= startingPoint) {
      					var currentStep = f - startingPoint;
      					row.style.opacity = 1 - (1 / steps * currentStep);
      				}
      			}
      		}
      
      		return table;
      	},
      
      	// Override getHeader method.
      	getHeader: function() {
      		if (this.config.appendLocationNameToHeader) {
      			return this.data.header + " " + this.fetchedLocationName;
      		}
      
      		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;
      					}
      				}
      			}
      		}
      	},
      
      	/* updateWeather(compliments)
      	 * Requests new data from openweather.org.
      	 * Calls processWeather on succesfull response.
      	 */
      	updateWeather: function() {
      		if (this.config.appid === "") {
      			Log.error("WeatherForecast: APPID not set!");
      			return;
      		}
      
      		var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.forecastEndpoint + 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;
      		/*
      		 * Submit a specific number of days to forecast, between 1 to 5 days.
      		 * The OpenWeatherMap API properly handles values outside of the 1 - 5 range and returns 5 days by default.
      		 * This is simply being pedantic and doing it ourselves.
      		 */
      		params += "&cnt=" + ((this.config.maxNumberOfDays < 1 || this.config.maxNumberOfDays > 5) ? 5 : this.config.maxNumberOfDays)*8;
      		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) {
      		var days_forecast = [];
      
      		this.fetchedLocationName = data.city.name + ", " + data.city.country;
      		this.forecast = [];
      
      		for (var i = 0, count = data.list.length; i < count; i++) {
      			let forecast = data.list[i];
      			let day = forecast.dt_txt.split(" ")[0];
      
      			if (!(day in days_forecast)) 
      				days_forecast[day] = {"dt":[], "icon":[], "temp":[]};
      
      			days_forecast[day].dt.push(forecast.dt);
      			days_forecast[day].icon.push(forecast.weather[0].icon);
      			days_forecast[day].temp.push(forecast.main.temp_min);
      			days_forecast[day].temp.push(forecast.main.temp_max);
      		}
      
      		for (let i in days_forecast) {
      			let min = days_forecast[i].temp.reduce((previous, current) => current = previous < current ? previous : current);
      			let max = days_forecast[i].temp.reduce((previous, current) => current = previous > current ? previous : current);
      			let icon = days_forecast[i].icon.reduce((previous, current) => current = this.config.iconTableOrdered.indexOf(previous) < this.config.iconTableOrdered.indexOf(current) ? previous : current);
      			
      			this.forecast.push({
      				day: moment(days_forecast[i].dt[0], "X").format("ddd"),
      				icon: this.config.iconTable[icon],
      				maxTemp: this.roundValue(min),
      				minTemp: this.roundValue(max)
      //				rain: this.roundValue(forecast.rain)
      			});
      		}
      
      		//Log.log(this.forecast);
      		this.show(this.config.animationSpeed, {lockString:this.identifier});
      		this.loaded = true;
      		this.updateDom(this.config.animationSpeed);
      	},
      
      	/* 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;
      		clearTimeout(this.updateTimer);
      		this.updateTimer = 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;
      	},
      
      	/* function(temperature)
      	 * Rounds a temperature to 1 decimal or integer (depending on config.roundTemp).
      	 *
      	 * argument temperature number - Temperature.
      	 *
      	 * return number - Rounded Temperature.
      	 */
      	roundValue: function(temperature) {
      		var decimals = this.config.roundTemp ? 0 : 1;
      		return parseFloat(temperature).toFixed(decimals);
      	}
      });
      
      
      posted in Troubleshooting
      S
      Sp4M
    • 1 / 1