1.0.1 • Published 10 months ago

@bensauer/node-templater v1.0.1

Weekly downloads
-
License
GPL-3
Repository
-
Last release
10 months ago

Node-Templater

Node-Templater ist eine Extension für Node-RED, mit der es möglich ist, Nodes anhand eines Templates zu vervielfachen.

Die Extension ist im Rahmen des Kurses "Ausgewählte Kapitel mobiler Anwendungen" der HTW Berlin im SoSe23 entstanden.

Konzept

Die Idee ist es in einem sog. Template Flow die zu vervielfachenden Nodes anzulegen, sodass diese dann als 'Bauanleitung' für den eigentlichen Flow dienen.

In der Regel sollen die Clones (die vervielfachten Nodes), aber nicht exakt identisch zu dem Original sein. Sondern in einem Attribute abweichen, sodass die Clones zum Beispiel auf anderen Inputs arbeiten.

Zu diesem Zweck können die Properties der Nodes im Template Flow mit einem Placeholder ersetzt werden. Welcher dann bei der Generierung der Clones durch konkrete Werte ersetzt wird. Der Name des Placeholders und die Werte für die Clones werden im sog. Template Node definiert.

Bei der Generierung der Clones werden dann alle Nodes, welche einen Placeholder enthalten, so oft kopiert, wie Werte in der Template-Node angegeben sind. Der Placeholder wird durch den konkreten Wert ersetzt, alle anderen Properties und die Verbindungen bleiben identisch.

Installation

  1. Package im Node-RED user directory installieren:
      npm i @bensauer/node-templater
  2. Node-RED neu starten
  3. Unter Node-RED-Dashboard -> "Manage Pallate" überprüfen, ob die Extension geladen wurde.

Bedienung

Zur Bedienung des Plugins gibt es einen eigenen Tab in der Node-RED Sidebar. Dieser enthält 2 Buttons:

  • "Generate Clones": Generiert für jeden Template-Flow einen neuen Flow, welcher die geklonten Nodes enthält.
  • "Delete Clones": Löscht alle generierten Flows.

Wichtig: 1. Vorm generieren müssen alle änderungen an den Template-Flows deployt sein. 2. Nach dem "Generate" oder "Delete" ausgeführt wurden erscheint eine Meldung, dass es Änderungen gegeben hat und mehrere Optionen, was getan werden kann ("ignore", "merge", ...). Am besten funktioniert es, wenn man keine der Optionen wählt und stattdessen einfach das Browser-Fenster neu lädt (force-reload). Die neuen Flows sind dann bereits deployt.

TLDR; Template-Flows anlegen/bearbeiten -> Deploy -> Generate Clones -> Browser force-reload

Beispiele

Um die Funktionsweise besser zu verstehen, empfiehlt es sich, als Erstes ein Beispiel anzuschauen. Im Ordner examples/ gibt es 3 Beispiele, welche sich ganz einfach in Node-RED importieren lassen. Am besten schaut man sich die Beispiele nacheinander an, um die Funktionsweise der Extension zu verstehen.

Hinweis: Die Beispiele benötigen zusätzlich die Node-RED Extensions "node-red-ping" und "node-red-dashboard"

Example1

Dies ist sozusagen das minimal Setup. Es gibt eine Template-Node, welche als Placeholder-Namen "url" festlegt und als Werte 5 URLs. Dann gibt es eine weitere Comment-Node, welche einfach nur als Name den Placeholder hat.

Nach dem Generieren können wir sehen, dass in dem neuen Flow 5 Comment-Nodes mit der jeweiligen URL als Namen sind.

Wenn man die Liste der URLs ändern möchte, einfach die Template-Node im Template-Flow bearbeiten, deployen und erneut auf "Generate Clones" drücken.

Example2

Hier wird es ein wenig komplexer.

Wir haben wieder die gleiche Template-Node mit den 5 URLs wie in Example1. Doch diesmal zusätzlich eine Inject-Node, welche alle 3 Sekunden ein Signal sendet, eine Ping-Node, welche getriggert vom Inject-Signal ein Ping an -{url}- schickt. Eine Template-Node (nicht die Comment-Node mit Naming Convention aus dieser Extension, sondern eine Node-RED native Node zum ändern von Messages), welche den Output formatiert und schließlich eine Debug-Node die den Ouptput im Debug-Tab ausgibt.

Nach dem Generieren sollte die Ping-Node 5-mal vorhanden sein. Sodass jetzt im Debug-Tab die Ping Zeiten aller 5 URLs gleichzeitig ausgegeben werden.

