ioBrokerioBroker Tutorials

Eigenes Logging in ioBroker

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 zeige ich Dir, wie ich mir dazu einen eigenen Datenpunkt, sowie eine globale Funktion implementiert habe.

Hier zunächst meine 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.

Mit diesen Anforderungen beginnen wir nun mit der Erstellung der benötigten Datenpunkte.

Im ersten Schritt wechseln wir nun in den Bereich Scripts und erstellen uns ein neues JavaScript. In das Script kopieren wir den folgenden Script-Code:

const EventListDestination = "javascript.0.SystemEventList.";

createState(EventListDestination + "EventList", "", false, { read: true, write: true, name: "Event-Liste", type: "string", role: "text", def: "" });
createState(EventListDestination + "NextEventId", 0, false, { read: true, write: true, name: "Nächste Event-Id", type: "number", def: 0 });

Das Script ist ein kleines Hilfsscript, mit dem wir uns im ersten Schritt die benötigten Datenpunkte für die Logging anlegen. In der 1. Zeile des Scripts wird dazu eine Konstante definiert, welche den Speicherort der neuen Datenpunkte angibt. Du kannst hier selbstverständlich auch einen anderen Speicherort definieren. Im nächsten Schritt werden mit den beiden createState Aufrufen ein Datenpunkt für die eigentliche Protokoll-Liste (EventList) sowie ein Datenpunkt für die maximale Protokoll-Id angelegt.

Nach dem Aktivieren und Speichern des Scripts sollten nun nach der ersten Ausführung die folgende Datenpunkte im entsprechenden Speichertort angelegt worden sein. Du kannst die Datenpunkte optional auch händisch anlegen, ich löse so etwas aber in der Regel mittels einem kleinen Script, welches ich nach dem einmaligen Ausführen dann wieder deaktiviere. Im Screenshot siehst Du hier nun die angelegten Datenpunkte für das Logging.

Im nächsten Schritt wechseln wir wieder in den Bereich Scripte und aktivieren nun den Expertenmodus. Den Expertenmodus benötigen wir, um ein neues globales Script anlegen zu können. Wir erstellen uns das Script global, sodass wir die Protokollierung in allen Scripts nutzen können.

Nach dem wir nun den Expertenmodus aktiviert haben, wird in der Liste der verfügbaren Scripts ein weiterer Ordner global eingeblendet. Unterhalb von diesem Ordner werden alle globalen Scripts gespeichert. Wir markieren nun den Ordner und klicken auf das markierte Plus-Symbol.

Als Script-Art wählen wir hier Javascript und klicken auf die markierte Schaltfläche hinzufügen.

Im nächsten Schritt müssen wir für das neue Script noch einen Namen definieren. Ich habe als Name SystemEvents gewählt und mit Ok das Script gespeichert.

Jetzt beginnen wir mit der eigentlichen Implementierung der Protokoll-Funktion. Dazu habe ich zunächst wieder über die Konstante den Speicherort der Protokollierung festgelegt. Falls Du oben einen anderen Speicherort gewählt hast, muss dieser dann hier ebenfalls angepasst werden.

Mit der Funktion createEventLog wird der eigentliche Eintrag in den Protokollierungs-Datenpunkt geschrieben. Die Funktion bekomme hierzu zwei Paramter. Im ersten Paramter habe ich den Typ des Eintrags (Info, Fehler, usw…) definiert. Mit dem zweiten Parameter wird die eigentliche Meldung übergeben. Die Funktion ermittelt dann die nächste Event-Id für die fortlaufende Nummerierung der Einträge, sowie den aktuellen Timestamp für die Zeitangabe. Hierzu wird die Zeitangabe in das Format TT.MM.JJ hh:mm:ss formatiert. Anschließend wird der neue Eintrag an die bestehenden Protokoll-Einträge vorangestellt. Der neueste Eintrag steht somit immer oben im Protokoll.

const EventListDestination = "javascript.0.SystemEventList.";

