A smarthome offers a lot of possibilities. Today, almost everything can be interconnected in this context, providing more convenience, quality of living, cost savings and security. If you want to access via the Internet, there are still some risks.
Starting from lighting to heating or camera surveillance to your washing machine – almost everything can now be connected to a smarthome. This is convenient and once you get used to it, you usually want to be able to have some functions not only in the local LAN.
But then it is necessary to make your system accessible via the Internet. With this step you are much more vulnerable from outside. You need to keep your system always up to date. A residual risk remains, even if you work with a Raspberry Pi under Debian with a very secure system.
Because of this I am currently not ready to open my system for the Internet. Nevertheless, I would like to use the advantages.
But the smarthome computer is usually still connected to the Internet via your network and a router. Why not use this existing connection? This may not be the most beautiful solution possible, but a safe one.
A Mail ControlI would like to show you an example of this solution for such a possible intermediate stage: an e-mail control.
On your computer with the smarthome software, another software checks regularly your mailbox. When a message meets certain criteria, the software starts actions.
In my case the smarthome computer is a Raspberry Pi. A cron job regularly – every 5 minutes – checks my special smarthome mailbox for new messages. Which minimum interval is possible depends on the mail provider. Some providers do not allow small intervals.
To ensure a high level of security here, several conditions must be met before an action is triggered. What are these steps? You’ll find mine in the following figure.
An example of an e-mail for a query might look like this:
From:name@provider.de
To:smarthome@provider.de
Subject: SH
Message:
**STATE
**LIGHT_G_OFF
Only if the subject is SH and the sender adress name@provider.de has permission and valid commands are included ( **STATE, **LIGHT.. ), the actions are performed by the software.
Examples of commands:
** STATE Could send back an email with interesting states in the message body, e. g. doors are open, which lights are on, etc.
** REBOOT Reboots the Raspberry Pi. This is not often necessary, but sometimes useful.
But you can also set actuators as a light. By the time offset of mail retrieval, which is obviously not useful for a direct control. But a forgotten light could be turned off. In my case it works with this command:
** LIGHT_G_OFF Turns off the lights in the garage.
** …
Realization with Lazarus and Free PascalFor the coding of this application I use Pascal as programming language. This may be not so common for Raspberry programs, but is quite interesting, if you want to compile to real binary code and use it on other platforms too. You'll find Lazarus under http://www.lazarus-ide.org/.
You fetch messages from the mailbox via the IMAP protocol. To do this there are several settingsnecessary – depending on your mail provider. In the source code, the values are stored as constants.
IMAP_HOST = 'imap.1und1.com';
IMAP_PORT = '993'; //or 143
MAIL_USER = 'smarthome@ihreadresse.de';
MAIL_PASSWORD = 'secret';
Lazarus does not provide functions working with mails by default. But there is a very good library Synapse from Ararat. You can find the download link at the end of this article. Unpack the archive to any folder and add the folder to the project. Alternatively, you click ADD FILES FROM THE FILE SYSTEM in the project inspector and select imapsend.pas in Synapse folder.
Programming the library is very simple. In the sample application all steps to check the mailbox for new mails is stored in the procedure CheckMailbox.
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;
//Settings for 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
//Are the new messages?
cnt:=Imap.StatusFolder('INBOX','UNSEEN');
if cnt>0 then
begin
Output('There are new mails ('+IntToStr(cnt)+').');
Imap.SelectFolder('INBOX'); //select Inbox
//check every new mail
for j:=Imap.SelectedCount-Imap.SelectedRecent+1 to Imap.SelectedCount do
begin
Imap.FetchMess(j,MimeMess.Lines); //fetch mail
MimeMess.DecodeMessage;
Output('');
Output('---');
output('Checking: '+MimeMess.Header.Subject+' from '+MimeMess.Header.From);
//check valid user and valid subject?
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('>>> Valid 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??
//Which actions should be executed?
if Pos('**STATE',mail.Text)>0 then ActionStateMail(user);
if Pos('**LIGHT_G_ON',mail.Text)>0 then ActionRunScript('/home/pi/scripts/light_g_on');
if Pos('**LIGHT_G_OFF',mail.Text)>0 then ActionRunScript('/home/pi/scripts/light_g_off');
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('There are no new mails');
end else Output('Login failed!');
MimeMess.Free;
Imap.free;
mail.Free;
end;
Perform ActionsIn the last part of the above procedure your possible actions are defined. Only your imagination is the limit! In the source code I have installed two basic functions as an example.
a) Mail
To send an email, another procedure is SendToEx of Synape used.
function Sendmail(const MailTo, Subject: string; const Mail Data: TStrings): boolean;
begin
Result: = SendToEx(MAIL_USER, MailTo, Subject, smtp_host, Maildata, MAIL_USER, MAIL_PASSWORD);
end;
The constants MAIL_USER, MAIL_PASSWORD have already been defined. The SMTP host is still required to send a mail.
Here is an example for the provider 1und1:
SMTP_Host = 'smtp.1und1.com';
A useful function could be a status mail about interesting states in your smart home. In my case, the status values are available as text files on the Raspberry Pi. These files are read and converted into a text. All text is stored in a TStringList and copied to the mail body text.
b) Run scripts / start programs
Lazarus and Free Pascal offer a number of ways to start other programs or scripts. If you want to work across platforms, the object TProcess is quite well.
ActionRunScript procedure (script: string);
var Process: TProcess;
begin
Process: = TProcess.Create (nil);
Process.CommandLine: = script;
Process.Options: = Process.Options + [poWaitOnExit];
Process.Execute;
Process.Free;
Output('command ' + script + ' executed.');
end;
Example Project and OutlookIn the download area you can find an example project for a console application. It is based on the above-described source code. You can use it with Windows or Linux.
But for a meaningful use, you must regularly run it with Cron.
If there is no new mail in your mailbox, the application looks like this:
Test application mailchecker: no new mails!
An example when there are new messages with the appropriate keyword looks like that:
Test application mailchecker: new mails!
Update the constants in mailcheck.pas to your mailbox settings and develop the project for your application. Maybe with a little HTML, a reply e-mail could show a smarthome state, which is a little bit more stylish.
You might also find better ways to use this control mode.
Good look for your experiments!
You'll find some more information about this and Lazarus on my website.
Comments