Schalten mit SignalK – Teil 1

Einer der Vorteile von einem „Bus-System“ ist, dass zum Schalten von Verbrauchern keine direkte Verbindung zwischen Schalter und Verbraucher mehr benötigt wird. Der Verbraucher wird über eine Leistungselektronik geschaltet, die über Botschaften vom Bus gesteuert wird. Ein nahe liegender Vorteil ist, dass die Verknüpfung von Schaltern und Verbrauchern jederzeit per Software geändert werden kann, also z.B. welcher Lichtschalter welche Lampen(kombination) schaltet. Zusätzlich lassen sich Schaltvorgänge auch einfach abhängig von Bedingungen schalten, so könnte sich z.B. ein Licht in Abhängigkeit von der Umgebungshelligkeit (und der Uhrzeit) ein- bzw ausschalten lassen oder z.B. eine Motorraumbelüftung in Abhängigkeit von der Temperatur.

Beispiele für Systeme zum Schalten über Bus-Systeme im Yacht- und Caravanbereich finden sich unter Anderem bei Mastervolt mit dem Digital DC 10x10A als Leistungselektronik und dem Digital Input zum Einlesen von Schaltern. Ein anderes System mit vielen verfügbaren Komponenten und Schnittstellen zu Masterbus und NMEA2000 ist CZone. Nun war die Annahme, dass sich basierend auf unserem laufenden Projekt ähnliches auch einfach mit SignalK realisieren lassen müsste. Das ganze ist jedoch etwas aufwändiger – daher hier die ersten Schritte zum Thema Schalten mit SignalK.

Schalten von Verbrauchern ist zur Zeit noch nicht vollständig im SignalK-Schema spezifiziert. Aber es gibt Diskussionen zu „Digital Switching„, die wir hier als Hinweis darauf betrachten, wie eine mögliche Spezifikation im Schema aussehen könnte. Desweiteren gehen wir davon aus, dass ein Schaltvorgang nicht als einfaches Delta für den Zustand des Schalter, sondern als Put-Request ausgeführt wird. Die Beschreibung von PUT-Requests und dem zugrunde liegenden Request/Response-Mechanismus deutet jedenfalls darauf hin. Bei einem Put-Request erhält der Anfrager eine Rückmeldung über den Status der Anfrage, im Gegensatz zu einem Delta, bei dem Botschaften nach dem „Fire and Forget“-Prinzip versendet werden.

Der Vorschlag für „Digital Switching“ im SignalK-Schema sieht vier Gruppen von Entitäten vor, über die Schaltvorgänge realisiert werden:

  • Inputs: Physikalische Eingänge, z.B. Schalter
  • Loads: Verbraucher
  • Fuses: Sicherungen
  • Switches: „Logische“ Zustände zum Steuern von Aktionen

SignalK als „Datenmodell“ repräsentiert nur den aktuellen Zustand dieser Entitäten. Um einen Schaltvorgang durchzuführen, wird noch ein Stück Software benötigt, das die tatsächliche Änderungen der Zustände durchführt. Auch hierfür gibt es zur Zeit noch wenig dedizierte Software im SignalK-Umfeld. Allerdings gibt es ein Node-RED Plugin für SignalK, das eine graphische Programmierung von Signalflüssen ermöglicht und daher ein einfach zu verwendender Kern für die Programmierung der Schaltvorgänge sein könnte (eine Liste mit den vorhandenen nodes ist hier). Aber wie passt das ganze jetzt zusammen? In diesem Teil werden wird damit anfangen, einen PUT-Request als „Input“ in Node-RED zu empfangen. Nachdem wir verstanden haben, wie dies funktioniertn, werden wir diesen Request dann im nächsten Schritt von einem Arduino erzeugen. Abschließend muss der Schaltvorgang dann zum Steuern des Verbrauchers (der „Load“) wieder an einen Arduino gesendet werden, was den aufwändigsten Teil darstellt.

Erste Praktische Schritte

Ich habe hier eine temporäre Installation des SignalK-Servers auf einem Debian-PC verwendet. Es sollte aber genau so auf dem Raspberry Pi funktionieren. Dafür muss nur „localhost“ in den Beispielen durch „raspberrypi“ ersetzt werden. Als erstes müssen wir das Node-RED Plugin installieren. Dafür starten wir den SignalK-Server, öffnen das Dashboard in einem Webbrowser (z.B. http://localhost:3000) und installieren dort im Appstore das Plugin „@signalk/signalk-node-red“. Anschließend ist evtl. ein Neustart des SignalK-Servers erforderlich. Danach können wir unter http://localhost:3000/plugins/signalk-node-red/redAdmin auf die Weboberfläche von Node-RED zugreifen. Diese sollte so aussehen wie auf dem Screenshot:

Oberfläche des SignalK Node-Red-Plugin nach der Installation
Oberfläche des Node-RED-Plugins nach der Installation.

Als nächstes müssen wir einen „Put-Handler“ in Node-RED erstellen. Diesen findet ihr in der Liste mit den „Nodes“ links im Fenster relativ weit unten. Nachdem er in das Flowchart gezogen ist, werden mit einem Doppelklick die Eigenschaften geöffnet. Es kann ein Name vergeben werden – ich verwende hier „Test-Input“ – und es muss der Pfad angegeben werden, auf den der Put-Handler reagiert. Hier stellen wir electrical.inputs.testinput ein. Das Dialogfeld sollte dann so wie im folgenden Screenshot aussehen:

Konfigurieren des PUT-Handler-Node im Node-RED-Plugin des SignalK-Server.
Konfiguration des Put-Handlers für den ersten Input in Node-RED

Abschließend können wir noch einen „Debug“-Node hinzufügen, mit dem wir den Wert des Put-Nodes im Debug-Tab ausgeben, und ihn durch klicken und ziehen mit dem PUT-Handler verbinden. Zuletzt müssen wir noch rechts oben auf den roten „Deploy“-Button klicken und dann darunter das „Debug“-Tab aktivieren, damit wir die Ausgaben des Debug-Nodes sehen können.

Nun gibt es zwei Wege, einen Put-Request an den Handler zu schicken. Der erste geht über das HTTP-REST-Interface des SignalK-Servers. Um dies zu testen, verwenden wir das Kommandozeilen-Programm curl, mit dem sich HTTP-Requests durchführen lassen. Um einen Put-Request auf den Pfad des gerade erstellten Inputs auszuführen, gebt folgendes Kommando in einem Terminal ein:

ralph@debian:~$ curl -X PUT -H "Content-Type: application/json" -d '{"value": 0.0}' http://localhost:3000/signalk/v1/api/vessels/self/electrical/inputs/testinput

Mit {„value“: 0.0} stellt ihr den Wert des Inputs ein. Der Server antwortet auf den Put-Request mit einem Status. Wenn alles geklappt hat, ist der Status „COMPLETED“ mit dem statusCode 200:

{"state":"COMPLETED","requestId":"e8868350-56c8-4f9d-84b5-15e08d8da33a","statusCode":200,"href":"/signalk/v1/requests/e8868350-56c8-4f9d-84b5-15e08d8da33a"}

In Node-Red solltet ihr jetzt rechts im Debug-Tab die Ausgabe des value sehen. Probiert verschiedene Werte aus und seht, wie sie per Put-Request an Node-RED übertragen werden:

Node-RED-Oberfläche mit Debug-Ausgabe nach ausführen des ersten PUT-Request
Node-RED Debug-Ausgabe nach dem Ausführen des ersten PUT-Request

Die zweite Möglichkeit besteht darin, einen Put-Request per Websocket auszuführen. Dafür braucht man zunächst ein Programm, mit dem man Websocket-Verbindungen aufbauen kann. Ich habe dafür den Chromium-Webbrowser mit der Erweiterung „Browser WebSocket Client“ verwendet. Nachdem die Erweiterung installiert und über das Button rechts oben geöffnet ist, muss noch die Adresse des Servers eingegeben werden. Für die Websocket-Verbindung zum SignalK-Server lautet sie:

ws://localhost:3000/signalk/v1/stream

Nachdem ihr sie im Feld: „Enter the server URL:“ eingegeben habt, könnt ihr auf den „Connect“-Button klicken, um die Verbindung aufzubauen:

Websocket-Verbindung zum SignalK-Server in der Chromium-Extension Browser WebSocket Client.
Websocket-Verbindung zum SignalK-Server in der Chromium-Extension Browser WebSocket Client

Nach dem Verbinden erscheinen weiter unten unter „Received Messages“ ein paar Botschaften vom SignalK-Server. Unter „Send a Message“ können wir eine Nachricht an den SignalK-Server senden, z.B. einen Put-Request codiert als JSON. Dafür gebt ihr den folgenden Request in das Feld „Message“ ein:

{
  "requestId": "123345-23232-232323",
  "put": {
    "path": "electrical.inputs.testinput",
    "value": 1
  }
}

Wenn ihr jetzt aus „Send“ drückt, wird der Put-Request an den SignalK-Server gesendet und ihr bekommt bei den „Received Messages“ wieder die Status-Meldung vom Server zu sehen (siehe Screenshot). Außerdem sollte im Debug-Tab der Node-RED-Oberfläche jetzt zu sehen sein, dass ein Put-Request mit dem value „1“ emfpangen worden ist.

PUT-Request und Antwort des SignalK-Servers im Browser WebSocket Client.
PUT-Request und Antwort des SignalK-Servers im Browser WebSocket Client

Ergebnis und nächste Schritte

So – grundsätzlich ist jetzt klar, wie ein Put-Request an den SignalK-Server gesendet und er dort verarbeitet werden kann. Gut zu dem bereits vorhandenen Arduino-Sketch hätte es gepasst, wenn die Requests auch per UDP oder TCP geschickt werden – das wird aber (noch) nicht unterstützt. Daher muss der Sketch erst umgebaut werden, damit im nächsten Schritt vom Arduino ein Schalter eingelesen werden und der Status an den SignalK-Server gesendet werden kann.