NEWS
Vergleich von zwei Eingangswerten um Wert festzulegen
-
@claus1985-0 sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Die beiden Eingangsnachrichten kommen zwar an aber aus Join kommt danach nichts raus.
Kann das daran liegen, dass die beiden Eingänge nicht gleichzeitig Nachrichten senden?Nun am Anfang wird abgewartet bis jede Nachricht gesendet wurde - es liegt eher daran, wenn ich mir Dein Log anschaue, dass beide Nodes das gleiche Topic haben. Somit kann die JOIN Node nicht unterscheiden, dass die Nachricht von 2 verschiedenen Nodes stammt. Setze mal zwischen die JOIN Node und den Loxone Teilen explizit das Topic. (Einmal hoch und einmal runter)
Den Haken in der JOIN Node ist ja gesetzt:
Sprich: die JOIN Node beginnt erst zu senden, wenn einmal beide Nodes mit unterschiedlichen Topics gesendet haben, dann aber sofort immer - also hat nichts mit gleichzeitig zu tun.
-
@rewenode sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
@mickym sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Ich wußte gar nicht, dass das geht - komischerweise aber nur mit enthält - wenn ich mit == versuche zu vergleichen - dann tut es nicht.
Der
payload.* (oder einfach $.*)
gibt nach dem Join ein Array mit 2 Werten zurück, das kannst du nicht mit einem Number vergleichen. Wohl aber fragen, ob ein bestimmter Wert enthalten ist.
Gruß
ReinerHerzlichen Dank! - Schön, wenn Du mir auch immer wieder hilfst mit Deinem Wissen.
Im Prinzip wird also mit $* einfach so ein Array gebildet, dass ich mit dem $each nochmal auseinander fummle? und dann wohl für den Vergleich nur ein match ala regEx gemacht.
OK sehe ich - allerdings muss man es dann für die Vergleiche trotzdem auseinander fummeln.
$each( $.*, function($v) {$v=0 ? true: false} );
Insofern hilft mir die Schreibweise ja eigentlich nichts. Ob ich jetzt payload oder $.* schreibe, da ist dann payload beschreibender.
-
Habe meinen vorhergehenden Post überarbeitet. Die topics müssen zwingend hoch und runter heißen - da sonst ja der Flow nicht mehr passt.
Ansonsten musst Du halt alle Nodes an die neuen Topics anpassen.
So hier nochmal der komplette Flow - direkt zum Anflanschen der Loxone Nodes:
Mit aufgenommen wurde das Ausfiltern, dass beide Nodes 1 liefern:
-
@mickym sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Ob ich jetzt payload oder $.* schreibe, da ist dann payload beschreibender.
Ja, da hast du recht. $ steht in JSONata für das komplette Eingabedocument (siehe ganz unten)
In Node-Red steht das $ dann für das, dem JSONata-Ausdruck, vorgesetzte Eingabeobjekt. Im konkreten Falle also payload.
$$ bezeichnet dagegen immer das Top level Object wie hier ganz gut beschrieben .Gruß
Reiner -
Danke schön. Die UK - Seite kannte ich noch nicht. Die andere war bislang schon meine Referenz.
-
@mickym sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Hier mal meine erfolgreichen JSONATA Switches - der letzte Flow - ist der gerade gepostete und der vorletzte war Deiner mit dem Wildcard und enthält.
Hi, da muss ich ganz ehrlich sagen, das ich das für mich für zu unübersichtlich halte, wenn ich nach Wochen mal schauen will was ich da umgestezt habe, auch kenne ich mich da ehrlich gesagt nicht genug mit Json bzw. Java aus um das aus dem Stehgreif nachvollziehen zu können. Da passiert mir zu viel versteckt in der Change Node. Wenn ich wirklich nur 2 verschiedene Status überwachen will, z,B. true oder false bzw. 1 oder 0 finde ich meine Lösung mit dem Switch und danach die Change Node zum payload setzen nachvollziehbarer. In meinem Fall nutze ich das z.B. um mir in der Vis anzeigen zu lassen ob in einem bestimmten Raum Licht an ist. Ist einer der Datenpunkte true, ist das Icon Gelb, andernfalls ist es schwarz.
Wenn man natürlich mehrere verschiedene Werte z.B. 0-100 bekommt, vereinfacht deine Version mit der Change Node die ganze Sache sehr, wenn ich nur ne Ausgabe, wenn alle 0 sind oder bei nem anderen bestimmten Wert haben will. -
@frankyboy73 Ich habe jetzt meine function Nodes - die alle Objekteigenschaften überprüft haben durch folgende logische Nodes ersetzt:
Geht halt nur bei true und false - aber dann ist das sehr einfach nun.
-
@mickym Ok, das ist jetzt auch für mich nachvollziehbarer. Du hast ja sogar nen Hilfe Text zu den Switches geschrieben. Vielleicht sollte ich sowas, bei meinen Umsetzungen auch mal öfter machen, dann weiß man später auch wofür man das gemacht hat. Tolle Idee.
@mickym
Aber durch das was da in Json drin steht steige ich nicht durch, ich sehe bei dem "and" switch nicht wie abgefragt wird ob alle true sind. Könntest du mir das noch als switch wo alle false sein müssen zu Verfügung stellen? -
@mickym hat funktioniert, besten Dank!
Eine Frage habe ich noch. Gibt es eine Möglichkeit mehrere Blöcke welche in Summe eine zusammenhängende Funktion bilden irgendwie zusammen zu fassen?
Hintergrund: Wenn ich die Funktion öfter benötige wäre es ja cool wenn ich sie nur einmal erstellen muss und dann quasi an mehreren Stellen darauf verlinken könnte. -
@claus1985-0 Hier als Gruppe und einer eigenen Node für die Zukunft.
Wenn Du nur die Node benutzt - musst halt immer Bedenken, dass den topic hoch und topic runter setzt bevor Du die Node fütterst. Kannst Dir ja auch einen Hilfetext dazu schreiben.
-
@mickym sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Ich habe jetzt meine function Nodes - die alle Objekteigenschaften überprüft haben durch folgende logische Nodes ersetzt:
Super
Du kannst die Ausdrücke noch um Einiges vereinfachen. Hier mal am Beispiel der OR mit den 2 Augängen:
( $withOR := function($i, $j){$i or $j}; $reduce( $each( payload, function($v) {$v} ),$withOR ); )
kannst du ersetzen durch:
$reduce(payload.*, function($i, $j){$i or $j})
Gruß
Reiner -
@rewenode Wow - danke - ob ich dass dann aber in paar Monaten noch verstehe. Aber probiere ich gleich aus.
Lieben Dank!!!
-
Hi, ich will hier ja jetzt nicht den Lehrmeister oder so rauskehren, aber ist nicht immer die rede davon Node Red soll verständlich, übersichtlich und nachvollziehbar sein? Man sollte von Funktion Node absehen?
Die meisten meiner Funktion Nodes habe ich mitlerweile ersetzen können. Aber bei meinen Funktion Nodes bin ich immer noch durchgestiegen, was wo und wann passiert. Aber jetzt mit Change Nodes oder Switch Nodes zu arbeiten in denen Funktionen bzw. Json benutzt wird, da bin ich raus. Ich verstehe bei den Inhalten nur noch Bahnhof. Es funktioniert, aber wieso? Keine Ahnung. Da bleibe ich für mich doch lieber bei längeren/größeren Flows mit Standartsachen die ich auch verstehe/nachvollziehen kann.
Ist nicht negativ gemeint, jeder soll es so umsetzen wie er damit am besten klar kommt.Das hier verstehe ich ja noch. Enthält das payload.* ein true setze ich den einen Ausgang, sonst den anderen Ausgang.
Aber was passiert hier? Kann mir das vielleicht jemand übersetzen? Schon mal Danke im voraus.
$reduce(payload.*, function($i, $j){$i or $j})
Was ist $i und $j?
-
@frankyboy73 sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Aber was passiert hier? Kann mir das vielleicht jemand übersetzen? Schon mal Danke im voraus.
Achtung, die Aussagen sind stark vereinfacht!
JSONata hat erstmal nicht direkt mit Node-Red oder JavaScript zu tun. Es ist vielmehr eine eigene Scriptsprache, die speziell für die einfache universelle Abfrage/Bearbeitung von JSON-Objekten entwickelt wurde.
Auf Grund ihrer Mächtigkeit wurde sie relativ früh in Node-Red an vielen Stellen benutzt und ist inzwischen in vielen Nodes direkt integriert.
JSONata hat allerdings eine eigene Syntax, nicht nicht wirklich was mit JavaScript gemein hat.
Um den Einstieg zu erleichtern, ist in einigen Nodes im JSONata-Editor neben der Befehlsreferenz eine Testmöglichkeit implementiert.
In das linke Fenster "Beispielnachricht" kannst ein gültiges JSON-Objekt reinschreiben und im Ergebnisfenster erscheint das Ergebnis des JSONata-Ausdruckes, den du im oberen Fenster eintragen kannst.
Zurück zum $reduce().
Dabei handelt es sich um eine in JSONata eingebaute Funktion. Die allgemeine Syntax ist:$reduce(array, function [, init])
Sie durchläuft ein array, wendet auf jedes Element die function an und gibt das Gesamtergebnis zurück.
Die Funktion hat mindestens 2 Parameter. (genaues erfährst du im Link)
Der erster Parameter ist der Accumulator, der das Ergebnis speichert. Hier $i genannt.
Der zweite Parameter ($j) ist der aktuelle Array-Wert beim Durchlaufen des array.
Die Benennung mit $i und $j ist dabei willkürlich.Das Array wird durch den Ausdruck payload.* aus dem payload Objekt gebildet.
Aus der payload{ "W1": true, "W2": false, "W3": true }
erzeugt der JSONata-Ausdruck payload.* das Array
[true, false, true]
Auf dieses Array wird nun für alle Elemente die funktion angewendet.
$i = $i or $j // $i steht für das bisherige Ergebnis und $j für den aktuellen Wert
Am Ende liefert also $reduce() den Wert $i also die or-Verknüpfung aller array-Werte zurück.
Ich hoffe, ich habs auf die Schnelle einigermaßen verständlich rübergebracht.
Also
Braucht man unbedingt JSONata in Node-Red?
Klare Antwort: Nein
Aaaber, mit JSONata lassen sich äußerst komplexe JSON-Objekte teils als Einzeiler abfragen/bearbeiten. Etwa vergleichbar mit regEx.Gruß
Reiner, der hier nur an der Oberfläche gekratzt hat ;-( -
@rewenode Danke, ich glaube es wird klarer. Also wäre hier $i im Prinzip der Name der Nachricht und $j der jeweilige Wert.
Und mit $i or $j sage ich ist eine der Nachrichten true (bzw. nicht null) ist die Bedingung erfüllt. Bei „and“ dann $i and $j , sind alle Nachrichten True (bzw. nicht null) dann ist die Bedingung erfüllt.
Geht das auch umgekehrt? Also wenn alle Nachrichten false bzw. Null sind, dann ist die Bedingung erfüllt?Edit: Ok, ich hab da wohl doch noch nen Denkfehler, was i und j sind. Ich lese mich da wohl mal erst etwas ein.
-
@frankyboy73 sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
$i im Prinzip der Name der Nachricht und $j der jeweilige Wert
Fast. der $reduce() "reduziert" das ganze array in dem es auf alle Werte des array die Funktion anwendet.
Für die $i könntest du auch $ergebnis schreiben und für $j z.B. auch $aktueller_array_wertWie die einzelnen array-Werte mit dem $ergebnis verknüpft werden bestimmt die Funktion. im Beispiel ist das or. Könnte aber auch jede beliebige "berechnung" wie and, +/-/* usw oder auch wieder eine eigene Funktion sein.
Bei dem simplen Bepiel-array mit den 3 Werten [true, false, true] wird das array (in einer Schleife) 3 mal durchlaufen. Ich nehm mal wieder $i und $j.1. $i noch nicht initialisiert, $j ist true => $i bekommt den Wert $j also true 2. $i = true, $j jetzt false => $i = true or false = true 3. $i = true, $j jetzt true => $i = true or true = true
Da $i zurückgegeben wird ist das Ergebnis true. Das array wurde also auf den Wert true (der oder-Verknüpfung aller array-Werte) reduziert.
-
@frankyboy73 sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
Hi, ich will hier ja jetzt nicht den Lehrmeister oder so rauskehren, aber ist nicht immer die rede davon Node Red soll verständlich, übersichtlich und nachvollziehbar sein? Man sollte von Funktion Node absehen?
Ich bin doch immer noch bei Dir - und es gibt wie @rewenode gesagt hat für ein paar Standardfunktionen - zum Beispiel alle Eigenschaften eines Objektes die nur true oder false aufweisen.
Ich nutze generell - für solche einmal erstellte Nodes nun die lokale Bibliothek, so dass auch diese Nodes immer greifbar sind:Wie würde denn ein normaler Flow (in dem Fall eher unübersichtlich und müsste immer wieder so gemacht werden - zum Beispiel UND Node aussehen - OK ich kann ihn noch in einen Subflow verpacken:
Und soviel Code ist es auch nicht. Ich bin ja auch erst dabei bisschen mehr in das JSONATA einzuarbeiten.
Wir sind ja beide auch Anhänger nicht gleich wegen jeder Kleinigkeit irgendwelche Nodes oder Adapter einzubinden, sondern versuchen das mit Hausmitteln zu lösen.
Mit JSONATA - kann man so auch easy zum Beispiel mit 2 Tagesperioden in einer Switch Node zu basteln. Erinnerst Du Dich noch an die Change NOdes, die über JSONATA moment nun diese Node überflüssig machen:
https://flows.nodered.org/node/node-red-contrib-moment
Mit JSONATA kann man dann auch eine Switch Node nutzen - im Prinzip hast Du mich ja auf die Idee gebracht, da ich JSONATA vorher noch nie als Selektionskriterium genutzt habe.
Also im Großen und Ganzen - bleibe ich unserer Philosophie schon treu - wenn es sich aber immer um die gleiche Aufgabenstellung handelt - dann macht es meines Erachtens schon Sinn - die Logik aus Sicht der Übersichtlichkeit zusammenzufassen. Es ändert sich an dieser Logik ja nicht - zudem solche Flowfragmente ja mehrfach wieder eingesetzt werden.
Ich denke, dass wir trotzdem noch dasselbe Verständnis haben- ich hatte da vorher auch Function Nodes und da sind die JSONATA Funktionen trotzdem noch einfacher, weil sie eben in CHange und Switch Nodes direkt verwendet werden können.
-
@frankyboy73 sagte in Vergleich von zwei Eingangswerten um Wert festzulegen:
@rewenode Danke, ich glaube es wird klarer. Also wäre hier $i im Prinzip der Name der Nachricht und $j der jeweilige Wert.
Und mit $i or $j sage ich ist eine der Nachrichten true (bzw. nicht null) ist die Bedingung erfüllt. Bei „and“ dann $i and $j , sind alle Nachrichten True (bzw. nicht null) dann ist die Bedingung erfüllt.
Geht das auch umgekehrt? Also wenn alle Nachrichten false bzw. Null sind, dann ist die Bedingung erfüllt?Edit: Ok, ich hab da wohl doch noch nen Denkfehler, was i und j sind. Ich lese mich da wohl mal erst etwas ein.
In der Doku : https://docs.jsonata.org/higher-order-functions
Siehst Du das immer einfach der letzte mit dem vorletzen Element genutzt werden. In der Doku werden also 1. mit 0. Zahl multipliziert, dann 2. mit 1. Zahl, dann 3. Zahl mit Produkt aus 1 und 2. Zahl.
Geht das auch umgekehrt? Also wenn alle Nachrichten false bzw. Null sind, dann ist die Bedingung erfüllt
Das machst Du mit der Funktion, die auf einen Wert reduziert:
Für dieses Reduce definierst Du ja eine eigene Funktion:
( $withAND := function($i, $j){$i and $j}; $reduce( $each( payload, function($v) {$not($v)} ), $withAND ) )
Du musst halt die Eingabe verneinen. Wobei ich wohl dann besser eine ODER Node verwenden würde und einfach das Ergebnis verneinen. Das wäre logischer.
Im Übrigen gibt es diese Reduce Funktion auch in der JOIN Node - das habe ich neulich ausprobiert.
So hier mal die Reduce Funktion in der JOIN Node - funktioniert ähnlich wie die reduce Funktion in JSONATA - es wird immer mit dem Vorgänger verknüpft:
Hier mal die AND Node - dass alles true sein muss:
Eigentlich ist das auch schon kurz - Insofern könnte man das auch anstelle JSONATA und der UND nutzen:
Mit dieser Funktion der JOIN Node hat es auch gebraucht bis ich das kapiert habe - macht aber nichts anderes als die reduce Funktion unter JSONATA:
Hier mal mit dem Hilfetext der JOIN - Node - damit man das gleich vergleichen kann.
Das heißt die JSONATA Eingabe:
$A and payload
entspricht dem Funktionsaufruf der reduce Funktion in JSONATA.
-
@mickym Ja, dieses Sequenz reduzieren des Join Node ist ja intern nichts anderes als ein JSONata $reduce().
Übrigens
$each( payload, function($v) {$v} )
macht aus aus dem Eingangs-payload-objekt
{ "wert1":0, "wert2":1, "wert3":0 }
folgendes array
[0,1,0]
Macht also genau dasselbe wie:
payload.*
Und deshalb kannst du es weglassen und stattdessen
$reduce(payload.*, function($i, $j){$i and $j})
schreiben.
-
@rewenode Ah OK - das heißt ich muss nicht mit $each durch das Array durchgehen.