IoT: Speichern & Anzeigen von Temperatursensordaten mit Azure Diensten
Wer sich mit Azure und Microsoft beschäftigt, kommt um das Thema IoT nicht herum. Es existieren zahlreiche spezialisierte Azure Dienste für IoT Szenarien.
Da wir bei BRICKMAKERS neben der Software auch eine ausgeprägte Leidenschaft zum Basteln pflegen, haben Philipp und ich ein IoT-Proof-of-Concept rund um die neuen Azure Services gebaut.
Uns ging es hierbei zunächst darum ein echtes Problem zu lösen und dies sinnvoll mit den neuesten Azure Technologien zu verbinden. Wir wollten ein kostengünstiges System bauen, mit dem man über Wlan Temperaturverlaufsdaten dauerhaft speichern und jederzeit abrufen kann. Dies ist z.B. bei der Vermietung von Ferienwohnungen interessant.
Dabei herausgekommen ist eine Architektur bestehend aus: Einem Mikrocontroller mit Wlan (ESP8266), DHT11 Temperatursensoren, Azure IoT Hub, Azure Stream Analytics, Azure Cosmos DB, Azure Functions und einer React Web App.
Was sich zunächst wie reines “Buzzword Bingo” anhört, hat durchaus eine praktische Relevanz und ist vor allem auch für große Business-Anwendungen interessant. Denn selbst bei einem so vermeintlich trivialen Anwendungsfall wie dem Messen von Lufttemperatur und Luftfeuchtigkeit fallen je nach Systemgröße enorme Datenmengen an, die sich mit IoT Hub und Co. elegant verarbeiten lassen. Mit der vorgehend beschriebenen Architektur lassen sich auch einzelne Teile leicht austauschen und/oder weitere Einzelservices integrieren. So könnte man z.B. neben dem Temperaturszenario noch weitere Sensoren hinzufügen. (z.B. Relais zur Überprüfung ob Fenster/Türen offen stehen o.ä.)
Im folgenden Artikel beschreiben wir die Architektur und Azure Services zum Erfassen, Verarbeiten, Speichern und Ausgeben von IoT Daten mit Code-Beispielen.
Erfassen und Speichern der IoT-Daten
IoT Device — ESP8266 Wifi Chip und DHT11 Sensor
Hinweise zur Einrichtung der Entwicklungsumgebung für den ESP8266 Wifi Chip findet ihr auf Philipp’s Blog. Wir verwenden den günstigen DHT11 Sensor zum Erfassen von Temperatur- und Luftfeuchtigkeitsdaten.
Mit dem hier verfügbaren Programm, das man auf den ESP8266 aufspielt, verbinden wir den ESP8266 Wifi Chip mit einem Wlan und senden die gemessene Temperatur und Luftfeuchtigkeit an das Azure IoT Hub. Um eine sichere Kommunikation zum IoT Hub zu gewährleisten, verwenden wir die Azure IoT Hub Arduino Library.
Folgende Abhänigigkeiten müssen noch installiert werden:
-
AzureIoTHub
-
AzureIoTUtility
-
AzureIoTProtocol_MQTT
-
ArduinoJson
-
DHT sensor library
-
Adafruit Unified Sensor
Da es für dieses Szenario ausreicht nur alle 15 Minuten Daten zu senden, haben wir den Deep Sleep Modus für den ESP8266 implementiert. So verbraucht der Chip wesentlich weniger Strom.
Azure IoT Hub
Im IoT Hub werden die angeschlossenen IoT-Geräte verwaltet und Zugriffsrechte verteilt. So kann sichergestellt werden, dass nur IoT-Geräte mit den entsprechenden Access Keys in das System schreiben können.
Das IoT Hub ist der erste Anlaufpunkt für die IoT-Daten, die von unseren Sensoren an das System gesendet werden. Da in einem IoT Szenario für gewöhnlich viele Geräte in kurzen Zyklen Daten einspeisen, ist es wichtig eine leistungsfähige Sammelstelle für diese Daten bereitzustellen.
Azure Stream Analytics
Der Dienst Stream Analytics eignet sich sowohl zur Echtzeitanalyse von Telemetriedaten als auch zur Weitergabe an Speicherdienste.
Für unsere Stream Analytics Instanz haben wir als Dateneingabe unsere IoT Hub Instanz und als Datenausgabe eine Cosmos DB konfiguriert. Die Cosmos DB hat den Vorteil, dass sie die JSON basierten Eingabedaten aus den IoT Geräten direkt als Dokument speichern kann. An dieser Stelle können aber auch SQL DBs, Blob Speicher, Event Hubs, Azure Table Storage, Power BI oder Azure Functions als Ausgabequellen definiert werden. Hier gibt es mehr Infos zu den Ausgabeoptionen von Stream Analytics.
Um die Daten für die Ausgabequelle passend zu transformieren, können über eine SQL-artige Abfragesprache Queries definiert werden.
In dieser sehr einfachen Abfrage werden die benötigten Felder für die Datenbank definiert und so unnütze Daten aus dem Payload entfernt.
Mit dem TIMESTAMP BY Keyword wird die Spalte definiert, die Stream Analytics als Zeitstempel für das Event verwenden soll. Dieser Zeitstempel kann entweder das Eintrittsdatum in das System oder ein vom Entwickler definiertes Feld sein. In diesem Fall macht es Sinn das eigentliche Messdatum zu verwenden, dass vom IoT-Gerät gesetzt wurde, da das Programm auf dem esp8266 Chip Nachrichten auch in einer Warteschlange parken kann, wenn z.B. kurzzeitig kein Internet verfügbar ist.
Azure Cosmos DB
Da Stream Analytics viele Datensenken ansprechen kann, ist die Wahl des Speichersystems nicht ganz einfach und hängt stark vom Einsatzszenario ab.
-
Wenn die nachträgliche Auswertung und Analyse in Verbindung mit bestehenden relationalen Daten ein Hauptanliegen ist, fährt man mit einer Azure SQL Datenbank gut
-
Wenn man sehr große teilstrukturierte Datenmengen erwartet, ist man mit einer NoSQL Lösung gut bedient
-
Falls man eine sehr günstige Form des Datenspeichers sucht, sollte man einen Blob-Storage verwenden
Wir haben uns in diesem Szenario für eine Cosmos DB entschieden, weil diese von Microsoft als Datensenke für teilstrukturierte JSON Daten empfohlen wird. Allerdings wären für unser Szenario auch die JSON Funktionen der Azure SQL Datenbank interessant.
Auslesen der IoT-Daten
Web App
Zum Anzeigen der Daten haben wir uns eine kleine React-basierte Single-Page-App geschrieben, die auf JSON Endpunkte zugreift, welche von Azure Functions bereitgestellt werden.
Die Technologien im Frontend sind React, Material UI und Recharts für die Diagramme.
Die Client-Anwendung wird auf einem Azure App Service gehostet. Die Rollouts auf den App Service werden über ein, im App Service gehostetes, Git-Repository gemacht. Hierbei trägt man die Adresse des App Service Git-Repository in dem lokalen Entwickler-Git-Repository als Remote ein und kann so den Webpack Build Ordner über Git auf den App Service pushen.
Vorher muss man diese Option noch bei Azure in den Deployment options des App Service freischalten.
Azure Function Appsfela pu
Um die Geräteliste aus dem IoT Hub und die Temperaturdaten aus der Cosmos DB auszulesen haben wir zwei Azure Functions aufgesetzt. Beide Functions sind in Node.js geschrieben. Node.js besitzt mit VSCode ein exzellentes Cross-Plattform-Tooling und die Functions Node.js Library hat eine gute Dokumentation.
Eine Function App ist im Endeffekt eine mini-API mit nur einem Endpunkt. Vorteile von Functions sind, dass man nur für sie bezahlt, wenn sie auch wirklich ausgeführt werden. 1 Million Requests pro Monat sind kostenlos. (wobei es hier auch noch ein Speicherlimit gibt; Mehr Details)
Ein sehr interessantes Feature von Azure Functions ist das Konzept von Triggern. So kann z.B. eine Function dann getriggert werden, wenn ein Messwert eines IoT-Geräts in eine Cosmos DB Collection geschrieben wird. Wenn der Messwert einen bestimmten Schwellwert überschreitet, kann man eine Benachrichtigung an einen Admin verschicken.
Dies ist nur eines von zahllosen Beispielen und Integrationsmöglichkeiten. Eine Doku aller Functions Trigger, findet ihr hier.
Wir nutzen in unserem Fall zwei Azure Functions mit je einem HTTP Trigger, bei dem die Function, wie eine “normale” REST-API einen HTTP-Request annimmt, verarbeitet und eine Response an den Anfragenden zurücksendet.
Auslesen der Geräteliste über die API des IoT Hub:
Nichts atemberaubendes… Aber gerade deshalb spannend, da man mit den gewohnten Programmierparadigmen Funktionen implementieren kann, ohne einen vollständigen App Service zu deployen.
Damit ein Client, in unserem Fall die Web App, auch auf die Functions Endpunkte zugreifen kann, muss die entsprechende Domain noch in den CORS Einstellungen der Function App hinterlegt werden. Im Azure Portal:
FUNCTION_NAME > Platform Features > CORSEhrlicherweise sollte man auch erwähnen, dass Azure Functions ebenso wie App Services in der Free Variante eine bestimmte Kaltstartzeit haben. Diese kann durch eine Reduktion von Code-Abhängigkeiten (z.B. npm Packages) verringert werden, ist aber in der Regel noch deutlich spürbar.
Mehr Infos zum Thema Azure Functions Lebenszyklus und Kaltstartzeit findet ihr hier.
Basis Info zu Azure Functions findet ihr hier.
Will man Azure Functions lokal debuggen, bietet sich das VS Code Plugin Azure Functions for Visual Studio Code an.
Fazit
Wie schon im Intro angedeutet ist dieser Artikel eher als oberflächlicher Einstieg in das Thema IoT und Serverless Computing zu verstehen. Zumindest sind wir mit diesem Vorsatz auch in das Thema gestartet.
Dies ist aus unserer Sicht auch wichtig um Erkenntnisse zu erlangen, wie man ein ähnliches Szenario mit komplexeren Anforderungen, mehr inhaltlicher Tiefe, etc. bearbeiten sollte.
Eine sehr positive Erkenntnis ist, dass man mit recht schonendem Ressourceneinsatz (entwicklungs- und ausgabenseitig) eine sehr performante und tragfähige Infrastruktur bauen kann. Hierbei ist das Iot Hub super geeignet, um viele unkontrolliert eintreffende Events zu verarbeiten und Cosmos DB liefert selbst bei vielen Datensätzen in der Datenbank gleichbleibende Queryzeiten.
Functions sind sehr interessant, aber entfalten ihre Vorteile nur in ganz bestimmten Szenarien. Als Ersatz für eine komplette Web API einer mittelgroßen Anwendung können wir uns eine Serverless Architektur (noch) nicht vorstellen, da bei einer steigenden Anzahl von Functions der Deployment- und Wartungsaufwand die Vorteile zunichte macht.
Wie bei den meisten neuen Azure Diensten ist die Doku ausgezeichnet. Es gibt viele Beispiele auf Github und sehr gute technische Artikel.
Eine für diesen Artikel war noch folgende Quelle hilfreich: http://gunnarpeipman.com/2016/02/beer-iot-using-stream-analytics-to-save-data-from-iot-hub-to-sql-database/