Hallo werte Forumsmitglieder,
um meine Logs zu Minimieren, suche ich nach Lösungen um unwichtige Werte nur gelegentlich abzufragen. Das wollte ich mittels Intervalle realisieren.
1.) Interval für ein Device:
Ich möchte gerne den Interval für ein Device via Script ändern.
z.B. den Interval für das Abfragen meines Devices "Wallbox" ändern, jeh nachdem ob ein Fahrzeug angesteckt ist oder nicht.
Also alle z.B. 15 Minuten checken ob "Connected", wenn ja dann alle 20 Sekunden die Ladewerte abfragen.
2.) Poll Interval für ein Attribut:
Die zweite Änderung betrifft das Poll Interval, das ich via Script ändern möchte. Ich möchte den beim Anlegen vergebenen Pollinteval dynamisch jeh nach Situation ändern. Also einen kurzen Deviceinterval und längere (dynamisch änderbare) unterschiedliche Intervalle für die einzelnen Attribute.
Bitte hat jemand so etwas schon gemacht und kann mit dabei helfen?
Viele Grüße
wollik
Ich mache sowas beispielsweise 1. zur Abfrage der Stundenpläne der Kinder (in Richtung Änderungen, Entfall) oder auch 2. für die Abfahrten an der Bushaltestelle oder auch 3. für die JSON-Abfrage an meiner C.M.I der technischen Alternative.
Was ich aber nicht mache: Intervalle oder Attribute dafür ändern. Ich weiß jetzt nicht, was für Geräte du dafür hast, aber die meisten die über Intervall zyklisch abrufen können, können das auch über get/set Befehle (z.B. reread by HTTPMOD) auf Kommando tun.
Für deinen Fall eins, könnte dann ein einfaches DOIF helfen:
defmod di_wallBoxData DOIF ([wallbox:connected] eq "Connected" and [+00:00:20]) (set wallbox reread)\
DOELSEIF ([+00:15:00]) (set wallbox reread)
Deinen Punkt 2 habe ich nicht verstanden. Aber Attributänderungen sind immer eine Änderung der Konfiguration. Wenn du das Problem bzw. was du eigentlich erreichen möchtest, genauer beschreiben könntest, kann bestimmt geholfen werden.
Ich mache bei den oben genannten:
- Stundenplan: DOIF mit festen Zeiten (morgens öfter als den Rest des Tages um kurzfristige Ändeurngen mitzubekommen. Könnte auch auf Intervall im Zeitraum umstellen...
- Abfahrten: Ein langsames Abfrageintervall und dann runter bis zu 30 Sekunden je näher der nächste Abfahrtstermin rückt, um Verrspätungen möglichst genau darzustellen.
- CMI: Erlaub nur eine Abfrage pro Minute. Da ich aber zwei unterschiedliche Knoten Abfrage, muss ich sicherstellen, dass die sich nicht gegenseitig behindern. Somit wird über ein DOIF (ein at hätte es hier auch getan) alle 61 Sekunden im Wechsel der jeweilige Knoten abgeftagt...
Wie wärs damit, unwichtige Werte ganz einfach nicht zu loggen?
Dann ists vollkommen egal, wie oft die Daten abgerufen werden.
Einerseits eine sinnvolle Regex für das Log, und andereseits einfach die Events reduzieren.
Stickwörter event-on-update-reading, event-on-change-reading, event-min-interval
lg, Stefan
Ja natürlich. Mir gehts dabei nicht ums loggen und auch nicht um unnötige Events sondern um unnötige Last im Netz (LAN und WAN). Und dafür ist es unabhängig der Events und Logs nicht egal wie of abgefragt wird.
Und insbesondere dann wenn ich nur wenige Werte logge und wegen event-on-change-reading ohnehin kein Event auslöse, ist es Ressourcenverschwendung zu oft und unnötig abzufragen.
Aber dein Vorschlag ist trotzdem richtig, garnicht erst zu loggen uund events zu vermeiden wenn man es nicht braucht...
Threadtitel und Problembeschreibung gehen da etwas auseinander ;)
LG und einen schönen Nikolaustag,
Tobi
LG,
Tobi
Hallo Icinger,
unter "Unwichtige Werte/Daten" verstehe ich bei meinem Wallboxbeispiel für alle 3 Phasen die Volt, Amper und Leistungs Werte, die ich nicht brauche wenn kein Auto angeschlossen ist, da dann Ampere und Leistung pro Phase immer 0 sind. Also kann ich auf das Loggen für diese Werte nicht verzichten, denn ich brauche diese Daten wenn das Auto läd.
Die Idee mit: event-on-update-reading, event-on-change-reading, event-min-interval sind natürlich eine sehr gute Idee. DANKE
Da muss ich mir mal anschauen wie ich das mit den Volt-Werten hinbekomme, denn die ändern sich ja jeh nach Netzlast, ob ein Auto geladen wird oder nicht.
wollik
Hallo tobi01001,
DANKE für Dein Beispiel mit dem zeitgesteuerten DOIF.
Wie sollte dann der Interval für das Device gesetzt werden?
Bitte könntest Du mir noch helfen wie die Abfrage für mit diesen Werten aussehen müsste?
Fhem_Device.........: OpenWB
Device_Readings.....: LP1_Plugged_Status
Device_Reading_Value: 1 (oder 0)
Also von Deinem Beispiel:
([wallbox:connected] eq "Connected" ....
Auf meine Umgebung:
([OpenWB:LP1_Plugged_Status] eq "1" .....
Zu meinem Interval pro Attribut:
Wenn mein PV-Inverter keinen Strom erzeugen kann (da nachts) möchte ich auch keine PV-Daten loggen. Ich brauche aber auch weiterhin (nachts) die Inverterdaten für die Hausversorgung und für meine Speicher.
Also die Idee war das Deviceinterval zu lassen und nur die Polintervalle für die PV-Erzeugungsattribute zu ändern.
Evtl. kann ich das mit event-on-change-reading lösen.
Aber ich wäre doch an einer Möglichkeit interessiert um den Pollinterval für ein einzelnes Attribut ändern zu können.
D A N K E
wollik
Ohne list deiner Device(s) wird das schwierig, weil ich/man ohne Kenntnis von Modul und definitio0n / attrribute etc. nicht sagen kann, was wie zu ändern wäre.
Interval für das Device würde ich dann ganz abschalten oder - sofern das nicht geht - auf eine Stunde oder gar mehr setzen.
Dein Ansatz mit ([OpenWB:LP1_Plugged_Status] eq "1") ist ok, nützt aber nichts, wenn man den Befehl zum Abholen der Daten nicht kennt.
Und beim Inverter ist es das gleiche, "das ganze Leben ist ein Quiz... und wir raten, raten, raten" ;D
Ohne List wird das nichts.
Aber wenn Nachts nichts erzeugt wird, kommen - wie Stefan schon angemerkt hatte - mit "event-on-change-reading" auch keinerlei Events und Logeinträge. Das ist wesentlich einfacher (und in dem Fall mMn auch viel sinnvoller) als ständig Attribute zu ändern - zumal du ja auch Grenzwerte / Schwellwerte angeben könntest, falls der Inverter Nachts um ein paar mA rumeiern sollte.
Gruß
Tobi
Hallo Tobi,
es handelt sich bei meiner Wallbox um eine "openWB". Diese ist in Fhem als Modbusdevice angelegt:
defmod OpenWB ModbusAttr 1 10 192.168.10.243:502 TCP
wobei diese 10 den Abfrageinterval in Sekunden festlegt.
Die verschiedenen Readings für dieses Device haben alle einen Pollinterval von 1, wodurch die Readings also alle 10 Sekunden von der Walbox abgeholt werden.
...
attr OpenWB obj-h10109-expr $val/100
attr OpenWB obj-h10109-poll 1
attr OpenWB obj-h10109-reading LP1_A3
attr OpenWB obj-h10109-type S16
...
attr OpenWB obj-h10114-poll 1
attr OpenWB obj-h10114-reading LP1_Plugged_Status
attr OpenWB obj-h10114-type S16
Also steht im Reading: LP1_Plugged_Status immer eine 1 oder eine 0.
In den Set Optionen für mein Device OpenWB habe ich auch die Option für "reread", den ich manuell ausführen kann, damit sollte es auch per Script wie Du es verwendest funktionieren. Ich probier das mal aus.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Das ich Schwellwerte bei "event-on-change-reading" setzen kann wußte ich nicht, das schau ich mir mal genauer an.
Aber das "event-on-change-reading" hilft nur um Logging zu miminieren, nicht aber um Traffic zu minimieren, aber die Reduktion des Traffics war ja auch nicht mein Hauptansatz.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Weiter wäre auch noch von Interesse wie fhem UserAttribute für ein Device, die via Scripte bearbeitet werden aktiviert.
1) Werden die aktiviert wenn der Deviceinterval zuschlägt?
Gibt es da evtl. auch einen PollIntervall für UserAddribute?
oder
2) Wenn sich ein Reading, das im Script verwendet wird ändert?
Hier mein Script zum Berechnen der Leistungen pro Phase:
attr OpenWB userReadings\
L1 {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V1", 0) * \
ReadingsNum ("OpenWB","LP1_A1", 0)));;},\
L2 {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V2", 0) * \
ReadingsNum ("OpenWB","LP1_A2", 0)));;}, \
L3 {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V3", 0) * \
ReadingsNum ("OpenWB","LP1_A3", 0)));;}
Bitte was für eine Liste bräuchtes Du?
DANKE erst mal, ich melde mich wenn ich weiter bin.
Viele Grüße
wollik
OpenWB_via_Modbus.txt
Hallo Tobi,
Dein Weg über das DOIF funktioniert leider nicht, der Befehl:
(set OpenWB reread) wird nicht ausgeführt;(
Ich habe eine neue Anfrage zu dem Modbus Device hier ins Forum gestellt, evtl. gibt es darüber weitere Infos.
Siehe: https://forum.fhem.de/index.php?topic=140009.msg1327152#msg1327152
DANKE erst mal für Dein DOIF, aber die Fragen zum Setzen der Device- oder Attributinterfalle bleibt noch offen.
Viele Grüße
wollik
Bin am Handy, daher nur kurz: setz mal bitte im DOIF das attribut do auf always.
Hatte ich vergessen ;D
Bei modbus kannst du die register auch einzeln abfragen. Das wäre wahrscheinlich effizienter als ein komplettes reread.
Kann ich vielleicht später mal schauen.
Bzgl list: unten in der device Ansicht ein "copy for fhem forum" und dann hier in Code Tags posten. Vorher schauen, dass keine persönlichen oder geheimen Daten dabei sind...
Hallo Tobi,
JAAA das wars!!! Mit do always kommen nun die Daten jeh nach Interval.
D A N K E
Bitte hast Du noch ein Beispiel um z.B. nur ein Modbusreading abzuholen?
Auslesen geht ja mit: ReadingsVal, aber da steht der Wert vom letztem Abholen drin.
Viele Grüße
wollik
Das Attrribut obj-h...-poll 1 sagt nur, dass dieses Register / diese Adresse zyklisch im Intervall mit abgeholt wird.
Wenn das Intervall entsprechend hoch ist, passiert das dann nicht so häufig. Aber es gibt sicher Werte, die man gar nicht regelmäßig holen braucht oder nur sehr selten weil die sich fast nie ändern.
Zitat von: wollik am 07 Dezember 2024, 13:46:02Bitte hast Du noch ein Beispiel um z.B. nur ein Modbusreading abzuholen?
Anstatt -poll 1 kannst du für diese Readings auch ein "obj-....-showGet 1" verwenden. Damit werden sie manuell über z.B. get OpenWB LP1_A1 abgerufen und aktualisiert.
Aber du hast in der OpenWB eh nicht so viele Readings und brauchst diese wahrscheinlich auch - zumindest beim Laden - realtiv häufig.
Die Frage ist, wie schnell du den Ladezustand erkennen willst/musst... Ich würde in etwa folgendes machen:
set OpenWB stop
attr OpenWB obj-h10114-showGet 1
defmod di_OpenWB_Data \
DOIF ([OpenWB:LP1_Plugged_Status] eq "1" \
and [+00:00:20]) (set OpenWB reread) \
DOELSEIF ([+00:01:00]) (get openWB LP1_Plugged_Status)
Damit würde, solange nichts an der WB angeschlossen ist, lediglich der plugged status im eingestellten Intervall geholt. Ist dann ein Fahrzeug angesteckt, wird alle 20 sekunden aktualisiert.
Deine userReadings haben keinen Trigger definiert. Die werden dann mit jedem Event, also jedem gelesenen Wert berechnet. Das ist unnötig.
Eleganter wäre
attr OpenWB userReadings \
L1:(LP1_V1|LP1_A1).* {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V1", 0) * \
ReadingsNum ("OpenWB","LP1_A1", 0)));;},\
L2:(LP1_V2|LP1_A2).* {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V2", 0) * \
ReadingsNum ("OpenWB","LP1_A2", 0)));;}, \
L3:(LP1_V3|LP1_A3).* {sprintf("%.0f", ( \
ReadingsNum ("OpenWB","LP1_V3", 0) * \
ReadingsNum ("OpenWB","LP1_A3", 0)));;}
Hallo Tobi,
JAAA das mit showGet 1 ist eine sehr gute Lösung D A N K E !!!
Die Funktion mit dem Trigger L1:(LP1_V1|LP1_A1).* habe ich nicht verstanden!?!
Bedeutet ":(LP1_V1|LP1_A1).*" das bei Änderungen von LP1_V1 oder von LP1_A1 der Wert vor dem ":" gesetzt wird?
Falls das so ist, bräuchte ich keinen Check auf LP1_V1 da sich dieser Wert oft marginal ändert aber nicht benötigt wird wenn LP1_A1 0 ist oder sich nicht geändert hat. Die Berechnung der Leistung V * A ist um ca. 20% zu hoch, also sehr ungenau, darum macht eine kleine Änderung im Voltbereich keinen großen Unterschied.
Aber wenn sich LP1_A1 ändert ist eine neue Berechnung von nöten.
Hier die Bedeutungen meiner OpenWB Readings:
LP1_V1 -> Am LadePunkt 1 Volt an der Phase 1
LP1_V2 -> Am LadePunkt 1 Volt an der Phase 2
LP1_V3 -> Am LadePunkt 1 Volt an der Phase 3
LP1_A1 -> Am LadePunkt 1 Ampere via Phase 1
LP1_A2 -> Am LadePunkt 1 Ampere via Phase 2
LP1_A3 -> Am LadePunkt 1 Ampere via Phase 3
Also würde mir doch:
L1:(LP1_A1).* {sprintf("%.0f", (\[/i][/b] genügen wenn ich die kleinen Änderungen an LP1_V1,2,3 ignorieren möchte oder?
Viele Grüße
wollik
Zitat von: wollik am 07 Dezember 2024, 17:01:00Also würde mir doch:
L1:(LP1_A1).* {sprintf("%.0f", (\[/i][/b] genügen wenn ich die kleinen Änderungen an LP1_V1,2,3 ignorieren möchte oder?
Ja, dann kannst du auch einfach L1:LP1_A1.* machen.
Wie kommst du auf die 20% Ungenauigkeit? Womit vergleichst du das?
Hallo Tobi,
es gibt ein Register, das die Leistung über alle 3 Phasen ausgibt. Wenn nur mit einer Phase geladen wird, müßte die Leistung L1 gleich groß wie die Gesamtleistung sein.
Beim 3 phasigem Laden muss ich erst alle drei Phasen zusammen zählen was auch eine um ca. 20% zu hohe errechnete Leistung anzeigt.
Viele Grüße
wollik
Zitat von: tobi01001 am 07 Dezember 2024, 18:07:13Zitat von: wollik am 07 Dezember 2024, 17:01:00Also würde mir doch:
L1:(LP1_A1).* {sprintf("%.0f", (\[/b] genügen wenn ich die kleinen Änderungen an LP1_V1,2,3 ignorieren möchte oder?
Ja, dann kannst du auch einfach L1:LP1_A1.* machen.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hallo Tobi,
derzeit wird mein Userreading L1 immer gesetzt wenn sich der Wert von L1_A1 ändert: L1:(LP1_A1).*
Bitte wie müßte die Syntax aussehen wenn ich das Userreading L1: beim nächsten Interval nur setzen will, wenn das Reading: LP1_Charge_Active auf "1" steht?
L1: ([LP1_Charge_Active] == 1 )
Ich bekomme keinen Syntaxfehler, aber bin mir nicht sicher ob das so funktioniert.
Bitte wie siehst Du das, oder wie würdes Du das realisieren?
Viele Grüße
wollik
Hi,
keine Ahung ob die eckigen Klammern für den Wert in dem Fall funktionieren (glaubs nicht). Aber du würdest ohnehin nur auf Events von Charge_Active triggern und rechnen. Damit ist die Berechnung im Zweifel arg statisch bzw. nutzlos.
Du kannst aber im userreading selbst Abfragen ob Charge_Active 1 ist und andernfalls 0 zurückgeben. In etwa so:
attr OpenWB userReadings L1:LP1_A1.* \
{\
if(ReadingsNum("OpenWB", "LP1_Charge_Active", 0) == 1) {\
sprintf("%.0f", (ReadingsNum("OpenWB","LP1_V1", 0) * ReadingsNum("OpenWB","LP1_A1", 0)));; \
} else {\
0;;\
}\
}, ...
Hallo Tobias,
DANKE für die schnelle Antwort,
aber ich möchte für dieses userReading nichts ausrechnen (für andere schon), sondern nur den Wert setzen wenn LP1_Active_Charge == 1
Hier mein Versuch zum Setzen des userReadings Total_Active_Energy:
Total_Active_Energy:(LP1_Charge_Active).* {\
if(ReadingsNum("OpenWB", "LP1_Charge_Active", 0) == 1)\
{sprintf("%.0f",(qx( ..... )));;}
Nur wenn LP1_Charge_Active == 1 dann soll ein Shell Befehl mittels qx ausgeführt und der Rückgabewert in das userReading geschrieben werden.
Wenn LP1_Charge_Active != 1 ist, soll das userReading nicht überschrieben werden.
Könnte das so funktionieren ? Ich kann es erst Testen wenn genug PV-Leistung für meine WB zur Verfügung steht.
Viele Grüße
wollik
Testen kann man immer... - zur Not mit Dummy's.
Ob du rechnest oder nicht, ändert an der Logik auch nichts.
Wenn du aber nur auf LP1_Charge_Active triggerst, wirst du deinen Wert nur bekommen, wenn Charge_Active auch ein Event auslöst. Wenn dann z.B. event-on-change-reading gesetzt sind, kommt der Wert einmal beim Wechsel von x auf 1, ansonsten bei jedem Event (was du im Eventmonitor beobachten kannst).
D.h. dein userreading braucht einen trigger falls es sich tatsächlich dynamisch in Abhängigkeit von ? ändern soll. Ich verstehe den Use-Case nicht bzw kann mir nicht vorstellen was dein eigentliches Ziel ist.
Total_Active_Energy soll was sein und bekommt welchen Wert? Klingt nach einem Anwendungsfall für "monotonic" ggf. in Kombination mit "LP1_Charge_Active".
Hallo Tobi,
also ich habe ein Device: OpenWB.
Tagsüber werden je nach Verbindungsstatus (LP1_Plugged_Status == 1) entweder alle 30 Minuten oder alle 5 Minuten) die Devicewerte abgefragt.
Das ist der Trigger für das Lesen der Readings also alle 5 oder 30 Minuten.
Leider gibt es bei der OpenWB kein Modbus Register über das man/frau sich den Wert des Energymeters auslesen kann, weßhalb ich mir ein userReading Total_Active_Energy angelegt habe, das mit einem Shellbefehl beschrieben wird.
Bei jedem Lesen der Device Readings, wird auch mein userReading Total_Active_Energy über den Shellbefehl gesetzt.
Ich suche nach einer Möglichkeit dieses userReading nur zu setzen und einen Logeintrag zu machen, wenn das Auto läd, dann steht nämlich das Reading: LP1_Charge_Active auf 1. Wenn das Auto nicht läd, soll mein userReading nicht überschrieben werden und ich möchte keinen Logeintrag mit dem alten Wert.
Vielen Dank für Deine Unterstützung bei diesem wilden Konstrukt.
wollik
Zitat von: wollik am 06 Februar 2025, 16:03:02Wenn das Auto nicht läd, soll mein userReading nicht überschrieben werden und ich möchte keinen Logeintrag mit dem alten Wert.
Dann musst Du dafür sorgen, dass in diesem Fall der Rückgabewert für das userReading 'undef' (ohne Anführungszeichen) ist.
Hallo Betateilchen,
also ich müßte einen else Zweig einbauen der mir undef zurück gibt, wie könnte das für dieses userReading dann aussehen?
Total_Active_Energy:(LP1_Charge_Active).* {\
if(ReadingsNum("OpenWB", "LP1_Charge_Active", 0) == 1) \
sprintf("%.0f",(qx( ..... )));;\
}\
else { \
? \
}
DANKE und viele Grüße
wollik
Verwende bitte endlich code tags in Deinen postings. Danke.
Zitat von: wollik am 08 Februar 2025, 16:17:10also ich müßte einen else Zweig einbauen der mir undef zurück gibt, wie könnte das für dieses userReading dann aussehen?
Zum Beispiel so:
Total_Active_Energy[/b]:(LP1_Charge_Active).* { ReadingsNum("OpenWB","LP1_Charge_Active",0)?sprintf("%.0f",(qx( ..... ))):undef }
Es gibt mehrere Lösungsansätze. Grundsätzlich bin ich kein Freund von qx() in solchen Konstrukten, aber das wollte ich jetzt nicht auch noch ändern.