Diese Seite beschreibt die allgemeine socket.io API, für die Geräte-spezifische siehe: smart-home-control APIs.
Der smart-home-control Socket.IO Server ist eine Art zentrales Hub für die Verknüpfungen und Kommunikation im Smart Home. Die Geräte kommunizieren nicht untereinander, sondern immer nur über den smart-home-control Server.
Im wesentlichen bietet der Server zwei Funktionen:
- Der Server bietet "Kanäle", wobei es je Gerät ein Kanal gibt. In diesen Kanäle können Geräte Daten hinterlegen. Immer wenn die Daten aktualisiert werden, werden alle anderen Clients in Echtzeit benachrichtigt.
- Über die Kanäle gibt es auch ein System, um Events (vergleichbar mit Funktionsaufrufen) an Geräte zu schicken. Events erkennt man am ":" im Namen.
Darüber hinaus gibt es noch ein paar spezielle Funktionen, die vom Server bereitgestellt werden:
- Für die Simulation von Rollenspielen gibt es ein Rollen-Management. Damit können die Endgeräte von Personen im Rollenspiel Zugriff auf bestimmte Daten bekommen oder entzogen werden.
- Für Webclients und Kamerabilder gibt es ein Server für statische Dateien. Bei den Kamerabildern geht es vor allem auch um das Cachen/Zwischenspeichern der Bilder, damit diese nicht von den Kameras direkt abgerufen werden müssen. Das ist notwendig für Clients, die von außerhalb auf das Smart Home LAN zugreifen. Darum kümmert sich ein Proxy Server.
- Der Server hat auch ein paar zusätzliche Funktionen für Gerätesteuerungen, um diesen ihre Konfiguration zu schicken und deren Status zu erfassen bzw. Geräte zu (de)aktivieren.
- Für das gesamt Smart Home gibt es auch noch Funktionen zum Zurücksetzen, Neustarten und Herunterfahren.
Zu Kanälen und Events stehen mehr Details und Beispiele in den Grundlagen der API. Zu den anderen Funktionen sind im Folgenden ein paar Beschreibungen.
- Rollen-Management
- Statische Dateien & Cache
- Gerätesteuerungen & -status
- Zurücksetzen, Neustarten, Herunterfahren
- Client API
- get: Zustand abfragen
- sub: Kanal abbonieren
- put: Zustand ändern
- Event abfangen
- Event auslösen
- Rolle abbonieren
- Rolle: Kanäle modifizieren
- Cache
- status:anmelden: Gerätesteuerung anmelden
- status:aktivieren: Gerät aktivieren
- status:deaktivieren: Gerät deaktivieren
- status:update: Gerätestatus updaten
- extern:anmelden: Externen Proxy anmelden
- reset: Smart Home zurücksetzen (Server neustarten)
- neustart: Smart Home neustarten
- herunterfahren: Smart Home herunterfahren
- Plugins
- Verhalten im Falle eine Reconnects
Rollen-Management
Als spezielle Funktion, damit man Rollen einfach konfigurieren kann, gibt es die Möglichkeit, Rollen statt Kanäle zu abbonieren. Rollen haben standardmäßig Zugriff auf bestimmte Kanäle, aber es ist möglich (z.B. von der Steuerungs-App aus), zu ändern, welche Kanäle eine Rolle abboniert hat. Also im Prinzip auf welche Informationen die Rolle Zugriff hat, nur dass das Feature keine Sicherheitsmechanismen hat, sondern nur dem Rollenspiel dient.
Wird Zugriff auf einen Kanal aktiviert, bekommt der Client den aktuellen Zustand. Wird der Zugriff deaktiviert, wird als Zustand null
gesendet. Außerdem werden keine Events mehr ausgelöst, wenn der Eventname mit dem zugehörigen Kanalname beginnt.
Außerdem kann die Rollen-Konfiguration über den speziellen Kanal rollen
abgefragt werden:
{
"nachbar": {
"name": "Max",
"rolle": "Nachbar",
"zugriffe": {
"sturzalarm": true,
"kuehlschrank": false,
}
},
// ...
}
Statische Dateien & Cache
Läuft der Server unter Port 3030, werden auf drei Pfaden statische Dateien bereitgestellt:
-
localhost:3030/ -> Dateien im Ordner
clients
-
localhost:3030/extern -> Dateien im Ordner
clients-extern
-
localhost:3030/cache -> Dateien im Ordner
cache
Der Pfad /extern
dient dem Proxy Server für Clients, die nicht im Smart Home LAN sind. Dateien in /cache
können dynamisch hinzugefügt werden. Dazu gibt es die Funktion/das Event cache:update
(siehe unten).
Gerätesteuerungen & -status
Um die Konfiguration im Smart Home einfacher updaten zu können, liegt die gesamte Konfiguration beim smart-home-control Server. Meldet sich ein Gerät in dem in Grundlagen der API beschrieben Prozess an, erhält es seine Konfiguration. Außerdem updatet der Server im Kanal status
automatisch, wenn sich das Gerät verbunden hat, oder die Verbindung beendet.
Über den Kanal status
können Gerätesteuerungen auch (de)aktiviert werden. Dazu werden die entsprechenden Events an den zugehörigen Client der Gerätesteuerung weitergeleitet.
Zurücksetzen, Neustarten, Herunterfahren
Diese Funktionen dienen speziell dem möglichst einfachen Umgang mit dem Smart Home für Anwender:innen. Damit können die Funktionen einfach als ein Button im Steuerungstablet eingebaut werden. Die Umsetzung von Neustart und Herunterfahren basiert auf Skripten, die von Ansible generiert werden.
Client API
get
: Zustand abfragen
z.B. socket.emit("get", "fenster")
Fordert den Server auf, einmal den aktuellen Zustand im Kanal fenster
zu senden. Existiert der Kanal (noch) nicht, wird nichts gesendet.
Bisher wird die Funktion noch nicht verwendet, evtl. ist es daher sinnvoll sie zu entfernen.
sub
: Kanal abbonieren
z.B. socket.emit("sub", "mikrofon")
Fordert den Server auf, einmal den aktuellen Zustand im Kanal mikrofon
zu senden, und bei jeder Änderung erneut. Existiert der Kanal (noch) nicht, wird nichts gesendet.
Das Abbonieren eines Kanals ist außerdem notwendig, um dort Events zu erhalten. (Das ist deswegen, damit das für Rollen einfacher gehandhabt werden kann).
put
: Zustand ändern
z.B. socket.emit("put", "fenster", {"offen": true})
Setzt den Zustand des Kanals auf das mitgegebene Objekt. Alle Clients, die den Kanal abboniert haben (außer dem Client, der put
aufruft), werden benachrichtigt. Dabei werden die Objekte gemerged, das heißt falls ein Key im aktuellen Zustand enthalten ist, im gegebenen Objekt aber nicht, bleibt dieser Key und der Wert dazu unverändert.
Geschützte Kanäle, wie z.B. status
, können nicht überschrieben werden.
Event abfangen
z.B. socket.on("steckdose:anschalten", callback)
Ruft callback
mit den Argumenten des Events auf, falls ein Client steckdose:anschalten
auslöst. Dazu muss der Kanal steckdose
abboniert sein (immer das was vor dem ersten :
steht). Mit once()
statt on()
wird das Event nur einmal empfangen, danach nicht mehr.
Aktuell können Clients ein Event auch selbst empfangen, wenn sie es auslösen. Mal schauen, ob das sinnvoll ist.
Event auslösen
z.B. socket.emit("steckdose:anschalten", <optionale Argumente>)
Löst das Event steckdose:anschalten
bei allen Clients aus, die einen Handler für das Event haben. Der Eventname muss aus zwei mit :
getrennten Teilen bestehen (um Events von serverseitigen Daten-Updates zu unterscheiden).
Rolle abbonieren
z.B. socket.emit("rollen:sub", "nachbar")
Abboniert als Client die Rolle nachbar
. Details zur Rolle erhält der Client dann über das Event rollen:rolle
:
{
"name": "Max",
"rolle": "Nachbar"
}
Rolle: Kanäle modifizieren
z.B. socket.emit("rollen:set", "nachbar", "sturzalarm", false)
Stellt den Zugriff auf sturzalarm
für die Rolle nachbar
auf false
.
Cache
z.B. socket.emit("cache:update", "kamera.jpg", "http://192.168.178.45:3000/photo", callback)
Lädt die Datei unter dem zweiten Argument herunter, und stellt sie in /cache/<fname>
zur Verfügung, wobei fname
vom ersten Argument gegeben wird.
Wenn optional ein callback gegeben ist, wird am Ende das callback aufgerufen mit dem Cache-Pfad als relativen (/cache/datei.jpg?1234
) URL. In allen Fällen wird auch cache:updated
mit dem gleichen URL als Argument aufgerufen, damit eventuelle Bridges die Datei auch cachen könnten.
status:anmelden
: Gerätesteuerung anmelden
z.B. socket.emit("status:anmelden", "fenster", callback)
Meldet die Gerätesteuerung anhand des ersten Arguments an. Zu jedem Gerätenamen kann nur eine Gerätesteuerung verbunden sein, um Fehler zu vermeiden. Es können aber mehrere Gerätesteuerungen den gleichen Kanal verwenden. Das ist der Fall beim Kühlschrank, wo die Gerätesteuerung dann zum Beispiel kuehlschrank.sensor
als Namen im ersten Argument angibt, und dann aber im Kanal kuehlschrank
schreibt, aber nur im Feld sensor
, und die Kameras in kameras
.
Das zweite Argument ist ein Callback, der mit dem Ergebnis der Anmeldung aufgerufen wird. Falls die Anmeldung geklappt hat, wird zurückgegeben:
{
erfolgreich: true,
aktiviert: true, // Ob das Gerät zu Beginn aktiviert sein soll (default: true)
config: {...} // Die Konfiguration für das Gerät
}
Ansonsten wird im Falle eines Fehlers zurückgeschickt:
{
erfolgreich: false
}
Der Prozess der Anmeldung ist auch in Grundlagen der API dargestellt.
status:aktivieren
: Gerät aktivieren
z.B. socket.emit("status:aktivieren", "mikrofon")
Aktiviert die Gerätesteuerung, die zu dem gegeben Namen (in der Regel Name des Kanals) gehört. Dazu wird das Event an den passenden Client weitergeleitet (Der Client der Gerätesteuerung erhält das Event status:aktivieren
ohne Argument).
Nur wenn die Gerätesteuerung aktiv ist, verarbeitet sie Events und updatet Daten. Gerätesteuerungen können außerdem eigene Handler für das (De)Aktivieren haben. So kann zum Beispiel das Mikrofon die Spracherkennung starten oder beenden.
status:deaktivieren
: Gerät deaktivieren
Genauso wie status:aktivieren
.
status:update
: Gerätestatus updaten
z.B. socket.emit("status:update", "sensfloor", true)
Über diese API Funktion kann eine Gerätesteuerung selbst den eigenen Status updaten. Aktuell betrifft das nur das Feld pending
, dessern Wert über das zweite Argument gegeben wird. Mit pending
kann angegeben werden, dass eine Statusänderung aussteht, aber noch nicht abgeschlossen ist. Zum Beispiel braucht der SensFloor etwas zum Starten, wenn er deaktiviert war und aktiviert wird. Wird das Feld dann wieder auf false gesetzt, ist die Statusänderung abgeschlossen.
extern:anmelden
: Externen Proxy anmelden
z.B. socket.emit("extern:anmelden", "<token>", callback)
Passt das Token, sendet der Server über das callback die Konfiguration des externen Proxy. Ein Token gibt es deswegen, weil in der Konfiguration API Keys stehen. Die API ist in Anlehung an status:anmelden
benannt, es wird vom Server aktuell aber nicht getrackt, ob der externe Proxy verbunden ist.
reset
: Smart Home zurücksetzen (Server neustarten)
Startet den smart-home-control Server neu, woraufhin eine neue Session ID generiert wird. Daraufhin starten auch alle Clients neu (dargestellt in Grundlagen der API). Beim Neustart werden alle Daten gelöscht.
neustart
: Smart Home neustarten
Startet über ein Skript, das von Ansible generiert wird, alle Raspis im Smart Home neu.
herunterfahren
: Smart Home herunterfahren
Fährt über ein Skript, das von Ansible generiert wird, alle Raspis im Smart Home herunter.
Plugins
Mit Plugins können dem Server zusätzliche, Kanal-spezifische (und damit meistens Gerät-spezifische) Funktionen hinzugefügt werden.
Das kann insbesondere sein, dass man Geräte ein- und ausschalten kann, was naturgemäß ein ausgeschaltetes Gerät nicht selbst machen kann. Aber zum Beispiel die WebPush Benachrichtigungen sind auch über ein Plugin (mit zugehörigem Kanal push-api
) implementiert.
Plugins liegen in smart-home-control/plugins.js
, wo auch ein Template für ein neues Plugin enthalten ist.
Verhalten im Falle eine Reconnects
Falls die Verbindung beim ersten Start geklappt hat, kümmert sich Socket.io selbst darum, verlorene Verbindungen wieder aufzubauen. Wenn das passiert, wird connect
im Client nochmal ausgelöst. Man muss dann allerdings nur nochmal sub
an den Server senden, aber nicht nochmal Socket.io Eventhandler (socket.on()
) initialisieren. Alternativ kann man mit socket.removeAllListeners("eventname")
zu Beginn jedes connect
die Handler zurücksetzen.