Erstellen von Drittanbieter-Widgets Added In: v0.8.0
Ein einzelnes Widget besteht aus zwei Hauptteilen:
- Ein Node-RED-Knoten, der in der Palette des Node-RED-Editors erscheint
.vue
und clientseitiger Code, der das Widget in ein Dashboard rendert
Sie können unsere Sammlung von Kern-Widgets hier erkunden. Wenn Sie eine Idee für ein Widget haben, das Sie in Dashboard 2.0 erstellen möchten, sind wir offen für Pull-Anfragen, und Sie können mehr in unserem Leitfaden Hinzufügen von Kern-Widgets lesen.
Wir erkennen jedoch auch an, dass es viele Gelegenheiten gibt, bei denen ein eigenständiges Repository/Paket besser funktioniert, wie es in Dashboard 1.0 sehr beliebt war.
Empfohlene Lektüre
Auf der linken Seite der Navigation finden Sie einen Abschnitt "Nützliche Anleitungen". Wir empfehlen, sich diese anzusehen, da sie einen guten Überblick über die Struktur der Dashboard 2.0-Codebasis und einige der zugrunde liegenden architektonischen Prinzipien geben, auf denen es aufgebaut ist.
Insbesondere werden die folgenden empfohlen:
Wie Widgets geladen werden
Dashboard 2.0 basiert auf VueJS, und daher müssen alle Widgets einer Vue-Komponente zugeordnet werden. Der Prozess funktioniert wie folgt:
- Der Dashboard 2.0-Client verbindet sich mit Node-RED
- Node-RED sendet ein
ui-config
-Objekt, das Details zu allen Seiten, Themen, Gruppen und Widgets enthält - Im Ereignishandler durchlaufen wir alle Widgets, die in der
ui-config
gefunden wurden:- Wenn der Widget-
type
mit einer Kernkomponente übereinstimmt, ordnen wir es dieser Komponente zu - Wenn das Widget ein Drittanbieter-Widget ist, laden wir die relevante
.umd.js
-Datei, die vom/resources
-Ordner des Widgets bereitgestellt wird.
- Wenn der Widget-
- Dashboard 2.0 lädt das relevante Layout (z.B. Grid, Fixed oder Notebook) abhängig von der aktiven URL/Seite.
- Innerhalb dieses Layout-Managers durchlaufen wir die Widgets und rendern ihre jeweiligen Vue-Komponenten.
- Jeder Komponente werden
id
,props
undstate
des Widgets übergeben.
- Jeder Komponente werden
Erste Schritte
Wir haben ein Beispiel-Node-Repository erstellt, das die Grundlagen für Ihr Widget bietet. Es enthält viele Beispiele für Funktionen, die Sie wahrscheinlich benötigen werden.
Das Basis-Repository hat die folgende Datei-/Ordnerstruktur:
Wie bei allen Node-RED-Knoten müssen Sie mit zwei Dateien beginnen:
/nodes/ui-example.html
- definiert die Eigenschaften des Knotens, die Bearbeitungs-UI und den Hilfetext./nodes/ui-example.js
- definiert das serverseitige Verhalten des Knotens
Jedes Widget muss dann clientseitigen Code definiert haben, der steuert, wie das Widget innerhalb eines Dashboards gerendert wird. Alle Inhalte innerhalb von /ui
werden in eine .umd.js
-Datei gepackt, die Dashboard zur Laufzeit lädt.
/ui/components/
- Ordner, der.vue
-Dateien für alle benötigten Vue-Komponenten enthält/ui/index.js
- Exportiert alle Vue-Komponenten, die in Dashboard 2.0 importiert werden müssen
Die Konfiguration des Knotens und der Widgets wird über zwei Dateien gesteuert:
vite.config.js
- enthält die Details, was in die erstellte.umd.js
-Datei des Widgets gepackt werden soll.package.json
- muss einennode-red-dashboard-2
-Abschnitt enthalten, der die Widgets definiert, die Dashboard importieren kann.
Lokal entwickeln
Um mit Ihrem eigenen Drittanbieter-Widget auf Ihrem lokalen Rechner zu arbeiten:
Node-RED & Dashboard installieren
- Installieren Sie Node-RED (Dokumentation)
- Installieren Sie
@flowfuse/node-red-dashboard
in Node-RED über die Option "Palette verwalten".
Das UI-Beispiel-Node installieren
- Forken Sie unser Beispiel-Node-Repository und klonen Sie es lokal auf Ihren Rechner.
- Installieren Sie im Beispiel-Node-Verzeichnis die erforderlichen Abhängigkeiten:bash
npm install
- Optional eine Quellkarte generieren (um den minimierten Code mit dem Originalcode zu verknüpfen), um das Debuggen des Frontend-Codes im Browser zu vereinfachen. Auf Linux kann dies erreicht werden durch:bash
export NODE_ENV=development
- Erstellen Sie im Beispiel-Node-Verzeichnis die
.umd.js
-Datei des Beispiel-Nodes (was Node-RED verwendet, um Ihr Widget auszuführen), dies generiert den/resources
-Ordner, der von Node-RED geladen wird.bashnpm run build
UI-Beispiel in Node-RED installieren
- Navigieren Sie zu Ihrem lokalen Node-RED-Verzeichnis:bash
cd ~/.node-red
- Installieren Sie die lokale Kopie des Beispiel-Nodes:bash
npm install /path/to/your/local/node-red-dashboard-example-node-folder
- Starten Sie Node-RED neu
Hinweis: Bei allen lokalen Änderungen, die Sie im /ui
-Ordner des Drittanbieter-Widgets vornehmen, müssen Sie npm run build
erneut ausführen, um die umd.js
-Datei zu aktualisieren, die Dashboard lädt, um das Widget zu rendern.
Konfigurieren Ihres Widgets
Benennen Ihres Widgets
Um externe Widgets in den Dashboard-Kern zu importieren, liest der ui-base
-Konfigurationsknoten von Dashboard die package.json
von Node-RED und überprüft alle Pakete, die in Node-RED mit node-red-dashboard-2-
im Paketnamen installiert wurden.
Daher stellen Sie bitte sicher, dass Ihre eigene Integration entsprechend benannt ist:
"name": "node-red-dashboard-2-<your-widget-name>"
Definieren Ihres Widgets
Innerhalb Ihrer eigenen package.json
müssen Sie einen node-red-dashboard-2
-Abschnitt definieren, der Dashboard mitteilt, wie Ihr Widget geladen werden soll. Ein Beispiel aus ui-example
ist wie folgt:
"node-red-dashboard-2": {
"version": "0.8.0", // die minimale unterstützte Version von Dashboard 2.0
"widgets": {
"ui-example": { // dieser Schlüssel muss mit dem "type" Ihres Widgets übereinstimmen, das in Node-RED registriert ist
"output": "ui-example.umd.js", // der Name der erstellten .js-Datei, die in Dashboard importiert wird, konfiguriert in vite.config.js
"component": "UIExample" // der Name der primären Vue-Komponente, die als Ihr Widget in Dashboard gerendert wird
}
}
}
Registrieren Ihres Nodes & Widgets
Mehr Details: Registrierung
Traditionell müssen Sie bei Node-RED Ihren Knoten mit RED.nodes.registerType("ui-example", UIExampleNode)
registrieren. Dies ist auch bei Dashboard der Fall, aber Sie müssen das Widget auch bei Dashboard registrieren.
Die Dashboard-Registrierung basiert auf einer .register()
-Funktion (siehe Dokumentation). Diese Funktion ist für jeden ui-base
, ui-page
oder ui-group
verfügbar. Für ui-group
und ui-page
wird die Funktion an den ui-base
weitergeleitet, wo ein Store aller Widgets im Dashboard gepflegt wird.
Ihr Widget sollte eines dieser als Eigenschaft in Ihrem Node-RED-Knoten definieren, höchstwahrscheinlich wird es ui-group
sein, wenn Sie möchten, dass Ihr Widget innerhalb einer Gruppe im Dashboard gerendert wird.
In Ihrer /nodes/ui-example.js
-Datei:
module.exports = function(RED) {
function UIExampleNode(config) {
RED.nodes.createNode(this, config);
var node = this;
// in welcher Gruppe rendern wir dieses Widget
const group = RED.nodes.getNode(config.group)
/**
* Weitere Konfiguration & Einrichtung hier
*/
// das Widget bei Dashboard registrieren
group.register(node, config, evts)
}
// Den Knoten bei Node-RED registrieren
RED.nodes.registerType("ui-example", UIExampleNode);
}
Anleitungen
Die folgenden sind Anleitungen und Beispiele zum Erstellen von Drittanbieter-Widgets. Wir haben auch den Abschnitt "Nützliche Anleitungen" in der linken Navigation, der allgemeinere Entwicklungsanleitungen beim Beitrag zu Dashboard 2.0 bietet.
Die Grundlagen von VueJS
Wir sind uns bewusst, dass viele Entwickler, die zu Dashboard 2.0 beitragen möchten, möglicherweise neu in VueJS sind, daher haben wir hier einige Grundlagen detailliert beschrieben.
Es ist sehr üblich, seit VueJS Anwendungen mit der "Composition API" zu sehen. Während dies eine leichtere Möglichkeit ist, Ihre Anwendungen zu erstellen, ist es nicht die intuitivste für diejenigen, die mit VueJS nicht vertraut sind. Daher verwenden wir größtenteils die "Options API"-Struktur in Dashboard 2.0 und in unseren Beispielen für bessere Lesbarkeit.
Mit der Options-API hat eine Vue-Komponente die folgende Struktur:
<template>
<!-- HTML-Vorlage für die Komponente -->
<!-- Sie können hier direkt auf alle in Ihren Komponenten definierten Variablen verweisen, z.B. -->
<div>{{ myVar }}</div>
</template>
<script>
export default {
// alle Eigenschaften, die an die Komponente übergeben werden
// in Dashboard 2.0 sind dies die 3 bereitgestellten:
props: ['id', 'props', 'state'],
// alle Daten, die Sie reaktiv und in Ihrer gesamten Komponente verfügbar machen möchten
// innerhalb des <script> verweisen Sie auf diese Variablen mit this.<myVar>
// innerhalb des HTML benötigen Sie das "this."-Präfix nicht
data () {
return {
myVar: 'Hallo Welt'
}
},
// Berechnete Eigenschaften sind Variablen, die sich automatisch aktualisieren, wenn sich ihre Abhängigkeiten ändern
computed: {
myComputedProp () {
return this.myVar + '!'
}
},
// alle Methoden, die innerhalb der Komponente verwendet werden
methods: {
myMethod () {
alert(this.myVar)
}
},
// Wird ausgeführt, wenn die Komponente erstellt und in den DOM geladen wird
mounted () {
alert('Komponente wurde geladen')
},
// Wird ausgeführt, wenn die Komponente entfernt wird
unmounted () {
alert('Komponente wurde entfernt')
}
}
</script>
<style>
/* alle CSS-Stile für die Komponente */
</style>
Verwenden von Vuetify-Komponenten
Sie sind frei, vollständig benutzerdefiniertes HTML/CSS zu definieren, wenn Sie Ihre Widgets definieren, aber wir haben auch native Unterstützung für die gesamte Vuetify-Komponentenbibliothek bereitgestellt, um Ihnen den Einstieg mit einer Vielzahl von UI-Komponenten zu erleichtern, die Sie möglicherweise nutzen möchten.
Zugriff auf Eigenschaften
Wenn Widgets in einem Dashboard-Layout gerendert werden, wird ihnen eine kleine Sammlung von Eigenschaften übergeben, die verwendet werden können, um das Verhalten des Widgets anzupassen:
Eigenschaft | Beschreibung |
---|---|
id | Die ID des Widgets, die von Node-RED zugewiesen wird |
props | Die in Node-RED definierten Eigenschaften, z.B. this.props.name oder this.props.group |
state | Der Zustand des Widgets, z.B. this.state.enabled oder this.state.visible |
Wenn Sie diese in Ihrer eigenen Vue-Komponente rendern, können Sie wie folgt darauf zugreifen:
<template>
<div>ID: {{ id }}</div>
<div>Name: {{ props.name }}</div>
<div>Gruppe: {{ props.group }}</div>
</template>
<script>
export default {
props: ['id', 'props', 'state'],
mounted () {
// wird beim Laden des Widgets ausgeführt
alert(this.id)
}
}
</script>
Kommunikation mit Node-RED
Ereignisse werden zwischen Node-RED und Dashboard 2.0 mit SocketIO hin und her gesendet. Sie können eine vollständige Aufschlüsselung dieser Ereignisse in unserem Leitfaden Ereignisarchitektur sehen.
Empfangen von Node-RED-Nachrichten
Wenn Ihr Knoten eine msg
in Node-RED empfängt, erhält der Dashboard 2.0-Client ein msg-input
-Ereignis über SocketIO. Sie können sich innerhalb der Vue-Komponente Ihres eigenen Widgets auf dieses Ereignis abonnieren mit:
export default {
props: ['id', 'props', 'state'],
// der Rest Ihrer Vue-Komponente hier
mounted () {
this.$socket.on('msg-input' + this.id, (msg) => {
// tun Sie etwas mit der msg
})
},
unmounted () {
// vom Ereignis abmelden, wenn das Widget zerstört wird
this.$socket.off('msg-input:' + this.id)
}
}
Es wird empfohlen, unseren eingebauten Daten-Tracker zu verwenden, um die Standard-Eingabe-/Ladeereignisse für Ihr Widget einzurichten. Dies kann durch Aufrufen des folgenden in der .vue
-Datei Ihres Widgets erfolgen:
export default {
inject: ['$dataTracker'],
// der Rest Ihrer Vue-Komponente hier
created () {
this.$dataTracker(this.id)
// wir können die Standardereignisse überschreiben, wenn wir möchten, mit
// this.$dataTracker(this.id, myOnInputFunction, myOnLoadFunction, myOnDynamicPropertiesFunction)
}
}
Weitere Details zur Anpassung des Daten-Trackers finden Sie hier.
Senden von Node-RED-Nachrichten
Sie können eine msg
an alle verbundenen Knoten in Node-RED senden, indem Sie eines der folgenden Ereignisse über SocketIO aufrufen:
this.$socket.emit('widget-action', this.id, msg)
: sendet einemsg
an alle verbundenen Knoten in Node-RED.this.$socket.emit('widget-change', this.id, msg)
: dasselbe wiewidget-action
, speichert auch die letzte Nachricht im Node-RED-Datenspeicher für dieses Widget, damit der Zustand wiederhergestellt werden kann, wenn das Dashboard aktualisiert wird.
Benutzerdefinierte SocketIO-Ereignisse
Wenn Sie Ihre eigenen SocketIO-Ereignisse und -Handler implementieren möchten, können Sie dies in Ihrer .vue
-Komponente tun mit:
this.$socket.emit('my-custom-event', this.id, msg)
Dann, wo Sie Ihren Knoten bei Dashboard auf der Serverseite registrieren (in der .js
-Datei Ihres Knotens), können Sie den relevanten Ereignishandler definieren:
evts = {
onSocket: {
// auf benutzerdefinierte Ereignisse abonnieren
'my-custom-event': function (conn, id, msg) {
// eine msg in Node-RED von diesem Knoten aus senden
node.send(msg)
}
}
}
group.register(node, config, evts)
Datenaufbewahrung & Datenspeicher
Wir verwenden das Konzept von Datenspeichern sowohl auf der Client- als auch auf der Serverseite von Dashboard 2.0. Diese werden verwendet, um die zentrale Speicherung des neuesten Zustands und der Daten, die einem Widget zugeordnet sind, zu zentralisieren.
Datenspeicher sind eine Zuordnung der ID des Widgets/Knotens zu den neuesten Daten, die in dieses Widget empfangen wurden. Dies wird am häufigsten verwendet, um den Zustand wiederherzustellen, wenn das Dashboard aktualisiert wird.
Node-RED-Datenspeicher
Der Datenspeicher von Node-RED wird für Drittanbieter-Widgets über den zugehörigen ui-base
zugänglich gemacht.
Um darauf in der .js
-Datei Ihres Widgets zuzugreifen, können Sie verwenden:
const group = RED.nodes.getNode(config.group)
const base = group.getBase()
Dann, wann immer Sie Daten im Datenspeicher speichern möchten, können Sie dies tun mit:
base.stores.data.save(base, node, msg)
Sie können mehr über den Node-RED-Datenspeicher in unserem Leitfaden Zustandsverwaltung lesen.
Node-RED-Zustandsspeicher
Zustand bezieht sich auf alle Eigenschaften Ihres Widgets, die sich zur Laufzeit geändert haben und sich von denen unterscheiden würden, die im Node-RED-Editor festgelegt sind.
Zum Beispiel kann das ui-dropdown
seine options
mit einer msg.options
-Nachricht überschrieben haben, die an den Knoten gesendet wird. Diese aktualisierten options
würden gegen den Knoten im Zustandsspeicher gespeichert werden.
Clientseitiger Datenspeicher
In der Clientseite von Dashboard 2.0 verwenden wir VueX, um den zentralisierten Zustand einer UI zu verwalten.
Mit VueX können Sie mapState
aufrufen, das den Store automatisch an Ihre Vue-Komponente bindet, z.B.:
<template>
<!-- Die neuesten Datenwerte vom Widget mit <id> abrufen -->
{{ messages[id] }}
</template>
<script>
// mapState von VueX importieren
import { mapState } from 'vuex'
export default {
props: ['id', 'props', 'state'],
// ... der Rest Ihrer Komponente hier
computed: {// die Nachrichten des Stores an unsere eigene Vue-Komponente binden
...mapState('data', ['messages'])
},
mounted () {
// zeigt die neueste Nachricht beim Laden des Widgets an
alert(this.messages[this.id])
}
}
</script>
Dann, um Daten zum Store hinzuzufügen:
this.$store.commit('data/bind', {
widgetId: this.id,
msg
})
Laden des Zustands
Wenn Dashboard 2.0 geladen wird, sendet es ein widget-load
-Ereignis an alle Widgets im Dashboard. Dies enthält den neuesten Wert aus dem Node-RED-Datenspeicher. Sie können sich auf dieses Ereignis in Ihrem Widget abonnieren mit:
export default {
props: ['id', 'props', 'state'],
// der Rest Ihrer Komponente hier
mounted () {
this.$socket.on('widget-load' + this.id, (msg) => {
// tun Sie etwas mit der msg
})
},
unmounted () {
// vom Ereignis abmelden, wenn das Widget zerstört wird
this.$socket.off('widget-load:' + this.id)
}
}
Styling mit Vuetify & CSS
Wir können unser eigenes CSS innerhalb des Repositories des Widgets definieren und sie in eine .vue
-Komponente wie folgt importieren:
<style scoped>
.ui-example-wrapper {
padding: 10px;
margin: 10px;
border: 1px solid black;
}
</style>
Vuetify bietet auch eine Handvoll von Dienstprogrammsklassen zur Unterstützung beim Styling, die alle direkt verwendet werden können:
Externe Abhängigkeiten
Ihr Widget kann eine beliebige Anzahl von npm
-Abhängigkeiten haben. Diese werden alle in die .umd.js
-Datei gebündelt, die Dashboard zur Laufzeit lädt.
In ui-example
haben wir eine Abhängigkeit von to-title-case
, die wir in unsere Vue-Komponente importieren und verwenden wie folgt:
import toTitleCase from 'to-title-case'
export default {
// der Rest der Komponente hier
computed: {
titleCase () {
return toTitleCase(this.input.title)
}
}
}
Sie können auch andere Vue-Komponenten aus Ihrem eigenen Repository laden, wie bei jeder VueJS-Komponente.