Hallo,
In den letzten Wochen habe ich die Softwarestruktur meines IoT-Servers grundlegend überarbeitet.
Dieser lief und läuft auch weiterhin auf einem RaspberryPi 3B. Als Betriebssystem verwende ich WindowsIoT. Diese Wahl habe ich getroffen, um den Server in C# programmieren zu können. Bisher war dies allerdings nur über sogenannte "Background Tasks" möglich. Diese sind praktisch im Webinterface zu verwalten und können Remote per VisualStudio debuggt werden. Allerdings haben sie den Nachteil, dass sie wie Windows-Store-Apps gewissen Einschränkungen unterliegen.
Dazu gehört, dass sie nicht auf beliebige Dateien im Dateisystem zugreifen können, sondern nur Zugriff auf einen zur App gehörenden Ordner haben. Eine weitere Einschränkung ist, dass Code nicht dynamisch nachgeladen werden kann. Während das am Anfang nicht unbedingt ein Problem darstellte, hat das Projekt mittlerweile eine gewisse Größe erreicht. Dadurch nimmt die Übertragung des Projekts auf den Raspberry beim Debuggen viel Zeit in Anspruch. Daher wollte ich eine Aufspaltung des Projektes in den "Core-Server" und Plugins durchführen. Praktisch kann man diese Unterteilung in verschiedene Assemblys auch mit Background-Tasks durchführen, jedoch müssen alle verwendeten Assemblys in der gleichen Projektmappe liegen.
.NET Core Anwendung
Als ich mit der Programmierung des Servers 2016 begonnen habe, war ich auf die Background-Tasks angewiesen, da es keine relevanten Alternativen gab. Mittlerweile gibt es jedoch .NET Core Anwendungen. Diese ermöglichen die Programmierung von C# Anwendungen, theoretisch Plattform- und Architekturabhängig. Jedoch muss für jede Plattform/Architektur-Kombination eine passende Runtime-Umgebung installiert werden. Die offiziell freigegebenen sind [hier] erhältlich, die noch in der Entwicklung befindlichen (dazu gehört aktuell auch WindowsIoT auf dem Raspberry) dagegen [hier]. Da es aktuell noch keinen Installer für WindowsIoT gibt, habe ich die Dateien aus dem ZIP-Archiv einfach in den Windows/System32 Ordner kopiert.
Nun musste meine Server-Anwendung noch von "IoT-Background-Task" auf ".Net Core Anwendung" umgestellt werden. Da es dafür keine triviale Möglichkeit gibt, habe ich einfach eine neue Projektmappe mit den gleichen Projekten angelegt und die Quelldateien rüberkopiert. Dabei habe ich festgestellt, dass einige verwendete Klassen bzw. Namespaces hier nicht existieren. Die entsprechenden Codeabschnitte mussten also auf alternative Klassen umgestellt werden. Das betrifft konkret die Bereiche TCP/UDP-Kommunikation, sowie Dateisystemzugriff und Datenverschlüsselung. Außerdem muss ein neuer Programmeinstiegspunkt angelegt werden.
Sind alle Umstellungen abgeschlossen und wird die Projektmappe erfolgreich kompiliert, so kann das Startprojekt (in meinem Fall "HomeAutomationServerLauncher") via Rechtsclick und "Veröffentlichen" freigegeben werden. Dabei sollte darauf geachtet werden, dass als "Target-Runtime" "Portable" oder die Runtime des Zielsystems ausgewählt wird. Läuft dieser Prozess ohne Fehler durch, so liegen die erzeugten Dateien im "Target-Location"-Ordner.
In den letzten Wochen habe ich die Softwarestruktur meines IoT-Servers grundlegend überarbeitet.
Dieser lief und läuft auch weiterhin auf einem RaspberryPi 3B. Als Betriebssystem verwende ich WindowsIoT. Diese Wahl habe ich getroffen, um den Server in C# programmieren zu können. Bisher war dies allerdings nur über sogenannte "Background Tasks" möglich. Diese sind praktisch im Webinterface zu verwalten und können Remote per VisualStudio debuggt werden. Allerdings haben sie den Nachteil, dass sie wie Windows-Store-Apps gewissen Einschränkungen unterliegen.
Dazu gehört, dass sie nicht auf beliebige Dateien im Dateisystem zugreifen können, sondern nur Zugriff auf einen zur App gehörenden Ordner haben. Eine weitere Einschränkung ist, dass Code nicht dynamisch nachgeladen werden kann. Während das am Anfang nicht unbedingt ein Problem darstellte, hat das Projekt mittlerweile eine gewisse Größe erreicht. Dadurch nimmt die Übertragung des Projekts auf den Raspberry beim Debuggen viel Zeit in Anspruch. Daher wollte ich eine Aufspaltung des Projektes in den "Core-Server" und Plugins durchführen. Praktisch kann man diese Unterteilung in verschiedene Assemblys auch mit Background-Tasks durchführen, jedoch müssen alle verwendeten Assemblys in der gleichen Projektmappe liegen.
.NET Core Anwendung
Als ich mit der Programmierung des Servers 2016 begonnen habe, war ich auf die Background-Tasks angewiesen, da es keine relevanten Alternativen gab. Mittlerweile gibt es jedoch .NET Core Anwendungen. Diese ermöglichen die Programmierung von C# Anwendungen, theoretisch Plattform- und Architekturabhängig. Jedoch muss für jede Plattform/Architektur-Kombination eine passende Runtime-Umgebung installiert werden. Die offiziell freigegebenen sind [hier] erhältlich, die noch in der Entwicklung befindlichen (dazu gehört aktuell auch WindowsIoT auf dem Raspberry) dagegen [hier]. Da es aktuell noch keinen Installer für WindowsIoT gibt, habe ich die Dateien aus dem ZIP-Archiv einfach in den Windows/System32 Ordner kopiert.
Nun musste meine Server-Anwendung noch von "IoT-Background-Task" auf ".Net Core Anwendung" umgestellt werden. Da es dafür keine triviale Möglichkeit gibt, habe ich einfach eine neue Projektmappe mit den gleichen Projekten angelegt und die Quelldateien rüberkopiert. Dabei habe ich festgestellt, dass einige verwendete Klassen bzw. Namespaces hier nicht existieren. Die entsprechenden Codeabschnitte mussten also auf alternative Klassen umgestellt werden. Das betrifft konkret die Bereiche TCP/UDP-Kommunikation, sowie Dateisystemzugriff und Datenverschlüsselung. Außerdem muss ein neuer Programmeinstiegspunkt angelegt werden.
Sind alle Umstellungen abgeschlossen und wird die Projektmappe erfolgreich kompiliert, so kann das Startprojekt (in meinem Fall "HomeAutomationServerLauncher") via Rechtsclick und "Veröffentlichen" freigegeben werden. Dabei sollte darauf geachtet werden, dass als "Target-Runtime" "Portable" oder die Runtime des Zielsystems ausgewählt wird. Läuft dieser Prozess ohne Fehler durch, so liegen die erzeugten Dateien im "Target-Location"-Ordner.
Veröffentlichen eines Projektes unter Visual Studio |
Das erzeugte Projekt befindet sich anschließend in "Target-Location" |
Beim Betrachten der erzeugten Dateien fällt auf, dass keine ausführbare Datei (".exe") dabei ist. Diese wird nicht benötigt, da wir mit der "dotnet.exe" aus der .NET Runtime bereits eine solche haben. Das Programm kann also nun über PowerShell oder einer anderen Console per
dotnet "C:\Program Files\HomeAutomationServer\HomeAutomationServerLauncher.dll"
gestartet werden.
Autostart mit dem TaskScheduler
Um die Anwendung automatisch nach dem Start des Betriebssystems auszuführen, habe ich diesen Befehl in eine Batch-Datei geschrieben und diesen an den Windows-TaskScheduler angehängt. Dazu habe ich folgenden Befehl verwendet:
Die Anwendung wird nun also bei jedem Windows-Start ausgeführt. Um die Anwendung sofort zu starten, kann man die Ausführung mit folgendem Befehl auslösen:
Um die Anwendung wieder aus dem Scheduler zu entfernen, kann folgener Befehl verwendet werden:
Plugins
Da der Server nun nicht mehr in einer Sandbox läuft, kann er auch Assemblys und damit Plugins nachladen. Deswegen habe ich damit begonnen, einige Abschnitte in Plugins auszulagern. Angefangen habe ich mit der Alexa-Implementierung, da sich diese dafür besonders angeboten hat.
Bisherige Alexa-Kommunikations-Struktur |
Der Grund dafür ist, dass der HTTP-Server, welcher die Alexa-Requests aus dem Internet bearbeitet, bisher in ein virtuelles Gerät ausgelagert war, welches ebenfalls als Background-Task auf dem Raspberry lief und sich intern mit dem Server verbunden hat. Nun läuft dieser als Plugin direkt auf dem Server. Gleichzeitig habe ich die zu Alexa gehörenden Logikelemente an diese Veränderung angepasst und mit in das Plugin ausgelagert. Beim Start des Servers sucht dieser nun im Plugin-Ordner nach ladbaren Assemblys und versucht in darin Plugins zu finden, welche daraufhin geladen werden.
Neue Alexa-Kommunikations-Struktur |
Die Struktur mit Plugins wird es mir in Zukunft ermöglichen, den Server variabler zu gestalten und weiter zu einer einfacheren Handhabung zu verbessern. Zudem wird es, sollte ich mich jemals für eine Veröffentlichung des Projektes entscheiden, Nutzern ermöglichen, selbst den Server zu erweitern.