Wednesday, 24 January 2018

Presence Detection

Presence Detection in My House

One of the key features of my home automation server setup is multi-device presence detection.  By enabling many devices to infer your presence or absence, a surprisingly accurate view is enabled.  After all, you would not want your Security Alarm to go off when you are sleeping, simply because you failed to walk by your Nest Thermostat every hour...

\

Implementation


So how is this strategy implemented?  Well, I use an "enhanced" wasp-in-the-box algorithm, coupled with multiple sensors - mostly Bluetooth devices (like phones, Fitbit sensors, and key tags), as well as X10 window and door sensors.

But, the power of a server is that we are not limited to these devices - for example, if someone turns on a light through the web interface or by talking to the Google Home locally, you know that someone is home.  By combining these capabilities, a very comprehensive view of presence is enabled.

Wasp-in-the-box

Wasp-in-the-box, simply stated is:
1. If an outside door opens, assume everyone is away
2. If you detect someone in the house, set them to home

It is the "detect someone" that provides the power of this capability.  All of the tiny single-board computers I use for my server have built-in Bluetooth; all of our personal devices have it also.  I use l2ping on the server to periodically "ping" each of the Bluetooth devices in our house - our Android phones, a Tile Bluetooth key tag attached to the car keys, and a Fitbit, on someones wrist -  as well as pinging when key events happen (like a door opening).

The key here is to only use Bluetooth to confirm that you are home - if a personal device is not on, it will not respond to a ping - but you could still be in the house.  Whereas, if a door opens, you are pretty sure that someone has either entered or left - so it is a very good time to check.

The only downside of using Bluetooth as part of this capability is that it is slow (in computer terms) - I use a 2-second timeout before I give up looking, so there is a very small window where you don't know the status of a device.

Finally, if a door opens (and you were home before), and you cannot find any of your Fitbit, your key Tag, or your phone, and there is no motion detected in the house, then you can be pretty confident that the person is away - so it is time to run the Rules Checker (to turn on  the House Alarm and turn down the thermostat, for example).

At the same time, there are many methods to determine if someone is home - the X10 motion sensor, the use of the web interface, an infrared remote being used to turn on the  TV or stereo... in fact, if ANY device is used (manually), you know someone is home - this simple rule (in the Rules Checker) is used to update the presence status.

That is the power of multi-device detection - it all adds up.  Over the past year since I've had this capability in place, it has been wrong very few times - and it is much more effective than yelling "Hey Honey, are you home?" when you walk in the door...





Wednesday, 11 October 2017

X10 Home Security DIY - Rules Engine

X10 Home Security DIY - Rules Engine

Adding a json-based rules engine to our Home Automation DIY means we can make any action happen when any IoT device event triggers it.  This is a practical and flexible alternative to a commercial solution, or to using the (too many!) apps for each of our IoT devices.

This means we can turn on a light when the front door opens, or send a text message when the alarm triggers: the possible combinations are almost infinite (which is why it is better to do this with rules than with a big 'if' statement).

I am quite pleased with this addition to our home security DIY - we now have our house reacting to us (through our presence), instead of us having to explicitly control it by pressing buttons or running apps.  By controlling our IoT devices using rules, the house seems quite artificially intelligent...

Here's how we do it:

1. Each IoT device has its own html section (a module), its own JavaScript file to control the actions and display elements, and its own Perl CGI file to control access to the device API.  The Perl CGI resides on the server (a linux host; for us it is a Raspberry Pi running Raspbian and Apache); the JavaScript is run on the client.

To facilitate rapid communication of each IoT device state, a json file is used.  For example, the json file for our security module (Security.json) looks like this:

{"X10security":"off"}

That is, it is a simple json-format list of key:value pairs, stored in a file.  Any time the Perl file executes a command, it updates the json file (and returns it to the JavaScript client so that the web interface is updated).

2. The rules engine, coded in Perl, reads the current state of all of the IoT modules from the json files, and stores it in a Perl hash (associative array).  The rules themselves are also in a json file, and are structured as follows:
  • a rule name, e.g. "name":"Rule1"
  • a set of trigger events, e.g. "front_door_opened", any of which will cause the rule to be evaluated
  • a set of conditions, all of which must be true in order for the rule to fire
  • a set of actions which are performed if the rule is fired
Conditions are tested against the list of module states from the json files, whose values are all stored in the hash (associative array) to make the lookup easy.  A json-format rule looks like this:

{ "name": "Rule3a Motion sensed", 
      "triggers": [ "motion_sensor_activated" ],
      "conditions": [ { "module": "security", "name": "X10security", "value": "off" },
        { "module": "devices", "name": "wemo", "value": "off" } ],
      "actions": [ { "module": "devices", "name": "wemo", "value": "blink" } ]
},
 
