Node-RED

Node-RED Context: Flow-, Global- und persistenter Speicher

Mit dem Node-RED Context merken sich Flows Werte zwischen Nachrichten. Diese Erklärung behandelt die drei Gültigkeitsbereiche, Arbeitsspeicher vs. Dateispeicher, mehrere Speicher, asynchronen Zugriff und ein praktisches Muster für den letzten MQTT-Wert pro Gerät.

Diagramm der Node-RED-Context-Gültigkeitsbereiche mit Node-, Flow- und Global-Speicher, die die letzten MQTT-Werte halten
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Der Node-RED Context ist der eingebaute Schlüssel-Wert-Speicher, mit dem sich ein Flow Werte zwischen Nachrichten merkt, etwa die letzte Temperatur, die ein Sensor gemeldet hat, oder einen Zähler der heutigen Alarme. Diese Erklärung behandelt die drei Context-Gültigkeitsbereiche, wie Context Neustarts übersteht, wie Sie mehrere Speicher gleichzeitig nutzen und ein sauberes Muster, um den letzten MQTT-Wert jedes Geräts zu behalten.

Warum Flows einen Zustand brauchen

Nachrichten in Node-RED sind unabhängig voneinander. Wenn ein mqtt in-Node einen Messwert ausgibt, kennt der nächste Node nur, was in dieser Nachricht steht. Viele reale Aufgaben brauchen mehr:

  • Einen Wert mit dem vorherigen vergleichen, um eine Änderung oder einen Trend zu erkennen.
  • Eine HTTP-Anfrage mit dem jüngsten Messwert beantworten, obwohl gerade keine MQTT-Nachricht eintrifft.
  • Ereignisse pro Schicht zählen oder sich merken, wann ein Alarm begann.
  • Werte aus zwei Topics kombinieren, die zu unterschiedlichen Zeiten eintreffen.

MQTT selbst bietet eine Form von Gedächtnis über retained messages: Der Broker speichert die letzte Nachricht eines Topics und übergibt sie neuen Abonnenten. Das ist ideal für Zustände, die mehrere Clients teilen, und Sie sollten es nutzen. Context ist das ergänzende Werkzeug für Zustände, die innerhalb von Node-RED leben. Wenn Sie unsicher sind, auf welche Seite eine Aufgabe gehört, zieht unsere Erklärung Was ein MQTT-Broker macht die Grenze.

Die drei Gültigkeitsbereiche des Node-RED Context

Gültigkeitsbereich Sichtbar für Typische Verwendung Zugriff in einer Function
Node Nur den Node, der ihn gesetzt hat Totbandfilter, Zähler innerhalb einer Function context.get() / context.set()
Flow Alle Nodes im selben Tab (oder in derselben Subflow-Instanz) Letzte Werte, die mehrere Nodes eines Tabs nutzen flow.get() / flow.set()
Global Jeden Node der Node-RED-Instanz Gemeinsame Konfiguration, Nachschlagetabellen global.get() / global.set()

Wählen Sie den engsten Gültigkeitsbereich, der funktioniert. Ein Wert im Global Context kann von jedem Node in jedem Tab geändert werden, was Fehler schwer nachvollziehbar macht. Node Context ist privat, nichts anderes kann ihn beschädigen.

Sie müssen keinen Code schreiben, um Context zu nutzen. Der Change-Node kann flow.- und global.-Eigenschaften setzen, lesen, verschieben und löschen, und Inject-, Switch- und Template-Nodes können sie lesen. Der Tab Context Data in der Seitenleiste des Editors zeigt die aktuellen Werte jedes Gültigkeitsbereichs und erlaubt es, Einträge beim Debuggen zu aktualisieren oder zu löschen.

Subflows haben eine Besonderheit: Der Flow Context innerhalb eines Subflows gehört zu dieser Instanz. Ein Subflow erreicht den Context seines übergeordneten Flows mit dem Präfix $parent., etwa flow.get("$parent.lastTemp").

Arbeitsspeicher vs. persistenter Context

Standardmäßig wird aller Context im Arbeitsspeicher gehalten. Das ist schnell, verschwindet aber, wenn Node-RED neu startet, der Container neu erstellt wird oder der Host neu bootet. Für alles, was Sie nicht leicht wiederherstellen können, schalten Sie dateibasierten Speicher ein.

Öffnen Sie settings.js (bei einer Standardinstallation in ~/.node-red/, im Docker-Image in /data/) und suchen Sie den Abschnitt contextStorage:

// settings.js
module.exports = {
    // ...
    contextStorage: {
        default: { module: "memory" },
        file:    { module: "localfilesystem" }
    },
    // ...
};

Starten Sie Node-RED neu. Sie haben nun zwei Speicher: default, der im Arbeitsspeicher bleibt, und file, der JSON-Dateien im Ordner context/ Ihres Benutzerverzeichnisses schreibt. Nodes wählen einen Speicher explizit:

flow.set("lastReading", msg.payload, "file");   // persistent
flow.set("scratch", 42);                        // Arbeitsspeicher (Standardspeicher)
const last = flow.get("lastReading", "file");

Im Change-Node und in anderen Editoren erscheint neben flow.- und global.-Feldern eine kleine Speicherauswahl, sobald Sie mehr als einen Speicher haben.

Soll alles persistent sein, setzen Sie stattdessen default: { module: "localfilesystem" }. Beachten Sie, wie der Dateispeicher arbeitet: Werte werden im Arbeitsspeicher zwischengespeichert und in einem Intervall auf die Festplatte geschrieben, standardmäßig alle 30 Sekunden, gesteuert über die Option flushInterval. Ein harter Absturz kann die Änderungen der letzten Sekunden verlieren. Für letzte Werte und Zähler ist das in Ordnung, aber Context ist keine Datenbank. Für historische Daten schreiben Sie in einen Zeitreihenspeicher wie InfluxDB, wie in unserem Node-RED-InfluxDB-Leitfaden gezeigt.

Beachten Sie auch, dass nur JSON-serialisierbare Werte zuverlässig persistiert werden. Funktionen, Timer und Klasseninstanzen kommen nach einem Neustart nicht intakt zurück; speichern Sie daher einfache Objekte, Zahlen und Zeichenketten.

Synchroner und asynchroner Zugriff

Mit den Speichern memory und localfilesystem arbeiten get und set wie oben gezeigt synchron. Manche Drittanbieter-Speicher, etwa Redis-basierte Module, sind asynchron und erfordern Callbacks:

flow.get("count", "redis", (err, count) => {
    if (err) { node.error(err, msg); return; }
    count = (count || 0) + 1;
    flow.set("count", count, "redis", (err) => {
        if (err) { node.error(err, msg); return; }
        msg.payload = count;
        node.send(msg);
        node.done();
    });
});

Code von Anfang an mit Callbacks zu schreiben kostet wenig und bedeutet, dass Sie den Speicher später wechseln können, ohne jede Function neu zu schreiben. Beachten Sie, dass ein get gefolgt von einem set nicht atomar ist. Bei sehr hohen Nachrichtenraten auf einem asynchronen Speicher können zwei Nachrichten denselben alten Zählerstand lesen. Halten Sie Zähler im Node Context, wo nur ein Node sie schreibt, oder bündeln Sie Aktualisierungen.

Sie können auch mehrere Schlüssel auf einmal lesen und schreiben, indem Sie Arrays übergeben: flow.get(["a", "b"]) liefert ein Array von Werten.

Muster: Den letzten MQTT-Wert pro Gerät behalten

Eine häufige Aufgabe für den Node-RED Context ist eine Live-Tabelle der zuletzt bekannten Werte: ein Eintrag pro Gerät, bei jeder Nachricht aktualisiert, von überall im Flow lesbar. Publizieren Sie einige Testdaten an den Öffentlichen MQTT-Broker von ConnectMQ und ersetzen Sie c8d1 durch Ihre eigene Zufallszeichenfolge (er ist nur für Tests gedacht, alle Daten sind öffentlich lesbar):

mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
  -t "connectmq/demo/c8d1/boiler/tank1/telemetry" -m '{"level": 71.5, "temp": 63.2}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
  -t "connectmq/demo/c8d1/boiler/pump2/telemetry" -m '{"rpm": 1450, "temp": 41.0}'

Abonnieren Sie in Node-RED mit einem mqtt in-Node auf connectmq/demo/c8d1/+/+/telemetry, Ausgabe auf geparstes JSON gesetzt, und verbinden Sie ihn mit dieser Function:

// Function "store latest"
const parts = msg.topic.split("/");
const deviceId = parts[3] + "/" + parts[4];       // z. B. "boiler/tank1"

const latest = flow.get("latest", "file") || {};
latest[deviceId] = {
    values: msg.payload,
    ts: Date.now()
};
flow.set("latest", latest, "file");

node.status({ text: Object.keys(latest).length + " devices" });
return null;

Nun kann jeder Node im Tab die Tabelle lesen. Ein http in-Node auf GET /latest, gefolgt von dieser Function und einem http response-Node, ergibt eine kleine API:

// Function "serve latest"
const latest = flow.get("latest", "file") || {};
const staleMs = 5 * 60 * 1000;
const now = Date.now();

msg.payload = Object.entries(latest).map(([id, v]) => ({
    device: id,
    values: v.values,
    ageSeconds: Math.round((now - v.ts) / 1000),
    stale: now - v.ts > staleMs
}));
return msg;

Das Flag stale ist das entscheidende Detail. Eine Tabelle letzter Werte, die nie abläuft, zeigt munter den Messwert eines Geräts, das gestern ausgefallen ist. Speichern Sie immer einen Zeitstempel zusammen mit dem Wert.

In industriellen Anwendungen lohnt es sich, die Geräteschlüssel an der ISA-95-Hierarchie auszurichten, etwa werk-muenchen/montage/linie-1/zelle-2. Dann spiegelt die Context-Tabelle dieselbe Struktur wider wie der Unified Namespace (UNS) auf dem Broker, und Werte lassen sich eindeutig einer Anlage zuordnen.

Checkliste: Best Practices für den Node-RED Context

  1. Verwenden Sie den engsten Gültigkeitsbereich: Node, dann Flow, dann Global.
  2. Aktivieren Sie einen Dateispeicher und wählen Sie ihn explizit für Werte, die Sie nicht wiederherstellen können.
  3. Speichern Sie Zeitstempel zusammen mit den Werten, damit Sie veraltete Daten erkennen.
  4. Vermeiden Sie riesige Objekte; große Context-Einträge verlangsamen jeden Flush und jede Aktualisierung der Seitenleiste.
  5. Versehen Sie globale Schlüssel mit einem Präfix nach Zweck, etwa cfg_ für Konfiguration und cache_ für Nachschlagedaten.
  6. Speichern Sie keine Geheimnisse im Context. Zugangsdaten gehören in Config-Nodes und Umgebungsvariablen.
  7. Nutzen Sie retained MQTT-Nachrichten für Zustände, die andere Clients brauchen, und Context für Zustände, die nur Node-RED braucht.
  8. Sichern Sie den Ordner context/ zusammen mit Ihren Flows. Betreiben Sie Node-RED in Containern? Unser Node-RED-Docker-Leitfaden zeigt, wie Sie /data auf einem persistenten Volume halten.

Die offizielle Context-Dokumentation behandelt die Speicher-API und die Konfigurationsoptionen vollständig. Für die Code-Seite dieser Muster siehe unseren Leitfaden zum Node-RED Function-Node, und für das größere Bild der Anbindung von Flows an Broker das Node-RED-MQTT-Tutorial.

Node-RED Context mit ConnectMQ kombinieren

Context bewahrt das Gedächtnis von Node-RED; der Broker das aller anderen. ConnectMQ ist ein vollständig verwalteter MQTT-Broker mit retained messages, MQTT-5-Session-Ablauf und TLS, sodass Geräte, Dashboards und Node-RED konsistente zuletzt bekannte Werte sehen. Das Portal ergänzt einen Live-Topic-Explorer und Schwellwert-Alarmregeln für schnelle Prüfungen, ohne einen Flow zu bauen. Starten Sie mit dem kostenlosen Serverless-Plan unter app.connectmq.com, ohne Kreditkarte, und verbinden Sie Node-RED mit dem generierten Benutzernamen, Passwort und der Client-ID.

Häufig gestellte Fragen

Was ist der Unterschied zwischen Flow und Global Context in Node-RED?

Flow Context teilen nur die Nodes im selben Tab, Global Context dagegen alle Nodes der Node-RED-Instanz. Verwenden Sie Flow Context, sofern nicht wirklich mehrere Tabs denselben Wert brauchen.

Wie übersteht der Node-RED Context einen Neustart?

Fügen Sie in settings.js unter contextStorage einen localfilesystem-Speicher hinzu, starten Sie Node-RED neu und schreiben Sie in diesen Speicher, zum Beispiel flow.set("key", value, "file").

Wo speichert Node-RED persistente Context-Dateien?

In einem Ordner context im Node-RED-Benutzerverzeichnis, meist ~/.node-red/context oder in Docker /data/context, gegliedert nach Gültigkeitsbereich.

Sollte ich für letzte Werte Context oder retained MQTT-Nachrichten verwenden?

Verwenden Sie retained messages, wenn andere MQTT-Clients den letzten Wert brauchen, und Context, wenn nur Node-RED ihn braucht, etwa um eine API zu bedienen oder Messwerte zu vergleichen. Viele Flows nutzen beides.

Verwandte Artikel

Node-RED als OPC-UA-Client zu MQTT mit ISA-95-Topics

Mit node-red-contrib-opcua OPC-UA-Variablen auf einer SPS oder einem Simulationsserver abonnieren, Node-IDs auf MQTT-Topics im ISA-95-Stil abbilden und Werte mit Qualität und Zeitstempel publizieren.

9 Min. Lesezeit

Node-RED Diagramm-Verlauf: MQTT-Chartdaten über Neustarts hinweg behalten

Dashboard-Diagramme vergessen alles, wenn Node-RED neu startet. Dieser Leitfaden zeigt zwei zuverlässige Wege, den Node-RED Diagramm-Verlauf für MQTT-Daten zu behalten: dateibasierten Context-Speicher und eine kleine SQLite-Tabelle, beide beim Start in Dashboard 2.0 zurückgespielt.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.