Weiter zum Inhalt
  • Home
  • Aktuell
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • 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. ioBroker Allgemein
  4. Log-Einträge eines bestimmten Adapters filtern

NEWS

  • Monatsrückblick Juli / August 2026 ist online!
    BluefoxB
    Bluefox
    9
    1
    412

  • Der neue Monatsrückblick für Mai und Juni 2026 ist online!
    BluefoxB
    Bluefox
    8
    1
    1.3k

  • wichtiges UPDATE für controller 7.2.2 im stable
    HomoranH
    Homoran
    10
    1
    3.8k

Log-Einträge eines bestimmten Adapters filtern

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
log
20 Beiträge 5 Kommentatoren 1.5k Aufrufe 3 Beobachtet
  • Ä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.
  • R Offline
    R Offline
    Rico0079
    schrieb am zuletzt editiert von
    #3

    Hallo, Versuchs mal hiermit.

    /* -- do not edit following lines - START --
    {
      "debug": false,
      "verbose": false,
      "mtime": 1547059146
    }
    -- do not edit previous lines - END --*/
    /*******************************************************************************
     * ---------------------------
     * Log Script für ioBroker zum Aufbereiten des Logs für Visualisierungen (vis)
     * ---------------------------
     *
     * Das Script liest regelmäßig (einstellbar, z.B. alle 2 Minuten) die tägliche
     * Log-Datei des ioBrokers aus und setzt das Ergebnis in Datenpunkte, aufgeteilt
     * je nach Einstellung unten.
     * Neue Log-Einträge werden in den Datenpunkten regelmäßig ergänzt.
     * Es stehen auch JSON-Datenpunkte zur Verfügung, mit diesen kann im vis eine
     * Tabelle ausgegeben werden (z.B. über das Widget 'basic - Tabelle')-
     *
     * Aktuelle Version:    https://github.com/Mic-M/iobroker.logfile-script
     * Support:             https://forum.iobroker.net/viewtopic.php?f=21&t=15514
     *
     * Change Log:
     *  0.8.1 Mic - Fix: L_SORTrolla_ORDER_DESC was not defined (renamed constant name was not changed in config)
     *  0.8 Mic - Fix: Script caused a "file not found" error if executed right at or shortly after midnight.
     *  0.7 Mic - Fix: States "...clearDateTime" will not get an initial date value on first script start,
     *                 also fix for "on({id: ".
     *  0.6 Mic + Put 0.5.1 BETA into stable
     *          + New option L_APPLY_CSS. If true, it will add <span class='log-info'>xxx</span>
     *            to each log string. 'log-info' for level info, 'log-error' for error, etc.
     *            This makes it easy to format a JSON table with CSS.
     *  0.5.1 BETA Mic + New States "Clear JSON log ..." and "Clear JSON log - Date/Time ...".
     *                   When the button "Clear JSON log" is pushed, the current date/time
     *                   will be set into the date/time state. Once refreshed
     *                   (per schedule in the script, e.g. after 2 minutes), the JSON
     *                   will be cleaned and display just newer logs.
     *                   Use Case: In vis, you can now add a button "clear log" or
     *                   "Mark as read". If you hit the button, the log will be
     *                   cleared and just new log items will be displayed.
     *                   *** THIS IS STILL BEING TESTED *** therefore a beta release...
     *  0.5  Mic + New parameter 'clean' to remove certain strings
     *             from the log line.
     *           + New parameter 'columns' for JSON output to specify which columns
     *             to be shown, and in which order.
     *           + New state "JSONcount" to have the number of log lines in state
     *           - Fixed a few issues
     *  0.4  Mic - Bug fix: improved validation of log line consistency
     *  0.3  Mic + Added filtering and blacklist
     *           - Several fixes
     *  0.2  Mic - Bug fix: corrected wrong function name
     *  0.1  Mic * Initial release
     *
     *******************************************************************************/
    
    /*******************************************************************************
     * Konfiguration: Pfade
     ******************************************************************************/
    // Pfad, unter dem die States in den Objekten angelegt werden.
    //const L_STATE_PATH = 'javascript.0.Logs'+ instance + '.' + 'mylog';
    const L_STATE_PATH = 'javascript.0.Logs_fuer_VIS';
    
    // Pfad zu dem Log-Verzeichnis auf dem Linux-Rechner.
    // Der Standard-Pfad auf Raspberry: '/opt/iobroker/log/'.
    const L_LOG_PATH = '/opt/iobroker/log/';
    
    /*******************************************************************************
     * Konfiguration: Alle Logeinträge - Global
     ******************************************************************************/
    // Zahl: Maximale Anzahl der letzten Logeinträge in den Datenpunkten. Alle älteren werden entfernt.
    // Bitte nicht allzu viele behalten, denn das kostet Performance.
    const L_NO_OF_ENTRIES = 200;
    
    // Sortierung der Logeinträge: true für descending (absteigend, also neuester oben), oder false für ascending (aufsteigend, also ältester oben)
    // Empfohlen ist true, damit neueste Einträge immer oben stehen.
    const L_SORT_ORDER_DESC = true;
    
    // Wie oft sollen die Log-Datenpunkte aktualisiert werden? Benutze den "Cron"-Button oben rechts für komfortable Einstellung
    // Bitte nicht jede Sekunde laufen lassen, alle paar Minuten sollte locker reichen.
    const L_SCHEDULE  = "*/1 * * * *"; // alle 2 Minuten
    //const L_SCHEDULE  = "*/10 * * * * *"; // alle 2 Minuten
    
    
    
    
    // Blacklist - falls einer dieser Begriffe enthalten ist, dann wird der Log-Eintrag
    // nicht aufgenommen. Praktisch, um penetrante Logeinträge zu eliminieren.
    // Mindestens 3 Zeichen erforderlich, sonst wird es nicht berücksichtigt.
    // Datenpunkt-Inhalte bei Änderung ggf. vorher löschen, diese werden nicht nachträglich gefiltert.
    const L_BLACKLIST_GLOBAL = ['<==Disconnect system.user.admin from ::ffff:', '', '', ''];
    
    // Entferne zusätzliche Leerzeichen, Tab-Stops, Zeilenumbrüche
    // Wird empfohlen. Falls nicht gewünscht, auf false setzen.
    const L_CLEAN_LOG = true;
    
    /*******************************************************************************
     * Konfiguration: JSON-Log (für Ausgabe z.B. im vis)
     ******************************************************************************/
    // Datumsformat für JSON Log. Z.B. volles z.B. Datum mit 'yyyy-mm-dd HH:MM:SS' oder nur Uhrzeit mit "HH:MM:SS". Die Platzhalter yyyy, mm, dd usw.
    // werden jeweils ersetzt. yyyy = Jahr, mm = Monat, dd = Tag, HH = Stunde, MM = Minute, SS = Sekunde. Auf Groß- und Kleinschreibung achten!
    // Die Verbinder (-, :, Leerzeichen, etc.) können im Prinzip frei gewählt werden.
    // Beispiele: 'HH:MM:SS' für 19:37:25, 'HH:MM' für 19:37, 'mm.dd HH:MM' für '25.07. 19:37'
    //const L_DATE_FORMAT = 'HH:MM:SS';
    const L_DATE_FORMAT = 'HH:MM:SS';
    
    // Max. Anzahl Zeichen der Log-Meldung im JSON Log.
    const L_LEN = 200;
    
    // Zahl: Maximale Anzahl der letzten Logeinträge in den Datenpunkten. Alle älteren werden entfernt.
    // Speziell für das JSON-Log zur Visualisierung, hier brauchen wir ggf. weniger als für L_NO_OF_ENTRIES gesamt.
    const L_NO_OF_ENTRIES_JSON = 200;
    
    // Füge CSS-Klasse hinzu je nach Log-Level (error, warn, info, etc.), um Tabellen-Text zu formatieren.
    // Beispiel für Info: ersetzt "xxx" durch "<span class='log-info'>xxx</span>""
    // Analog für error: log-error, warn: log-warn, etc.
    // Beim Widget "basic - Table" im vis können im Reiter "CSS" z.B. folgende Zeilen hinzugefügt werden,
    // um Warnungen in oranger und Fehler in roter Farbe anzuzeigen.
    // .log-warn { color: orange; }
    // .log-error { color: red; }
    const L_APPLY_CSS = true;
    
    // L_APPLY_CSS wird nur für die Spalte "level" (also error, info) angewendet, aber nicht für die
    // restlichen Spalten wie Datum, Log-Eintrag, etc.
    // Falls alle Zeilen formatiert werden sollen: auf false setzen.
    const L_APPLY_CSS_LIMITED_TO_LEVEL = true;
    
    
    /*******************************************************************************
     * Konfiguration: Datenpunkte und Filter
     ******************************************************************************/
    // Dies ist das Herzstück dieses Scripts: hier werden die Datenpunkte
    // konfiguriert, die erstellt werden sollen. Hierbei können wir entsprechend
    // Filter setzen, also Wörter/Begriffe, die in Logeinträgen enthalten sein
    // sollen und in den Datenpunkten aufgenommen werden.
    //
    // id:         Hier Begriff ohne Leerzeichen, z.B. "error", "sonoff", etc.
    //             Die ID wird dann Teil der ID der Datenpunkte.
    // filter_all: ALLE Begriffe müssen in der Logzeile enthalten sein. Ist einer
    //             der Begriffe nicht enthalten, dann wird der komplette Logeintrag
    //             auch nicht übernommen.
    //             Leeres Array eingeben [] falls hier filtern nicht gewünscht.
    // filter_any: Mindestens einer der gelisteten Begriffe muss enthalten sein.
    //             Leeres Array eingeben [] falls hier filtern nicht gewünscht.
    // blacklist:  Wenn einer dieser Begriffe im Logeintrag enthalten ist,
    //             so wird der komplette Logeintrag nicht übernommen, egal was
    //             vorher in filter_all oder filter_any definiert ist.
    //             Mindestens 3 Zeichen erforderlich, sonst wird es nicht
    //             berücksichtigt.
    // clean:      Der Log-Eintrag wird um diese Zeichenfolgen bereinigt, d.h. diese
    //             werden entfernt, aber die restliche Zeile bleibt bestehen. Z.B.
    //             um unerwünschte Zeichenfolgen zu entfernen oder Log-Ausgaben
    //             zu kürzen.
    // columns:    Nur für JSON (für vis).
    //             Folgende Spalten gibt es: 'date','level','source','msg'
    //             Hier können einzelne Spalten entfernt oder die Reihenfolge
    //             verändert werden.
    //             Bitte keine anderen Werte eintragen.
    //
    // filter_all, filter_any und blacklist werden gleichzeitig ausgeführt.
    // Bei den Filtern bitte beachten: Datenpunkt-Inhalte bei Änderung ggf. vorher
    // löschen, diese werden nicht nachträglich gefiltert.
    //
    // Die Filter-Einträge können natürlich beliebig geändert und erweitert werden,
    // bitte aber den Aufbau beibehalten.
    //
    const L_FILTER = [
    //  {
    //    id:          'all',    // wir wollen hier alle Logeinträge, keine Filterung
    //    filter_all:  ['', ''], // wird ignoriert, wenn leer
    //    filter_any:  ['+++'], // wird ignoriert, wenn leer
    //    blacklist:   ['', ''], // wird ignoriert, wenn leer
    //    clean:       ['', '', ''], // wird ignoriert, wenn leer
    //    columns:     ['date','level','source','msg'],  // Spaltenreihenfolge für JSON (Tabelle in vis)
    //  },
    //  {
    //    id:          'debug',
    //    filter_all:  [' - debug: '], // nur Logeinträge mit Level 'debug'
    //    filter_any:  ['', ''],
    //    blacklist:   ['', ''],
    //    clean:       ['', '', ''],
    //    columns:     ['date','level','source','msg'],
    //  },
    //  {
    //    id:          'info',
    //    filter_all:  [' - info: '],  // nur Logeinträge mit Level 'info'
    //    filter_any:  ['', ''],
    //    blacklist:   ['', ''],
    //    clean:       ['', '', ''],
    //    columns:     ['date','level','source','msg'],
    //  },
    //  {
    //    id:          'warn',
    //    filter_all:  [' - warn: '],  // nur Logeinträge mit Level 'warn'
    //    filter_any:  ['', ''],
    //    blacklist:   ['', ''],
    //    clean:       ['', '', ''],
    //    columns:     ['date','level','source','msg'],
    //  },
    //  {
    //    id:          'error',
    //    filter_all:  [' - error: '],  // nur Logeinträge mit Level 'error'
    //    filter_any:  ['', ''],
    //    blacklist:   ['', ''],
    //    clean:       ['', '', ''],
    //    columns:     ['date','level','source','msg'],
    //  },
    //  {
    //   id:          'warnanderror',
    //    filter_all:  ['', ''],
    //    filter_any:  [' - error: ', ' - warn: '],
    //    blacklist:   [''],
    //    clean:       ['', '', ''],
    //    columns:     ['date','source','msg'],
    //  },
    
      {
        id:          'all',
        filter_all:  [''],
        filter_any:  [''],
        blacklist:   [''],
        clean:       [''],
        //clean:       ['system.','steckdosen.','sontiges.','licht.','script.js.java.wol.','script.js.java.shutdown.','script.js.smarthome.','rolladen.','javascript.0','info','+++ ',' +++','NAS_und_VMware.shutdown_WinNAS_v01:','adapter_starten_stoppen:','rolladen_tag_nacht:','script.js.java.wol.wol_winnas:','backup_erstellen:','briefkasten_v0_1: ','stufenbeleuchtung_v01: ','weihnachten: ','echo_stati: ','NAS_und_VMware.shutdown_synology_v0_1:','shutdown_synology_v0_1: ','weckradio: ','kueche_v0_2: ','schlafzimmer_v0_3: ','schlafzimmer_tv_v0_1: ','licht.weckzeit_v0_2: ','NAS_und_VMware.start_stop_esxp: ','wol_synology: ','steckdosen.ps4_lueftung_v0_2:','wol_daniel: ','NAS_und_VMware.wake_on_lan_v0_2: ','alexa_benachrichtigungen: ','anwesenheit: ','system_ctr_vis: ','reboot__skript: ','weckzeit_v0_2:','wol_winnas: ','wol_qnap_archiv: ','lichterkette_flur_v0_3: ','reboot_skript: ','briefkasten_tuerklingel_v0_1: ','shutdown_qnap-archiv_v0_1: '],
        columns:     ['date','msg'],
      },  
      
     
      
      
      
      // Beispiel für individuellen Eintrag. Hier wird Euer Hubschrauber-Landeplatz
      // überwacht :-) Wir wollen nur Einträge vom Adapter 'hubschr.0'.
      // Dabei sollen entweder Wetterwarnungen, Alarme, oder UFOs gemeldet werden.
      // Alles unter Windstärke "5 Bft" interessiert uns dabei nicht, daher haben
      // wir '0 Bft' bis '4 Bft' auf die Blackliste gesetzt.
      // Außerdem entfernen wir von der Log-Zeile die Zeichenfolgen '****', '!!!!'
      // und 'ufo gesichtet', der Rest bleibt aber bestehen.
      // Zudem haben wir unter columns die Spaltenreihenfolge geändert. 'level'
      // herausgenommen, und Quelle ganz vorne.
      //{
      //  id:          'hubschrauberlandeplatz',
      //  filter_all:  ['hubschr.0'],
    //    filter_any:  ['wetterwarnung', 'alarm', 'ufo'],
        //blacklist:   ['0 Bft', '1 Bft', '2 Bft', '3 Bft', '4 Bft'],
        //clean:       ['****', '!!!!', 'ufo gesichtet'],
        //columns:     ['level','date','msg'],
      //},
    
    ];
    
    
    
    /*******************************************************************************
     * Konfiguration: Konsolen-Ausgaben
     ******************************************************************************/
    // Auf true setzen, wenn zur Fehlersuche einige Meldungen ausgegeben werden sollen.
    // Ansonsten bitte auf false stellen.
    const LOG_DEBUG = false;
    
    // Auf true setzen, wenn ein paar Infos im Log ausgegeben werden dürfen, bei false bleiben die Infos weg.
    const LOG_INFO = true;
    
    /*******************************************************************************
     * Experten-Konfiguration
     ******************************************************************************/
    // Regex für die Aufteilung des Logs in 1-Datum/Zeit, 3-Level, 5-Quelle und 7-Logtext.
    // Ggf. anzupassen bei anderem Datumsformat im Log. Wir erwarten ein Format
    // wie '2018-07-22 12:45:02.769  - info: javascript.0 Stop script script.js.ScriptAbc'
    const REGEX_LOG = /([0-9_.\-:\s]*)(\s+\- )(silly|debug|info|warn|error|)(: )([a-z0-9.\-]*)(\s)(.*)/g;
    
    // Debug: Falls auf true, dann werden die Datenpunkte nicht ausgelesen, sondern von
    // der Log-Datei immer neu gesetzt.
    const DEBUG_IGNORE_STATES = false;
    
    // Leer lassen! Nur setzen, falls ein eigener Filename für das Logfile verwendet wird für Debug.
    const L_LOG_FILENAME = '';
    
    
    /*******************************************************************************
     * Ab hier nichts mehr ändern / Stop editing here!
     ******************************************************************************/
    
    /**
     * Executed on every script start. Also sets the schedule.
     */
    init();
    function init() {
    
        // Create states
        L_createStates();
    
        // Now we call the main update function. This is redundant since we set a schedule further below,
        // however it is useful if we change something in the script and save it, so that we see the changes
        // after 5 seconds and not after the time the schedule is set.
        // We use setTimeout() to execute 5s later and avoid error message on initial start if states not yet created.
        setTimeout(function() { L_UpdateLog(); }, 5000);
    
        // Schedule script accordingly.
        // We execute 30 seconds later since we called the function right before.
        setTimeout(function() {
            schedule(L_SCHEDULE, function () {  // apply schedule
               L_UpdateLog();
            });
        }, 30000);
    
        // Set current date to state if button is pressed
        for (var i = 0; i < L_FILTER.length; i++) {
            var strIDCleanFinal = L_STATE_PATH + '.' + 'log' + prepStateNameInclCapitalizeFirst(L_FILTER[i].id) + 'JSONclear';
            on({id: strIDCleanFinal, change: "any", val: true}, function(obj) {
                var currentDate = new Date();
                setState(obj.id + 'DateTime', currentDate.toString());
            }); // warning on the left can be ignored, we need a function here...
        }
    
    }
    
    /**
     * Main function. Process content of today's logfile (e.g. /opt/iobroker/log/iobroker.2018-07-19.log)
     */
    function L_UpdateLog() {
    
        // A couple warnings
        if (DEBUG_IGNORE_STATES) L_Log2('DEBUG_IGNORE_STATES is set to true!', "warn");
        if (L_LOG_FILENAME !== '') L_Log2('L_LOG_FILENAME is set: "' + L_LOG_FILENAME + '"', "warn");
    
        // Path and filename to log file
        var strLogPathFinal = L_LOG_PATH;
        if (strLogPathFinal.slice(-1) !== '/') strLogPathFinal = strLogPathFinal + '/';
        var strFullLogPath = strLogPathFinal + L_LOG_FILENAME;
        if (L_LOG_FILENAME === '') strFullLogPath = strLogPathFinal + 'iobroker.' + L_GetCurrentISODate() + '.log';
        if (LOG_DEBUG) L_Log('Path and Filename: ' + '>' + strFullLogPath + '<');
    
        // Reads the log file entry, result will be string in variable "data"
        var fs = require('fs');
        fs.readFile(strFullLogPath, 'utf8', function (err,data) {
            if (err) {
                // At midnight, the script will use the new log file of the day.
                // However, the server may not yet have it created, so we ignore the 'file not found error' for 3 hours.
                // This should be enough time for ioBroker until we get a log entry and therefore a log file.
                if(L_IsTimeInRange('00:00:00', '03:00:00')) {
                    if (LOG_DEBUG) L_Log('Midnight or right after, so a log file of the new day does not exist yet');
                    return; // exit function
                } else {
                    return L_Log2('Error when trying to read the log file, msg: ' + err, 'error'); // Exit function with error msg
                }
            }
    
            // get log entries into array, these are separated by new line in the file...
            var logArray = data.split(/\r?\n/);
    
            // We process each log entry line
    
            // We add one element per each filter to the Array ('all', 'error', etc.)
            var logArrayProcessed = [];
            for (var j = 0; j < L_FILTER.length; j++) {
                logArrayProcessed[L_FILTER[j].id] = '';
            }
            for (var i = 0; i < logArray.length; i++) {
                var loopElement = logArray[i];
    
                // Clean up
                loopElement = loopElement.replace(/\u001b\[.*?m/g, ''); // Remove color escapes - https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
                if (loopElement.substr(0,9) === 'undefined') loopElement = loopElement.substr(9,99999); // sometimes, a log line starts with the term "undefined", so we remove it.
                if (L_CLEAN_LOG) loopElement = loopElement.replace(/\s\s+/g, ' '); // Remove white space, tab stops, new line
    
                // Check against global blacklist
                if(L_StringContainsTerms(loopElement, L_BLACKLIST_GLOBAL, 'blacklist')) loopElement = '';
    
                /////////////////
                // Split log levels.
                ////////////////
                // We apply regex here. This will also eliminate all log lines without proper info
                // like date/time, log level, and entry.
                var arrSplitLogLine = L_SplitLogLine(loopElement, REGEX_LOG);
                if (arrSplitLogLine !== false) {
    
                    /////////////////
                    // We apply our filters.
                    /////////////////
                    if (L_IsValueEmptyNullUndefined(L_FILTER) === false) {
    
                        // Now let's iterate again over the filter array elements
                        // We check if both the "all" and "any" filters  apply. If yes, - and blacklist false - we add the log line.
                        for (var k = 0; k < L_FILTER.length; k++) {
                            if ( (L_StringContainsTerms(loopElement, L_FILTER[k].filter_all, 'every') === true)
                                && (L_StringContainsTerms(loopElement, L_FILTER[k].filter_any, 'some') === true)
                                && (L_StringContainsTerms(loopElement, L_FILTER[k].blacklist, 'blacklist') === false)
                                ){
                                    logArrayProcessed[L_FILTER[k].id] = logArrayProcessed[L_FILTER[k].id] + loopElement + "\n";
                            }
                            // Now we remove terms if desired
                            if (L_IsValueEmptyNullUndefined(L_FILTER[k].clean) === false) {
                                for (var lpTerm of L_FILTER[k].clean) {
                                    if (lpTerm !== '') {
                                        logArrayProcessed[L_FILTER[k].id] = logArrayProcessed[L_FILTER[k].id].replace(lpTerm, '');
                                    }
                                }
                            }
                        }
                    } // if
                } // if
    
            } // for loop
    
            // Process further
            L_processLogAndSetToState(logArrayProcessed);
    
            if (LOG_INFO) L_Log('Log-Datenpunkte aktualisiert');
    
    
        }); //  fs.readFile
    
    }
    
    
    
    /**
     * Further processes the log array
     */
    function L_processLogAndSetToState(arrayLogInput) {
    
        // Build log levels array and add filters (like 'all', 'alerts', etc.)
        var arrayFilterIds = [];
        for (var i = 0; i < L_FILTER.length; i++) {
            arrayFilterIds.push(L_FILTER[i].id); // each filter id into array
        }
    
        // Loop through the log filter ids
    
        for (var k = 0; k < arrayFilterIds.length; k++) {
    
            // Log filter id(all, error, etc.) = arrayFilterIds[k]
            // Content of Log Level = arrayLogInput[arrayFilterIds[k]]
            var strLoopLogContent = arrayLogInput[arrayFilterIds[k]];
    
            // Get full path to state
            var strStateFullPath = L_STATE_PATH + '.' + 'log' + prepStateNameInclCapitalizeFirst(arrayFilterIds[k]);
    
            // Get state contents of loop filter id and append it
            var strStateLogContent = getState(strStateFullPath).val;
            if (!DEBUG_IGNORE_STATES) {
                if (L_IsValueEmptyNullUndefined(strStateLogContent) === false) {
                    strLoopLogContent = strLoopLogContent + strStateLogContent; // "\n" not needed, always added above
                }
            }
    
            if (L_IsValueEmptyNullUndefined(strLoopLogContent) === false) {
                // Convert to array for easier handling
                var myArray = strLoopLogContent.split(/\r?\n/);
    
                // Remove duplicates
                myArray = L_arrayRemoveDuplicates(myArray);
    
                // Remove empty values
                myArray = L_cleanArray(myArray);
    
                // Sort array descending
                myArray = L_SortLogByDate(myArray, 'desc');
    
                // Separate ID for JSON
                var myArrayJSON = myArray;
    
                // This is to clear the log
                // Let's remove elements if current date in state "logXXXJSONclearDateTime" is greater than log date.
                var strDateFromState = getState(strStateFullPath + 'JSONclearDateTime').val;
                if (L_IsValueEmptyNullUndefined(strDateFromState) === false) {
                    if (strDateFromState !== 0) { // we set it to 0 via vis widget if we want to clear the state
                        myArrayJSON = L_clearArrayByDate(myArrayJSON, strDateFromState);
                    }
                }
    
                // Just keep the first x elements of the array
                myArray = myArray.slice(0, L_NO_OF_ENTRIES);
                myArrayJSON = myArrayJSON.slice(0, L_NO_OF_ENTRIES_JSON);
    
                // Sort ascending if desired
                if (!L_SORT_ORDER_DESC) {
                    myArray = myArray.reverse();
                    myArrayJSON = myArrayJSON.reverse();
                }
    
                // ** Finally set the states
    
                ///////////////////////////////
                // -1- Full Log, String, separated by "\n"
                ///////////////////////////////
                var strResult = myArray.join("\n");
                setState(strStateFullPath, strResult);
    
                ///////////////////////////////
                // -2- JSON, with elements date and msg
                ///////////////////////////////
    
                // Let's put together the JSON
                var jsonArr = [];
                for (var j = 0; j < myArrayJSON.length; j++) {
                    // +++
                    // We apply regex here to get 4 elements in array: datetime, level, source, message
                    // +++
                    var arrSplitLogLine = L_SplitLogLine(myArrayJSON[j], REGEX_LOG);
                    if (arrSplitLogLine !== false) {
                        var strLogMsg = arrSplitLogLine.message;
                        // Reduce the length for each log message per configuration
                        strLogMsg = strLogMsg.substr(0, L_LEN);
                        // ++++++
                        // Build the final Array
                        // ++++++
                        // We need this section to generate the JSON with the columns (which ones, and order) as specified in L_FILTER
    
                        var objectJSONentry = {}; // object (https://stackoverflow.com/a/13488998)
                        if (L_IsValueEmptyNullUndefined(L_FILTER[k].columns)) L_Log2('Columns not specified in L_FILTER', 'error');
                        // Prepare CSS
                        var strCSS1, strCSS2;
                        var strCSS1_level, strCSS2_level;
                        if (L_APPLY_CSS) {
                            strCSS1 = "<span class='log-" + arrSplitLogLine.level + "'>";
                            strCSS2 = '</span>';
                            strCSS1_level = strCSS1;
                            strCSS2_level = strCSS1;
                            if (L_APPLY_CSS_LIMITED_TO_LEVEL) {
                                strCSS1 = '';
                                strCSS2 = '';
                            }
                        }
    
                        for (var lpCol of L_FILTER[k].columns) {
                            switch (lpCol) {
                                case 'date' :
                                    objectJSONentry.date = strCSS1 + L_ReformatLogDate(arrSplitLogLine.datetime, L_DATE_FORMAT) + strCSS2;
                                    break;
                                case 'level' :
                                    objectJSONentry.level = strCSS1_level + arrSplitLogLine.level + strCSS2_level;
                                    break;
                                case 'source' :
                                    objectJSONentry.source = strCSS1 + arrSplitLogLine.source + strCSS2;
                                    break;
                                case 'msg' :
                                    objectJSONentry.msg = strCSS1 + strLogMsg + strCSS2;
                                    break;
                                default:
                                    //nothing;
                            }
                        }
                        // Ok, so now we have the JSON entry.
                        jsonArr.push(objectJSONentry);
                    }
    
                }
                if (L_IsValueEmptyNullUndefined(myArrayJSON) === false) {
                    setState(strStateFullPath + 'JSON', JSON.stringify(jsonArr));
                    setState(strStateFullPath + 'JSONcount', myArrayJSON.length);
                } else {
                    // Is empty here if for example L_clearArrayByDate had no hits
                    setState(strStateFullPath + 'JSON', '');
                    setState(strStateFullPath + 'JSONcount', 0);
                }
            } else {
                // No log available, so we clean it.
                setState(strStateFullPath, '');
                setState(strStateFullPath + 'JSON', '');
                setState(strStateFullPath + 'JSONcount', 0);
            }
        }
    }
    
    /**
     * Clear array: if strDate is greater or equal than log date, we remove the entire log entry
     */
    function L_clearArrayByDate(inputArray, strDate) {
        var dtState = new Date(strDate); // the date provided from the state
    
        var newArray = [];
        for (var lpLog of inputArray) {
            var dtLog = new Date(lpLog.substr(0,23));
            if (dtLog >= dtState) {
                newArray.push(lpLog);
            }
    
      }
      return newArray;
    }
    
    
    
    /**
     * Checks if the string provided contains either every or some terms.
     * @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 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
     * @source https://stackoverflow.com/questions/36283767/javascript-select-the-string-if-it-matches-multiple-words-in-array
     */
    function L_StringContainsTerms(strInput, arrayTerms, type) {
        if(type === 'blacklist') {
            if (Array.isArray(arrayTerms)) {
                var arrayTermsNew = [];
                for (var lpTerm of arrayTerms) {
                    if (lpTerm.length >= 3) {
                        arrayTermsNew.push(lpTerm);
                    }
                }
                if(L_IsValueEmptyNullUndefined(arrayTermsNew) === false) {
                    var 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') {
                    var bResultEvery = arrayTerms.every(function(word) {
                        return strInput.indexOf(word) > -1;
                    });
                    return bResultEvery;
                } else if(type === 'some') {
                    var 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
            }
        }
    }
    
    
    /**
     * Splits a given log line into an array with 4 elements.
     * @param {string} strLog   Log line like '2018-07-22 11:47:53.019  - info: javascript.0 script.js ...'
     * @param {string} strRegex RegEx
     * @param {boolean} validity check: true for yes, false for no
     * @return: Array with 4 elements: datetime (e.g. 2018-07-22 11:47:53.019),
     *          level (e.g. info), source (e.g. javascript.0)
     *          and message (e.g. script.js....)
     *          Returns FALSE if no match
     */
    function L_SplitLogLine(strLog, strRegex) {
    
        // At first we split into array
        var returnArray = [];
        var m;
        do {
            m = strRegex.exec(strLog);
            if (m) {
                returnArray.datetime = m[1];
                returnArray.level = m[3];
                returnArray.source = m[5];
                returnArray.message = m[7];
            }
        } while (m);
    
        // Now we check if we have valid entries we want
        if ((returnArray.datetime === undefined)
            || (returnArray.level === undefined)
            || (returnArray.source === undefined)
            || (returnArray.message === undefined)
        ){
            return false; // no valid hits
        }
    
        // We can return the array now, since it meets all requirements
        return returnArray;
    
    }
    
    
    
    
    /**
     * Create all States we need at this time.
     */
    function L_createStates() {
    
        var statesArray = [];
        if (L_IsValueEmptyNullUndefined(L_FILTER) === false) {
            for(var i = 0; i < L_FILTER.length; i++) {
                if (L_FILTER[i].id !== '') {
                    var strIDClean = prepStateNameInclCapitalizeFirst(L_FILTER[i].id);
                    if (LOG_DEBUG) L_Log('clean ID: ' + '>' + strIDClean + '<');
                    statesArray.push({ id:'log' + strIDClean, name:'Filtered Log - ' + strIDClean, type:"string", role: "log", def: ""});
                    statesArray.push({ id:'log' + strIDClean + 'JSON', name:'Filtered Log - ' + strIDClean + ' - JSON', type:"string", role: "log", def: ""});
                    statesArray.push({ id:'log' + strIDClean + 'JSONcount', name:'Filtered Log - Count of JSON ' + strIDClean, role: "log", type:"number", def: 0});
                    statesArray.push({ id:'log' + strIDClean + 'JSONclear', name:'Clear JSON log ' + strIDClean, role: "button", type:"boolean", def: false});
                    statesArray.push({ id:'log' + strIDClean + 'JSONclearDateTime', name:'Clear JSON log - Date/Time ' + strIDClean, role: "log", type:"string", def: ''});
                }
            }
        }
    
        for (var s=0; s < statesArray.length; s++) {
            createState(L_STATE_PATH + '.' + statesArray[s].id, {
                'name': statesArray[s].name,
                'desc': statesArray[s].name,
                'type': statesArray[s].type,
                'read': true,
                'write': true,
                'role': statesArray[s].role,
                'def': statesArray[s].def,
            });
        }
    }
    
    /**
     * Will just keep lower case letters, numbers, '-' and '_' and removes the rest
     * Also, capitalize first Letter.
     */
    function prepStateNameInclCapitalizeFirst(stringInput) {
        var strProcess = stringInput;
        strProcess = strProcess.replace(/([^a-z0-9_\-]+)/gi, '');
        strProcess = strProcess.toLowerCase();
        strProcess = strProcess.charAt(0).toUpperCase() + strProcess.slice(1);
        return strProcess;
    
    }
    
    /**
     * Clean Array: Will remove 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
     *
     */
    function L_cleanArray(inputArray) {
      var newArray = [];
      for (var 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
     */
    function L_arrayRemoveDuplicates(inputArray) {
        var uniqueArray;
        uniqueArray = inputArray.filter(function(elem, pos) {
            return inputArray.indexOf(elem) == pos;
        });
        return uniqueArray;
    }
    
    
    /**
     * Sorts the log array by date. We expect the first 23 chars of each element being a date in string format.
     * @param {array}   arrayInput
     * @param {string}  order        asc or desc for ascending or descending order
     */
    function L_SortLogByDate(arrayInput, order) {
        var result = arrayInput.sort(function(a,b){
                // Turn your strings into dates, and then subtract them
                // to get a value that is either negative, positive, or zero.
                a = new Date(a.substr(0,23));
                b = new Date(b.substr(0,23));
                if (order === "asc") {
                    return a - b;
                } else {
                    return b - a;
                }
    
        });
    
        return result;
    }
    
    
    
    /**
     * Returns the current date in ISO format "YYYY-MM-DD".
     * @return  {string}    Date in ISO format
     */
    function L_GetCurrentISODate() {
        var currDate = new Date();
        return currDate.getFullYear() + '-' + L_ZeroPad((currDate.getMonth() + 1), 2) + '-' + L_ZeroPad(currDate.getDate(), 2);
    }
    
    
    /**
     * Fügt Vornullen zu einer Zahl hinzu, macht also z.B. aus 7 eine "007".
     * 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 L_ZeroPad(num, places) {
        if (L_IsNumber(num)) {
            // isNumber will also be true for a string which is actually a number, like '123'.
            var zero = places - num.toString().length + 1;
            return Array(+(zero > 0 && zero)).join("0") + num;
        } else {
            // No number provided, so we through an eror
            L_Log2('Function [' + arguments.callee.toString().match(/function ([^\(]+)/)[1] + '] - no number/string provided', 'error');
        }
    
    }
    
    
    /**
     * Reformats a log date string accordingly
     * @param {date}    strDate   The date to convert
     * @param {string}  format      e.g. 'yyyy-mm-dd HH:MM:SS'.
     *
     */
    function L_ReformatLogDate(strDate, format) {
    
        var strResult = format;
        strResult = strResult.replace('yyyy', strDate.substr(0,4));
        strResult = strResult.replace('mm', strDate.substr(5,2));
        strResult = strResult.replace('dd', strDate.substr(8,2));
        strResult = strResult.replace('HH', strDate.substr(11,2));
        strResult = strResult.replace('MM', strDate.substr(14,2));
        strResult = strResult.replace('SS', strDate.substr(17,2));
    
        return strResult;
    
    }
    
    
    
    /**
     * Prüft ob Variableninhalt eine Zahl ist.
     * @param {any} Variable, die zu prüfen ist auf Zahl
     * @return true falls Zahl, false falls nicht.
     * 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
     */
    function L_IsNumber(n) {
        return /^-?[\d.]+(?:e-?\d+)?$/.test(n);
    }
    
    
    /**
     * Checks if Array or String is not undefined, null or empty.
     * @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 >"< is considered empty
     */
    function L_IsValueEmptyNullUndefined(inputVar) {
        if (typeof inputVar !== 'undefined' && inputVar !== null) {
            var strTemp = JSON.stringify(inputVar);
            strTemp = strTemp.replace(/\s+/g, ''); // remove all whitespaces
            strTemp = strTemp.replace(/\"+/g, "");  // remove all >"<
            strTemp = strTemp.replace(/\'+/g, "");  // remove all >'<
            if (strTemp !== '') {
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }
    
    
    /**
     * Logs a message
     * @param string strMessage - die Message
     * @param string strType - don't add if [info], use "warn" for [warn] and "error" for [error]
     */
    function L_Log(strMessage) {
        L_Log2(strMessage, 'info');
    }
    function L_Log2(strMessage, strType) {
        var strMsgFinal = '[L] ' + strMessage + '';
        if (strType === "error") {
            log(strMsgFinal, "error");
        } else if (strType === "warn") {
            log(strMsgFinal, "warn");
        } else {
            log(strMsgFinal, "info");
        }
    }
    
    
    
    /*********************************************
     * Checks wether the current date/time is within the range provided.
     * Source: https://forum.iobroker.net/viewtopic.php?t=1072#p8484
     * @param  string    strLower - a time as string, e.g. '20:00:00'
     * @param  string    strUpper - a time as string, e.g. '22:30:00'
     * @return boolean   true if current time is within range, false if not
     ********************************************/
    function L_IsTimeInRange(strLower, strUpper) {
        var now = new Date();
        var lower = addTime(strLower);
        var upper = addTime(strUpper);
        var inRange = false;
        if (upper > lower) {
            // opens and closes in same day
            inRange = (now >= lower && now <= upper) ? true : false;
        } else {
            // closes in the following day
            inRange = (now >= upper && now <= lower) ? false : true;
        }
        return inRange;
    
        // Additional function needed to get a date/time value of the current date with the time provided as string
        function addTime(strTime) {
            var time = strTime.split(':');
            var dNewDate = new Date();
            var d = new Date(dNewDate.getFullYear(), dNewDate.getMonth(), dNewDate.getDate());
            d.setHours(time[0]);
            d.setMinutes(time[1]);
            d.setSeconds(time[2]);
            return d;
        }
    
    }
    
    
    
    Dr. BakteriusD 1 Antwort Letzte Antwort
    0
    • R Rico0079

      Hallo, Versuchs mal hiermit.

      /* -- do not edit following lines - START --
      {
        "debug": false,
        "verbose": false,
        "mtime": 1547059146
      }
      -- do not edit previous lines - END --*/
      /*******************************************************************************
       * ---------------------------
       * Log Script für ioBroker zum Aufbereiten des Logs für Visualisierungen (vis)
       * ---------------------------
       *
       * Das Script liest regelmäßig (einstellbar, z.B. alle 2 Minuten) die tägliche
       * Log-Datei des ioBrokers aus und setzt das Ergebnis in Datenpunkte, aufgeteilt
       * je nach Einstellung unten.
       * Neue Log-Einträge werden in den Datenpunkten regelmäßig ergänzt.
       * Es stehen auch JSON-Datenpunkte zur Verfügung, mit diesen kann im vis eine
       * Tabelle ausgegeben werden (z.B. über das Widget 'basic - Tabelle')-
       *
       * Aktuelle Version:    https://github.com/Mic-M/iobroker.logfile-script
       * Support:             https://forum.iobroker.net/viewtopic.php?f=21&t=15514
       *
       * Change Log:
       *  0.8.1 Mic - Fix: L_SORTrolla_ORDER_DESC was not defined (renamed constant name was not changed in config)
       *  0.8 Mic - Fix: Script caused a "file not found" error if executed right at or shortly after midnight.
       *  0.7 Mic - Fix: States "...clearDateTime" will not get an initial date value on first script start,
       *                 also fix for "on({id: ".
       *  0.6 Mic + Put 0.5.1 BETA into stable
       *          + New option L_APPLY_CSS. If true, it will add <span class='log-info'>xxx</span>
       *            to each log string. 'log-info' for level info, 'log-error' for error, etc.
       *            This makes it easy to format a JSON table with CSS.
       *  0.5.1 BETA Mic + New States "Clear JSON log ..." and "Clear JSON log - Date/Time ...".
       *                   When the button "Clear JSON log" is pushed, the current date/time
       *                   will be set into the date/time state. Once refreshed
       *                   (per schedule in the script, e.g. after 2 minutes), the JSON
       *                   will be cleaned and display just newer logs.
       *                   Use Case: In vis, you can now add a button "clear log" or
       *                   "Mark as read". If you hit the button, the log will be
       *                   cleared and just new log items will be displayed.
       *                   *** THIS IS STILL BEING TESTED *** therefore a beta release...
       *  0.5  Mic + New parameter 'clean' to remove certain strings
       *             from the log line.
       *           + New parameter 'columns' for JSON output to specify which columns
       *             to be shown, and in which order.
       *           + New state "JSONcount" to have the number of log lines in state
       *           - Fixed a few issues
       *  0.4  Mic - Bug fix: improved validation of log line consistency
       *  0.3  Mic + Added filtering and blacklist
       *           - Several fixes
       *  0.2  Mic - Bug fix: corrected wrong function name
       *  0.1  Mic * Initial release
       *
       *******************************************************************************/
      
      /*******************************************************************************
       * Konfiguration: Pfade
       ******************************************************************************/
      // Pfad, unter dem die States in den Objekten angelegt werden.
      //const L_STATE_PATH = 'javascript.0.Logs'+ instance + '.' + 'mylog';
      const L_STATE_PATH = 'javascript.0.Logs_fuer_VIS';
      
      // Pfad zu dem Log-Verzeichnis auf dem Linux-Rechner.
      // Der Standard-Pfad auf Raspberry: '/opt/iobroker/log/'.
      const L_LOG_PATH = '/opt/iobroker/log/';
      
      /*******************************************************************************
       * Konfiguration: Alle Logeinträge - Global
       ******************************************************************************/
      // Zahl: Maximale Anzahl der letzten Logeinträge in den Datenpunkten. Alle älteren werden entfernt.
      // Bitte nicht allzu viele behalten, denn das kostet Performance.
      const L_NO_OF_ENTRIES = 200;
      
      // Sortierung der Logeinträge: true für descending (absteigend, also neuester oben), oder false für ascending (aufsteigend, also ältester oben)
      // Empfohlen ist true, damit neueste Einträge immer oben stehen.
      const L_SORT_ORDER_DESC = true;
      
      // Wie oft sollen die Log-Datenpunkte aktualisiert werden? Benutze den "Cron"-Button oben rechts für komfortable Einstellung
      // Bitte nicht jede Sekunde laufen lassen, alle paar Minuten sollte locker reichen.
      const L_SCHEDULE  = "*/1 * * * *"; // alle 2 Minuten
      //const L_SCHEDULE  = "*/10 * * * * *"; // alle 2 Minuten
      
      
      
      
      // Blacklist - falls einer dieser Begriffe enthalten ist, dann wird der Log-Eintrag
      // nicht aufgenommen. Praktisch, um penetrante Logeinträge zu eliminieren.
      // Mindestens 3 Zeichen erforderlich, sonst wird es nicht berücksichtigt.
      // Datenpunkt-Inhalte bei Änderung ggf. vorher löschen, diese werden nicht nachträglich gefiltert.
      const L_BLACKLIST_GLOBAL = ['<==Disconnect system.user.admin from ::ffff:', '', '', ''];
      
      // Entferne zusätzliche Leerzeichen, Tab-Stops, Zeilenumbrüche
      // Wird empfohlen. Falls nicht gewünscht, auf false setzen.
      const L_CLEAN_LOG = true;
      
      /*******************************************************************************
       * Konfiguration: JSON-Log (für Ausgabe z.B. im vis)
       ******************************************************************************/
      // Datumsformat für JSON Log. Z.B. volles z.B. Datum mit 'yyyy-mm-dd HH:MM:SS' oder nur Uhrzeit mit "HH:MM:SS". Die Platzhalter yyyy, mm, dd usw.
      // werden jeweils ersetzt. yyyy = Jahr, mm = Monat, dd = Tag, HH = Stunde, MM = Minute, SS = Sekunde. Auf Groß- und Kleinschreibung achten!
      // Die Verbinder (-, :, Leerzeichen, etc.) können im Prinzip frei gewählt werden.
      // Beispiele: 'HH:MM:SS' für 19:37:25, 'HH:MM' für 19:37, 'mm.dd HH:MM' für '25.07. 19:37'
      //const L_DATE_FORMAT = 'HH:MM:SS';
      const L_DATE_FORMAT = 'HH:MM:SS';
      
      // Max. Anzahl Zeichen der Log-Meldung im JSON Log.
      const L_LEN = 200;
      
      // Zahl: Maximale Anzahl der letzten Logeinträge in den Datenpunkten. Alle älteren werden entfernt.
      // Speziell für das JSON-Log zur Visualisierung, hier brauchen wir ggf. weniger als für L_NO_OF_ENTRIES gesamt.
      const L_NO_OF_ENTRIES_JSON = 200;
      
      // Füge CSS-Klasse hinzu je nach Log-Level (error, warn, info, etc.), um Tabellen-Text zu formatieren.
      // Beispiel für Info: ersetzt "xxx" durch "<span class='log-info'>xxx</span>""
      // Analog für error: log-error, warn: log-warn, etc.
      // Beim Widget "basic - Table" im vis können im Reiter "CSS" z.B. folgende Zeilen hinzugefügt werden,
      // um Warnungen in oranger und Fehler in roter Farbe anzuzeigen.
      // .log-warn { color: orange; }
      // .log-error { color: red; }
      const L_APPLY_CSS = true;
      
      // L_APPLY_CSS wird nur für die Spalte "level" (also error, info) angewendet, aber nicht für die
      // restlichen Spalten wie Datum, Log-Eintrag, etc.
      // Falls alle Zeilen formatiert werden sollen: auf false setzen.
      const L_APPLY_CSS_LIMITED_TO_LEVEL = true;
      
      
      /*******************************************************************************
       * Konfiguration: Datenpunkte und Filter
       ******************************************************************************/
      // Dies ist das Herzstück dieses Scripts: hier werden die Datenpunkte
      // konfiguriert, die erstellt werden sollen. Hierbei können wir entsprechend
      // Filter setzen, also Wörter/Begriffe, die in Logeinträgen enthalten sein
      // sollen und in den Datenpunkten aufgenommen werden.
      //
      // id:         Hier Begriff ohne Leerzeichen, z.B. "error", "sonoff", etc.
      //             Die ID wird dann Teil der ID der Datenpunkte.
      // filter_all: ALLE Begriffe müssen in der Logzeile enthalten sein. Ist einer
      //             der Begriffe nicht enthalten, dann wird der komplette Logeintrag
      //             auch nicht übernommen.
      //             Leeres Array eingeben [] falls hier filtern nicht gewünscht.
      // filter_any: Mindestens einer der gelisteten Begriffe muss enthalten sein.
      //             Leeres Array eingeben [] falls hier filtern nicht gewünscht.
      // blacklist:  Wenn einer dieser Begriffe im Logeintrag enthalten ist,
      //             so wird der komplette Logeintrag nicht übernommen, egal was
      //             vorher in filter_all oder filter_any definiert ist.
      //             Mindestens 3 Zeichen erforderlich, sonst wird es nicht
      //             berücksichtigt.
      // clean:      Der Log-Eintrag wird um diese Zeichenfolgen bereinigt, d.h. diese
      //             werden entfernt, aber die restliche Zeile bleibt bestehen. Z.B.
      //             um unerwünschte Zeichenfolgen zu entfernen oder Log-Ausgaben
      //             zu kürzen.
      // columns:    Nur für JSON (für vis).
      //             Folgende Spalten gibt es: 'date','level','source','msg'
      //             Hier können einzelne Spalten entfernt oder die Reihenfolge
      //             verändert werden.
      //             Bitte keine anderen Werte eintragen.
      //
      // filter_all, filter_any und blacklist werden gleichzeitig ausgeführt.
      // Bei den Filtern bitte beachten: Datenpunkt-Inhalte bei Änderung ggf. vorher
      // löschen, diese werden nicht nachträglich gefiltert.
      //
      // Die Filter-Einträge können natürlich beliebig geändert und erweitert werden,
      // bitte aber den Aufbau beibehalten.
      //
      const L_FILTER = [
      //  {
      //    id:          'all',    // wir wollen hier alle Logeinträge, keine Filterung
      //    filter_all:  ['', ''], // wird ignoriert, wenn leer
      //    filter_any:  ['+++'], // wird ignoriert, wenn leer
      //    blacklist:   ['', ''], // wird ignoriert, wenn leer
      //    clean:       ['', '', ''], // wird ignoriert, wenn leer
      //    columns:     ['date','level','source','msg'],  // Spaltenreihenfolge für JSON (Tabelle in vis)
      //  },
      //  {
      //    id:          'debug',
      //    filter_all:  [' - debug: '], // nur Logeinträge mit Level 'debug'
      //    filter_any:  ['', ''],
      //    blacklist:   ['', ''],
      //    clean:       ['', '', ''],
      //    columns:     ['date','level','source','msg'],
      //  },
      //  {
      //    id:          'info',
      //    filter_all:  [' - info: '],  // nur Logeinträge mit Level 'info'
      //    filter_any:  ['', ''],
      //    blacklist:   ['', ''],
      //    clean:       ['', '', ''],
      //    columns:     ['date','level','source','msg'],
      //  },
      //  {
      //    id:          'warn',
      //    filter_all:  [' - warn: '],  // nur Logeinträge mit Level 'warn'
      //    filter_any:  ['', ''],
      //    blacklist:   ['', ''],
      //    clean:       ['', '', ''],
      //    columns:     ['date','level','source','msg'],
      //  },
      //  {
      //    id:          'error',
      //    filter_all:  [' - error: '],  // nur Logeinträge mit Level 'error'
      //    filter_any:  ['', ''],
      //    blacklist:   ['', ''],
      //    clean:       ['', '', ''],
      //    columns:     ['date','level','source','msg'],
      //  },
      //  {
      //   id:          'warnanderror',
      //    filter_all:  ['', ''],
      //    filter_any:  [' - error: ', ' - warn: '],
      //    blacklist:   [''],
      //    clean:       ['', '', ''],
      //    columns:     ['date','source','msg'],
      //  },
      
        {
          id:          'all',
          filter_all:  [''],
          filter_any:  [''],
          blacklist:   [''],
          clean:       [''],
          //clean:       ['system.','steckdosen.','sontiges.','licht.','script.js.java.wol.','script.js.java.shutdown.','script.js.smarthome.','rolladen.','javascript.0','info','+++ ',' +++','NAS_und_VMware.shutdown_WinNAS_v01:','adapter_starten_stoppen:','rolladen_tag_nacht:','script.js.java.wol.wol_winnas:','backup_erstellen:','briefkasten_v0_1: ','stufenbeleuchtung_v01: ','weihnachten: ','echo_stati: ','NAS_und_VMware.shutdown_synology_v0_1:','shutdown_synology_v0_1: ','weckradio: ','kueche_v0_2: ','schlafzimmer_v0_3: ','schlafzimmer_tv_v0_1: ','licht.weckzeit_v0_2: ','NAS_und_VMware.start_stop_esxp: ','wol_synology: ','steckdosen.ps4_lueftung_v0_2:','wol_daniel: ','NAS_und_VMware.wake_on_lan_v0_2: ','alexa_benachrichtigungen: ','anwesenheit: ','system_ctr_vis: ','reboot__skript: ','weckzeit_v0_2:','wol_winnas: ','wol_qnap_archiv: ','lichterkette_flur_v0_3: ','reboot_skript: ','briefkasten_tuerklingel_v0_1: ','shutdown_qnap-archiv_v0_1: '],
          columns:     ['date','msg'],
        },  
        
       
        
        
        
        // Beispiel für individuellen Eintrag. Hier wird Euer Hubschrauber-Landeplatz
        // überwacht :-) Wir wollen nur Einträge vom Adapter 'hubschr.0'.
        // Dabei sollen entweder Wetterwarnungen, Alarme, oder UFOs gemeldet werden.
        // Alles unter Windstärke "5 Bft" interessiert uns dabei nicht, daher haben
        // wir '0 Bft' bis '4 Bft' auf die Blackliste gesetzt.
        // Außerdem entfernen wir von der Log-Zeile die Zeichenfolgen '****', '!!!!'
        // und 'ufo gesichtet', der Rest bleibt aber bestehen.
        // Zudem haben wir unter columns die Spaltenreihenfolge geändert. 'level'
        // herausgenommen, und Quelle ganz vorne.
        //{
        //  id:          'hubschrauberlandeplatz',
        //  filter_all:  ['hubschr.0'],
      //    filter_any:  ['wetterwarnung', 'alarm', 'ufo'],
          //blacklist:   ['0 Bft', '1 Bft', '2 Bft', '3 Bft', '4 Bft'],
          //clean:       ['****', '!!!!', 'ufo gesichtet'],
          //columns:     ['level','date','msg'],
        //},
      
      ];
      
      
      
      /*******************************************************************************
       * Konfiguration: Konsolen-Ausgaben
       ******************************************************************************/
      // Auf true setzen, wenn zur Fehlersuche einige Meldungen ausgegeben werden sollen.
      // Ansonsten bitte auf false stellen.
      const LOG_DEBUG = false;
      
      // Auf true setzen, wenn ein paar Infos im Log ausgegeben werden dürfen, bei false bleiben die Infos weg.
      const LOG_INFO = true;
      
      /*******************************************************************************
       * Experten-Konfiguration
       ******************************************************************************/
      // Regex für die Aufteilung des Logs in 1-Datum/Zeit, 3-Level, 5-Quelle und 7-Logtext.
      // Ggf. anzupassen bei anderem Datumsformat im Log. Wir erwarten ein Format
      // wie '2018-07-22 12:45:02.769  - info: javascript.0 Stop script script.js.ScriptAbc'
      const REGEX_LOG = /([0-9_.\-:\s]*)(\s+\- )(silly|debug|info|warn|error|)(: )([a-z0-9.\-]*)(\s)(.*)/g;
      
      // Debug: Falls auf true, dann werden die Datenpunkte nicht ausgelesen, sondern von
      // der Log-Datei immer neu gesetzt.
      const DEBUG_IGNORE_STATES = false;
      
      // Leer lassen! Nur setzen, falls ein eigener Filename für das Logfile verwendet wird für Debug.
      const L_LOG_FILENAME = '';
      
      
      /*******************************************************************************
       * Ab hier nichts mehr ändern / Stop editing here!
       ******************************************************************************/
      
      /**
       * Executed on every script start. Also sets the schedule.
       */
      init();
      function init() {
      
          // Create states
          L_createStates();
      
          // Now we call the main update function. This is redundant since we set a schedule further below,
          // however it is useful if we change something in the script and save it, so that we see the changes
          // after 5 seconds and not after the time the schedule is set.
          // We use setTimeout() to execute 5s later and avoid error message on initial start if states not yet created.
          setTimeout(function() { L_UpdateLog(); }, 5000);
      
          // Schedule script accordingly.
          // We execute 30 seconds later since we called the function right before.
          setTimeout(function() {
              schedule(L_SCHEDULE, function () {  // apply schedule
                 L_UpdateLog();
              });
          }, 30000);
      
          // Set current date to state if button is pressed
          for (var i = 0; i < L_FILTER.length; i++) {
              var strIDCleanFinal = L_STATE_PATH + '.' + 'log' + prepStateNameInclCapitalizeFirst(L_FILTER[i].id) + 'JSONclear';
              on({id: strIDCleanFinal, change: "any", val: true}, function(obj) {
                  var currentDate = new Date();
                  setState(obj.id + 'DateTime', currentDate.toString());
              }); // warning on the left can be ignored, we need a function here...
          }
      
      }
      
      /**
       * Main function. Process content of today's logfile (e.g. /opt/iobroker/log/iobroker.2018-07-19.log)
       */
      function L_UpdateLog() {
      
          // A couple warnings
          if (DEBUG_IGNORE_STATES) L_Log2('DEBUG_IGNORE_STATES is set to true!', "warn");
          if (L_LOG_FILENAME !== '') L_Log2('L_LOG_FILENAME is set: "' + L_LOG_FILENAME + '"', "warn");
      
          // Path and filename to log file
          var strLogPathFinal = L_LOG_PATH;
          if (strLogPathFinal.slice(-1) !== '/') strLogPathFinal = strLogPathFinal + '/';
          var strFullLogPath = strLogPathFinal + L_LOG_FILENAME;
          if (L_LOG_FILENAME === '') strFullLogPath = strLogPathFinal + 'iobroker.' + L_GetCurrentISODate() + '.log';
          if (LOG_DEBUG) L_Log('Path and Filename: ' + '>' + strFullLogPath + '<');
      
          // Reads the log file entry, result will be string in variable "data"
          var fs = require('fs');
          fs.readFile(strFullLogPath, 'utf8', function (err,data) {
              if (err) {
                  // At midnight, the script will use the new log file of the day.
                  // However, the server may not yet have it created, so we ignore the 'file not found error' for 3 hours.
                  // This should be enough time for ioBroker until we get a log entry and therefore a log file.
                  if(L_IsTimeInRange('00:00:00', '03:00:00')) {
                      if (LOG_DEBUG) L_Log('Midnight or right after, so a log file of the new day does not exist yet');
                      return; // exit function
                  } else {
                      return L_Log2('Error when trying to read the log file, msg: ' + err, 'error'); // Exit function with error msg
                  }
              }
      
              // get log entries into array, these are separated by new line in the file...
              var logArray = data.split(/\r?\n/);
      
              // We process each log entry line
      
              // We add one element per each filter to the Array ('all', 'error', etc.)
              var logArrayProcessed = [];
              for (var j = 0; j < L_FILTER.length; j++) {
                  logArrayProcessed[L_FILTER[j].id] = '';
              }
              for (var i = 0; i < logArray.length; i++) {
                  var loopElement = logArray[i];
      
                  // Clean up
                  loopElement = loopElement.replace(/\u001b\[.*?m/g, ''); // Remove color escapes - https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
                  if (loopElement.substr(0,9) === 'undefined') loopElement = loopElement.substr(9,99999); // sometimes, a log line starts with the term "undefined", so we remove it.
                  if (L_CLEAN_LOG) loopElement = loopElement.replace(/\s\s+/g, ' '); // Remove white space, tab stops, new line
      
                  // Check against global blacklist
                  if(L_StringContainsTerms(loopElement, L_BLACKLIST_GLOBAL, 'blacklist')) loopElement = '';
      
                  /////////////////
                  // Split log levels.
                  ////////////////
                  // We apply regex here. This will also eliminate all log lines without proper info
                  // like date/time, log level, and entry.
                  var arrSplitLogLine = L_SplitLogLine(loopElement, REGEX_LOG);
                  if (arrSplitLogLine !== false) {
      
                      /////////////////
                      // We apply our filters.
                      /////////////////
                      if (L_IsValueEmptyNullUndefined(L_FILTER) === false) {
      
                          // Now let's iterate again over the filter array elements
                          // We check if both the "all" and "any" filters  apply. If yes, - and blacklist false - we add the log line.
                          for (var k = 0; k < L_FILTER.length; k++) {
                              if ( (L_StringContainsTerms(loopElement, L_FILTER[k].filter_all, 'every') === true)
                                  && (L_StringContainsTerms(loopElement, L_FILTER[k].filter_any, 'some') === true)
                                  && (L_StringContainsTerms(loopElement, L_FILTER[k].blacklist, 'blacklist') === false)
                                  ){
                                      logArrayProcessed[L_FILTER[k].id] = logArrayProcessed[L_FILTER[k].id] + loopElement + "\n";
                              }
                              // Now we remove terms if desired
                              if (L_IsValueEmptyNullUndefined(L_FILTER[k].clean) === false) {
                                  for (var lpTerm of L_FILTER[k].clean) {
                                      if (lpTerm !== '') {
                                          logArrayProcessed[L_FILTER[k].id] = logArrayProcessed[L_FILTER[k].id].replace(lpTerm, '');
                                      }
                                  }
                              }
                          }
                      } // if
                  } // if
      
              } // for loop
      
              // Process further
              L_processLogAndSetToState(logArrayProcessed);
      
              if (LOG_INFO) L_Log('Log-Datenpunkte aktualisiert');
      
      
          }); //  fs.readFile
      
      }
      
      
      
      /**
       * Further processes the log array
       */
      function L_processLogAndSetToState(arrayLogInput) {
      
          // Build log levels array and add filters (like 'all', 'alerts', etc.)
          var arrayFilterIds = [];
          for (var i = 0; i < L_FILTER.length; i++) {
              arrayFilterIds.push(L_FILTER[i].id); // each filter id into array
          }
      
          // Loop through the log filter ids
      
          for (var k = 0; k < arrayFilterIds.length; k++) {
      
              // Log filter id(all, error, etc.) = arrayFilterIds[k]
              // Content of Log Level = arrayLogInput[arrayFilterIds[k]]
              var strLoopLogContent = arrayLogInput[arrayFilterIds[k]];
      
              // Get full path to state
              var strStateFullPath = L_STATE_PATH + '.' + 'log' + prepStateNameInclCapitalizeFirst(arrayFilterIds[k]);
      
              // Get state contents of loop filter id and append it
              var strStateLogContent = getState(strStateFullPath).val;
              if (!DEBUG_IGNORE_STATES) {
                  if (L_IsValueEmptyNullUndefined(strStateLogContent) === false) {
                      strLoopLogContent = strLoopLogContent + strStateLogContent; // "\n" not needed, always added above
                  }
              }
      
              if (L_IsValueEmptyNullUndefined(strLoopLogContent) === false) {
                  // Convert to array for easier handling
                  var myArray = strLoopLogContent.split(/\r?\n/);
      
                  // Remove duplicates
                  myArray = L_arrayRemoveDuplicates(myArray);
      
                  // Remove empty values
                  myArray = L_cleanArray(myArray);
      
                  // Sort array descending
                  myArray = L_SortLogByDate(myArray, 'desc');
      
                  // Separate ID for JSON
                  var myArrayJSON = myArray;
      
                  // This is to clear the log
                  // Let's remove elements if current date in state "logXXXJSONclearDateTime" is greater than log date.
                  var strDateFromState = getState(strStateFullPath + 'JSONclearDateTime').val;
                  if (L_IsValueEmptyNullUndefined(strDateFromState) === false) {
                      if (strDateFromState !== 0) { // we set it to 0 via vis widget if we want to clear the state
                          myArrayJSON = L_clearArrayByDate(myArrayJSON, strDateFromState);
                      }
                  }
      
                  // Just keep the first x elements of the array
                  myArray = myArray.slice(0, L_NO_OF_ENTRIES);
                  myArrayJSON = myArrayJSON.slice(0, L_NO_OF_ENTRIES_JSON);
      
                  // Sort ascending if desired
                  if (!L_SORT_ORDER_DESC) {
                      myArray = myArray.reverse();
                      myArrayJSON = myArrayJSON.reverse();
                  }
      
                  // ** Finally set the states
      
                  ///////////////////////////////
                  // -1- Full Log, String, separated by "\n"
                  ///////////////////////////////
                  var strResult = myArray.join("\n");
                  setState(strStateFullPath, strResult);
      
                  ///////////////////////////////
                  // -2- JSON, with elements date and msg
                  ///////////////////////////////
      
                  // Let's put together the JSON
                  var jsonArr = [];
                  for (var j = 0; j < myArrayJSON.length; j++) {
                      // +++
                      // We apply regex here to get 4 elements in array: datetime, level, source, message
                      // +++
                      var arrSplitLogLine = L_SplitLogLine(myArrayJSON[j], REGEX_LOG);
                      if (arrSplitLogLine !== false) {
                          var strLogMsg = arrSplitLogLine.message;
                          // Reduce the length for each log message per configuration
                          strLogMsg = strLogMsg.substr(0, L_LEN);
                          // ++++++
                          // Build the final Array
                          // ++++++
                          // We need this section to generate the JSON with the columns (which ones, and order) as specified in L_FILTER
      
                          var objectJSONentry = {}; // object (https://stackoverflow.com/a/13488998)
                          if (L_IsValueEmptyNullUndefined(L_FILTER[k].columns)) L_Log2('Columns not specified in L_FILTER', 'error');
                          // Prepare CSS
                          var strCSS1, strCSS2;
                          var strCSS1_level, strCSS2_level;
                          if (L_APPLY_CSS) {
                              strCSS1 = "<span class='log-" + arrSplitLogLine.level + "'>";
                              strCSS2 = '</span>';
                              strCSS1_level = strCSS1;
                              strCSS2_level = strCSS1;
                              if (L_APPLY_CSS_LIMITED_TO_LEVEL) {
                                  strCSS1 = '';
                                  strCSS2 = '';
                              }
                          }
      
                          for (var lpCol of L_FILTER[k].columns) {
                              switch (lpCol) {
                                  case 'date' :
                                      objectJSONentry.date = strCSS1 + L_ReformatLogDate(arrSplitLogLine.datetime, L_DATE_FORMAT) + strCSS2;
                                      break;
                                  case 'level' :
                                      objectJSONentry.level = strCSS1_level + arrSplitLogLine.level + strCSS2_level;
                                      break;
                                  case 'source' :
                                      objectJSONentry.source = strCSS1 + arrSplitLogLine.source + strCSS2;
                                      break;
                                  case 'msg' :
                                      objectJSONentry.msg = strCSS1 + strLogMsg + strCSS2;
                                      break;
                                  default:
                                      //nothing;
                              }
                          }
                          // Ok, so now we have the JSON entry.
                          jsonArr.push(objectJSONentry);
                      }
      
                  }
                  if (L_IsValueEmptyNullUndefined(myArrayJSON) === false) {
                      setState(strStateFullPath + 'JSON', JSON.stringify(jsonArr));
                      setState(strStateFullPath + 'JSONcount', myArrayJSON.length);
                  } else {
                      // Is empty here if for example L_clearArrayByDate had no hits
                      setState(strStateFullPath + 'JSON', '');
                      setState(strStateFullPath + 'JSONcount', 0);
                  }
              } else {
                  // No log available, so we clean it.
                  setState(strStateFullPath, '');
                  setState(strStateFullPath + 'JSON', '');
                  setState(strStateFullPath + 'JSONcount', 0);
              }
          }
      }
      
      /**
       * Clear array: if strDate is greater or equal than log date, we remove the entire log entry
       */
      function L_clearArrayByDate(inputArray, strDate) {
          var dtState = new Date(strDate); // the date provided from the state
      
          var newArray = [];
          for (var lpLog of inputArray) {
              var dtLog = new Date(lpLog.substr(0,23));
              if (dtLog >= dtState) {
                  newArray.push(lpLog);
              }
      
        }
        return newArray;
      }
      
      
      
      /**
       * Checks if the string provided contains either every or some terms.
       * @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 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
       * @source https://stackoverflow.com/questions/36283767/javascript-select-the-string-if-it-matches-multiple-words-in-array
       */
      function L_StringContainsTerms(strInput, arrayTerms, type) {
          if(type === 'blacklist') {
              if (Array.isArray(arrayTerms)) {
                  var arrayTermsNew = [];
                  for (var lpTerm of arrayTerms) {
                      if (lpTerm.length >= 3) {
                          arrayTermsNew.push(lpTerm);
                      }
                  }
                  if(L_IsValueEmptyNullUndefined(arrayTermsNew) === false) {
                      var 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') {
                      var bResultEvery = arrayTerms.every(function(word) {
                          return strInput.indexOf(word) > -1;
                      });
                      return bResultEvery;
                  } else if(type === 'some') {
                      var 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
              }
          }
      }
      
      
      /**
       * Splits a given log line into an array with 4 elements.
       * @param {string} strLog   Log line like '2018-07-22 11:47:53.019  - info: javascript.0 script.js ...'
       * @param {string} strRegex RegEx
       * @param {boolean} validity check: true for yes, false for no
       * @return: Array with 4 elements: datetime (e.g. 2018-07-22 11:47:53.019),
       *          level (e.g. info), source (e.g. javascript.0)
       *          and message (e.g. script.js....)
       *          Returns FALSE if no match
       */
      function L_SplitLogLine(strLog, strRegex) {
      
          // At first we split into array
          var returnArray = [];
          var m;
          do {
              m = strRegex.exec(strLog);
              if (m) {
                  returnArray.datetime = m[1];
                  returnArray.level = m[3];
                  returnArray.source = m[5];
                  returnArray.message = m[7];
              }
          } while (m);
      
          // Now we check if we have valid entries we want
          if ((returnArray.datetime === undefined)
              || (returnArray.level === undefined)
              || (returnArray.source === undefined)
              || (returnArray.message === undefined)
          ){
              return false; // no valid hits
          }
      
          // We can return the array now, since it meets all requirements
          return returnArray;
      
      }
      
      
      
      
      /**
       * Create all States we need at this time.
       */
      function L_createStates() {
      
          var statesArray = [];
          if (L_IsValueEmptyNullUndefined(L_FILTER) === false) {
              for(var i = 0; i < L_FILTER.length; i++) {
                  if (L_FILTER[i].id !== '') {
                      var strIDClean = prepStateNameInclCapitalizeFirst(L_FILTER[i].id);
                      if (LOG_DEBUG) L_Log('clean ID: ' + '>' + strIDClean + '<');
                      statesArray.push({ id:'log' + strIDClean, name:'Filtered Log - ' + strIDClean, type:"string", role: "log", def: ""});
                      statesArray.push({ id:'log' + strIDClean + 'JSON', name:'Filtered Log - ' + strIDClean + ' - JSON', type:"string", role: "log", def: ""});
                      statesArray.push({ id:'log' + strIDClean + 'JSONcount', name:'Filtered Log - Count of JSON ' + strIDClean, role: "log", type:"number", def: 0});
                      statesArray.push({ id:'log' + strIDClean + 'JSONclear', name:'Clear JSON log ' + strIDClean, role: "button", type:"boolean", def: false});
                      statesArray.push({ id:'log' + strIDClean + 'JSONclearDateTime', name:'Clear JSON log - Date/Time ' + strIDClean, role: "log", type:"string", def: ''});
                  }
              }
          }
      
          for (var s=0; s < statesArray.length; s++) {
              createState(L_STATE_PATH + '.' + statesArray[s].id, {
                  'name': statesArray[s].name,
                  'desc': statesArray[s].name,
                  'type': statesArray[s].type,
                  'read': true,
                  'write': true,
                  'role': statesArray[s].role,
                  'def': statesArray[s].def,
              });
          }
      }
      
      /**
       * Will just keep lower case letters, numbers, '-' and '_' and removes the rest
       * Also, capitalize first Letter.
       */
      function prepStateNameInclCapitalizeFirst(stringInput) {
          var strProcess = stringInput;
          strProcess = strProcess.replace(/([^a-z0-9_\-]+)/gi, '');
          strProcess = strProcess.toLowerCase();
          strProcess = strProcess.charAt(0).toUpperCase() + strProcess.slice(1);
          return strProcess;
      
      }
      
      /**
       * Clean Array: Will remove 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
       *
       */
      function L_cleanArray(inputArray) {
        var newArray = [];
        for (var 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
       */
      function L_arrayRemoveDuplicates(inputArray) {
          var uniqueArray;
          uniqueArray = inputArray.filter(function(elem, pos) {
              return inputArray.indexOf(elem) == pos;
          });
          return uniqueArray;
      }
      
      
      /**
       * Sorts the log array by date. We expect the first 23 chars of each element being a date in string format.
       * @param {array}   arrayInput
       * @param {string}  order        asc or desc for ascending or descending order
       */
      function L_SortLogByDate(arrayInput, order) {
          var result = arrayInput.sort(function(a,b){
                  // Turn your strings into dates, and then subtract them
                  // to get a value that is either negative, positive, or zero.
                  a = new Date(a.substr(0,23));
                  b = new Date(b.substr(0,23));
                  if (order === "asc") {
                      return a - b;
                  } else {
                      return b - a;
                  }
      
          });
      
          return result;
      }
      
      
      
      /**
       * Returns the current date in ISO format "YYYY-MM-DD".
       * @return  {string}    Date in ISO format
       */
      function L_GetCurrentISODate() {
          var currDate = new Date();
          return currDate.getFullYear() + '-' + L_ZeroPad((currDate.getMonth() + 1), 2) + '-' + L_ZeroPad(currDate.getDate(), 2);
      }
      
      
      /**
       * Fügt Vornullen zu einer Zahl hinzu, macht also z.B. aus 7 eine "007".
       * 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 L_ZeroPad(num, places) {
          if (L_IsNumber(num)) {
              // isNumber will also be true for a string which is actually a number, like '123'.
              var zero = places - num.toString().length + 1;
              return Array(+(zero > 0 && zero)).join("0") + num;
          } else {
              // No number provided, so we through an eror
              L_Log2('Function [' + arguments.callee.toString().match(/function ([^\(]+)/)[1] + '] - no number/string provided', 'error');
          }
      
      }
      
      
      /**
       * Reformats a log date string accordingly
       * @param {date}    strDate   The date to convert
       * @param {string}  format      e.g. 'yyyy-mm-dd HH:MM:SS'.
       *
       */
      function L_ReformatLogDate(strDate, format) {
      
          var strResult = format;
          strResult = strResult.replace('yyyy', strDate.substr(0,4));
          strResult = strResult.replace('mm', strDate.substr(5,2));
          strResult = strResult.replace('dd', strDate.substr(8,2));
          strResult = strResult.replace('HH', strDate.substr(11,2));
          strResult = strResult.replace('MM', strDate.substr(14,2));
          strResult = strResult.replace('SS', strDate.substr(17,2));
      
          return strResult;
      
      }
      
      
      
      /**
       * Prüft ob Variableninhalt eine Zahl ist.
       * @param {any} Variable, die zu prüfen ist auf Zahl
       * @return true falls Zahl, false falls nicht.
       * 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
       */
      function L_IsNumber(n) {
          return /^-?[\d.]+(?:e-?\d+)?$/.test(n);
      }
      
      
      /**
       * Checks if Array or String is not undefined, null or empty.
       * @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 >"< is considered empty
       */
      function L_IsValueEmptyNullUndefined(inputVar) {
          if (typeof inputVar !== 'undefined' && inputVar !== null) {
              var strTemp = JSON.stringify(inputVar);
              strTemp = strTemp.replace(/\s+/g, ''); // remove all whitespaces
              strTemp = strTemp.replace(/\"+/g, "");  // remove all >"<
              strTemp = strTemp.replace(/\'+/g, "");  // remove all >'<
              if (strTemp !== '') {
                  return false;
              } else {
                  return true;
              }
          } else {
              return true;
          }
      }
      
      
      /**
       * Logs a message
       * @param string strMessage - die Message
       * @param string strType - don't add if [info], use "warn" for [warn] and "error" for [error]
       */
      function L_Log(strMessage) {
          L_Log2(strMessage, 'info');
      }
      function L_Log2(strMessage, strType) {
          var strMsgFinal = '[L] ' + strMessage + '';
          if (strType === "error") {
              log(strMsgFinal, "error");
          } else if (strType === "warn") {
              log(strMsgFinal, "warn");
          } else {
              log(strMsgFinal, "info");
          }
      }
      
      
      
      /*********************************************
       * Checks wether the current date/time is within the range provided.
       * Source: https://forum.iobroker.net/viewtopic.php?t=1072#p8484
       * @param  string    strLower - a time as string, e.g. '20:00:00'
       * @param  string    strUpper - a time as string, e.g. '22:30:00'
       * @return boolean   true if current time is within range, false if not
       ********************************************/
      function L_IsTimeInRange(strLower, strUpper) {
          var now = new Date();
          var lower = addTime(strLower);
          var upper = addTime(strUpper);
          var inRange = false;
          if (upper > lower) {
              // opens and closes in same day
              inRange = (now >= lower && now <= upper) ? true : false;
          } else {
              // closes in the following day
              inRange = (now >= upper && now <= lower) ? false : true;
          }
          return inRange;
      
          // Additional function needed to get a date/time value of the current date with the time provided as string
          function addTime(strTime) {
              var time = strTime.split(':');
              var dNewDate = new Date();
              var d = new Date(dNewDate.getFullYear(), dNewDate.getMonth(), dNewDate.getDate());
              d.setHours(time[0]);
              d.setMinutes(time[1]);
              d.setSeconds(time[2]);
              return d;
          }
      
      }
      
      
      
      Dr. BakteriusD Online
      Dr. BakteriusD Online
      Dr. Bakterius
      Most Active
      schrieb am zuletzt editiert von
      #4

      @Rico0079 Wenn ich das richtig verstehe, wird damit das Log über Datenpunkte nach VIS gebracht? Das ist aber nicht das was ich möchte. Es wäre schön, das ioBroker-Log dirket anzupassen bzw. gewisse Einträge zu filtern. Unter VIS brauche ich das Log nicht.

      1 Antwort Letzte Antwort
      0
      • R Offline
        R Offline
        Rico0079
        schrieb am zuletzt editiert von
        #5

        Ah ok verstehe nicht ganz wofür das gut sein soll den Eintrag zu filtern. Wenn es nur um den Eintrag als solches get. Die log wird doch eh gelöscht von daher ist doch egal was der Adapter schreibt beim Neustart.

        1 Antwort Letzte Antwort
        0
        • Dr. BakteriusD Online
          Dr. BakteriusD Online
          Dr. Bakterius
          Most Active
          schrieb am zuletzt editiert von
          #6

          Ganz einfach: ich will im System-Log nur 'warn' und 'error' anzeigen lassen um so auf einen Blick sehen zu können ob Probleme aufgetaucht sind. Jetzt schreibt mir aber der gewollte Neustart des Adapters jede Stunde einen Error in das Log. Meines Erachtens nach, hat der dort aber nichts verloren - eine gewollte Aktion ist kein Fehler!

          paul53P liv-in-skyL 2 Antworten Letzte Antwort
          0
          • Dr. BakteriusD Dr. Bakterius

            Ganz einfach: ich will im System-Log nur 'warn' und 'error' anzeigen lassen um so auf einen Blick sehen zu können ob Probleme aufgetaucht sind. Jetzt schreibt mir aber der gewollte Neustart des Adapters jede Stunde einen Error in das Log. Meines Erachtens nach, hat der dort aber nichts verloren - eine gewollte Aktion ist kein Fehler!

            paul53P Offline
            paul53P Offline
            paul53
            schrieb am zuletzt editiert von
            #7

            @Dr-Bakterius sagte:

            eine gewollte Aktion ist kein Fehler!

            Das hängt davon ab, wie man die gewollte Aktion erzeugt.

            Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
            Produktiv: Asus PN42 / N100 / 8 GB / 500 GB; Proxmox mit 2 VM (iob / openCCU)

            Dr. BakteriusD 1 Antwort Letzte Antwort
            0
            • Dr. BakteriusD Dr. Bakterius

              Ganz einfach: ich will im System-Log nur 'warn' und 'error' anzeigen lassen um so auf einen Blick sehen zu können ob Probleme aufgetaucht sind. Jetzt schreibt mir aber der gewollte Neustart des Adapters jede Stunde einen Error in das Log. Meines Erachtens nach, hat der dort aber nichts verloren - eine gewollte Aktion ist kein Fehler!

              liv-in-skyL Offline
              liv-in-skyL Offline
              liv-in-sky
              schrieb am zuletzt editiert von
              #8

              @Dr-Bakterius

              das angebotene script (weiter oben) macht das - damit kann filter setzen, was man sehen will und was nicht - und dann halt in der vis ansehen

              dort bekommst du dann genau, was du suchst

              nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

              Dr. BakteriusD 1 Antwort Letzte Antwort
              0
              • paul53P paul53

                @Dr-Bakterius sagte:

                eine gewollte Aktion ist kein Fehler!

                Das hängt davon ab, wie man die gewollte Aktion erzeugt.

                Dr. BakteriusD Online
                Dr. BakteriusD Online
                Dr. Bakterius
                Most Active
                schrieb am zuletzt editiert von
                #9

                @paul53 Unter 'Instanzen' wird bei 'neu starten' ein Cronjob angelegt, der genau dafür vom System vorgesehen ist.

                cron.jpg

                Weshalb diese Aktion mit einem Error versehen wird kann ich nicht nachvollziehen.

                paul53P 1 Antwort Letzte Antwort
                0
                • liv-in-skyL liv-in-sky

                  @Dr-Bakterius

                  das angebotene script (weiter oben) macht das - damit kann filter setzen, was man sehen will und was nicht - und dann halt in der vis ansehen

                  dort bekommst du dann genau, was du suchst

                  Dr. BakteriusD Online
                  Dr. BakteriusD Online
                  Dr. Bakterius
                  Most Active
                  schrieb am zuletzt editiert von
                  #10

                  @liv-in-sky Naja, nicht wirklich. So habe ich im Admin mein Log und nicht im Frontend vom VIS. Das hat für mich dort nichts verloren.

                  liv-in-skyL 1 Antwort Letzte Antwort
                  0
                  • Dr. BakteriusD Dr. Bakterius

                    @paul53 Unter 'Instanzen' wird bei 'neu starten' ein Cronjob angelegt, der genau dafür vom System vorgesehen ist.

                    cron.jpg

                    Weshalb diese Aktion mit einem Error versehen wird kann ich nicht nachvollziehen.

                    paul53P Offline
                    paul53P Offline
                    paul53
                    schrieb am zuletzt editiert von
                    #11

                    @Dr-Bakterius sagte:

                    Unter 'Instanzen' wird bei 'neu starten' ein Cronjob angelegt, der genau dafür vom System vorgesehen ist.

                    Der Cronjob ist nur für Instanzen vorgesehen, die nicht als Daemon laufen. RFLink ist sicherlich als Daemon programmiert.

                    Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
                    Produktiv: Asus PN42 / N100 / 8 GB / 500 GB; Proxmox mit 2 VM (iob / openCCU)

                    Dr. BakteriusD 1 Antwort Letzte Antwort
                    0
                    • paul53P paul53

                      @Dr-Bakterius sagte:

                      Unter 'Instanzen' wird bei 'neu starten' ein Cronjob angelegt, der genau dafür vom System vorgesehen ist.

                      Der Cronjob ist nur für Instanzen vorgesehen, die nicht als Daemon laufen. RFLink ist sicherlich als Daemon programmiert.

                      Dr. BakteriusD Online
                      Dr. BakteriusD Online
                      Dr. Bakterius
                      Most Active
                      schrieb am zuletzt editiert von
                      #12

                      @paul53 Das mag ja sein, aber dennoch handelt es sich um eine geplante und gewollte Aktion die nicht als Error behandelt werden sollte. IMHO sollte man hier ioB überarbeiten. Ich mach auch gerne ein GIT Issue auf, wenn ich weiß wo genau. Gehört das zum rflink-Adapter, zum Admin-Adapter oder ganz wo anders hin?

                      paul53P 1 Antwort Letzte Antwort
                      0
                      • Dr. BakteriusD Dr. Bakterius

                        @liv-in-sky Naja, nicht wirklich. So habe ich im Admin mein Log und nicht im Frontend vom VIS. Das hat für mich dort nichts verloren.

                        liv-in-skyL Offline
                        liv-in-skyL Offline
                        liv-in-sky
                        schrieb am zuletzt editiert von
                        #13

                        @Dr-Bakterius sagte in Log-Einträge eines bestimmten Adapters filtern:

                        @liv-in-sky Naja, nicht wirklich. So habe ich im Admin mein Log und nicht im Frontend vom VIS. Das hat für mich dort nichts verloren.

                        (für mich) einfacher als in der vis alles wichtiges zu sehen , was meinem iobroker angeht (auch im bezug zu überblick verschaffen, wenn nicht daheim und nur handy vorhanden) war mein hintergedanke - habe ein tablet mit vis im flur stehen - kurzer blick darauf - kein rechner einschalten oder sowas

                        letztlich kann man auch die angebotenen datenpunkte durch scripten so auswerten, das man sich mails oder telegram sendet

                        Image 4.png

                        nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                        Dr. BakteriusD 1 Antwort Letzte Antwort
                        0
                        • Dr. BakteriusD Dr. Bakterius

                          @paul53 Das mag ja sein, aber dennoch handelt es sich um eine geplante und gewollte Aktion die nicht als Error behandelt werden sollte. IMHO sollte man hier ioB überarbeiten. Ich mach auch gerne ein GIT Issue auf, wenn ich weiß wo genau. Gehört das zum rflink-Adapter, zum Admin-Adapter oder ganz wo anders hin?

                          paul53P Offline
                          paul53P Offline
                          paul53
                          schrieb am zuletzt editiert von
                          #14

                          @Dr-Bakterius sagte:

                          Gehört das zum rflink-Adapter, zum Admin-Adapter oder ganz wo anders hin?

                          error: host.iobroker instance system.adapter.rflink.0 terminated with code 156 () 
                          

                          Sieht nach js-controller aus.

                          Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
                          Produktiv: Asus PN42 / N100 / 8 GB / 500 GB; Proxmox mit 2 VM (iob / openCCU)

                          1 Antwort Letzte Antwort
                          0
                          • liv-in-skyL liv-in-sky

                            @Dr-Bakterius sagte in Log-Einträge eines bestimmten Adapters filtern:

                            @liv-in-sky Naja, nicht wirklich. So habe ich im Admin mein Log und nicht im Frontend vom VIS. Das hat für mich dort nichts verloren.

                            (für mich) einfacher als in der vis alles wichtiges zu sehen , was meinem iobroker angeht (auch im bezug zu überblick verschaffen, wenn nicht daheim und nur handy vorhanden) war mein hintergedanke - habe ein tablet mit vis im flur stehen - kurzer blick darauf - kein rechner einschalten oder sowas

                            letztlich kann man auch die angebotenen datenpunkte durch scripten so auswerten, das man sich mails oder telegram sendet

                            Image 4.png

                            Dr. BakteriusD Online
                            Dr. BakteriusD Online
                            Dr. Bakterius
                            Most Active
                            schrieb am zuletzt editiert von
                            #15

                            @liv-in-sky Mit welchem Widget lasst du denn die json-Daten unter VIS anzeigen?

                            liv-in-skyL 1 Antwort Letzte Antwort
                            0
                            • Dr. BakteriusD Dr. Bakterius

                              @liv-in-sky Mit welchem Widget lasst du denn die json-Daten unter VIS anzeigen?

                              liv-in-skyL Offline
                              liv-in-skyL Offline
                              liv-in-sky
                              schrieb am zuletzt editiert von
                              #16

                              @Dr-Bakterius

                              json-table


                              [{"tpl":"tplTableBody","data":{"g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","static_value":"","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis.0/VIS/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis.0/VIS/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis.0/VIS/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"table_oid":"javascript.2.mylog.logErrorJSON","colName1":"Uhrzeit","colWidth1":"80px","colCount":"4","colWidth2":"50px","colWidth3":"50px","colWidth4":"580px","colWidth5":"40px","colWidth6":"40px","colName2":"Log-Eintrag","class":"mdui-table","show_scroll":true,"hide_header":true,"g_last_change":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"new_on_top":true,"max_rows":"2000","detailed_wid":"w00377","name":"System_Logs"},"style":{"left":"811px","top":"123px","width":"772px","height":"181px","text-align":"left","color":"#a5d5ee","background-color":"","font-family":"Arial, Helvetica, sans-serif","z-index":"20","background":"","box-shadow":"","border-radius":"10px","font-size":"14px","border-style":"solid","border-color":"#303030"},"widgetSet":"basic"}]

                              nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                              Dr. BakteriusD 1 Antwort Letzte Antwort
                              1
                              • liv-in-skyL liv-in-sky

                                @Dr-Bakterius

                                json-table


                                [{"tpl":"tplTableBody","data":{"g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","static_value":"","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis.0/VIS/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis.0/VIS/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis.0/VIS/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"table_oid":"javascript.2.mylog.logErrorJSON","colName1":"Uhrzeit","colWidth1":"80px","colCount":"4","colWidth2":"50px","colWidth3":"50px","colWidth4":"580px","colWidth5":"40px","colWidth6":"40px","colName2":"Log-Eintrag","class":"mdui-table","show_scroll":true,"hide_header":true,"g_last_change":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"new_on_top":true,"max_rows":"2000","detailed_wid":"w00377","name":"System_Logs"},"style":{"left":"811px","top":"123px","width":"772px","height":"181px","text-align":"left","color":"#a5d5ee","background-color":"","font-family":"Arial, Helvetica, sans-serif","z-index":"20","background":"","box-shadow":"","border-radius":"10px","font-size":"14px","border-style":"solid","border-color":"#303030"},"widgetSet":"basic"}]

                                Dr. BakteriusD Online
                                Dr. BakteriusD Online
                                Dr. Bakterius
                                Most Active
                                schrieb am zuletzt editiert von
                                #17

                                @liv-in-sky Danke!

                                1 Antwort Letzte Antwort
                                0
                                • Dr. BakteriusD Online
                                  Dr. BakteriusD Online
                                  Dr. Bakterius
                                  Most Active
                                  schrieb am zuletzt editiert von
                                  #18

                                  Ich bin zwar immer noch der Meinung, dass die Error-Meldung in diesem Fall ungerechtfertigt ist und es vielleicht überhaupt praktisch wäre Filter einrichten zu können, doch habe ich das Log nun doch in meine VIS-Oberfläche bei den Systemwerten integriert:

                                  system.png

                                  liv-in-skyL 1 Antwort Letzte Antwort
                                  0
                                  • Dr. BakteriusD Dr. Bakterius

                                    Ich bin zwar immer noch der Meinung, dass die Error-Meldung in diesem Fall ungerechtfertigt ist und es vielleicht überhaupt praktisch wäre Filter einrichten zu können, doch habe ich das Log nun doch in meine VIS-Oberfläche bei den Systemwerten integriert:

                                    system.png

                                    liv-in-skyL Offline
                                    liv-in-skyL Offline
                                    liv-in-sky
                                    schrieb am zuletzt editiert von
                                    #19

                                    @Dr-Bakterius

                                    wenn das nicht klasse und prof. aussieht !

                                    nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                                    1 Antwort Letzte Antwort
                                    0
                                    • Dr. BakteriusD Dr. Bakterius

                                      Aus bestimmten Gründen muss ich den rflink-Adapter regelmässig über 'neu starten' per cron neu starten. Dabei wird jedes Mal ein Error-Eintrag im Log vermerkt:

                                      error: host.iobroker instance system.adapter.rflink.0 terminated with code 156 ()
                                      

                                      Kann man bestimmte Einträge wie diesen filtern? Oder kann man nicht generell bei geplanten Neustarts auf einen Error-Eintrag verzichten (da würde 'info' völlig reichen)?

                                      AlCalzoneA Offline
                                      AlCalzoneA Offline
                                      AlCalzone
                                      Developer
                                      schrieb am zuletzt editiert von
                                      #20

                                      @Dr-Bakterius sagte in Log-Einträge eines bestimmten Adapters filtern:

                                      Oder kann man nicht generell bei geplanten Neustarts auf einen Error-Eintrag verzichten (da würde 'info' völlig reichen)?

                                      Wenn ich mich richtig erinnere, wird das in einer der kommenden Versionen kein "error" mehr sein. Etwas Geduld bitte.

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

                                      1 Antwort Letzte Antwort
                                      0

                                      Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                                      Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                                      Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                                      Registrieren Anmelden
                                      Antworten
                                      • In einem neuen Thema antworten
                                      Anmelden zum Antworten
                                      • Älteste zuerst
                                      • Neuste zuerst
                                      • Meiste Stimmen


                                      Support us

                                      ioBroker
                                      Community Adapters
                                      Donate
                                      FAQ Cloud / IOT
                                      HowTo: Node.js-Update
                                      HowTo: Backup/Restore
                                      Downloads
                                      BLOG

                                      364

                                      Online

                                      33.0k

                                      Benutzende

                                      83.7k

                                      Themen

                                      1.3m

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

                                      • Du hast noch kein Konto? Registrieren

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