Ein Smarthome bietet eine Menge Möglichkeiten. Heute kann fast alles in diesem Zusammenhang miteinander verbunden werden und dadurch mehr Bequemlichkeit, Wohnqualität, Kosteneinsparungen und Sicherheit ermöglichen. Möchte man von unterwegs über das Internet zugreifen, gibt es aber Gefahren.
Von der Beleuchtung über die Heizung und Kameraüberwachung bis zur Waschmaschine lässt sich heute alles mit einem Smarthome verbinden. Das ist bequem und wenn man sich daran gewöhnt hat, möchte man meistens einige Funktionen auch unterwegs mobil nutzen können.
Dafür es es aber erforderlich, das eigene System über das Internet erreichbar zu machen. Damit sind Sie aber auch von außen viel stärker angreifbar. Sie müssen sich regelmäßig mit Updates versorgen und Ihr System aktuell halten. Ein Restrisiko bleibt aber dennoch bestehen, auch wenn man mit einem Raspberry Pi unter Debian mit einem sehr sicheren System arbeitet.
Ich bin aus diesen Gründen momentan noch nicht bereit, mein System für das Internet zu öffnen. Trotzdem hätte ich gerne eine Möglichkeit, die Vorteile mobil zu nutzen.
Da aber der Smarthome-Rechner meist trotzdem mit dem Internet verbunden ist, warum nicht diese bestehenden Verbindung nutzen? Damit ist vielleicht nicht die schönste Lösung realisierbar, aber vielleicht erst einmal eine sichere.
Eine Mail-Steuerung
Ich möchte hier einen Lösungsvorschlag für so eine mögliche Zwischenstufe vorstellen: eine E-Mail-Steuerung.
Auf dem Rechner mit der Smarthome-Software läuft eine weitere Software, die in regelmäßigen Abständen ein bestimmtes Mail-Postfach auf Nachrichten überprüft. Wenn eine Nachricht bestimmte Kriterien erfüllt, werden von der Software Aktionen auf dem Smarthome-Rechner ausgeführt.
In meinem Fall ist das ein Raspberry Pi. Über einen Cron-Job wird regelmäßig alle 5 min mein Smarthome-Mail-Postfach auf neue Nachrichten abgefragt. Welches Intervall möglich ist, hängt aber vom jeweiligen Mail-Anbieter ab. Manche Anbieter lassen nicht alle Intervalle zu.
Um auch hier eine hohe Sicherheit zu gewährleisten, müssen mehrere Bedingungen erfüllt sein, bevor eine Aktion vom Programm ausgelöst wird. Welche das sind, ist in der folgenden Abbildung dargestellt.
Ein Beispiel für eine Mail könnte so aussehen:
Von: name@provider.de An: smarthome@provider.de Betreff: SH Nachrichtentext:**STATUS **LICHT_WZ_AUS
Nur wenn im Betreff SH steht, der Absender name@provider.de eine Berechtigung hat und gültige Befehle (**STATUS, **LICHT..) enthalten sind, nur dann werden Aktionen ausgeführt.
Beispiele für Befehle:
**STATUS Könnte eine Mail an den Absender zurückschicken und in den Nachrichtentext interessante Zustände liefern, z. B. welche Türen sind offen, welche Lichter sind an usw.
**REBOOT Führt einen Neustart des Raspberry Pi’s durch. Das ist zwar nicht oft erforderlich, aber machmal doch praktisch.
Es können aber auch Aktoren gesetzt werden, um z. B. ein Licht auszuschalten. Durch den Zeitversatz des Mailabrufs, ist das natürlich nicht für eine direkte Steuerung sinnvoll. Aber so könnte ein vergessenes Licht noch ausgeschaltet werden. In meinem Fall erfolgt das über dieses Kommando.
**LICHT_WZ_AUS Schaltet z. B. das Licht im Wohnzimmer aus.
**…
Realisierung mit Lazarus und Freepascal
Das Abrufen der Nachrichten von der Mailbox erfolgt über das IMAP-Protokoll. Dafür sind mehrere Einstellungen, abhängig vom Mail-Provider, notwendig. Im Quellcode werden die Werte als Konstanten hinterlegt.
IMAP_HOST = 'imap.1und1.com'; IMAP_PORT = '993'; MAIL_USER = 'smarthome@ihreadresse.de'; MAIL_PASSWORD = 'geheim';
Lazarus stellt von Haus aus keine Funktionen zum Arbeiten mit Mails zur Verfügung. Es gibt aber eine sehr gute Bibliothek von Synapse von Ararat. Den Download-Link dazu finden Sie am Ende des Artikels. Entpacken Sie das Archiv in einen beliebigen Ordner und fügen den Ordner dem Projekt hinzu. Alternativ können Sie auch im Projektinspektor auf HINZUFÜGEN: DATEIEN AUS DEM DATEISYSTEM klicken und die Datei imapsend.pas im Synapse-Ordner auswählen.
Dafür ist die Arbeit mit der Bibliothek sehr einfach. Die Prüfung auf neuen Nachrichten und das Auslösen von Aktionen findet in einer einzigen Prozedur CheckMailbox statt.
procedure CheckMailbox; var s, user : string; j, cnt ,spcnt : integer; mail : TStringList; Imap : TIMAPSend; MimeMess : TMimeMess; MimePart : TMimePart; begin mail:=TStringList.Create; imap:=TIMAPSend.create; MimeMess:=TMimeMess.Create; //Einstellungen für IMAP Imap.TargetHost:=IMAP_HOST; Imap.TargetPort:=IMAP_PORT; Imap.UserName:=MAIL_USER; Imap.Password:=MAIL_PASSWORD; Imap.AutoTLS:=false; Imap.FullSSL:=false; if Imap.Login then begin //Gibt es neue ungelesene Nachrichten?? cnt:=Imap.StatusFolder('INBOX','UNSEEN'); if cnt>0 then begin Output('Es gibt '+IntToStr(cnt)+' neue Nachricht(en)'); Imap.SelectFolder('INBOX'); //Ordner Inbox auswählen //neue Nachrichten einzeln durchlaufen for j:=Imap.SelectedCount-Imap.SelectedRecent+1 to Imap.SelectedCount do begin Imap.FetchMess(j,MimeMess.Lines); //Nachricht abholen MimeMess.DecodeMessage; Output(''); Output('---'); output('Prüfung: '+MimeMess.Header.Subject+' von '+MimeMess.Header.From); //Prüfen, ob eine Aktions-Mail vorliegt if (ValidUsers.IsValid(MimeMess.Header.From)=true) and (Uppercase(MimeMess.Header.Subject)=ACTION_SUBJECT) then begin mail.Clear; user:=MimeMess.Header.From; spcnt:=MimeMess.MessagePart.GetSubPartCount(); Output('>>> Gültige Mail'); if spcnt>0 then for cnt:=0 to {spcnt-1} 0 do begin MimePart:=MimeMess.MessagePart.GetSubPart(cnt); MimePart.DecodePart; mail.Add(MimePart.Primary); mail.Add(MimePart.Secondary); setlength(s,MimePart.DecodedLines.Size); MimePart.DecodedLines.Read(s[1],length(s)); mail.Add(s); end else mail.AddStrings(MimeMess.MessagePart.Lines); //output(mail.Text); //Gibt es Aktionen?? //Welche Aktionen sollen ausgeführt werden?? if Pos('**STATUS',mail.Text)>0 then ActionStateMail(user); if Pos('**LICHT_WZ_EIN',mail.Text)>0 then ActionRunScript('/home/pi/scripts/licht_wz_ein'); if Pos('**LICHT_WZ_AUS',mail.Text)>0 then ActionRunScript('/home/pi/scripts/licht_wz_aus'); if Pos('**REBOOT',mail.Text)>0 then ActionRunScript('/home/pi/scripts/reboot_pi'); if Pos('**HELP',mail.Text)>0 then ActionHelp(user); end; end; end else Output('Es gibt keine neuen Nachrichten!'); end else Output('Login fehlgeschlagen!'); MimeMess.Free; Imap.free; mail.Free; end;
Aktionen ausführen
Im letzten Teil der obigen Prozedur werden mögliche Aktionen definiert, die Sie ermöglichen möchten.
Hier gibt es nur Ihren Einfallsreichtum als Grenze. Im Quellcode habe ich zwei Grundfunktionen als Beispiel eingebaut.
a) Mail senden
Um eine Mail zu senden, wird eine weitere Prozedur SendToEx von Synape benutzt.
function SendMail(const MailTo, Subject : string; const MailData: TStrings) : boolean; begin Result:=SendToEx(MAIL_USER, MailTo, Subject, SMTP_HOST, MailData, MAIL_USER, MAIL_PASSWORD); end;
Die Konstanten MAIL_USER, MAIL_PASSWORD sind bereits bei der Mail-Abfrage definiert worden. Für das Senden eines Mails ist noch der SMTP-Host erforderlich.
Für den Anbieter 1und1 wäre das beispielsweise:
SMTP_HOST = 'smtp.1und1.com';
Ein Beispiel für die Anwendung könnte eine Status-Mail über interessante Zustände im Smarthome sein. In meinem Fall stehen die Statuswerte als Textfiles auf dem Raspberry Pi zur Verfügung. Diese Dateien werden eingelesen und in einen Text umgesetzt. Der gesamte Text wird in einer TStringList gespeichert und am Ende als Mail-Text versendet.
procedure ActionStateMail(user : string); var mailtext,datei : TStringList; i : integer; begin mailtext:=TStringList.Create; datei:=TStringList.Create; mailtext.Add('Status im Smarthome:'); mailtext.Add(''); datei.LoadFromFile('/var/www/status/garagentor.txt'); if datei[0]='1' then mailtext.Add('Garagentor: GESCHLOSSEN') else mailtext.Add('Garagentor: OFFEN'); datei.LoadFromFile('/var/www/status/garagentuer.txt'); if datei[0]='1' then mailtext.Add('Garagentüre: GESCHLOSSEN') else mailtext.Add('Garagentüre: OFFEN'); datei.LoadFromFile('/var/www/status/kaninchen.txt'); if datei[0]='1' then mailtext.Add('Kaninchen: GEFÜTTERT') else mailtext.Add('Kaninchen: HUNGRIG'); //Codierung anpassen auf Ansi for i:=0 to mailtext.Count-1 do mailtext[i]:=UTF8ToAnsi(mailtext[i]); //Mail verschicken SendMail(user,'Smarthome: Status',mailtext); Output('Befehl **STATUS ausgeführt.'); mailtext.Free; datei.Free; end;
b) Skripte/andere Programme ausführen
Unter Lazarus und Freepascal gibt eine Reihe von Möglichkeiten, wie andere Programme oder Skripte gestartet werden können.
Wenn man plattformübergreifend arbeiten möchte, eignet sich das Objekt TProcess recht gut.
procedure ActionRunScript(script : string); var Process : TProcess; begin Process:=TProcess.Create(nil); Process.CommandLine:=script; Process.Options:=Process.Options+[poWaitOnExit]; Process.Execute; Process.Free; Output('Befehl '+script+' ausgeführt.'); end;
Beispiel-Projekt und Ausblick
Im Download-Bereich finden Sie ein Beispiel-Projekt für eine Konsolenanwendung. Sie basiert auf den oben beschriebenen Quelltexten. Sie können es sowohl unter Windows, wie auch unter Linux benutzen.
Für einen sinnvollen Einsatz müssen Sie es aber regelmäßig über Cron aufrufen.
Falls keine neue Mail im Postfach ist, sieht die Anwendung aus, wie in folgendem Bild dargestellt:
Ein Beispiel dafür, dass eine neue Mail mit dem entsprechenden Schlüsselwort da ist, sieht wie in dieser Abbildung aus:
Passen Sie doch die Konstanten in mailcheck.pas auf Ihr Mail-Postfach an und entwickeln Sie das Projekt für Ihren Anwendungsfall weiter. Mit ein wenig HTML könnte eine Antwort-Mail mit einem Smarthome-Status beispielsweise eine schickere Optik bekommen.
Vielleicht finden Sie ja auch eine noch viel bessere Möglichkeit diese Steuerungsart zu nutzen.
Viel Erfolg!
Download
Für die Kompilierung benötigen Sie die Library Synapse. Diese können Sie unter http://synapse.ararat.cz/doku.php/download finden. Haben Sie Lazarus noch nicht auf Ihrem Rechner installiert, schauen Sie sich am besten den Artikel Lazarus installieren an.
Links
Artikel von Michaël Van Canneyt zum Senden von Mails mit Lazarus
https://www.freepascal.org/~michael/articles/lazmail/lazmail-en.pdf
Wikipedia-Artikel zu IMAP
https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol
Wiki von Lazarus über TProcess
http://wiki.freepascal.org/Executing_External_Programs/de
Wiki über Synapse
http://wiki.freepascal.org/Synapse
Wikipedia-Eintrag zu Cron
https://de.wikipedia.org/wiki/Cron
Installation von Lazarus / Freepascal
Pingback: Control you smarthome with mails – Tech+Code