NEWS
Einfache Funktion - Wertüberwachung mit 2 Verzögerungszeiten
-
Schau mal Folgendes.
Für eine fixe Verzögerung gibt es die delay Node. Wenn Du Dir die Hilfe kannst Du Dir das anpassen.
Die Verzögerung soll aber nicht aufaddiert werden sondern neu gestartet sobald der Wert aus dem entsprechenden Range war. Es soll nur einmal ein true oder ein false also Ausgang generiert werden.
Standardmässig wird jede Nachricht um einen fixen Zeitanteil verzögert, wenn Du also willst, dass die Verzögerung mit jeder Nachricht neu gestartet werden soll, dann musst Du vor jede Nachricht eine eigene Nachricht mit msg.reset setzen.
Für sowas nutzt man dann eine function Node.
Damit wird immer ein reset gesendet, bevor die payload gesendet wird. In dem Fall auch über delay noch mit einer variablen Verzögerung.
Schau mal ob der Flow das macht, was Du bzgl. Verzögerung macht, was Du willst, in dem Du die Inject Node nach Belieben betätigst.Hier mal zum Import:
Größer -50 und kleiner -300 soll überwacht werden für beide Werte soll eine einstellbare Verzögerung ablaufen.
Dazu lenkt man den Nachrichtenstrom einfach über eine switch Node an 2 verschiedene Ausgänge.
Es darf erst wieder ein true kommen wenn der aktuelle wert auf false steht und umgekehrt.
Das kannst Du über eine function Node machen oder einfach über den Flow Kontext und einer Switch Node filtern.
Der Vorteil von NodeRed - ist, dass Du jederzeit eine Debug Node an jede Stelle des Flows machen kannst und somit genau siehst, ob Deine Logik wie erwartet funktioniert.
-
@mickym hi vielen Dank für deine Ausführungen .. ich hab den code mal importiert ... zum testen.
Wenn ich injecte kommt nach 30 sek der payload raus .. wenn ich weiter injecte wird er neu gestartet ok und nach dem letzten klick eben läuft die zeit ... das muss ich nun abstrahieren für meine Anwendung ..
Ich hab einen Einspeisewert der schwankt angenommen ständig
wenn der länger als Zeit X kleiner -300 ist soll true resultieren .. wenn er jedoch länger als Zeit X größer -50 ist soll ein false resultieren. Das ganze müsste gegenseitig verriegelt sein , sodass halt das false nur kommt wenn das true aktiv ist und umgekehrt.Das ist meine Datenbasis
da schwirrt alle paar sekunden ein Wert ein[ { "id": "50ee6e8eb5c5f3a8", "type": "mqtt in", "z": "42d8e26124256b59", "name": "Netzübergabe", "topic": "openWB/evu/W", "qos": "2", "datatype": "auto-detect", "broker": "baede69d4c21ead9", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 150, "y": 280, "wires": [ [ "8f78648a1939bd66" ] ] }, { "id": "71f9943a7d86393c", "type": "victron-input-system", "z": "42d8e26124256b59", "service": "com.victronenergy.system/0", "path": "/Ac/ConsumptionOnOutput/L1/Power", "serviceObj": { "service": "com.victronenergy.system/0", "name": "Venus system" }, "pathObj": { "path": "/Ac/ConsumptionOnOutput/L1/Power", "type": "float", "name": "Power on output of inverter/charger, L1 (W)" }, "initial": "", "name": "", "onlyChanges": false, "x": 290, "y": 340, "wires": [ [ "8f78648a1939bd66" ] ] }, { "id": "8f78648a1939bd66", "type": "function", "z": "42d8e26124256b59", "name": "Berechnung Einschaltbedingung", "func": "if (msg.topic === \"openWB/evu/W\") context.set(\"netz\",msg.payload);\nif (msg.topic === \"Venus system - Power on output of inverter/charger, L1 (W)\") context.set(\"verbrauchAC\",msg.payload);\nif (msg.topic === \"Venus system - VE.Bus charge power (W)\") context.set(\"verbrauchDC\",msg.payload);\n\nvar netz = context.get(\"netz\") || 0;\nvar verbrauchAC = context.get(\"verbrauchAC\") || 0;\nvar verbrauchDC = context.get(\"verbrauchDC\") || 0;\n\n// Wenn Wert C negativ ist, addiere A und B, sonst gebe nur B aus\nif (verbrauchDC < 0) {\n msg.payload = netz + verbrauchAC; // A + B wird ausgegeben\n} else {\n msg.payload = netz; // Nur B wird ausgegeben\n}\n\nmsg.topic = \"NETZberechnung\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 710, "y": 260, "wires": [ [] ] }, { "id": "5a65949a3ab516bd", "type": "victron-input-system", "z": "42d8e26124256b59", "service": "com.victronenergy.system/0", "path": "/Dc/Vebus/Power", "serviceObj": { "service": "com.victronenergy.system/0", "name": "Venus system" }, "pathObj": { "path": "/Dc/Vebus/Power", "type": "float", "name": "VE.Bus charge power (W)" }, "name": "", "onlyChanges": false, "x": 240, "y": 400, "wires": [ [ "8f78648a1939bd66" ] ] }, { "id": "baede69d4c21ead9", "type": "mqtt-broker", "name": "", "broker": "192.168.123.14", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthRetain": "false", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closeRetain": "false", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willRetain": "false", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" } ]
-
@i0br0ker Ja ich habe weder ein Victron system noch habe ich Deine mqtt topics - also kann ich mit Dir nur zusammen die Logik entwickeln.
Ich hab einen Einspeisewert der schwankt angenommen ständig
wenn der länger als Zeit X kleiner -300 ist soll true resultieren .. wenn er jedoch länger als Zeit X größer -50 ist soll ein false resultieren. Das ganze müsste gegenseitig verriegelt sein , sodass halt das false nur kommt wenn das true aktiv ist und umgekehrt.
In diesem Fall würde ich nicht mit einer delay Node sondern einer trigger Node arbeiten. Ich werde also mal einen Flow entwerfen, in dem ich mit Inject Nodes den Wert -350, -200 und -30 in einen Flow injiziere.
-
hab sowas gerade mal gemacht
die Verzögerung müsste genau umgekehrt sein ... das heisst der wert müsst für zeit x ständig getriggert werden damit er auslöst -
@i0br0ker Ja deswegen ist das mit der delay Node falsch - ich entwerfe Dir einen komplett anderen Flow.
-
@i0br0ker Ich gehe mal davon aus, dass wenn zwischen -50 und -300 kommt, dann soll der timer immer zurückgesetzt werden.
-
@mickym hmm .. ja genau sollte so sein ... heisst wenn die einspeisung länger weg fällt ( zeit X) also der wert angenommen 0 ist muss er false schalten und wenn er länger als zeit X einspeist also -400 muss true schalten - das ganze sollte die ganze zeit hin und her korrespondieren und nichts doppelt passieren.
-
@i0br0ker sagte in Einfache Funktion - Wertüberwachung mit 2 Verzögerungszeiten:
@mickym hmm .. ja genau sollte so sein ... heisst wenn die einspeisung länger weg fällt ( zeit X) also der wert angenommen 0 ist muss er false schalten und wenn er länger als zeit X einspeist also -400 muss true schalten - das ganze sollte die ganze zeit hin und her korrespondieren und nichts doppelt passieren.
Du kannst es gleich probieren - einen kleinen Moment noch.
-
@i0br0ker So dann schau mal, ob das so tut wie Du willst. Mit den Inject Nodes simulierst Du den Eingang.
Am Anfang den delay setzen mit der Inject Node. Später kannst Du den Flow kontext dann selbst modifizieren.
Hier der Import:
Wie Du siehst ohne function Nodes und ohne eine Zeile Code zu schreiben.
-
@mickym krasses Konstrukt aber es scheint zu passen .. gut ich brauch halt 2 versch. Verzögerungen aber die kann ich ja hard rein coden in den trigger ...
Ich werde es morgen live testen wenn die Sonne scheintDANKE an der Stelle schonmal für die Hilfe und deine Zeit
-
@i0br0ker Du kannst den msg.delay auch an die unterschiedlichen Ausgänge setzen - dann brauchst die flow Variable nicht. Kommt halt darauf an, wie Du es modifizieren willst. Aber wie Du siehst ist es sehr transparent und man kann an jeder Node prüfen, ob die Logik funktioniert und muss sich nicht durch Code quälen.
Ja oder einfach in die trigger Nodes eintragen - das ist am einfachsten und dann kannst Dir den flow Kontext sparen. Wenn Du die Verzögerung direkt in die trigger Node einträgst, dann kannst Du diese Nodes wegschmeißen
-
Darf ich an dem Thema nochmal anknüpfen
Ich bin gerade am testen und habe noch folgendes Problem.
Ich bekomme von 3 quellen Werte mit unterschiedlichen datenraten.
Ich würde diese 3 Quellen gerne zeitgleich in eine Funktion einspeisen, die eine Berechnung macht.
Alles was ich bisher versucht habe funktioniert nicht wirklich ( Begrenzung der Nachrichten ) .. weil dann zufällig nur einzelne Quellen übertragen werden.Die Berechnung ist folgende:
Also ich würde gerne alle 3 Werte vorhalten und dann zeitgleich berechnen und ausgeben in einem 5 Sekunden Intervall zum Beispiel ...
-
@i0br0ker Also ich kann an dem Code nichts falsches finden und verstehe das Problem nicht wirklich. Natürlich kann man das alles mit weniger Code machen.
Alles was ich bisher versucht habe funktioniert nicht wirklich ( Begrenzung der Nachrichten ) .. weil dann zufällig nur einzelne Quellen übertragen werden.
Das ist doch richtig, weil nur dann was ausgegeben wird, wenn sich was geändert hat. Ansonsten musst Du sagen was Du willst:
- Du wartest bis alle 3 topics einen Wert geliefert haben?
- Du möchtest generell eine kontunierliche Ausgabe der letzten Berechnung (auch wenn sich nichts geändert hat.
Zu Punkt 1 - würde ich das ganze dann nicht über den Kontext machen, sondern eine Nachricht mit allen Werten erzeugen, die Du dann von mir aus wieder mit Code für die Ausgabe behandeln kannst.
Zu Punkt 2: Einfach eine Trigger Node die letzte Nachricht im 5s Intervall ausgeben lassen.Zeitgleich passiert nur etwas in dem Du es sammelst - wie gesagt wenn Du warten willst, dass alle 3 topics geliefert haben müssen, um eine saubere Berechnung zu ermöglichen oder nicht? Es wird immer ms zeitliche Unterschiede geben, wenn die Dinge in das System kommen, da generell NodeRed oder auch andere Systeme alle Inputs nur sequentiell verarbeiten, wenn auch im ms Bereich.
Ich werde Dir wieder mal einen Flow mit den 3 Messgrößen mit Inject Nodes zur Simulation bereitstellen und Deinen Code zur Berechnung benutzen.
-
@mickym ich hab es nun mal so gemacht
Ich speichere die 3 Werte in jeweils in einer Flow variable und triggere die Berechnung dann
alle Sekunde mit dem Inject.
So hab ich immer den zuletzt gemessenen Wert der 3 Datenquellen zur sekündlichen Berechnung -
@i0br0ker Ja und das ist halt Käse, weil Du nicht davon ausgehen kannst, dass sich alle Sekunden, welche Werte geändert haben und Du somit nur ein zufälligest Zustandsbild bekommst. Ausserdem belasstest Du das System nur unnötig mit dieser Inject Node und dem sekündlichen Trigger. Sinnvoller ist es die 3 Teile Einspeisung, AC und DC triggern zu lassen. Ich mach Dir mal einen Vorschlag in dem ich die 3 Nodes Einspeisung, AC und DC mit Inject Nodes simuliere - und du quasi den Rest des Flows mal hinter Deine Nodes machst.
-
@i0br0ker So hier mein Vorschlag:
Statt der Inject Nodes klemmst Du die Change Nodes zum Vereinfachen der topics hinter Deine function Nodes.
Die beiden Varianten unterscheiden sich wie folgt. Oben müssen alle 3 Werte aktualisiert werden, bevor eine erneute Berechnung stattfindet. Unten wird nachdem alle 3 Werte geliefert wurden, nach jeder Änderung eine Berechnung durchgeführt.
Unten ist einfach die blau markierte Option angehakt.
Hier zum Import:
Alle Sekunden zu triggern - ohne das eventuell eine Änderung stattgefunden hat, ist mE Unsinn. Wenn Du einen konstante Ausgabe willst, auch ohne das sich was geändert hat, kannst Du auch die letzte Berechnung dauernd mit einer Triggernode ausgeben. Keine Ahnung - vielleicht für einen Grafen.
Eine Triggernode - kann die letzte Berechnung dann kontinuierlich senden, falls Du das wünschst.
Ist aber meines Erachtens auch nur unsinniger Overhead - da brauche ich dann auch keine Begrenzung.
-
Vielleicht schaffe ich es ja noch, Dich von der Codiererei wegzubringen und Dich von den Vorteilen der grafischen Programmierung mittels NodeRed zu überzeugen.
-
@mickym ja so langsam aber sicher verstehe ich die funktionsweise
Super hab es eingebaut und es läuft ... aber eine Frage:
Hinten raus variieren die Topics - dort finde ich immer mal wieder alle 3 eingangs Topics.
Was sagt mir das dann? der Topic der da drin steht hat auch getriggert zu dem Zeitpunkt? -
@i0br0ker Ja der topic der da drin steht, war der letzte - das war ja die letzte Nachricht die getriggert hat. Wie gesagt, wenn Du willst, dass alle 3 immer neue Werte geliefert haben wollen, dann musst Du die Option auslassen. Du könntest theoretisch auch mit einer Switch Node filtern, dass Du nur dann eine Berechnung durchlässt, wenn ein bestimmter topic getriggert hat. Wie gesagt eine Parallelverarbeitung wirst Du in keinem Hausautomationssystem finden, sondern es wird immer einen zeitlichen Abstand zwischen den einzelnen Triggern geben.
Das topic dass Du hinten siehst, stammt also von einem der 3 Change Nodes mit dem Du die topics festlegst.
Das ist ja Bestandteil des Nachrichtenobjektes - auch wenn Du in der payload alle 3 Werte in einem Objekt zur Berechnung immer mitschleppst.
Am Besten siehst Du das, in dem Du Dir das gesamte Nachrichtenobjekt hinter der JOIN Node ausgeben lässt.
In der Berechnung überschreiben wir ja dann das payload Objekt wieder mit einem skalaren, numerischen Wert.
Das topic wird aber nicht angefasst. Du könntest das topic auch löschen oder einfach ein neues Topic Netzberechnung setzen, wenn es Dich verwirrt.
-
@mickym Wenn Du sagts die Einspeisung ist immer konstant, Du willst aber nur dann eine neue Berechnung machen, wenn sich verbrauchAC und verbrauchDC getriggert wurden, dann kannst Du das auch kaskadieren. Aber wie gesagt, Du musst Dich entscheiden - WANN Du eine Berechnung durchführen willst. Einen definierten Zeitpunkt musst Du festlegen und kann nicht das System für Dich festlegen.