Hinweis: Sollte nach dem Generieren keine Ausgabe im Debug-Tab zusehen sein, muss die Debug-Node "angeschubst" werden. Dafür einfach die Debug-Node bearbeiten und nochmal deployen.

Example3

Es kann notwendig sein, dass nicht nur eine Node vervielfacht werden soll, sondern eine ganze Kette oder ein Netz an Nodes. Dies ist zum Beispiel der Fall, wenn man UI Elemente verwendeten möchte, da für jedes UI Element auch wirklich eine eigene Node existieren muss.

Wollen wir also Example2 erweitern, sodass der Output nicht nur im Debug-Tab geloggt wird, sondern auch in einem UI-Dashboard visuell angezeigt wird, müssen wir uns einem Workaround behelfen:

Anstelle die zu vervielfachenden Nodes direkt in den Template-Flow zu tun, erstellen wir ein Subflow, in dem alle Nodes, welche vervielfacht werden sollen, auslagern. Um innerhalb des Subflows die Werte des Placeholders verwenden zu können definieren wir im Subflow eine Umgebungsvariable. Welche wir dann mittels der Inject-Node verwenden können. In dem Template-Flow verwenden wir dann den Subflow wie eine normale Node und setzen unter Properties den Placeholder als die Umgebungsvariable.

Ein Subflow kann auch, wie alle anderen Nodes, Aus- und Eingänge haben. Wir nutzen den Eingang, um das Trigger-Signal zu geben und den Ausgang, um die ermittelten Ping Zeiten wieder alle gemeinsam in einem Chart auszugeben.

Nach der Generierung kann man auf dem UI-Dashboard unter {node_red_url}/ui sehen, wie für jede URL ein eigener Zeiger alle 3 Sekunden die Ping Zeit anzeigt. Und danneben alle Ping Zeiten zusammen in einem Chart angezeigt werden.

Technische Details

Tempalate-Flows

  • Müssen den Suffix "template" im Namen haben.
  • Müssen genau eine Template-Node enthalten.
  • Dürfen deaktiviert sein.

Tempalate-Nodes

  • Müssen comment-nodes sein,
  • Die Template-Node muss nach folgendem Muster benannt sein: var:-{x}-wobei x dem Namen des Placeholder entspricht. (In den Properties der anderen Nodes muss der Placeholder dann folgendermaßen angegeben werden: -{x}-)
  • In dem Textfeld der comment-node müssen die, für die Generierung der Clones zu verwendeten, Werte in einer Komma-Separierten-Liste angegeben werden. Bsp.: 1,2,3

Button: "Generate Clones"

Wenn auf den "Generate Clones"-Button gedrückt wird, wird als erstes "Delete Clones" ausgeführt, um die alten generierten Flows zu löschen.

Dann werden via API Call alle Flows mit der "template" Endung geholt. In diesen Flows wird dann nach der Template-Node (Comment-Node mit konkretem Namensschema) gesucht und der Placeholder und die Liste an Werten extrahiert.

Dann werden alle Nodes (bis auf die Template-Node), die sich im Flow befinden kopiert. In den kopierten Nodes wird daraufhin nach Nodes gesucht, in denen der Placeholder vertreten ist.

Von diesen Nodes wird dann für jeden Wert eine Kopie erstellt. Der Placeholder wird durch den Wert ersetzt, die Verbindung zu anderen Nodes wird ebenfalls kopiert und die y-Position wird so verschoben, dass sich die Clones nicht überlappen.

Daraufhin werden noch die Verbindungen anderer Nodes ggf. so angepasst, dass sie auf die Clones zeigen.

Außerdem müssen die IDs aller neuen Nodes noch angepasst werden.

Die Clones und sonstigen Nodes werden dann einem neuen Flow hinzugefügt, dabei werden die Properties des Template-Flows übernommen. Letztendlich wird der neue Flow via API Call in Node-RED eingefügt.

Button: "Delete Clones"

Wenn auf den "löschen"-Button gedrückt wird, werden via API Call alle Flows mit der "generated" Endung gelöscht.

IDs

In Node-RED hat jeder flow/node/subflow/... eine eigene unique ID. Das heißt alle Nodes, welche aus dem Template-Flow in den neuen Flow "kopiert" werden, brauchen eine neue ID.

