123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- /* eslint-disable */
-
- /* Magic Mirror
- * Module: CurrentWeather
- *
- * By Michael Teeuw https://michaelteeuw.nl
- * MIT Licensed.
- *
- * This module is deprecated. Any additional feature will no longer be merged.
- */
- 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,
- useKMPHwind: false,
- lang: config.language,
- decimalSymbol: ".",
- showHumidity: false,
- showSun: true,
- 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,
- useLocationAsHeader: false,
-
- calendarClass: "calendar",
- tableClass: "large",
-
- onlyTemp: false,
- hideTemp: false,
- roundTemp: false,
-
- iconTable: {
- "01d": "day-sunny",
- "02d": "day-cloudy",
- "03d": "cloudy",
- "04d": "cloudy-windy",
- "09d": "showers",
- "10d": "rain",
- "11d": "thunderstorm",
- "13d": "snow",
- "50d": "fog",
- "01n": "night-clear",
- "02n": "night-cloudy",
- "03n": "night-cloudy",
- "04n": "night-cloudy",
- "09n": "night-showers",
- "10n": "night-rain",
- "11n": "night-thunderstorm",
- "13n": "night-snow",
- "50n": "night-alt-cloudy-windy"
- }
- },
-
- // 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.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 supspacer = document.createElement("sup");
- supspacer.innerHTML = " ";
-
- var humidityIcon = document.createElement("sup");
- humidityIcon.className = "wi wi-humidity humidityIcon";
- humidityIcon.innerHTML = " ";
-
- small.appendChild(humidity);
- small.appendChild(supspacer);
- small.appendChild(humidityIcon);
- }
-
- if (this.config.showSun) {
- 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");
- wrapper.className = this.config.tableClass;
-
- 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 = "light";
-
- 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 = ".";
- }
-
- if (this.config.hideTemp === false) {
- var weatherIcon = document.createElement("span");
- weatherIcon.className = "wi weathericon wi-" + this.weatherType;
- large.appendChild(weatherIcon);
-
- 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", {
- DEGREE: this.feelsLike + degreeLabel
- });
- small.appendChild(feelsLike);
-
- wrapper.appendChild(small);
- }
-
- return wrapper;
- },
-
- // Override getHeader method.
- getHeader: function () {
- if (this.config.useLocationAsHeader && this.config.location !== false) {
- return this.config.location;
- }
-
- if (this.config.appendLocationNameToHeader) {
- if (this.data.header) return this.data.header + " " + this.fetchedLocationName;
- else return this.fetchedLocationName;
- }
-
- return this.data.header ? 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":
- tempInF = 1.8 * (this.temperature - 273.15) + 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":
- this.feelsLike = (windChillInC + 273.15).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];
-
- 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 });
- this.sendNotification("CURRENTWEATHER_TYPE", { type: this.config.iconTable[data.weather[0].icon].replace("-", "_") });
- },
-
- /* 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:
- * https://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;
- var roundValue = parseFloat(temperature).toFixed(decimals);
- return roundValue === "-0" ? 0 : roundValue;
- }
- });
|