UNPKG

iobroker.swiss-weather-api

Version:

Connects to SRF Weather API (https://developer.srgssr.ch/apis/srf-weather)

1,526 lines (1,472 loc) 129 kB
"use strict"; //process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; Wieder entfernen - Hoffe sie haben jetzt das Zertifikatsmanagement im Griff... /* * Created with @iobroker/create-adapter v1.18.0 */ const utils = require("@iobroker/adapter-core"); var dns = require('dns'); const cron = require('node-cron'); const { https } = require('follow-redirects'); const adapterName = "swiss-weather-api"; const undf = "undefined" var defaultLanguage = "de"; var timeout; var geolocationId; var access_token; let cronJob; var today; var today1; var today2; var today3; var today4; var today5; var today6; var today7; var today8; var today9; var lastSuccessfulRun; Date.prototype.addDays = function(days) { var date = new Date(this.valueOf()); date.setDate(date.getDate() + days); return date; } /** * HACK!!! * Helper function for https://github.com/baerengraben/ioBroker.swiss-weather-api/issues/78 * For Details see * @param {Date} date obj.date_time * @returns {String} String inluding a number for cleaning up the timestamp problem. */ function cleanUpTimestampProblem(date){ var myHours = date.getHours(); if (myHours > 0 && myHours < 3) { return "1" } else if (myHours > 3 && myHours < 6) { return "2" } else if (myHours > 6 && myHours < 9) { return "3"; } else if (myHours > 9 && myHours < 12) { return "4"; } else if (myHours > 12 && myHours < 15) { return "5"; } else if (myHours > 15 && myHours < 18) { return "6"; } else if (myHours > 18 && myHours < 21) { return "7"; } else if (myHours > 21 && myHours < 24) { return "8"; } else { self.log.error("Error in cleanUpTimestampProblem(). This should not happend. If error persists, create an issue on https://github.com/baerengraben/ioBroker.swiss-weather-api."); return "0"; }; } /** * Checks if JSON is valid * @param str JSON String * @returns {boolean} true == valid; false == invalid */ function isValidJSONString(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } /** * returns formattet Time as hhmm * @param actualDate Date Object * @returns {string} hour + min */ function getTimeFormattet(actualDate) { var hour = (actualDate.getHours()<10?'0':'') + actualDate.getHours(); var min = (actualDate.getMinutes()<10?'0':'') + actualDate.getMinutes(); // var sec = (actualDate.getSeconds()<10?'0':'') + actualDate.getSeconds(); // removed due to https://github.com/baerengraben/ioBroker.swiss-weather-api/issues/57 return hour + min; } /** * Get name of day * @param date Date Object * @param defaultLanguage language code * @returns {string} Name of Day */ function getDayName(date,defaultLanguage){ var mainversion = parseInt(process.version.substr(1,2)) var weekday; var arrayOfWeekdays = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"] // dateObj.toLocaleString("default", { weekday: "long" }) is only supported > nodejs 13 if (mainversion >12){ weekday = date.toLocaleString(defaultLanguage , { weekday: "long" }); } else { var weekdayNumber = date.getDay(); weekday = arrayOfWeekdays[weekdayNumber]; } return weekday; } /** * Get longitude/latitude from system if not set or not valid * do not change if we have already a valid value * so we could use different settings compared to system if necessary * @param self Adapter */ function getSystemData(self) { if (typeof self.config.longitude === undf || self.config.longitude == null || self.config.longitude.length === 0 || isNaN(self.config.longitude) || typeof self.config.latitude === undf || self.config.latitude == null || self.config.latitude.length === 0 || isNaN(self.config.latitude)) { self.log.info("longitude/longitude not set, get data from system "); self.getForeignObject("system.config", (err, state) => { if (err || state === undf || state === null) { self.log.error("longitude/latitude not set in adapter-config and reading in system-config failed"); self.setState('info.connection', false, true); } else { self.config.longitude = state.common.longitude; self.config.latitude = state.common.latitude; self.log.info("system longitude: " + self.config.longitude + " latitude: " + self.config.latitude); } }); } else { self.log.info("longitude/longitude will be set by self-Config - longitude: " + self.config.longitude + " latitude: " + self.config.latitude); } } /** * Reads ioBroker default Language and set it to adapter defaultLanguage * @param self Adapter, */ function getSystemLanguage(self) { self.getForeignObject("system.config", (err, state) => { if (err || state === undf || state === null) { self.log.error("Default language not set in system-config. Setting default language as 'de' to use for weekday names."); self.defaultLanguage = "de"; } else { self.defaultLanguage = state.common.language; self.log.debug("use system language for weekday names: " + self.defaultLanguage); } }); } /** * Creates a json Object for usage with Material Design JSON Chart used for Widgets * @param body srf api response containing days json object * @returns {*{}} containing Json for usage with Material Design JSON Chart */ function createJsonForWidgets(body) { let sun = []; let rain = []; let wind = []; let calculatedMinSunHour; let calculatedMaxSunHour; let calculatedMinPrecipitation; let calculatedMaxprecipitation; let calculatedMinWind; let calculatedMaxWind; body["days"].forEach(function (obj, index) { if (typeof obj.SUN_H !== undf || obj.SUN_H != null || typeof obj.RRR_MM !== undf || obj.RRR_MM != null || typeof obj.FF_KMH !== undf || obj.FF_KMH != null) { sun.push(obj.SUN_H); rain.push(obj.RRR_MM); wind.push(obj.FF_KMH); } }) //Template let axisLabelsTempl = ["","","","","","","","",""]; let rainTempl = { "type": "bar", "data": rain, "yAxis_id": 0, "barIsStacked": false, "datalabel_show": true, "line_UseFillColor": true, "yAxis_show": false, "color": "blue", "legendText": "Total Niederschlag", "yAxis_min": 0, "yAxis_max": Math.max(...rain) + 5, "yAxis_maxSteps": 1, "yAxis_position": "left", "yAxis_gridLines_show": true, "yAxis_appendix": " mm", "yAxis_gridLines_border_show": false, "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "displayOrder": 1, "tooltip_AppendText": " mm", "datalabel_append": " mm", "datalabel_align": "bottom", "datalabel_color": "rgb(27, 17, 28)", "datalabel_backgroundColor": "blue", "datalabel_borderRadius": 5 }; let sunTempl = { "type": "line", "data": sun, "yAxis_id": 1, "datalabel_show": true, "line_UseFillColor": false, "yAxis_show": false, "color": "yellow", "legendText": "Sonnenstunden", "yAxis_min": 0, "yAxis_max": Math.max(...sun) + 3, "yAxis_maxSteps": 3, "yAxis_position": "right", "yAxis_gridLines_show": false, "yAxis_appendix": " h", "yAxis_gridLines_border_show": false, "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "displayOrder": 1, "tooltip_AppendText": " h", "datalabel_append": " h", "datalabel_align": "left", "datalabel_color": "rgb(27, 17, 28)", "datalabel_backgroundColor": "yellow", "datalabel_borderRadius": 5 }; let windTempl = { "type": "line", "data": wind, "yAxis_id": 2, "datalabel_show": true, "line_UseFillColor": false, "yAxis_show": false, "color": "aqua", "legendText": "Wind Geschwindigkeit in km/h", "yAxis_min": 0, "yAxis_max": Math.max(...wind) + 10, "yAxis_maxSteps": 10, "yAxis_position": "right", "yAxis_gridLines_show": false, "yAxis_appendix": " mm", "yAxis_gridLines_border_show": false, "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "displayOrder": 1, "tooltip_AppendText": " km/h", "datalabel_append": " km/h", "datalabel_align": "right", "datalabel_color": "rgb(27, 17, 28)", "datalabel_backgroundColor": "aqua", "datalabel_borderRadius": 5 }; //Create JSON var chartJsonWeek = {}; // empty Object var axisLabelsWeek = 'axisLabels'; var graphsWeek = 'graphs'; chartJsonWeek[axisLabelsWeek] = JSON.parse(JSON.stringify(axisLabelsTempl)); chartJsonWeek[graphsWeek] = []; // empty Array, push graphs attributes in here let myRainData = JSON.parse(JSON.stringify(rainTempl)); myRainData.yAxis_min = chartJsonWeek[graphsWeek].push(myRainData); chartJsonWeek[graphsWeek].push(JSON.parse(JSON.stringify(sunTempl))); chartJsonWeek[graphsWeek].push(JSON.parse(JSON.stringify(windTempl))); return chartJsonWeek; } /** * Creates a json Object for usage with Material Design JSON Chart used for Views * @param body srf api response containing hours json object * @returns {*[]} containing Json for usage with Material Design JSON Chart */ function createJsonForViews(body) { let maxTempDay0; let maxTempDay1; let maxTempDay2; let maxTempDay3; let maxTempDay4; let minTempDay0; let minTempDay1; let minTempDay2; let minTempDay3; let minTempDay4; let calculatedMinTempDay0; let calculatedMinTempDay1; let calculatedMinTempDay2; let calculatedMinTempDay3; let calculatedMinTempDay4; let calculatedMaxTempDay0; let calculatedMaxTempDay1; let calculatedMaxTempDay2; let calculatedMaxTempDay3; let calculatedMaxTempDay4; let deltaTemp = 5; // this value is added or subtracted to calculate the minimum and maximum temperature values on the y-axis. // calculate avgTemp for each day body["days"].forEach(function (obj, index) { if (index == 0) { if (typeof obj.TX_C !== undf || obj.TX_C != null || typeof obj.TN_C !== undf || obj.TN_C != null) { maxTempDay0 = obj.TX_C; minTempDay0 = obj.TN_C; } } else if (index == 1) { if (typeof obj.TX_C !== undf || obj.TX_C != null || typeof obj.TN_C !== undf || obj.TN_C != null) { maxTempDay1 = obj.TX_C; minTempDay1 = obj.TN_C; } } else if (index == 2) { if (typeof obj.TX_C !== undf || obj.TX_C != null || typeof obj.TN_C !== undf || obj.TN_C != null) { maxTempDay2 = obj.TX_C; minTempDay2 = obj.TN_C; } } else if (index == 3) { if (typeof obj.TX_C !== undf || obj.TX_C != null || typeof obj.TN_C !== undf || obj.TN_C != null) { maxTempDay3 = obj.TX_C; minTempDay3 = obj.TN_C; } } else if (index == 4) { if (typeof obj.TX_C !== undf || obj.TX_C != null || typeof obj.TN_C !== undf || obj.TN_C != null) { maxTempDay4 = obj.TX_C; minTempDay4 = obj.TN_C; } } // When min/max could not be calculated, set default value 15 if (typeof maxTempDay0 === undf || maxTempDay0 == null){ maxTempDay0 = 30; } if (typeof maxTempDay1 === undf || maxTempDay1 == null){ maxTempDay1 = 30; } if (typeof maxTempDay2 === undf || maxTempDay2 == null){ maxTempDay2 = 30; } if (typeof maxTempDay3 === undf || maxTempDay3 == null){ maxTempDay3 = 30; } if (typeof maxTempDay4 === undf || maxTempDay4 == null){ maxTempDay4 = 30; } if (typeof minTempDay0 === undf || minTempDay0 == null){ minTempDay0 = 0; } if (typeof minTempDay1 === undf || minTempDay1 == null){ minTempDay1 = 0; } if (typeof minTempDay2 === undf || minTempDay2 == null){ minTempDay2 = 0; } if (typeof minTempDay3 === undf || minTempDay3 == null){ maxTempDay3 = 0; } if (typeof minTempDay4 === undf || minTempDay4 == null){ minTempDay4 = 0; } }) calculatedMinTempDay0 = minTempDay0 - deltaTemp; calculatedMinTempDay1 = minTempDay1 - deltaTemp; calculatedMinTempDay2 = minTempDay2 - deltaTemp; calculatedMinTempDay3 = minTempDay3 - deltaTemp; calculatedMinTempDay4 = minTempDay4 - deltaTemp; calculatedMaxTempDay0 = maxTempDay0 + deltaTemp; calculatedMaxTempDay1 = maxTempDay1 + deltaTemp; calculatedMaxTempDay2 = maxTempDay2 + deltaTemp; calculatedMaxTempDay3 = maxTempDay3 + deltaTemp; calculatedMaxTempDay4 = maxTempDay4 + deltaTemp; //Templates let myHoursFull = [ "0h", "1h", "2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "10h", "11h", "12h", "13h", "14h", "15h", "16h", "17h", "18h", "19h", "20h", "21h", "22h", "23h" ]; let myHoursReduced = [ "0h", "1h", "2h" ]; let myGraphsTemplateTemperatur = { "data": [ 17, 19, 18, 19, 19, 20, 20, 21, 22, 24, 24, 24, 23, 22, 23, 23, 24, 23, 23, 22, 22, 21, 20, 20 ], "type": "line", "color": "gray", "legendText": "Temperatur", "line_pointSizeHover": 5, "line_pointSize": 0, "line_Tension": 0.3, "yAxis_show": false, "yAxis_gridLines_show": false, "yAxis_gridLines_ticks_length": 5, "yAxis_min": 0, "yAxis_max": 30, "yAxis_step": 5, "yAxis_position": "left", "yAxis_appendix": " °C", "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "displayOrder": 0, "tooltip_AppendText": " °C", "datalabel_backgroundColor": [ "#2b9a44", "#2b9a44", "#3aa35b", "#2b9a44", "#2b9a44", "#1d922e", "#1d922e", "#0e8917", "#008000", "#668f00", "#668f00", "#668f00", "#338700", "#008000", "#338700", "#338700", "#668f00", "#338700", "#338700", "#008000", "#008000", "#0e8917", "#1d922e", "#1d922e" ], "datalabel_color": "white", "datalabel_offset": -10, "datalabel_fontFamily": "RobotoCondensed-Light", "datalabel_fontSize": 12, "datalabel_borderRadius": 6, "datalabel_show": "auto", "line_PointColor": [ "#2b9a44", "#2b9a44", "#3aa35b", "#2b9a44", "#2b9a44", "#1d922e", "#1d922e", "#0e8917", "#008000", "#668f00", "#668f00", "#668f00", "#338700", "#008000", "#338700", "#338700", "#668f00", "#338700", "#338700", "#008000", "#008000", "#0e8917", "#1d922e", "#1d922e" ], "line_PointColorBorder": [ "#2b9a44", "#2b9a44", "#3aa35b", "#2b9a44", "#2b9a44", "#1d922e", "#1d922e", "#0e8917", "#008000", "#668f00", "#668f00", "#668f00", "#338700", "#008000", "#338700", "#338700", "#668f00", "#338700", "#338700", "#008000", "#008000", "#0e8917", "#1d922e", "#1d922e" ], "line_PointColorHover": [ "#2b9a44", "#2b9a44", "#3aa35b", "#2b9a44", "#2b9a44", "#1d922e", "#1d922e", "#0e8917", "#008000", "#668f00", "#668f00", "#668f00", "#338700", "#008000", "#338700", "#338700", "#668f00", "#338700", "#338700", "#008000", "#008000", "#0e8917", "#1d922e", "#1d922e" ], "line_PointColorBorderHover": [ "#2b9a44", "#2b9a44", "#3aa35b", "#2b9a44", "#2b9a44", "#1d922e", "#1d922e", "#0e8917", "#008000", "#668f00", "#668f00", "#668f00", "#338700", "#008000", "#338700", "#338700", "#668f00", "#338700", "#338700", "#008000", "#008000", "#0e8917", "#1d922e", "#1d922e" ], "use_gradient_color": true, "gradient_color": [ { "value": -20, "color": "#5b2c6f66" }, { "value": 0, "color": "#2874a666" }, { "value": 14, "color": "#73c6b666" }, { "value": 22, "color": "#00800066" }, { "value": 27, "color": "#ffa50066" }, { "value": 35, "color": "#ff000066" } ], "use_line_gradient_fill_color": true, "line_gradient_fill_color": [ { "value": -20, "color": "#5b2c6f66" }, { "value": 0, "color": "#2874a666" }, { "value": 14, "color": "#73c6b666" }, { "value": 22, "color": "#00800066" }, { "value": 27, "color": "#ffa50066" }, { "value": 35, "color": "#ff000066" } ] }; let myGraphsTemplateRegenwahrscheinlichkeit = { "data": [ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 19, 33, 36, 23, 14, 16, 34, 46, 40, 24, 22 ], "type": "line", "color": "#93BDFF", "legendText": "Regenwahrscheinlichkeit", "line_UseFillColor": true, "line_pointSize": 0, "line_pointSizeHover": 5, "yAxis_min": 0, "yAxis_max": 100, "yAxis_maxSteps": 10, "yAxis_position": "left", "yAxis_gridLines_show": false, "yAxis_gridLines_border_show": false, "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "yAxis_appendix": " %", "displayOrder": 1, "tooltip_AppendText": " %", "datalabel_show": false }; let myGraphsTemplateNiederschlag = { "data": [ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1.3", "2.5", 0, 1.9, 1.17, 0, 0, 0, 0.18, 0.7, 0.2, 0, 0 ], "type": "bar", "color": "#0061C1", "legendText": "Niederschlag", "yAxis_min": 0, "yAxis_max": 5, "yAxis_maxSteps": 10, "yAxis_position": "right", "yAxis_gridLines_show": false, "yAxis_appendix": " mm", "yAxis_gridLines_border_show": false, "yAxis_zeroLineWidth": 0.1, "yAxis_zeroLineColor": "black", "displayOrder": 1, "tooltip_AppendText": " mm", "datalabel_show": false }; var chartJson = []; //Day0 var chartJsonDay0 = {} // empty Object var axisLabelsDay0 = 'axisLabels'; var graphsDay0 = 'graphs'; chartJsonDay0[axisLabelsDay0] = []; // empty Array, push axisLabels attributes in here chartJsonDay0[graphsDay0] = []; // empty Array, push graphs attributes in here let myGraphsTemperaturDay0 = JSON.parse(JSON.stringify(myGraphsTemplateTemperatur)); myGraphsTemperaturDay0.yAxis_min = calculatedMinTempDay0; //setting y-axis min value myGraphsTemperaturDay0.yAxis_max = calculatedMaxTempDay0; //setting y-axis max value let myGraphsTemperaturDataDay0 = []; let myGraphsNiederschlagDay0 = JSON.parse(JSON.stringify(myGraphsTemplateNiederschlag)); let myGraphsNiederschlagDataDay0 = []; let myGraphsRegenwahrscheinlichkeitDay0 = JSON.parse(JSON.stringify(myGraphsTemplateRegenwahrscheinlichkeit)); let myGraphsRegenwahrscheinlichkeitDataDay0 = []; //Day1 var chartJsonDay1 = {} // empty Object var axisLabelsDay1 = 'axisLabels'; var graphsDay1 = 'graphs'; chartJsonDay1[axisLabelsDay1] = []; // empty Array, push axisLabels attributes in here chartJsonDay1[graphsDay1] = []; // empty Array, push graphs attributes in here let myGraphsTemperaturDay1 = JSON.parse(JSON.stringify(myGraphsTemplateTemperatur)); myGraphsTemperaturDay1.yAxis_min = calculatedMinTempDay1; //setting y-axis min value myGraphsTemperaturDay1.yAxis_max = calculatedMaxTempDay1; //setting y-axis max value let myGraphsTemperaturDataDay1 = []; let myGraphsNiederschlagDay1 = JSON.parse(JSON.stringify(myGraphsTemplateNiederschlag)); let myGraphsNiederschlagDataDay1 = []; let myGraphsRegenwahrscheinlichkeitDay1 = JSON.parse(JSON.stringify(myGraphsTemplateRegenwahrscheinlichkeit)); let myGraphsRegenwahrscheinlichkeitDataDay1 = []; //Day2 var chartJsonDay2 = {} // empty Object var axisLabelsDay2 = 'axisLabels'; var graphsDay2 = 'graphs'; chartJsonDay2[axisLabelsDay2] = []; // empty Array, push axisLabels attributes in here chartJsonDay2[graphsDay2] = []; // empty Array, push graphs attributes in here let myGraphsTemperaturDay2 = JSON.parse(JSON.stringify(myGraphsTemplateTemperatur)); myGraphsTemperaturDay2.yAxis_min = calculatedMinTempDay2; //setting y-axis min value myGraphsTemperaturDay2.yAxis_max = calculatedMaxTempDay2; //setting y-axis max value let myGraphsTemperaturDataDay2 = []; let myGraphsNiederschlagDay2 = JSON.parse(JSON.stringify(myGraphsTemplateNiederschlag)); let myGraphsNiederschlagDataDay2 = []; let myGraphsRegenwahrscheinlichkeitDay2 = JSON.parse(JSON.stringify(myGraphsTemplateRegenwahrscheinlichkeit)); let myGraphsRegenwahrscheinlichkeitDataDay2 = []; //Day3 var chartJsonDay3 = {} // empty Object var axisLabelsDay3 = 'axisLabels'; var graphsDay3 = 'graphs'; chartJsonDay3[axisLabelsDay3] = []; // empty Array, push axisLabels attributes in here chartJsonDay3[graphsDay3] = []; // empty Array, push graphs attributes in here let myGraphsTemperaturDay3 = JSON.parse(JSON.stringify(myGraphsTemplateTemperatur)); myGraphsTemperaturDay3.yAxis_min = calculatedMinTempDay3; //setting y-axis min value myGraphsTemperaturDay3.yAxis_max = calculatedMaxTempDay3; //setting y-axis max value let myGraphsTemperaturDataDay3 = []; let myGraphsNiederschlagDay3 = JSON.parse(JSON.stringify(myGraphsTemplateNiederschlag)); let myGraphsNiederschlagDataDay3 = []; let myGraphsRegenwahrscheinlichkeitDay3 = JSON.parse(JSON.stringify(myGraphsTemplateRegenwahrscheinlichkeit)); let myGraphsRegenwahrscheinlichkeitDataDay3 = []; //Day4 var chartJsonDay4 = {} // empty Object var axisLabelsDay4 = 'axisLabels'; var graphsDay4 = 'graphs'; chartJsonDay4[axisLabelsDay4] = []; // empty Array, push axisLabels attributes in here chartJsonDay4[graphsDay4] = []; // empty Array, push graphs attributes in here let myGraphsTemperaturDay4 = JSON.parse(JSON.stringify(myGraphsTemplateTemperatur)); myGraphsTemperaturDay4.yAxis_min = calculatedMinTempDay4; //setting y-axis min value myGraphsTemperaturDay4.yAxis_max = calculatedMaxTempDay4; //setting y-axis max value let myGraphsTemperaturDataDay4 = []; let myGraphsNiederschlagDay4 = JSON.parse(JSON.stringify(myGraphsTemplateNiederschlag)); let myGraphsNiederschlagDataDay4 = []; let myGraphsRegenwahrscheinlichkeitDay4 = JSON.parse(JSON.stringify(myGraphsTemplateRegenwahrscheinlichkeit)); let myGraphsRegenwahrscheinlichkeitDataDay4 = []; body["hours"].forEach(function(obj,index) { if (index < 24) { if (typeof obj.TTT_C !== undf || obj.TTT_C != null) { myGraphsTemperaturDataDay0.push(obj.TTT_C); } if (typeof obj.PROBPCP_PERCENT !== undf || obj.PROBPCP_PERCENT != null) { myGraphsRegenwahrscheinlichkeitDataDay0.push(obj.PROBPCP_PERCENT); } if (typeof obj.RRR_MM !==undf || obj.RRR_MM != null) { myGraphsNiederschlagDataDay0.push(obj.RRR_MM); } } else if (index > 23 && index < 48){ if (typeof obj.TTT_C !== undf || obj.TTT_C != null) { myGraphsTemperaturDataDay1.push(obj.TTT_C); } if (typeof obj.PROBPCP_PERCENT !== undf || obj.PROBPCP_PERCENT != null) { myGraphsRegenwahrscheinlichkeitDataDay1.push(obj.PROBPCP_PERCENT); } if (typeof obj.RRR_MM !== undf || obj.RRR_MM != null) { myGraphsNiederschlagDataDay1.push(obj.RRR_MM); } } else if (index > 47 && index < 72){ if (typeof obj.TTT_C !== undf || obj.TTT_C != null) { myGraphsTemperaturDataDay2.push(obj.TTT_C); } if (typeof obj.PROBPCP_PERCENT !== undf || obj.PROBPCP_PERCENT != null) { myGraphsRegenwahrscheinlichkeitDataDay2.push(obj.PROBPCP_PERCENT); } if (typeof obj.RRR_MM !== undf || obj.RRR_MM != null) { myGraphsNiederschlagDataDay2.push(obj.RRR_MM); } } else if (index > 71 && index < 96){ if (typeof obj.TTT_C !== undf || obj.TTT_C != null) { myGraphsTemperaturDataDay3.push(obj.TTT_C); } if (typeof obj.PROBPCP_PERCENT !== undf || obj.PROBPCP_PERCENT != null) { myGraphsRegenwahrscheinlichkeitDataDay3.push(obj.PROBPCP_PERCENT); } if (typeof obj.RRR_MM !== undf || obj.RRR_MM != null) { myGraphsNiederschlagDataDay3.push(obj.RRR_MM); } } else if (index > 95){ if (typeof obj.TTT_C !== undf || obj.TTT_C != null) { myGraphsTemperaturDataDay4.push(obj.TTT_C); } if (typeof obj.PROBPCP_PERCENT !== undf || obj.PROBPCP_PERCENT != null) { myGraphsRegenwahrscheinlichkeitDataDay4.push(obj.PROBPCP_PERCENT); } if (typeof obj.RRR_MM !== undf || obj.RRR_MM != null) { myGraphsNiederschlagDataDay4.push(obj.RRR_MM); } } }); // Day0 myGraphsTemperaturDay0.data = myGraphsTemperaturDataDay0; myGraphsRegenwahrscheinlichkeitDay0.data = myGraphsRegenwahrscheinlichkeitDataDay0; myGraphsNiederschlagDay0.data = myGraphsNiederschlagDataDay0; // Day1 myGraphsTemperaturDay1.data = myGraphsTemperaturDataDay1; myGraphsRegenwahrscheinlichkeitDay1.data = myGraphsRegenwahrscheinlichkeitDataDay1; myGraphsNiederschlagDay1.data = myGraphsNiederschlagDataDay1; // Day2 myGraphsTemperaturDay2.data = myGraphsTemperaturDataDay2; myGraphsRegenwahrscheinlichkeitDay2.data = myGraphsRegenwahrscheinlichkeitDataDay2; myGraphsNiederschlagDay2.data = myGraphsNiederschlagDataDay2; // Day3 myGraphsTemperaturDay3.data = myGraphsTemperaturDataDay3; myGraphsRegenwahrscheinlichkeitDay3.data = myGraphsRegenwahrscheinlichkeitDataDay3; myGraphsNiederschlagDay3.data = myGraphsNiederschlagDataDay3; // Day4 myGraphsTemperaturDay4.data = myGraphsTemperaturDataDay4; myGraphsRegenwahrscheinlichkeitDay4.data = myGraphsRegenwahrscheinlichkeitDataDay4; myGraphsNiederschlagDay4.data = myGraphsNiederschlagDataDay4; //Day0 chartJsonDay0[axisLabelsDay0] = myHoursFull; chartJsonDay0[graphsDay0].push(myGraphsTemperaturDay0 ); chartJsonDay0[graphsDay0].push(myGraphsRegenwahrscheinlichkeitDay0); chartJsonDay0[graphsDay0].push(myGraphsNiederschlagDay0); //Day1 chartJsonDay1[axisLabelsDay1] = myHoursFull; chartJsonDay1[graphsDay1].push(myGraphsTemperaturDay1); chartJsonDay1[graphsDay1].push(myGraphsRegenwahrscheinlichkeitDay1); chartJsonDay1[graphsDay1].push(myGraphsNiederschlagDay1); //Day2 chartJsonDay2[axisLabelsDay2] = myHoursFull; chartJsonDay2[graphsDay2].push(myGraphsTemperaturDay2); chartJsonDay2[graphsDay2].push(myGraphsRegenwahrscheinlichkeitDay2); chartJsonDay2[graphsDay2].push(myGraphsNiederschlagDay2); //Day3 chartJsonDay3[axisLabelsDay3] = myHoursFull; chartJsonDay3[graphsDay3].push(myGraphsTemperaturDay3); chartJsonDay3[graphsDay3].push(myGraphsRegenwahrscheinlichkeitDay3); chartJsonDay3[graphsDay3].push(myGraphsNiederschlagDay3); //Day4 chartJsonDay4[axisLabelsDay4] = myHoursReduced; chartJsonDay4[graphsDay4].push(myGraphsTemperaturDay4); chartJsonDay4[graphsDay4].push(myGraphsRegenwahrscheinlichkeitDay4); chartJsonDay4[graphsDay4].push(myGraphsNiederschlagDay4); chartJson.push(chartJsonDay0); chartJson.push(chartJsonDay1); chartJson.push(chartJsonDay2); chartJson.push(chartJsonDay3); chartJson.push(chartJsonDay4); return chartJson; } /** * Deletes all Objects of Adapter * @param self this Adapter */ async function deleteAllAdapterObjects(self){ self.log.debug('Deleting all geolocation objects'); let resp1 = await self.delObjectAsync('geolocation', {recursive: true}); self.log.debug('Deleting all forecast objects'); let resp2 = await self.delObjectAsync('forecast', {recursive: true}); } /** * Get Token by REST-Calling SRF Weather API * @param self this adapterinfo.connection * @param myCallback Callback */ function getToken(self,myCallback){ self.log.debug('getting Token...'); //Convert consumerKey and consumerSecret to base64 let data = self.config.consumerKey + ":" + self.config.consumerSecret; let buff = Buffer.from(data); let base64data = buff.toString('base64'); self.log.debug('"' + data + '" converted to Base64 is "' + base64data + '"'); //Options for getting Access-Token var options_Access_Token = { "json": true, "method": "POST", "hostname": "api.srgssr.ch", "port": null, "path": "/oauth/v1/accesstoken?grant_type=client_credentials", "headers": { "Authorization": "Basic " + base64data, "Cache-Control": "no-cache", "Content-Length": 0, "Postman-Token": "24264e32-2de0-f1e3-f3f8-eab014bb6d76" } }; self.log.debug("Options to get Access Token: " + JSON.stringify(options_Access_Token)); var req = https.request(options_Access_Token, function (res) { var chunks = []; res.on("data", function (chunk) { chunks.push(chunk); }); res.on("end", function () { self.log.debug("Answer of Request Access Token: " + Buffer.concat(chunks).toString()); if (!isValidJSONString(Buffer.concat(chunks).toString())){ self.log.error("Delivered SRF-JSON is not valid: " + Buffer.concat(chunks).toString()); self.log.error("Possible cause is an incorrectly configured adapter. Please check configuration. If error persists, create an issue on https://github.com/baerengraben/ioBroker.swiss-weather-api."); self.setState('info.connection', false, true); return; } var body = JSON.parse(Buffer.concat(chunks).toString()); if (typeof body.access_token === undf || body.access_token == null) { self.log.warn("Got no Token - Is Adapter correctly configured (consumerKey/consumerSecret)? It may also be that the maximum number of queries for today is exhausted"); self.setState('info.connection', false, true); return; } else if (body.access_token === ""){ self.log.warn("Got an empty Token - It may be that the maximum number of queries for today is exhausted"); self.setState('info.connection', false, true); return; } access_token = body.access_token.toString(); self.log.debug("Access_Token : " + access_token); myCallback(self,getForecast); }); res.on("error", function (error) { self.setState('info.connection', false, true); self.log.error(error) }); }); req.end(); } /** * Sets the current hour objects with the corresponding values of forecast.hours.day0 * @param self Adapter */ function setCurrentHour(self){ self.log.info('update current hour...'); // update current_hour objects function updateVariables() { var promise = new Promise((resolve, reject) => { self.log.debug('Defining local current_hour variables...'); //get systemtime hour var date = new Date(); var hour = (date.getHours()<10?'0':'') + date.getHours(); //Fix for https://github.com/baerengraben/ioBroker.swiss-weather-api/issues/52 var path = self.namespace + ".forecast.hours.day0"; if (date.getHours()===0){ //check if forecast values already has nextday values in day0/0000 self.getState(self.namespace + ".forecast.hours.day0.0000.date_time", function (err, state) { if ((typeof state !== "undefined") && (state !== null)) { if (date.getDay() === new Date(state.val).getDay()){ self.log.info("forecast is containing aktual values vor 00:00. So using day0 values"); } else { self.log.info("forecast is containing yesterdays values vor 00:00. So using day1 values."); path = self.namespace + ".forecast.hours.day1" } } else { self.log.error("Cannot read date_time" + ':' + 'This should not happen. Please go to github and create an issue.'); } }); } let currentHourVariables = {}; Object.assign(currentHourVariables, {local_background_color: "dummycolor"}); Object.assign(currentHourVariables, {local_temperature : 0}); Object.assign(currentHourVariables, {local_text_color : "dummycolor"}); Object.assign(currentHourVariables, {local_DD_DEG : 0}); Object.assign(currentHourVariables, {local_FF_KMH : 0}); Object.assign(currentHourVariables, {local_FX_KMH : 0}); Object.assign(currentHourVariables, {local_ICON_URL_COLOR : "dummyicon"}); Object.assign(currentHourVariables, {local_ICON_URL_DARK : "dummyicon"}); Object.assign(currentHourVariables, {local_ICON_URL_LIGHT : "dummyicon"}); Object.assign(currentHourVariables, {local_PROBPCP_PERCENT : 0}); Object.assign(currentHourVariables, {local_RRR_MM : 0}); Object.assign(currentHourVariables, {local_symbol_code : 0}); Object.assign(currentHourVariables, {local_TTH_C : 0}); Object.assign(currentHourVariables, {local_TTL_C : 0}); Object.assign(currentHourVariables, {local_TTT_C : 0}); Object.assign(currentHourVariables, {date_time : "1970-01-01T00:00:00+02:00"}); Object.assign(currentHourVariables, {local_symbol24_code : 0}); Object.assign(currentHourVariables, {local_DEWPOINT_C : 0}); Object.assign(currentHourVariables, {local_RELHUM_PERCENT : 0}); Object.assign(currentHourVariables, {local_DEWPOINT_C : 0}); Object.assign(currentHourVariables, {local_FRESHSNOW_CM : 0}); Object.assign(currentHourVariables, {local_PRESSURE_HPA : 0}); Object.assign(currentHourVariables, {local_SUN_MIN : 0}); Object.assign(currentHourVariables, {local_IRRADIANCE_WM2 : 0}); Object.assign(currentHourVariables, {local_TTTFEEL_C : 0}); self.log.debug('Updating local current_hour variables...'); self.getState(path + '.' + hour + '00.cur_color.background_color', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.cur_color.background_color' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_background_color = state.val; } else { self.log.info(path + '.' + hour + '00.cur_color.background_color' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.cur_color.temperature', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.cur_color.temperature' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_temperature = state.val; } else { self.log.info(path + '.' + hour + '00.cur_color.temperature' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.cur_color.text_color', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.cur_color.text_color' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_text_color = state.val; } else { self.log.info(path + '.' + hour + '00.cur_color.text_color' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.DD_DEG', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.DD_DEG' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_DD_DEG = state.val; } else { self.log.info(path + '.' + hour + '00.DD_DEG' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.FF_KMH', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.FF_KMH' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_FF_KMH = state.val; } else { self.log.info(path + '.' + hour + '00.FF_KMH' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.FX_KMH', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.FX_KMH' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_FX_KMH = state.val; } else { self.log.info(path + '.' + hour + '00.FX_KMH' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.ICON_URL_COLOR', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.ICON_URL_COLOR' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_ICON_URL_COLOR = state.val; } else { self.log.info(path + '.' + hour + '00.ICON_URL_COLOR' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.ICON_URL_DARK', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.ICON_URL_DARK' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_ICON_URL_DARK = state.val; } else { self.log.info(path + '.' + hour + '00.ICON_URL_DARK' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.ICON_URL_LIGHT', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.ICON_URL_LIGHT' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_ICON_URL_LIGHT = state.val; } else { self.log.info(path + '.' + hour + '00.ICON_URL_LIGHT' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.PROBPCP_PERCENT', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.PROBPCP_PERCENT' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_PROBPCP_PERCENT = state.val; } else { self.log.info(path + '.' + hour + '00.PROBPCP_PERCENT' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.RRR_MM', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.RRR_MM' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_RRR_MM = state.val; } else { self.log.info(path + '.' + hour + '00.RRR_MM' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.symbol_code', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.symbol_code' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_symbol_code = state.val; } else { self.log.info(path + '.' + hour + '00.symbol_code' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.TTH_C', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.TTH_C' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_TTH_C = state.val; } else { self.log.info(path + '.' + hour + '00.TTH_C' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.TTL_C', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.TTL_C' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_TTL_C = state.val; } else { self.log.info(path + '.' + hour + '00.TTL_C' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.TTT_C', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.TTT_C' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_TTT_C = state.val; } else { self.log.info(path + '.' + hour + '00.TTT_C' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.date_time', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.date_time' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.date_time = state.val; } else { self.log.info(path + '.' + hour + '00.date_time' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.symbol24_code', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.symbol24_code' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_symbol24_code = state.val; } else { self.log.info(path + '.' + hour + '00.symbol24_code' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.DEWPOINT_C', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.DEWPOINT_C' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_DEWPOINT_C = state.val; } else { self.log.info(path + '.' + hour + '00.DEWPOINT_C' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.RELHUM_PERCENT', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.RELHUM_PERCENT' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_RELHUM_PERCENT = state.val; } else { self.log.info(path + '.' + hour + '00.RELHUM_PERCENT' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.FRESHSNOW_CM', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.FRESHSNOW_CM' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_FRESHSNOW_CM = state.val; } else { self.log.info(path + '.' + hour + '00.FRESHSNOW_CM' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.PRESSURE_HPA', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.PRESSURE_HPA' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_PRESSURE_HPA = state.val; } else { self.log.info(path + '.' + hour + '00.PRESSURE_HPA' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.SUN_MIN', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.SUN_MIN' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_SUN_MIN = state.val; } else { self.log.info(path + '.' + hour + '00.SUN_MIN' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.IRRADIANCE_WM2', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.IRRADIANCE_WM2' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_IRRADIANCE_WM2 = state.val; } else { self.log.info(path + '.' + hour + '00.IRRADIANCE_WM2' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); self.getState(path + '.' + hour + '00.TTTFEEL_C', function (err, state) { if (err) { self.log.error(path + '.' + hour + '00.TTTFEEL_C' + ':' + 'This should not happen. Error is ' + err.message); } if ((typeof state !== "undefined") && (state !== null)) { currentHourVariables.local_TTTFEEL_C = state.val; } else { self.log.info(path + '.' + hour + '00.TTTFEEL_C' + ':' + 'This should not happen. State is undefined or null. So in this run no data is copied for this value'); } }); // Fix for https://github.com/baerengraben/ioBroker.swiss-weather-api/issues/66 // Wait 5s to ensure, that all "getStates" are done setTimeout(function() { resolve(currentHourVariables); }, 5000) }) return promise; } function addCurrentHourObjects(result) { //first do updateVariables() and wait until its finished // const result = updateVariables(); let updatePath = "forecast.current_hour"; self.log.debug('...and now add updated variables to current_hour objects.'); //*** Create current_hour object *** self.setObjectNotExists(updatePath, { type: "channel", common: { name: "Holds the current hour data. This is updated on every full hour by coping the data from forecast.hours.day0 - actual hour", role: "info" }, native: {}, }); self.setObjectNotExists(updatePath + "." + "date_time", { type: "state", common: { name: "Date for validity of record", type: "string", role: "text", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "date_time", { val: result.date_time, ack: true }); }); self.setObjectNotExists(updatePath + "." + "TTT_C", { type: "state", common: { name: "Current temperature in °C", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "TTT_C", { val: result.local_TTT_C, ack: true }); }); self.setObjectNotExists(updatePath + "." + "TTL_C", { type: "state", common: { name: "Error range lower limit", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "TTL_C", { val: result.local_TTL_C, ack: true }); }); self.setObjectNotExists(updatePath + "." + "TTH_C", { type: "state", common: { name: "Error range upper limit", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "TTH_C", { val: result.local_TTH_C, ack: true }); }); self.setObjectNotExists(updatePath + "." + "PROBPCP_PERCENT", { type: "state", common: { name: "Probability of precipitation in %", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "PROBPCP_PERCENT", { val: result.local_PROBPCP_PERCENT, ack: true }); }); self.setObjectNotExists(updatePath + "." + "RRR_MM", { type: "state", common: { name: "Precipitation total", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "RRR_MM", { val: result.local_RRR_MM, ack: true }); }); self.setObjectNotExists(updatePath + "." + "FF_KMH", { type: "state", common: { name: "Wind speed in km/h", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "FF_KMH", { val: result.local_FF_KMH, ack: true }); }); self.setObjectNotExists(updatePath + "." + "FX_KMH", { type: "state", common: { name: "Peak wind speed in km/h", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "FX_KMH", { val: result.local_FX_KMH, ack: true }); }); self.setObjectNotExists(updatePath + "." + "DD_DEG", { type: "state", common: { name: "Wind direction in angular degrees: 0 = North wind", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "DD_DEG", { val: result.local_DD_DEG, ack: true }); }); self.setObjectNotExists(updatePath + "." + "symbol_code", { type: "state", common: { name: "Mapping to weather icon", type: "number", role: "value", write: false }, native: {}, }, function () { self.setState(updatePath + "." + "symbol_code", { val: result.local_symbol_code, ack: true }); }); self.setObjectNotExists(updatePath + "." + "ICON_URL_COLOR", { type: "state", common: { name: "URL to color Icon", type: "string", role: "weather.icon" }, native: {}, }, function () { self.setState(updatePath + "." + "ICON_URL_COLOR", { val: result.local_ICON_URL_COLOR, ack: true }); }); self.setObjectNotExists(updatePath + "." + "ICON_URL_DARK", { type: "state", common: { name: "URL to dark Icon", type: "string", role: "weather.icon" }, native: {}, }, function () { self.setState(updatePath + "." + "ICON_URL_DARK", { val: result.local_ICON_URL_DARK, ack: true }); }); self.setObjectNotExists(updatePath + "." + "ICON_URL_LIGHT", { type: "state", common: { name: "URL to light Icon", type: "string", role: "weather.icon" }, native: {}, }, function () { self.setState(updatePath + "." + "ICON_URL_LIGHT", { val: result.local_ICON_URL_LIGHT, ack: true }); }); self.setObjectNotExists(updatePath + "." + "cur_color", { type: "channel",