ioBrokerioBroker Tutorials

Eigenes Logging in ioBroker – Teil 4

In diesem Artikel zeige ich Dir, wie Du Dein eigenes Logging in ioBroker implementieren kannst.

In unserem Smart-Home hatte ich die Idee, bestimmte Ereignisse in Form eines eigenen Protokolls zu speichern. Derzeit dokumentiere ich mir z.B. die Türstatus oder Status zur automatischen Beleuchtung. Im Artikel werde ich ich ein neues, angepasstes Script mit den Funktionsupdates zeigen:

Hier zunächst meine Basis-Anforderungen an das Protokoll:

  • Protokoll-Eintrag mit folgenden Angaben:
    – Eindeutige, fortlaufende Vorgangsnummer (ID)
    – Datum- und Zeitangabe des Eintrags
    – Art des Protokoll-Eintrags (Fehler, Info, usw…)
    – Protokoll-Text
  • Protokoll muss nachträglich leerbar sein.
  • Einfacher Aufruf im JavaScript-Code.

Im 1. Teil der Artikelreihe habe wir bereits ein Script dazu implementiert. Im Laufe der Zeit kamen nun aber weitere Anforderungen dazu, welche im neuen Script berücksichtigt wurden:

  • Einstellbar maximale Anzahl an Log-Einträgen
    Hier gab es bei mir in meiner Umgebung sowie auch bei einigen Anwendern das Problem von zu langen Ladezeiten der VIS. Bei einigen Tausend Datensätzen ist das auch kein Wunder. Daher habe ich hier für eine neue Einstellung (maxEventCount) vorgesehen, mit dem die Anzahl der maximalen Einträge begrenzt werden kann.
  • Mehrfach-Aufruf Problematik (Timing-Problem)
    Wenn in einem Trigger oder sonstigen Script mehrere Aufrufe der Funktion createEventLog() hintereinander implementiert wurden, dann kam hier aufgrund eines Timing-Problems nur der letzte Log-Eintrag im Datenpunkt an. Dies kann einfach mit dem separaten Beispiel-Code umgangen werden.

Für die Installation des Scripts muss einfach das bestehende Script mit dem folgenden Script-Code ersetzt werden. Bitte beachte dabei, dass bei einer Änderung des globalen Code-Bereichs alle Scripte automatisch einmalig ausgeführt werden. Hier nun der neue Script-Code für die Logging-Funktionalität:

const EventListDestination = "javascript.0.SystemEventList.";
const maxEventCount = 500;
 
function createEventlog(EventType, EventText) {
  let EventList = getState(EventListDestination + "EventList").val;
  
  // Nur die letzten x Einträge im Script belassen
  let eventList = EventList.split('<br>');
  let eventCount = eventList.length;
  let newEventList = "";

  for (var i = 0; i < eventCount; i++) {
    if ( i < (maxEventCount-1) ) {
      newEventList = newEventList + "<br>" + eventList[i];
    } else {
      break;
    }
  }
  
  EventList = newEventList;
 
  // Neue Event-Id und Zeitpunkt ermitteln
  let EventId = getState(EventListDestination + "NextEventId").val;
  let EventDateTime = formatDate(getDateObject((new Date().getTime())), "TT.MM.JJ hh:mm:ss");
 
  EventId = EventId + 1;
  setState(EventListDestination + "NextEventId", EventId);
   
  let FormatedEventId = ("00000" + EventId).slice(-5);
  let EventLog = FormatedEventId + " - " + EventDateTime + " - " + EventType + " - " + EventText;
  EventList = EventLog + EventList;
   
  setState(EventListDestination + "EventList", EventList);
}

Beispiel-Code für das mehrmalige Aufrufen der createEventLog() Funktion:

function sleep(milliseconds) {
 return new Promise(resolve => setTimeout(resolve, milliseconds));
}

async function createMultipleLogs() {
  createEventlog("Info", "Test Nachricht 1");
  await sleep(100);
  createEventlog("Info", "Test Nachricht 2");
  await sleep(100);
  createEventlog("Info", "Test Nachricht 3");
  await sleep(100);    
}

createMultipleLogs();

Vielen Dank für euer Feedback. Bei weiteren Fragen oder Anregungen gerne melden 🙂

Matthias Korte

Hauptberuflich Software-Entwickler und seit einigen Jahren Smart-Home Fan. Angefangen hat alles mit einem RaspberryMatic und einer schaltbaren Steckdose. Mittlerweile habe ich einige Steckdosen, Sensoren, und Thermostate sowie ioBroker zur Visualisierung im Einsatz.