Eine Möglichkeit wäre es gewesen, Pseudo-Random neue IDs zu generieren. Das hat den Nachteil, dass es nicht mehr nachvollziehbar ist, von welcher Node die Kopie kopiert wurde. Deshalb setzen sich die IDs der neuen Nodes aus den ersten 4 Zeichen der Template-Flow-ID + der Original-ID zusammen. Zusätzlich wird der ID der Clones ihr Index in der Werteliste angehangen. So sind alle IDs unique und nachvollziehbar.

Beispiel:

In einem Template-Flow mit der ID 61c5075ce5905d65 gibt es eine Node (mit Placeholder) mit der ID 6476bb0d7466339a, dann ist die ID des 2. Clones dieser Node: 61c56476bb0d7466339a1 (61c5 + 6476bb0d7466339a + 1).

Placeholder

Placeholder lassen sich überall dort in der Konfiguration einer Node verwenden, wo es möglich ist Zeichenketten einzutragen (z.b. auch in einer Function-Node im js-code). Solange der Placeholder in der JSON-Representation der Node irgendwo als Substring eines values, oder eines Elements eines Arrays auftaucht, wird er korrekt ersetzt. Auch wenn der Placeholder in dem JSON verschachtelt ist, wird er berücksichtigt.

Der Name des Placeholders (also alles zwischen -{ und }-) darf nur aus kleinen Buchstaben (ohne Umlaute) bestehen. Also Regex: [a-z]+

Leider ist es ohne weiteres nicht möglich, den Placeholder in ein Zahlenfeld einzusetzen.

Da die Werte in einer Komma-Separierten-Liste angegeben werden, ist es ebenfalls nicht möglich, dass ein Wert ein Komma enthält.

Codebase

Neben der package.json, README und LICENSE gibt es noch 2 weitere Files:

useless-node.js

Eine Node-RED "extension" wird nur dann vollständig und ohne Warnings geladen, wenn sie eine Node registriert. Zu diesem Zweck wird die useless-node in der package.json angegeben und in useless-node.js registriert. Die Node an sich tut nichts und kann ignoriert werden.

templater-plugin.html

In dieser Datei ist der gesamte relevante Code für die Extension. Leider müssen Node-RED plugins in einer HTML-Datei definiert werden, welche dann aus einem einzigen script-tag besteht, in dem der komplette Javascript Code ist.

Aus diesem Grund ist es auch nicht möglich, den Code auf mehrere Datein aufzuteilen. Um dennoch Lesbarkeit und Übersicht zu Gewehrleisten ist der Code auf viele Funktionen aufgeteilt und ausführlich kommentiert.

Ausblick

Folgende Dinge könnte man angehen, wenn man die Extension weiter entwickeln möchte:

  • Native Template-Node

    Eine eigene Node erstellen, welche die Comment-Node mit Naming Convention ersetzt, um für den Anwender die Nutzung zu einfachen und die Funktion klarer zu machen.

  • PUT verwenden

    Beim erneuten Generieren der Flows die Flows nicht erst via DELETE zu löschen, um sie dann via POST neu anzulegen. Sondern einfach via PUT updaten. Dies könnte den Vorteil haben, dass die "Merge" Funktion (Wenn Node-RED Änderungen erkennt) besser funktioniert.

  • Extension in der Node-RED Flow Library veröffentlichen.

    Die Veröffentlichung in der offiziellen Library beantragen, sodass die Extension direkt über das UI installiert werden kann.

  • Werte nach Pattern generieren

    Statt die Werte in der Template-Node fest anzugeben, könnte man sich eine Syntax überlegen, mit der man z.B. sagt Ganzzahlen von 1 bis 30.

  • **Komma in Werten erlauben

    In der Template-Node die Art der Werteliste flexibel machen, sodass diese z.B. Semikolion-Getrennt ist und damit Kommas in den Werten selber erlaubt.

  • Placeholder in Zahlenfeldern ermöglichen

    In dem man bspw. neben dem Placeholder-String noch eine Ganzzahliege (möglichst lange (damit uniqü)) ID festlegt, welche dann in Zahlenfeldern verwendet werden kann und genauso ersetzt wird. Dann müsste aber zusätzlich noch eine Überprüfung stattfinden, ob alle Werte valide Zahlen sind.

  • Aussagekräftige Fehlermeldungen

    Welche im Node-RED-Dashboard z.B. als PopUp Mitteilung angezeigt werden, um den Nutzer z.B. über Fehlkonfigurationen aufzuklären.

1.0.1

10 months ago

1.0.0

10 months ago