Skip to content

Technik Blog

IoT, Smart Home & Mikrocontroller einfach erklärt

Menu
  • Smarthome
  • Gartenautomation
  • Mikrocontroller
    • Arduino
    • ESP32 & Co.
    • Calliope Mini
    • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
Menu

Node-RED Function Node erklärt: JavaScript und komplexe Logik im Flow

Veröffentlicht am 2. November 202631. Oktober 2026 von Stefan Draeger

Ein Flow soll Nachrichten auf verschiedene Ausgänge verteilen, Systeminformationen abfragen oder auf das Ergebnis eines Dateizugriffs warten. Mit der Node-RED Function Node lässt sich dafür eigener JavaScript-Code direkt in die Verarbeitung einbauen. Dabei kommt es vor allem darauf an, wie der Code mit den Nachrichten und der Node-RED-Laufzeit zusammenarbeitet.

In diesem Beitrag zeige ich dir die Rückgabe über mehrere Ausgänge, das Einbinden der Node.js-Module os und fs sowie das asynchrone Senden mit node.send(). Zum Einstieg vergleichen wir eine einfache Berechnung mit der Change Node. JavaScript-Grundkenntnisse setze ich dabei voraus.

Node-RED Function Node: Weniger Nodes, mehr Möglichkeiten mit JavaScript
Dieses Video auf YouTube ansehen.

Inhaltsverzeichnis

  • Was macht die Function Node in Node-RED?
  • Der erste Flow: Inject, Function und Debug
  • Change oder Function: denselben Sensorwert auf zwei Wegen verändern
    • Berechnung mit der Change Node
    • Dieselbe Berechnung mit der Function Node
  • Mehrere Ausgänge in der Function Node verwenden
    • Variante 1: Module direkt in der Function Node zuordnen
  • os und fs als Node.js-Module einbinden
    • Variante 2: Module zentral über functionGlobalContext bereitstellen
  • Systeminformationen mit os abfragen
  • Mit fs Dateien asynchron lesen
  • Verzögerte Ereignisse mit node.send() ausgeben
  • Zustand und Lebenszyklus der Function Node
  • Fazit

Was macht die Function Node in Node-RED?

Node-RED bringt für viele Aufgaben bereits passende Nodes mit. Werte lassen sich verändern, Nachrichten nach Bedingungen aufteilen und Daten für die nächste Verarbeitung vorbereiten. Eine Function Node ergänzt diese Möglichkeiten um eigenen JavaScript-Code.

Der Code im Reiter Funktion wird für jede eingehende Nachricht ausgeführt. Über msg greifen wir auf diese Nachricht zu. Anschließend geben wir sie mit return msg; weiter.

Für einfache Aufgaben lohnt sich allerdings ein Blick auf die anderen Nodes:

AufgabePassende Node
Eine Eigenschaft setzen, verschieben oder löschenChange
Nachrichten anhand einer Bedingung auf Ausgänge verteilenSwitch
Mehrere Berechnungen und Bedingungen mit JavaScript kombinierenFunction

Die Function Node ist deshalb nicht automatisch die bessere Wahl. Eine einzelne Temperaturprüfung bleibt mit einer Switch Node oft gut nachvollziehbar. Interessant wird JavaScript vor allem dann, wenn mehrere Berechnungen und Entscheidungen zusammengehören. Das lässt sich bereits an einem kleinen Sensorbeispiel zeigen.

Der erste Flow: Inject, Function und Debug

Für den Einstieg genügt ein Flow aus Inject, Function und Debug. Die Inject Node liefert die Zahl 21.5 in msg.payload. Im Reiter Funktion addieren wir einen beispielhaften Korrekturwert von 0,5 °C:

msg.payload = msg.payload + 0.5;
return msg;

Mit return msg; gibt die Function Node die veränderte Nachricht weiter. Nach dem Übernehmen der Änderungen und dem Auslösen der Inject Node ist in der Debug Node die Zahl 22 zu erwarten.

Change oder Function: denselben Sensorwert auf zwei Wegen verändern

Braucht es für diese Berechnung überhaupt JavaScript? Zum Vergleich sendet eine Inject Node dieselbe Nachricht gleichzeitig an eine Change Node und eine Function Node. Beide Zweige enden an derselben Debug Node.

Node-RED Flow mit Debug Ausgaben aus Zweig mit Change Node und Function Node
Node-RED Flow mit Debug Ausgaben aus Zweig mit Change Node und Function Node

Für den direkten Vergleich liegt der Messwert in msg.sensor_value. Die Payload enthält eine Kennzeichnung des jeweiligen Zweigs. In den folgenden Beispielen verwenden wir wieder msg.payload für die Nutzdaten.

Die Inject Node setzt msg.sensor_value auf die Zahl 21.5 und msg.payload auf aus der Change Node.

Berechnung mit der Change Node

Die Change Node setzt msg.sensor_value auf das Ergebnis des folgenden JSONata-Ausdrucks:

sensor_value + 0.5

In der Change Node ist dafür JSONata als Ausdruckstyp hinterlegt. Der Ausdruck greift direkt über sensor_value auf den Messwert zu; ein vorangestelltes msg. wird hier nicht benötigt. Die Payload mit dem Text aus der Change Node bleibt erhalten.

Change Node zum incrementieren eines Sensorwertes in Node-RED
Change Node zum incrementieren eines Sensorwertes in Node-RED

Dieselbe Berechnung mit der Function Node

Im Reiter Funktion steht folgender JavaScript-Code:

msg.sensor_value = msg.sensor_value + 0.5;
msg.payload = "aus der Function Node";
return msg;

Die erste Zeile erhöht den Sensorwert um 0.5. Anschließend wird die Payload zur Kennzeichnung dieses Zweigs geändert und die Nachricht weitergegeben.

einfacher Javascript Code in der Function Node
einfacher Javascript Code in der Function Node

Nach dem Auslösen erhält die Debug Node zwei Nachrichten mit sensor_value: 22. Eine trägt die Payload aus der Change Node, die andere aus der Function Node. Da die gesamte Nachricht angezeigt wird, sind Messwert und Kennzeichnung gemeinsam sichtbar. Die Reihenfolge der Ausgaben ist für den Vergleich unerheblich.

Für die einfache Addition genügt die Change Node. Die folgenden Beispiele zeigen, was die Function Node darüber hinaus bietet: mehrere Ausgänge, eingebundene Node.js-Module und asynchrone Verarbeitung.

Den vollständigen Vergleichsflow kannst du über die Importfunktion des Node-RED-Editors einfügen. Er enthält die Testwerte und benötigt keine zusätzliche Hardware.

Vergleichsflow mit Change und Function als JSON anzeigen
[
    {
        "id": "312e13b9e367f556",
        "type": "tab",
        "label": "Flow 3",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "b483af58d0c2346b",
        "type": "inject",
        "z": "312e13b9e367f556",
        "name": "Beispiel - Sensorwert",
        "props": [
            {
                "p": "sensor_value",
                "v": "21.5",
                "vt": "num"
            },
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "aus der Change Node",
        "payloadType": "str",
        "x": 140,
        "y": 60,
        "wires": [
            [
                "b33de94e434b6c37",
                "e3344f275ca031b1"
            ]
        ]
    },
    {
        "id": "b33de94e434b6c37",
        "type": "change",
        "z": "312e13b9e367f556",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "sensor_value",
                "pt": "msg",
                "to": "sensor_value + 0.5",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 510,
        "y": 60,
        "wires": [
            [
                "54097cef99de77c6"
            ]
        ]
    },
    {
        "id": "54097cef99de77c6",
        "type": "debug",
        "z": "312e13b9e367f556",
        "name": "Ausgabe des geänderten Sensorwertes",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 860,
        "y": 60,
        "wires": []
    },
    {
        "id": "e3344f275ca031b1",
        "type": "function",
        "z": "312e13b9e367f556",
        "name": "Increment des Sensorwertes",
        "func": "msg.sensor_value = msg.sensor_value + 0.5;\nmsg.payload = \"aus der Function Node\";\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 500,
        "y": 140,
        "wires": [
            [
                "54097cef99de77c6"
            ]
        ]
    }
]

Mehrere Ausgänge in der Function Node verwenden

Die Function Node erhält eine Nachricht als msg. Mit return msg; wird sie weitergegeben, mit return null; endet ihre Verarbeitung an dieser Node. Andere Flow-Zweige laufen davon unabhängig weiter. Wer nur die Payload ändern möchte, sollte die bestehende Nachricht weiterverwenden: So bleiben etwa msg.topic oder die für HTTP-Flows wichtigen Eigenschaften msg.req und msg.res erhalten.

Variante 1: Module direkt in der Function Node zuordnen

Für getrennte Verarbeitungswege lässt sich die Anzahl der Ausgänge im Bearbeitungsdialog auf zwei oder mehr erhöhen.

Node-RED definieren der Anzahl der Ausgänge einer Function Node
Node-RED definieren der Anzahl der Ausgänge einer Function Node

Jeder Ausgang wird mit einer eigenen Debug Node verbunden. Die Inject Node liefert für dieses Beispiel eine Zahl in msg.payload:

if (msg.payload > 25) {
    return [null, msg];
}
return [msg, null];

Werte bis einschließlich 25 gehen an Ausgang 1, höhere Werte an Ausgang 2. Die Position im Array ordnet die Nachricht dem Ausgang zu; null lässt ihn frei. Das Array allein erzeugt keine zusätzlichen Anschlüsse: Die zwei Ausgänge müssen auch im Dialog eingestellt sein.

Mehrere Nachrichten an einem Ausgang werden als inneres Array übergeben.

Node-RED Flow mit mehreren Payload Events
Node-RED Flow mit mehreren Payload Events

Hier erhält Ausgang 1 zwei Nachrichten nacheinander, während Ausgang 2 frei bleibt:

return [[
    { payload: "erste Nachricht" },
    { payload: "zweite Nachricht" }
], null];

os und fs als Node.js-Module einbinden

Ein direktes require("os") oder require("fs") steht im Reiter Funktion nicht zur Verfügung. Die Function Node läuft in einer eigenen Ausführungsumgebung. Für die Bereitstellung der Module gibt es zwei alternative Wege: die Zuordnung direkt in der Node oder eine zentrale Freigabe in der settings.js. Für die Beispiele genügt einer dieser Wege.

Die Zuordnung direkt in der Function Node wird über functionExternalModules freigeschaltet. Die Einstellung gehört in das vorhandene exportierte Konfigurationsobjekt der verwendeten settings.js. Eine Änderung wird nach einem Neustart von Node-RED wirksam:

functionExternalModules: true,
Node-RED settings-js erlauben das Module direkt geladen werden können
Node-RED settings-js erlauben das Module direkt geladen werden können

Im Bearbeitungsdialog lassen sich anschließend Module und die zugehörigen Variablennamen festlegen. Für unsere Beispiele wird das Modul os der Variablen os und das Modul fs der Variablen fs zugeordnet. Beide gehören zu Node.js; eine zusätzliche npm-Installation ist dafür nicht nötig. Bei Drittanbieterpaketen sind dagegen die Freigaben und Installationsregeln der eigenen Node-RED-Konfiguration zu beachten.

Modul os in der Function Node im Reiter Setup geladen
Modul os in der Function Node im Reiter Setup geladen

Variante 2: Module zentral über functionGlobalContext bereitstellen

Alternativ werden die Module zentral in der vorhandenen Eigenschaft functionGlobalContext der settings.js ergänzt. Andere bereits vorhandene Einträge bleiben erhalten:

functionGlobalContext: {
    osModule: require("os"),
    fsModule: require("fs")
},
Node-RED settings-js vordefinierte globale Variablen setzen
Node-RED settings-js vordefinierte globale Variablen setzen

Nach dem Neustart greift die Function Node bei dieser Variante über den globalen Context darauf zu. Die folgenden Zeilen sind nur für diese zentrale Bereitstellung nötig; bei der Zuordnung im Dialog stehen die Variablen bereits bereit:

const os = global.get("osModule");
const fs = global.get("fsModule");

Systeminformationen mit os abfragen

Mit dem eingebundenen os-Modul lassen sich Informationen über das System abfragen, auf dem Node-RED läuft. Dafür verwenden wir einen separaten kleinen Flow:

einfacher Flow in Node-RED zum ermitteln der Serverdaten via Function Node und Modul os
einfacher Flow in Node-RED zum ermitteln der Serverdaten via Function Node und Modul os

Für einen separaten Test reicht eine Inject Node, die eine Function Node auslöst. Diese ersetzt die Payload durch aktuelle Systemdaten:

msg.payload = {
    hostname: os.hostname(),
    plattform: os.platform(),
    laufzeitSekunden: Math.floor(os.uptime())
};
return msg;

Die nachgeschaltete Debug Node zeigt Hostname, Plattform und Betriebssystemlaufzeit. Die Werte stammen von dem Rechner, auf dem Node-RED läuft, nicht vom Browser-Rechner. os.uptime() beschreibt dabei die Laufzeit des Betriebssystems und nicht die Laufzeit des Flows.

Mit fs Dateien asynchron lesen

Bei einem Dateizugriff steht das Ergebnis erst später fest. Statt synchron zu warten, lesen wir mit fs.readFile() im Hintergrund. Wenn der Callback aufgerufen wird, gibt node.send() die Nachricht weiter. node.done() meldet der Node-RED-Laufzeit anschließend, dass die Verarbeitung dieser Eingangsnachricht abgeschlossen ist.

Das folgende Beispiel liest unter Fedora die Datei /etc/hostname. Voraussetzung ist das zuvor eingebundene fs-Modul. Die Function Node besitzt zwei Ausgänge: Ausgang 1 für den Dateiinhalt und Ausgang 2 für Fehler. Beide lassen sich zum Testen mit Debug Nodes verbinden:

fs.readFile("/etc/hostname", "utf8", (err, inhalt) => {
    if (err) {
        msg.payload = { datei: "/etc/hostname", fehler: err.message };
        node.send([null, msg]);
        node.done();
        return;
    }
    msg.payload = inhalt.trim();
    node.send([msg, null]);
    node.done();
});
return;

Der erfolgreiche Lesevorgang liefert den Dateiinhalt an Ausgang 1. Fehlt die Datei oder fehlen Leserechte, landet die Fehlermeldung an Ausgang 2. Der Pfad bezieht sich auf das Dateisystem der Node-RED-Laufzeit; der Dateizugriff erfolgt mit den Rechten des Benutzers, unter dem der Service läuft.

Die Rückgabe am Ende sendet hier keine Nachricht. Erst der Callback kennt das Ergebnis und verschickt es mit node.send(). Ein return msg; innerhalb des Callbacks würde nur diesen Callback beenden. Ein zusätzliches return msg; außerhalb könnte dagegen die ursprüngliche Nachricht vorzeitig ausgeben. node.send() unterstützt dieselbe Ausgangszuordnung per Array wie die synchrone Rückgabe.

In diesem Beispiel werden Fehler bewusst über Ausgang 2 behandelt. Soll stattdessen eine Catch Node reagieren, kann der Fehlerpfad node.error(err, msg); aufrufen und die Verarbeitung anschließend mit node.done(); abschließen. Für einfache Dateioperationen bleibt eine vorhandene Datei-Node ebenfalls eine passende Lösung.

Verzögerte Ereignisse mit node.send() ausgeben

Ein Timer zeigt dasselbe Prinzip ohne zusätzliches Modul. Jede eingehende Nachricht löst eine Ausgabe aus, die eine Sekunde später am einzigen Ausgang erscheint:

setTimeout(() => {
    msg.payload = "Verzögertes Ereignis";
    node.send(msg);
    node.done();
}, 1000);
return;
verzögertes senden von Nachrichten mit einer Function Node in Node-RED

node.send() erzeugt selbst keine Asynchronität. Der Timer bestimmt den Zeitpunkt, die Methode übernimmt die Ausgabe. Jede Eingangsnachricht startet in diesem Beispiel einen eigenen Timer. Bei zwei konfigurierten Ausgängen könnte der Callback beispielsweise mit node.send([null, msg]); gezielt Ausgang 2 ansprechen. Noch offene Timer der Function Node werden beim Stoppen oder erneuten Bereitstellen aufgeräumt.

Zustand und Lebenszyklus der Function Node

Nicht jeder Wert gehört in die aktuelle Nachricht. Für Daten, die zwischen mehreren Aufrufen erhalten bleiben sollen, stehen context für die einzelne Node, flow für den Flow-Tab und global für die gesamte Laufzeit zur Verfügung. Ob diese Werte einen Neustart überstehen, hängt vom eingerichteten Context-Speicher ab.

Vorbereitungen für die Verarbeitung gehören in den Reiter Start. Im Reiter Stopp werden selbst angelegte Verbindungen oder Ereignis-Listener wieder geschlossen beziehungsweise entfernt. Das verhindert, dass nach einem erneuten Bereitstellen noch alte Verbindungen bestehen.

Für die Fehlersuche helfen Meldungen mit node.warn() und node.error(). Wie sich diese gezielt einsetzen lassen, beschreibe ich im Beitrag Node-RED Debugging ohne Debug Node: Meldungen direkt aus der Function Node. Über node.status() lässt sich außerdem ein kurzer Zustand direkt unter der Node anzeigen.

Fazit

Die Function Node ergänzt einen Flow um eigene Verarbeitung, mehrere Ausgabewege und den Zugriff auf bereitgestellte Node.js-Module. Für sofort verfügbare Ergebnisse genügt return. Bei einem später eintreffenden Ergebnis übernehmen node.send() und node.done() die Ausgabe und den Abschluss.

Der Vergleich mit der Change Node bleibt dabei hilfreich: Eine einfache Wertänderung benötigt noch keinen eigenen Code. Mit Modulzugriffen oder mehreren zusammengehörenden Verarbeitungsschritten kann eine Function Node die passende Ergänzung sein. Entscheidend ist, ob der konkrete Flow damit nachvollziehbar bleibt.

Weiterführende Dokumentation: Function Nodes in Node-RED, Node.js-Modul os und Node.js-Modul fs.

Transparenzhinweis: Dieser Beitrag wurde mit Unterstützung künstlicher Intelligenz erstellt und redaktionell geprüft. Mehr zur Nutzung von KI

Letzte Aktualisierung am: 31. Oktober 2026

Foto von Stefan Draeger
Über den Autor

Stefan Draeger — Entwickler & Tech-Blogger

Ich zeige praxisnah, wie du Projekte mit Arduino, ESP32 und Smarthome-Komponenten umsetzt – Schritt für Schritt, mit Code und Schaltplänen.

Mehr Artikel von Stefan →

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Kategorien

Kontakt & Hilfe

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden? Erstelle einfach ein Support-Ticket.

Support-Ticket erstellen
Keine Beiträge verpassen

Newsletter abonnieren

Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32, Smarthome und IoT direkt in dein Postfach.

Newsletter abonnieren
Videos & Tutorials

Draeger-IT auf YouTube

Entdecke meine Videos zu Arduino, ESP32, Raspberry Pi, Smarthome und spannenden Elektronikprojekten – mit Tutorials, Tests und Praxisbeispielen.

YouTube-Kanal besuchen
Freiwillige Unterstützung

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee. So hilfst du dabei, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

Auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kostenlose Online-Werkzeuge

Tools

Praktische Generatoren, Rechner und Hilfsmittel für deine Elektronik- und Entwicklungsprojekte.

Generatoren & Konverter

  • QR-Code Generator
  • Passwort Generator
  • PNG zu WebP konvertieren
  • Bilder online komprimieren
  • Code online formatieren

Rechner & Tabellen

  • Unix-Zeitstempel-Rechner
  • ASCII-Tabelle
  • ASCII Code umrechnen – Text, Dezimal, Hex & Binär
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner

LED-Matrix

  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix Generator
Kontakt

Anschrift & Kontaktdaten

Stefan Draeger

Königsberger Str. 13
38364 Schöningen

Telefon 01556 5432686

E-Mail info@draeger-it.blog

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com
Social Media

Folge mir auf

Weitere Projekte, Videos und Neuigkeiten findest du auch auf meinen Social-Media-Kanälen.

  • f Facebook
  • in LinkedIn
  • ▶ YouTube
  • ♪ TikTok
  • P Pinterest
  • ◎ Instagram
Rechtliche Informationen

Rechtliches

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
  • KI-Transparenz bei draeger-it.blog
©2026 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
  • Optionen verwalten
  • Dienste verwalten
  • Verwalten von {vendor_count}-Lieferanten
  • Lese mehr über diese Zwecke
Einstellungen anzeigen
  • {title}
  • {title}
  • {title}