The above rule basically reads "If the motion sensor triggers, and security is off, and the wemo device is also off, then set the wemo device to blink.

The actual rule-to-state comparison is:

First, we check that the trigger event matches at least one of the rule triggers:

     foreach my $ruletrigger (@$ruletriggers) {
       if ($trigger eq $ruletrigger) { $triggerresult = true; }
    }

Then, we check that all of the conditions are true:

  if ($triggerresult eq true) {
    my $overallconditionresult = true;
    foreach my $rulecondition (@$ruleconditions) {
      # look up the value/state of the condition name
      my $stateactual = $state{$rulecondition->{'module'}}{$rulecondition->{'name'}} ;
      my $conditionresult = eval ('$stateactual ' . eq . ' $conditionactual');
      if (!$conditionresult) {
        $overallconditionresult = false;
      }      
   }
}

Finally, if all of the conditions are met, we perform all of the actions (which will involve calling the Perl functions for each of the listed modules to execute the action, just like calling them from the Javascript files).

if ($overallconditionresult) {
 foreach my $action (@$ruleactions) {
         my $ret = `/usr/bin/perl $action->{'module'} -d "$action->{'name'}=$action->{'value'}" `;
 }

Now, by coding up a (remarkably short) set of rules, we can automate all kinds of things across our devices.  We can send all manner of notifications if the door opens, or we can turn lights, tv's, plugs, etc on or off.  We have implemented a presence detection algorithm in just two rules, and from there we automatically turn the security system on when we leave, and off when we come home.  By adding a 'heartbeat' using cron, we can make things happen at specific times.

In a future update, I'll post the complete code for the rules engine (just 300 lines!).

Monday, 28 August 2017

X10 Home Security DIY - Adding voice control and linking up with online services

X10 Home Security DIY - adding Voice Control with Google Home

The last phase of the implementation involves linking up the Home Automation server with the online world, to take advantage of Google Home and services like IFTTT

IFTTT makes it possible to (for example) schedule a light to turn on at dawn/dusk, to link a Google Home custom voice command with X10, or to have our lights turn red when Manchester United score!

Note that this is the opposite of using IFTTT for notifications - now, we want an external event to trigger an internal action.  This must be accomplished securely - we do not wish to forward a port through our router unless it is highly secure.  Most IoT devices that link to outside web services do it through a secure tunnel: for example, using ngrok.

Using ngrok, we will create a secure tunnel to our internal server: specifically, to the x10cmd.pl CGI script that drives the X10 CM15A.

So the steps are as follows:
1. Create an IFTTT account if you do not have one from the notification section.
2. Add the Webhooks service to your IFTTT account.
3. Create an App (recipe) to trigger on the weather channel, with the "Then" action being the Webhook - fill in the destination IP with your ngrok address (see below). 
4. Install and run ngrok on your server to point to the server port and the CGI script that contains your x10cmd.pl file.

The URL field in the IFTTT app is as follows (use either http or https):
http://serverid.ngrok.io/x10cmd.pl
Where:
  serverid - the URL reported by ngrok when you start it on your server.

The Method field is GET or POST.  With GET you paste the parameters into the URL field (e.g. append ?device=mydev&cmd=mycmd to the url).  With POST you specify the Content Type as application-x-www-form-urlencoded, paste the parameters into the body (e.g. device=A3&cmd=ON) (Note there is no ? needed in the body unlike in the URL).
Where:
  mydev - your internal X10 device id (e.g. A3)
  mycmd - you internal X10 command (e.g. ON or OFF)

For a voice command to do the same using Google Home, create an IFTTT app that triggers on Google Assistant instead.  Here, you can use a custom phrase (like "OK Google, turn the A3 light ON").  You can even use parameters in the trigger phrase, so that it only takes one app to trigger all of your devices; to do this, select the "Say a phrase with a text ingredient" type of Google Assistant trigger, and place $ in they phrase, and "text ingredient" in the action to send the paramter on to ngrok.



Friday, 9 December 2016

Home Security DIY - Updated Control Panel

Here is the updated Control Panel:

You will note the separate on/off buttons have been replaced with single sliders with active colours (blue background when "on", grey when "off").  This is much more like the kinds of settings screens you typically see on mobile devices.  they are easy to code also: just one line per control in the HTML and mostly one-line calls in Javascript.

I also played around with some of the tiling layout generators, but couldn't find anything that really kept the flexibility across phone/tablet/computer, and was lightweight enough not to take a hit on the performance.

The other differences are all in the Javascript code: I converted all the server calls to jQuery ($.get and $.getJSON).  On the server side, all the CGI scripts are in perl or python, depending on the service they are calling - which can be in perl (file I/O), python (lifxlan-master and Honeywell thermostat using therm.py), bash shell (for mochad and curl to web services like IFTTT, openweathermap/Dark Sky).

The big advantage of DIY is seen here - in total there are about 500 lines of code and they run lightning-fast.  It is clean and simple, has a common look-and-feel across all platforms , and when someone opens the front door, I get notifications on 7 different platforms (X10 devices, linphone, SSH, Google mail, IFTTT Maker, lifx, and notify-my-android).



Monday, 14 November 2016

X10 Home Security DIY - Arm / Disarm


Most home security systems come with an entry panel that is used to Arm or Disarm the system upon entry or exit.  Some come with key tags (or apps on your phone) that will arm or disarm the function automatically - we'll take a look at that option in a later post.  For now, let's look at implementing a simple arm and disarm function using a keycode.

There are several methods that can be used to implement this function on a web server:
  1. Using a global environment variable - purists would no doubt prefer this method, as it demonstrates their advanced coding skills and understanding of Linux environments.
  2. Using a file.  That is, you store the ARM/DISARM status in a file accessible from the server.  I prefer this method - it is similar to how passwords are stored, and the file can be encrypted and protected more easily.
We may also need to implement an arm delay - to allow for someone hitting the ARM button in the control panel just before opening the door and exiting the building.  Or maybe we just delay the disarm write until the very next window/door sensor event has completed.

Implementation


We modify the X10arm.pl script called from the control panel (when the ARM button is pressed) to open the X10.log file and write the status "X10 Alarm System is ARMED" into the file.  Similarly, we modify the X10disarm.pl script to write the status "X10 Alarm System is DISARMED" into the log file.

Now, when a trigger event happens (window/door sensor, motion sensor), we condition the notification response based on the X10 Alarm status (which we read from the X10.log file) in the bashX10.sh script.  If the system is ARMED, we send out all kinds of notifications; if the system is DISARMED, we limit the notifications (to flashing the lights, or popping up a desktop notification on my desktop, for example).

We further modify the X10disarm button to call a separate HTML file first - here is where we implement the keycode.  Instead of calling X10disarm.pl from the control panel HTML, we call security.htm instead - and this file contains a simple form to produce a keycode panel, as shown below:

 

Again, we use some nice styling to produce hover effects and shading (thankyou w3schools for the styling library), store the entered codes into a Javascript variable, and when the Submit button is pressed, we compare the submitted code to the stored and encrypted passcode, and then set the X10.log status to "X10 Alarm System is DISARMED" if the code matches.  We can even allow three attempts or some such method to prevent unauthorized access, but I wouldn't recommend relying on this method alone - after all, notifications would already have been sent out by the motion sensor or window/door sensor logic if someone unauthorized entered your building.  

Browser hackers will also note that the user could always right-click and select "inspect code" in Google Chrome in order to examine the html file and variables (which is another reason to put the keycode in a separate file), so we don't want to disallow all notifications.

A note on External Security of the Control Panel


If you expose your control panel to the internet (by providing a port forward through your router to the Abyss server port that services it) then you will need to implement at least SSL (https:) security.  Me, I prefer not to run the risk at all - the control panel and the entire server are only visible if you are connected to my LAN, and then again only if you are a recognized IP stored in the reservations list on my router.  It is simple enough to get a message or status out of my LAN (e.g. to IFTTT); it is very difficult indeed to get in.

Sunday, 6 November 2016

X10 Home Security DIY - Control


So we want a system that we can control from all devices - computers, tablets, and smartphones (iOS and Android).  Generally, this would imply developing apps for each platform, but there is one application that works on all these devices - an internet browser.

This means that if we develop the functionality to work on a server, and develop a set of mobile-friendly pages, then we can develop the control mechanism once, but access it from all devices using the browser - this is definitely the way to go for a DIY project.

From previous development efforts, I've found that the Abyss web server from Aprelium is a very flexible and easy-to-install server.  With a bit of HTML, Javascript, and CSS development knowledge it is remarkable how easy it is to develop websites.

The other key piece is the same mochad daemon that we use to catch X10 RF commands.  This function came with a set of scripts that have the ability to send out X10 powerline commands, so we can use it to control X10 devices by calling the commands directly from HTML buttons.

Control Flowchart



any LAN client --> LAN
--> Abyss web server on localhost:8080 -->
--> index.html Control Panel --> X10 powerline commands -->
--> mochad daemon running on port 1099 --> netcat TCP
--> X10 CM15A controller --> household wiring -->
--> X10 devices

At the same time, we can use the lifxlan-master scripts to send commands to LIFX bulbs on the LAN, and even send commands to IFTTT Maker channel to control other devices (like the Thermostat fan).  We'll integrate an ARM/DISARM function into the control panel (and add a numeric keypad for an access code) in a later post.

Here is the control panel.


Here's the html file that implements the control panel

A few comments on the code:

The file uses a simple table with buttons to perform the control functions.  A little bit of fancy styling is used to make the table and the buttons rounded, and perform some simple effects (like changing the cursor when it is over the buttons, and some simple animations to give the feedback that a button is clicked).  Each of the buttons then calls a perl script (x10cmd.pl) with parameters indicating the command to be performed. The perl script then calls the system function for the button - e.g. lifxlan-master for the LIFX bulb, or the x10cmd shell script for the x10 commands, and so on. 

The styling also makes the control panel usable from mobile devices (I tried to use very common-denominator styling so that it will work even from very old Android and iPhone phones).  This has the added advantage of raising the WAF (Wife Approval Factor), as it will work from her fancy new mobile phone as well.

The perl scipt x10cmd.pl gives simple feedback that the command was executed in a basic html page.  I plan to migrate all of this code, and the Abyss web server, to a standalone Linux PC so that it does not load down my desktop (although from what I have seen so far, it is hardly noticeable).

Sunday, 30 October 2016

X10 Home Security DIY - Notification


So, I've got some old X10 Pro stuff in a box, and I see what commercial products like iSmartAlarm can do, so here's the goal:

A do-it-yourself Home Security System not unlike iSmartAlarm:

  • A central hub
  • Window and door sensors
  • A motion sensor
  • Notifications
  • Arm and disarm functions on phones and tablets
  • A central control panel

My Proposal:


  • Use my desktop linux PC as the central hub, with the ActiveHomePro CM15A controller to receive RF events and to send out X10 powerline commands
  • Use my old X10 window and door sensors
  • Use the mochad linux TCP gateway to connect to the CM15A.  Mochad is a daemon that runs on a linux platform waiting for RF commands to be received and for powerline commands to be transmitted using the CM15A.
  • Use a bash script (bashX10.sh) to listen for events on the mochad port and to send various notifications, e.g.
  • Using linphonec for linux, Android and iPhone hosts to receive messages
  • Using curl to send to the IFTTT Maker channel, which can trigger all kinds of other things, like an events log in Google Drive, SMS messages to cell phones, and so on
  • Using lifxlan-master to send commands directly to LIFX bulbs over the LAN (rather than going through IFTTT, which is slower and requires internet access)
  • Using nc (netconnect) to initiate commands back to the cm15a - like the chime, and light and appliance modules

Notifications

The flowchart for notifications is as follows:




We send out notifications to:
- Android & iOS phones and linux desktops on my LAN (using linphone and notify-my-android)
- the IFTTT Maker channel (to Google Drive and to anywhere on the cloud)
- LIFX bulbs over my LAN using lifxlan-master
- X10 devices using x10cmd to send pl commands back through the CM15A

For now, the IFTTT link is used to keep a log of the notification events in Google Drive (see IFTTT to show how to link the IFTTT Maker channel to Google Drive in a simple recipe), and to notify my cell phone via SMS if I am not home.

The "at home" status is determined by pinging my cell phone on the LAN using nmap and awk from the bashX10.sh script.

References

[1] Lifxlan-master
[2] mochad
[3] linphone
[4] IFTTT

Alternatives:  

I could have used Home Assistant but they don't support the X10 RF sensors; someone has just started supporting mochad, but it is early days yet.  I could also have purchased an iSmartAlarm system, but where's the fun in that?  The incremental cost for this system is $0 - the hardware was sitting around doing nothing, and my time is (almost) free - and as you can see, I am leveraging the expert development efforts of many other fine developers who make their code freely available on the net.

Notifications: 

There are so many options for notifying to other devices, and chat on linphone is not exactly fit for this purpose (it is really a VOIP application, and the interface is quite finicky when used without a SIP account).

I've tried using SSH as well , but it only works on devices that are on the LAN and have SSH (available on Android, linux, and iOS, but not on a Chromebook without enabling Developer mode).

Pushover is a commercial choice, and the cost is quite reasonable - it can support notifications on phones, tablets, linux and windows computers, and chromebooks - it might be worth a try.

Pushbullet is another choice - free, but seems somehow to have lost its way, and it is not supported on my old Android cell.

I am presently using notify-my-android to push notifications to our Android phones when we are not home.  it is free for low volumes, and it is quite reliable.