Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. [Vorlage] Hilfreiche JavaScript-Funktionen

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.7k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.1k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    3.0k

[Vorlage] Hilfreiche JavaScript-Funktionen

Geplant Angeheftet Gesperrt Verschoben JavaScript
javascript
23 Beiträge 10 Kommentatoren 12.8k Aufrufe 43 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • MicM Offline
    MicM Offline
    Mic
    Developer
    schrieb am zuletzt editiert von Mic
    #1

    Dies ist eine Sammlung von JavaScript-Funktionen, die hilfreich zur Erstellung von Skripten im JavaScript-Adapter sind. Ich pflege diese Scripts kontinuierlich und ergänze entsprechend.

    Bitte beachtet: ioBroker bringt schon einige tolle Funktionen mit, siehe: ioBroker JavaScript-Funktionen

    Weitere hilfreiche Ressourcen:

    • Aufruf: Welche guten JavaScripts setzt ihr ein? Sammlung einiger Scripts
    • javascript.info: Gutes JavaScript-Tutorial
    • regex101: Zum einfachen Erstellen und Testen von Regular Expressions

    1. Strings

    /**
     * Will just keep lower case letters, numbers, and replaces the rest with a single "-"
     * Use Case: to prepare a sting for a file name.
     * @param {string}  strInput   Input String
     * @return {string}   the sanitized string 
     */
    function sanitizeStr(strInput) {
     
        let strT = strInput.toLowerCase();
        let strResult = strT.replace(/([^a-z0-9]+)/gi, '-');
        return strResult;
    
    }
    

    /**
     * Clean a given string for using in ioBroker as part of a atate
     * Will just keep letters, incl. Umlauts, numbers, "-" and "_" and "."
     * @param  {string}  strInput   Input String
     * @return {string}   the processed string 
     */
    function cleanStringForState(strInput) {
        let strResult = strInput.replace(/([^a-zA-ZäöüÄÖÜß0-9\-\._]+)/gi, '');
        return strResult;
    }
    

    /**
     * Checks if the string provided contains either every or some terms.
     * Requires function isLikeEmpty().
     * Source: https://stackoverflow.com/questions/36283767/javascript-select-the-string-if-it-matches-multiple-words-in-array
     * @param {string} strInput - The string on which we run this search
     * @param {array} arrayTerms - The terms we are searching, e.g. ["hue", "error", "raspberry"]
     * @param {string} type - 'every': all terms must match to be true,
     *                        'some': at least one term (or more) must match
     *                        'blacklist': different here: function will always
     *                         return FALSE, but if one of the arrayTerms contains
     *                         minimum 3 chars and is found in provided string,
     *                         we return TRUE (= blacklisted item found).
     * @return {boolean}       true, if it contains ALL words, false if not all words (or none)
     *                         Also, will return true if arrayTerms is not array or an empty array
     */
    function strMatchesTerms(strInput, arrayTerms, type) {
        if(type === 'blacklist') {
            if (Array.isArray(arrayTerms)) {
                let arrayTermsNew = [];
                for (let lpTerm of arrayTerms) {
                    if (lpTerm.length >= 3) {
                        arrayTermsNew.push(lpTerm);
                    }
                }
                if(isLikeEmpty(arrayTermsNew) === false) {
                    let bResultBL = arrayTermsNew.some(function(word) {
                        return strInput.indexOf(word) > -1;
                    });
                    return bResultBL;
                } else {
                    return false; // return false if no items to be blacklisted
                }
            } else {
                return false; // we return false if the arrayTerms given is not an array. Want to make sure if we really should blacklist...
            }
    
        } else {
            if (Array.isArray(arrayTerms)) {
                if(type === 'every') {
                    let bResultEvery = arrayTerms.every(function(word) {
                        return strInput.indexOf(word) > -1;
                    });
                    return bResultEvery;
                } else if(type === 'some') {
                    let bResultSome = arrayTerms.some(function(word) {
                        return strInput.indexOf(word) > -1;
                    });
                    return bResultSome;
                }
    
            } else {
                return true; // we return true if the arrayTerms given is not an array
            }
        }
    }
    

    /**
      * Encrypts or decrypts a string.
      * @source https://codereview.stackexchange.com/questions/127454/a-small-custom-encryption-decryption-script
      * @param {string}  strInput   The input string to be encrypted or decrypted
      * @param {boolean}  bEncrypt  if true, it will be encrypted, otherwise decrypted
      * @return {string}  Encrypted or decrypted string.
    */
    function cryptStr(strInput, bEncrypt) {
        var text = strInput;
        var crypted = '';
        for(var i = 0; i < text.length; i++) {
            var ASCII = text[i].charCodeAt(0);
            var n = null;
            if(i % 2 === 0) {
                n = bEncrypt === true ? ASCII + 4 : ASCII - 4;
            }
            else if(i % 2 == 1) {
                n = bEncrypt === true ? ASCII + 7 : ASCII - 7;
            }
            var s = String.fromCharCode(n);
            crypted += s;
        }
        return crypted;
    }
    

    2. Strings/Arrays gemischt


    ACHTUNG: Bitte /[ und /] durch /\\[ und /\\[ ersetzen, wird durch das Forum nicht korrekt dargestellt.

    /**
     * Checks if Array or String is not undefined, null or empty.
     * 08-Sep-2019: added check for [ and ] to also catch arrays with empty strings.
     * @param inputVar - Input Array or String, Number, etc.
     * @return true if it is undefined/null/empty, false if it contains value(s)
     * Array or String containing just whitespaces or >'< or >"< or >[< or >]< is considered empty
     */
    function isLikeEmpty(inputVar) {
        if (typeof inputVar !== 'undefined' && inputVar !== null) {
            let strTemp = JSON.stringify(inputVar);
            strTemp = strTemp.replace(/\s+/g, ''); // remove all whitespaces
            strTemp = strTemp.replace(/\"+/g, "");  // remove all >"<
            strTemp = strTemp.replace(/\'+/g, "");  // remove all >'<
            strTemp = strTemp.replace(/\[+/g, "");  // remove all >[<
            strTemp = strTemp.replace(/\]+/g, "");  // remove all >]<
            if (strTemp !== '') {
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }
    

    3. Arrays

    /**
     * Removing Array element(s) by input value. 
     * @param {array}   arr             the input array
     * @param {string}  valRemove       the value to be removed
     * @param {boolean} [exact=true]    OPTIONAL: default is true. if true, it must fully match. if false, it matches also if valRemove is part of element string
     * @return {array}  the array without the element(s)
     */
    function arrayRemoveElementsByValue(arr, valRemove, exact) {
    
        if (exact === undefined) exact = true;
    
        for ( let i = 0; i < arr.length; i++){ 
            if (exact) {
                if ( arr[i] === valRemove) {
                    arr.splice(i, 1);
                    i--; // required, see https://love2dev.com/blog/javascript-remove-from-array/
                }
            } else {
                if (arr[i].indexOf(valRemove) != -1) {
                    arr.splice(i, 1);
                    i--; // see above
                }
            }
        }
        return arr;
    }
    

    /**
     * Clean Array: Removes all falsy values: undefined, null, 0, false, NaN and "" (empty string)
     * Source: https://stackoverflow.com/questions/281264/remove-empty-elements-from-an-array-in-javascript
     * @param {array} inputArray       Array to process
     * @return {array}  Cleaned array
     */
    function cleanArray(inputArray) {
      var newArray = [];
      for (let i = 0; i < inputArray.length; i++) {
        if (inputArray[i]) {
          newArray.push(inputArray[i]);
        }
      }
      return newArray;
    }
    

    /**
     * Remove Duplicates from Array
     * Source - https://stackoverflow.com/questions/23237704/nodejs-how-to-remove-duplicates-from-array
     * @param {array} inputArray       Array to process
     * @return {array}  Array without duplicates.
     */
    function arrayRemoveDublicates(inputArray) {
        let uniqueArray;
        uniqueArray = inputArray.filter(function(elem, pos) {
            return inputArray.indexOf(elem) == pos;
        });
        return uniqueArray;
    }
    

    /**
     * Returns the next or previous element of an array for a given element.
     * Use case is to easily switch through an array of elements...
     * If it is the last element of the array, it will return the first one, if bNext is true.
     * If it is the first element of the array, it will return the last one, if bNext is false.
     * If not found, it will ALWAYS return the first element.
     *
     * @param {array}   inputArray  Array
     * @param {string}  strElement  for this String we want to get the next/previous array element
     * @param {boolean} bNext       next element if true, previous element if false
     * @return {string} The next or previous element from the array
     */
    function arrayGetNextOrPreviousValue(inputArray, strElement, bNext) {
        let iLength = inputArray.length; // Number of elements in the Array
        let iPosition = inputArray.indexOf(strElement) + 1; // Current position. We add 1 since first element is in position 0
        let iPositionNext = iPosition + 1;
        let iPositionPrevious = iPosition - 1;
        
        if (bNext) {
            // if not found, it will return the first element...
            if (iPositionNext > iLength) iPositionNext = 1;
            return inputArray[iPositionNext - 1];
        } else {
            if (iPosition === 0) { // will be zero if not found
                return inputArray[0]; // return the first element, if not found
            } else {
                if (iPositionPrevious < 1) iPositionPrevious = iLength;
                return inputArray[iPositionPrevious - 1];
            }
        }
    }
    

    /**
     * Sort array case-insensitive
     * @param {object} arrayInput  Array to be sorted
     * @return {object}   case-insensitive sorted array
     */
    function arraySortCaseInsensitive(arrayInput) {
        let arrayResult = [...arrayInput]; // We use array spreads '...' to copy array. If not, array is changed by reference and not value.
        arrayResult.sort(function (a, b) {
            return a.toLowerCase().localeCompare(b.toLowerCase());
        });
        return arrayResult;
    }
    


    indexOf() ist eine bereits vorhandene Funktion in JavaScript. Sie gibt den Index des Elements
    zurück (0, 1, 2, 3, usw.), oder -1, falls das Element nicht im Array ist.
    Beispiel:

    let arrayFruits = ['Apfel', 'Birne', 'Pfirsich'];
    let fruit = 'Banane';
    // indexOf() return the index of an element in the array, or -1 if it's not in the array.
    if (arrayFruits.indexOf(fruit) > -1) {
        log(fruit + ' ist im Array enthalten.');
    } else {
        log(fruit + ' ist im Array NICHT enthalten.');
    }
    

    4. Zahlen

    /**
     * Prüft ob Variableninhalt eine Zahl ist.
     * isNumber ('123'); // true  
     * isNumber ('123abc'); // false  
     * isNumber (5); // true  
     * isNumber ('q345'); // false
     * isNumber(null); // false
     * isNumber(undefined); // false
     * isNumber(false); // false
     * isNumber('   '); // false
     * @source https://stackoverflow.com/questions/1303646/check-whether-variable-is-number-or-string-in-javascript
     * @param {any} n     Variable, die zu prüfen ist auf Zahl
     * @return {boolean}  true falls Zahl, false falls nicht.
      */
    function isNumber(n) { 
        return /^-?[\d.]+(?:e-?\d+)?$/.test(n); 
    }
    

    /**
     * Fügt Vornullen zu einer Zahl hinzu, macht also z.B. aus 7 eine "007". 
     * Akzeptiert sowohl Datentyp number und string als Eingabe.
     * zeroPad(5, 4);    // wird "0005"
     * zeroPad('5', 6);  // wird "000005"
     * zeroPad(1234, 2); // wird "1234" :)
     * @param  {string|number}  num     Zahl, die Vornull(en) bekommen soll
     * @param  {number}         places  Anzahl Stellen.
     * @return {string}         Zahl mit Vornullen wie gewünscht.
     */
    function zeroPad(num, places) {
        let zero = places - num.toString().length + 1;
        return Array(+(zero > 0 && zero)).join("0") + num;        
    } 
    

    5. Datum/Zeit


    Dies ist eine eher wenig bekannte ioBroker-interne Funktion, siehe Dokumentation. Daher führe ich sie hier auf.
    Man kann damit einfach Zeiten vergleichen. Im folgenden Beispiel wird geprüft, ob die aktuelle Uhrzeit innerhalb des Bereichs ist.

    let result = compareTime('20:00', '22:30', 'between');
    log('Liegt die aktuelle Uhrzeit zwischen 20:00 und 22:30?: ' + result);
    

    /**
     * ---------------------------------------------------------------------------------------------
     * Converts a given date into a string by replacing "YYYY, MM, DD, hh, mm, ss" in given format.
     * Optional: will replace like DD-MM-YYYY with "Today"/"Yesterday" if within # (hash).
     *           So, '#DD.MM.YY#, hh:mm:ss' will become 'Today, 08:25:13'.
     *           Use optional parameters [todayString] and [yesterdayString] accordingly to replace
     *           with your terms you want to use for "Today" and "Yesterday".
     * ---------------------------------------------------------------------------------------------
     * Version: 1.1
     * Author: Mic
     * Source: https://forum.iobroker.net/topic/24179/
     * ---------------------------------------------------------------------------------------------
     * @param {object|number}  inputDate            The date to convert. Accepts both a date object (like: "new Date()") 
     *                                              or a timestamp number like 1582826332588 (so like what "Date.now()" returns)
     * @param {string}         format               String of which "YYYY, MM, DD, hh, mm, ss" will be replaced accordingls.
     *                                              Examples: 'YYYY-MM-DD hh:mm:ss', 'DD.MM.YY, hh:mm:ss', 'DD.MM.YY um hh:mm:ss Uhr'
     * @param {string}         [todayString]        Optional. String for "Today". Default is "Heute".
     * @param {string}         [yesterdayString]    Optional. String for "Yesterday". Default is "Gestern".
     * @return {string}                             The format containing the date values for YYYY, MM, DD, hh, mm, ss
     */
    function dateToString(inputDate, format, todayString='Heute', yesterdayString='Yesterday') {
    
        let strResult = format;
    
        // Convert inputDate to date. This is to accept timestamps, which will be converted to a date object as well
        let dateGiven = new Date(inputDate);
    
    
        // Replace today's date and yesterday's date
        let hashkMatch = strResult.match(/#(.*)#/);
        if (hashkMatch != null) {
            let todayYesterdayTxt = todayYesterday(dateGiven);
            if(todayYesterdayTxt != '') {
                // We have either today or yesterday, so set according txt
                strResult = strResult.replace('#'+hashkMatch[1]+'#', todayYesterdayTxt);
            } else {
                // Neither today nor yesterday, so remove all ##
                strResult = strResult.replace(/#/g, '');
            }        
        }
    
        // Replace YYYY, YY, MM, DD, hh, mm, ss accordingly with actual date/times
        strResult = strResult.replace(/Y{4}/g, zeroPad(dateGiven.getFullYear(), 4));
        strResult = strResult.replace(/Y{2}/g, zeroPad(dateGiven.getFullYear(), 2));
        strResult = strResult.replace(/M{2}/g, zeroPad((dateGiven.getMonth() + 1), 2));
        strResult = strResult.replace(/D{2}/g, zeroPad(dateGiven.getDate(), 2));
        strResult = strResult.replace(/h{2}/g, zeroPad(dateGiven.getHours(), 2));
        strResult = strResult.replace(/m{2}/g, zeroPad(dateGiven.getMinutes(), 2));
        strResult = strResult.replace(/s{2}/g, zeroPad(dateGiven.getSeconds(), 2));
     
        return strResult;
    
    
    
        /**
         * Add leading numbers -  see https://forum.iobroker.net/topic/24179/
         */
        function zeroPad(num, places) {
            let zero = places - num.toString().length + 1;
            return Array(+(zero > 0 && zero)).join('0') + num;        
        } 
    
        /**
         * @param {object} dateGiven   Date object
         * @return                     'Heute', if today, 'Gestern' if yesterday, empty string if neither today nor yesterday
         */
        function todayYesterday(dateGiven) {
            const today = new Date();
            const yesterday = new Date(); 
            yesterday.setDate(today.getDate() - 1)
            if (dateGiven.toLocaleDateString() == today.toLocaleDateString()) {
                return todayString;
            } else if (dateGiven.toLocaleDateString() == yesterday.toLocaleDateString()) {
                return yesterdayString;
            } else {
                return '';
            }
        }
    
    }
    
    
    

    /**
     * Returns the current date in ISO format "YYYY-MM-DD".
     * Requires function zeroPad().
     * @return  {string}    Date in ISO format
     */
    function getCurrentIsoDate() {
        let currDate = new Date();
        return currDate.getFullYear() + '-' + zeroPad((currDate.getMonth() + 1), 2) + '-' + zeroPad(currDate.getDate(), 2);
    }
    
    

    /**
     * Converts a "date" datatype into ISO date. E.g. March 23, 2016 will become "2016-03-23" 
     * Requires function zeroPad().
     * @param   {object}  inputDate   Date created with "new Date()". If you want the current date, use "new Date()"
     * @return  {string}  Date in ISO format
     */
    function dateToIsoDate(inputDate) {
        return inputDate.getFullYear() + '-' + zeroPad((inputDate.getMonth() + 1), 2) + '-' + zeroPad(inputDate.getDate(), 2);
    }
    

    /**
     * Converts a given date datatype into European date/time. E.g. '9:03pm and 17 seconds' -> '21:03:17'
     * Requires function zeroPad().
     * @param   {object}   inputDate   Date created with "new Date()". If you want the current date, use "new Date()"
     * @return  {string}    Date in European date/time as String
     */
    function dateToEuroString(inputDate) {
        return zeroPad(inputDate.getHours(), 2) + ':' + zeroPad(inputDate.getMinutes(), 2) + ':' + zeroPad(inputDate.getSeconds(), 2);
    }
    

    /**
     * Abfrage, ob ein Datum innerhalb eines Bereichs ist.
     * Angeregt von: https://forum.iobroker.net/topic/2289/
     * Zum Aufruf ist das ISO-Datumsformat JJJJ-MM-TT erforderlich, z.B. 2019-12-24.
     * Gepostet unter: https://forum.iobroker.net/post/256400
     * @param {string}   strDateToCheck       Das zu prüfende Datum. Falls aktuelles Datum geprüft werden soll: 'now' eingeben.
     * @param {string}   strDateFirst         Datum: Zeitraum erster Tag.
     * @param {string}   strDateLast          Datum: Zeitraum letzter Tag.
     */
    function isDateInRange(strDateToCheck, strDateFirst, strDateLast) {
        // Prepare the date we want to check. Either current date, or provided date in variable strDateToCheck
        let dtToCheck;
        if (strDateToCheck == 'now') {
            dtToCheck = new Date();
        } else {
             dtToCheck = new Date(strDateToCheck);
        }
        dtToCheck.setHours(0, 0, 0, 0); // Same basis for hours, minutes etc. as for all dates
        let dtFirst = new Date(strDateFirst);
        dtFirst.setHours(0, 0, 0, 0);
        let dtLast = new Date(strDateLast);
        dtLast.setHours(0, 0, 0, 0);
        let isInRange = false;
        if ( (dtLast >= dtFirst) && (dtToCheck >= dtFirst) && (dtToCheck <= dtLast) )  {
            isInRange = true;
        }
        return isInRange;
    }
    

    /**
     * Add certain number of minutes to a given date/time.
     * @param {object}    dateInp      Date created with "new Date()". If you want the current date, use "new Date()"
     * @param {number}    minutesInp   Number of minutes to be added to the given date.
     * @return {object}   New date with the minutes added
     */
    function dateAddMinutes(dateInp, minutesInp) {
        return new Date(dateInp.getTime() + (minutesInp * 60000));
    }
    

    /**
     * Add certain number of days to a given date/time.
     * @param {object}    dateInp      Date created with "new Date()". If you want the current date, use "new Date()"
     * @param {number}    numberOfDays   Number of days to be added to the given date.
     * @return {object}   New date with the days added
     */
    function addDays(dateInp, numberOfDays) {
        return new Date(dateInp.getTime() + (numberOfDays * 24 * 60 * 60 * 1000));
    }
    

    6. Filesystem

    /**
     * Check if a file in the file system exists. It works synchronously.
     * See: https://stackoverflow.com/questions/4482686/
     * Version: Mic - 0.1 (27 Jan 2020)
     * @param {string}  filePath   Full file path incl. file name, like '/etc/passwd' or '/tmp/textfile.txt'
     */
    function fileExistsSync(filePath) {
        const fs = require('fs');
        if (fs.existsSync(filePath)) {
            return true;
        } else {
            return false;
        }
    }
    

    7. Regular Expressions - RegExp

    /**
     * Escapes a string for use in RegEx as (part of) pattern
     * Source: https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
     * @param {string} inputStr  The input string to be escaped
     * @return {string}  The escaped string
     */
    function escapeRegExp(inputStr) {
    	return inputStr.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
    }
    

    8. XML

    /**
     * Simple XML parser. Quelle: https://gist.github.com/petersirka/9e79b1d43cf6e579fc62
     * Wandelt ein XML in ein Array um, damit viel einfacher handhabbar.
     * @param  {string}  xml
     * @return {object}
     */
    function xmlParse(xml) {
    
        let beg = -1;
        let end = 0;
        let tmp = 0;
        let current = [];
        let obj = {};
        let from = -1;
    
        while (true) {
    
            beg = xml.indexOf('<', beg + 1);
            if (beg === -1)
                break;
    
            end = xml.indexOf('>', beg + 1);
            if (end === -1)
                break;
    
            let el = xml.substring(beg, end + 1);
            let c = el[1];
    
            if (c === '?' || c === '/') {
    
                let o = current.pop();
    
                if (from === -1 || o !== el.substring(2, el.length - 1))
                    continue;
    
                let path = current.join('.') + '.' + o;
                let value = xml.substring(from, beg);
    
                if (typeof(obj[path]) === 'undefined')
                    obj[path] = value;
                else if (obj[path] instanceof Array)
                    obj[path].push(value);
                else
                    obj[path] = [obj[path], value];
    
                from = -1;
                continue;
            }
    
            tmp = el.indexOf(' ');
            let hasAttributes = true;
    
            if (tmp === -1) {
                tmp = el.length - 1;
                hasAttributes = false;
            }
    
            from = beg + el.length;
    
            let isSingle = el[el.length - 2] === '/';
            let name = el.substring(1, tmp);
    
            if (!isSingle)
                current.push(name);
    
            if (!hasAttributes)
                continue;
    
            let match = el.match(/\w+\=\".*?\"/g);
            if (match === null)
                continue;
    
            let attr = {};
            let length = match.length;
    
            for (let i = 0; i < length; i++) {
                let index = match[i].indexOf('"');
                attr[match[i].substring(0, index - 1)] = match[i].substring(index + 1, match[i].length - 1);
            }
    
            obj[current.join('.') + (isSingle ? '.' + name : '') + '[]'] = attr;
        }
    
        return obj;
    }
    

    9. Astro

    /**
     * Check if a certain time is matching Astro name(s). 
     * Example use case: when turning on a light, you can use different colors depending on the 
     *                   current Astro time like 'sunrise', 'goldenHour'.
     * Version 1.0
     * @param {string|array} astroNames  A single name like 'sunset' as string, or an array of names,
     *                                   like ['goldenHour', 'sunsetStart', 'sunset', 'dusk']
     * @param {object} [dateTime]        Optional: A date object (new Date()). If omitted, we use current time.
     * @return {boolean}                 true if matching, false if not.
     */
    function isTimeInAstro(astroNames, dateTime=undefined) {
    
        if (!Array.isArray(astroNames)) astroNames = [astroNames]; // Put into array if it is a single string.
    
        const LOG_DEBUG = false;
    
        if ((dateTime != undefined) && !_isValidDate(dateTime)) { log('Provided parameter for dateTime is not a valid date.', 'error'); return; };
    
        let G_timeString = (dateTime == undefined) ? _dateToEuroStringTime(new Date()) : _dateToEuroStringTime(dateTime);
        if(LOG_DEBUG) log('[DEBUG] Time: ' + G_timeString);
    
        let strCurrAstroName = _getAstroName(G_timeString);
        if(LOG_DEBUG) log('[DEBUG] Current Astro: ' + strCurrAstroName);
        for (let lpVal of astroNames) {
            if (strCurrAstroName === lpVal) {
                return true;
            }
        }
        return false; // Kein Treffer, also geben wir false zurück.
    
        //////////////////////////////// End. Functions are following below. ////////////////////////////////
    
        /*******************************************************************************
         * Get Astro name for given time. Returns like 'sunrise', 'goldenHour' etc.
         *   Example (September):
         *   01:10 -> nadir; 05:05 -> nightEnd; 05:44 -> nauticalDawn; 06:21 -> dawn; 06:53 -> sunrise; 06:56 -> sunriseEnd; 07:34 -> goldenHourEnd; 
         *   13:10 -> solarNoon; 18:46 -> goldenHour; 19:23 -> sunsetStart; 19:27 -> sunset; 19:58 -> dusk; 20:35 -> nauticalDusk; 21:14 -> night
         * @param {string}   strTime    Zeit in 'HH:MM' oder 'HH:MM:SS', z.B. '19:23', '08:45:12'.
         * @return {string}             Astro name like 'sunrise', 'goldenHour' etc.
        ******************************************************************************/
        function _getAstroName(strTime) {
            
            strTime = strTime.substring(0, 5); // remove seconds
    
            let arrAstroArrays = _getAstroArrays();
            for (let i = 0; i <= arrAstroArrays[0].length; i++) {
                if (strTime < arrAstroArrays[0][i]) {
                    if (i === 0) {
                        // Hit on first element of array, so we return last element of array
                        return arrAstroArrays[1][arrAstroArrays[1].length - 1];
                    } else {
                        // We return the element -1
                        return arrAstroArrays[1][i-1];
                    }
                }
            }
            // We did not find anything, so it is the last element of the array
            return arrAstroArrays[1][arrAstroArrays[0].length - 1];
    
    
            /***********************************
             * Gibt ein Array aus 2 Arrays zurück
             * 1. Sortierte Liste der Uhrzeiten der Astrozeiten, z.B. ["01:20","05:13","05:53","06:31",....]
             * 2. Sortierte Liste der Astronamen, typischerweise: ["nadir","nightEnd","nauticalDawn","dawn", ...]
             **********************************/
            function _getAstroArrays() {
                let currDate = new Date();
                let suncalc = require('suncalc');
                if(_getSystemConfig('latitude') == '' || _getSystemConfig('longitude') == '') log('Latitude and/or Longitude is blank in ioBroker admin settings.', 'warn');
                let times = suncalc.getTimes(currDate, _getSystemConfig('latitude'), _getSystemConfig('longitude'));
                
                // Get all current Astro Times in arrays
                let astroTimes = [];
                let astroBoth = [];
                for (let t in times) {
                    let Hour = times[t].getHours();
                    let Minute = times[t].getMinutes();
                
                    if ( Hour < 10 ) { Hour = "0" + Hour; }
                    if ( Minute < 10 ) { Minute = "0" + Minute; }
                    let TimeString = Hour + ':' + Minute;
                
                    astroTimes.push(TimeString);
                    astroBoth.push(TimeString + "#" + t);
                    
                }
                astroTimes.sort();
                
                // We  bring the names in same sort order as the times
                // Supposed to result in: ["nadir","nightEnd","nauticalDawn","dawn","sunrise","sunriseEnd","goldenHourEnd","solarNoon","goldenHour","sunsetStart","sunset","dusk","nauticalDusk","night"]
                astroBoth.sort();
                let astroNames = [];
                for (let lpVal of astroBoth) {
                    astroNames.push(lpVal.substring(6));
                }    
                
                return [ astroTimes, astroNames ];
    
                /**
                 * Returns a value as configured in Administration Settings of ioBroker
                 * @param {string}  what     Options like: city, country, longitude, latitude, language, tempUnit, 
                 *                                         currency, dateFormat, isFloatComma, licenseConfirmed, 
                 *                                         defaultHistory, activeRepo, diag
                 *                           To see all options, use: log('All options: ' +  JSON.stringify(getObject('system.config').common));
                 * @return {string}          The option. Will be an empty string if value is not set.
                 */
                function _getSystemConfig(what) {
                    let config = getObject('system.config').common;
                    if (config[what] == undefined) {
                        log('Setting [' + what + '] not found in ioBroker admin settings.', 'warn');
                        return '';
                    }
                    return config[what];
                }
    
            }
    
        }
    
        // https://stackoverflow.com/questions/643782/
        function _isValidDate(date) {
            return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
        }
    
        /**
         * Converts a given date datatype into European date/time. E.g. '9:03pm and 17 seconds' -> '21:03:17'
         * @param   {object}   inputDate   Date created with "new Date()". If you want the current date, use "new Date()"
         * @return  {string}    Time in European format like '21:03:17'
         */
        function _dateToEuroStringTime(inputDate) {
            return _zeroPad(inputDate.getHours(), 2) + ':' + _zeroPad(inputDate.getMinutes(), 2) + ':' + _zeroPad(inputDate.getSeconds(), 2);
    
            // Fügt Vornullen zu einer Zahl hinzu, macht also z.B. aus 7 eine "007". 
            function _zeroPad(num, places) {
                let zero = places - num.toString().length + 1;
                return Array(+(zero > 0 && zero)).join("0") + num;        
            } 
        }
    
    }
    

    10. ioBroker


    Mit diesem Script bzw. dieser Funktion können States (Datenpunkte) unter 0_userdata.0 oder unter javascript.x angelegt werden.
    Dabei können mehrere States gleichzeitig angelegt werden. Sobald alle erfolgreich angelegt wurden, kann danach (per callback) ein beliebiger Code ausgeführt werden, also beispielsweise die Haupt-Funktion des Scripts.

    Function, mit Beschreibung in Deutsch): https://github.com/Mic-M/iobroker.createUserStates
    Support: https://forum.iobroker.net/topic/26839/

    /**
     * Returns a value as configured in Administration Settings of ioBroker
     * @param {string}  what     Options like: city, country, longitude, latitude, language, tempUnit, 
     *                                         currency, dateFormat, isFloatComma, licenseConfirmed, 
     *                                         defaultHistory, activeRepo, diag
     *                           To see all options, use: log('All options: ' +  JSON.stringify(getObject('system.config').common));
     * @return {string}          The option. Will be an empty string if value is not set.
     */
    function getSystemConfig(what) {
        let config = getObject('system.config').common;
        if (config[what] == undefined) {
            log('Setting [' + what + '] not found in ioBroker admin settings.', 'warn');
            return '';
        }
        return config[what];
    


    Hinweis (07.01.2019): Bislang gab es hier eine Function isState(), diese ist nun hinfällig, weil es mit existsState() nun (mind. ab JS-Adapter-Version 4.3.4, gg. früher schon) eine neue ioBroker-Funktion gibt, um zu prüfen, ob ein State (Datenpunkt) existiert. Beispiel:

    const STATE_ID = '0_userdata.0.LivingRoom.Lights.Sideboard.Brightness'
    if( existsState(STATE_ID) ) {
        log('Datenpunkt existiert');
    } else {
        log('Datenpunkt ist nicht vorhanden');
    }
    

    /**
     * Vor wie vielen Sekunden wurde ein State aktualisiert?
     * Per Default wird der Timestamp genommen. Durch Setzen von what auf 'lc' wird die letzte Änderung genommen.
     * @param {string}  stateId   Id zum State, z.B. 'fullybrowser.0.192_168_0_10.isFullyAlive'
     * @param {string} [what='ts'] Optional. 'ts' für timestamp (= Default), lc für lastchanged.
     * @return {number} Vergangene Anzahl an Sekunden, als der State zuletzt aktualisiert wurde
     */
    function stateLastUpdated(stateId, what) {
    
        if (what === undefined) what = 'ts';
        if(what !== 'ts' && what !== 'lc') what = 'ts';
    
        let dtNow = new Date();
        let tsNow = dtNow.getTime();
        let dtCheck = new Date(getState(stateId)[what]);
        let tsCheck = dtCheck.getTime();
    
        return Math.round((tsNow - tsCheck) / 1000); // Zeitdifferenz in Sekunden
    
    }
    

    /**
     * Adapter einschalten/neu starten oder ausschalten
     * Quelle: https://forum.iobroker.net/topic/24179/vorlage-hilfreiche-javascript-funktionen/
     * WICHTIG: In JavaScript-Adapter-Instanz Haken bei "setObject erlauben" aktivieren.
     * Version: 0.3 Mic
     * @param {string}    adapterInstancePath  Pfad zur Adapter-Instanz, z.B. "spotify-premium.0"
     * @param {boolean}   flag                 true für Einschalten oder Neustart (falls bereits eingeschaltet), false für Ausschalten
      * @param {object}  [callback]            Optional: a callback function.
      */
    function adapterOnOff(adapterInstancePath, flag, callback){
        const PATH = 'system.adapter.' + adapterInstancePath;
        let obj = getObject(PATH);
        obj.common['enabled'] = flag;  // Adapter einschalten/neu starten oder ausschalten
        setObject(PATH, obj, function(){
            if (typeof callback === 'function') { // execute if a function was provided to parameter callback
                return callback();
            }
        });
    }
    

    /**
     * Is a certain adapter up and running?
     * @param {string}   adapterState  Main state of adapter, e.g. 'hm-rpc.0'
     * @param {number}   [minUptime=0] Optional: minimum number of minutes the adapter is running.
     *                                 Default = 0 minutes, so the uptime will not be checked by default.
     *                                 If you provide a certain number of minutes, the function will return false if 
    *                                  if adapter is running less time than this number of minutes.
     * @return {boolean}               true if adapter is actively running yes, false if not.
     */
    function isAdapterAlive(adapterState, minUptime) {
        if(minUptime === undefined) minUptime = 0;
    
        let isAlive = false;
        if ( (getState('system.adapter.' + adapterState + '.alive').val) && (getState('system.adapter.' + adapterState + '.connected').val) ) {
            if( (getState('system.adapter.' + adapterState + '.uptime').val / 60) > minUptime ) {
                isAlive = true;
            }
        }
        return isAlive;
    }
    

    /**
     * Change VIS View
     * @param {string}   toView                 Projekt + '/' + Viewname (aus Datenpunkt vis.0.control.data übernehmen)
     * @param {string}   [instance='FFFFFFFF']  Optional: Instanz. Default ist 'FFFFFFFF', sollte das nicht gehen, dann Wert vom Vis, Menü Tools, Feld "Instanz ID" nehmen
     */
    function changeVisView(toView, instance){
        if (instance === undefined) instance = 'FFFFFFFF';
        let visCmd = '{"instance": "' + instance + '", "command": "changeView", "data": "' + toView + '"}';
        setState('vis.0.control.command', visCmd);
    }
    

    11. Weiteres für das Schreiben von Scripten

    /**
     * Retrieve values from a CONFIG variable, example:
     * const CONF = [{car: 'bmw', color: 'black', hp: '250'}, {car: 'audi', color: 'blue', hp: '190'}]
     * To get the color of the Audi, use: getConfigValuePerKey(CONF, 'car', 'audi', 'color')
     * To find out which car has 190 hp, use: getConfigValuePerKey(CONF, 'hp', '190', 'car')
     * @param {object}  config     The configuration variable/constant
     * @param {string}  key1       Key to look for.
     * @param {string}  key1Value  The value the key should have
     * @param {string}  key2       The key which value we return
     * @returns {any}    Returns the element's value, or number -1 of nothing found.
     */
    function getConfigValuePerKey(config, key1, key1Value, key2) {
        for (let lpConfDevice of config) {
            if ( lpConfDevice[key1] === key1Value ) {
                if (lpConfDevice[key2] === undefined) {
                    return -1;
                } else {
                    return lpConfDevice[key2];
                }
            }
        }
        return -1;
    }
    

    1 Antwort Letzte Antwort
    31
    • MicM Offline
      MicM Offline
      Mic
      Developer
      schrieb am zuletzt editiert von Mic
      #2

      So, habe noch ein paar Funktionen ergänzt, außerdem alle in Spoiler gepackt, somit sieht das schon mal deutlich übersichtlicher aus.
      Ich werde weiter ergänzen.. Ich hoffe, die Forumsoftware macht mir keinen Strich durch die Rechnung wegen zu langem Text im Beitrag :-) , aber dann teile ich auf oder lagere auf Github aus.

      Ich ergänze gerne auch hilfreiche Funktionen von Euch, bitte einfach hier posten. Diese sollten im ioBroker getestet sein und laufen, und wiederkehrend verwendbar sein, also nicht zugeschnitten auf einen bestimmten Adapter oder zu speziell.

      Als nächstes könnte man dann Functions vereinfachen/zusammenfassen, gerade unter "Datum/Zeit" finden sich da einige Kandidaten, die sehr ähnlich sind. Aber das ist auch der Vorteil hier beim sammeln, dann sieht man das gleich.

      1 Antwort Letzte Antwort
      0
      • MicM Offline
        MicM Offline
        Mic
        Developer
        schrieb am zuletzt editiert von Mic
        #3

        paar Sachen ergänzt...

        1 Antwort Letzte Antwort
        0
        • MicM Offline
          MicM Offline
          Mic
          Developer
          schrieb am zuletzt editiert von
          #4

          ein paar Funktionen nachgetragen...

          1 Antwort Letzte Antwort
          0
          • S Offline
            S Offline
            Superdad
            schrieb am zuletzt editiert von
            #5

            Vielen Dank für deine Arbeit!

            CCU3

            iOBroker auf IntelNUC Proxmox

            1 Antwort Letzte Antwort
            1
            • M Offline
              M Offline
              Marty56
              schrieb am zuletzt editiert von
              #6

              Große Klasse. Danke dafür. Sofort einen Bookmark gemacht!!

              HW:NUC (16 GB Ram)
              OS: Debian Bullseye, Promox V7, node v16.x npm 8.19.3

              1 Antwort Letzte Antwort
              1
              • L Offline
                L Offline
                leuchtturm
                schrieb am zuletzt editiert von leuchtturm
                #7

                Auch von mir ein herzliches Danke.
                War auf der Suche nach einer Funktion add Day to Date.
                Und schwupps schon gefunden 😎

                1 Antwort Letzte Antwort
                1
                • MicM Offline
                  MicM Offline
                  Mic
                  Developer
                  schrieb am zuletzt editiert von
                  #8

                  ein paar Funktionen ergänzt...

                  1 Antwort Letzte Antwort
                  0
                  • MicM Offline
                    MicM Offline
                    Mic
                    Developer
                    schrieb am zuletzt editiert von
                    #9

                    stateLastUpdated() ergänzt.

                    1 Antwort Letzte Antwort
                    0
                    • MicM Offline
                      MicM Offline
                      Mic
                      Developer
                      schrieb am zuletzt editiert von
                      #10

                      isState() durch existsState() ersetzt:
                      Hinweis (07.01.2019): Bislang gab es hier eine Function isState(), diese ist nun hinfällig, weil es mit existsState() nun (mind. ab JS-Adapter-Version 4.3.4, gg. früher schon) eine neue ioBroker-Funktion gibt, um zu prüfen, ob ein State (Datenpunkt) existiert. Beispiel:

                      1 Antwort Letzte Antwort
                      0
                      • MicM Offline
                        MicM Offline
                        Mic
                        Developer
                        schrieb am zuletzt editiert von
                        #11

                        createUserStates() ergänzt:

                        Mit diesem Script bzw. dieser Funktion können States (Datenpunkte) unter 0_userdata.0 oder unter javascript.x angelegt werden. Dabei können mehrere States gleichzeitig angelegt werden. Sobald alle erfolgreich angelegt wurden, kann danach (per callback) ein beliebiger Code ausgeführt werden, also beispielsweise die Haupt-Funktion des Scripts.

                        1 Antwort Letzte Antwort
                        0
                        • MicM Offline
                          MicM Offline
                          Mic
                          Developer
                          schrieb am zuletzt editiert von
                          #12

                          isTimeInAstro() und fileExistsSync() ergänzt.

                          1 Antwort Letzte Antwort
                          0
                          • MicM Offline
                            MicM Offline
                            Mic
                            Developer
                            schrieb am zuletzt editiert von
                            #13

                            Notiz an mich selbst:
                            json2table() hinzufügen, also Umwandlung JSON in HTML-Tabelle.
                            https://forum.iobroker.net/topic/32540/json-zu-html-und-in-datei-schreiben-ablegen

                            1 Antwort Letzte Antwort
                            0
                            • Matthias StübnerM Offline
                              Matthias StübnerM Offline
                              Matthias Stübner
                              schrieb am zuletzt editiert von
                              #14

                              Ich möchte dateToString(), selbiges wird aber als unbekannt markiert. Muss ich, und wenn ja was, irgendein zusätzliches Modul/Adapter laden?

                              MicM htreckslerH 2 Antworten Letzte Antwort
                              0
                              • Matthias StübnerM Matthias Stübner

                                Ich möchte dateToString(), selbiges wird aber als unbekannt markiert. Muss ich, und wenn ja was, irgendein zusätzliches Modul/Adapter laden?

                                MicM Offline
                                MicM Offline
                                Mic
                                Developer
                                schrieb am zuletzt editiert von Mic
                                #15

                                @Matthias-Stübner
                                Was meinst du genau mit "als unbekannt markiert"? Am besten bitte Logausgabe hier posten.
                                Du brauchst keine weiteren Adapter ö.ä. hierfür.

                                1 Antwort Letzte Antwort
                                0
                                • Matthias StübnerM Matthias Stübner

                                  Ich möchte dateToString(), selbiges wird aber als unbekannt markiert. Muss ich, und wenn ja was, irgendein zusätzliches Modul/Adapter laden?

                                  htreckslerH Offline
                                  htreckslerH Offline
                                  htrecksler
                                  Forum Testing
                                  schrieb am zuletzt editiert von
                                  #16

                                  @Matthias-Stübner das im Editor unterstrichen wird, kannst DU an der Stelle ignorieren.
                                  Es sollte dennoch wie erwartet funktionieren.

                                  Gruss Hermann

                                  ioBroker auf Proxmox (Debian) auf IntelNuc als Produktivsystem

                                  moelskiM 1 Antwort Letzte Antwort
                                  0
                                  • htreckslerH htrecksler

                                    @Matthias-Stübner das im Editor unterstrichen wird, kannst DU an der Stelle ignorieren.
                                    Es sollte dennoch wie erwartet funktionieren.

                                    moelskiM Offline
                                    moelskiM Offline
                                    moelski
                                    schrieb am zuletzt editiert von
                                    #17

                                    Danke für die Funktionen !

                                    Grüße Dominik

                                    1 Antwort Letzte Antwort
                                    0
                                    • AlCalzoneA Offline
                                      AlCalzoneA Offline
                                      AlCalzone
                                      Developer
                                      schrieb am zuletzt editiert von
                                      #18

                                      clearStr stimmt nicht mit seiner Beschreibung überein:

                                      > String(null)
                                      'null'
                                      

                                      Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                                      MicM 1 Antwort Letzte Antwort
                                      0
                                      • AlCalzoneA AlCalzone

                                        clearStr stimmt nicht mit seiner Beschreibung überein:

                                        > String(null)
                                        'null'
                                        
                                        MicM Offline
                                        MicM Offline
                                        Mic
                                        Developer
                                        schrieb am zuletzt editiert von Mic
                                        #19

                                        @AlCalzone
                                        Danke für den Hinweis, hab die Funktion jetzt ersatzlos entfernt :grinning:
                                        Ist so "generisch" eher nicht zu gebrauchen, weil z.B. andere Datentypen (wie number) auch nicht behandelt werden und je nach Einsatzzweck was unterschiedliches zu prüfen ist.

                                        Christoph1337C 1 Antwort Letzte Antwort
                                        0
                                        • MicM Mic

                                          @AlCalzone
                                          Danke für den Hinweis, hab die Funktion jetzt ersatzlos entfernt :grinning:
                                          Ist so "generisch" eher nicht zu gebrauchen, weil z.B. andere Datentypen (wie number) auch nicht behandelt werden und je nach Einsatzzweck was unterschiedliches zu prüfen ist.

                                          Christoph1337C Offline
                                          Christoph1337C Offline
                                          Christoph1337
                                          schrieb am zuletzt editiert von
                                          #20

                                          Moin zusammen,

                                          ich habe mal versucht ein paar der Funktionen bei mir einzufügen.

                                          Allerdings bekomme ich immer folgende Meldung:

                                          script.js.common.Array compile failed: at script.js.common.Array:256

                                          das komische. Das Script geht garnicht bis Zeile 256...

                                          Auch wenn ich dann alle Zeilen aus kommentiere habe ich dieses Problem.

                                          /**
                                           * Remove Duplicates from Array
                                           * Source - https://stackoverflow.com/questions/23237704/nodejs-how-to-remove-duplicates-from-array
                                           * @param {array} inputArray       Array to process
                                           * @return {array}  Array without duplicates.
                                           */
                                          
                                          function GlobalarrayRemoveDublicates(inputArray) {
                                              let uniqueArray;
                                              uniqueArray = inputArray.filter(function(elem, pos) {
                                                  return inputArray.indexOf(elem) == pos;
                                              });
                                              return uniqueArray;
                                          }
                                          
                                          /**
                                           * Clean Array: Removes all falsy values: undefined, null, 0, false, NaN and "" (empty string)
                                           * Source: https://stackoverflow.com/questions/281264/remove-empty-elements-from-an-array-in-javascript
                                           * @param {array} inputArray       Array to process
                                           * @return {array}  Cleaned array
                                           */
                                          /*
                                          function GlobalcleanArray(inputArray) {
                                            var newArray = [];
                                            for (let i = 0; i < inputArray.length; i++) {
                                              if (inputArray[i]) {
                                                newArray.push(inputArray[i]);
                                              }
                                            }
                                            return newArray;
                                          }
                                          */
                                          /**
                                           * Removing Array element(s) by input value. 
                                           * @param {array}   arr             the input array
                                           * @param {string}  valRemove       the value to be removed
                                           * @param {boolean} [exact=true]    OPTIONAL: default is true. if true, it must fully match. if false, it matches also if valRemove is part of element string
                                           * @return {array}  the array without the element(s)
                                           */
                                          /*
                                          function GlobalarrayRemoveElementsByValue(arr, valRemove, exact) {
                                           
                                              if (exact === undefined) exact = true;
                                           
                                              for ( let i = 0; i < arr.length; i++){ 
                                                  if (exact) {
                                                      if ( arr[i] === valRemove) {
                                                          arr.splice(i, 1);
                                                          i--; // required, see https://love2dev.com/blog/javascript-remove-from-array/
                                                      }
                                                  } else {
                                                      if (arr[i].indexOf(valRemove) != -1) {
                                                          arr.splice(i, 1);
                                                          i--; // see above
                                                      }
                                                  }
                                              }
                                              return arr;
                                          }
                                          */
                                          /**
                                           * Checks if Array or String is not undefined, null or empty.
                                           * 08-Sep-2019: added check for [ and ] to also catch arrays with empty strings.
                                           * @param inputVar - Input Array or String, Number, etc.
                                           * @return true if it is undefined/null/empty, false if it contains value(s)
                                           * Array or String containing just whitespaces or >'< or >"< or >[< or >]< is considered empty
                                           */
                                          /*
                                          function GlobalisLikeEmpty(inputVar) {
                                              if (typeof inputVar !== 'undefined' && inputVar !== null) {
                                                  let strTemp = JSON.stringify(inputVar);
                                                  strTemp = strTemp.replace(/\s+/g, ''); // remove all whitespaces
                                                  strTemp = strTemp.replace(/\"+/g, "");  // remove all >"<
                                                  strTemp = strTemp.replace(/\'+/g, "");  // remove all >'<
                                                  strTemp = strTemp.replace(/[+/g, "");  // remove all >[<
                                                  strTemp = strTemp.replace(/]+/g, "");  // remove all >]<
                                                  if (strTemp !== '') {
                                                      return false;
                                                  } else {
                                                      return true;
                                                  }
                                              } else {
                                                  return true;
                                              }
                                          }
                                          */
                                          
                                          Christoph1337C liv-in-skyL AlCalzoneA 3 Antworten Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          865

                                          Online

                                          32.4k

                                          Benutzer

                                          81.5k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe