Allgemein
Mit Hilfe der Azure Function wird die zentrale Nachrichtenstelle des Cloudservice implementiert. Hier werden alle Nachrichten verarbeitet, die vom IoT-Hub empfangen und an die Default-Route weitergeleitet werden. Die implementierte Azure-Function wird im weiteren Verlauf Smart Home Master genannt, da dies der Benennung in der Software entspricht.
Der Smart Home Master empfängt JSON-codierte Nachtrichten, deren Aufbau dem von Enocean entspricht. Derzeit können drei Nachrichtentypen verarbeitet werden. Telegram-, Device- und Command Nachrichten. Telegram- und Device-Nachrichten werden vom Gateway verwendet, um Informationen in die Cloud zu senden. Die Command Nachricht wurde von uns eingeführt. Sie ermöglicht Geräten, die nicht direkt programmiert werden können, Nachrichten an andere IoT-Geräte zu übermitteln.
Komponenten des Smart Home Masters
Der Smart Home Master besteht im Wesentlichen aus zwei Komponenten. Die Basisklasse ist die Annahmestelle für eingehenden Nachrichten. Sie decodiert entsprechend des Nachrichtentyps und leitet im Anschluss alle weiteren Aktionen ein. Der Datenbank Client ist für Kommunikation mit der SQL-Datenbank zuständig. Er verwaltet die Verbindung zum Datenbankserver, ordnet die Daten den entsprechenden Tabellen zu und versendet die SQL-Querys.

