Webserver

In unseren letzten Blogbeiträgen haben wir erläutert wie die Hardware und die Software des eigentlichen Alarmsystems funktioniert. Da diese Komponenten mithilfe einer App steuerbar sein sollen, muss eine entsprechende Schnittstelle geschaffen werden. Dafür soll ein Webserver eingesetzt werden, da der Pi für die Kamera generell im Wlan das Hauses hängt und theoretisch auch von außerhalb ein Zugriff möglich wäre. Unsere Wahl fiel dafür auf Spring Boot, da es einfach zu entwickeln ist, kein JavaEE voraussetzt und trotzdem viele Funktionen bietet.

Da es möglich sein soll lediglich über die App die Alarmanlage zu steuern, muss der Webserver alle Funktionalitäten anbieten, die zum Steuern nötig sind. Genauer sind das die CRUD-Operationen für Regeln und Komponenten – Create, Read, Update & Delete. Dementsprechend muss der Webserver eine Ansprechstelle für fast jede der Funktionen anbieten. Diese greifen dann auf die Methoden der Klasse Alarmsystem zu, um die entsprechenden Operationen auszuführen. Um nun zu erklären wie genau der Webserver aufgebaut ist, muss jedoch erstmal die Funktionsweise von Spring Boot näher erläutert werden:

Eine Spring Boot-Applikation basiert auf verschiedenen Klassenarten: Der Application-Klasse, dem Webcontroller-Klasse und optionalle Konfigurations-Klassen. Die Application-Klasse ist dabei die Klasse, die gestartet wird und dann den Webserver hochfährt. Sie erkennt außerdem automatisch die Webcontroller-Klasse und Konfigurations-Klassen und bindet diese in den Server ein. Da entsprechende Klassen alle mit Annotationen versehen werden, kann Spring Boot diese von alleine erkennen und es muss in der Application-Klasse lediglich eine Main-Methode erstellt werden, welche den Server mit lediglich einem Befehl startet. Die nächste Klasse ist die Webcontroller-Klasse. In dieser werden alle Endpunkte des Webservers erstellt. Dabei könne alle HTTP-Methoden verwendet werden, wie auch Parameter. Ein Endpunkt wird dann als Methode der Klasse definiert und das Return-Objekt der Methode ist der Response der HTTP-Anfrage. Die große Besonderheit bei Spring Boot ist jedoch, dass dabei automatisch eine Umwandlung von Java-Klassen in JSON-Objekte vorgenommen wird. Somit ist die Schnittstellen-Definition um einiges simpler und auch einfach anzusprechen. Zusätzlich ist eine Umwandlung auch in die andere Richtung möglich, zum Beispiel bei einem Post-Request. Dafür wird mithilfe von Annotationen lediglich ein Input Paramter als Post-Body erklärt und sobald ein JSON-Objekt, welches kompatibel zum Parameter ist, eintrifft, wird dieses in ein instanziiertes Java-Objekt umgewandelt. Die letzten Klassen die für unsere Spring Boot-Applikation relevant ist, sind die Konfigurations-Klassen. Mit diesen können Einstellungen an der Spring Boot-Applikation verändert oder aktiviert werden. Dafür muss in der Regel lediglich eine Annotation zu der entsprechenden Klasse hinzugefügt werden und die Einstellungen sind beim nächsten Hochfahren aktiv.

Wie ist nun unser Webserver aufgebaut? Natürlich besitzt er die Application-Klasse, um den Webserver zu starten. Interessanter wird es bei der Webcontroller-Klasse. Hier gibt es nun Methoden für fast jede CRUD-Operation der beiden Klassen Rule und Component. Diese sind nach dem REST-Prinzip ansprechbar, also POST für CREATE, GET für READ, PUT für UPDATE und DELETE für DELETE. Die beiden GET-Methoden liefern dabei eine Liste aller Objekte zurück. Bei POST und UPDATE muss ein zur Klasse passender Body mitgeschickt werden und für DELETE die Id als Request-Parameter, welches Objekt gelöscht werden soll. Jedoch besteht eine Besonderheit bei der Klasse Component. Diese stellt, wie im letzten Beitrag erklärt, die Basisklasse für die Klassen Sensor und Aktor da. Da eine neue Komponente jedoch automatisch registriert werden soll, wird dafür natürlich keine POST/CREATE-Methode angeboten. Stattdessen wird eine Registration-Methode dargeboten, die einen sogenannten „Einwahlmodus“ aktiviert. Sobald ein Request an diese geschickt wird, nimmt das Alarmsystem für 60 Sekunden Anmeldungen von neuen Komponenten entgegen.

Generell steht damit der Webserver und die Applikation rudimentär ist lauffähig. Da hier aber eine Alarmanlage umgesetzt wird, die das Haus auch schützen soll, muss natürlich auch über Sicherheitsmaßnahmen des Servers nachgedacht werden. Deswegen ist es sinnvoll zumindest den Zugang mit einem Username und einem Passwort zuschützen. Zum Anmelden wird ein weiterer Endpunkt angeboten, der eben diese erwartet. Dies geschieht aktuell noch über die simple Übermittlung der Daten, kann aber noch später ausgebaut werden. Da es sich hier aber um eine HTTP-Schnittstelle handelt und HTTP zustandslos ist, muss noch weiter abgesichert werden, dass die Anfragen an die anderen Endpunkte von einem Gerät kommen, welches angemeldet ist. Dies geschieht mithilfe von Sessions. Sobald ein User sich anmeldet, wird ein Session-Attribut gesetzt, welches dies bestätigt. Mithilfe eines Cookies wird dann die Session gemerkt und sichergestellt, dass es sich um das gleiche Gerät handelt. Bei jeder Anfrage wird, dann das Attribut abgefragt, ob das Gerät angemeldet ist oder nicht. Sofern es das ist, wird die Anfrage problemlos ausgeführt, andernfalls wird diese mit dem Code 403(Unaouthorized) abgebrochen.

Jetzt muss nur noch geklärt werden, wie Sessions mit Spring Boot implementiert werden. Dies ist zum Glück sehr simpel. Dafür muss lediglich die Konfigurations-Klasse „HttpSessionConfig“ erstellt und mit der entsprechenden Annotation versehen werden. Dadurch sind Sessions automatisch im Webserver aktiviert. Ein weitere Zusatz ist jedoch erforderlich. Dadurch, dass Sessions in gewisser Weise persistent sind, müssen die Daten dafür irgendwo gespeichert werden. Spring Boot nutzt dafür Redis, einen In-Memory-Speicher. Dieses muss dann zur Zeit der Ausführung verfügbar sein und der Port und optionale Einwahldaten in einer Datei festgehalten werden, auf die Spring Boot Zugriff hat. Dadurch sind Sessions in Spring Boot einsetzbar.

Damit wäre die Schnittstelle zwischen der App oder jeglicher anderer webangebundener Software grundsätzlich umgesetzt. Weitere Funktionen können natürlich hinzugefügt werden, was aber aufgrund der einfachen und simplen Struktur von Spring Boot kein Problem darstellen sollte.

Ausführen auf dem Raspberry Pi

Ein Problem welches aber noch besprochen werden sollte, ist die Ausführung der Software auf dem Raspberry Pi. Generell geschieht dies wie in der Projektbeschreibung schon erläutert über die Java Virtual Machine(JVM). Aus dem Projekt wird eine Jar gebaut, die mithilfe der Overlays in Buildroot intigriert wird. In der Inittab wird diese dann hineingeschrieben, sodass sie bei jedem Neustart das Alarmsystem und der Webserver auch gestartet werden. Jedoch muss für den Webserver wie im oberen Abschnitt beschrieben auch Redis laufen. Zum Glück hat Buildroot einen Redis-Server eingebaut, der lediglich in der Konfiguration eingebaut ist. Sobald dieser hinzugefügt wird und ebenfalls in der Inittab gestartet wird, hat Spring Boot darauf Zugriff und kann die Sessions aufbauen.

Ein allerletztes Problem besteht jedoch leider noch. Beim ausführen der Komponente mit der UART Schnittstelle wird nach kurzer Zeit ein CoreDump von der JVM geschmissen. Um dem genauer auf den Grund zu gehen haben wir eine Jar gebaut, die lediglich Testdaten über die UART-Schnittstelle schreibt und gleichzeitig auch wieder liest. Dabei sind wir zu dem Ergebnis gekommen, dass der Fehler auftritt, wenn die Verbindung kurzfristig unterbrochen wird und es dem Programm nicht möglich ist, auf die Schnittstelle zu schreiben. Wie dieser Fehler in Verbindung mit der Funk-Hardware auftritt oder ob dies ein softwareseitig zu lösen ist, ist uns aktuell jedoch nicht bekannt. Sofern dieser Bug aber behoben wird, ist das Projekt grundlegend umgesetzt und es müsste nur noch ein Feinschliff vorgenommen werden.

Home Security: Zusammenbringen der App und des Backends auf dem Pi

Ein Kommentar zu „Home Security: Zusammenbringen der App und des Backends auf dem Pi

  • 1. Juli 2017 um 1:46 Uhr
    Permalink

    Machen Sie sich wegen der Benotung keine Sorge über den CoreDump. Arbeiten Sie lieber am Feinschliff, wenn Sie wollen. 🙂 Die Umsetzung mit SpringBoot finde ich übrigens sehr interessant.

Kommentare sind geschlossen.