function createEventlog(EventType, EventText) {
  let EventList = getState(EventListDestination + "EventList").val;
  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 + "<br>" + EventList;
  
  setState(EventListDestination + "EventList", EventList);
}

Wir können das neue globale Script nun speichern und aktivieren. Nach dem Speichern werden alle angelegten Scripte einmalig ausgeführt, da eine Änderung an den globalen Scripten gemacht wurde. Grundsätzlich solltest Du in den globalen Scripten möglichst wenig Scripte implementieren, da dieser Code bei jedem Script vorangestellt und ausgeführt wird. Gerade bei vielen globalen Scripts kann dies auf Dauer zu Performance-Problemen führen.

Wir können nun in allen Scripts mit dem folgenden Aufruf einen Eintrag in unseren Protokoll-Datenpunkt schreiben:

Beispiel-Aufruf 1:
In diesem Beispiel wird eine Info-Eintrag geschrieben.

createEventlog("Info", "Test Nachricht");

Beispiel-Aufruf 2:
Im zweiten Beispiel können wir auch Fehler z.B. Low-Bat Meldungen dokumentieren.

createEventlog("Fehler", "Fehler-Nachricht");

Im folgenden Scriptcode habe ich nun die Funktion zur Dokumentation eines Tür-Status implementiert. Im Trigger auf den STATE Datenpunkt unserer Haustür habe ich hier den aktuellen Zustand im Protokoll gespeichert.

on({id: "hm-rpc.0.XXXXXXXXX.STATE", change: "ne"}, function (obj) {
  var value = obj.state.val;

  if ( value === true ) {
    createEventlog("Info", "Haustür wurde geöffnet");
  } else {
    createEventlog("Info", "Haustür wurde geschlossen");
  }  
});

Im nächsten Schritt schauen wir uns nun die Visualisierung des Protokolls auf VIS an. Dazu werde ich nun meine System-View um ein weiteres HTML-Widget erweitern.

Im HTML-Code des Widgets fügen wir nun das folgende Object-Binding ein:

{javascript.0.SystemEventList.EventList}

Das Widget in VIS sieht nun wie folgt aus:

In der Visualisierung wird nun der Inhalt der Protokollierung wie folgt angezeigt. Im Protokoll ist vorne die eindeutige Nummer zu sehen. Als nächstes folgt der Zeitstempel des Eintrags sowie die Art und die eigentliche Meldung.

Ich finde diese Form der Protokollierung schon mal sehr praktisch. In einem späteren Teil werden wir dann noch Erweiterungen wie z.B. verschiedene Ansichten vorsehen. Ich denke gerade Filter auf die Art der Einträge sind ein wichtiges Thema.

Ich hoffe ich konnte Dir mit diesem Artikel bereits einen ersten Einblick in die Möglichkeiten der eigenen Protokollierung in ioBroker geben. Über Kommentare, Fragen oder Anregungen freue ich mich.

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.

27 Gedanken zu „Eigenes Logging in ioBroker

  • Ivan Andric

    Hallo Matthias,
    erst einmal vielen Dank für die vielen Informationen und Anleitungen zu ioBroker. Ich selber benutze das Tool erst seit kurzer Zeit und orientiere mich daher auch an deinen Beispielen.
    Beim Thema Logging (wie im Artikel beschrieben) funktioniert soweit alles, jedoch bin ich mit der Darstellung noch nicht zufrieden. Ich benutze statt VIS das HABPanel und dort erscheint der Log nicht schön untereinender wie bei dir, sondern alle Log-Daten nebeneinander in einer Zeile. So wie es aussieht wird die Variable nicht berücksichtigt.
    Ich habe zum Probieren im HABPanel ein Template angelegt und dort folgendes eingetragen.
    Tür-Log
    {{itemValue(‚javascript.0.SystemEventList.EventList‘)}}
    Weiter habe ich noch ein Dummy angelegt und als Item
    javascript.0.SystemEventList.EventList angegeben.

    Bei beiden sieht der output wie folgt aus:
    00004 – 30.12.19 15:05:06 – Info – Haustür wurde geschlossen00003 – 30.12.19 15:03:36 – Info – Haustür wurde geöffnet00002 – 30.12.19 13:53:47 – Info – Haustür wurde geschlossen00001 – 30.12.19 13:53:04 – Info – Haustür wurde geöffnet
    Der Zeilenumbruch wird also nicht berücksichtigt.
    Hast du eine Idee?
    Vielen Dank!
    Liebe Grüße
    Ivan

    Antwort
  • Ivan Andric

    Sehe gerade, dass die Kommentar Funktion den Zeilenumbruch raus geschnitten hat.
    Es müsste korrekt wie folgt aussehen:
    00004 – 30.12.19 15:05:06 – Info – Haustür wurde geschlossen(br)00003 – 30.12.19 15:03:36 – Info – Haustür wurde geöffnet(br)00002 – 30.12.19 13:53:47 – Info – Haustür wurde geschlossen(br)00001 – 30.12.19 13:53:04 – Info – Haustür wurde geöffnet(br)
    Habe zur Darstellung für den Zeilenumbruch hier (br) benutzt damit dieser nicht wieder raus geschnitten wird.

    Antwort
    • Matthias Korte

      Hallo Ivan,

      ich habe das derzeit nur in VIS eingesetzt. Das Problem hier ist definitiv der Zeilenumbruch, welcher in dieser Form wohl in HABPanel nicht funktioniert :-/
      Ich vermute das Problem liegt im Bereich {{itemValue(…)}}.

      Antwort
    • Thomas

      Hallo,
      hab die Lösung im openhab Forum gefunden:

      Antwort
      • Matthias Korte

        Hallo Thomas,

        danke für Deinen Hinweis – kannst Du vielleicht hier noch kurz den Link posten. Danke 🙂

        LG Matthias

        Antwort
      • Thomas Steil

        Hallo Matthias,

        irgendwie ging der Link beim C&P verloren. Hier was ich in meinem Template stehen habe:

        Abgesehen davon werden aber manchmal Ereignisse nicht geloggt. Ich habe 2 Aufrufe in einem Skript und davon landet zu 90% nur 1 Aufruf in der Liste. Das ist irgendwie seltsam.
        Danke trotzdem für deine Tipps. Hat mir schon einige Male geholfen!

        Gruß
        Thomas

        Antwort
        • Thomas Steil

          OK, es dein Webserver welcher meine Links oder Script-Snippets rausfiltert 🙂 Wie bekomme ich meinen Code hier rein? 😀
          Dann verkürze ich es eben noch weiter. Vor das itemValue muss ein ng-bind-html

          Antwort
  • Ivan Andric

    Danke, habe es jetzt unter VIS am laufen.

    Antwort
  • Harald

    Hallo,

    tolles Video und gleich umgesetzt!

    Jetzt noch eine Frage:
    Wie muss der Code aussehen, wenn ich z.B. die Textfarbe bei einer „warn“ Meldung in rot haben möchte?

    Antwort
  • Martin

    Hallo,
    das ganze klappt bei mir auch so wie beschrieben. Meine Frage ist jetzt wie kann ich die funktion „createEventlog“ mit parametern im blocky ausführen? Geht das überhaupt?

    Antwort
    • Matthias Korte

      Hallo Martin,
      dazu kommt in den nächsten Tagen ein Artikel 🙂

      LG Matthias

      Antwort
      • Mathias

        Hallo Matthias,

        ist der Artikel schon veröffentlicht? Mich würde es auch interresieren, wie ich die unterschiedlichen Meldungen farblich anpassen kann.

        MfG,
        Mathias mit einem „t“

        Antwort
  • Pingback: Eigenes Logging in ioBroker – Teil 2 – Nutzung in Blockly – smarthome-tricks.de

  • Jens Hübner

    Hallo Matthias,

    Frage dazu: Wie kann ich denn die Temperatur loggen bzw. dann auch visualisieren?
    Sollte ich das über eigenes Logging machen (alle 5 min) oder über zB. InfluxDB?
    Und wie funktioniert dann die Visualisierung als Diagramm oder Linienverlauf?

    Dank Dir.

    Gruß
    jens

    Antwort
  • Andreas

    Hallo,

    ich finde deinen Beitrag, sehr cool.
    Auch wie man das mit Blockly umsetzt, sehr gut.

    Was mich noch interessieren würde ist,
    – Welches Widget muss ich benutzen um einen Scrollbalken für die Protokollierung zu haben?
    – unterschiedliche Farben für Fehler oder Info
    – ggf. auch einen Filter für Fehler oder Info wäre cool

    Danke und Grüße
    Andreas

    Antwort
    • Andreas

      das mit den Scollbalken habe ich gerade selbst gefunden … : – )

      Antwort
  • Torsten

    Hallo Matthias,

    Vielen Dank für das Script/die Anregung. Ich hab’s gleich nachgebaut, da ich es für sinnvoll halte. Es funktioniert grundsätzlich, leider erzeugt es immer genau zwei Einträge im Log. Habe schon das normale Systemlog durchgesucht. Ich finde den Fehler nicht. Kannst Du mir einen Tipp geben auf was ich achten sollte?

    Gruß & Danke im Vorraus
    Torsten

    Antwort
    • Matthias Korte

      Hallo Torsten,

      zeige mir Doch mal ein Beispiel, wie Du die Funktion in Blockly oder im Script verwendest. Evtl. stimmt hier was nicht.

      Grüße,
      Matthias

      Antwort
  • Pingback: Eigenes Logging in ioBroker – Teil 3 – Integration in HABPanel – smarthome-tricks.de

  • Wolfgang Scholz

    Hallo Matthias,
    ich nutze deine Scripte um Telefonanrufe mit dem tr-064 Adapter zu loggen. Das funktioniert auch einwandfrei. Da aber Telefonnummern unterschiedlich lang sind sieht das Logging unschön aus. Kann man das Logging oder die Ausgabe auch formatiert ausgeben, also z.B. mit Tabulator?

    Vielen Dank für die Anregung und freundliche Grüße
    Wolfgang

    Antwort
  • Yavuz

    Wenn die Aufrufe von verschiedenen Programmen zu schnell hintereinander erfolgen, kann es nicht funktionieren. Bräuchte eine Verzögerung.
    Versuch mal:
    createEventlog(„Info“, „Test Nachricht 1“);
    createEventlog(„Info“, „Test Nachricht 2“);
    createEventlog(„Info“, „Test Nachricht 3“);
    createEventlog(„Info“, „Test Nachricht 4“);
    Es würde nur „Test Nachricht 4“ in der Event Liste stehen. Die Vorherigen wären „verschluckt“

    Antwort
    • Matthias Korte

      Moin,
      danke für den Hinweis, ich werde mir das ansehen. Es wird dann nochmals eine Erweiterung für das Logging geben.

      LG Matthias

      Antwort
  • Mike

    moin,
    wenn man über 10.000 Einträge hat, wird die VIS seeeeehr langsam. Gibt es eine Möglichkeit, nur die letzten 1.000 Einträge im Logbuch stehen und zu lassen und die älteren werden automatisch gelöscht?
    Lg Mike

    Antwort
    • Matthias Korte

      Moin Mike,
      ja, das stimmt, ist mir so auch schon aufgefallen. Ich werde hier demnächst einen weiteren Teil veröffentlichen, dann wird das Thema verbessert.

      Einen guten und vor allem gesunden Rutsch ins neue Jahr.
      LG Matthias

      Antwort
      • Mike

        Super – bin gespannnt….

        Antwort
        • Wann wird denn damit zu rechnen sein?

          Antwort
          • Matthias Korte

            Hallo Mike,

            ich hatte das für Samstag geplant, aber leider kam etwas dazwischen. Habe dann gestern alles implementiert und getestet. Gleich kommt der Artikel dazu 🙂
            LG Matthias

Schreibe einen Kommentar

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