Designfrage [Heimautomation]

Hoeze

Lieutenant
Registriert
Juni 2010
Beiträge
701
Ich hab hier einen RaspberryPi, an den ein Türöffner sowie Kamera + Türsprechanlage angeschlossen sind.
Zusätzlich hab ich einen RPi als Benutzerschnittstelle.
Jetzt stellt sich die Frage, wie ich die Kommunikation realisiere.

Anforderungen:
+ möglichst sicher:
=> Authentifizierung über Client-Zertifikate
+ einfach erweiterbar, gut mit Scripten verwendbar
=> RESTful-API?
------------------------------------------------------------------------------------------------------

Grundsätzlich möchte ich nur Geräten Zugriff auf das System geben, welche dazu auch berechtigt sind.
=> OpenVPN/SSH-Tunnel​

Da ich wegen der Kamera sowieso schon einen Apache am Laufen habe, liegt es natürlich nahe, den auch gleich für die Türkontrolle weiterzuverwenden.
Allerdings hab ich dabei zwei Probleme:
+ Wie realisiere ich hier eine Rechteverwaltung (zertifikatsbasiert)?
+ Wie erstelle ich hier eine vernünftige REST-API?

Am einfachsten wäre es meiner Meinung nach, wenn ich die verschiedenen Funktionen in verschiedene Unterordner packe, und diese dann mit .htaccess - Dateien schütze:
+ www/rest/doorctl/open
+ www/rest/doorctl/close
+ www/rest/doorctl/.htaccess
Nur ist das leider nicht besonders elegant, was Rechteverwaltung angeht - ganz zu Schweigen, dass ich gar nicht weiß, ob man mit .htaccess auch Client-Zertifikate verwalten kann...


Was haltet ihr davon?


PS:
Noch ein kleines Logikproblem:
Türöffner wird gedrückt => Client sendet alle 250ms das Kommando "Tür öffnen" an die Türkontrolle.
Auf der Türkontrolle läuft ein Timer, welcher die Tür für 500ms offen hält. Das Kommando "Tür öffnen" soll diesen Timer zurücksetzen.
Wie kann man das auf einem Webserver lösen? Den Timer in eine Datei schreiben/lesen tötet nur die SD-Karte...
 
Kannst den Wert nicht einfach ins RAM schreiben lassen statt in eine Datei ?
Ansonsten würden sich kleine C Programme anbieten, die dann vom Webserver gestartet werden.

Was den login angeht, reicht dir SSH + public key nicht aus? Notfalls in SSH noch eine IP Range einstellen.
Nur das Gerät welches den Key besitzt kann sich einloggen, mit oder ohne passwort.
 
Zuletzt bearbeitet von einem Moderator:
Was ich davon halte? Kann man so machen. Wäre aber nicht mein persönlicher Favorit. Dein Ansatz ist nicht schlecht, daher möchte ich dir ein paar Denkanstöße für dein Projekt geben:

Ich fasse mal kurz zusammen. Du suchst:
  • Authentifizierung
  • Verschlüsselung
  • Restful API
  • Kommunikation mit deiner Hardware

Da du versuchst Zuständer deiner REST-API über den Apache in Dateien zu schreiben und die Geräte als Ordnerstruktur im Apache erzeugt sind, glaube ich, dass das eines deiner ersten Projekte dieser Größe und Komplexität ist. Daher mein erster Rat: YAGNI and KISS. Halte dein Projekt klein. Mache kleine Schritte, die Erfolg versprechen und baue darauf hin auf.

Was das technische angeht, wirst du ein größeres Framework brauchen. Das wird dich mit den Themen unterstützen. Meine Empfehlung wäre Django. Das kann alle die geforderten Eigenschaften. Jedoch wirst du viel Einarbeitungszeit benötigen, denn es ist kein kleines Framework und je nach Programmiererfahrung wirst du viel neues entdecken, das deine Gehirnzellen fordern wird. Meiner Meinung nach ist die Doku gut und umfangreich. Damit kannst du auch URLs dynamisch "erzeugen" und die Zugriffe werden nicht auf Ordner oder Dateien im Apache abgebildet.

Einen Gedanken zu der REST-API: Ein gutes Design für eine REST-API kann viel Zeit kosten. Für ein dein eigenes Heimprojekt solltest du dich sehr auf das Wesentliche beschränken.

Zu deinem Logikproblem: Hier brauchst du etwas Interprozesskommunikation. Dein Timer ist ein Prozess, der 500ms schläft. Läuft diese Zeit ab, wird der Prozess aufgeweckt und verriegelt das Schloss. Wir dein Prozess vorher aufgeweckt z.B. durch ein Interrupt-Signal, wird der Prozess einfach wieder für 500ms Schlafen gelegt. Das brauchst du in keine Datei zu schreiben.

btw: Auf deinen Pis läuft ein Linux. Daher kannst du Dateien auch im Ram erzeugen. Alles was unter /tmp liegt, liegt im Ram. (Ja, ich weiß. Irgendwann vielleicht auch im Swap auf der SD-Karte.) So lange dein Ram ausreicht, kannst du dort Dateien erzeugen und beliebig beschreiben.
 
rob- schrieb:
Kannst den Wert nicht einfach ins RAM schreiben lassen statt in eine Datei ?
Ansonsten würden sich kleine C Programme anbieten, die dann vom Webserver gestartet werden.

Nunja, wie kann ich (in python) eine Variable eines anderen Prozesses ändern?

rob- schrieb:
Was den login angeht, reicht dir SSH + public key nicht aus? Notfalls in SSH noch eine IP Range einstellen.
Nur das Gerät welches den Key besitzt kann sich einloggen, mit oder ohne passwort.

SSH + PublicKey funktioniert natürlich, aber dann müsste ich für jeden Anwendungszweck einen neuen User anlegen... Muss ich mir überlegen...
 
Dann bieten sich dir noch "Shared Memory" an, ist praktisch wie eine Datei, aber die Show läuft im RAM ab.
Damit lassen sich auch Zugriffsrechte recht leicht umsetzen.
http://man7.org/linux/man-pages/man7/shm_overview.7.html

Wie man SM / POSIX API in Python nutzt musst mal schauen, geht aber definitiv.
 
Zuletzt bearbeitet von einem Moderator:
Ich schreibe sowas auf ne RAM-Disk um die Speicherkarte zu schonen. Geht halt nur solange das kleine Dateien sind. Ein Counter würde da schon gehen. Aus Bequemlichkeit habe ich ein schon vorhandenes Verzeichnis mit tmpfs-Dateisystem zum Ablegen verwendet (Ist glaub ich /run).
 
Ungeziefer schrieb:
Was das technische angeht, wirst du ein größeres Framework brauchen. Das wird dich mit den Themen unterstützen. Meine Empfehlung wäre Django. Das kann alle die geforderten Eigenschaften. Jedoch wirst du viel Einarbeitungszeit benötigen, denn es ist kein kleines Framework und je nach Programmiererfahrung wirst du viel neues entdecken, das deine Gehirnzellen fordern wird. Meiner Meinung nach ist die Doku gut und umfangreich. Damit kannst du auch URLs dynamisch "erzeugen" und die Zugriffe werden nicht auf Ordner oder Dateien im Apache abgebildet.

Vielen Dank für deinen Post, das war echt hilfreich :)
Dann werd ich mir jetzt mal Django näher ansehen.
 
Ungeziefer schrieb:
Was das technische angeht, wirst du ein größeres Framework brauchen. Das wird dich mit den Themen unterstützen. Meine Empfehlung wäre Django. Das kann alle die geforderten Eigenschaften. Jedoch wirst du viel Einarbeitungszeit benötigen, denn es ist kein kleines Framework und je nach Programmiererfahrung wirst du viel neues entdecken, das deine Gehirnzellen fordern wird. Meiner Meinung nach ist die Doku gut und umfangreich. Damit kannst du auch URLs dynamisch "erzeugen" und die Zugriffe werden nicht auf Ordner oder Dateien im Apache abgebildet.

Mit Verlaub, dann ist das doch genau die falsche Empfehlung. Was Hoeze bauen will ist alles andere als komplex und benötigt daher kein (wirklich gutes) Fullstack-Framework bei dem er sich erstmal viel einlesen will. Er braucht kein Template-System, keine Forms, keine Datenbankanbindung kein nichts.
Was er sucht ist im Prinzip ein total einfaches "Micro-Framework" welches in HTTP-Responses erstellen lässt, im Best-Case ist das direkt auf REST ausgelegt. Und von denen gibt es doch wirklich genug, und ich gebe extra keine Empfehlungen weil der Thread sonst ausartet wie Threads über Programmiersprachen, jeder preist seinen Liebling an.

Im Prinzip benötigt er doch nur solche Dinge (Pseudocode):
Code:
:url matches "/doorctl/open":
    if(isOpenDoor())
        return HTTP=4xx, Status="Already Open"

    openDoor()
    return HTTP=200, Status="Success"
 
ice-breaker schrieb:
Mit Verlaub, dann ist das doch genau die falsche Empfehlung. Was Hoeze bauen will ist alles andere als komplex und benötigt daher kein (wirklich gutes) Fullstack-Framework bei dem er sich erstmal viel einlesen will. Er braucht kein Template-System, keine Forms, keine Datenbankanbindung kein nichts.

Wenn es ausschließlich darum geht mit einem HTTP-Aufruf eine Türe zu öffnen, dann stimme ich dir voll und ganz zu. Mit Django dieses kleine Problem zu lösen, ist einfach nur ein Overkill.

Aber die Anforderung an das Projekt ist (so wie ich das verstanden hab): Authentifizierung, Verschlüsselung und REST-API. Diese Punkte sind alle keine Trivialitäten. Meiner Meinung nach ist es besser ein bestehendes Framework zu nutzen, das diese Anforderungen erfüllt, bevor ich es selber neu implementiere. Vor allem für eine sichere Verschlüsselung und eine saubere REST-API braucht es ein umfangreiches Werkzeug. Django ist ein mögliches Werkzeug dafür.

ice-breaker schrieb:
Was er sucht ist im Prinzip ein total einfaches "Micro-Framework" welches in HTTP-Responses erstellen lässt, im Best-Case ist das direkt auf REST ausgelegt. Und von denen gibt es doch wirklich genug,[...]
Leider kenne ich nicht so viele Frameworks, die RESTful URL-Designs ermöglichen. (Webentwicklung ist nicht meine Spezialität.) Daher hätten mich Alternativen schon interessiert.
 
Ungeziefer schrieb:
Leider kenne ich nicht so viele Frameworks, die RESTful URL-Designs ermöglichen. (Webentwicklung ist nicht meine Spezialität.) Daher hätten mich Alternativen schon interessiert.

Meine Paradedisziplin ist java, allerdings sind java-Programme nicht so flexibel wie Scripte.
Python benutze ich hingegen nicht allzu oft, von daher wärs schon nicht schlecht, mal so ein paar Meinungen über solche Frameworks zu hören :)
 
Keine Framework-Empfehlung, aber ein alternativer Ansatz wäre nodejs zu verwenden. Habe damit die Beleuchtungssteuerung auf meinem Pi mit API und einfachem Webinterface realisiert.
Begründung: Webserver mit PHP/Perl oder als App-Proxy konfiguriert ist auf dem Raspberry Pi ganz schön resourcenhungrig (zumindest auf dem alten Pi). nodejs gehört mit seinem Event-getriebenen JavaScript nicht zu meiner Lieblingssprache, ein Webserver lässt sich aber in wenigen Zeilen realisieren, mit integrierter API oder via npm nachinstallierbaren Paketen lässt sich auch einfach eine RESTful API implementieren ("express" -> route). JavaScript hat auch keine Probleme mit JSON :D
Pakete für Low-Level-Zugriff auf die I/O-Pins gibt's auch und das Timerproblem löst sich auch fast von alleine.

Auf der folgenden Seite ist ein einfacher HTTPS-Server mit Zertifikaten implementiert: http://nategood.com/nodejs-ssl-client-cert-auth-api-rest

Falls du doch mit was anderem globale Timer via Lockfile realisieren willst und /tmp bei dir nicht im RAM liegt (wie auf meinem Pi), dann in der Datei /etc/fstab einen mountpoint des Typs tmpfs anlegen und dort die Datei speichern, dann sollte die im Arbeitsspeicher landen solange Platz ist (sonst swap). Bei mir ist z.B. /run ein tmpfs.

tl;dr: Generell wäre nodejs nicht meine erste Wahl, aber gerade auf dem Raspberry Pi ist damit für deine Anforderungen eine sehr effiziente Lösung möglich. Auf meinem Licht-Pi sind insgesamt 50MB RAM belegt (Raspbian inklusive btsync, tmux und laufendem Node-Script)
 
Hoeze schrieb:
Meine Paradedisziplin ist java, allerdings sind java-Programme nicht so flexibel wie Scripte.[...]

Mit Java lässt sich dieses Problem auch lösen. Damit ziehst du auch ein paar Dickschiffe an aber ein anderer Ansatz wäre mit einem Java Applicaion Server bzw. Wildfly (ehem. JBoss). Da sind auch Authentifizierung, Zertifikate und Verschlüsselung machbar. Es ist nur eben auch alles nicht ganz einfach. ;) Mit JSF und Ablegern kannst du die Urls abbilden. Die Kommunikation mit der HW sollte auch gehen aber ohne konkretere Hinweise kann ich keine Tipps geben.

Java würde ich nicht unflexibel nennen. Es ist nicht so leicht zusammen "gehackt" wie Python oder Bash.
 
Zurück
Oben