da_users doofe Fragen zu NodeRed und drumherum

  • Ich mache jetzt einfach mal einen Sammelthread für kurze, doofe Fragen zu NodeRed ;)

    Akut habe ich gerade ein Problem mit JS in NodeRed, ich vermute, dass sich JS weigert eine payload als Array zu erkennen. Die Payload sieht so aus:

    Code
    {"status":"ONLINE","lineV":"229.4 Volts","bchargePCT":"100.0 Percent","timeleftMINS":"60.0 Minutes","outputV":"229.7 Volts","linefreqHz":"50.0 Hz","dwakeSEC":"-1 Seconds","statflag":"0x05000008"}


    Mein Ziel ist es, die Einheiten wegzubekommen. Meine Idee war ein Function-Node, bei dem ich jedes Element durchgehe, den Wert am Char ' ' splitte und nur den ersten Splitter wieder als Wert setze.
    Das ist das erste mal, dass ich mit JS arbeite, und irgendwie will das nicht so, wie ich will, ich scheitere schon alleine beim durchzählen der Elemente. Für folgenden Code:

    Code
    let i = 0;
    msg.payload.array.foreach(element => i++);
    msg.payload = i;
    
    
    return msg;


    erhalte ich diese Fehlermeldung:

    Code
    TypeError: Cannot read property 'foreach' of undefined


    Dieser, deutlich einfacher Code

    Code
    msg.payload = msg.payload[0];
    return msg;


    liefert als Ergebnis einfach "undefined". Was mich zu dem Ergebnis führt, dass die Payload einfach nicht als Array erkannt wird. Was ist den da der Kniff?

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Also hier hab ich die Liste generiert zum PV Channels auslesen.

    JavaScript
    msg.options = new Array();
    for (var i = 0; i < msg.payload.result.channels.length; i++) {
    msg.options[i]=new Object();
    msg.options[i] [msg.payload.result.channels[i].label]=msg.payload.result.channels[i].channelid;
    }    
    return msg;

    --------------
    Guides nicht mehr verfügbar wegen Youtube unvermögen guten von schlechten Kodi Videos zu unterscheiden.

  • Nö, funktioniert schon der Basisansatz nicht, überhaupt an "payload.length" zu kommen:

    Code
    var i = msg.payload.length;
    //msg.payload.array.foreach(element => i++);
    msg.payload = i;
    
    
    return msg;


    liefert ebenfalls "undefined".

    Um mal eben den Sinn etwas zu erörtern:

    Das ganze soll dazu dienen, meine an diesem RasPi hängende USV auszulesen und die Werte in eine InfluxDB zu schieben. Den Basisflow habe ich im Internet gefunden ( https://nerdiy.de/nodered-usv-status-auslesen/ ). Darin wird per exec-Node der Befehl "/sbin/apcaccess" ausgeführt, mit einem "function-Node" namens "convert2Json" verarbeitet und dann eigentlich in einem Dashboard angezeigt.

    Ich habe jetzt angefangen mit einem "change"-Node die Werte, die ich brauchen kann und bekomme in einer Message neu einzusortieren. Dessen Ausgabe ist oben zu sehen. Ich habe mal den Flow auf das - fast - notwendigste heruntergebrochen:

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Ich hab mir das ganze jetzt mal angeschaut.
    Ich war hinter dein Problem gar nicht eingestiegen.
    du musst beim Bewegen ( change) payload.status z.B. als quelle nehmen.

    Davon ab versteh ich den Zwischenschritt nicht. Du könntest den kompletten Output in einem Schritt ändern und die Werte dann einzeln in die Influx DB exportieren. Die Werte kommen ja aus dem Ursprungsnode. Per Function node wandelst du das dann in das Format was du möchtest.
    Danach schreibst du den Wert in deine Influx DB.

    --------------
    Guides nicht mehr verfügbar wegen Youtube unvermögen guten von schlechten Kodi Videos zu unterscheiden.

  • Ich war hinter dein Problem gar nicht eingestiegen.
    du musst beim Bewegen ( change) payload.status z.B. als quelle nehmen.

    Du meinst den Change-Node?
    Ich verschiebe erst msg.payload nach msg.tmp. Damit ist msg.tmp meine Quelle und in msg.payload bastel ich mir eine neue Payload zusammen.


    Davon ab versteh ich den Zwischenschritt nicht. Du könntest den kompletten Output in einem Schritt ändern und die Werte dann einzeln in die Influx DB exportieren. Die Werte kommen ja aus dem Ursprungsnode. Per Function node wandelst du das dann in das Format was du möchtest.

    Ich weiß jetzt nicht, was du als "Zwischenschritt" meinst? Und wie ich den kompletten Output in einem Schritt ändern soll?
    Was ich allerdings nicht will ist, die Werte dann einzeln in die InfluxDB zu schreiben. Wenn ich die als eine Message in die InfluxDB schicke, wird das nämlich eine Zeile in einer einzelnen Tabelle. Einzeln (=> mehrere Messages) werden mehrere Zeilen, oder ich schreibe sie in mehrere Tabellen. Da die Werte zum gleichen Zeitpunkt von der gleichen Quelle genommen wurden, macht m.E. ersteres mehr Sinn.

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Ok... ich komm hier nicht mehr weiter.

    Bevor ich mich in die "Höhe des Löwen" (sprich: µC-Forum) begebe: kennt jemand ein gutes deutschsprachiges Node-Red-Forum?

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • https://forum.iobroker.net/category/96/node-red
    Das Unterforum von ioBroker ist recht aktiv. Für den wird Node-RED als Adapter angeboten.

    Danke, ich werde es wohl demnächst dort mal probieren.

    Payload ist ein Object und kein Array.

    Ähm?
    Ein Array ist aber ein Objekt!? Und nach meinem Verständnis sollte das Object "payload" aus einem Array von "Namen-Wert-Paaren" bestehen.

    payload.status zb zum Zugriff auf die Werte

    Das ist mir bekannt. Was ich aber will, ist nacheinander auf alle Werte zuzugreifen und diese zu modifzieren. Und zwar unabhängig wie der Name des "Namen-Wert-Paares" lautet.

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Ein Array ist aber ein Objekt!? Und nach meinem Verständnis sollte das Object "payload" aus einem Array von "Namen-Wert-Paaren" bestehen.

    Ein Array ist eine Datenstruktur. Diese kannst Du bspw. an ein Objekt als Eigenschaft definieren/anhängen. .status kann ein Array sein. payload ist das Objekt an dem .status als Eigenschaft zugeordnet wird, entweder als Einzelwert oder als Array. Entweder durchnummeriert (status[x]) oder als assoziatives Array (status[name] = wert).

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • So.. mal wieder ne Frage zu NodeRed, und dahinter gleich noch eine für Influx bei der ich auf hilfreiche Hinweise hoffe ;)

    1.) Ich habe einige Zähler die nur als "Gesamtzähler" auslesbar sind: Stromzähler und Wärmemengenzähler der Wärmepumpe z.B. Sinniger wäre aber manchmal einen Tageszähler zu haben, etwa um nachzugucken, was die WP heute an Strom gebraucht hat und was an Wärme rausgekommen ist. Auch hätte ich gerne "Abrechnungsjahrzähler". Ist ja grundsätzlich kein Problem das umzusetzen, weil aus den Gesamtzählerwerten kann man ja auch die Tageswerte ausrechnen.
    Mein erster Ansatz in Node-Red: Subflow erstellt. Dieser merkt sich auf eine spezielle "Reset" Message den aktuellen Zählerwert in der Variable flow.startwert, zieht diesen jedem neu kommenden Zählerstand ab und gibt damit den Wert seit letzten Reset aus.
    Problem: bei einem Neustart von NodeRed ist flow.startwert nicht mehr existent. Also gibt der Subflow bei einem Reset auf einem separaten Ausgang auch den "StartWert" aus, diese werden von mehreren Subflows eingesammelt und in einer Datei gespeichert. Beim neu deployen, oder Neustart von NodeRed sollen diese Werte dann wieder eingelesen werden und als StartWert dem Subflow übergeben werden.
    Funktioniert leider nur nicht zuverlässig genug.

    Also die Frage: hat schonmal jemand sowas realisiert? Kann Tipps oder evtl. sogar einen Flow/Node rüberreichen?

    Mein neuer Ansatz wäre ja: Alle Werte kommen ja sowieso in eine InfluxDB. Für die Startwerte der Tageszähler könnte ich also auch aus der DB den ersten Wert des Tages auslesen und übergeben, die Abfrage sollte hoffentlich nicht so schwer sein. Und dann mal gucken, wie ich die Abfrage für den Abrechnungsjahrzähler mache: erster Wert vom letzten 1. Juni).

    2.) Betreffs Influx:
    Ich habe noch die 1.8.irgendwas, also noch mit der alten InfluxQL. Grundsäztlich kommen bei mir doch jede Menge Daten zusammen, die man dann oft in dieser Form mehr braucht (z.b. Tageszählerwert reicht der letzte). InfluxDB hat ja die Möglichkeit der "Retention & Downsampling". Mir ist gerade - aus welchen Gründen auch immer - das englischsprachige Tut auf der InfluxDB-Homepage zu hoch. Hat da jemand einen guten Tipp für was (deutschsprachiges) wo das evtl. nochmal besser aufbereitet ist?

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Zu 1.)
    Die Abfrage

    SQL
    SELECT first("Verdichter Verbrauch") FROM "Stromzähler" WHERE time > now() - (1d) GROUP BY time(1d) fill(null) tz('Europe/Berlin')

    liefert den ersten Wert für heute und für gestern. Muss man halt dann nur noch den passenden weiterverarbeiten.

    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

  • Die obige Abfrage hat in Verbindung mit meinem Flow ein Problem: Das Measurement wird in meinem flow komplett geschrieben, also Zählerstand Total und Tageszähler. Wenn der Flow die Datenbank das erste Mal am Tag abfragt, gibt es entsprechend noch keinen Zählerstand für diesen Tag. Die Rückmeldung ist dafür also 'null'. Das führte irgendwie dazu, dass mein Flow am Ende des Tages (warum auch immer) den Tageszähler nicht richtig ausgerechnet hat und dann den Zählerstand in den Tageszähler geschrieben hat.

    Es scheint zu funktionieren, wenn man statt mit 'null' mit 'previous' "fillt":

    SQL
    SELECT first("Verdichter Verbrauch") FROM "Stromzähler" WHERE time > now() - (1d) GROUP BY time(1d) fill(previous) tz('Europe/Berlin')
    Zitat von root2

    Merke: Das "S" in "IoT" steht für Sicherheit!

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!