Wird eine Command Message empfangen, muss die empfangene Nachricht an das entsprechende Zielgerät weitergeleitet werden. Hierfür unterhält der Smart Home Master eine Clientverbindung zum IoT-Hub. Über diese kann er die Anweisung geben eine Cloud-to-Device Nachricht zu versenden. Das Zielgerät wird über den Inhalt der Command Message festgelegt.
Der Datenbank Client kann Geräte zur Datenbank hinzufügen oder Daten eines Gerätes speichern. Mit einer Device-Nachricht, wird dem Gateway mitgeteilt, dass ein neues Gerät hinzugefügt wurde oder sich die Konfiguration eines bestehenden Gerätes verändert hat. Der Datenbank Client liest den Gerätetyp aus der Nachricht und erstellt dementsprechend die SQL-Query. Mittels dieser wird überprüft, ob für die spezifizierte Geräteklasse schon eine Tabelle existiert. Ist dies nicht der Fall, wird eine entsprechende Tabelle erstellt. Im Anschluss wird geprüft, ob ein Eintrag in der Gerätetabelle besteht. Wenn nicht, wird ein Passender hinzugefügt. Diese Funktionalitäten sind innerhalb der SQL-Querys implementiert.
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'tabSocket')
BEGIN
CREATE TABLE tabSocket(
friendlyId VARCHAR(64) NOT NULL,
sensorTimeStamp VARCHAR(25) NOT NULL,
button VARCHAR(32),
buttonValue VARCHAR(32),
PRIMARY KEY (friendlyId, sensorTimeStamp)
);
END
Der Beispielcode zeigt die SQL-Query zum Erzeugen der Steckdosentabelle. Zuerst wird geprüft, ob bereits eine Tabelle für Steckdosen existiert. Wenn nicht, wird eine Tabelle mit den angegeben Spalten erstellt. Ist eine Steckdosentabelle vorhanden, wird nichts weiter gemacht.
Derzeit wird nur der Fall abgedeckt, dass ein Gerät neu hinzugefügt wurde. Änderungen an bestehenden Geräten werden derzeit nicht berücksichtigt. Folgende Device-Typen sind unterstützt:
- Temperatur Sensoren
- Bewegungsmelder
- Fenster/Tür Sensoren
- Lichtschalter
- Rollladen Schalter
Wird für ein bekanntes Gerät eine Nachricht des Typs Telegram empfangen, liegen neue Daten vor, die in der Datenbank abgespeichert werden sollen. Somit bekommt der Datenbank Client den Auftrag, die Daten an die Datenbank zu übertragen und in der, zum Gerät passenden, Tabelle abzuspeichern. Eine Query für diesen Fall kann folgendermaßen aussehen:
private string buildQueryStoreShutterSwitchData(Telegram payload)
{
return $@"
INSERT INTO tabShutterSwitch(friendlyId, sensorTimeStamp, button,
buttonValue)
VALUES
(
'{payload.friendlyId}',
'{ConvertFromUnixTimestamp(payload.timestamp)}',
'{payload.functions[0].key}',
'{payload.functions[0].value}'
);
";
}
Die Query wird von einer Funktion zusammengesetzt. Die Query selbst ist ein String, der an die Datenbank übertragen wird. Mit Hilfe der Spracheigenschaften von C# werden die aktuellen Daten im String ersetzt und können somit zur Datenbank gesendet werden.
Telegrammaufbau
Header
header" : {
"httpStatus" : null,
"code" : null,
"message" : null,
"content" : "telegram",
"gateway" : "DC-GW/EO-IP v1.0.12",
"timestamp" : 1559642972508
},
Jede Nachricht, besteht aus einem Header und einem nachrichtspezifischen Teil. Der Header enthält allgemeine Informationen, wie den Content, der die Art der Nachricht definiert, der Kennung des Gateways und einem Time-Stamp. Da der Wert Content des Headers beschreibt, um welchen Typ von Nachricht es sich handelt, muss dieser zuerst ausgewertet werden, bevor der Rest der Nachricht interpretiert werden kann.
Telegram Frame
"telegram" : {
"deviceId" : "050B5032",
"friendlyId" : "Steckdose1",
"physicalDevice" : "eSchalter",
"timestamp" : 1559642972508,
"direction" : "from",
"functions" : [ {
"key" : "buttonBI",
"channel" : null,
"value" : "released",
"meaning" : "Button released",
"unit" : null,
"timestamp" : null,
"age" : null,
"relatedDeviceId" : null,
"relatedFriendlyId" : null } ],
"signal" : null,
"telegramInfo" : {
"rorg" : "F6",
"data" : "40",
"status" : "30",
"dbm" : -58
}
}
Über den Telegram-Frame werden aktuelle Gerätedaten versendet. Es wird übermittelt, um welches Gerät es sich handelt, wann die Daten erfasst wurden und die eigentliche Payload. Diese ist unter functions zu finden. Sie ist als Array von Json-Objekten aufgebaut. Jedes dieser Objekte ist ein Key-Value Paar, mit zusätzlichen Metadaten.
Device Frame
"device" : {
"deviceId" : "050E720B",
"friendlyId" : "TemperaturHumidity_1",
"physicalDevice" : "Temperature",
"learnInProcedure" : "manuallyConfigured",
"eeps" : [ {
"eep" : "A5-04-02",
"variation" : null,
"version" : 0.9,
"direction" : "from",
"baseIdChannel" : null
} ],
"manufacturer" : null,
"location" : "D21 02.03",
"firstSeen" : 1559820902997,
"lastSeen" : null,
"secured" : false,
"functionGroups" : null,
"deviceType" : null,
"iotLabel" : null,
"productId" : null,
"remanState" : null,
"remanCode" : null,
"dbm" : null,
"softSmartAck" : false,
"transmitModes" : [ {
"key" : "temperature",
"transmitOnConnect" : true,
"transmitOnEvent" : true,
"transmitOnDuplicate" : false
}, {
"key" : "humidity",
"transmitOnConnect" : true,
"transmitOnEvent" : true,
"transmitOnDuplicate" : false
} ],
"configuration" : null,
"states" : null,
"operable" : true,
"supported" : true,
"deleted" : null
}
Über den Device Frame werden allgemeine Informationen zu einem Gerät übertragen. Es wird angegeben, welche Id ein Gerät hat, wie es heißt, wo es sich befindet und von welchem Hersteller es stammt. Es werden noch eine Vielzahl an Zusatzinformationen bereitgestellt, die ,an dieser Stelle, aber nicht von Bedeutung sind und nicht benötigt werden um die Basisfunktionalität zu gewährleisten.
Comand Frame
"comand" : {
"from" : "deviceName",
"to" : "deviceName",
"payload": ""
}
Ein Comand Frame dient dazu, eine Nachricht an ein anderes IoT-Gerät zu versenden, dass mit dem IoT-Hub verbunden ist. From und to geben Quelle und Ziel der Nachricht an und müssen den Gerätenamen im IoT-Hub entsprechen. In Payload kann ein beliebiger Nachrichtenstring gespeichert werden. Dies kann, bei Bedarf, auch ein Json-Objekt sein.