Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Node-Red
    5. Datum und Zeitverarbeitung mit NodeRed

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Datum und Zeitverarbeitung mit NodeRed

    This topic has been deleted. Only users with topic management privileges can see it.
    • mickym
      mickym Most Active @mickym last edited by mickym

      @mickym Wieder ein Test der positiv verlief mit der Moment Bibliothek.

      Auch die Verarbeitung von Monatsnamen um moment-Objekte zu erstellen, funktioniert einwandfrei:

      a576556e-3318-415c-8229-b78815c61d81-image.png

      $moment(payload,'DD.MMMM YYYY','de').format('DD.MM.YY - HH:mm')
      

      Auch Umlaute wie März werden korrekt verarbeitet.

      Bei abgekürzten Monatsnamen muss man im Deutschen darauf achten, dass die Strings immer mit 4 Zeichen abgekürzt werden.

      $moment(payload,'DD.MMM. YYYY','de').format('DD.MM.YY - HH:mm')
      

      Sind die Monatsnamen 4 Buchstaben oder kürzer werden sie voll ausgeschrieben (wichtig also März ausschreiben), ansonsten die ersten 3 Buchstaben + Punkt. Eine ähnliche Absonderlichkeit ergab sich bei 3stelligen Wochentagsnamen die immer 2 Buchstaben + Punkt enthalten:

      d0ce53a1-6316-477f-890e-c3577c35ec75-image.png

      1 Reply Last reply Reply Quote 0
      • mickym
        mickym Most Active last edited by mickym

        Einen weitere Anwendung bzw. Flow - um Zeitspannen der moments- Bibliothek zu nutzen, um sich in seiner Visualisierung nicht den Zeitstempel der letzten Meldung, sondern die Zeitspanne seit der letzten Meldung ausgeben zu lassen.

        42b10732-55ce-45e1-a69e-1d0af478a00e-image.png

        etwas später:

        d8fe7d91-8981-4c3e-9c9e-dd5baefc7c3f-image.png

        Die Texte werden automatisch durch die Humanize Funktion ausgegeben und sind also nicht änderbar und folgen folgendem Schema:

        c370e5ad-5625-4e31-b0c6-a4fe253f4223-image.png

        Ich gebe es hier direkt im NR-Dashboard aus, man könnte es aber auch natürlich in eigene Datenpunkte schreiben lassen und diese dann im VIS oder einer anderen Visualisierung ausgeben lassen. Es werden ja Strings zurückgegeben.

        Alle Geräte der letzte Meldungstatus man anzeigen lassen will, leiten man in einen zentralen Flow:

        0c88002f-1f6e-4e6f-8649-91941eb4763f-image.png

        Die Daten werden alle im Flowtext gesammelt und momentan nicht mit einem festen zeitlichen Trigger ausgegeben, sondern sobald sich ein Gerät meldet, werden alle anderen mit aktualisiert. Das belastet das System weniger. Man könne aber einen zeitlichen Trigger leicht realisieren, indem man die Inject-Node triggern lässt. Ansonsten triggert für Node-Red Dashboard Nutzer natürlich auch ein Wechsel der Seiten.

        Hiermal der Kern des Flows - für Ein- und Ausgang muss man selbst sorgen. Für die einzelnen Geräte wird immer das topic zur Identifikation genutzt (ggf. muss man der Nachricht halt selbst ein Topic verpassen).

        [
           {
               "id": "753c1b7eb6df5805",
               "type": "function",
               "z": "c297780ec96fcd08",
               "name": "Zeitstempel in fState",
               "func": "flow.set ('fState.' + msg.topic, msg.payload);\nreturn msg;",
               "outputs": 1,
               "noerr": 0,
               "initialize": "",
               "finalize": "",
               "libs": [],
               "x": 700,
               "y": 520,
               "wires": [
                   [
                       "2a3f9c0bbc0ea013"
                   ]
               ]
           },
           {
               "id": "abee507e5c1eb5bf",
               "type": "change",
               "z": "c297780ec96fcd08",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "$moment()\t",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 470,
               "y": 520,
               "wires": [
                   [
                       "753c1b7eb6df5805"
                   ]
               ]
           },
           {
               "id": "2a3f9c0bbc0ea013",
               "type": "change",
               "z": "c297780ec96fcd08",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "fState",
                       "tot": "flow"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 930,
               "y": 520,
               "wires": [
                   [
                       "c1c76a5e7c06c5d8"
                   ]
               ]
           },
           {
               "id": "c1c76a5e7c06c5d8",
               "type": "split",
               "z": "c297780ec96fcd08",
               "name": "",
               "splt": "\\n",
               "spltType": "str",
               "arraySplt": 1,
               "arraySpltType": "len",
               "stream": false,
               "addname": "topic",
               "x": 1110,
               "y": 520,
               "wires": [
                   [
                       "cf60e787307a4d6f"
                   ]
               ]
           },
           {
               "id": "cf60e787307a4d6f",
               "type": "change",
               "z": "c297780ec96fcd08",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "$moment(payload).locale('de').fromNow()",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1280,
               "y": 520,
               "wires": [
                   [
                       "8d22e1665c558f9b"
                   ]
               ]
           },
           {
               "id": "8215e211b17961ce",
               "type": "ui_ui_control",
               "z": "c297780ec96fcd08",
               "name": "",
               "events": "all",
               "x": 740,
               "y": 480,
               "wires": [
                   [
                       "2a3f9c0bbc0ea013"
                   ]
               ]
           },
           {
               "id": "74b5b9f8b6250713",
               "type": "inject",
               "z": "c297780ec96fcd08",
               "name": "Trigger",
               "props": [
                   {
                       "p": "payload"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "",
               "payload": "true",
               "payloadType": "bool",
               "x": 750,
               "y": 560,
               "wires": [
                   [
                       "2a3f9c0bbc0ea013"
                   ]
               ]
           }
        ]
        

        1 Reply Last reply Reply Quote 2
        • mickym
          mickym Most Active last edited by

          Hier mal wieder eine genial, einfache Methode, wie man verschiedene Bestandteile eines Datums mit Hilfe der moments library analysieren und als Objekt zur Verfügung stellen kann - um sie ggf. auch dann wieder in einzelne Datenpunkte zu zerlegen.

          Als erstes nutzt man halt den Formatstring, um verschiedene Bestandteile des Datums zu ermitteln und trennt diese mit Kommas.

          Zum Beispiel:

          $moment().format('YYYY,Q,M,DDD,W,e,H')	
          

          Das Ganze soll auch noch in Zahlenwerte konvertiert werden - deshalb habe ich alles vermieden, was Wörter ausspuckt.

          YYYY = gibt die 4 stellige Jahreszahl an
          Q = das Quartal (1-4)
          M = der Monat (1-12)
          DDD = Tag des Jahres (1-365(bzw. 366))
          W = Kalenderwoche europäisch
          e = Wochentag beginnend mit 0 = So.
          H = Stunde (0-23)

          Der Trick ist nun, dass man einfach eine CSV Node zur Konvertierung nutzt.

          d2d05e41-8e0f-4492-b795-ada92c289e2f-image.png

          Mit Zahlenwerte ermitteln wird automatisch die Konvertierung durchgeführt und mit den Namen als Spalte werden die Objekteigenschaften gleich richtig benannt.

          Somit ergibt dieser Flow - ein Objekt mit den entsprechenden Eigenschaften:

          c1bbd2a2-8fde-45f7-8c59-8c3e884d4af1-image.png

          Hier der einfache Flow:

          [
             {
                 "id": "90e855fff6300508",
                 "type": "debug",
                 "z": "a3b6dd9f9b565227",
                 "name": "Datum analysiert",
                 "active": true,
                 "tosidebar": true,
                 "console": false,
                 "tostatus": false,
                 "complete": "payload",
                 "targetType": "msg",
                 "statusVal": "",
                 "statusType": "auto",
                 "x": 890,
                 "y": 4460,
                 "wires": []
             },
             {
                 "id": "81785bd9ea91f30d",
                 "type": "inject",
                 "z": "a3b6dd9f9b565227",
                 "name": "",
                 "props": [
                     {
                         "p": "payload"
                     },
                     {
                         "p": "topic",
                         "vt": "str"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "",
                 "payload": "true",
                 "payloadType": "bool",
                 "x": 330,
                 "y": 4460,
                 "wires": [
                     [
                         "37cb9f15de0e0171"
                     ]
                 ]
             },
             {
                 "id": "37cb9f15de0e0171",
                 "type": "change",
                 "z": "a3b6dd9f9b565227",
                 "name": "",
                 "rules": [
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "$moment().format('YYYY,Q,M,DDD,W,e,H')\t",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 510,
                 "y": 4460,
                 "wires": [
                     [
                         "16121dc11c791032"
                     ]
                 ]
             },
             {
                 "id": "16121dc11c791032",
                 "type": "csv",
                 "z": "a3b6dd9f9b565227",
                 "name": "",
                 "sep": ",",
                 "hdrin": "",
                 "hdrout": "none",
                 "multi": "one",
                 "ret": "\\n",
                 "temp": "year,quarter,month,day of year,week of year,day of week,hour",
                 "skip": "0",
                 "strings": true,
                 "include_empty_strings": "",
                 "include_null_values": "",
                 "x": 710,
                 "y": 4460,
                 "wires": [
                     [
                         "90e855fff6300508"
                     ]
                 ]
             }
          ]
          

          1 Reply Last reply Reply Quote 1
          • mickym
            mickym Most Active last edited by mickym

            Hier mal wieder eine neue Anwendung mit der $moments Bibliothek um zu überprüfen ob der aktuelle Zeitpunkt in einem von mehreren definierten Zeitfenstern liegt.

            Praktische Anwendung könnte zum Beispiel sein, dass ein Gerät oder Heizung zu bestimmten Zeit innerhalb eines Tages eingeschaltet werden soll oder nicht. Dies habe ich gerade als Lösungsvorschlag für einem Beispielflow erstellt.

            [
               {
                   "id": "811d7797475ab2a4",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "Check mehrer Zeitfenster",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "[]",
                           "tot": "json"
                       },
                       {
                           "t": "set",
                           "p": "payload[0]",
                           "pt": "msg",
                           "to": "$moment().isBetween($moment(\"06:00\", \"HH:mm\"),$moment(\"08:00\", \"HH:mm\"),'minute','[)')",
                           "tot": "jsonata"
                       },
                       {
                           "t": "set",
                           "p": "payload[1]",
                           "pt": "msg",
                           "to": "$moment().isBetween($moment(\"11:00\", \"HH:mm\"),$moment(\"13:00\", \"HH:mm\"),'minute','[)')",
                           "tot": "jsonata"
                       },
                       {
                           "t": "set",
                           "p": "payload[2]",
                           "pt": "msg",
                           "to": "$moment().isBetween($moment(\"19:00\", \"HH:mm\"),$moment(\"23:00\", \"HH:mm\"),'minute','[)')",
                           "tot": "jsonata"
                       },
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "payload ~> $reduce (function($A, $i){$A or $i})",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1610,
                   "y": 2060,
                   "wires": [
                       [
                           "a49f55322d881c9c"
                       ]
                   ]
               }
            ]
            

            Die Prüfung der Zeitfenster speichert man in einem Array:

            594f25d1-3ec6-4876-9e57-69bb4609b0b3-image.png

            Zum Schluss verknüpft man alle Arraywerte mit ODER, um zu überprüfen, ob aktuell eines der definierten Zeitfenster WAHR ist und gibt das Ergebnis als ein Boolean aus.

            Außerdem wird hier die Anwendung des Ein- und Ausschlusses der Zeitgrenzen gezeigt. Normalerweise sind die angegebenen Zeitgrenzen ausgeschlossen. Mit eckigen Klammern schließt man diese ein, mit runden Klammern schließt man sie aus.

            Das Beispiel [) schließt also den Anfang ein, das Ende aus.

            Ergänzung: Man kann das ganze natürlich auch in einen Ausdruck verfrachten, dann schaut das noch schöner aus:

            a52dc24e-2884-4c57-9ac7-78558307514f-image.png

            [
               {
                   "id": "218060d1fbd89410",
                   "type": "change",
                   "z": "578345f4956c7a57",
                   "name": "Check Zeitfenster",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "[\t   $moment().isBetween(\t       $moment(\"06:00\", \"HH:mm\"),\t       $moment(\"08:00\", \"HH:mm\"),\t       'minute',\t       '[)'\t   ),\t   $moment().isBetween(\t       $moment(\"11:00\", \"HH:mm\"),\t       $moment(\"13:00\", \"HH:mm\"),\t       'minute',\t       '[)'\t   ),\t   $moment().isBetween(\t       $moment(\"18:00\", \"HH:mm\"),\t       $moment(\"23:00\", \"HH:mm\"),\t       'minute',\t       '[)'\t   )\t]~> $reduce (function($A, $i){$A or $i})",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 450,
                   "y": 2640,
                   "wires": [
                       [
                           "85ad88e10464701c"
                       ]
                   ]
               }
            ]
            

            1 Reply Last reply Reply Quote 1
            • B
              Bernhard59 last edited by

              Hallo zusammen, ich habe auch ein Problem mit der Zeit... wer hat das nicht 😉

              Ich möchte in der Regelung meiner Solaranlage den Wechselrichter abschalten, wenn er eine bestimmte Zeit keine Werte mehr über meinen DTU Adapter zu meinem Flow gesendet hat. Das kommt manchmal vor und um zu verhindern, daß mein Solarakku zu tief entladen wird, soll der Wechselrichter abgeschaltet werden. Dazu möchte ich den " timestamp of last inverter statistics udpate" mit der aktuellen Uhrzeit vergleichen und wenn die Differenz der beiden z.B. größer als 10 min ist, soll der Befehl zum Abschalten erfolgen. Ich weiß, wie ich den " timestamp of last inverter statistics udpate" mit einer iobroker Node auslese und wie ich abschalte, aber wie ich die beiden Zeiten verwenden und daraus eine Differenzüberschreitung ermitteln kann ist mir noch unklar.

              Vielleicht kann mir ja hier jemand helfen... besten Dank im Voraus...

              mickym 1 Reply Last reply Reply Quote 0
              • mickym
                mickym Most Active @Bernhard59 last edited by

                @bernhard59 Für so was nutzt man eine trigger Node und führt keine Berechnungen durch.

                B 1 Reply Last reply Reply Quote 0
                • B
                  Bernhard59 @mickym last edited by

                  @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                  @bernhard59 Für so was nutzt man eine trigger Node und führt keine Berechnungen durch.

                  Danke für die schnelle Antwort... und wie funktioniert das ?

                  mickym 1 Reply Last reply Reply Quote 0
                  • mickym
                    mickym Most Active @Bernhard59 last edited by mickym

                    @bernhard59 sagte in Datum und Zeitverarbeitung mit NodeRed:

                    @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                    @bernhard59 Für so was nutzt man eine trigger Node und führt keine Berechnungen durch.

                    Danke für die schnelle Antwort... und wie funktioniert das ?

                    6ad223ac-e357-48f4-9fe8-47b2ef5649e0-image.png

                    und halt vorne dran die Node oder die Nachrichten die Du sonst empfängst, also parallel schalten. Sind die 10 Minuten abgelaufen, wird der trigger automatisch wieder scharf-

                    B 1 Reply Last reply Reply Quote 0
                    • B
                      Bernhard59 @mickym last edited by

                      @mickym

                      Danke... dann versuche ich das mal...

                      B 1 Reply Last reply Reply Quote 0
                      • B
                        Bernhard59 @Bernhard59 last edited by

                        Perfekt, es funktioniert und soooo einfach... DANKE

                        mickym 1 Reply Last reply Reply Quote 0
                        • mickym
                          mickym Most Active @Bernhard59 last edited by

                          @bernhard59 sagte in Datum und Zeitverarbeitung mit NodeRed:

                          Perfekt, es funktioniert und soooo einfach... DANKE

                          Ja Node-Red halt. 😉

                          B 1 Reply Last reply Reply Quote 0
                          • B
                            Bernhard59 @mickym last edited by

                            Jetzt habe ich das nächste Problem und vielleicht kannst du mir wieder helfen...

                            Ich möchte mir, wenn die Datenübertragung mit der DTU längere Zeit nicht funktioniert eine Mail schicken. Das habe ich auch an anderen Stellen im Flow schon gemacht und es funktioniert einwandfrei.

                            Ich lese ja den Unix-Zeitstempel der letzten Aktualisierung der Wechselrichterstatistik mit einem iobroker In Nodes ein und werte diesen dann mit einen Trigger aus und wenn dann eine bestimmte Zeit keine Aktualisierung stattgefunden hat, möchte ich eine Mail bekommen. Das funktioniert auch alles, nur die Mail Nodes sagt dann "Senden fehlgeschlagen" und bringt folgende Fehlermeldung:
                            "Error: Mail command failed: 550-Requested action not taken: mailbox unavailable 550 Sender address is not allowed."

                            Wenn ich aber mit einem Injekt Nodes vor dem Trigger einen Timestamp schicke, geht die Mail einwandfrei raus... ich habe schon alle möglichen Einstellungen probiert... kein Erfolg.

                            Kennst du dich da aus?

                            a20197d7-257a-41b8-9bf8-4e7e189a7694-image.png

                            mickym 1 Reply Last reply Reply Quote 0
                            • mickym
                              mickym Most Active @Bernhard59 last edited by mickym

                              @bernhard59 Dann sind da halt noch eine Menge anderer Eigenschaften im Nachrichtenobjekt. Du du eh eine function nutzt, würde ich halt ein neues Nachrichtenobjekt erstellen, das nur den Zeitstempel und topic enthält.

                              var newMsg = {payload:msg.payload, topic:msg.topic};
                              return newMsg;
                              

                              oder halt

                              var newMsg = {payload:"keine Datenübertragung", topic: "Warnung"};
                              return newMsg;
                              

                              Sobald Dein Nachrichtenobjekt ja eine dieser Eigenschaften aufweist:

                              a70d1019-9447-4992-a3ae-a10f49be7c65-image.png

                              zum Beispiel msg.to und da Mist drin steht gibts halt eine Fehlermeldung.

                              B 1 Reply Last reply Reply Quote 0
                              • B
                                Bernhard59 @mickym last edited by

                                @mickym

                                Perfekt... Ich habe das erste gerade mit einer zusätzlichen Funktion probiert... funktioniert einwandfrei... Wieder einmal ein groooooßes DANKESCHÖN...

                                Ich muss mich wohl doch mal intensiver damit beschäftigen...

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post

                                Support us

                                ioBroker
                                Community Adapters
                                Donate

                                660
                                Online

                                31.7k
                                Users

                                79.7k
                                Topics

                                1.3m
                                Posts

                                node-red
                                5
                                33
                                28176
                                Loading More Posts
                                • Oldest to Newest
                                • Newest to Oldest
                                • Most Votes
                                Reply
                                • Reply as topic
                                Log in to reply
                                Community
                                Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                The ioBroker Community 2014-2023
                                logo