NEWS
Stringauswertung
-
Versuche mich mit einer Buffer-Auswertung.
Der String erhalte ich von einem TCP-Stack.
Der String ist im ASCII-Format, also lesbar.Alle 10sec. wird ein Heartbeat gesendet (OK) und je nach Abfrage weitere Daten.
Mir geht es nun darum in Node-Red erstmal anhand der empf. Strings einen Switch zu machen um dann die weiteren Daten auszuwerten.Ich habe dies mit einem Functions-Node versucht. Lese die ersten Zeichen des Strings aus und
und switche dann in verschiedene Ausgänge. Soweit der Plan.Jedoch scheint bei einem neuen String, noch ein Teil des vorhergehenden String enthalten zu sein und ich bekomme den String einfach nicht leer damit die Auswertung dann korrekt funzt.
Hoffe ich konnte mein Anliegen etwas verständlich rüberbringen.
Habe mein Flow mal angehängt. ist aber noch ziemlich alpha!
[ { "id": "2273974f.f819a8", "type": "tab", "label": "Flow 1", "disabled": false, "info": "" }, { "id": "403929ae.aea368", "type": "tcp in", "z": "2273974f.f819a8", "name": "", "server": "client", "host": "192.168.0.25", "port": "5555", "datamode": "stream", "datatype": "utf8", "newline": "", "topic": "", "base64": false, "x": 260, "y": 80, "wires": [ [ "f8c5f505.70c898" ] ] }, { "id": "f8c5f505.70c898", "type": "function", "z": "2273974f.f819a8", "name": "", "func": "var str = msg.payload.substring(0,8);\n\nvar o = str.startsWith(\"OK\"); // OK\nvar v = str.startsWith(\"VER\"); // Version\nvar p = str.startsWith(\"GP\"); // PG\n\nif (o)\n{\n o == false; \n var msg1 = { payload:\"Heartbeat\" }; // OK Heartbeat\n}\nif (v)\n{\n v == false; \n var msg2 = { payload:\"Version\" }; // Version\n}\nif (p)\n{\n p == false; \n var msg3 = { payload:\"Test\" }; // PG\n}\n\n \nreturn [msg1,msg2,msg3];\n", "outputs": 3, "noerr": 0, "initialize": "", "finalize": "", "x": 480, "y": 200, "wires": [ [ "316ed78.d1c4428" ], [ "f134f415.ddee18" ], [ "70825105.cfe04" ] ] }, { "id": "316ed78.d1c4428", "type": "debug", "z": "2273974f.f819a8", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 670, "y": 180, "wires": [] }, { "id": "f134f415.ddee18", "type": "debug", "z": "2273974f.f819a8", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 670, "y": 220, "wires": [] }, { "id": "70825105.cfe04", "type": "debug", "z": "2273974f.f819a8", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 670, "y": 260, "wires": [] } ]
Danke
Pat -
@valbuz Du machst meines Erachtens wieder den Fehler eine Function Node zu verwenden. Du willst eine Switch indem Du die payload bei den ersten 9 Zeichen prüfst ob eine bestimmte Zeichenkette vorhanden ist. Warum verwendest Du keinen Switch Node???
Bei den function nodes verbirgst Du wieder alles da drin, so dass Du die Vorteil von Node-Red nicht nutzt. Du müsstest die msg Objekte global definieren - aber ich will darauf nicht eingehen.
Meines Erachtens erreichst Du Dein Ziel eben mit einer Switch Node.
[ { "id": "93a70147.f77e4", "type": "switch", "z": "2273974f.f819a8", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "jsonata_exp", "v": "$contains($substring(payload, 0, 8), \"OK\")\t\t", "vt": "jsonata" }, { "t": "jsonata_exp", "v": "$contains($substring(payload, 0, 8), \"VER\")\t\t", "vt": "jsonata" }, { "t": "jsonata_exp", "v": "$contains($substring(payload, 0, 8), \"GP\")\t\t", "vt": "jsonata" } ], "checkall": "true", "repair": false, "outputs": 3, "x": 470, "y": 400, "wires": [ [ "16400f41.1f55f1" ], [ "2ad52799.94bb88" ], [ "d755e8c4.dade18" ] ] }, { "id": "16400f41.1f55f1", "type": "change", "z": "2273974f.f819a8", "name": "Heartbeat", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Heartbeat", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 640, "y": 360, "wires": [ [] ] }, { "id": "2ad52799.94bb88", "type": "change", "z": "2273974f.f819a8", "name": "Version", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Version", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 640, "y": 400, "wires": [ [] ] }, { "id": "d755e8c4.dade18", "type": "change", "z": "2273974f.f819a8", "name": "Test", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Test", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 630, "y": 440, "wires": [ [] ] } ]
-
@mickym Danke!
Soweit läuft's
ztw. scheint sich jedoch der Payload zu "überschneiden"
(also der Heartbeat "OK" und ein Teil des zweiten Strings "PRFSTATE"
Dann funzt die Auswertung nicht mehr korrekt. Anhand von nur 2 Zeichen möchte ich nicht auswerten.Hoffe Du meinst was ich meine
Danke
-
@valbuz Dann mach das doch nicht so kompliziert. Das geht doch mit einem Switch am einfachsten:
- Statt der komplexen String Auswertung gibt es im Switch die Funktion enthält - da kannst Du nach dem Schlüsselwort suchen egal wo der im String steht.
- Priorisierst Du die spezifischeren Dinge immer oben - also "PRFST" vor "OK" oder eben umgekehrt - wie Du es halt brauchst.
- Sagst Du dass die Regelüberprüfung nach 1. Übereinstimmung stoppen soll.
Das ist dann letztlich noch einfacher als in meinem zuerst geposteten Flow.
Hier nur ein Screenshot und die Definition des Switch Nodes:
[ { "id": "72cd49f5.4967f8", "type": "switch", "z": "dce8fa20.2e93c8", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "cont", "v": "PRFST", "vt": "str" }, { "t": "cont", "v": "VER", "vt": "str" }, { "t": "cont", "v": "OK", "vt": "str" } ], "checkall": "false", "repair": false, "outputs": 3, "x": 1060, "y": 400, "wires": [ [], [], [] ] } ]
Die payload dann selbst setzen hast Du ja im ersten Flow gesehen, wie man das macht. Also nur den Switch Node ersetzen und die Change Nodes anhand der Ausgänge platzieren.
Im Prinzip kannst auch den ursprünglichen Switch nehmen und nach Prio sortieren (einfach an den 3 Linien mit der Maus ziehen) und dann nach 1. Übereinstimmung beenden.
-
@valbuz Oder Du machst das so einfach - dass Du aus Deinem IP String - eben vor der Switch Node über einen Change Node die payload auf 8 Zeichen kürzt und dann auswertest.
Ich habe dann auch in dem Switch noch ein Andernfalls eingebaut - falls Du das mal brauchen solltest - kannst aber wieder entfernen.
[ { "id": "67d886a6.de6ed8", "type": "change", "z": "dce8fa20.2e93c8", "name": "Nur 8 Zeichen", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "$substring(payload, 0, 8)\t", "tot": "jsonata" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1460, "y": 1460, "wires": [ [ "e0048b04.0e69b8", "72cd49f5.4967f8" ] ] }, { "id": "e0048b04.0e69b8", "type": "debug", "z": "dce8fa20.2e93c8", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 1670, "y": 1380, "wires": [] }, { "id": "515561cc.25ebd", "type": "inject", "z": "dce8fa20.2e93c8", "name": "Text", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Dies ist ein langer String", "payloadType": "str", "x": 1210, "y": 1460, "wires": [ [ "67d886a6.de6ed8" ] ] }, { "id": "72cd49f5.4967f8", "type": "switch", "z": "dce8fa20.2e93c8", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "cont", "v": "PRFST", "vt": "str" }, { "t": "cont", "v": "VER", "vt": "str" }, { "t": "cont", "v": "OK", "vt": "str" }, { "t": "else" } ], "checkall": "false", "repair": false, "outputs": 4, "x": 1670, "y": 1460, "wires": [ [], [], [], [ "f3830817.ac1618" ] ] }, { "id": "f3830817.ac1618", "type": "debug", "z": "dce8fa20.2e93c8", "name": "No Code", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1890, "y": 1520, "wires": [] } ]
Change Node um payload auf 8 Zeichen zu kürzen:
und hier nochmals der Switch Node - das Anderenfalls wieder entfernen wenn nicht benötigt:
Mit dem Anderenfalls kann man dann ggf. noch komplexere Analysen und Flows starten.
und wie man sieht alles ohne function Node.
-
-
@mickym Also soweit funktioniert das ganze recht gut. Danke nochmals!
Je nach Befehl bekomme ich jedoch mehrere Befehle in einem String zurück
Das heisst nach dem Switch des ersten Matches ist fertig und der zweite Befehl wird dann natürlich nicht mehr gesetzt.
Ich denke man müsste den String zerlegen.....Ist dies der richtige Ansatz? Oder fällt Dir eine andere Möglichkeit ein?
Danke
Pat -
@valbuz Nein - das einfachste ist, Du hörst mit Deiner Beschränkung auf 8 Zeichen auf und änderst den Switch auf "alle Regeln überprüfen" - dann feuert er auch aus allen Rohren.
Wenn die Reihenfolge bei komplexeren Befehlen wichtig ist - hängst Du halt noch einen Switch hinterher (in dem Du natürlich nicht mehr nach dem Ursprungsbefehl auswertest) , die dann auch parallel abgearbeitet werden können.
-
@valbuz Ansonsten kannst Du ja anstelle der ersten 8 Zeichen, wenn Dir die Parallelverarbeitung nicht zusagt - erst mal alle Möglichkeiten der Split/Aufteilen Node nutzen. Diese kann Dir entweder Deinen String in Häppchen zu x Zeichen (also auch 8 wenn Du willst) zerhacken oder Du findest eine charakteristische Zeichen oder Bytefolge die vor oder nach einem Befehl auftritt.
Wenn Du nie mehr als 2 Befehle oder nur bei bestimmten Befehlen 2 Folgebefehle erwartest kannst Du noch eine Switch node dahinter klemmen.
Das sind jetzt bevor Du Teilstrings und Schleifenkonstrukte wählst mit der vorangegangenen Parallelverarbeitung 4 weitere Möglichkeiten, die schnell effizient und einfach zu implementieren sind.