8 Gedanken zu „Eigenes Logging in ioBroker – Teil 4

  • Sascha

    Hallo Mathias,
    die Idee mit dem eigenen Logging ist ja echt Prima. Habe ich gleich bei mir in Blockly implementiert.
    Nun habe ich aber Blockly Skripte, welche parallel getriggert werden.
    Da ist es dann offensichtlich so, dass das zuletzt getriggerte Skript auf dem Log erscheint.
    Im Teil 4 beschreibst du eine Lösung dazu in Javascript. Wie kann ich diese in Blockly implementieren?
    Funktioniert die in Teil 4 beschriebene Lösung auch Skriptübergreifend?

    Vielen Dank für diesen tollen Blog und deine Hilfe.

    Grüße
    Sascha

    Antwort
  • Sascha

    Hallo Mathias,
    vielen Dank für das tolle Skript. Ich habe die Blockly Variante nun in mein System integriert.
    Globales Skript aus Teil 4 und den Blockly Aufruf aus Teil 2.
    Nach ein paar Tagen viel leider auf, dass bei parallel angestoßenen Skripten immer nur das Log des letzten aufgeführt wird. Gibt es eine Möglichkeit dies auch in Blockly zu verhindern?
    Ich könnte natürlich manuelle Zeitversätze da rein bringen, was aber auf Dauer nicht zielführend wäre.
    Hast du vielleicht ne Idee?

    Grüße
    Sascha

    Antwort
    • Matthias Korte

      Hallo Sascha,

      ich prüfe das, und werde es ergänzen.

      LG Matthias

      Antwort
      • Sascha Doderer

        Prima,
        würde mich freuen, wenn dass das Problem lösbar ist.
        Wenn du noch Informationen benötigst, melde dich gerne.

        Grüße
        Sascha

        Antwort
  • Hallo Matthias
    Zunächst einmal Danke für deine Anleitungen.
    Die Einbindung in meinem iobroker hat hervorragend geklappt, jedoch habe ich das Problem, dass mir als Zeitstempel des Ereignisses nicht die aktuelle Zeit (Sommerzeit) sondern die MEZ (UTC+1) anzeigt wird. Hast Du einen Tipp für mich, wie ich das korrigieren kann?
    Gruß
    Simon

    Antwort
  • Mike Wolfelsperger

    Hallo Matthias,

    wo genau wird der Beispiel-Code für das mehrmalige Aufrufen eingetragen?

    Gruß Mike

    Antwort
  • Ivan

    Hallo Matthias,

    zuerst muss ich ein Lob für deine Beiträge und Anleitungen aussprechen. Für mich waren sie bisher sehr informativ und anregend. Damit habe ich auch meine Kenntnisse erweitern können.
    Daher mal ein Feedback mit der Info, was ich beim Logging verändert habe.

    Von Anfang an fand ich es unpraktisch das alle Einträge hintereinander im Log stehen. Auf meinem Tablet kann ich mir auch nur eine kleine Anzahl anzeigen lassen und auch wenn ich mir mit „maxEventCount“ die Anzahl minimieren kann, ist eine Suche nach einem bestimmten Event sehr mühselig. Daher habe ich dein Script etwas angepasst. In „maxEventCount“ habe ich jetzt nur etwas mehr Einträge zugelassen wie ich sie mir auf dem Tablet anzeigen lassen kann. Da die Event-Liste nicht passend ist um diese per history oder SQL in eine Datenbank zu speichern, bin ich wie folgt vorgegangen.

    Zuerst habe ich mir einen weiteren Text Datenpunkt „EventLog“ angelegt und dort history bzw. SQL eingeschaltet. Dein Script habe ich um den Punkt erweitert, dass der Event auch in „EventLog“ gespeichert wird und die Einträge für 6 Monate vorgehalten werden. Somit habe ich eine Schöne Datenbank in der ich auch mal nach etwas suchen bzw. auswerten kann.
    Zusätzlich habe ich für einige relevante Events den Versand per WhatsApp zugefügt, damit ich das auch wirklich mitbekomme, unabhängig ob ich Zuhause bin bzw. mit die Event-Liste auf dem Tablet anschaue. Insgesamt sieht es dann wie folgt aus (am Beispiel der Haustür).

    on({id: „hmip.0.devices.3014F711A00000xyzxyzxyz.channels.1.windowOpen“, change: „ne“}, function (obj) {
    var value = obj.state.val;

    if ( value === false ) {
    createEventlog(„Info“, „Haustür wurde geschlossen“);
    setState(„javascript.0.SystemEventList.EventLog“/*EventLog*/, ‚Haustür wurde geschlossen‘);
    setState(„whatsapp-cmb.0.sendMessage“/*Send message*/, ([‚Haustür wurde geschlossen‘].join(“)));
    } else {
    createEventlog(„Info“, „Haustür wurde geöffnet“);
    setState(„javascript.0.SystemEventList.EventLog“/*EventLog*/, ‚Haustür wurde geöffnet‘);
    setState(„whatsapp-cmb.0.sendMessage“/*Send message*/, ([‚Haustür wurde geöffnet‘].join(“)));
    }
    });

    Liebe Grüße

    Ivan

    Antwort

Schreibe einen Kommentar zu Simon Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht.