Zustandsmanagement
Dashboard 2.0 bietet einen Datenspeicher innerhalb von Node-RED, sodass es möglich ist, Ihre Dashboard-Clients zu aktualisieren und Daten beizubehalten. Dies ist besonders nützlich für Widgets wie ui-chart
, bei denen Sie möglicherweise eine Historie von Datenpunkten beibehalten möchten, oder für Widgets wie ui-text
, bei denen Sie den zuletzt angezeigten Wert beibehalten möchten.
Diese Seite beschreibt die verschiedenen "Stores", die wir eingerichtet haben, und wofür sie verwendet werden.
Sie können sich auch die Ereignisarchitektur ansehen, um einen detaillierteren Einblick zu erhalten, wann diese Stores verwendet werden und wie sie mit dem Rest des Dashboards interagieren.
Client-Seite (Dashboard)
Ein Bild, das die drei clientseitigen Vuex-Stores zeigt, die wir im Dashboard 2.0 haben
Unsere clientseitigen Stores basieren auf VueX. Diese Stores verlieren ihre Daten bei einem Client-Refresh (werden jedoch von den serverseitigen Stores neu befüllt) und werden nur verwendet, um eine zentralisierte, konsistente Ansicht der Daten über die gesamte Vue-Anwendung hinweg zu erhalten, während der Benutzer im Dashboard navigiert.
setup
Store
Dieser speichert nur die Antwort von unserer initialen /_setup
-Anfrage. Dieses Objekt enthält im Kern die SocketIO-Konfiguration, um dem Client zu helfen, sich mit dem Server zu verbinden.
Es ist auch möglich, dass Plugins diesem Objekt (siehe Plugins hinzufügen) zusätzliche Daten hinzufügen, die in der gesamten Anwendung nützlich sein können.
ui
Store
In diesem Store speichern wir die vollständige ui-config, die alle Seiten, Themen, Gruppen und Widgets beschreibt, die auf einem Dashboard gerendert werden sollen.
data
Store
Der clientseitige Datenspeicher ist eine Zuordnung von Widget-IDs zu entweder:
- Der letzten
msg
, die vom Widget empfangen wurde - Einem Array von
msg
-Objekten, das alle bekanntenmsg
-Objekte darstellt, die vom Widget empfangen wurden
In den meisten Fällen benötigt ein Widget nur einen Verweis auf die letzte Nachricht. In einigen Fällen, z.B. ui-chart
, ist die vollständige Historie erforderlich, um eine Historie von Daten darzustellen.
Wenn ein Widget zum ersten Mal geladen wird, senden wir ein widget-load
-Ereignis, das im Standard-onLoad
-Handler versucht, die letzte vom Widget empfangene Nachricht aus dem serverseitigen Datenspeicher abzurufen und im clientseitigen data
Store zu speichern. Mehr darüber erfahren Sie in der Ereignisarchitektur.
Es ist möglich, dass ein Widget auf das zugeordnete msg
-Objekt zugreift, indem es:
<template>
<pre>this.messages[this.id]</pre>
</template>
<script>
export default {
computed: {
...mapState('data', ['messages'])
}
}
</script>
Ein Beispiel für eine Widget.vue-Datei, die den data
Store verwendet, um auf die letzte vom Widget empfangene Nachricht zuzugreifen
Dieser Wert wird auch automatisch aktualisiert, wenn eine neue Nachricht empfangen wird, solange dieses Widget die Standardhandler verwendet, die ebenfalls in der Ereignisarchitektur beschrieben sind.
Server-Seite (Node-RED)
Ein Bild, das die zwei serverseitigen Stores zeigt, die wir im Dashboard 2.0 haben
Unsere serverseitigen Stores pflegen die "Single Source of Truth". Wenn sich ein Dashboard-Client verbindet, werden die zentralisierten Daten an jeden Client gesendet, und die clientseitigen Stores werden mit den relevanten Teilen dieses zentralisierten Stores befüllt.
In unserer serverseitigen Architektur verwenden wir zwei eigenständige Stores:
datastore
: Eine Zuordnung jedes Widgets zur neuestenmsg
, die von einem entsprechenden Knoten im Editor empfangen wurde.statestore
: Ein Store für alle dynamischen Eigenschaften, die auf Widgets gesetzt sind (z.B. Sichtbarkeit oder das Setzen einer Eigenschaft zur Laufzeit). Oft sind diese Werte Überschreibungen der Basis-Konfiguration, die imdatastore
gefunden wird.
Jedes Mal, wenn eine Funktion serverseitig in diese Stores schreiben möchte, wird eine Überprüfung durchgeführt, um sicherzustellen, dass alle bereitgestellten Nachrichten gespeichert werden dürfen. Ein Beispiel dafür, wo dies blockiert würde, ist, wenn msg._client.socketid
angegeben ist und der relevante Knotentyp so eingerichtet ist, dass er auf Socket-Einschränkungen hört (standardmäßig sind dies ui-control
und ui-notification
). In diesem Fall möchten wir diese Daten nicht in unserem zentralisierten Store speichern, da sie nicht für alle Benutzer des Dashboards relevant sind.
Stores importieren
Stores werden in die .js
-Datei eines Knotens importiert mit:
const store = require('<path>/<to>/store.js')
Daten Store
Der serverseitige datastore
ist ein zentralisierter Store für alle Nachrichten, die von Widgets im Editor empfangen werden. Es ist ein einfacher Key-Value-Store, wobei der Schlüssel die ID des Widgets ist und der Wert die vom Widget empfangene Nachricht ist. In einigen Fällen, z.B. ui-chart
, speichern wir anstelle der nur neuesten empfangenen msg
tatsächlich eine Historie.
datastore.save
Wenn ein Widget eine Nachricht empfängt, speichert der Standard-node.on('input')
-Handler die empfangene Nachricht, die der ID des Widgets im Datenspeicher zugeordnet ist, mit:
datastore.save(base, node, msg)
base
: Derui_base
-Knoten, an den der Store angehängt istnode
: Das Node-RED-Knotenobjekt, für das wir den Zustand speichernmsg
: Die Nachricht, die vom Knoten empfangen wurde
Dies speichert die letzte vom Widget empfangene Nachricht, die von demselben Widget beim Laden abgerufen werden kann mit:
datastore.get
Wenn ein Widget initialisiert wird, versucht es, die neueste Nachricht aus dem Datenspeicher abzurufen mit:
datastore.get(node.id)
Dies stellt sicher, dass beim Aktualisieren des Clients oder wenn neue Clients nach der Datengenerierung verbunden werden, der Zustand konsistent dargestellt wird.
datastore.append
Mit .append
können wir mehrere Nachrichten gegen dasselbe Widget speichern, was eine Historie des Zustands darstellt, anstatt nur einen einzigen Punktverweis auf den letzten Wert.
datastore.append(base, node, msg)
base
: Derui_base
-Knoten, an den der Store angehängt istnode
: Das Node-RED-Knotenobjekt, für das wir den Zustand speichernmsg
: Die Nachricht, die vom Knoten empfangen wurde
Dies wird in ui-chart
verwendet, um die Historie von Datenpunkten zu speichern, wobei jeder Datenpunkt eine individuelle Nachricht sein könnte, die vom Widget empfangen wurde.
datastore.clear
Wenn ein Widget aus dem Editor entfernt wird, können wir den Datenspeicher von allen gegen dieses Widget gespeicherten Nachrichten löschen mit:
datastore.clear(node.id)
Dies stellt sicher, dass wir keine veralteten Daten im Datenspeicher haben und dass wir keine Daten gegen Widgets gespeichert haben, die nicht mehr im Editor existieren.
Zustands Store
Der statestore
ist ein zentralisierter Store für alle dynamischen Eigenschaften, die gegen Widgets im Editor gesetzt sind. Dynamische Eigenschaften können durch das Senden von msg.<property>
-Payloads an einen gegebenen Knoten gesetzt werden, z.B. für ui-dropdown
können wir msg.options
senden, um die "Options"-Eigenschaft zur Laufzeit zu überschreiben.
Auf der obersten Ebene ist es key-mapped zu den Widget-IDs, dann hat jedes Widget eine Zuordnung, wobei jeder Schlüssel der Eigenschaftsname ist, der auf den Wert verweist.
statestore.getAll
Für eine gegebene Widget-ID alle gesetzten dynamischen Eigenschaften zurückgeben.
statestore.getAll(node.id)
statestore.getProperty
Für eine gegebene Widget-ID den Wert einer bestimmten Eigenschaft zurückgeben.
statestore.getProperty(node.id, property)
statestore.set
Gegeben eine Widget-ID und Eigenschaft, den zugehörigen Wert in der entsprechenden Zuordnung speichern
statestore.set(base, node, msg, property, value)
base
: Derui_base
-Knoten, an den der Store angehängt istnode
: Das Node-RED-Knotenobjekt, für das wir den Zustand speichernmsg
: Die Nachricht, die vom Knoten empfangen wurdeproperty
: Der zu speichernde Eigenschaftsnamevalue
: Der Wert, der gegen die Eigenschaft gespeichert werden soll
statestore.reset
Alle dynamischen Eigenschaften für ein gegebenes Widget/Node entfernen.
statestore.reset(node.id)