Skip to content
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • 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

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. Node-Red
  5. Laufschrift in einem NodeRed Flow erzeugen

NEWS

  • Wartung am 15.11. – Forum ab 22:00 Uhr nicht erreichbar
    BluefoxB
    Bluefox
    12
    2
    234

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

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.7k

Laufschrift in einem NodeRed Flow erzeugen

Laufschrift in einem NodeRed Flow erzeugen

Scheduled Pinned Locked Moved Node-Red
12 Posts 3 Posters 1.9k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mickymM Offline
    mickymM Offline
    mickym
    Most Active
    wrote on last edited by mickym
    #1

    Da ich von einem User hier an Board gefragt worden bin, ob man in NodeRed eine Laufschrift erzeugen kann und ich vergeblich nach einer bereits fertigen Node gesucht habe, habe ich dieses Mal selbst ein function Node geschrieben. 😉

    Hintergrund ist wohl, dass man bei den KNX-Tastern auf 14 Zeichen zur Anzeige von Text. Gibt auch bereits einen Flow zu dem Thema: https://knx-user-forum.de/forum/supportforen/proserv/1470641-14-byte-text-von-node-red-auf-den-bus
    Das kam mir aber sehr komplex vor.

    Für die Möglichkeiten des Scroll-Textes habe ich mich wie in diesem Video beschrieben an diese Gira Blöcke angelehnt.

    Hier dann als Demo im NodeRed Dashboard da ich ja keinen KNX Taster habe:

    Mode Zirkulierend:

    Dabei konnte ich mal wieder meine Javascript Skills testen - aber die sind natürlich laienhaft im Vergleich zu den Profis hier.

    Interessant ist, wie man in function Nodes (ich fand das nicht dokumentiert) einen Timer erstellen kann, der auch bei erneutem Aufruf der Node ansprechbar bleibt. Das geht anscheinend in dem man die Variable nicht normal im Kontext abspeichert sondern quasi als Eigenschaft des Kontextes. Das wusste ich noch nicht. Man erstellt deshalb auch keine Variable sondern erstellt es quasi implizit im Kontext:

    context.timer; /* undokumentiert - setze Variable im Node Kontext um 
                        auf Timerinstanz zu zugreifen */
    

    Hier nun die Funktionsweise dieser Node:

    Laufschrift erzeugen

    Diese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.

    Grundsätzlich startet eine msg.payload automatisch die Node mit Standardvorgaben.
    Ein erneutes Senden einer msg.payload stoppt bzw. inaktiviert die Node wieder.

    Konfiguration

    Eine Nachricht, die keine msg.payload enthält (z. Bsp. nur eine msg.config) oder eine leere msg.payload stoppt die Node.
    Die Konfigurationsparameter können über eine msg.config erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden.

    Das Konfiguationsobjekt ist direkt im Code wie folgt beschrieben:

    {"offset": 1,        // scrollen um x Zeichen
    "textwindow": 14,   // Fenster wie groß der Text sein darf
    "interval": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird
    "mode": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her
    "separator": " * "  // Trennungsstring am Ende des Textes}
    

    Die passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich.

    Den gleichen Text findet man auch in der Beschreibung zu der function Node:

    Ansonsten habe ich alles in den Hilfetext der function Node geschrieben mit einem Beispielflow:

    17d0ecb5-fb40-4d6d-8cba-1db3f53c0868-image.png

    Demo:

    Lauftext.gif

    Und natürlich zum Schluss der Beispielflow mit der function Node für den Lauftext:

    EDIT: 5.2.2023
    Enthält nun Version 0.3 - wenn die Textlänge der payload unter oder gleich dem textwindow ist, wird der Text unverändert als einfacher String weitergegeben.

    EDIT 11.2.2023
    Enthält nun Version 0.4 - Lauftext wird nur noch gestoppt mit leerer payload oder Länge kleiner textwindow. Ansonsten kann nun Text und Konfiguration dynamisch geändert werden.

    EDIT 17.2.2023
    Timer nicht mehr direkt im Kontext gespeichert und leere msg.config ohne payload startet keinen neuen Timer mehr. Version 0.5.1

    [
        {
            "id": "03201976729fd712",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "Beispiel",
            "props": [
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "Dies ist ein sehr, sehr langer Text",
            "payloadType": "str",
            "x": 210,
            "y": 220,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "f03c5796d29ad693",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "",
            "props": [
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "Hallo",
            "payloadType": "str",
            "x": 210,
            "y": 320,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "4cd600bbf5582f51",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "stop",
            "props": [
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "",
            "payloadType": "str",
            "x": 210,
            "y": 360,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "8cfd9b55e5251123",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "config fast",
            "props": [
                {
                    "p": "config",
                    "v": "{\"offset\":2,\"textwindow\":14,\"interval\":200,\"mode\":0,\"separator\":\" * \"}",
                    "vt": "json"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "x": 200,
            "y": 120,
            "wires": [
                [
                    "4c274b6ade59ef73"
                ]
            ]
        },
        {
            "id": "fda69c0a0c8d05bc",
            "type": "catch",
            "z": "5289f6ad4bf32e52",
            "name": "",
            "scope": [
                "9bf7625128ecafdc"
            ],
            "uncaught": false,
            "x": 230,
            "y": 540,
            "wires": [
                [
                    "05275e48396c5862"
                ]
            ]
        },
        {
            "id": "05275e48396c5862",
            "type": "debug",
            "z": "5289f6ad4bf32e52",
            "name": "ErrObjekt",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "true",
            "targetType": "full",
            "statusVal": "",
            "statusType": "auto",
            "x": 400,
            "y": 540,
            "wires": []
        },
        {
            "id": "10903a351cc8f674",
            "type": "change",
            "z": "5289f6ad4bf32e52",
            "name": "Modus",
            "rules": [
                {
                    "t": "set",
                    "p": "modes",
                    "pt": "msg",
                    "to": "[{\"id\":0,\"Beschreibung\":\"0 - Zirkulierend\"},{\"id\":1,\"Beschreibung\":\"1 - Anfang bis Ende\"},{\"id\":2,\"Beschreibung\":\"2 - Hin und Her\"}]",
                    "tot": "json"
                },
                {
                    "t": "set",
                    "p": "payload",
                    "pt": "msg",
                    "to": "modes[id=$$.config.mode].Beschreibung",
                    "tot": "jsonata"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 410,
            "y": 120,
            "wires": [
                [
                    "a9fff8ec4b1f4231"
                ]
            ]
        },
        {
            "id": "a9fff8ec4b1f4231",
            "type": "ui_text",
            "z": "5289f6ad4bf32e52",
            "group": "57f13d6f733e5c9d",
            "order": 5,
            "width": 0,
            "height": 0,
            "name": "Modus",
            "label": "Modus",
            "format": "{{msg.payload}}",
            "layout": "row-spread",
            "className": "",
            "x": 690,
            "y": 120,
            "wires": []
        },
        {
            "id": "23af56526b7b3c88",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "Beispiel 2",
            "props": [
                {
                    "p": "payload"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "Neuer Beispieltext 2!",
            "payloadType": "str",
            "x": 200,
            "y": 260,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "a07f352124bb3886",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "config slow",
            "props": [
                {
                    "p": "config",
                    "v": "{\"offset\":2,\"textwindow\":14,\"interval\":1000,\"mode\":0,\"separator\":\" * \"}",
                    "vt": "json"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "x": 200,
            "y": 160,
            "wires": [
                [
                    "4c274b6ade59ef73"
                ]
            ]
        },
        {
            "id": "a4bc525066ffdd78",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "Beispiel immer schnell",
            "props": [
                {
                    "p": "payload"
                },
                {
                    "p": "config",
                    "v": "{     \"offset\": 2,     \"textwindow\": 14,     \"interval\": 200,     \"mode\": 0,     \"separator\": \" * \" }",
                    "vt": "json"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "Dies ist ein sehr, sehr langer Text",
            "payloadType": "str",
            "x": 160,
            "y": 420,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "daf6067dc52d7873",
            "type": "inject",
            "z": "5289f6ad4bf32e52",
            "name": "Beispiel 2 immer langsam",
            "props": [
                {
                    "p": "payload"
                },
                {
                    "p": "config",
                    "v": "{\"offset\":2,\"textwindow\":14,\"interval\":1000,\"mode\":0,\"separator\":\" * \"}",
                    "vt": "json"
                }
            ],
            "repeat": "",
            "crontab": "",
            "once": false,
            "onceDelay": 0.1,
            "topic": "",
            "payload": "Neuer Beispieltext 2!",
            "payloadType": "str",
            "x": 150,
            "y": 460,
            "wires": [
                [
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "5f2b32e2189a673e",
            "type": "function",
            "z": "5289f6ad4bf32e52",
            "name": "Laufschrift v0.5.1",
            "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      17.02.2023\n* Version:    v 0.5.1\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? \"aktiv\" : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
            "outputs": 1,
            "noerr": 0,
            "initialize": "",
            "finalize": "",
            "libs": [],
            "x": 510,
            "y": 320,
            "wires": [
                [
                    "69b97a0af5eb83ad",
                    "3b908b1849af30ba"
                ]
            ],
            "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
        },
        {
            "id": "69b97a0af5eb83ad",
            "type": "ui_text",
            "z": "5289f6ad4bf32e52",
            "group": "57f13d6f733e5c9d",
            "order": 6,
            "width": 0,
            "height": 0,
            "name": "",
            "label": "",
            "format": "{{msg.payload}}",
            "layout": "col-center",
            "className": "",
            "x": 710,
            "y": 320,
            "wires": []
        },
        {
            "id": "3b908b1849af30ba",
            "type": "debug",
            "z": "5289f6ad4bf32e52",
            "name": "Node 1",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "payload",
            "targetType": "msg",
            "statusVal": "",
            "statusType": "auto",
            "x": 720,
            "y": 280,
            "wires": []
        },
        {
            "id": "4c274b6ade59ef73",
            "type": "junction",
            "z": "5289f6ad4bf32e52",
            "x": 300,
            "y": 140,
            "wires": [
                [
                    "10903a351cc8f674",
                    "ed7d5b75938de5ff"
                ]
            ]
        },
        {
            "id": "ed7d5b75938de5ff",
            "type": "junction",
            "z": "5289f6ad4bf32e52",
            "x": 380,
            "y": 320,
            "wires": [
                [
                    "5f2b32e2189a673e"
                ]
            ]
        },
        {
            "id": "57f13d6f733e5c9d",
            "type": "ui_group",
            "name": "Test",
            "tab": "20b3095113f94d70",
            "order": 1,
            "disp": true,
            "width": "6",
            "collapse": false,
            "className": ""
        },
        {
            "id": "20b3095113f94d70",
            "type": "ui_tab",
            "name": "Home",
            "icon": "dashboard",
            "order": 1,
            "disabled": false,
            "hidden": false
        }
    ]
    

    EDIT 21.2.2023
    Neue Version: 0.6.
    Ab hier wird nur noch der Code der einzelnen Node gepostet:

    [
       {
           "id": "5f2b32e2189a673e",
           "type": "function",
           "z": "5289f6ad4bf32e52",
           "name": "Laufschrift v0.6",
           "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      21.02.2023\n* Version:    v 0.6\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nvar description = config.mode ? (config.mode === 1) ? \"Anfang - Ende\" : \"Hin und Her\" : \"Zirkulierend\";\ndescription = \"Modus: \" + description + \"; Offset: \" + config.offset + \"; Intervall: \" + config.interval + \" ms; Textfenster: \" + config.textwindow;\n\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2  (true = vorwärts, false = rückwärts)\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? description : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            output = text.slice(i, config.textwindow + i);\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n            output = text.slice(i, config.textwindow + i);\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    if (msg.payload) node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
           "outputs": 1,
           "noerr": 0,
           "initialize": "",
           "finalize": "",
           "libs": [],
           "x": 500,
           "y": 320,
           "wires": [
               [
                   "69b97a0af5eb83ad",
                   "3b908b1849af30ba"
               ]
           ],
           "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
       }
    ]
    

    Die Beschreibung zu Version 0.6 ist hier: https://forum.iobroker.net/post/951154

    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.

    C 1 Reply Last reply
    6
    • mickymM mickym

      Da ich von einem User hier an Board gefragt worden bin, ob man in NodeRed eine Laufschrift erzeugen kann und ich vergeblich nach einer bereits fertigen Node gesucht habe, habe ich dieses Mal selbst ein function Node geschrieben. 😉

      Hintergrund ist wohl, dass man bei den KNX-Tastern auf 14 Zeichen zur Anzeige von Text. Gibt auch bereits einen Flow zu dem Thema: https://knx-user-forum.de/forum/supportforen/proserv/1470641-14-byte-text-von-node-red-auf-den-bus
      Das kam mir aber sehr komplex vor.

      Für die Möglichkeiten des Scroll-Textes habe ich mich wie in diesem Video beschrieben an diese Gira Blöcke angelehnt.

      Hier dann als Demo im NodeRed Dashboard da ich ja keinen KNX Taster habe:

      Mode Zirkulierend:

      Dabei konnte ich mal wieder meine Javascript Skills testen - aber die sind natürlich laienhaft im Vergleich zu den Profis hier.

      Interessant ist, wie man in function Nodes (ich fand das nicht dokumentiert) einen Timer erstellen kann, der auch bei erneutem Aufruf der Node ansprechbar bleibt. Das geht anscheinend in dem man die Variable nicht normal im Kontext abspeichert sondern quasi als Eigenschaft des Kontextes. Das wusste ich noch nicht. Man erstellt deshalb auch keine Variable sondern erstellt es quasi implizit im Kontext:

      context.timer; /* undokumentiert - setze Variable im Node Kontext um 
                          auf Timerinstanz zu zugreifen */
      

      Hier nun die Funktionsweise dieser Node:

      Laufschrift erzeugen

      Diese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.

      Grundsätzlich startet eine msg.payload automatisch die Node mit Standardvorgaben.
      Ein erneutes Senden einer msg.payload stoppt bzw. inaktiviert die Node wieder.

      Konfiguration

      Eine Nachricht, die keine msg.payload enthält (z. Bsp. nur eine msg.config) oder eine leere msg.payload stoppt die Node.
      Die Konfigurationsparameter können über eine msg.config erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden.

      Das Konfiguationsobjekt ist direkt im Code wie folgt beschrieben:

      {"offset": 1,        // scrollen um x Zeichen
      "textwindow": 14,   // Fenster wie groß der Text sein darf
      "interval": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird
      "mode": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her
      "separator": " * "  // Trennungsstring am Ende des Textes}
      

      Die passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich.

      Den gleichen Text findet man auch in der Beschreibung zu der function Node:

      Ansonsten habe ich alles in den Hilfetext der function Node geschrieben mit einem Beispielflow:

      17d0ecb5-fb40-4d6d-8cba-1db3f53c0868-image.png

      Demo:

      Lauftext.gif

      Und natürlich zum Schluss der Beispielflow mit der function Node für den Lauftext:

      EDIT: 5.2.2023
      Enthält nun Version 0.3 - wenn die Textlänge der payload unter oder gleich dem textwindow ist, wird der Text unverändert als einfacher String weitergegeben.

      EDIT 11.2.2023
      Enthält nun Version 0.4 - Lauftext wird nur noch gestoppt mit leerer payload oder Länge kleiner textwindow. Ansonsten kann nun Text und Konfiguration dynamisch geändert werden.

      EDIT 17.2.2023
      Timer nicht mehr direkt im Kontext gespeichert und leere msg.config ohne payload startet keinen neuen Timer mehr. Version 0.5.1

      [
          {
              "id": "03201976729fd712",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "Beispiel",
              "props": [
                  {
                      "p": "payload"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "Dies ist ein sehr, sehr langer Text",
              "payloadType": "str",
              "x": 210,
              "y": 220,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "f03c5796d29ad693",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "",
              "props": [
                  {
                      "p": "payload"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "Hallo",
              "payloadType": "str",
              "x": 210,
              "y": 320,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "4cd600bbf5582f51",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "stop",
              "props": [
                  {
                      "p": "payload"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "",
              "payloadType": "str",
              "x": 210,
              "y": 360,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "8cfd9b55e5251123",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "config fast",
              "props": [
                  {
                      "p": "config",
                      "v": "{\"offset\":2,\"textwindow\":14,\"interval\":200,\"mode\":0,\"separator\":\" * \"}",
                      "vt": "json"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "x": 200,
              "y": 120,
              "wires": [
                  [
                      "4c274b6ade59ef73"
                  ]
              ]
          },
          {
              "id": "fda69c0a0c8d05bc",
              "type": "catch",
              "z": "5289f6ad4bf32e52",
              "name": "",
              "scope": [
                  "9bf7625128ecafdc"
              ],
              "uncaught": false,
              "x": 230,
              "y": 540,
              "wires": [
                  [
                      "05275e48396c5862"
                  ]
              ]
          },
          {
              "id": "05275e48396c5862",
              "type": "debug",
              "z": "5289f6ad4bf32e52",
              "name": "ErrObjekt",
              "active": true,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "true",
              "targetType": "full",
              "statusVal": "",
              "statusType": "auto",
              "x": 400,
              "y": 540,
              "wires": []
          },
          {
              "id": "10903a351cc8f674",
              "type": "change",
              "z": "5289f6ad4bf32e52",
              "name": "Modus",
              "rules": [
                  {
                      "t": "set",
                      "p": "modes",
                      "pt": "msg",
                      "to": "[{\"id\":0,\"Beschreibung\":\"0 - Zirkulierend\"},{\"id\":1,\"Beschreibung\":\"1 - Anfang bis Ende\"},{\"id\":2,\"Beschreibung\":\"2 - Hin und Her\"}]",
                      "tot": "json"
                  },
                  {
                      "t": "set",
                      "p": "payload",
                      "pt": "msg",
                      "to": "modes[id=$$.config.mode].Beschreibung",
                      "tot": "jsonata"
                  }
              ],
              "action": "",
              "property": "",
              "from": "",
              "to": "",
              "reg": false,
              "x": 410,
              "y": 120,
              "wires": [
                  [
                      "a9fff8ec4b1f4231"
                  ]
              ]
          },
          {
              "id": "a9fff8ec4b1f4231",
              "type": "ui_text",
              "z": "5289f6ad4bf32e52",
              "group": "57f13d6f733e5c9d",
              "order": 5,
              "width": 0,
              "height": 0,
              "name": "Modus",
              "label": "Modus",
              "format": "{{msg.payload}}",
              "layout": "row-spread",
              "className": "",
              "x": 690,
              "y": 120,
              "wires": []
          },
          {
              "id": "23af56526b7b3c88",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "Beispiel 2",
              "props": [
                  {
                      "p": "payload"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "Neuer Beispieltext 2!",
              "payloadType": "str",
              "x": 200,
              "y": 260,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "a07f352124bb3886",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "config slow",
              "props": [
                  {
                      "p": "config",
                      "v": "{\"offset\":2,\"textwindow\":14,\"interval\":1000,\"mode\":0,\"separator\":\" * \"}",
                      "vt": "json"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "x": 200,
              "y": 160,
              "wires": [
                  [
                      "4c274b6ade59ef73"
                  ]
              ]
          },
          {
              "id": "a4bc525066ffdd78",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "Beispiel immer schnell",
              "props": [
                  {
                      "p": "payload"
                  },
                  {
                      "p": "config",
                      "v": "{     \"offset\": 2,     \"textwindow\": 14,     \"interval\": 200,     \"mode\": 0,     \"separator\": \" * \" }",
                      "vt": "json"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "Dies ist ein sehr, sehr langer Text",
              "payloadType": "str",
              "x": 160,
              "y": 420,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "daf6067dc52d7873",
              "type": "inject",
              "z": "5289f6ad4bf32e52",
              "name": "Beispiel 2 immer langsam",
              "props": [
                  {
                      "p": "payload"
                  },
                  {
                      "p": "config",
                      "v": "{\"offset\":2,\"textwindow\":14,\"interval\":1000,\"mode\":0,\"separator\":\" * \"}",
                      "vt": "json"
                  }
              ],
              "repeat": "",
              "crontab": "",
              "once": false,
              "onceDelay": 0.1,
              "topic": "",
              "payload": "Neuer Beispieltext 2!",
              "payloadType": "str",
              "x": 150,
              "y": 460,
              "wires": [
                  [
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "5f2b32e2189a673e",
              "type": "function",
              "z": "5289f6ad4bf32e52",
              "name": "Laufschrift v0.5.1",
              "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      17.02.2023\n* Version:    v 0.5.1\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? \"aktiv\" : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
              "outputs": 1,
              "noerr": 0,
              "initialize": "",
              "finalize": "",
              "libs": [],
              "x": 510,
              "y": 320,
              "wires": [
                  [
                      "69b97a0af5eb83ad",
                      "3b908b1849af30ba"
                  ]
              ],
              "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
          },
          {
              "id": "69b97a0af5eb83ad",
              "type": "ui_text",
              "z": "5289f6ad4bf32e52",
              "group": "57f13d6f733e5c9d",
              "order": 6,
              "width": 0,
              "height": 0,
              "name": "",
              "label": "",
              "format": "{{msg.payload}}",
              "layout": "col-center",
              "className": "",
              "x": 710,
              "y": 320,
              "wires": []
          },
          {
              "id": "3b908b1849af30ba",
              "type": "debug",
              "z": "5289f6ad4bf32e52",
              "name": "Node 1",
              "active": true,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "payload",
              "targetType": "msg",
              "statusVal": "",
              "statusType": "auto",
              "x": 720,
              "y": 280,
              "wires": []
          },
          {
              "id": "4c274b6ade59ef73",
              "type": "junction",
              "z": "5289f6ad4bf32e52",
              "x": 300,
              "y": 140,
              "wires": [
                  [
                      "10903a351cc8f674",
                      "ed7d5b75938de5ff"
                  ]
              ]
          },
          {
              "id": "ed7d5b75938de5ff",
              "type": "junction",
              "z": "5289f6ad4bf32e52",
              "x": 380,
              "y": 320,
              "wires": [
                  [
                      "5f2b32e2189a673e"
                  ]
              ]
          },
          {
              "id": "57f13d6f733e5c9d",
              "type": "ui_group",
              "name": "Test",
              "tab": "20b3095113f94d70",
              "order": 1,
              "disp": true,
              "width": "6",
              "collapse": false,
              "className": ""
          },
          {
              "id": "20b3095113f94d70",
              "type": "ui_tab",
              "name": "Home",
              "icon": "dashboard",
              "order": 1,
              "disabled": false,
              "hidden": false
          }
      ]
      

      EDIT 21.2.2023
      Neue Version: 0.6.
      Ab hier wird nur noch der Code der einzelnen Node gepostet:

      [
         {
             "id": "5f2b32e2189a673e",
             "type": "function",
             "z": "5289f6ad4bf32e52",
             "name": "Laufschrift v0.6",
             "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      21.02.2023\n* Version:    v 0.6\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nvar description = config.mode ? (config.mode === 1) ? \"Anfang - Ende\" : \"Hin und Her\" : \"Zirkulierend\";\ndescription = \"Modus: \" + description + \"; Offset: \" + config.offset + \"; Intervall: \" + config.interval + \" ms; Textfenster: \" + config.textwindow;\n\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2  (true = vorwärts, false = rückwärts)\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? description : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            output = text.slice(i, config.textwindow + i);\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n            output = text.slice(i, config.textwindow + i);\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    if (msg.payload) node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
             "outputs": 1,
             "noerr": 0,
             "initialize": "",
             "finalize": "",
             "libs": [],
             "x": 500,
             "y": 320,
             "wires": [
                 [
                     "69b97a0af5eb83ad",
                     "3b908b1849af30ba"
                 ]
             ],
             "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
         }
      ]
      

      Die Beschreibung zu Version 0.6 ist hier: https://forum.iobroker.net/post/951154

      C Offline
      C Offline
      capuccino
      wrote on last edited by
      #2

      @mickym ezgif-5-205085e86b.gif

      Danke klappt wunderbar.

      mickymM 1 Reply Last reply
      2
      • C capuccino

        @mickym ezgif-5-205085e86b.gif

        Danke klappt wunderbar.

        mickymM Offline
        mickymM Offline
        mickym
        Most Active
        wrote on last edited by
        #3

        @capuccino sagte in Laufschrift in einem NodeRed Flow erzeugen:

        @mickym ezgif-5-205085e86b.gif

        Danke klappt wunderbar.

        Na das freut mich. 🙂 - Ist doch schön, dass man so eine Anwendung auch in der Praxis sehen kann. Danke für die Rückmeldung. 👍

        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 Reply Last reply
        0
        • mickymM Offline
          mickymM Offline
          mickym
          Most Active
          wrote on last edited by
          #4

          So hier eine neue Version: v0.3 - ist die eingegebene Textlänge < der config.textwindow wird der Text normal - also nur einmal ausgegeben.

          [
             {
                 "id": "9bf7625128ecafdc",
                 "type": "function",
                 "z": "5289f6ad4bf32e52",
                 "name": "Laufschrift v0.3",
                 "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      02.02.2023\n* Autor:      @mickym\n*/\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) config = msg.config;\ncontext.set(\"config\", config);\n\nvar bActive = context.get(\"active\") || false; //hole aktuellen Status\nbActive = !bActive; //ändere Status\nbActive = bActive && msg.payload ? true : false; //ohne payload deaktiviere immer\n\nnode.status(\n    { \n        fill: \"blue\", \n        shape: bActive ? \"dot\" : \"ring\", \n        text: bActive ? \"aktiv\" : \"inaktiv\" \n    }\n);\n\n\ncontext.set(\"active\",bActive);\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\n\nif (bActive) {\n    context.timer = setInterval(laufschrift, config.interval);\n}\nelse {\n    clearInterval(context.timer);\n}\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2\n\nif (msg.payload.length <= config.textwindow && msg.payload) {\n    node.send(msg);\n    clearInterval(context.timer);\n}\n\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    node.send(msg);\n\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}\n\n",
                 "outputs": 1,
                 "noerr": 0,
                 "initialize": "",
                 "finalize": "",
                 "libs": [],
                 "x": 600,
                 "y": 260,
                 "wires": [
                     [
                         "69b97a0af5eb83ad",
                         "3b908b1849af30ba"
                     ]
                 ],
                 "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nEin erneutes Senden einer `msg.payload` stoppt bzw. inaktiviert die Node wieder. \r\n\r\n## Konfiguration\r\nEine Nachricht, die keine msg.payload enthält (z. Bsp. nur eine `msg.config`) oder eine leere msg.payload stoppt die Node.\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\n\r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
             }
          ]
          

          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 Reply Last reply
          1
          • mickymM Offline
            mickymM Offline
            mickym
            Most Active
            wrote on last edited by mickym
            #5

            So hier nochmal eine verbesserte Version v0.4:

            Lauftext wurd nur noch durch einen leere payload oder ein Text kleiner config.textwindow gestoppt. Alles andere kann nun dynamisch geändert werden, sowohl der Lauftext als auch die Konfiguration.

            Nur die function Node:

            [
                {
                    "id": "9bf7625128ecafdc",
                    "type": "function",
                    "z": "5289f6ad4bf32e52",
                    "name": "Laufschrift v0.4",
                    "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      11.02.2023\n* Autor:      @mickym\n*/\n\nlet timer = context.get(\"timer\") || false;\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (timer && !msg.paylaod) {\n        clearInterval(timer);\n        msg.payload = context.get(\"text\");\n        timer = setInterval(laufschrift, config.interval);\n    }\n}\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        node.send(msg);\n        clearInterval(timer);\n        timer = false;\n    } else {\n        clearInterval(timer);\n        context.set(\"text\",msg.payload);\n        timer = setInterval(laufschrift, config.interval);\n    }\n} else if (msg.payload == \"\") \n{\n    clearInterval(timer);\n    timer = false;\n}\n\ncontext.set(\"timer\", timer);\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: timer ? \"dot\" : \"ring\",\n        text: timer ? \"aktiv\" : \"inaktiv\"\n    }\n);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    node.send(msg);\n\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
                    "outputs": 1,
                    "noerr": 0,
                    "initialize": "",
                    "finalize": "",
                    "libs": [],
                    "x": 600,
                    "y": 280,
                    "wires": [
                        [
                            "69b97a0af5eb83ad",
                            "3b908b1849af30ba"
                        ]
                    ],
                    "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
                }
            ]
            

            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 Reply Last reply
            2
            • A Offline
              A Offline
              alex58765
              wrote on last edited by
              #6

              Hallo myckym,

              vielen Dank für diesen mega Lauftext.

              Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

              Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

              Gruß Alex

              mickymM 2 Replies Last reply
              0
              • A alex58765

                Hallo myckym,

                vielen Dank für diesen mega Lauftext.

                Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

                Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

                Gruß Alex

                mickymM Offline
                mickymM Offline
                mickym
                Most Active
                wrote on last edited by mickym
                #7

                Ok - vielleicht habe ich noch einen Fehler entdeckt - ich hab nun die Version 0.3 mit 0.4 in Version 0.5 kombiniert. damit ist der Code noch etwas einfacher und übersichtlicher.

                Der Fehler ist wahrscheinlich bei Einspeisen einer neuen Konfig aufgetreten, ohne neue Nachricht.

                Also mal Version 0.5.1 versuchen - hoffe damit ist der Fehler weg:

                [
                   {
                       "id": "1cf74aa315093c4e",
                       "type": "function",
                       "z": "5289f6ad4bf32e52",
                       "name": "Laufschrift v0.5.1",
                       "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      17.02.2023\n* Version:    v 0.5.1\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? \"aktiv\" : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
                       "outputs": 1,
                       "noerr": 0,
                       "initialize": "",
                       "finalize": "",
                       "libs": [],
                       "x": 170,
                       "y": 1280,
                       "wires": [
                           []
                       ],
                       "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
                   }
                ]
                
                

                Der Timer wird nun nur noch an einer Stelle gesetzt! - Damit sollten in die irre laufenden Timer der Vergangenheit angehören.

                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 Reply Last reply
                0
                • A alex58765

                  Hallo myckym,

                  vielen Dank für diesen mega Lauftext.

                  Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

                  Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

                  Gruß Alex

                  mickymM Offline
                  mickymM Offline
                  mickym
                  Most Active
                  wrote on last edited by mickym
                  #8

                  @alex58765 sagte in Laufschrift in einem NodeRed Flow erzeugen:

                  Hallo myckym,

                  vielen Dank für diesen mega Lauftext.

                  Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

                  Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

                  Gruß Alex

                  Bitte neue Version 0.5 überprüfen, dass Datum und Version zu Beginn des Codes 0.5 vom 17.2.2023 ist und Rückmeldung, ob es nun funktioniert. Danke!

                  So nochmal testen, war noch ein Buchstabendreher drin und nochmal Vereinfachung der Bedingung für neue Konfigurationsübernahmen.

                  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.

                  A 2 Replies Last reply
                  1
                  • mickymM mickym

                    @alex58765 sagte in Laufschrift in einem NodeRed Flow erzeugen:

                    Hallo myckym,

                    vielen Dank für diesen mega Lauftext.

                    Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

                    Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

                    Gruß Alex

                    Bitte neue Version 0.5 überprüfen, dass Datum und Version zu Beginn des Codes 0.5 vom 17.2.2023 ist und Rückmeldung, ob es nun funktioniert. Danke!

                    So nochmal testen, war noch ein Buchstabendreher drin und nochmal Vereinfachung der Bedingung für neue Konfigurationsübernahmen.

                    A Offline
                    A Offline
                    alex58765
                    wrote on last edited by
                    #9

                    @mickym funktioniert bestens. Vielen herzlichen Dank!!!!

                    1 Reply Last reply
                    0
                    • mickymM mickym

                      @alex58765 sagte in Laufschrift in einem NodeRed Flow erzeugen:

                      Hallo myckym,

                      vielen Dank für diesen mega Lauftext.

                      Ein Hinweis. Ab Version 0.4 ändert sich die Ausgabe nicht mehr automatisch, wenn sich der Payload Text am Eingang ändert.

                      Beispiel bei mir. Titeltext am Eingang wechselt, dann wird weiterhin der Text des vorangehenden Titels angezeigt.

                      Gruß Alex

                      Bitte neue Version 0.5 überprüfen, dass Datum und Version zu Beginn des Codes 0.5 vom 17.2.2023 ist und Rückmeldung, ob es nun funktioniert. Danke!

                      So nochmal testen, war noch ein Buchstabendreher drin und nochmal Vereinfachung der Bedingung für neue Konfigurationsübernahmen.

                      A Offline
                      A Offline
                      alex58765
                      wrote on last edited by
                      #10

                      @mickym eine Frage noch. Ich habe es teilweise so in Verwendung, dass ich den Text Blockweise anzeigen lasse. Das heißt der ich nutze Mode 1 und Offset mit Wert 14. Hast du eine Idee, was man anpassen muss, dass am Ende nicht 14 Leerzeichen angezeigt werden bevor es von vorne wieder losgeht?

                      mickymM 1 Reply Last reply
                      0
                      • A alex58765

                        @mickym eine Frage noch. Ich habe es teilweise so in Verwendung, dass ich den Text Blockweise anzeigen lasse. Das heißt der ich nutze Mode 1 und Offset mit Wert 14. Hast du eine Idee, was man anpassen muss, dass am Ende nicht 14 Leerzeichen angezeigt werden bevor es von vorne wieder losgeht?

                        mickymM Offline
                        mickymM Offline
                        mickym
                        Most Active
                        wrote on last edited by mickym
                        #11

                        @alex58765 Ok - ich habe eine Version 0.6 gemacht - die beinhaltet nun folgende Änderungen.

                        1. In dem Mode 1 und 2 - wird grundsätzlich nicht mehr mit Leerzeichen auf die Textwindowlänge aufgefüllt.
                        2. In dem Mode 1 und 2 - gibts am Textende einen Zyklus Pause. Das ist auf die Schnelle nicht anders machbar, ich finde das persönlich aber einen ganz sinnvollen Effekt.
                        3. Im Status werden jetzt die aktuellen Parameter ausgeben.

                        27a1989e-fd74-41cb-8ee2-e01436484668-image.png

                        Ich werde die Version 0.6 nur noch als einzelne Node ausgeben.

                        [
                           {
                               "id": "5f2b32e2189a673e",
                               "type": "function",
                               "z": "5289f6ad4bf32e52",
                               "name": "Laufschrift v0.6",
                               "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      21.02.2023\n* Version:    v 0.6\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nvar description = config.mode ? (config.mode === 1) ? \"Anfang - Ende\" : \"Hin und Her\" : \"Zirkulierend\";\ndescription = \"Modus: \" + description + \"; Offset: \" + config.offset + \"; Intervall: \" + config.interval + \" ms; Textfenster: \" + config.textwindow;\n\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2  (true = vorwärts, false = rückwärts)\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? description : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            output = text.slice(i, config.textwindow + i);\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n            output = text.slice(i, config.textwindow + i);\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    if (msg.payload) node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
                               "outputs": 1,
                               "noerr": 0,
                               "initialize": "",
                               "finalize": "",
                               "libs": [],
                               "x": 500,
                               "y": 320,
                               "wires": [
                                   [
                                       "69b97a0af5eb83ad",
                                       "3b908b1849af30ba"
                                   ]
                               ],
                               "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
                           }
                        ]
                        

                        EDIT: Hab die Node nochmal geändert - deutsche Sprache - schwere Sprache. 😉

                        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.

                        A 1 Reply Last reply
                        1
                        • mickymM mickym

                          @alex58765 Ok - ich habe eine Version 0.6 gemacht - die beinhaltet nun folgende Änderungen.

                          1. In dem Mode 1 und 2 - wird grundsätzlich nicht mehr mit Leerzeichen auf die Textwindowlänge aufgefüllt.
                          2. In dem Mode 1 und 2 - gibts am Textende einen Zyklus Pause. Das ist auf die Schnelle nicht anders machbar, ich finde das persönlich aber einen ganz sinnvollen Effekt.
                          3. Im Status werden jetzt die aktuellen Parameter ausgeben.

                          27a1989e-fd74-41cb-8ee2-e01436484668-image.png

                          Ich werde die Version 0.6 nur noch als einzelne Node ausgeben.

                          [
                             {
                                 "id": "5f2b32e2189a673e",
                                 "type": "function",
                                 "z": "5289f6ad4bf32e52",
                                 "name": "Laufschrift v0.6",
                                 "func": "/**\n* Zweck:      Erzeugt eine Laufschrift als payload\n* Datum:      21.02.2023\n* Version:    v 0.6\n* Autor:      @mickym\n*/\n\n\ncontext.timer; /* undokumentiert - setze Variable im Node Kontext um \n                    auf Timerinstanz zu zugreifen */\nclearInterval(context.timer);\n\nvar active = context.get(\"active\") || false;\n\n\nvar config = context.get(\"config\") || {\n    \"offset\": 1,        // scrollen um x Zeichen\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes\n}\n\n\nif (msg.config) {\n    config = msg.config;\n    context.set(\"config\", config);\n    if (!msg.payload) {\n        msg.payload = context.get(\"text\");\n    }\n}\n\nvar description = config.mode ? (config.mode === 1) ? \"Anfang - Ende\" : \"Hin und Her\" : \"Zirkulierend\";\ndescription = \"Modus: \" + description + \"; Offset: \" + config.offset + \"; Intervall: \" + config.interval + \" ms; Textfenster: \" + config.textwindow;\n\n\nif (msg.payload) {\n    if (msg.payload.length <= config.textwindow) {\n        active = false;\n        node.send(msg);\n        node.done;\n    } else {\n        active = true;\n        context.set(\"text\",msg.payload);\n        context.timer = setInterval(laufschrift, config.interval);\n    }\n} else active = false;\n\n\nvar text = msg.payload + config.separator;\nvar i = 0; //Positionszähler\nvar d; // für mode 2  (true = vorwärts, false = rückwärts)\n\nnode.status(\n    {\n        fill: \"blue\",\n        shape: active ? \"dot\" : \"ring\",\n        text: active ? description : \"inaktiv\"\n    }\n);\n\ncontext.set(\"active\",active);\n\nfunction laufschrift(){\n   // var len = text.length;\n    var output; \n\n\n\n    switch (config.mode) {\n        case 0:\n            // code block\n            output = text.substr(i, config.textwindow);\n            text = text.substr(config.offset) + text.substr(0, config.offset);\n            break;\n        case 1:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow,\" \");\n            output = text.slice(i, config.textwindow + i);\n            i < text.length ? i+=config.offset : i=0;\n            break;\n        case 2:\n            // code block\n            // output = text.slice(i, config.textwindow + i).padEnd(config.textwindow, \" \");\n            output = text.slice(i, config.textwindow + i);\n            if (i <= 0) d = true;\n            if (i >= text.length) d = false;\n            d ? i += config.offset : i -= config.offset;\n            if (i < 0) i = 0;\n            if (i > text.length) i = text.length;\n            break;\n        default:\n        // code block\n        error(\"invalid mode in config\");\n    }\n\n    /* msg = {  //nur für debug Zwecke\n        \"config\": config,\n        \"payload\": output,\n        \"Textlänge\": output.length,\n        \"Zähler\": i\n    } */\n\n    msg.payload = output;\n    if (msg.payload) node.send(msg);\n    node.done;\n}\n\n/**\n* @param {string} text\n*/\nfunction error(text){\n    node.status(\n        {\n            fill: \"red\",\n            shape: \"dot\",\n            text: \"Error: \" + text\n        }\n    );\n    clearInterval(context.timer);\n    \n    node.error(text, msg);\n}",
                                 "outputs": 1,
                                 "noerr": 0,
                                 "initialize": "",
                                 "finalize": "",
                                 "libs": [],
                                 "x": 500,
                                 "y": 320,
                                 "wires": [
                                     [
                                         "69b97a0af5eb83ad",
                                         "3b908b1849af30ba"
                                     ]
                                 ],
                                 "info": "# Laufschrift erzeugen \r\n\r\nDiese Node erzeugt in konfigurierbaren Textteile, um so eine Laufschrift zu erzeugen.\r\n\r\nGrundsätzlich startet eine `msg.payload` automatisch die Node mit Standardvorgaben. \r\nGestoppt wird er Lauftext durch eine leere oder eine `msg.payload` deren Text kürzer, als `textwindow`ist.\r\n\r\n## Konfiguration\r\nDie Konfigurationsparameter können über eine `msg.config` erstellt werden. Dabei muss das Konfigurations-Objekt vollständig übergeben werden. \r\nDie Konfiguration wird sofort auf den Lauftext angewandt. \r\nDas Konfiguationsobjekt ist direkt im Code wie folgt beschrieben: \r\n\r\n    \r\n    {\"offset\": 1,        // scrollen um x Zeichen\r\n    \"textwindow\": 14,   // Fenster wie groß der Text sein darf\r\n    \"interval\": 1000,   // ms mit der sich der Text bewegt bzw. ausgegeben wird\r\n    \"mode\": 0,          // 0 = Zirkulierend; 1 = Anfang - Ende; 2 = Hin und Her\r\n    \"separator\": \" * \"  // Trennungsstring am Ende des Textes}\r\n\r\nDie passenden Scrollparameter muss man halt selbst herausfinden. Ausserdem belasten natürlich zu kurze Intervalle das System. Voreingestellt sind 1000 ms - was ein Laufschrift sehr ruckelig macht, aber dafür kann man die payload besser debuggen, falls erforderlich."
                             }
                          ]
                          

                          EDIT: Hab die Node nochmal geändert - deutsche Sprache - schwere Sprache. 😉

                          A Offline
                          A Offline
                          alex58765
                          wrote on last edited by
                          #12

                          @mickym Vielen Dank für deine Mühe.

                          Ich hatte noch das PRoblem, dass er immer beim Holen der Titelinformation den Text neugetriggert hat auch wenn sich inhaltlich nichts geändert hat. Das habe ich aber mit einem filter node wegbekommen, dass er bis Wertänderung blockiert.

                          Super Ding!!!

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          Support us

                          ioBroker
                          Community Adapters
                          Donate

                          70

                          Online

                          32.4k

                          Users

                          81.3k

                          Topics

                          1.3m

                          Posts
                          Community
                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                          ioBroker Community 2014-2025
                          logo
                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Recent
                          • Tags
                          • Unread 0
                          • Categories
                          • Unreplied
                          • Popular
                          • GitHub
                          • Docu
                          • Hilfe