NEWS
Anfängerfrage: Eigener Alarmlogger
-
Hallo zusammen,
Vorerst Mal bitte ich um Erbarmen. Bin wirklich ein Anfänger. Ich möchte gerne gewisse Ereignisse im vis HTML Widget anzeigen. Dazu wollte ich wie folgt vorgehen:function machwas(InZahl) { log(InZahl + "</br> "+ String(getState('0_userdata.0.Sicherheit.sAlarmLogHistory').val)); setState('0_userdata.0.Sicherheit.sAlarmLogHistory', InZahl + "</br> "+ String(getState('0_userdata.0.Sicherheit.sAlarmLogHistory').val), false); }
Nun der Test mit folgenden Werten:
machwas("1");
machwas("2");
machwas("3");
machwas("4");ergibt im Objekt sAlarmLogHistory nur den letzten Wert ("4</br>") und nicht wie erwartet die vorherigen Werte im String.
Wie mache ich es, dass im Objekt sAlarmLogHistory "1</br>2</br>3</br>4</br>" steht? -
Was gibt denn das Log aus?
Ein Zeilenumbruch in HTML ist
<br/>
. Du hast die falsche Reihenfolge erwischt.Und zudem: wenn schon wäre der Wert nach deiner Reihe: 4</br>3</br>... Da du ja Werte immer vorne dran hängst.
-
@seyav
An die Funktion machwas(InZahl) wird nur eine Zahl übergeben und innerhalb der Funktion auch nur ausgewertet. Weshalb sollten 4 Zahlen im Datenpunkt stehen ? -
@UncleSam Reihenfolge: Hast Du recht. Der log ist:
19:31:16.560 info javascript.0 (2716) script.js.____TESTS____.Skript_5: 1</br> 19:31:16.561 info javascript.0 (2716) script.js.____TESTS____.Skript_5: 2</br> 19:31:16.562 info javascript.0 (2716) script.js.____TESTS____.Skript_5: 3</br> 19:31:16.563 info javascript.0 (2716) script.js.____TESTS____.Skript_5: 4</br>
-
@seyav OK, dann könnte es sein, dass die Werte noch nicht in den Datenpunkt geschrieben wurden (du machst das ja sehr schnell hinter einander). Was passiert, wenn du es eine Zeile nach der anderen ausführst (zB mit einem timeout)?
-
@paul53 Ich möchte einzelne Ereignisse in einem Datenpunkt chronologisch sammeln und im vis anzeigen (Tür geöffnet, Tür geschlossen usw. mit Zeitangabe)
-
@seyav sagte in Anfängerfrage: Eigener Alarmlogger:
Der log ist:
Aufruf aus einer Schleife: Das funktioniert mit getState('0_userdata.0.Sicherheit.sAlarmLogHistory') nicht, da die Schleife durchlaufen ist bevor das erste setState() fertig ist (asynchrone Abarbeitung).
-
@seyav sagte:
Tür geöffnet, Tür geschlossen usw. mit Zeitangabe
Dann ist genügend Zeit zwischen den Ereignissen. Du kannst die Funktion nicht in einer Schleife testen.
-
@UncleSam Ja. habe ich vermutet. Doch, ich möchte von verschiedenen Programmen jeweils den log auslösen. Dazu habe ich die Routine "machwas" im "global" teil aufgeführt und rufe sie von meinen Programmen auf. Nun, wenn genügend Zeit ist, um die Werte in den Datenpunkt zu schreiben, funktioniert es ja auch. Das Problem ist, wenn die Aufrufe zu schnell hintereinander passieren. Ich wollte mit dem Use Case oben mein Problem erläutern. Irgendwie brauche ich eine Lösung, um Daten in den Datenpunkt synchron zu schreiben.
Wenn das nicht geht, muss ich mir irgendwie mit timeout behelfen, wo ich die Zeitspanne dazu irgendwie beherrschen muss. -
@seyav Schreib eine Funktion, die den Inhalt selber speichert anstatt jedes mal den Wert des Datenpunktes auszulesen. Ansonsten musst du mit asynchronen Methoden oder Callbacks arbeiten und machst dir eine Hand ab.
Aber mal ganz ehrlich: wenn du so viele Daten schreiben willst, macht dann eine Ausgabe als HTML Sinn? Das kann ja niemand mehr lesen.
-
@UncleSam Also, das mit dem HTML geht es um Folgendes:
Wegen Callbacks &co hast Du Recht. Ich lasse Finger davon. Ich versuche es mal mit befüllen eines String Variablen.
Alle paar Sekunden schreibe ich dann den Stringwert in den Datenpunkt. -
@seyav Eben, da passiert ja nicht innerhalb von zehn Millisekunden etwas. Dein ursprüngliches Skript würde also funktioneren.
-
@UncleSam Hab mal so gelöst:
/*************************************************/ // Globale Funktion, um Alarme auf dem vis auszugeben, im NAS zu loggen und auf dem Mobile (tts) auszugeben // Max 5 schnellfolgende Meldungen /*************************************************/ var sLog = new Array(5); var sTxt = new Array(5); var sDauer = new Array(5); var sInSay = new Array(5); var iMeldungSpanne=3000; // 3 Sek pro Meldung var LogenInVerzeichnis = "/home/pi/nas/history.csv"; // Text Datei auf NAS var URLSoundAusgabe = "http://192.168.1.147:50000/tts="; // Mobile im Wohnzimmer for (var i = 0; i < sLog.length; i++) {sLog[i] = "";} // Array sLog Initialisieren var vIntervall=null; // k.A. ob es wirklich nötig ist vIntervall=setInterval(function(){StringArrayAusgeben();}, iMeldungSpanne *5 + 200); // Endless loop, alle 15 Sekunden // Max 5 Meldungen vom Array sLog mit Zeitspanne 3Sek ausgeben // falls innert 15 sek > 5 Meldungen eintreffen, gehen die verloren function HistoryAnlegen(InText, InDauerText, InSay){ // sLog[i] synchron befüllen for (var i = 0; i < sLog.length; i++){ if(sLog[i]==""){ /***** Datum loggen, wenn es sich geändert hat ******/ var sLastHistoryDate=getState('0_userdata.0.Sicherheit.dLastHistoryDate').val; var sCurrentDate=formatDate(new Date(), "<B>JJJJ.MM.TT</B>"); if (sCurrentDate != sLastHistoryDate){ setState('0_userdata.0.Sicherheit.dLastHistoryDate', sCurrentDate, true); strTmp = sCurrentDate + "<br>"; } /***** den Text 'Offen Seit..." ermitteln ******/ var strTmp="" if (InDauerText + "" == ""){strTmp = strTmp + formatDate(new Date(), "<B> SS:mm</B>:ss") + " " + String(InText) + "<br>";} else{ if(InDauerText>59){ InDauerText=(InDauerText/60).toFixed(1); strTmp = strTmp + formatDate(new Date(), "<B> SS:mm</B>:ss") + " " + String(InText) + ", " + InDauerText + " Min. offen<br>"; } else{ strTmp = strTmp + formatDate(new Date(), "<B> SS:mm</B>:ss") + " " + String(InText) + ", " + InDauerText + " Sek. offen<br>"; } } sLog[i]=strTmp;sTxt[i]=InText;sDauer[i]=InDauerText;sInSay[i]=InSay;break; } } } async function StringArrayAusgeben(){ // Wird alle 15 Sek einmal aufgerufen for (var j = 0; j < 5; j++){ if(sLog[j]!="" ){ const result = await StringArrayAusgebenSub(sLog[j], sTxt[j], sDauer[j], sInSay[j], j);sLog[j]=""; // Alle 3 Sek eine Meldung ausgeben } } } function StringArrayAusgebenSub(InStrTimeStamp, InStr, InDauerText, InSay, InCounter){return new Promise(resolve => {setTimeout(() =>{ // Durchlauf: 3 Sek /***** Alarme am Handy aussagen, false InSay=true ******/ if (InSay && getState('0_userdata.0.Sicherheit.bAlarmIstScharf').val){request(URLSoundAusgabe + InStr.toLowerCase());} /***** Alarme in die LogDatei ergänzen ******/ wl(InStr, InDauerText); /***** Alarme im Objekt sAlarmLogHistory ergänzen ******/ InStrTimeStamp = InStrTimeStamp + String(getState('0_userdata.0.Sicherheit.sAlarmLogHistory').val); setState('0_userdata.0.Sicherheit.sAlarmLogHistory', InStrTimeStamp, false); resolve('resolved');}, iMeldungSpanne);}); } function wl(InText, InDauerText){ var fs = require('fs'); fs.appendFileSync(LogenInVerzeichnis, formatDate(new Date(), "DD.MM.YYYY") + ";" + formatDate(new Date(), "SS:mm:ss") + ";" + InText + ";" + InDauerText + "\n", 'utf8'); }
Die echten Programmer mögen meine Art der Codierung verzeihen. Doch, es tut, was es tun muss. Kann sicher optimiert werden. Vor allem, die anfängliche 15 Sek Warterei kriege ich nicht heraus.