Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. Node-Red
  5. Datum und Zeitverarbeitung mit NodeRed

NEWS

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    11
    1
    363

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    24
    1
    1.6k

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    9.5k

Datum und Zeitverarbeitung mit NodeRed

Geplant Angeheftet Gesperrt Verschoben Node-Red
node-red
33 Beiträge 5 Kommentatoren 32.7k Aufrufe 5 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • mickymM mickym

    Da ich mich nun mal 1-2 Tage intensiv mit der "eingebauten" Datums- und Uhrzeitverarbeitung in NodeRed beschäftigt habe, würde ich meine Erkenntnisse gerne teilen und vielleicht springt ja für den einen oder anderen was nützliches heraus.

    Es geht in diesem Thread nicht um die Installation von zusätzlichen Nodes, die noch weitere Steuerungsmöglichkeiten bieten, sondern das was im Grundbaukasten bereits vorhanden ist.

    Als wer noch mehr zu den Themen - scheduling oder Zeit filtern sucht - der soll sich mal folgende Nodes anschauen:

    1. cronplus: https://flows.nodered.org/node/node-red-contrib-cron-plus - alles und noch mehr was iobroker mit dem cron als Scheduler bietet.
    2. lightscheduler: https://flows.nodered.org/node/node-red-contrib-light-scheduler triggert - aber vor allem filtert nach Zeitereignissen
    3. bigtimer - wobei ich zwar am Anfang begeistert war, aber ich inzwischen den Nutzen nicht mehr sehr hoch einschätze:
      https://flows.nodered.org/node/node-red-contrib-bigtimer

    Doch mir geht es ja nicht darum, mit welchen zusätzlichen Nodes man noch was machen kann, so wie man mit dem Grundbaukasten Zeit- und Datumsereignisse verarbeitet. Zum Schluss stelle ich dann noch einen kleinen Flow vor, den man als Timer nutzen kann. ;) - und zwar flexibler als bei den fertigen Nodes. ;)

    Die Javascript Bibliothek, die in Node Red für die Datums- und Uhrzeit verarbeitung verfügbar ist, ist wohl die moment.js - und die Funktionen dieser Bibliothek werden ich nun im Verlauf weiter vorstellen - allerdings nicht über Javascript, sondern im Prinzip kann man diese ganze Bibliothek über JSONATA nutzen. Erst seit dem ich mich damit nun etwas näher beschäftigt habe, ergeben sich neuen Möglichkeiten, wobei ich auch noch hin und wieder ??? habe und deswegen vielleicht manches hier umständlich aussieht.

    Dennoch kommt bei diesem Thread quasi kein natives Javascript zur Anwendung (also keine Function Nodes). ;) ;)

    Ich denke, das im Blockly wohl auch die moment.js eingebunden ist - insofern kann man das vergleichen und gegenüberstellen.

    Was im Standard nicht verfügbar ist, sind die Astrozeiten - dafür bieten sich aber alle 3 oben genannten Nodes an - die hier eine Vielzahl an Funktionen bieten - wer da mehr wissen will, meldet sich einfach.

    Wie gesagt - sowohl im Blockly als auch in Node Red wurde für die Datums und Uhrzeitverarbeitung die moment.js Bibliothek verfügbar gemacht. Dabei geht in NodeRed in meinen Augen die Möglichkeiten der Nutzung über das hinaus, was üblicherweise in den Puzzleteilchen angeboten wird. ;)

    Die volle Funktionalität der moment.js Bibliothek sollte man sich als Nachschlagewerk als Seite abspeichern:
    https://momentjs.com/docs/#/parsing/

    Anscheinend wird die Bibliothek nicht mehr weiter entwickelt - wird aber noch gewartet.

    Nodes die vollkommen überflüssig sind, sind die moment.js Nodes - zumindest seitdem die moment.js Bibliothek unter NodeRed im JSONATA verfügbar gemacht wurde. Diese Nodes : https://flows.nodered.org/node/node-red-contrib-moment können also komplett ersetzt werden. Ich hatte die anfangs auch, werden nun aber rausgeschmissen.

    Dreh- und Angelpunkte bei der Nutzung der moment.js Bibliothek sind natürlich die moment-Objekte. Diese sind keine date-Objekte von Javascript. Wer also die moment.js Bibliothek im Javascript nutzen will, muss sie nach Installation halt wie üblich mit require in den Code einbinden.

    https://momentjs.com/docs/#/use-it/

    var moment = require('moment'); // require
    moment().format()
    

    In NodeRed ist es wie gesagt nicht erforderlich und man benötigt weder eine moment.js Insallation noch muss man Bibliohteken global verfügbar machen - außer man wollte die moment.js in function Nodes nutzen, was hier aber nicht der Fall ist und deswegen auch nicht weiter beschrieben wird. Hier geht es deshalb ausschließlich um die moment.js Funktionen, die JSONATA in NodeRed zur Verfügung stellt und die deshalb in verschiedenen Nodes wie der Change-Node, der Inject-Node, der Switch-Node, Join-Node etc. zur Verfügung steht und angewandt wird.

    Im folgenden werde ich mich etwas an Blockly orientieren - da in meinen Augen die gleiche Bibliothek dahinter liegt und erklären, wie man das im JSONATA und in NodeRed umsetzt.

    mickymM Offline
    mickymM Offline
    mickym
    Most Active
    schrieb am zuletzt editiert von mickym
    #4

    3. Datums- und Uhrzeitvergleiche

    Im Blockly vergleiche ich ein Datumsobjekt mit einem String oder Uhrzeit

    41d3adbc-b2bb-4533-ae79-5234cd51a047-image.png

    Ob ich damit auch ein Datum vergleichen kann, weiß ich nicht und es scheint auch nur die aktuelle Zeit verglichen zu werden. Ansonsten muss man eben für den Vergleich alles in Datumsobjekte umwandeln, das ergibt ja Zeitstempel im UNIX Millisekunden Format und vergleicht diese eben miteinander - ist eigentlich auch kein großer Akt - dann hätte man sich dieses Puzzle auch sparen können.

    In der Moments Bibliothek kann ich wiederum 2 Moment-Objekte oder 1 Moment-Objekt mit String - Array oder Objekt vergleichen.

    Hier mal wieder alle Möglichkeiten aus der Doku: https://momentjs.com/docs/#/query/

    Für die Vergleiche habe ich mal 2 moment Objekte genommen - da hatte ich dann mit JSONATA leichte Schwierigkeiten, deswegen schaut das etwas komplizierter aus.

    Bei Stringvergleichen war das keine Problem, aber wenn ich 2 Moment Objekte miteinander vergleichen musste - kann ich das nicht mit einem Einzeiler - da müssen dann größere Fachleute als ich ran.

    Ich habe es nun so gelöst:

    (
        /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */
        $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
        $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
        $a.isBefore($b);
    )
    

    Also beide Momentobjekte erzeugt und dann verglichen. isBefore, isAfter, isSame etc. ist ja selbsterklärend und entspricht den gleichen Möglichkeiten, die hier Blockly bietet - nur dass eben 2 Moments, Moments mit Strings oder Arrays oder Objekten verglichen werden können.

    Neben den intelligenten Datums und Uhrzeitvergleichen, kann man sich diese natürlich über eine Change-Node ausgeben lassen oder direkt in einer Switch Node bearbeiten. Habe mal beide Varianten ausprobiert:

    6168c211-d459-4e44-9225-f5f2de60c2ad-image.png

    Ein Feature ist nämlich bei diesen Vergleichen noch erwähnenswert.
    Beide Zeiten unterscheiden sich um EINE Sekunde.

    fcd78e70-512f-48f2-97dd-5be13a27dc6a-image.png

    In einem Fall werden die Zeiten als identisch gesehen, im anderen Fall nicht.

    Das liegt an dem optionalen Parameter bei dem man die Genauigkeit des Vergleiches festlegen kann:

    (
        /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */
        $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
        $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
        $a.isSame($b, 'minute');
    )
    

    Im Fall der Gleichheit kann man mit dem zusätzlichen Parameter die Genauigkeit angeben.

    Hier wieder die Flows zum Nachvollziehen:

    [
        {
            "id": "d188a814.e04a98",
            "type": "switch",
            "z": "6e170384.60c96c",
            "name": "Zeitvergleich timeA mit timeB (kann auch payload sein)",
            "property": "payload",
            "propertyType": "msg",
            "rules": [
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isBefore($b);\t)",
                    "vt": "jsonata"
                },
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isSame($b);\t)",
                    "vt": "jsonata"
                },
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isAfter($b);\t)",
                    "vt": "jsonata"
                }
            ],
            "checkall": "true",
            "repair": false,
            "outputs": 3,
            "x": 1620,
            "y": 2380,
            "wires": [
                [
                    "b4916682.149148"
                ],
                [
                    "fa06bddb.66ba4"
                ],
                [
                    "a18e91aa.f7308"
                ]
            ],
            "outputLabels": [
                "vorher",
                "jetzt",
                "nachher"
            ]
        },
        {
            "id": "42a8b703.938598",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (A < B)",
            "props": [
                {
                    "p": "timeA",
                    "v": "08.12.2021 11:30:58",
                    "vt": "str"
                },
                {
                    "p": "timeB",
                    "v": "16.12.2031 15:18:26",
                    "vt": "str"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "timeA liegt vor timeB",
            "payloadType": "str",
            "x": 1220,
            "y": 2340,
            "wires": [
                [
                    "d188a814.e04a98",
                    "da19780.c02ad88",
                    "63a51f8c.1ebb7"
                ]
            ]
        },
        {
            "id": "f40bd97a.aeea38",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (B < A)",
            "props": [
                {
                    "p": "timeA",
                    "v": "16.12.2031 15:18:26",
                    "vt": "str"
                },
                {
                    "p": "timeB",
                    "v": "08.12.2021 11:30:58",
                    "vt": "str"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "timeA liegt hinter timeB",
            "payloadType": "str",
            "x": 1220,
            "y": 2380,
            "wires": [
                [
                    "d188a814.e04a98"
                ]
            ]
        },
        {
            "id": "e6827e39.c5da5",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (A < jetzt)",
            "props": [
                {
                    "p": "timeA",
                    "v": "08.12.2021 11:30:58",
                    "vt": "str"
                },
                {
                    "p": "timeB",
                    "v": "",
                    "vt": "date"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "timeA liegt in der Vergangenheit",
            "payloadType": "str",
            "x": 1210,
            "y": 2420,
            "wires": [
                [
                    "d188a814.e04a98"
                ]
            ]
        },
        {
            "id": "761cefe4.729fc",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (jetzt < A)",
            "props": [
                {
                    "p": "timeA",
                    "v": "16.12.2031 15:18:26",
                    "vt": "str"
                },
                {
                    "p": "timeB",
                    "v": "",
                    "vt": "date"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "timeA liegt in der Zukunft",
            "payloadType": "str",
            "x": 1210,
            "y": 2460,
            "wires": [
                [
                    "d188a814.e04a98"
                ]
            ]
        },
        {
            "id": "41a3133b.a5c94c",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (A = B) ?",
            "props": [
                {
                    "p": "timeA",
                    "v": "08.12.2021 11:30:58",
                    "vt": "str"
                },
                {
                    "p": "timeB",
                    "v": "08.12.2021 11:30:57",
                    "vt": "str"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "timeA = timeB",
            "payloadType": "str",
            "x": 1210,
            "y": 2500,
            "wires": [
                [
                    "d188a814.e04a98",
                    "719366f5.750378"
                ]
            ]
        },
        {
            "id": "7cdf530.bf841ac",
            "type": "inject",
            "z": "6e170384.60c96c",
            "name": "Vergleich timeA,timeB (jetzt = jetzt ?)",
            "props": [
                {
                    "p": "timeA",
                    "v": "",
                    "vt": "date"
                },
                {
                    "p": "timeB",
                    "v": "",
                    "vt": "date"
                },
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "jetzt = jetzt ?",
            "payloadType": "str",
            "x": 1200,
            "y": 2540,
            "wires": [
                [
                    "d188a814.e04a98"
                ]
            ]
        },
        {
            "id": "6c556c55.0afd74",
            "type": "comment",
            "z": "6e170384.60c96c",
            "name": "Zeitvergleiche",
            "info": "",
            "x": 1030,
            "y": 2280,
            "wires": []
        },
        {
            "id": "b4916682.149148",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Vorher",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1950,
            "y": 2340,
            "wires": []
        },
        {
            "id": "da19780.c02ad88",
            "type": "change",
            "z": "6e170384.60c96c",
            "name": "Vergleiche $moment mit $moment",
            "rules": [
                {
                    "t": "set",
                    "p": "payload",
                    "pt": "msg",
                    "to": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isBefore($b);\t)",
                    "tot": "jsonata"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 1580,
            "y": 2220,
            "wires": [
                [
                    "70cb81ee.f06a7"
                ]
            ]
        },
        {
            "id": "70cb81ee.f06a7",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "",
            "active": false,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "false",
            "statusVal": "",
            "statusType": "auto",
            "x": 1830,
            "y": 2220,
            "wires": []
        },
        {
            "id": "63a51f8c.1ebb7",
            "type": "change",
            "z": "6e170384.60c96c",
            "name": "$moment mit String",
            "rules": [
                {
                    "t": "set",
                    "p": "payload",
                    "pt": "msg",
                    "to": "$moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de').isBefore(timeB)",
                    "tot": "jsonata"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 1530,
            "y": 2160,
            "wires": [
                [
                    "4af98501.9a70dc"
                ]
            ]
        },
        {
            "id": "4af98501.9a70dc",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "",
            "active": false,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "false",
            "statusVal": "",
            "statusType": "auto",
            "x": 1740,
            "y": 2160,
            "wires": []
        },
        {
            "id": "fa06bddb.66ba4",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Zeit identisch",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1970,
            "y": 2380,
            "wires": []
        },
        {
            "id": "a18e91aa.f7308",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Nachher",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1960,
            "y": 2420,
            "wires": []
        },
        {
            "id": "719366f5.750378",
            "type": "switch",
            "z": "6e170384.60c96c",
            "name": "Zeitvergleich mit Minutengenauigkeit",
            "property": "payload",
            "propertyType": "msg",
            "rules": [
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isBefore($b, 'minute');\t)",
                    "vt": "jsonata"
                },
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isSame($b, 'minute');\t)",
                    "vt": "jsonata"
                },
                {
                    "t": "jsonata_exp",
                    "v": "(\t    /* Vergleiche gehen nicht mit Einzeiler - wenn man nicht normale Stringvergleiche etc. nutzt */\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a.isAfter($b, 'minute');\t)",
                    "vt": "jsonata"
                }
            ],
            "checkall": "true",
            "repair": false,
            "outputs": 3,
            "x": 1570,
            "y": 2500,
            "wires": [
                [
                    "eae6f820.a21208"
                ],
                [
                    "e83be57d.539fa8"
                ],
                [
                    "3b3db16d.d8b2fe"
                ]
            ],
            "outputLabels": [
                "vorher",
                "jetzt",
                "nachher"
            ]
        },
        {
            "id": "eae6f820.a21208",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Vorher",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1950,
            "y": 2460,
            "wires": []
        },
        {
            "id": "e83be57d.539fa8",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Zeit identisch",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1970,
            "y": 2500,
            "wires": []
        },
        {
            "id": "3b3db16d.d8b2fe",
            "type": "debug",
            "z": "6e170384.60c96c",
            "name": "Nachher",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 1960,
            "y": 2540,
            "wires": []
        }
    ]
    

    Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

    1 Antwort Letzte Antwort
    2
    • mickymM mickym

      Da ich mich nun mal 1-2 Tage intensiv mit der "eingebauten" Datums- und Uhrzeitverarbeitung in NodeRed beschäftigt habe, würde ich meine Erkenntnisse gerne teilen und vielleicht springt ja für den einen oder anderen was nützliches heraus.

      Es geht in diesem Thread nicht um die Installation von zusätzlichen Nodes, die noch weitere Steuerungsmöglichkeiten bieten, sondern das was im Grundbaukasten bereits vorhanden ist.

      Als wer noch mehr zu den Themen - scheduling oder Zeit filtern sucht - der soll sich mal folgende Nodes anschauen:

      1. cronplus: https://flows.nodered.org/node/node-red-contrib-cron-plus - alles und noch mehr was iobroker mit dem cron als Scheduler bietet.
      2. lightscheduler: https://flows.nodered.org/node/node-red-contrib-light-scheduler triggert - aber vor allem filtert nach Zeitereignissen
      3. bigtimer - wobei ich zwar am Anfang begeistert war, aber ich inzwischen den Nutzen nicht mehr sehr hoch einschätze:
        https://flows.nodered.org/node/node-red-contrib-bigtimer

      Doch mir geht es ja nicht darum, mit welchen zusätzlichen Nodes man noch was machen kann, so wie man mit dem Grundbaukasten Zeit- und Datumsereignisse verarbeitet. Zum Schluss stelle ich dann noch einen kleinen Flow vor, den man als Timer nutzen kann. ;) - und zwar flexibler als bei den fertigen Nodes. ;)

      Die Javascript Bibliothek, die in Node Red für die Datums- und Uhrzeit verarbeitung verfügbar ist, ist wohl die moment.js - und die Funktionen dieser Bibliothek werden ich nun im Verlauf weiter vorstellen - allerdings nicht über Javascript, sondern im Prinzip kann man diese ganze Bibliothek über JSONATA nutzen. Erst seit dem ich mich damit nun etwas näher beschäftigt habe, ergeben sich neuen Möglichkeiten, wobei ich auch noch hin und wieder ??? habe und deswegen vielleicht manches hier umständlich aussieht.

      Dennoch kommt bei diesem Thread quasi kein natives Javascript zur Anwendung (also keine Function Nodes). ;) ;)

      Ich denke, das im Blockly wohl auch die moment.js eingebunden ist - insofern kann man das vergleichen und gegenüberstellen.

      Was im Standard nicht verfügbar ist, sind die Astrozeiten - dafür bieten sich aber alle 3 oben genannten Nodes an - die hier eine Vielzahl an Funktionen bieten - wer da mehr wissen will, meldet sich einfach.

      Wie gesagt - sowohl im Blockly als auch in Node Red wurde für die Datums und Uhrzeitverarbeitung die moment.js Bibliothek verfügbar gemacht. Dabei geht in NodeRed in meinen Augen die Möglichkeiten der Nutzung über das hinaus, was üblicherweise in den Puzzleteilchen angeboten wird. ;)

      Die volle Funktionalität der moment.js Bibliothek sollte man sich als Nachschlagewerk als Seite abspeichern:
      https://momentjs.com/docs/#/parsing/

      Anscheinend wird die Bibliothek nicht mehr weiter entwickelt - wird aber noch gewartet.

      Nodes die vollkommen überflüssig sind, sind die moment.js Nodes - zumindest seitdem die moment.js Bibliothek unter NodeRed im JSONATA verfügbar gemacht wurde. Diese Nodes : https://flows.nodered.org/node/node-red-contrib-moment können also komplett ersetzt werden. Ich hatte die anfangs auch, werden nun aber rausgeschmissen.

      Dreh- und Angelpunkte bei der Nutzung der moment.js Bibliothek sind natürlich die moment-Objekte. Diese sind keine date-Objekte von Javascript. Wer also die moment.js Bibliothek im Javascript nutzen will, muss sie nach Installation halt wie üblich mit require in den Code einbinden.

      https://momentjs.com/docs/#/use-it/

      var moment = require('moment'); // require
      moment().format()
      

      In NodeRed ist es wie gesagt nicht erforderlich und man benötigt weder eine moment.js Insallation noch muss man Bibliohteken global verfügbar machen - außer man wollte die moment.js in function Nodes nutzen, was hier aber nicht der Fall ist und deswegen auch nicht weiter beschrieben wird. Hier geht es deshalb ausschließlich um die moment.js Funktionen, die JSONATA in NodeRed zur Verfügung stellt und die deshalb in verschiedenen Nodes wie der Change-Node, der Inject-Node, der Switch-Node, Join-Node etc. zur Verfügung steht und angewandt wird.

      Im folgenden werde ich mich etwas an Blockly orientieren - da in meinen Augen die gleiche Bibliothek dahinter liegt und erklären, wie man das im JSONATA und in NodeRed umsetzt.

      mickymM Offline
      mickymM Offline
      mickym
      Most Active
      schrieb am zuletzt editiert von mickym
      #5

      4. Rechnen mit Datum und Uhrzeit

      Hier habe ich im Blockly gar keinen Baustein gefunden. Ich gehe davon aus, dass man halt alles in Timestamps also UNIX Millisekunden umrechnet und dann rechnet.

      Hier wieder die Doku:
      https://momentjs.com/docs/#/manipulating/

      Neben dem jeweiligen Setzen des Moment-Objektes auf den Anfang oder das Ende einer Zeiteinheit Start und End of Time, gibt es die Möglichkeit Zeitspannen in die Vergangenheit oder in die Zukunft mit Text ausgeben zu lassen. Time from/to now oder Time from/to X. Also in einem Textformat sich die Zeit relativ entweder zur aktuellen ZEit oder einem beliebigen Zeitpunkt ausgeben zu lassen.

      Dabei bleiben die ZEitangaben aber bewußt wage und werden nur immer exakter.

      6635a3aa-64e3-4f37-bd36-7a2e1a97c372-image.png

      Nun zum Rechnen - da die innerhalb der Objekte funktioniert - braucht man sich um irgendwelche Wechsel oder Einheiten keine Gedanken zu machen:

      Mit folgendem Einzeiler addieren ich zu aktuellen Zeit 600s dazu - also 10 Minuten (Grün im Screenshot):

      $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add(600,'s').format('DD.MM.YYYY HH:mm:ss')
      

      Das tolle ist aber das ich auch ganze Objekte addieren kann, wie 600 Sekunden und 8 Stunden. ;) (Rot im Screenshot)

      $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add({'seconds':600,'hours':8}).format('DD.MM.YYYY HH:mm:ss')
      

      79a8cd12-0e18-4875-90ba-f035583c87d3-image.png

      Leider habe ich es nicht geschafft an das duration Objekt über JSONATA ranzukommen - deshalb hab ich das wieder als JSONATA Skript mühsam zurückverwandelt. Wie gesagt - wahrscheinlich geht das eleganter - aber ich bin zu blöd dazu.

      Jedenfalls um das Delta wieder herauszubekommen, habe ich folgendes JSONATA Skript gebastelt:

      Erstmal wird zur aktuellen Zeit folgende Zeitstpanne hinzugerechnet:

      {
          "days": 8,
          "hours": 3,
          "minutes": 47,
          "seconds": 28
      }
      

      5c58812b-c23f-4c2b-80f8-49f93a24bff9-image.png

      Die jetzige Zeit timeA plus 8 Tage, 3 Stunden, 47 Minuten und 28 Sekunden ergibt dann timeB.

      Um dann wieder die Differenz zu jetzt zu berechnen - und ohne Zugriff auf das duration Objekt habe ich folgendes Skript verwendet:

      (
          $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
          $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
          
          /* $b.diff($a) */
          /* $moment.duration($b.diff($a)); */
          
              /* Kein Zugriff auf duration  - also manuell berechnen*/
              
          $days := $b.diff($a, 'days');
          $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');
          $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');
          $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');
          
          $sec := $b.diff($a)/1000;
          
      
          
          $difference := {
              "days": $days,
              "hours":$hours,
              "minutes": $minutes,
              "seconds": $seconds
          }; 
          
      
      )
      

      Nun noch ein einfaches Beispiel wie man diese "lesbare" Format für eine Zeitdiffernz verwenden kann:

      $moment().locale('de').endOf('year').fromNow()
      

      Damit beantwortet man die Frage, wie lange dieses Jahr noch dauert? :grin:

      Mit der locale gesetzt bekommt man dann diese Antwort:

      c833e769-a5c7-4e3e-82c3-79d01f5d2eb1-image.png

      Hier wieder alles zum Ausprobieren:

      [
         {
             "id": "66130be.e3d21f4",
             "type": "comment",
             "z": "6e170384.60c96c",
             "name": "Addiere Zeit",
             "info": "",
             "x": 1150,
             "y": 2660,
             "wires": []
         },
         {
             "id": "d1d93ace.9e1b68",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "jetzt ",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "",
             "payloadType": "date",
             "x": 1210,
             "y": 2720,
             "wires": [
                 [
                     "83777c88.0e9f4"
                 ]
             ]
         },
         {
             "id": "5fe67e1b.303bc",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "false",
             "statusVal": "",
             "statusType": "auto",
             "x": 1950,
             "y": 2720,
             "wires": []
         },
         {
             "id": "90f0662.532d198",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "jetzt + 600 s",
             "props": [
                 {
                     "p": "payload"
                 },
                 {
                     "p": "x",
                     "v": "600",
                     "vt": "num"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "",
             "payloadType": "date",
             "x": 1210,
             "y": 2840,
             "wires": [
                 [
                     "e17fd57b.bc3688"
                 ]
             ]
         },
         {
             "id": "83777c88.0e9f4",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "Addiere payload + 600 Sekunden (fix)",
             "rules": [
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add(600,'s').format('DD.MM.YYYY HH:mm:ss')",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1490,
             "y": 2720,
             "wires": [
                 [
                     "5fe67e1b.303bc"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "e17fd57b.bc3688",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "Addiere payload + x",
             "rules": [
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x,'s').format('DD.MM.YYYY HH:mm:ss');\t    )",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1620,
             "y": 2840,
             "wires": [
                 [
                     "5fe67e1b.303bc"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "effe038a.cbb48",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "jetzt ",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "",
             "payloadType": "date",
             "x": 1210,
             "y": 2760,
             "wires": [
                 [
                     "30786bec.22b774"
                 ]
             ]
         },
         {
             "id": "30786bec.22b774",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "Addiere payload + 8 Std. 10 Sekunden (fix Objekt)",
             "rules": [
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add({'seconds':600,'hours':8}).format('DD.MM.YYYY HH:mm:ss')",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1530,
             "y": 2760,
             "wires": [
                 [
                     "5fe67e1b.303bc"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "59cb1204.56d48c",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "jetzt + 8 Tagen + 8 Stunden und 5 Minuten",
             "props": [
                 {
                     "p": "payload"
                 },
                 {
                     "p": "x",
                     "v": "{\"days\":8,\"hours\":8,\"minutes\":5}",
                     "vt": "json"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "",
             "payloadType": "date",
             "x": 1140,
             "y": 2880,
             "wires": [
                 [
                     "28620d53.734272"
                 ]
             ]
         },
         {
             "id": "28620d53.734272",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "Addiere payload + x",
             "rules": [
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                     "tot": "jsonata"
                 },
                 {
                     "t": "set",
                     "p": "fromNow",
                     "pt": "msg",
                     "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()\t",
                     "tot": "jsonata"
                 },
                 {
                     "t": "set",
                     "p": "objMoment",
                     "pt": "msg",
                     "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').toObject()",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1620,
             "y": 2880,
             "wires": [
                 [
                     "5fe67e1b.303bc",
                     "7492d83.5499d28",
                     "2fd5b727.226098"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "7492d83.5499d28",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "fromNow",
             "targetType": "msg",
             "statusVal": "",
             "statusType": "auto",
             "x": 1960,
             "y": 2880,
             "wires": []
         },
         {
             "id": "2fd5b727.226098",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "objMoment",
             "targetType": "msg",
             "statusVal": "",
             "statusType": "auto",
             "x": 1960,
             "y": 2940,
             "wires": []
         },
         {
             "id": "c38cc5bf.7f7f38",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "jetzt + 8 Tagen + 3 Stunden + 47 Minuten +28 Sekunden",
             "props": [
                 {
                     "p": "payload"
                 },
                 {
                     "p": "x",
                     "v": "{\"days\":8,\"hours\":3,\"minutes\":47,\"seconds\":28}",
                     "vt": "json"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "",
             "payloadType": "date",
             "x": 1150,
             "y": 2980,
             "wires": [
                 [
                     "f6e8d65f.929de8"
                 ]
             ]
         },
         {
             "id": "f6e8d65f.929de8",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
             "rules": [
                 {
                     "t": "set",
                     "p": "timeA",
                     "pt": "msg",
                     "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                     "tot": "jsonata"
                 },
                 {
                     "t": "set",
                     "p": "timeB",
                     "pt": "msg",
                     "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                     "tot": "jsonata"
                 },
                 {
                     "t": "delete",
                     "p": "x",
                     "pt": "msg"
                 },
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1440,
             "y": 3040,
             "wires": [
                 [
                     "fb984b77.f03568"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "fb984b77.f03568",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "true",
             "targetType": "full",
             "statusVal": "",
             "statusType": "auto",
             "x": 1830,
             "y": 3040,
             "wires": []
         },
         {
             "id": "3fe4ca70.df9536",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "true",
             "payloadType": "bool",
             "x": 1150,
             "y": 3100,
             "wires": [
                 [
                     "30471772.8d6318"
                 ]
             ]
         },
         {
             "id": "30471772.8d6318",
             "type": "change",
             "z": "6e170384.60c96c",
             "name": "Wann endet dieses Jahr?",
             "rules": [
                 {
                     "t": "set",
                     "p": "payload",
                     "pt": "msg",
                     "to": "$moment().locale('de').endOf('year').fromNow()",
                     "tot": "jsonata"
                 }
             ],
             "action": "",
             "property": "",
             "from": "",
             "to": "",
             "reg": false,
             "x": 1350,
             "y": 3100,
             "wires": [
                 [
                     "2e00f9b5.373e16"
                 ]
             ],
             "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
         },
         {
             "id": "9958c57.83b6e38",
             "type": "comment",
             "z": "6e170384.60c96c",
             "name": "Zeitvergleiche",
             "info": "",
             "x": 1150,
             "y": 2940,
             "wires": []
         },
         {
             "id": "2e00f9b5.373e16",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "false",
             "statusVal": "",
             "statusType": "auto",
             "x": 1630,
             "y": 3100,
             "wires": []
         },
         {
             "id": "8577b178.59305",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "false",
             "statusVal": "",
             "statusType": "auto",
             "x": 1610,
             "y": 3160,
             "wires": []
         },
         {
             "id": "1dce01d9.b2e5de",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "$moment().startOf('day').seconds()",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "$moment('18:48:12','HH:mm:ss').diff($moment().startOf('day'),'seconds')",
             "payloadType": "jsonata",
             "x": 1340,
             "y": 3160,
             "wires": [
                 [
                     "8577b178.59305"
                 ]
             ]
         },
         {
             "id": "4c679067.458b3",
             "type": "debug",
             "z": "6e170384.60c96c",
             "name": "",
             "active": true,
             "tosidebar": true,
             "console": false,
             "tostatus": false,
             "complete": "false",
             "statusVal": "",
             "statusType": "auto",
             "x": 1590,
             "y": 3220,
             "wires": []
         },
         {
             "id": "964661.389f19a",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "$moment('18:48:12','HH:mm:ss').diff($moment().startOf('day'),'seconds')",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "$moment('18:48:12','HH:mm:ss').diff($moment().startOf('day'),'seconds')",
             "payloadType": "jsonata",
             "x": 1230,
             "y": 3240,
             "wires": [
                 [
                     "4c679067.458b3"
                 ]
             ]
         },
         {
             "id": "3021c4fa.70473c",
             "type": "inject",
             "z": "6e170384.60c96c",
             "name": "$moment().diff($moment().startOf('day'),'seconds')",
             "props": [
                 {
                     "p": "payload"
                 }
             ],
             "repeat": "",
             "crontab": "",
             "once": false,
             "onceDelay": 0.1,
             "topic": "",
             "payload": "$moment().diff($moment().startOf('day'),'seconds')",
             "payloadType": "jsonata",
             "x": 1290,
             "y": 3200,
             "wires": [
                 [
                     "4c679067.458b3"
                 ]
             ]
         }
      ]
      

      Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

      1 Antwort Letzte Antwort
      1
      • mickymM mickym

        Da ich mich nun mal 1-2 Tage intensiv mit der "eingebauten" Datums- und Uhrzeitverarbeitung in NodeRed beschäftigt habe, würde ich meine Erkenntnisse gerne teilen und vielleicht springt ja für den einen oder anderen was nützliches heraus.

        Es geht in diesem Thread nicht um die Installation von zusätzlichen Nodes, die noch weitere Steuerungsmöglichkeiten bieten, sondern das was im Grundbaukasten bereits vorhanden ist.

        Als wer noch mehr zu den Themen - scheduling oder Zeit filtern sucht - der soll sich mal folgende Nodes anschauen:

        1. cronplus: https://flows.nodered.org/node/node-red-contrib-cron-plus - alles und noch mehr was iobroker mit dem cron als Scheduler bietet.
        2. lightscheduler: https://flows.nodered.org/node/node-red-contrib-light-scheduler triggert - aber vor allem filtert nach Zeitereignissen
        3. bigtimer - wobei ich zwar am Anfang begeistert war, aber ich inzwischen den Nutzen nicht mehr sehr hoch einschätze:
          https://flows.nodered.org/node/node-red-contrib-bigtimer

        Doch mir geht es ja nicht darum, mit welchen zusätzlichen Nodes man noch was machen kann, so wie man mit dem Grundbaukasten Zeit- und Datumsereignisse verarbeitet. Zum Schluss stelle ich dann noch einen kleinen Flow vor, den man als Timer nutzen kann. ;) - und zwar flexibler als bei den fertigen Nodes. ;)

        Die Javascript Bibliothek, die in Node Red für die Datums- und Uhrzeit verarbeitung verfügbar ist, ist wohl die moment.js - und die Funktionen dieser Bibliothek werden ich nun im Verlauf weiter vorstellen - allerdings nicht über Javascript, sondern im Prinzip kann man diese ganze Bibliothek über JSONATA nutzen. Erst seit dem ich mich damit nun etwas näher beschäftigt habe, ergeben sich neuen Möglichkeiten, wobei ich auch noch hin und wieder ??? habe und deswegen vielleicht manches hier umständlich aussieht.

        Dennoch kommt bei diesem Thread quasi kein natives Javascript zur Anwendung (also keine Function Nodes). ;) ;)

        Ich denke, das im Blockly wohl auch die moment.js eingebunden ist - insofern kann man das vergleichen und gegenüberstellen.

        Was im Standard nicht verfügbar ist, sind die Astrozeiten - dafür bieten sich aber alle 3 oben genannten Nodes an - die hier eine Vielzahl an Funktionen bieten - wer da mehr wissen will, meldet sich einfach.

        Wie gesagt - sowohl im Blockly als auch in Node Red wurde für die Datums und Uhrzeitverarbeitung die moment.js Bibliothek verfügbar gemacht. Dabei geht in NodeRed in meinen Augen die Möglichkeiten der Nutzung über das hinaus, was üblicherweise in den Puzzleteilchen angeboten wird. ;)

        Die volle Funktionalität der moment.js Bibliothek sollte man sich als Nachschlagewerk als Seite abspeichern:
        https://momentjs.com/docs/#/parsing/

        Anscheinend wird die Bibliothek nicht mehr weiter entwickelt - wird aber noch gewartet.

        Nodes die vollkommen überflüssig sind, sind die moment.js Nodes - zumindest seitdem die moment.js Bibliothek unter NodeRed im JSONATA verfügbar gemacht wurde. Diese Nodes : https://flows.nodered.org/node/node-red-contrib-moment können also komplett ersetzt werden. Ich hatte die anfangs auch, werden nun aber rausgeschmissen.

        Dreh- und Angelpunkte bei der Nutzung der moment.js Bibliothek sind natürlich die moment-Objekte. Diese sind keine date-Objekte von Javascript. Wer also die moment.js Bibliothek im Javascript nutzen will, muss sie nach Installation halt wie üblich mit require in den Code einbinden.

        https://momentjs.com/docs/#/use-it/

        var moment = require('moment'); // require
        moment().format()
        

        In NodeRed ist es wie gesagt nicht erforderlich und man benötigt weder eine moment.js Insallation noch muss man Bibliohteken global verfügbar machen - außer man wollte die moment.js in function Nodes nutzen, was hier aber nicht der Fall ist und deswegen auch nicht weiter beschrieben wird. Hier geht es deshalb ausschließlich um die moment.js Funktionen, die JSONATA in NodeRed zur Verfügung stellt und die deshalb in verschiedenen Nodes wie der Change-Node, der Inject-Node, der Switch-Node, Join-Node etc. zur Verfügung steht und angewandt wird.

        Im folgenden werde ich mich etwas an Blockly orientieren - da in meinen Augen die gleiche Bibliothek dahinter liegt und erklären, wie man das im JSONATA und in NodeRed umsetzt.

        mickymM Offline
        mickymM Offline
        mickym
        Most Active
        schrieb am zuletzt editiert von mickym
        #6

        5. Abschluss

        So zum Abschluss habe ich mal meine neuen Kenntnisse dazu genutzt, um mit den einfachen Boardmitteln einen Timer zu erstellen.

        Einen der nicht geschwätzig ist. Wie gesagt, dass schöne an der Bibliothek ist dass man Objekte mit beliebigen Einheiten dazu addieren kann.

        Hier der Flow:

        429df954-1b1c-4dd4-9c83-d1be0831cf9b-image.png

        Hier mal der 9 Minuten und 28 Sekunden Timer Ausgabe in lesbarer aber nicht geschwätziger Form:
        Die Einheiten werden auch richtig auf und abgerundet. Wenn also in 7 Minuten ausgegeben wird, dann befindet sich er Timer zwischen 7:29 und 6:30 Minuten.

        3d38a592-8c0d-4b83-b447-64a30bb930ee-image.png

        und hier die geschwätzige Ausgabe mittels Angabe von verbleibenden Minuten und Sekunden.

        78f50370-b24a-4122-8ef0-37be86d1ac32-image.png

        Das Ende der Ausgabe ist noch unschön und kann man sicher anders lösen - aber das kann ja jeder für sich mal machen.

        Hier noch den Timerflow zum Import:

        [
           {
               "id": "1ebefb6.e95e305",
               "type": "inject",
               "z": "6e170384.60c96c",
               "name": "",
               "props": [
                   {
                       "p": "payload"
                   },
                   {
                       "p": "topic",
                       "vt": "str"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "timer",
               "payload": "{\"minutes\":9,\"seconds\":28}",
               "payloadType": "json",
               "x": 1030,
               "y": 1720,
               "wires": [
                   [
                       "f057bad5.22c0c8"
                   ]
               ]
           },
           {
               "id": "f057bad5.22c0c8",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "Timer läuft ab",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "(\t    $x := payload;\t    $moment().add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1360,
               "y": 1700,
               "wires": [
                   [
                       "d539534f.ccfa8"
                   ]
               ],
               "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
           },
           {
               "id": "d539534f.ccfa8",
               "type": "trigger",
               "z": "6e170384.60c96c",
               "name": "",
               "op1": "",
               "op2": "0",
               "op1type": "pay",
               "op2type": "str",
               "duration": "-1",
               "extend": false,
               "overrideDelay": false,
               "units": "s",
               "reset": "",
               "bytopic": "all",
               "topic": "topic",
               "outputs": 1,
               "x": 1580,
               "y": 1700,
               "wires": [
                   [
                       "173f530c.7cf97d",
                       "ffe4b703.5c7ac8",
                       "5ad21dfe.76dc14"
                   ]
               ]
           },
           {
               "id": "ba662ea7.2a6e3",
               "type": "inject",
               "z": "6e170384.60c96c",
               "name": "reset",
               "props": [
                   {
                       "p": "reset",
                       "v": "true",
                       "vt": "bool"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "",
               "x": 1350,
               "y": 1760,
               "wires": [
                   [
                       "d539534f.ccfa8"
                   ]
               ]
           },
           {
               "id": "173f530c.7cf97d",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1810,
               "y": 1700,
               "wires": [
                   [
                       "16b62a7a.c7e9c6"
                   ]
               ]
           },
           {
               "id": "16b62a7a.c7e9c6",
               "type": "rbe",
               "z": "6e170384.60c96c",
               "name": "",
               "func": "rbe",
               "gap": "",
               "start": "",
               "inout": "out",
               "septopics": true,
               "property": "payload",
               "x": 1570,
               "y": 1620,
               "wires": [
                   [
                       "3aa094bf.4cd0bc"
                   ]
               ]
           },
           {
               "id": "5414e8d9.006ec8",
               "type": "debug",
               "z": "6e170384.60c96c",
               "name": "",
               "active": false,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "false",
               "statusVal": "",
               "statusType": "auto",
               "x": 1970,
               "y": 1560,
               "wires": []
           },
           {
               "id": "9e313ea9.6c67e",
               "type": "comment",
               "z": "6e170384.60c96c",
               "name": "Timer ausgabe",
               "info": "",
               "x": 800,
               "y": 1500,
               "wires": []
           },
           {
               "id": "ffe4b703.5c7ac8",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').isSameOrAfter($moment())",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1810,
               "y": 1760,
               "wires": [
                   [
                       "9cb1684c.9731a8"
                   ]
               ]
           },
           {
               "id": "9cb1684c.9731a8",
               "type": "switch",
               "z": "6e170384.60c96c",
               "name": "Timer abgelaufen?",
               "property": "payload",
               "propertyType": "msg",
               "rules": [
                   {
                       "t": "false"
                   }
               ],
               "checkall": "true",
               "repair": false,
               "outputs": 1,
               "x": 1810,
               "y": 1820,
               "wires": [
                   [
                       "2a83c3b3.e36c4c"
                   ]
               ]
           },
           {
               "id": "2a83c3b3.e36c4c",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "Timer abgelaufen, dann reset",
               "rules": [
                   {
                       "t": "set",
                       "p": "reset",
                       "pt": "msg",
                       "to": "true",
                       "tot": "bool"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1520,
               "y": 1880,
               "wires": [
                   [
                       "d539534f.ccfa8"
                   ]
               ]
           },
           {
               "id": "3aa094bf.4cd0bc",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "",
               "rules": [
                   {
                       "t": "change",
                       "p": "payload",
                       "pt": "msg",
                       "from": "vor ein paar Sekunden",
                       "fromt": "str",
                       "to": "Timer wurde beendet",
                       "tot": "str"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1800,
               "y": 1620,
               "wires": [
                   [
                       "5414e8d9.006ec8"
                   ]
               ]
           },
           {
               "id": "5ad21dfe.76dc14",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
               "rules": [
                   {
                       "t": "set",
                       "p": "timeA",
                       "pt": "msg",
                       "to": "$moment().format('DD.MM.YYYY HH:mm:ss')",
                       "tot": "jsonata"
                   },
                   {
                       "t": "set",
                       "p": "timeB",
                       "pt": "msg",
                       "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                       "tot": "jsonata"
                   },
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1420,
               "y": 1500,
               "wires": [
                   [
                       "6c4aa2f5.a318ac"
                   ]
               ],
               "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
           },
           {
               "id": "21f3fe07.9102e2",
               "type": "debug",
               "z": "6e170384.60c96c",
               "name": "",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "false",
               "statusVal": "",
               "statusType": "auto",
               "x": 1950,
               "y": 1500,
               "wires": []
           },
           {
               "id": "6c4aa2f5.a318ac",
               "type": "change",
               "z": "6e170384.60c96c",
               "name": "",
               "rules": [
                   {
                       "t": "set",
                       "p": "payload",
                       "pt": "msg",
                       "to": "(\t    $str := payload.days > 0 ? payload.days & ' Tage(n) ' : '';\t    $str := payload.hours > 0 ? $str & payload.hours & ' Stunde(n) ' : '';\t    $str := payload.minutes > 0 ? $str & payload.minutes & ' Minute(n) ' : '';\t    $str := $str & payload.seconds & ' Sekunde(n)';\t    $str := ($str = '0 Sekunde(n)' or str = '-1 Sekunde(n)') ? 'Timer beendet' : $str;\t\t\t)",
                       "tot": "jsonata"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 1750,
               "y": 1500,
               "wires": [
                   [
                       "21f3fe07.9102e2"
                   ]
               ]
           },
           {
               "id": "7acd75d2.b229ac",
               "type": "inject",
               "z": "6e170384.60c96c",
               "name": "",
               "props": [
                   {
                       "p": "payload"
                   },
                   {
                       "p": "topic",
                       "vt": "str"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "timer",
               "payload": "{\"seconds\":5}",
               "payloadType": "json",
               "x": 1070,
               "y": 1760,
               "wires": [
                   [
                       "f057bad5.22c0c8"
                   ]
               ]
           },
           {
               "id": "6ef0f333.4dd95c",
               "type": "inject",
               "z": "6e170384.60c96c",
               "name": "timer: {\"hours\":2,\"minutes\":47,\"seconds\":28}",
               "props": [
                   {
                       "p": "payload"
                   },
                   {
                       "p": "topic",
                       "vt": "str"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "timer",
               "payload": "{\"hours\":2,\"minutes\":47,\"seconds\":28}",
               "payloadType": "json",
               "x": 990,
               "y": 1680,
               "wires": [
                   [
                       "f057bad5.22c0c8"
                   ]
               ]
           },
           {
               "id": "6c51e401.1c82bc",
               "type": "inject",
               "z": "6e170384.60c96c",
               "name": "timer: {\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
               "props": [
                   {
                       "p": "payload"
                   },
                   {
                       "p": "topic",
                       "vt": "str"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "timer",
               "payload": "{\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
               "payloadType": "json",
               "x": 970,
               "y": 1640,
               "wires": [
                   [
                       "f057bad5.22c0c8"
                   ]
               ]
           }
        ]
        

        FAZIT und ENDE: ;)
        Ich finde die moment.js Bibliothek und wie man sie in NodeRed mit Standardmitteln nutzen kann, wirklich sehr mächtig und es erleichtert einem das Hantieren mit Datums - und Uhrzeitformaten. Wie gesagt was JSONATA Programmierung oder manchmal diese Abkürzungs Syntax bedeutet, das überfordert mich leicht.

        Deshalb mal ganz allgemein: Wenn jemand Fragen hat gerne. Wenn mir jemand erklären kann, wie ich unter JSONATA an das Duration Objekt der moment.js Library komme - gerne.

        Ich hoffe es ist OK, wenn ich hier mal das was ich herausgefunden habe, aufschreibe und hoffe auch, dass es dem einen oder anderen bei seinen eigenen Projekten hilft.

        Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

        R F G 4 Antworten Letzte Antwort
        3
        • mickymM mickym

          5. Abschluss

          So zum Abschluss habe ich mal meine neuen Kenntnisse dazu genutzt, um mit den einfachen Boardmitteln einen Timer zu erstellen.

          Einen der nicht geschwätzig ist. Wie gesagt, dass schöne an der Bibliothek ist dass man Objekte mit beliebigen Einheiten dazu addieren kann.

          Hier der Flow:

          429df954-1b1c-4dd4-9c83-d1be0831cf9b-image.png

          Hier mal der 9 Minuten und 28 Sekunden Timer Ausgabe in lesbarer aber nicht geschwätziger Form:
          Die Einheiten werden auch richtig auf und abgerundet. Wenn also in 7 Minuten ausgegeben wird, dann befindet sich er Timer zwischen 7:29 und 6:30 Minuten.

          3d38a592-8c0d-4b83-b447-64a30bb930ee-image.png

          und hier die geschwätzige Ausgabe mittels Angabe von verbleibenden Minuten und Sekunden.

          78f50370-b24a-4122-8ef0-37be86d1ac32-image.png

          Das Ende der Ausgabe ist noch unschön und kann man sicher anders lösen - aber das kann ja jeder für sich mal machen.

          Hier noch den Timerflow zum Import:

          [
             {
                 "id": "1ebefb6.e95e305",
                 "type": "inject",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "props": [
                     {
                         "p": "payload"
                     },
                     {
                         "p": "topic",
                         "vt": "str"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "timer",
                 "payload": "{\"minutes\":9,\"seconds\":28}",
                 "payloadType": "json",
                 "x": 1030,
                 "y": 1720,
                 "wires": [
                     [
                         "f057bad5.22c0c8"
                     ]
                 ]
             },
             {
                 "id": "f057bad5.22c0c8",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "Timer läuft ab",
                 "rules": [
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "(\t    $x := payload;\t    $moment().add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1360,
                 "y": 1700,
                 "wires": [
                     [
                         "d539534f.ccfa8"
                     ]
                 ],
                 "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
             },
             {
                 "id": "d539534f.ccfa8",
                 "type": "trigger",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "op1": "",
                 "op2": "0",
                 "op1type": "pay",
                 "op2type": "str",
                 "duration": "-1",
                 "extend": false,
                 "overrideDelay": false,
                 "units": "s",
                 "reset": "",
                 "bytopic": "all",
                 "topic": "topic",
                 "outputs": 1,
                 "x": 1580,
                 "y": 1700,
                 "wires": [
                     [
                         "173f530c.7cf97d",
                         "ffe4b703.5c7ac8",
                         "5ad21dfe.76dc14"
                     ]
                 ]
             },
             {
                 "id": "ba662ea7.2a6e3",
                 "type": "inject",
                 "z": "6e170384.60c96c",
                 "name": "reset",
                 "props": [
                     {
                         "p": "reset",
                         "v": "true",
                         "vt": "bool"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "",
                 "x": 1350,
                 "y": 1760,
                 "wires": [
                     [
                         "d539534f.ccfa8"
                     ]
                 ]
             },
             {
                 "id": "173f530c.7cf97d",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "rules": [
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1810,
                 "y": 1700,
                 "wires": [
                     [
                         "16b62a7a.c7e9c6"
                     ]
                 ]
             },
             {
                 "id": "16b62a7a.c7e9c6",
                 "type": "rbe",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "func": "rbe",
                 "gap": "",
                 "start": "",
                 "inout": "out",
                 "septopics": true,
                 "property": "payload",
                 "x": 1570,
                 "y": 1620,
                 "wires": [
                     [
                         "3aa094bf.4cd0bc"
                     ]
                 ]
             },
             {
                 "id": "5414e8d9.006ec8",
                 "type": "debug",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "active": false,
                 "tosidebar": true,
                 "console": false,
                 "tostatus": false,
                 "complete": "false",
                 "statusVal": "",
                 "statusType": "auto",
                 "x": 1970,
                 "y": 1560,
                 "wires": []
             },
             {
                 "id": "9e313ea9.6c67e",
                 "type": "comment",
                 "z": "6e170384.60c96c",
                 "name": "Timer ausgabe",
                 "info": "",
                 "x": 800,
                 "y": 1500,
                 "wires": []
             },
             {
                 "id": "ffe4b703.5c7ac8",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "rules": [
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').isSameOrAfter($moment())",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1810,
                 "y": 1760,
                 "wires": [
                     [
                         "9cb1684c.9731a8"
                     ]
                 ]
             },
             {
                 "id": "9cb1684c.9731a8",
                 "type": "switch",
                 "z": "6e170384.60c96c",
                 "name": "Timer abgelaufen?",
                 "property": "payload",
                 "propertyType": "msg",
                 "rules": [
                     {
                         "t": "false"
                     }
                 ],
                 "checkall": "true",
                 "repair": false,
                 "outputs": 1,
                 "x": 1810,
                 "y": 1820,
                 "wires": [
                     [
                         "2a83c3b3.e36c4c"
                     ]
                 ]
             },
             {
                 "id": "2a83c3b3.e36c4c",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "Timer abgelaufen, dann reset",
                 "rules": [
                     {
                         "t": "set",
                         "p": "reset",
                         "pt": "msg",
                         "to": "true",
                         "tot": "bool"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1520,
                 "y": 1880,
                 "wires": [
                     [
                         "d539534f.ccfa8"
                     ]
                 ]
             },
             {
                 "id": "3aa094bf.4cd0bc",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "rules": [
                     {
                         "t": "change",
                         "p": "payload",
                         "pt": "msg",
                         "from": "vor ein paar Sekunden",
                         "fromt": "str",
                         "to": "Timer wurde beendet",
                         "tot": "str"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1800,
                 "y": 1620,
                 "wires": [
                     [
                         "5414e8d9.006ec8"
                     ]
                 ]
             },
             {
                 "id": "5ad21dfe.76dc14",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                 "rules": [
                     {
                         "t": "set",
                         "p": "timeA",
                         "pt": "msg",
                         "to": "$moment().format('DD.MM.YYYY HH:mm:ss')",
                         "tot": "jsonata"
                     },
                     {
                         "t": "set",
                         "p": "timeB",
                         "pt": "msg",
                         "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                         "tot": "jsonata"
                     },
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1420,
                 "y": 1500,
                 "wires": [
                     [
                         "6c4aa2f5.a318ac"
                     ]
                 ],
                 "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
             },
             {
                 "id": "21f3fe07.9102e2",
                 "type": "debug",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "active": true,
                 "tosidebar": true,
                 "console": false,
                 "tostatus": false,
                 "complete": "false",
                 "statusVal": "",
                 "statusType": "auto",
                 "x": 1950,
                 "y": 1500,
                 "wires": []
             },
             {
                 "id": "6c4aa2f5.a318ac",
                 "type": "change",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "rules": [
                     {
                         "t": "set",
                         "p": "payload",
                         "pt": "msg",
                         "to": "(\t    $str := payload.days > 0 ? payload.days & ' Tage(n) ' : '';\t    $str := payload.hours > 0 ? $str & payload.hours & ' Stunde(n) ' : '';\t    $str := payload.minutes > 0 ? $str & payload.minutes & ' Minute(n) ' : '';\t    $str := $str & payload.seconds & ' Sekunde(n)';\t    $str := ($str = '0 Sekunde(n)' or str = '-1 Sekunde(n)') ? 'Timer beendet' : $str;\t\t\t)",
                         "tot": "jsonata"
                     }
                 ],
                 "action": "",
                 "property": "",
                 "from": "",
                 "to": "",
                 "reg": false,
                 "x": 1750,
                 "y": 1500,
                 "wires": [
                     [
                         "21f3fe07.9102e2"
                     ]
                 ]
             },
             {
                 "id": "7acd75d2.b229ac",
                 "type": "inject",
                 "z": "6e170384.60c96c",
                 "name": "",
                 "props": [
                     {
                         "p": "payload"
                     },
                     {
                         "p": "topic",
                         "vt": "str"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "timer",
                 "payload": "{\"seconds\":5}",
                 "payloadType": "json",
                 "x": 1070,
                 "y": 1760,
                 "wires": [
                     [
                         "f057bad5.22c0c8"
                     ]
                 ]
             },
             {
                 "id": "6ef0f333.4dd95c",
                 "type": "inject",
                 "z": "6e170384.60c96c",
                 "name": "timer: {\"hours\":2,\"minutes\":47,\"seconds\":28}",
                 "props": [
                     {
                         "p": "payload"
                     },
                     {
                         "p": "topic",
                         "vt": "str"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "timer",
                 "payload": "{\"hours\":2,\"minutes\":47,\"seconds\":28}",
                 "payloadType": "json",
                 "x": 990,
                 "y": 1680,
                 "wires": [
                     [
                         "f057bad5.22c0c8"
                     ]
                 ]
             },
             {
                 "id": "6c51e401.1c82bc",
                 "type": "inject",
                 "z": "6e170384.60c96c",
                 "name": "timer: {\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                 "props": [
                     {
                         "p": "payload"
                     },
                     {
                         "p": "topic",
                         "vt": "str"
                     }
                 ],
                 "repeat": "",
                 "crontab": "",
                 "once": false,
                 "onceDelay": 0.1,
                 "topic": "timer",
                 "payload": "{\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                 "payloadType": "json",
                 "x": 970,
                 "y": 1640,
                 "wires": [
                     [
                         "f057bad5.22c0c8"
                     ]
                 ]
             }
          ]
          

          FAZIT und ENDE: ;)
          Ich finde die moment.js Bibliothek und wie man sie in NodeRed mit Standardmitteln nutzen kann, wirklich sehr mächtig und es erleichtert einem das Hantieren mit Datums - und Uhrzeitformaten. Wie gesagt was JSONATA Programmierung oder manchmal diese Abkürzungs Syntax bedeutet, das überfordert mich leicht.

          Deshalb mal ganz allgemein: Wenn jemand Fragen hat gerne. Wenn mir jemand erklären kann, wie ich unter JSONATA an das Duration Objekt der moment.js Library komme - gerne.

          Ich hoffe es ist OK, wenn ich hier mal das was ich herausgefunden habe, aufschreibe und hoffe auch, dass es dem einen oder anderen bei seinen eigenen Projekten hilft.

          R Offline
          R Offline
          rewenode
          schrieb am zuletzt editiert von
          #7

          @mickym Saubere Arbeit !! Danke!

          1 Antwort Letzte Antwort
          0
          • mickymM mickym

            5. Abschluss

            So zum Abschluss habe ich mal meine neuen Kenntnisse dazu genutzt, um mit den einfachen Boardmitteln einen Timer zu erstellen.

            Einen der nicht geschwätzig ist. Wie gesagt, dass schöne an der Bibliothek ist dass man Objekte mit beliebigen Einheiten dazu addieren kann.

            Hier der Flow:

            429df954-1b1c-4dd4-9c83-d1be0831cf9b-image.png

            Hier mal der 9 Minuten und 28 Sekunden Timer Ausgabe in lesbarer aber nicht geschwätziger Form:
            Die Einheiten werden auch richtig auf und abgerundet. Wenn also in 7 Minuten ausgegeben wird, dann befindet sich er Timer zwischen 7:29 und 6:30 Minuten.

            3d38a592-8c0d-4b83-b447-64a30bb930ee-image.png

            und hier die geschwätzige Ausgabe mittels Angabe von verbleibenden Minuten und Sekunden.

            78f50370-b24a-4122-8ef0-37be86d1ac32-image.png

            Das Ende der Ausgabe ist noch unschön und kann man sicher anders lösen - aber das kann ja jeder für sich mal machen.

            Hier noch den Timerflow zum Import:

            [
               {
                   "id": "1ebefb6.e95e305",
                   "type": "inject",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "props": [
                       {
                           "p": "payload"
                       },
                       {
                           "p": "topic",
                           "vt": "str"
                       }
                   ],
                   "repeat": "",
                   "crontab": "",
                   "once": false,
                   "onceDelay": 0.1,
                   "topic": "timer",
                   "payload": "{\"minutes\":9,\"seconds\":28}",
                   "payloadType": "json",
                   "x": 1030,
                   "y": 1720,
                   "wires": [
                       [
                           "f057bad5.22c0c8"
                       ]
                   ]
               },
               {
                   "id": "f057bad5.22c0c8",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "Timer läuft ab",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "(\t    $x := payload;\t    $moment().add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1360,
                   "y": 1700,
                   "wires": [
                       [
                           "d539534f.ccfa8"
                       ]
                   ],
                   "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
               },
               {
                   "id": "d539534f.ccfa8",
                   "type": "trigger",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "op1": "",
                   "op2": "0",
                   "op1type": "pay",
                   "op2type": "str",
                   "duration": "-1",
                   "extend": false,
                   "overrideDelay": false,
                   "units": "s",
                   "reset": "",
                   "bytopic": "all",
                   "topic": "topic",
                   "outputs": 1,
                   "x": 1580,
                   "y": 1700,
                   "wires": [
                       [
                           "173f530c.7cf97d",
                           "ffe4b703.5c7ac8",
                           "5ad21dfe.76dc14"
                       ]
                   ]
               },
               {
                   "id": "ba662ea7.2a6e3",
                   "type": "inject",
                   "z": "6e170384.60c96c",
                   "name": "reset",
                   "props": [
                       {
                           "p": "reset",
                           "v": "true",
                           "vt": "bool"
                       }
                   ],
                   "repeat": "",
                   "crontab": "",
                   "once": false,
                   "onceDelay": 0.1,
                   "topic": "",
                   "x": 1350,
                   "y": 1760,
                   "wires": [
                       [
                           "d539534f.ccfa8"
                       ]
                   ]
               },
               {
                   "id": "173f530c.7cf97d",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1810,
                   "y": 1700,
                   "wires": [
                       [
                           "16b62a7a.c7e9c6"
                       ]
                   ]
               },
               {
                   "id": "16b62a7a.c7e9c6",
                   "type": "rbe",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "func": "rbe",
                   "gap": "",
                   "start": "",
                   "inout": "out",
                   "septopics": true,
                   "property": "payload",
                   "x": 1570,
                   "y": 1620,
                   "wires": [
                       [
                           "3aa094bf.4cd0bc"
                       ]
                   ]
               },
               {
                   "id": "5414e8d9.006ec8",
                   "type": "debug",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "active": false,
                   "tosidebar": true,
                   "console": false,
                   "tostatus": false,
                   "complete": "false",
                   "statusVal": "",
                   "statusType": "auto",
                   "x": 1970,
                   "y": 1560,
                   "wires": []
               },
               {
                   "id": "9e313ea9.6c67e",
                   "type": "comment",
                   "z": "6e170384.60c96c",
                   "name": "Timer ausgabe",
                   "info": "",
                   "x": 800,
                   "y": 1500,
                   "wires": []
               },
               {
                   "id": "ffe4b703.5c7ac8",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').isSameOrAfter($moment())",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1810,
                   "y": 1760,
                   "wires": [
                       [
                           "9cb1684c.9731a8"
                       ]
                   ]
               },
               {
                   "id": "9cb1684c.9731a8",
                   "type": "switch",
                   "z": "6e170384.60c96c",
                   "name": "Timer abgelaufen?",
                   "property": "payload",
                   "propertyType": "msg",
                   "rules": [
                       {
                           "t": "false"
                       }
                   ],
                   "checkall": "true",
                   "repair": false,
                   "outputs": 1,
                   "x": 1810,
                   "y": 1820,
                   "wires": [
                       [
                           "2a83c3b3.e36c4c"
                       ]
                   ]
               },
               {
                   "id": "2a83c3b3.e36c4c",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "Timer abgelaufen, dann reset",
                   "rules": [
                       {
                           "t": "set",
                           "p": "reset",
                           "pt": "msg",
                           "to": "true",
                           "tot": "bool"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1520,
                   "y": 1880,
                   "wires": [
                       [
                           "d539534f.ccfa8"
                       ]
                   ]
               },
               {
                   "id": "3aa094bf.4cd0bc",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "rules": [
                       {
                           "t": "change",
                           "p": "payload",
                           "pt": "msg",
                           "from": "vor ein paar Sekunden",
                           "fromt": "str",
                           "to": "Timer wurde beendet",
                           "tot": "str"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1800,
                   "y": 1620,
                   "wires": [
                       [
                           "5414e8d9.006ec8"
                       ]
                   ]
               },
               {
                   "id": "5ad21dfe.76dc14",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                   "rules": [
                       {
                           "t": "set",
                           "p": "timeA",
                           "pt": "msg",
                           "to": "$moment().format('DD.MM.YYYY HH:mm:ss')",
                           "tot": "jsonata"
                       },
                       {
                           "t": "set",
                           "p": "timeB",
                           "pt": "msg",
                           "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                           "tot": "jsonata"
                       },
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1420,
                   "y": 1500,
                   "wires": [
                       [
                           "6c4aa2f5.a318ac"
                       ]
                   ],
                   "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
               },
               {
                   "id": "21f3fe07.9102e2",
                   "type": "debug",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "active": true,
                   "tosidebar": true,
                   "console": false,
                   "tostatus": false,
                   "complete": "false",
                   "statusVal": "",
                   "statusType": "auto",
                   "x": 1950,
                   "y": 1500,
                   "wires": []
               },
               {
                   "id": "6c4aa2f5.a318ac",
                   "type": "change",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "rules": [
                       {
                           "t": "set",
                           "p": "payload",
                           "pt": "msg",
                           "to": "(\t    $str := payload.days > 0 ? payload.days & ' Tage(n) ' : '';\t    $str := payload.hours > 0 ? $str & payload.hours & ' Stunde(n) ' : '';\t    $str := payload.minutes > 0 ? $str & payload.minutes & ' Minute(n) ' : '';\t    $str := $str & payload.seconds & ' Sekunde(n)';\t    $str := ($str = '0 Sekunde(n)' or str = '-1 Sekunde(n)') ? 'Timer beendet' : $str;\t\t\t)",
                           "tot": "jsonata"
                       }
                   ],
                   "action": "",
                   "property": "",
                   "from": "",
                   "to": "",
                   "reg": false,
                   "x": 1750,
                   "y": 1500,
                   "wires": [
                       [
                           "21f3fe07.9102e2"
                       ]
                   ]
               },
               {
                   "id": "7acd75d2.b229ac",
                   "type": "inject",
                   "z": "6e170384.60c96c",
                   "name": "",
                   "props": [
                       {
                           "p": "payload"
                       },
                       {
                           "p": "topic",
                           "vt": "str"
                       }
                   ],
                   "repeat": "",
                   "crontab": "",
                   "once": false,
                   "onceDelay": 0.1,
                   "topic": "timer",
                   "payload": "{\"seconds\":5}",
                   "payloadType": "json",
                   "x": 1070,
                   "y": 1760,
                   "wires": [
                       [
                           "f057bad5.22c0c8"
                       ]
                   ]
               },
               {
                   "id": "6ef0f333.4dd95c",
                   "type": "inject",
                   "z": "6e170384.60c96c",
                   "name": "timer: {\"hours\":2,\"minutes\":47,\"seconds\":28}",
                   "props": [
                       {
                           "p": "payload"
                       },
                       {
                           "p": "topic",
                           "vt": "str"
                       }
                   ],
                   "repeat": "",
                   "crontab": "",
                   "once": false,
                   "onceDelay": 0.1,
                   "topic": "timer",
                   "payload": "{\"hours\":2,\"minutes\":47,\"seconds\":28}",
                   "payloadType": "json",
                   "x": 990,
                   "y": 1680,
                   "wires": [
                       [
                           "f057bad5.22c0c8"
                       ]
                   ]
               },
               {
                   "id": "6c51e401.1c82bc",
                   "type": "inject",
                   "z": "6e170384.60c96c",
                   "name": "timer: {\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                   "props": [
                       {
                           "p": "payload"
                       },
                       {
                           "p": "topic",
                           "vt": "str"
                       }
                   ],
                   "repeat": "",
                   "crontab": "",
                   "once": false,
                   "onceDelay": 0.1,
                   "topic": "timer",
                   "payload": "{\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                   "payloadType": "json",
                   "x": 970,
                   "y": 1640,
                   "wires": [
                       [
                           "f057bad5.22c0c8"
                       ]
                   ]
               }
            ]
            

            FAZIT und ENDE: ;)
            Ich finde die moment.js Bibliothek und wie man sie in NodeRed mit Standardmitteln nutzen kann, wirklich sehr mächtig und es erleichtert einem das Hantieren mit Datums - und Uhrzeitformaten. Wie gesagt was JSONATA Programmierung oder manchmal diese Abkürzungs Syntax bedeutet, das überfordert mich leicht.

            Deshalb mal ganz allgemein: Wenn jemand Fragen hat gerne. Wenn mir jemand erklären kann, wie ich unter JSONATA an das Duration Objekt der moment.js Library komme - gerne.

            Ich hoffe es ist OK, wenn ich hier mal das was ich herausgefunden habe, aufschreibe und hoffe auch, dass es dem einen oder anderen bei seinen eigenen Projekten hilft.

            F Offline
            F Offline
            frankyboy73
            schrieb am zuletzt editiert von
            #8

            @mickym Ja, tolle Arbeit und super erklärt. :+1:

            Schöne Grüße Frank

            1 Antwort Letzte Antwort
            0
            • mickymM mickym

              5. Abschluss

              So zum Abschluss habe ich mal meine neuen Kenntnisse dazu genutzt, um mit den einfachen Boardmitteln einen Timer zu erstellen.

              Einen der nicht geschwätzig ist. Wie gesagt, dass schöne an der Bibliothek ist dass man Objekte mit beliebigen Einheiten dazu addieren kann.

              Hier der Flow:

              429df954-1b1c-4dd4-9c83-d1be0831cf9b-image.png

              Hier mal der 9 Minuten und 28 Sekunden Timer Ausgabe in lesbarer aber nicht geschwätziger Form:
              Die Einheiten werden auch richtig auf und abgerundet. Wenn also in 7 Minuten ausgegeben wird, dann befindet sich er Timer zwischen 7:29 und 6:30 Minuten.

              3d38a592-8c0d-4b83-b447-64a30bb930ee-image.png

              und hier die geschwätzige Ausgabe mittels Angabe von verbleibenden Minuten und Sekunden.

              78f50370-b24a-4122-8ef0-37be86d1ac32-image.png

              Das Ende der Ausgabe ist noch unschön und kann man sicher anders lösen - aber das kann ja jeder für sich mal machen.

              Hier noch den Timerflow zum Import:

              [
                 {
                     "id": "1ebefb6.e95e305",
                     "type": "inject",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "props": [
                         {
                             "p": "payload"
                         },
                         {
                             "p": "topic",
                             "vt": "str"
                         }
                     ],
                     "repeat": "",
                     "crontab": "",
                     "once": false,
                     "onceDelay": 0.1,
                     "topic": "timer",
                     "payload": "{\"minutes\":9,\"seconds\":28}",
                     "payloadType": "json",
                     "x": 1030,
                     "y": 1720,
                     "wires": [
                         [
                             "f057bad5.22c0c8"
                         ]
                     ]
                 },
                 {
                     "id": "f057bad5.22c0c8",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "Timer läuft ab",
                     "rules": [
                         {
                             "t": "set",
                             "p": "payload",
                             "pt": "msg",
                             "to": "(\t    $x := payload;\t    $moment().add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                             "tot": "jsonata"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1360,
                     "y": 1700,
                     "wires": [
                         [
                             "d539534f.ccfa8"
                         ]
                     ],
                     "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                 },
                 {
                     "id": "d539534f.ccfa8",
                     "type": "trigger",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "op1": "",
                     "op2": "0",
                     "op1type": "pay",
                     "op2type": "str",
                     "duration": "-1",
                     "extend": false,
                     "overrideDelay": false,
                     "units": "s",
                     "reset": "",
                     "bytopic": "all",
                     "topic": "topic",
                     "outputs": 1,
                     "x": 1580,
                     "y": 1700,
                     "wires": [
                         [
                             "173f530c.7cf97d",
                             "ffe4b703.5c7ac8",
                             "5ad21dfe.76dc14"
                         ]
                     ]
                 },
                 {
                     "id": "ba662ea7.2a6e3",
                     "type": "inject",
                     "z": "6e170384.60c96c",
                     "name": "reset",
                     "props": [
                         {
                             "p": "reset",
                             "v": "true",
                             "vt": "bool"
                         }
                     ],
                     "repeat": "",
                     "crontab": "",
                     "once": false,
                     "onceDelay": 0.1,
                     "topic": "",
                     "x": 1350,
                     "y": 1760,
                     "wires": [
                         [
                             "d539534f.ccfa8"
                         ]
                     ]
                 },
                 {
                     "id": "173f530c.7cf97d",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "rules": [
                         {
                             "t": "set",
                             "p": "payload",
                             "pt": "msg",
                             "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()",
                             "tot": "jsonata"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1810,
                     "y": 1700,
                     "wires": [
                         [
                             "16b62a7a.c7e9c6"
                         ]
                     ]
                 },
                 {
                     "id": "16b62a7a.c7e9c6",
                     "type": "rbe",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "func": "rbe",
                     "gap": "",
                     "start": "",
                     "inout": "out",
                     "septopics": true,
                     "property": "payload",
                     "x": 1570,
                     "y": 1620,
                     "wires": [
                         [
                             "3aa094bf.4cd0bc"
                         ]
                     ]
                 },
                 {
                     "id": "5414e8d9.006ec8",
                     "type": "debug",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "active": false,
                     "tosidebar": true,
                     "console": false,
                     "tostatus": false,
                     "complete": "false",
                     "statusVal": "",
                     "statusType": "auto",
                     "x": 1970,
                     "y": 1560,
                     "wires": []
                 },
                 {
                     "id": "9e313ea9.6c67e",
                     "type": "comment",
                     "z": "6e170384.60c96c",
                     "name": "Timer ausgabe",
                     "info": "",
                     "x": 800,
                     "y": 1500,
                     "wires": []
                 },
                 {
                     "id": "ffe4b703.5c7ac8",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "rules": [
                         {
                             "t": "set",
                             "p": "payload",
                             "pt": "msg",
                             "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').isSameOrAfter($moment())",
                             "tot": "jsonata"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1810,
                     "y": 1760,
                     "wires": [
                         [
                             "9cb1684c.9731a8"
                         ]
                     ]
                 },
                 {
                     "id": "9cb1684c.9731a8",
                     "type": "switch",
                     "z": "6e170384.60c96c",
                     "name": "Timer abgelaufen?",
                     "property": "payload",
                     "propertyType": "msg",
                     "rules": [
                         {
                             "t": "false"
                         }
                     ],
                     "checkall": "true",
                     "repair": false,
                     "outputs": 1,
                     "x": 1810,
                     "y": 1820,
                     "wires": [
                         [
                             "2a83c3b3.e36c4c"
                         ]
                     ]
                 },
                 {
                     "id": "2a83c3b3.e36c4c",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "Timer abgelaufen, dann reset",
                     "rules": [
                         {
                             "t": "set",
                             "p": "reset",
                             "pt": "msg",
                             "to": "true",
                             "tot": "bool"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1520,
                     "y": 1880,
                     "wires": [
                         [
                             "d539534f.ccfa8"
                         ]
                     ]
                 },
                 {
                     "id": "3aa094bf.4cd0bc",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "rules": [
                         {
                             "t": "change",
                             "p": "payload",
                             "pt": "msg",
                             "from": "vor ein paar Sekunden",
                             "fromt": "str",
                             "to": "Timer wurde beendet",
                             "tot": "str"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1800,
                     "y": 1620,
                     "wires": [
                         [
                             "5414e8d9.006ec8"
                         ]
                     ]
                 },
                 {
                     "id": "5ad21dfe.76dc14",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                     "rules": [
                         {
                             "t": "set",
                             "p": "timeA",
                             "pt": "msg",
                             "to": "$moment().format('DD.MM.YYYY HH:mm:ss')",
                             "tot": "jsonata"
                         },
                         {
                             "t": "set",
                             "p": "timeB",
                             "pt": "msg",
                             "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                             "tot": "jsonata"
                         },
                         {
                             "t": "set",
                             "p": "payload",
                             "pt": "msg",
                             "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                             "tot": "jsonata"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1420,
                     "y": 1500,
                     "wires": [
                         [
                             "6c4aa2f5.a318ac"
                         ]
                     ],
                     "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                 },
                 {
                     "id": "21f3fe07.9102e2",
                     "type": "debug",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "active": true,
                     "tosidebar": true,
                     "console": false,
                     "tostatus": false,
                     "complete": "false",
                     "statusVal": "",
                     "statusType": "auto",
                     "x": 1950,
                     "y": 1500,
                     "wires": []
                 },
                 {
                     "id": "6c4aa2f5.a318ac",
                     "type": "change",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "rules": [
                         {
                             "t": "set",
                             "p": "payload",
                             "pt": "msg",
                             "to": "(\t    $str := payload.days > 0 ? payload.days & ' Tage(n) ' : '';\t    $str := payload.hours > 0 ? $str & payload.hours & ' Stunde(n) ' : '';\t    $str := payload.minutes > 0 ? $str & payload.minutes & ' Minute(n) ' : '';\t    $str := $str & payload.seconds & ' Sekunde(n)';\t    $str := ($str = '0 Sekunde(n)' or str = '-1 Sekunde(n)') ? 'Timer beendet' : $str;\t\t\t)",
                             "tot": "jsonata"
                         }
                     ],
                     "action": "",
                     "property": "",
                     "from": "",
                     "to": "",
                     "reg": false,
                     "x": 1750,
                     "y": 1500,
                     "wires": [
                         [
                             "21f3fe07.9102e2"
                         ]
                     ]
                 },
                 {
                     "id": "7acd75d2.b229ac",
                     "type": "inject",
                     "z": "6e170384.60c96c",
                     "name": "",
                     "props": [
                         {
                             "p": "payload"
                         },
                         {
                             "p": "topic",
                             "vt": "str"
                         }
                     ],
                     "repeat": "",
                     "crontab": "",
                     "once": false,
                     "onceDelay": 0.1,
                     "topic": "timer",
                     "payload": "{\"seconds\":5}",
                     "payloadType": "json",
                     "x": 1070,
                     "y": 1760,
                     "wires": [
                         [
                             "f057bad5.22c0c8"
                         ]
                     ]
                 },
                 {
                     "id": "6ef0f333.4dd95c",
                     "type": "inject",
                     "z": "6e170384.60c96c",
                     "name": "timer: {\"hours\":2,\"minutes\":47,\"seconds\":28}",
                     "props": [
                         {
                             "p": "payload"
                         },
                         {
                             "p": "topic",
                             "vt": "str"
                         }
                     ],
                     "repeat": "",
                     "crontab": "",
                     "once": false,
                     "onceDelay": 0.1,
                     "topic": "timer",
                     "payload": "{\"hours\":2,\"minutes\":47,\"seconds\":28}",
                     "payloadType": "json",
                     "x": 990,
                     "y": 1680,
                     "wires": [
                         [
                             "f057bad5.22c0c8"
                         ]
                     ]
                 },
                 {
                     "id": "6c51e401.1c82bc",
                     "type": "inject",
                     "z": "6e170384.60c96c",
                     "name": "timer: {\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                     "props": [
                         {
                             "p": "payload"
                         },
                         {
                             "p": "topic",
                             "vt": "str"
                         }
                     ],
                     "repeat": "",
                     "crontab": "",
                     "once": false,
                     "onceDelay": 0.1,
                     "topic": "timer",
                     "payload": "{\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                     "payloadType": "json",
                     "x": 970,
                     "y": 1640,
                     "wires": [
                         [
                             "f057bad5.22c0c8"
                         ]
                     ]
                 }
              ]
              

              FAZIT und ENDE: ;)
              Ich finde die moment.js Bibliothek und wie man sie in NodeRed mit Standardmitteln nutzen kann, wirklich sehr mächtig und es erleichtert einem das Hantieren mit Datums - und Uhrzeitformaten. Wie gesagt was JSONATA Programmierung oder manchmal diese Abkürzungs Syntax bedeutet, das überfordert mich leicht.

              Deshalb mal ganz allgemein: Wenn jemand Fragen hat gerne. Wenn mir jemand erklären kann, wie ich unter JSONATA an das Duration Objekt der moment.js Library komme - gerne.

              Ich hoffe es ist OK, wenn ich hier mal das was ich herausgefunden habe, aufschreibe und hoffe auch, dass es dem einen oder anderen bei seinen eigenen Projekten hilft.

              G Offline
              G Offline
              Garf
              schrieb am zuletzt editiert von
              #9

              @mickym
              1A. Mega, was für eine Herkulesarbeit. Danke dafür.

              1 Antwort Letzte Antwort
              0
              • mickymM mickym

                5. Abschluss

                So zum Abschluss habe ich mal meine neuen Kenntnisse dazu genutzt, um mit den einfachen Boardmitteln einen Timer zu erstellen.

                Einen der nicht geschwätzig ist. Wie gesagt, dass schöne an der Bibliothek ist dass man Objekte mit beliebigen Einheiten dazu addieren kann.

                Hier der Flow:

                429df954-1b1c-4dd4-9c83-d1be0831cf9b-image.png

                Hier mal der 9 Minuten und 28 Sekunden Timer Ausgabe in lesbarer aber nicht geschwätziger Form:
                Die Einheiten werden auch richtig auf und abgerundet. Wenn also in 7 Minuten ausgegeben wird, dann befindet sich er Timer zwischen 7:29 und 6:30 Minuten.

                3d38a592-8c0d-4b83-b447-64a30bb930ee-image.png

                und hier die geschwätzige Ausgabe mittels Angabe von verbleibenden Minuten und Sekunden.

                78f50370-b24a-4122-8ef0-37be86d1ac32-image.png

                Das Ende der Ausgabe ist noch unschön und kann man sicher anders lösen - aber das kann ja jeder für sich mal machen.

                Hier noch den Timerflow zum Import:

                [
                   {
                       "id": "1ebefb6.e95e305",
                       "type": "inject",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "props": [
                           {
                               "p": "payload"
                           },
                           {
                               "p": "topic",
                               "vt": "str"
                           }
                       ],
                       "repeat": "",
                       "crontab": "",
                       "once": false,
                       "onceDelay": 0.1,
                       "topic": "timer",
                       "payload": "{\"minutes\":9,\"seconds\":28}",
                       "payloadType": "json",
                       "x": 1030,
                       "y": 1720,
                       "wires": [
                           [
                               "f057bad5.22c0c8"
                           ]
                       ]
                   },
                   {
                       "id": "f057bad5.22c0c8",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "Timer läuft ab",
                       "rules": [
                           {
                               "t": "set",
                               "p": "payload",
                               "pt": "msg",
                               "to": "(\t    $x := payload;\t    $moment().add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                               "tot": "jsonata"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1360,
                       "y": 1700,
                       "wires": [
                           [
                               "d539534f.ccfa8"
                           ]
                       ],
                       "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                   },
                   {
                       "id": "d539534f.ccfa8",
                       "type": "trigger",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "op1": "",
                       "op2": "0",
                       "op1type": "pay",
                       "op2type": "str",
                       "duration": "-1",
                       "extend": false,
                       "overrideDelay": false,
                       "units": "s",
                       "reset": "",
                       "bytopic": "all",
                       "topic": "topic",
                       "outputs": 1,
                       "x": 1580,
                       "y": 1700,
                       "wires": [
                           [
                               "173f530c.7cf97d",
                               "ffe4b703.5c7ac8",
                               "5ad21dfe.76dc14"
                           ]
                       ]
                   },
                   {
                       "id": "ba662ea7.2a6e3",
                       "type": "inject",
                       "z": "6e170384.60c96c",
                       "name": "reset",
                       "props": [
                           {
                               "p": "reset",
                               "v": "true",
                               "vt": "bool"
                           }
                       ],
                       "repeat": "",
                       "crontab": "",
                       "once": false,
                       "onceDelay": 0.1,
                       "topic": "",
                       "x": 1350,
                       "y": 1760,
                       "wires": [
                           [
                               "d539534f.ccfa8"
                           ]
                       ]
                   },
                   {
                       "id": "173f530c.7cf97d",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "rules": [
                           {
                               "t": "set",
                               "p": "payload",
                               "pt": "msg",
                               "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').fromNow()",
                               "tot": "jsonata"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1810,
                       "y": 1700,
                       "wires": [
                           [
                               "16b62a7a.c7e9c6"
                           ]
                       ]
                   },
                   {
                       "id": "16b62a7a.c7e9c6",
                       "type": "rbe",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "func": "rbe",
                       "gap": "",
                       "start": "",
                       "inout": "out",
                       "septopics": true,
                       "property": "payload",
                       "x": 1570,
                       "y": 1620,
                       "wires": [
                           [
                               "3aa094bf.4cd0bc"
                           ]
                       ]
                   },
                   {
                       "id": "5414e8d9.006ec8",
                       "type": "debug",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "active": false,
                       "tosidebar": true,
                       "console": false,
                       "tostatus": false,
                       "complete": "false",
                       "statusVal": "",
                       "statusType": "auto",
                       "x": 1970,
                       "y": 1560,
                       "wires": []
                   },
                   {
                       "id": "9e313ea9.6c67e",
                       "type": "comment",
                       "z": "6e170384.60c96c",
                       "name": "Timer ausgabe",
                       "info": "",
                       "x": 800,
                       "y": 1500,
                       "wires": []
                   },
                   {
                       "id": "ffe4b703.5c7ac8",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "rules": [
                           {
                               "t": "set",
                               "p": "payload",
                               "pt": "msg",
                               "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').isSameOrAfter($moment())",
                               "tot": "jsonata"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1810,
                       "y": 1760,
                       "wires": [
                           [
                               "9cb1684c.9731a8"
                           ]
                       ]
                   },
                   {
                       "id": "9cb1684c.9731a8",
                       "type": "switch",
                       "z": "6e170384.60c96c",
                       "name": "Timer abgelaufen?",
                       "property": "payload",
                       "propertyType": "msg",
                       "rules": [
                           {
                               "t": "false"
                           }
                       ],
                       "checkall": "true",
                       "repair": false,
                       "outputs": 1,
                       "x": 1810,
                       "y": 1820,
                       "wires": [
                           [
                               "2a83c3b3.e36c4c"
                           ]
                       ]
                   },
                   {
                       "id": "2a83c3b3.e36c4c",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "Timer abgelaufen, dann reset",
                       "rules": [
                           {
                               "t": "set",
                               "p": "reset",
                               "pt": "msg",
                               "to": "true",
                               "tot": "bool"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1520,
                       "y": 1880,
                       "wires": [
                           [
                               "d539534f.ccfa8"
                           ]
                       ]
                   },
                   {
                       "id": "3aa094bf.4cd0bc",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "rules": [
                           {
                               "t": "change",
                               "p": "payload",
                               "pt": "msg",
                               "from": "vor ein paar Sekunden",
                               "fromt": "str",
                               "to": "Timer wurde beendet",
                               "tot": "str"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1800,
                       "y": 1620,
                       "wires": [
                           [
                               "5414e8d9.006ec8"
                           ]
                       ]
                   },
                   {
                       "id": "5ad21dfe.76dc14",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                       "rules": [
                           {
                               "t": "set",
                               "p": "timeA",
                               "pt": "msg",
                               "to": "$moment().format('DD.MM.YYYY HH:mm:ss')",
                               "tot": "jsonata"
                           },
                           {
                               "t": "set",
                               "p": "timeB",
                               "pt": "msg",
                               "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                               "tot": "jsonata"
                           },
                           {
                               "t": "set",
                               "p": "payload",
                               "pt": "msg",
                               "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                               "tot": "jsonata"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1420,
                       "y": 1500,
                       "wires": [
                           [
                               "6c4aa2f5.a318ac"
                           ]
                       ],
                       "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                   },
                   {
                       "id": "21f3fe07.9102e2",
                       "type": "debug",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "active": true,
                       "tosidebar": true,
                       "console": false,
                       "tostatus": false,
                       "complete": "false",
                       "statusVal": "",
                       "statusType": "auto",
                       "x": 1950,
                       "y": 1500,
                       "wires": []
                   },
                   {
                       "id": "6c4aa2f5.a318ac",
                       "type": "change",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "rules": [
                           {
                               "t": "set",
                               "p": "payload",
                               "pt": "msg",
                               "to": "(\t    $str := payload.days > 0 ? payload.days & ' Tage(n) ' : '';\t    $str := payload.hours > 0 ? $str & payload.hours & ' Stunde(n) ' : '';\t    $str := payload.minutes > 0 ? $str & payload.minutes & ' Minute(n) ' : '';\t    $str := $str & payload.seconds & ' Sekunde(n)';\t    $str := ($str = '0 Sekunde(n)' or str = '-1 Sekunde(n)') ? 'Timer beendet' : $str;\t\t\t)",
                               "tot": "jsonata"
                           }
                       ],
                       "action": "",
                       "property": "",
                       "from": "",
                       "to": "",
                       "reg": false,
                       "x": 1750,
                       "y": 1500,
                       "wires": [
                           [
                               "21f3fe07.9102e2"
                           ]
                       ]
                   },
                   {
                       "id": "7acd75d2.b229ac",
                       "type": "inject",
                       "z": "6e170384.60c96c",
                       "name": "",
                       "props": [
                           {
                               "p": "payload"
                           },
                           {
                               "p": "topic",
                               "vt": "str"
                           }
                       ],
                       "repeat": "",
                       "crontab": "",
                       "once": false,
                       "onceDelay": 0.1,
                       "topic": "timer",
                       "payload": "{\"seconds\":5}",
                       "payloadType": "json",
                       "x": 1070,
                       "y": 1760,
                       "wires": [
                           [
                               "f057bad5.22c0c8"
                           ]
                       ]
                   },
                   {
                       "id": "6ef0f333.4dd95c",
                       "type": "inject",
                       "z": "6e170384.60c96c",
                       "name": "timer: {\"hours\":2,\"minutes\":47,\"seconds\":28}",
                       "props": [
                           {
                               "p": "payload"
                           },
                           {
                               "p": "topic",
                               "vt": "str"
                           }
                       ],
                       "repeat": "",
                       "crontab": "",
                       "once": false,
                       "onceDelay": 0.1,
                       "topic": "timer",
                       "payload": "{\"hours\":2,\"minutes\":47,\"seconds\":28}",
                       "payloadType": "json",
                       "x": 990,
                       "y": 1680,
                       "wires": [
                           [
                               "f057bad5.22c0c8"
                           ]
                       ]
                   },
                   {
                       "id": "6c51e401.1c82bc",
                       "type": "inject",
                       "z": "6e170384.60c96c",
                       "name": "timer: {\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                       "props": [
                           {
                               "p": "payload"
                           },
                           {
                               "p": "topic",
                               "vt": "str"
                           }
                       ],
                       "repeat": "",
                       "crontab": "",
                       "once": false,
                       "onceDelay": 0.1,
                       "topic": "timer",
                       "payload": "{\"days\":3,\"hours\":1,\"minutes\":47,\"seconds\":28}",
                       "payloadType": "json",
                       "x": 970,
                       "y": 1640,
                       "wires": [
                           [
                               "f057bad5.22c0c8"
                           ]
                       ]
                   }
                ]
                

                FAZIT und ENDE: ;)
                Ich finde die moment.js Bibliothek und wie man sie in NodeRed mit Standardmitteln nutzen kann, wirklich sehr mächtig und es erleichtert einem das Hantieren mit Datums - und Uhrzeitformaten. Wie gesagt was JSONATA Programmierung oder manchmal diese Abkürzungs Syntax bedeutet, das überfordert mich leicht.

                Deshalb mal ganz allgemein: Wenn jemand Fragen hat gerne. Wenn mir jemand erklären kann, wie ich unter JSONATA an das Duration Objekt der moment.js Library komme - gerne.

                Ich hoffe es ist OK, wenn ich hier mal das was ich herausgefunden habe, aufschreibe und hoffe auch, dass es dem einen oder anderen bei seinen eigenen Projekten hilft.

                R Offline
                R Offline
                rewenode
                schrieb am zuletzt editiert von rewenode
                #10

                Hab den Post weiter unten für iobroker und node-red aktualisiert und den alten gelöscht.

                mickymM 1 Antwort Letzte Antwort
                0
                • R rewenode

                  Hab den Post weiter unten für iobroker und node-red aktualisiert und den alten gelöscht.

                  mickymM Offline
                  mickymM Offline
                  mickym
                  Most Active
                  schrieb am zuletzt editiert von mickym
                  #11

                  @rewenode Ja das wollte ich eigentlich verhindern - mit der externen Einbindung - da musst Du wieder an der settings.js rumbasteln, dass Du externe Bibliotheken verfügbar machst.

                  Konnte Deinen Flow auch nicht einbinden - da irgendein parse Error - aber Dank Deiner Erklärung konnte ich es auch nachvollziehen - allerdings auch nur in der Standalone Version:

                  bb64d421-f136-4521-a8f8-d82c43f35da3-image.png

                  In der function Node muss man halt die Bibliothek noch bekannt machen:

                  af2b6a1e-fe05-4b31-b7c5-4cad429ed9e8-image.png

                  Interessant ist dass der duration strings nur bis zu Stunden auflöst - also 195 Stunden.

                  Habs mal mit 5 Jahre + 30 Tagen + 3 Stunden + 47 Minuten +28 Sekunden - ausprobiert. :grin: Dann kommen auch nur 44547 Stunden raus. ;) - Damit ist der Mehrwert nun nicht so hoch - als dass sich der Streß mit Einbindung externer Bibliotheken lohnt.

                  16220424-1800-4717-9574-1a03385bf557-image.png

                  Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                  1 Antwort Letzte Antwort
                  0
                  • R Offline
                    R Offline
                    rewenode
                    schrieb am zuletzt editiert von rewenode
                    #12

                    @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                    @rewenode Ja das wollte ich eigentlich verhindern - mit der externen Einbindung - da musst Du wieder an der settings.js rumbasteln, dass Du externe Bibliotheken verfügbar machst.
                    Konnte Deinen Flow auch nicht einbinden - da irgendein parse Error - aber Dank Deiner Erklärung konnte ich es auch nachvollziehen - allerdings auch nur in der Standalone Version:

                    Ja, sorry. hatte es in einer stand alone version getestet.
                    Hier nochmal für die ioBroker Version.
                    Da gehts dann ganz einfach, wenn man einmal die moment.js eingebunden hat. Ein function-node ist dann nicht mehr nötig.

                    1. binde die moment.js über die settings.js ein.
                      Die befindet sich in
                    /opt/iobroker/node_modules/iobroker.node-red/settings.js
                    

                    Dort muss di function functionGlobalContext um den Eintrag

                    moment:require("moment")
                    

                    erweitert werden.

                    Beispiel aus meiner settings.ja

                    functionGlobalContext: {
                            moment:require("moment")
                            //'%%functionGlobalContext%%'
                            // os:require('os'),
                            // jfive:require("johnny-five"),
                            // j5board:require("johnny-five").Board({repl:false})
                        },
                    

                    Dann die node-red instanz neu starten.
                    Das wars.

                    moment.duration kann in JSONata immer mit

                    $globalContext('moment.duration')
                    

                    verwendet werden.

                    2021-12-09_21-37-51.png

                    moment steht dann natürlich auch in function-nodes zur Verfügung.

                    [
                        {
                            "id": "5d6fc95c.e73438",
                            "type": "tab",
                            "label": "Flow 3",
                            "disabled": false,
                            "info": ""
                        },
                        {
                            "id": "c38cc5bf.7f7f38",
                            "type": "inject",
                            "z": "5d6fc95c.e73438",
                            "name": "jetzt + 8 Tagen + 3 Stunden + 47 Minuten +28 Sekunden",
                            "props": [
                                {
                                    "p": "payload"
                                },
                                {
                                    "p": "x",
                                    "v": "{\"days\":8,\"hours\":3,\"minutes\":47,\"seconds\":28}",
                                    "vt": "json"
                                }
                            ],
                            "repeat": "",
                            "crontab": "",
                            "once": false,
                            "onceDelay": 0.1,
                            "topic": "",
                            "payload": "",
                            "payloadType": "date",
                            "x": 250,
                            "y": 140,
                            "wires": [
                                [
                                    "f6e8d65f.929de8",
                                    "c535b75f1d3d6bb6"
                                ]
                            ]
                        },
                        {
                            "id": "f6e8d65f.929de8",
                            "type": "change",
                            "z": "5d6fc95c.e73438",
                            "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                            "rules": [
                                {
                                    "t": "set",
                                    "p": "timeA",
                                    "pt": "msg",
                                    "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                    "tot": "jsonata"
                                },
                                {
                                    "t": "set",
                                    "p": "timeB",
                                    "pt": "msg",
                                    "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                    "tot": "jsonata"
                                },
                                {
                                    "t": "delete",
                                    "p": "x",
                                    "pt": "msg"
                                },
                                {
                                    "t": "set",
                                    "p": "payload",
                                    "pt": "msg",
                                    "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                                    "tot": "jsonata"
                                }
                            ],
                            "action": "",
                            "property": "",
                            "from": "",
                            "to": "",
                            "reg": false,
                            "x": 720,
                            "y": 140,
                            "wires": [
                                [
                                    "fb984b77.f03568"
                                ]
                            ],
                            "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                        },
                        {
                            "id": "fb984b77.f03568",
                            "type": "debug",
                            "z": "5d6fc95c.e73438",
                            "name": "",
                            "active": true,
                            "tosidebar": true,
                            "console": false,
                            "tostatus": false,
                            "complete": "true",
                            "targetType": "full",
                            "statusVal": "",
                            "statusType": "auto",
                            "x": 1050,
                            "y": 140,
                            "wires": []
                        },
                        {
                            "id": "9958c57.83b6e38",
                            "type": "comment",
                            "z": "5d6fc95c.e73438",
                            "name": "Zeitvergleiche",
                            "info": "",
                            "x": 110,
                            "y": 100,
                            "wires": []
                        },
                        {
                            "id": "c535b75f1d3d6bb6",
                            "type": "change",
                            "z": "5d6fc95c.e73438",
                            "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                            "rules": [
                                {
                                    "t": "set",
                                    "p": "timeA",
                                    "pt": "msg",
                                    "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                    "tot": "jsonata"
                                },
                                {
                                    "t": "set",
                                    "p": "timeB",
                                    "pt": "msg",
                                    "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                    "tot": "jsonata"
                                },
                                {
                                    "t": "delete",
                                    "p": "x",
                                    "pt": "msg"
                                },
                                {
                                    "t": "set",
                                    "p": "payload",
                                    "pt": "msg",
                                    "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t    $globalContext('moment.duration')($b.diff($a)).humanize()\t\t)",
                                    "tot": "jsonata"
                                }
                            ],
                            "action": "",
                            "property": "",
                            "from": "",
                            "to": "",
                            "reg": false,
                            "x": 720,
                            "y": 200,
                            "wires": [
                                [
                                    "cf428b715b7fa6a5"
                                ]
                            ],
                            "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                        },
                        {
                            "id": "cf428b715b7fa6a5",
                            "type": "debug",
                            "z": "5d6fc95c.e73438",
                            "name": "",
                            "active": true,
                            "tosidebar": true,
                            "console": false,
                            "tostatus": false,
                            "complete": "true",
                            "targetType": "full",
                            "statusVal": "",
                            "statusType": "auto",
                            "x": 1050,
                            "y": 200,
                            "wires": []
                        }
                    ]
                    

                    Gruß
                    Reiner

                    mickymM 2 Antworten Letzte Antwort
                    0
                    • R rewenode

                      @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                      @rewenode Ja das wollte ich eigentlich verhindern - mit der externen Einbindung - da musst Du wieder an der settings.js rumbasteln, dass Du externe Bibliotheken verfügbar machst.
                      Konnte Deinen Flow auch nicht einbinden - da irgendein parse Error - aber Dank Deiner Erklärung konnte ich es auch nachvollziehen - allerdings auch nur in der Standalone Version:

                      Ja, sorry. hatte es in einer stand alone version getestet.
                      Hier nochmal für die ioBroker Version.
                      Da gehts dann ganz einfach, wenn man einmal die moment.js eingebunden hat. Ein function-node ist dann nicht mehr nötig.

                      1. binde die moment.js über die settings.js ein.
                        Die befindet sich in
                      /opt/iobroker/node_modules/iobroker.node-red/settings.js
                      

                      Dort muss di function functionGlobalContext um den Eintrag

                      moment:require("moment")
                      

                      erweitert werden.

                      Beispiel aus meiner settings.ja

                      functionGlobalContext: {
                              moment:require("moment")
                              //'%%functionGlobalContext%%'
                              // os:require('os'),
                              // jfive:require("johnny-five"),
                              // j5board:require("johnny-five").Board({repl:false})
                          },
                      

                      Dann die node-red instanz neu starten.
                      Das wars.

                      moment.duration kann in JSONata immer mit

                      $globalContext('moment.duration')
                      

                      verwendet werden.

                      2021-12-09_21-37-51.png

                      moment steht dann natürlich auch in function-nodes zur Verfügung.

                      [
                          {
                              "id": "5d6fc95c.e73438",
                              "type": "tab",
                              "label": "Flow 3",
                              "disabled": false,
                              "info": ""
                          },
                          {
                              "id": "c38cc5bf.7f7f38",
                              "type": "inject",
                              "z": "5d6fc95c.e73438",
                              "name": "jetzt + 8 Tagen + 3 Stunden + 47 Minuten +28 Sekunden",
                              "props": [
                                  {
                                      "p": "payload"
                                  },
                                  {
                                      "p": "x",
                                      "v": "{\"days\":8,\"hours\":3,\"minutes\":47,\"seconds\":28}",
                                      "vt": "json"
                                  }
                              ],
                              "repeat": "",
                              "crontab": "",
                              "once": false,
                              "onceDelay": 0.1,
                              "topic": "",
                              "payload": "",
                              "payloadType": "date",
                              "x": 250,
                              "y": 140,
                              "wires": [
                                  [
                                      "f6e8d65f.929de8",
                                      "c535b75f1d3d6bb6"
                                  ]
                              ]
                          },
                          {
                              "id": "f6e8d65f.929de8",
                              "type": "change",
                              "z": "5d6fc95c.e73438",
                              "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                              "rules": [
                                  {
                                      "t": "set",
                                      "p": "timeA",
                                      "pt": "msg",
                                      "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                      "tot": "jsonata"
                                  },
                                  {
                                      "t": "set",
                                      "p": "timeB",
                                      "pt": "msg",
                                      "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                      "tot": "jsonata"
                                  },
                                  {
                                      "t": "delete",
                                      "p": "x",
                                      "pt": "msg"
                                  },
                                  {
                                      "t": "set",
                                      "p": "payload",
                                      "pt": "msg",
                                      "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                                      "tot": "jsonata"
                                  }
                              ],
                              "action": "",
                              "property": "",
                              "from": "",
                              "to": "",
                              "reg": false,
                              "x": 720,
                              "y": 140,
                              "wires": [
                                  [
                                      "fb984b77.f03568"
                                  ]
                              ],
                              "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                          },
                          {
                              "id": "fb984b77.f03568",
                              "type": "debug",
                              "z": "5d6fc95c.e73438",
                              "name": "",
                              "active": true,
                              "tosidebar": true,
                              "console": false,
                              "tostatus": false,
                              "complete": "true",
                              "targetType": "full",
                              "statusVal": "",
                              "statusType": "auto",
                              "x": 1050,
                              "y": 140,
                              "wires": []
                          },
                          {
                              "id": "9958c57.83b6e38",
                              "type": "comment",
                              "z": "5d6fc95c.e73438",
                              "name": "Zeitvergleiche",
                              "info": "",
                              "x": 110,
                              "y": 100,
                              "wires": []
                          },
                          {
                              "id": "c535b75f1d3d6bb6",
                              "type": "change",
                              "z": "5d6fc95c.e73438",
                              "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                              "rules": [
                                  {
                                      "t": "set",
                                      "p": "timeA",
                                      "pt": "msg",
                                      "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                      "tot": "jsonata"
                                  },
                                  {
                                      "t": "set",
                                      "p": "timeB",
                                      "pt": "msg",
                                      "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                      "tot": "jsonata"
                                  },
                                  {
                                      "t": "delete",
                                      "p": "x",
                                      "pt": "msg"
                                  },
                                  {
                                      "t": "set",
                                      "p": "payload",
                                      "pt": "msg",
                                      "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t    $globalContext('moment.duration')($b.diff($a)).humanize()\t\t)",
                                      "tot": "jsonata"
                                  }
                              ],
                              "action": "",
                              "property": "",
                              "from": "",
                              "to": "",
                              "reg": false,
                              "x": 720,
                              "y": 200,
                              "wires": [
                                  [
                                      "cf428b715b7fa6a5"
                                  ]
                              ],
                              "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                          },
                          {
                              "id": "cf428b715b7fa6a5",
                              "type": "debug",
                              "z": "5d6fc95c.e73438",
                              "name": "",
                              "active": true,
                              "tosidebar": true,
                              "console": false,
                              "tostatus": false,
                              "complete": "true",
                              "targetType": "full",
                              "statusVal": "",
                              "statusType": "auto",
                              "x": 1050,
                              "y": 200,
                              "wires": []
                          }
                      ]
                      

                      Gruß
                      Reiner

                      mickymM Offline
                      mickymM Offline
                      mickym
                      Most Active
                      schrieb am zuletzt editiert von mickym
                      #13

                      @rewenode Vielen Dank - die Anleitung ist sicher nützlich - wobei ich deswegen nun keine externe Bibliotheken einbinden würde. Aber in meiner Standalone Konfig habe ich das Duration Teil auch mal getestet, wie Du es wieder aufgelöst bekommst und es funktioniert !!!! - wenn man keine Wochen benutzt. ;)

                      0d75ad0f-18fe-4a39-9ce0-ffdc0d045d99-image.png

                      aber dann ist das Duration doch ganz nützlich - hier mal der Code:

                      (
                          $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
                          $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
                          
                          /* $b.diff($a) */
                          $d := $globalContext('md')($b.diff($a));
                      
                          $difference := {
                              "years" : $d.years(),
                              "months":$d.months(),
                              "weeks": $d.weeks(),
                              "days": $d.days(),
                              "hours":$d.hours(),
                              "minutes":$d.minutes(),
                              "seconds": $d.seconds()
                          }; 
                      )
                      

                      Das gute ist ja dass das richtig umgerechnet wird und wirklich Schaltjahre etc. alles berücksichtig wird.
                      Ausgangspunkt: 9.12.2021, 21:51:50
                      Als zu addierenden Zeitraum habe ich bewußt mal einen etwas redundanten Zeitraum genommen (2 Wochen und 30 Tage)

                      {
                          "years": 5,
                          "months": 1,
                          "weeks": 2,
                          "days": 30,
                          "hours": 3,
                          "minutes": 47,
                          "seconds": 28
                      }
                      

                      Also dieser Zeitraum wird addiert und das Ergebnis ist verifiziert:

                      9.12.2021 + 5 Jahre = 9.12.2026
                      9.12.2026 + 1 Monat = 9.1.2027
                      9.1.2027 + 2 Wochen = 23.1.2027
                      23.1.2027 + 30 Tage = 22.2.2027 21:51:50
                      22.2.2027 21:51:50 + 3 Std. = 23.2.2027 0:51:50
                      23.2.2027 0:51:50 + 47 Minuten = 23.2.2027 1:38:50
                      23.2.2027 1:38:50 + 28 Sekunden = 23.2.2027 1:39:18

                      Ausgangspunkt: 9.12.2021, 21:51:50
                      Das Duration Objekt liefert (wie gesagt - Wochen muss man rausnehmen)

                      {
                          "years": 5,
                          "months": 2,
                          "days": 13,
                          "hours": 3,
                          "minutes": 47,
                          "seconds": 28
                      }
                      

                      9.12.2021 + 5 Jahre = 9.12.2026
                      9.12.2026 + 2 Monate = 9.2.2027
                      9.2.2027 + 1 Woche = 16.2.2027
                      16.2.2027 + 13 Tage = 1.3.2027 ?????????
                      9.2.2027 + 13 Tage = 22.2.2027 21:51:50
                      22.2.2027 21:51:50 + 3 Std. = 23.2.2027 0:51:50
                      23.2.2027 0:51:50 + 47 Minuten = 23.2.2027 1:38:50
                      23.2.2027 1:38:50 + 28 Sekunden = 23.2.2027 1:39:18

                      Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                      1 Antwort Letzte Antwort
                      0
                      • R rewenode

                        @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                        @rewenode Ja das wollte ich eigentlich verhindern - mit der externen Einbindung - da musst Du wieder an der settings.js rumbasteln, dass Du externe Bibliotheken verfügbar machst.
                        Konnte Deinen Flow auch nicht einbinden - da irgendein parse Error - aber Dank Deiner Erklärung konnte ich es auch nachvollziehen - allerdings auch nur in der Standalone Version:

                        Ja, sorry. hatte es in einer stand alone version getestet.
                        Hier nochmal für die ioBroker Version.
                        Da gehts dann ganz einfach, wenn man einmal die moment.js eingebunden hat. Ein function-node ist dann nicht mehr nötig.

                        1. binde die moment.js über die settings.js ein.
                          Die befindet sich in
                        /opt/iobroker/node_modules/iobroker.node-red/settings.js
                        

                        Dort muss di function functionGlobalContext um den Eintrag

                        moment:require("moment")
                        

                        erweitert werden.

                        Beispiel aus meiner settings.ja

                        functionGlobalContext: {
                                moment:require("moment")
                                //'%%functionGlobalContext%%'
                                // os:require('os'),
                                // jfive:require("johnny-five"),
                                // j5board:require("johnny-five").Board({repl:false})
                            },
                        

                        Dann die node-red instanz neu starten.
                        Das wars.

                        moment.duration kann in JSONata immer mit

                        $globalContext('moment.duration')
                        

                        verwendet werden.

                        2021-12-09_21-37-51.png

                        moment steht dann natürlich auch in function-nodes zur Verfügung.

                        [
                            {
                                "id": "5d6fc95c.e73438",
                                "type": "tab",
                                "label": "Flow 3",
                                "disabled": false,
                                "info": ""
                            },
                            {
                                "id": "c38cc5bf.7f7f38",
                                "type": "inject",
                                "z": "5d6fc95c.e73438",
                                "name": "jetzt + 8 Tagen + 3 Stunden + 47 Minuten +28 Sekunden",
                                "props": [
                                    {
                                        "p": "payload"
                                    },
                                    {
                                        "p": "x",
                                        "v": "{\"days\":8,\"hours\":3,\"minutes\":47,\"seconds\":28}",
                                        "vt": "json"
                                    }
                                ],
                                "repeat": "",
                                "crontab": "",
                                "once": false,
                                "onceDelay": 0.1,
                                "topic": "",
                                "payload": "",
                                "payloadType": "date",
                                "x": 250,
                                "y": 140,
                                "wires": [
                                    [
                                        "f6e8d65f.929de8",
                                        "c535b75f1d3d6bb6"
                                    ]
                                ]
                            },
                            {
                                "id": "f6e8d65f.929de8",
                                "type": "change",
                                "z": "5d6fc95c.e73438",
                                "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                                "rules": [
                                    {
                                        "t": "set",
                                        "p": "timeA",
                                        "pt": "msg",
                                        "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                        "tot": "jsonata"
                                    },
                                    {
                                        "t": "set",
                                        "p": "timeB",
                                        "pt": "msg",
                                        "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                        "tot": "jsonata"
                                    },
                                    {
                                        "t": "delete",
                                        "p": "x",
                                        "pt": "msg"
                                    },
                                    {
                                        "t": "set",
                                        "p": "payload",
                                        "pt": "msg",
                                        "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t        /* Kein Zugriff auf duration  - also manuell berechnen*/\t        \t    $days := $b.diff($a, 'days');\t    $hours := $b.diff($a, 'hours') - 24 * $b.diff($a, 'days');\t    $minutes := $b.diff($a, 'minutes') - 60 * $b.diff($a, 'hours');\t    $seconds := $b.diff($a, 'seconds') - 60 * $b.diff($a, 'minutes');\t    \t    $sec := $b.diff($a)/1000;\t    \t\t    \t    $difference := {\t        \"days\": $days,\t        \"hours\":$hours,\t        \"minutes\": $minutes,\t        \"seconds\": $seconds\t    }; \t    \t\t)",
                                        "tot": "jsonata"
                                    }
                                ],
                                "action": "",
                                "property": "",
                                "from": "",
                                "to": "",
                                "reg": false,
                                "x": 720,
                                "y": 140,
                                "wires": [
                                    [
                                        "fb984b77.f03568"
                                    ]
                                ],
                                "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                            },
                            {
                                "id": "fb984b77.f03568",
                                "type": "debug",
                                "z": "5d6fc95c.e73438",
                                "name": "",
                                "active": true,
                                "tosidebar": true,
                                "console": false,
                                "tostatus": false,
                                "complete": "true",
                                "targetType": "full",
                                "statusVal": "",
                                "statusType": "auto",
                                "x": 1050,
                                "y": 140,
                                "wires": []
                            },
                            {
                                "id": "9958c57.83b6e38",
                                "type": "comment",
                                "z": "5d6fc95c.e73438",
                                "name": "Zeitvergleiche",
                                "info": "",
                                "x": 110,
                                "y": 100,
                                "wires": []
                            },
                            {
                                "id": "c535b75f1d3d6bb6",
                                "type": "change",
                                "z": "5d6fc95c.e73438",
                                "name": "timeA = payload; timeB =payload +x; diff timeB-timeA",
                                "rules": [
                                    {
                                        "t": "set",
                                        "p": "timeA",
                                        "pt": "msg",
                                        "to": "$moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').format('DD.MM.YYYY HH:mm:ss')",
                                        "tot": "jsonata"
                                    },
                                    {
                                        "t": "set",
                                        "p": "timeB",
                                        "pt": "msg",
                                        "to": "(\t    $x := x;\t    $moment(payload,['DD.MM.YYYY HH:mm:ss','x'],'de').add($x).format('DD.MM.YYYY HH:mm:ss');\t    )",
                                        "tot": "jsonata"
                                    },
                                    {
                                        "t": "delete",
                                        "p": "x",
                                        "pt": "msg"
                                    },
                                    {
                                        "t": "set",
                                        "p": "payload",
                                        "pt": "msg",
                                        "to": "(\t    $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');\t    \t    /* $b.diff($a) */\t    /* $moment.duration($b.diff($a)); */\t    \t    $globalContext('moment.duration')($b.diff($a)).humanize()\t\t)",
                                        "tot": "jsonata"
                                    }
                                ],
                                "action": "",
                                "property": "",
                                "from": "",
                                "to": "",
                                "reg": false,
                                "x": 720,
                                "y": 200,
                                "wires": [
                                    [
                                        "cf428b715b7fa6a5"
                                    ]
                                ],
                                "info": "akzeptiert Datumsformate ('DD.MM.YYYY HH:mm:ss') oder timestamps('x')"
                            },
                            {
                                "id": "cf428b715b7fa6a5",
                                "type": "debug",
                                "z": "5d6fc95c.e73438",
                                "name": "",
                                "active": true,
                                "tosidebar": true,
                                "console": false,
                                "tostatus": false,
                                "complete": "true",
                                "targetType": "full",
                                "statusVal": "",
                                "statusType": "auto",
                                "x": 1050,
                                "y": 200,
                                "wires": []
                            }
                        ]
                        

                        Gruß
                        Reiner

                        mickymM Offline
                        mickymM Offline
                        mickym
                        Most Active
                        schrieb am zuletzt editiert von
                        #14

                        @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.

                        Der Import geht aber im Moment trotzdem nicht - manche Flows mögen irgendwie nicht. :(

                        798dec83-bddd-42bb-a3be-813f7838d1c6-image.png

                        Aber egal - ich hab das ja erst mal miteinbinden können und auch testen können mit dem Durations Objekt - also vielen Dank Dir dafür.

                        Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                        R 1 Antwort Letzte Antwort
                        0
                        • mickymM mickym

                          @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.

                          Der Import geht aber im Moment trotzdem nicht - manche Flows mögen irgendwie nicht. :(

                          798dec83-bddd-42bb-a3be-813f7838d1c6-image.png

                          Aber egal - ich hab das ja erst mal miteinbinden können und auch testen können mit dem Durations Objekt - also vielen Dank Dir dafür.

                          R Offline
                          R Offline
                          rewenode
                          schrieb am zuletzt editiert von
                          #15

                          @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                          @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.

                          Ah, sorry. Bin halt zu selten hier. Hab's grad korrigiert und einen Reimport getestet, also bei mir gehts.

                          Gruß
                          Reiner

                          mickymM 1 Antwort Letzte Antwort
                          0
                          • R rewenode

                            @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                            @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.

                            Ah, sorry. Bin halt zu selten hier. Hab's grad korrigiert und einen Reimport getestet, also bei mir gehts.

                            Gruß
                            Reiner

                            mickymM Offline
                            mickymM Offline
                            mickym
                            Most Active
                            schrieb am zuletzt editiert von mickym
                            #16

                            @rewenode sagte in Datum und Zeitverarbeitung mit NodeRed:

                            @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                            @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.
                            

                            Ah, sorry. Bin halt zu selten hier. Hab's grad korrigiert und einen Reimport getestet, also bei mir gehts.

                            Gruß
                            Reiner

                            Ja mit den CodeTags geht es :+1: :+1: :+1: - da funkt der Browser nicht dazwischen. Das ist ja die Version ohne function Node aber global verfügbarer moment Bibliothek ;) - aber wie gesagt ich habe es ja nun ausprobiert - und mit Deiner Anleitung geht es ja direkt.

                            (
                                $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
                                $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
                                
                                /* $b.diff($a) */
                                /* $moment.duration($b.diff($a)); */
                                
                                $globalContext('moment.duration')($b.diff($a)).humanize()
                            
                            )
                            

                            Aber wie gesagt - nur dafür würde ich moments nicht extra einbinden. Im Prinzip ist es halt nur die exakte Umrechnung von Zeitperioden erforderlich - ansonsten war ja gerade der Sinn des Postings - was alles mit Boardmitteln geht. ;)

                            Für die eigentliche Umrechnung - für die aus meiner Sicht das Duration Objekt nützlich ist, habe ich ja unten gepostet.

                            Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                            R 1 Antwort Letzte Antwort
                            0
                            • mickymM mickym

                              @rewenode sagte in Datum und Zeitverarbeitung mit NodeRed:

                              @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                              @rewenode In Zukunft wäre es hilfreich Spoiler und CodeTags zu nutzen - sonst muss man immer scrollen um den Code zu kopieren.
                              

                              Ah, sorry. Bin halt zu selten hier. Hab's grad korrigiert und einen Reimport getestet, also bei mir gehts.

                              Gruß
                              Reiner

                              Ja mit den CodeTags geht es :+1: :+1: :+1: - da funkt der Browser nicht dazwischen. Das ist ja die Version ohne function Node aber global verfügbarer moment Bibliothek ;) - aber wie gesagt ich habe es ja nun ausprobiert - und mit Deiner Anleitung geht es ja direkt.

                              (
                                  $b := $moment(timeB,['DD.MM.YYYY HH:mm:ss','x'],'de');
                                  $a := $moment(timeA,['DD.MM.YYYY HH:mm:ss','x'],'de');
                                  
                                  /* $b.diff($a) */
                                  /* $moment.duration($b.diff($a)); */
                                  
                                  $globalContext('moment.duration')($b.diff($a)).humanize()
                              
                              )
                              

                              Aber wie gesagt - nur dafür würde ich moments nicht extra einbinden. Im Prinzip ist es halt nur die exakte Umrechnung von Zeitperioden erforderlich - ansonsten war ja gerade der Sinn des Postings - was alles mit Boardmitteln geht. ;)

                              Für die eigentliche Umrechnung - für die aus meiner Sicht das Duration Objekt nützlich ist, habe ich ja unten gepostet.

                              R Offline
                              R Offline
                              rewenode
                              schrieb am zuletzt editiert von rewenode
                              #17

                              @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                              Aber wie gesagt - nur dafür würde ich moments nicht extra einbinden. Im Prinzip ist es halt nur die exakte Umrechnung von Zeitperioden erforderlich - ansonsten war ja gerade der Sinn des Postings - was alles mit Boardmitteln geht.

                              Ja, wollte nur eine Möglichkeit zeigen, moment.duration in node-red JSONata zugänglich zu machen.
                              Kann ja mal hilfreich sein, zumal man sich über diesen Trick nahezu beliebige Bibliotheken in JSONata zugänglich machen kann.

                              Ja, und was Bordmittel angeht, sind bei mir immer die die ich zur Lösung des Problems unbedingt brauche und die in node-red prinzipiell möglich sind;-)
                              Aber generell stimme ich zu, auch wenn man Vieles nicht so eng sehen darf.
                              Ich glaube nicht, dass eine komplexe JSONata-Funktion im change-node weniger undurchsichtig ist, wie die gleiche Funktionalität per Javascript im function-node.

                              Gruß
                              Reiner

                              mickymM 1 Antwort Letzte Antwort
                              0
                              • R rewenode

                                @mickym sagte in Datum und Zeitverarbeitung mit NodeRed:

                                Aber wie gesagt - nur dafür würde ich moments nicht extra einbinden. Im Prinzip ist es halt nur die exakte Umrechnung von Zeitperioden erforderlich - ansonsten war ja gerade der Sinn des Postings - was alles mit Boardmitteln geht.

                                Ja, wollte nur eine Möglichkeit zeigen, moment.duration in node-red JSONata zugänglich zu machen.
                                Kann ja mal hilfreich sein, zumal man sich über diesen Trick nahezu beliebige Bibliotheken in JSONata zugänglich machen kann.

                                Ja, und was Bordmittel angeht, sind bei mir immer die die ich zur Lösung des Problems unbedingt brauche und die in node-red prinzipiell möglich sind;-)
                                Aber generell stimme ich zu, auch wenn man Vieles nicht so eng sehen darf.
                                Ich glaube nicht, dass eine komplexe JSONata-Funktion im change-node weniger undurchsichtig ist, wie die gleiche Funktionalität per Javascript im function-node.

                                Gruß
                                Reiner

                                mickymM Offline
                                mickymM Offline
                                mickym
                                Most Active
                                schrieb am zuletzt editiert von
                                #18

                                @rewenode sagte in Datum und Zeitverarbeitung mit NodeRed:

                                Ja, und was Bordmittel angeht, sind bei mir immer die die ich zur Lösung des Problems unbedingt brauche und die in node-red prinzipiell möglich sind;-)
                                Aber generell stimme ich zu, auch wenn man Vieles nicht so eng sehen darf.
                                Ich glaube nicht, dass eine komplexe JSONata-Funktion im change-node weniger undurchsichtig ist, wie die gleiche Funktionalität per Javascript im function-node.

                                Grundsätzlich stimme ich Dir zu - wobei ich function Nodes wirklich nur nutze, wenn alles andere sehr umständlich ist - weil ich eben denke, dass man sich die ganze Genialität von Node Red zunichte machen kann, wenn man zuviel in function Nodes packt. Sehe ich leider sehr häufig auch in Beispielen. ;) Letzlich kannst jeden Flow in eine function Node packen - aber dann brauche ich Node Red nicht - sondern kann ja - zumindest im iobroker - Javascript original schreiben. - OK als Standaloneversion hat man mit Node Red halt noch die Hardwareanbindung zur Verfügung. Aber die Klärung philosophischer Fragen sind dann wohl eher OT. ;)

                                Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                1 Antwort Letzte Antwort
                                1
                                • mickymM mickym

                                  Da ich mich nun mal 1-2 Tage intensiv mit der "eingebauten" Datums- und Uhrzeitverarbeitung in NodeRed beschäftigt habe, würde ich meine Erkenntnisse gerne teilen und vielleicht springt ja für den einen oder anderen was nützliches heraus.

                                  Es geht in diesem Thread nicht um die Installation von zusätzlichen Nodes, die noch weitere Steuerungsmöglichkeiten bieten, sondern das was im Grundbaukasten bereits vorhanden ist.

                                  Als wer noch mehr zu den Themen - scheduling oder Zeit filtern sucht - der soll sich mal folgende Nodes anschauen:

                                  1. cronplus: https://flows.nodered.org/node/node-red-contrib-cron-plus - alles und noch mehr was iobroker mit dem cron als Scheduler bietet.
                                  2. lightscheduler: https://flows.nodered.org/node/node-red-contrib-light-scheduler triggert - aber vor allem filtert nach Zeitereignissen
                                  3. bigtimer - wobei ich zwar am Anfang begeistert war, aber ich inzwischen den Nutzen nicht mehr sehr hoch einschätze:
                                    https://flows.nodered.org/node/node-red-contrib-bigtimer

                                  Doch mir geht es ja nicht darum, mit welchen zusätzlichen Nodes man noch was machen kann, so wie man mit dem Grundbaukasten Zeit- und Datumsereignisse verarbeitet. Zum Schluss stelle ich dann noch einen kleinen Flow vor, den man als Timer nutzen kann. ;) - und zwar flexibler als bei den fertigen Nodes. ;)

                                  Die Javascript Bibliothek, die in Node Red für die Datums- und Uhrzeit verarbeitung verfügbar ist, ist wohl die moment.js - und die Funktionen dieser Bibliothek werden ich nun im Verlauf weiter vorstellen - allerdings nicht über Javascript, sondern im Prinzip kann man diese ganze Bibliothek über JSONATA nutzen. Erst seit dem ich mich damit nun etwas näher beschäftigt habe, ergeben sich neuen Möglichkeiten, wobei ich auch noch hin und wieder ??? habe und deswegen vielleicht manches hier umständlich aussieht.

                                  Dennoch kommt bei diesem Thread quasi kein natives Javascript zur Anwendung (also keine Function Nodes). ;) ;)

                                  Ich denke, das im Blockly wohl auch die moment.js eingebunden ist - insofern kann man das vergleichen und gegenüberstellen.

                                  Was im Standard nicht verfügbar ist, sind die Astrozeiten - dafür bieten sich aber alle 3 oben genannten Nodes an - die hier eine Vielzahl an Funktionen bieten - wer da mehr wissen will, meldet sich einfach.

                                  Wie gesagt - sowohl im Blockly als auch in Node Red wurde für die Datums und Uhrzeitverarbeitung die moment.js Bibliothek verfügbar gemacht. Dabei geht in NodeRed in meinen Augen die Möglichkeiten der Nutzung über das hinaus, was üblicherweise in den Puzzleteilchen angeboten wird. ;)

                                  Die volle Funktionalität der moment.js Bibliothek sollte man sich als Nachschlagewerk als Seite abspeichern:
                                  https://momentjs.com/docs/#/parsing/

                                  Anscheinend wird die Bibliothek nicht mehr weiter entwickelt - wird aber noch gewartet.

                                  Nodes die vollkommen überflüssig sind, sind die moment.js Nodes - zumindest seitdem die moment.js Bibliothek unter NodeRed im JSONATA verfügbar gemacht wurde. Diese Nodes : https://flows.nodered.org/node/node-red-contrib-moment können also komplett ersetzt werden. Ich hatte die anfangs auch, werden nun aber rausgeschmissen.

                                  Dreh- und Angelpunkte bei der Nutzung der moment.js Bibliothek sind natürlich die moment-Objekte. Diese sind keine date-Objekte von Javascript. Wer also die moment.js Bibliothek im Javascript nutzen will, muss sie nach Installation halt wie üblich mit require in den Code einbinden.

                                  https://momentjs.com/docs/#/use-it/

                                  var moment = require('moment'); // require
                                  moment().format()
                                  

                                  In NodeRed ist es wie gesagt nicht erforderlich und man benötigt weder eine moment.js Insallation noch muss man Bibliohteken global verfügbar machen - außer man wollte die moment.js in function Nodes nutzen, was hier aber nicht der Fall ist und deswegen auch nicht weiter beschrieben wird. Hier geht es deshalb ausschließlich um die moment.js Funktionen, die JSONATA in NodeRed zur Verfügung stellt und die deshalb in verschiedenen Nodes wie der Change-Node, der Inject-Node, der Switch-Node, Join-Node etc. zur Verfügung steht und angewandt wird.

                                  Im folgenden werde ich mich etwas an Blockly orientieren - da in meinen Augen die gleiche Bibliothek dahinter liegt und erklären, wie man das im JSONATA und in NodeRed umsetzt.

                                  mickymM Offline
                                  mickymM Offline
                                  mickym
                                  Most Active
                                  schrieb am zuletzt editiert von mickym
                                  #19

                                  So noch ein paar Ergänzungen bzw. neue Erkenntnisse - wenn man es braucht.

                                  Um Switch Nodes mit Zeitfenstern zu definieren - kann man die moments Bibliothek wie folgt nutzen:

                                  [
                                     {
                                         "id": "9ec63930.7a41d8",
                                         "type": "switch",
                                         "z": "6e170384.60c96c",
                                         "name": "Is es Zwischen 10:48 and 17:05?",
                                         "property": "$moment().isBetween($moment(\"10:48\", \"HH:mm\"),$moment(\"17:05\", \"HH:mm\"),'minute')",
                                         "propertyType": "jsonata",
                                         "rules": [
                                             {
                                                 "t": "true"
                                             },
                                             {
                                                 "t": "false"
                                             }
                                         ],
                                         "checkall": "true",
                                         "repair": false,
                                         "outputs": 2,
                                         "x": 1560,
                                         "y": 2140,
                                         "wires": [
                                             [
                                                 "63e091c.217c47"
                                             ],
                                             [
                                                 "57759b84.262984"
                                             ]
                                         ]
                                     },
                                     {
                                         "id": "76ac8c2.21f6f74",
                                         "type": "inject",
                                         "z": "6e170384.60c96c",
                                         "name": "",
                                         "props": [
                                             {
                                                 "p": "payload"
                                             }
                                         ],
                                         "repeat": "",
                                         "crontab": "",
                                         "once": false,
                                         "onceDelay": 0.1,
                                         "topic": "",
                                         "payload": "payload ist unwichtig, wo ich rauskomme ist wichtig ;)",
                                         "payloadType": "str",
                                         "x": 1330,
                                         "y": 2140,
                                         "wires": [
                                             [
                                                 "9ec63930.7a41d8"
                                             ]
                                         ]
                                     },
                                     {
                                         "id": "63e091c.217c47",
                                         "type": "debug",
                                         "z": "6e170384.60c96c",
                                         "name": "true",
                                         "active": true,
                                         "tosidebar": true,
                                         "console": false,
                                         "tostatus": false,
                                         "complete": "payload",
                                         "targetType": "msg",
                                         "statusVal": "",
                                         "statusType": "auto",
                                         "x": 1810,
                                         "y": 2120,
                                         "wires": []
                                     },
                                     {
                                         "id": "57759b84.262984",
                                         "type": "debug",
                                         "z": "6e170384.60c96c",
                                         "name": "false",
                                         "active": true,
                                         "tosidebar": true,
                                         "console": false,
                                         "tostatus": false,
                                         "complete": "payload",
                                         "targetType": "msg",
                                         "statusVal": "",
                                         "statusType": "auto",
                                         "x": 1810,
                                         "y": 2160,
                                         "wires": []
                                     }
                                  ]
                                  

                                  Ohne 3. Parameter bei dem Moments Funktion isBetween() - kann man dann über eckige bzw. runde Klammern noch angeben, ob die Anfangs- bzw. Endzeiten aus bzw. eingeschlossen sind in dem definierten Zeitraum.
                                  Ohne Angabe ist die Anfangszeit eingeschlossen, die Endzeit ausgeschlossen!!!

                                  5fcdf127-b7db-49bb-ab91-8d96e9db1c15-image.png

                                  Braucht man wieder über Nachtzeiträume negiert man das entweder oder nutzt den false Ausgang. ;)

                                  Am sichersten ist man, wenn man 2 moments Objekte vergleicht und dann auch noch die Genauigkeit spezifiziert:

                                  $moment().isBetween($moment("10:48", "HH:mm"),$moment("17:05", "HH:mm"),'minute')
                                  

                                  Das 1. moments Objekt ist Anfangszeit mit Format zu richtigen Interpretation, das 2. moments Objekt die Endzeit mit Format zur richtigen Interpretation und die Genauigkeit ist auf Minute gesetzt.

                                  Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                  1 Antwort Letzte Antwort
                                  0
                                  • mickymM mickym

                                    Da ich mich nun mal 1-2 Tage intensiv mit der "eingebauten" Datums- und Uhrzeitverarbeitung in NodeRed beschäftigt habe, würde ich meine Erkenntnisse gerne teilen und vielleicht springt ja für den einen oder anderen was nützliches heraus.

                                    Es geht in diesem Thread nicht um die Installation von zusätzlichen Nodes, die noch weitere Steuerungsmöglichkeiten bieten, sondern das was im Grundbaukasten bereits vorhanden ist.

                                    Als wer noch mehr zu den Themen - scheduling oder Zeit filtern sucht - der soll sich mal folgende Nodes anschauen:

                                    1. cronplus: https://flows.nodered.org/node/node-red-contrib-cron-plus - alles und noch mehr was iobroker mit dem cron als Scheduler bietet.
                                    2. lightscheduler: https://flows.nodered.org/node/node-red-contrib-light-scheduler triggert - aber vor allem filtert nach Zeitereignissen
                                    3. bigtimer - wobei ich zwar am Anfang begeistert war, aber ich inzwischen den Nutzen nicht mehr sehr hoch einschätze:
                                      https://flows.nodered.org/node/node-red-contrib-bigtimer

                                    Doch mir geht es ja nicht darum, mit welchen zusätzlichen Nodes man noch was machen kann, so wie man mit dem Grundbaukasten Zeit- und Datumsereignisse verarbeitet. Zum Schluss stelle ich dann noch einen kleinen Flow vor, den man als Timer nutzen kann. ;) - und zwar flexibler als bei den fertigen Nodes. ;)

                                    Die Javascript Bibliothek, die in Node Red für die Datums- und Uhrzeit verarbeitung verfügbar ist, ist wohl die moment.js - und die Funktionen dieser Bibliothek werden ich nun im Verlauf weiter vorstellen - allerdings nicht über Javascript, sondern im Prinzip kann man diese ganze Bibliothek über JSONATA nutzen. Erst seit dem ich mich damit nun etwas näher beschäftigt habe, ergeben sich neuen Möglichkeiten, wobei ich auch noch hin und wieder ??? habe und deswegen vielleicht manches hier umständlich aussieht.

                                    Dennoch kommt bei diesem Thread quasi kein natives Javascript zur Anwendung (also keine Function Nodes). ;) ;)

                                    Ich denke, das im Blockly wohl auch die moment.js eingebunden ist - insofern kann man das vergleichen und gegenüberstellen.

                                    Was im Standard nicht verfügbar ist, sind die Astrozeiten - dafür bieten sich aber alle 3 oben genannten Nodes an - die hier eine Vielzahl an Funktionen bieten - wer da mehr wissen will, meldet sich einfach.

                                    Wie gesagt - sowohl im Blockly als auch in Node Red wurde für die Datums und Uhrzeitverarbeitung die moment.js Bibliothek verfügbar gemacht. Dabei geht in NodeRed in meinen Augen die Möglichkeiten der Nutzung über das hinaus, was üblicherweise in den Puzzleteilchen angeboten wird. ;)

                                    Die volle Funktionalität der moment.js Bibliothek sollte man sich als Nachschlagewerk als Seite abspeichern:
                                    https://momentjs.com/docs/#/parsing/

                                    Anscheinend wird die Bibliothek nicht mehr weiter entwickelt - wird aber noch gewartet.

                                    Nodes die vollkommen überflüssig sind, sind die moment.js Nodes - zumindest seitdem die moment.js Bibliothek unter NodeRed im JSONATA verfügbar gemacht wurde. Diese Nodes : https://flows.nodered.org/node/node-red-contrib-moment können also komplett ersetzt werden. Ich hatte die anfangs auch, werden nun aber rausgeschmissen.

                                    Dreh- und Angelpunkte bei der Nutzung der moment.js Bibliothek sind natürlich die moment-Objekte. Diese sind keine date-Objekte von Javascript. Wer also die moment.js Bibliothek im Javascript nutzen will, muss sie nach Installation halt wie üblich mit require in den Code einbinden.

                                    https://momentjs.com/docs/#/use-it/

                                    var moment = require('moment'); // require
                                    moment().format()
                                    

                                    In NodeRed ist es wie gesagt nicht erforderlich und man benötigt weder eine moment.js Insallation noch muss man Bibliohteken global verfügbar machen - außer man wollte die moment.js in function Nodes nutzen, was hier aber nicht der Fall ist und deswegen auch nicht weiter beschrieben wird. Hier geht es deshalb ausschließlich um die moment.js Funktionen, die JSONATA in NodeRed zur Verfügung stellt und die deshalb in verschiedenen Nodes wie der Change-Node, der Inject-Node, der Switch-Node, Join-Node etc. zur Verfügung steht und angewandt wird.

                                    Im folgenden werde ich mich etwas an Blockly orientieren - da in meinen Augen die gleiche Bibliothek dahinter liegt und erklären, wie man das im JSONATA und in NodeRed umsetzt.

                                    mickymM Offline
                                    mickymM Offline
                                    mickym
                                    Most Active
                                    schrieb am zuletzt editiert von mickym
                                    #20

                                    @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

                                    Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                    1 Antwort Letzte Antwort
                                    0
                                    • mickymM Offline
                                      mickymM Offline
                                      mickym
                                      Most Active
                                      schrieb am zuletzt editiert von mickym
                                      #21

                                      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"
                                                 ]
                                             ]
                                         }
                                      ]
                                      

                                      Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                      1 Antwort Letzte Antwort
                                      2
                                      • mickymM Offline
                                        mickymM Offline
                                        mickym
                                        Most Active
                                        schrieb am zuletzt editiert von
                                        #22

                                        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"
                                                   ]
                                               ]
                                           }
                                        ]
                                        

                                        Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                        1 Antwort Letzte Antwort
                                        1
                                        • mickymM Offline
                                          mickymM Offline
                                          mickym
                                          Most Active
                                          schrieb am zuletzt editiert von mickym
                                          #23

                                          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"
                                                     ]
                                                 ]
                                             }
                                          ]
                                          

                                          Jeder Flow bzw. jedes Script, das ich hier poste implementiert jeder auf eigene Gefahr. Flows und Scripts können Fehler aufweisen und weder der Seitenbetreiber noch ich persönlich können hierfür haftbar gemacht werden. Das gleiche gilt für Empfehlungen aller Art.

                                          1 Antwort Letzte Antwort
                                          1
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          800

                                          Online

                                          32.5k

                                          Benutzer

                                          81.8k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe