I’ve always dreamed of having a “smart-home.” There’s just something cool about being able to flip switches and read sensors and have a program turn a light on when you open the door, but only if it’s dark. This post is about home automation.

UPDATE: I made a video demoing everything:



I learned a lot during the process and am still learning. There are all these low-power sensors and things that use a radio technology called Z-wave. Basically, you know about wifi and bluetooth. Well there’s also Z-wave and Zigbee and some others that are made to be really low-powered, low-bandwidth for (possibly battery-powered) internet-of-things devices like switches, sensors, lights, etc. So I got some zwave stuff.

Here’s the hardware I have:

HUE color-changing LED lights can be controlled from my phone or laptop whether I’m in the house or out of it A door sensor tells me when the door is open or closed. A security camera can pivot around the apartment and see what it looks like A Multisensor records temperature, relative humidity, light, and UV, and has alarms for motion and jiggling I have two in-line plug-switches. One that turns on and off a big light and the other that turns on and off my space heater A router with DD-WRT installed set up as a VPN server (so I can securely access my home network when away) A Raspberry Pi 2 with a Z-wave Aeon Z-stick USB dongle

With those components, I can do all sorts of neat things, like:

Turn the heat on when I’m on my way home so it’s warm when I get there

Turn lights on and off from afar

Get notifications on my phone if there’s motion when I’m not home or if the temperature drops below a certain value

See how much energy (in kWh) I’ve used for heat

See neat graphs of temperature and light vs. time throughout the day.

If I walk towards the bathroom in the middle of the night, turn on a dim red light so I can see. Turn it off automatically in a few minutes.

Here’s what the control panel looks like. It’s just a webpage on my local network. It works from the laptop, the phone, the tablet, etc.

Setting it all up

There are off-the-shelf hubs that can do a lot of this that most people would be happy with. That just isn’t me. I really like open-source stuff, I don’t want my home hosted by some third-party company (no “cloud”), I do a lot of programming in Python, and I like Raspberry Pis. I chose to try home-assistant as the driver of all my automation, and have been really happy with it, but I did have to contribute to it a bit to get it working properly, which is really fun. So here’s what I did. Hopefully this will help someone who’s searching for info.

Raspberry Pi 2, home-assistant, and the Aeon Z-Stick

Home-assistant needs Python 3.4, so the first thing you have to do is make sure your Raspberry Pi 2 has at a Raspbian OS based on Debian Jessie on it. Upgrade like this. Then, install home-assistant as described on their webpage. The complex part is building the openzwave library to give home-assistant access to the Z-wave stuff. The current home-assistant instructions work, but you won’t get good support for newer devices like the Aeon Multisensor 6. I’ve been working on unforking the library but there are some lingering issues. If you want to just install my fork, it will work (checkout the python3 branch).

UPDATE: With version 0.15 of home-assistant, unforking the library has been accomplished. You can now use the current home-assistant instructions.

I recommend making an alias for your Z-stick so it always shows up as /dev/zwave

instead of, like, /dev/ttyACM0 or /dev/ttyACM1 . You can do this by running

$ udevadm info -a -n /dev/ttyACM0 1 $ udevadm info -a -n /dev/ttyACM0

and noting the idVendor, and idProduct, then add a line to new file, /etc/udev/rules.d/99-usb-serial.rules :

SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="zwave" 1 SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="zwave"

Configuring the Aeon Labs Multisensor 6

This multisensor is pretty cool but by default it only sends updates once an hour. When on battery, this makes sense because this will drain the battery in like a year, and more frequent updates would drain it faster. But if you plug it in to power, you’ll probably want quicker updates. I figured out how to adjust the configuration using the python-openzwave library that was installed above. Here is an example script that does some config of stuff. Run it with ipython3 or python3.

(UPDATE: You can alternatively use the web-gui ozwcp. )

from openzwave.option import ZWaveOption options = ZWaveOption('/dev/zwave', config_path='/home/pi/python-openzwave/openzwave/config', user_path='.', cmd_line='') # or /usr/local/share/python-openzwave/config if installed # /home/pi/python-openzwave/openzwave/config if testing options.set_append_log_file(False) options.set_console_output(True) options.set_save_log_level('Debug') options.set_logging(False) options.lock() from openzwave.network import ZWaveNetwork network = ZWaveNetwork(options, log=None) node2 = network.nodes[2] print(node2.product_name) # this is the multisensor on my network. Yours may be a different node. # get current config values node2.get_sensors() node2.request_all_config_params() # set timing and stuff on multisensor node2.request_config_param(111) # this shows the current interval (3600 seconds) node2.set_config_param(111, 120) # set the temperature sensor interval to 120 seconds node2.set_config_param(3, 125) # set motion sensor On duration to just over 2 minutes. (shorter and it never registers as on!) # set reporting of power level on Aeon smart energy switches node5.set_config_param(101,2) # send multisensor info about power node5.set_config_param(111,20) # send it every 20 seconds. network.stop() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from openzwave . option import ZWaveOption options = ZWaveOption ( '/dev/zwave' , config_path = '/home/pi/python-openzwave/openzwave/config' , user_path = '.' , cmd_line = '' ) # or /usr/local/share/python-openzwave/config if installed # /home/pi/python-openzwave/openzwave/config if testing options . set_append_log_file ( False ) options . set_console_output ( True ) options . set_save_log_level ( 'Debug' ) options . set_logging ( False ) options . lock ( ) from openzwave . network import ZWaveNetwork network = ZWaveNetwork ( options , log = None ) node2 = network . nodes [ 2 ] print ( node2 . product_name ) # this is the multisensor on my network. Yours may be a different node. # get current config values node2 . get_sensors ( ) node2 . request_all_config_params ( ) # set timing and stuff on multisensor node2 . request_config_param ( 111 ) # this shows the current interval (3600 seconds) node2 . set_config_param ( 111 , 120 ) # set the temperature sensor interval to 120 seconds node2 . set_config_param ( 3 , 125 ) # set motion sensor On duration to just over 2 minutes. (shorter and it never registers as on!) # set reporting of power level on Aeon smart energy switches node5 . set_config_param ( 101 , 2 ) # send multisensor info about power node5 . set_config_param ( 111 , 20 ) # send it every 20 seconds. network . stop ( )

So yeah, that’s cool. You can poke around and do lots of low-level zwave stuff with that. The api-demo.py that comes with python-openzwave is pretty interesting if you want to learn more.

Then, to get the multisensor to turn a Phillips HUE light on red on motion in the middle of the night (assuming you’re heading for the bathroom), try this:

automation: - alias: Turn on light on motion trigger: platform: state entity_id: sensor.aeotec_multisensor_6_burglar from: '0' to: '8' action: service: light.turn_on entity_id: light.living_room data: brightness: 254 rgb_color: [255, 0, 0] condition: - platform: time before: '05:00' - platform: time after: '01:00' - platform: numeric_state entity_id: sensor.aeotec_multisensor_6_luminance # At least one of the following required below: 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 automation : - alias : Turn on light on motion trigger : platform : state entity_id : sensor.aeotec_multisensor_6_burglar from : '0' to : '8' action : service : light.turn_on entity_id : light.living_room data : brightness : 254 rgb_color : [255 , 0 , 0 ] condition : - platform : time before : '05 :00' - platform : time after : '01 :00' - platform : numeric_state entity_id : sensor.aeotec_multisensor_6_luminance # At least one of the following required below : 4

You’ll want another rule to turn it off later, like a few minutes after the motion sensor stops seeing motion. Anyway you get the idea.

The installation of the custom fork of python-openzwave is the biggest pain right now. Hopefully we’ll get that all worked out soon so this will be easier.

I run home-assistant in a screen instance, though there are more correct ways to get it to work when you log off the raspberry pi.

Oh and for notifications on my phone, I set up an Instapush account using this component. My config for this isn’t perfect but I am getting notifications.

automation: - alias: 'Alert on Low temperature' trigger: platform: numeric_state entity_id: sensor.aeotec_multisensor_6_temperature below: 18.0 action: service: notify.notify data: message: 'Temperature at Apt Low' notify: name: notify platform: instapush api_key: [redacted] app_secret: [redacted] event: motion tracker: sensor 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 automation : - alias : 'Alert on Low temperature' trigger : platform : numeric_state entity_id : sensor.aeotec_multisensor_6_temperature below : 18.0 action : service : notify.notify data : message : 'Temperature at Apt Low' notify : name : notify platform : instapush api_key : [redacted] app_secret : [redacted] event : motion tracker : sensor

Next steps

I have to get more serious history plots working with InFluxDB. There’s a ticket for that. I got it and graphana compiled on the Raspberry Pi after some efforts following these instructions. The dependency phantomjs takes like 2 days to build on the Raspberry Pi so I got a pre-built one from here. It worked but I wish I could have built it myself.

More lights!

Z-wave smoke detector

The original motivation for learning this was to monitor my mom’s house for furnace breaks when she’s away so the pipes don’t freeze. Her house could also use a flood sensor in case the pipes break and flood the basement like they did in like 1989.

Hope that helps someone.

Oh, and one thing I’ve had trouble with is when I unplug the Z-stick (ZW090) from the Raspberry Pi and plug it in to my laptop, I see nothing at all in /dev/ for it, and no messages from dmesg. It’s like, dead to the usb. I even tried pressing the reset button and cannot for the life of me get it to reappear. When I plug it back into the pi, it works fine. If anyone knows how to fix this, let me know!

UPDATE: It was just a bad USB connection. I put it in a different computer and it worked fine. A USB extension cable also works!

UPDATE 2: I just added Infrared capabilities and can now control my A/C, TV, and stereo too.