Die Firmware des Controllers bietet eine einfache Kommandostruktur, mit der sie ohne App oder automatisiert von anderen Systemen gesteuert werden kann (REST-API). Dadurch lässt sich der Controller in bestehende Infrastruktur, wie bspw. Bastelprojekte (Raspberry Pi und Co), wissenschaftliche Experimente oder groß angelegte Systeme integrieren – eben überall dort, wo proprietäre Software zum Einsatz kommt oder spezielle Wünsche erfüllt werden wollen.
Der Zustand des Controllers wird durch seinen Parametersatz bestimmt.
Eigentlich ist alles ein Parameter: die Spannung an den Analogausgängen, der Name des WLAN-Netzes mit dem der Controller verbunden ist, die Messwerte angeschlossener SenseAct-Erweiterungen, die Systemzeit, usw.
Insgesamt gibt es weit über hundert Parameter, aber keine Angst – nur die wenigsten werden für dich relevant sein.
Es ist jedoch wichtig, die drei Kommandoarten zu kennen, mit denen du CresControl steuern kannst:
Um den Wert eines Parameters zu erhalten muss lediglich dessen Namen über eine der Kommandoschnittstellen an den Controller übermittelt werden:
[NAME-DES-PARAMETERS]
Der Controller wird in seiner Antwort den Parameternamen wiederholen und dessen Wert durch „::“ getrennt übermitteln:
[NAME-DES-PARAMETERS>::<WERT-DES-PARAMETERS]
Die Spannung am Analogeingang A (In A) kann beispielsweise ausgelesen werden, indem folgendes Kommando übermittelt wird:
in-a:voltage
Der Controller liefert als Antwort beispielsweise:
in-a:voltage::5.10
„in-a:voltage“ ist hier der Name der Eingangsspannung an In A (eine Liste aller Parameternamen findest du in der Command-Reference).
Um den Wert eines Parameters zu verändern wird der Name des Parameters, gefolgt von einem Gleichheitszeichen („=“) und anschließend dem gewünschten Wert übermittelt:
[NAME-DES-PARAMETERS>=<GEWÜNSCHTER-WERT]
Mit dem folgenden Kommando kann die Spannung am Analogausgang A beispielsweise auf 4.20 Volt gesetzt werden (beachte Punkt statt Komma!):
out-a:voltage=4.20
Wie bei einer Lese-Anfrage wiederholt der Controller das Kommando und bestätigt den einstellten Wert hinter dem „::“:
out-a:voltage=5::5.00
Beachte, dass nicht alle Parameter geschrieben werden können. Die Eingangsspannung an den Analogeingängen ist ein „Messwert“ und kann natürlich nicht gesetzt werden. Das gleiche gilt für die Messwerte der SenseAct Erweiterungen oder diverse Zustandsparameter.
Ob ein Parameter einen Schreibzugriff erlaubt kannst du der Command-Reference entnehmen. Falls du doch versuchst, einen „read-only“ Parameter zu verändern wird der Controller mit „no access“ antworten.
Neben den Parametern, die gelesen oder geschrieben werden können, bietet der Controller eine Reihe von „Funktionen“. Diese Funktionsaufrufe starten bestimmte Routinen, wie bspw ein Firmwareupdate, einen Scan nach WiFi-Netzwerken in der Umgebung oder führen ein gespeichertes Skript aus (siehe „Script-Feature“). Wie in Programmiersprachen üblich sind Funktionsaufrufe durch die angehängten Klammern („()“) gekennzeichnet, welche ggf. Funktionsargumente enthalten (durch Komma getrennt):
[NAME-DER-FUNKTION(ARG1,ARG2,…)]
Das folgende Kommando führt ein Firmwareupdate durch:
firmware:perform-update()
Als Antwort kommt exemplarisch:
firmware:perform-update()::firmware is up to date
Die Funktion um den CresControl mit einem WiFi zu verbinden benötigt hingegen zwei Argumente: den Namen des Zielnetzwerks und dessen WPA2-Schlüssel:
wifi:client:connect(„MEIN WLAN“,“MEIN PASSWORT“)
Welche Funktionen welche Argumente benötigen kannst du wieder der Command-Reference entnehmen.
Pro API-Aufruf können auch mehrere Kommandos auf einmal übermittelt werden. Dafür werden diese einfach mit einem Semikolon („;“) oder einem Zeilenumbruch separiert.
Der folgende Aufruf setzt beispielsweise sämtliche Ausgangsspannungen auf einmal:
out-a:voltage=0;out-b:voltage=0;out-c:voltage=0;out-d:voltage=0;out-e:voltage=0;out-f:voltage=0
Die Parameter des Controllers haben die in Programmiersprachen gängigen Datentypen.
Die Datentypen sind:
Float: Beim Datentyp „float“ handelt es sich um Gleitkommazahlen, mit bis zu zwei Nachkommastellen. Wichtig: anstatt eines Kommas wird wie im englischhsprachigen Raum üblich ein Dezimalpunkt verwendet.
Der Parameter „out-a:voltage“ ist beispielsweise diesen Typs und wir können ihn mit dem Kommando „out-a:voltage=4.20“ schreiben.
Integer: ganze Zahlen
Boolean: Dies sind wahr/falsch Werte. Im Protokoll des Controllers können diese wahlweise als true/false, t/f oder 1/0 ausgedrückt werden. Ein Beispiel hierfür ist der Parameter „out-a:enabled“, der den Analogausgang A aktiviert („out-a:enabled=true“), bzw deaktiviert („out-a:enabled=false“).
String: beim Typ „String“ handelt es sich um Text. Dieser wird in Anführungszeichen gesetzt, wie im folgenden Beispiel zu sehen ist: ‚tag=„mein Controller“‘.
Text, der nicht in Anführungszeichen gesetzt ist, wird vom Controller als Kommando interpretiert, was bei der Arithmetikfunktionalität eine Rolle spielt (siehe Abschnitt „Arithmetik“).
Es gibt drei Arten möglicher Parameterzugriffe:
read-only Parameter können nur gelesen, jedoch nicht geschrieben werden. Dies ist beispielsweise für Zustandsgrößen und Messwerte der Fall.
write-only Parameter können nur geschrieben, allerdings nicht gelesen werden. Derzeit existieren keine Parameter dieses Zugrifftyps.
read-write Parameter können sowohl gelesen, als auch geschrieben werden.
Daneben existieren manche Parameter, die keinerlei Zugriff erlauben (beispielsweise Passwörter), bzw. nur intern verwendet werden. Diese Parameter sind für den Anwender von untergeordneter Bedeutung.
Wie im Abschnitt „Datentypen“ erwähnt, müssen Text-Werte immer in Anführungszeichen gesetzt werden. Häufig kommt es vor, dass innerhalb des Textes selbst ebenfalls Gänsefüßchen vorkommen.
Damit ein im Text enthaltenes Anführungszeichen als Buchstabe - und nicht als Steuerzeichen - interpretiert wird, muss im Text enthaltenen Anführungszeichen ein Backslash () vorangestellt werden (sog. „escape“).
Beispiel für eine ungültige Eingabe:
tag="ich sage "hey""
Korrekt escaped wird daraus:
tag="ich sage \"hey\""
Die Kommandos sind in erster Linie für Maschine-Maschine-Kommunikation (API) gedacht und sind dabei dennoch für einen Menschen lesbar und nachvollziehbar. In manchen Situationen ist es trotzdem praktisch, ein Kommando manuell auszuführen. Beispielsweise wenn du an einem Python Skript arbeitest und mal eben schnell ein Kommando testen möchtest.
Es kann auch vorkommen, dass manche Funktionen in der App (noch) nicht verfügbar sind und nur über die API bedient werden können.
Eine der Kommandoschnittstellen ist der http-Server des Controllers. Dieser nimmt unter dem Pfad ‚/command?query=‘ Kommandos entgegen. Wenn du die IP-Adresse oder den Hostnamen (entspricht dem tag) deines Controllers kennst, dann öffne in deinem Browser einfach die URL
http://<DIE-IP-DES-GERÄTS>/command?query=[HIER-STEHT-DAS-KOMMANDO]
Angenommen, unser CC hat die IP-Adresse 192.168.178.63 und wir möchten wieder die Spannung am Analogeingang A auslesen, so sieht die URL für uns folgendermaßen aus:
http://192.168.178.63/command?query=in-a:voltage
Anstelle der IP ist der Controller auch unter seiner Domain erreichbar:
http://mein-crescontrol/command?query=in-a:voltage
HTTP ist die einfachste Möglichkeit mit dem Controller ohne App zu interagieren, weil lediglich ein Webbrowser benötigt wird und auch die Windows/Linux/MacOS-Kommandozeilen bereits die notwendigen Pakete vorinstalliert haben, um HTTP-Kommandos automatisiert auszuführen.
In der Eingabeaufforderung/PowerShell unter Windows geht das zum Beispiel so:
wget „http://192.168.178.63/command?query=in-a:voltage“
Unter Linux ist das CmdLet „curl“ bereits installiert:
curl http://192.168.178.63/command?query=in-a:voltage
Für eine Automatisierung existieren diverse http-Biblioteken in allen gängigen Programmiersprachen.
Hinweis:
Die HTTP-Kommandozeile ist synchron, d.h. der Controller kann nur Anfragen beantworten (Request-Response-Prinzip), allerdings von sich aus - also ungefragt - nichts senden.
Für einfache Steuer- und Konfigurationskommandos ist dies allerdings ausreichend.
Das Mittel der Wahl ist in den meisten Fällen der Websocket-Server des Controllers. Die Kommandos sehen hier genauso aus wie bei den anderen Schnittstellen, allerdings haben Websockets den Vorteil, dass eine bestehende Verbindung nach einem Kommando aufrecht erhalten wird und der Controller dadurch „von sich aus“ Nachrichten senden kann. Für manche Kommandos ist dies notwendig, so zum Beispiel für das „Subscription-Feature“, bei dem der CC alle Abonnenten selbständig informiert wenn sich Parameterwerte ändern. Auch für Datenlogging auf einem externen Gerät ist es von Vorteil, die interessanten Parameter nicht im Sekundentakt auslesen zu müssen, sondern dem Controller den Auftrag zu geben, diese in einem gewünschten Takt mitzuteilen (siehe „Monitor-Feature“).
Probieren wir das gleich mal aus.
Zunächst benötigen wir einen Websocket-Client. Im Crescience HUB steht ein deartiger Client bereits zur Verfügung: im Experten-Tab findest du ganz unten ein Kommandozeile, mit der du mit dem Controller „chatten“ kannst.
Alternativ gibt es auch Websocket-Clients für alle möglichen Plattformen (Browser-Plugins, Apps, etc.). Empfehlenswert ist der sehr minimalistische „SimpleWebsocketClient“ (SWC), der für alle gängigen Browser als Plugin verfügbar ist (https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo).
Im Websocket-Client tragen wir die IP oder den Hostnamen des Controllers ein. Außerdem muss der Port 81 angegeben werden (üblicherweise wird der Port mit einem „:“ an die Adresse angehängt).
Im SWC sieht das folgendermaßen aus:
<Screenshot SWC Verbindung>
Wir öffnen die Verbindung und können nun unsere Kommandos übermitteln:
<Screenshot SWC in-a-Kommando>
Wie du siehst funktionieren die bekannten Kommandos hier genauso wie bei den anderen Schnittstellen.
Da Websockets wie gesagt asynchron sind, können wir uns hier auch mittels des subscribe-Kommandos (subscription:subscribe()) als Abonnent eintragen, um immer auf dem Laufenden zu bleiben:
<Screenshot subscription>
Wenn wir jetzt in der App einen Schieberegler betätigen erhalten wir den aktuellen Wert des entsprechenden Parameters in unserer Websocket-Verbindung:
<Screenshot eingehende Subscriber-Messages>
Um Daten zu loggen können wir das „Monitor-Feature“ benutzen indem wir die Funktion tasks:add-monitor(PARAMETER,PERIODE,NAME) aufrufen. Diese Funktion benötigt drei Argumente:
PARAMETER: der oder die Parameter, die periodisch gesendet werden sollen
PERIODE: die Periode mit der die Parameter gesendet werden sollen (in Millisekunden)
NAME: ein Name für diesen Monitor (notwendig, um ihn später zu löschen/pausieren)
Mit dem Kommando tasks:create-monitor(„time:daytime;in-a:voltage;in-b:voltage“,1000,„Eingangs-Logger“) können wir beispielsweise die Eingansspannungen loggen:
<Screenshot Monitor>
Die Antwort auf dieses Kommando entspricht der Task-ID, die unserem Monitor zugewiesen wurde (in unserem Fall 1). Mit dem Kommando tasks:get-all() können wir sicherstellen, dass der Task erfolgreich angelegt wurde.
Wie du siehst, können mehrere Parameter gleichzeitig abgefragt werden indem ihre Namen durch „;“ getrennt aufgelistet werden (das funktioniert generell mit allen Kommandos auf allen Schnittstellen).
Wir erhalten jetzt in einem Takt von einer Sekunde die Werte der beiden Analog-Ins.
Um den Monitor zu beenden rufen wir die Funktion tasks:remove-task(TASK-ID) auf oder schließen einfach die Websocket-Verbindung.
Auch für Websockets existieren Bibliotheken für alle gängigen Programmiersprachen.