Setting Up the Raspberry Pi 3 for Home Assistant

A guide to set up a Raspberry Pi 3 with Home Assistant.

Igor Shults

With the recent news that Nest’s Revolv was going to shut down its services, I was happy to have chosen open-source for my home automation stack. I’ve been seeing posts crop up on Twitter and Reddit about wanting an “offline” solution (one that works even without the Internet, but still functions within a LAN), and decided to share my experiences with setting up a brand new Raspberry Pi 3 with the open-source Home Assistant platform. As a warning, I must say that I AM still new to this, so I apologize in advance for any errors, but I figured I would share my information as it may help a few people who run across the same issues I had. Hopefully this information doesn’t become too outdated too soon.

Why

An open-source home automation platform ensures that your data is safe, secure, and always available when you need it. You control the system, so you are not reliant on any third-party for services or data (which also means you have no one to blame but yourself if something goes wrong!). I picked Home Assistant partially to start learning more Python (I’m mostly a JVM guy), but I’ve heard great things about other frameworks such as OpenHAB. I chose the Pi 3 for its enhanced processor and built-in Wifi/Bluetooth capability. If you prefer slightly less manual configuration (especially for something like Z-Wave), then you may want to check out the Docker image for Home Assistant as well.

Prerequisites

Before starting setup, there are a few things you may need:

  • A Raspberry Pi 3 running Raspbian Jessie. The Raspberry Pi site has a great installation guide. - A micro SD card for the Pi. - A power charger/adapter for the Pi (I used an old cell phone charger). - Basic knowledge of Linux Bash commands. - Basic knowledge of YAML. - A mouse, keyboard, and HDMI display + cable (temporarily) - (Optional) Knowledge of Python if you plan on adding features. Also useful for debugging.

If you don’t have all of these, I’d recommend spending the ~$50 to purchase the materials, and a few weekends to brush up on the above.

Configuring the Pi

To start off, I’m going to assume that you can boot into your Raspberry Pi and you have Raspbian Jessie running (Home Assistant recommends this version as it has Python 3.4 already installed). You should hopefully have a mouse, keyboard, and display to interface with it. The very first thing you’ll want to do is configure it for your locale and timezone. Next you ~can~ should change your password. Finally, we’ll connect to Wifi (if you’re not wired) and update the OS from the terminal. After all of these you may need to restart. Here is a cheatsheet:

# Update Locale/Timezone
Menu -> Preferences -> Raspberry Pi Configuration -> Localisation -> Set Locale... or Set Timezone...

# Change Keyboard Layout
Menu -> Preferences -> Keyboard and Mouse -> Keyboard -> Keyboard Layout

# Change password
Menu -> Preferences -> Raspberry Pi Configuration -> System -> Change Password...

# Access the outside world!
Click Wifi symbol -> Choose network, enter password

# Update OS (from the Terminal)
sudo apt-get update
sudo apt-get dist-upgrade

# Reboot (from the Terminal)
sudo reboot

Installing TightVNC for remote access

Ideally we would like to control the Pi from our main machine(s), rather than having to log into every time. If you don’t mind a dedicated “command station” for the Pi, then you can skip this part. First we’ll install the TightVNC server:

sudo apt-get install tightvncserver

To set up a password and make sure it works, you can run:

tightvncserver -geometry 1600x900 :1

Next up, we’ll set it up to run automatically on boot (otherwise we have to manually login to the Pi after each reboot):

sudo nano /etc/systemd/system/vncserver@:1.service

# Paste this into the file:

  [Unit]
  Description=Remote desktop service (VNC)
  After=syslog.target network.target

  [Service]
  Type=forking
  User=pi
  #PAMName=login
  #PIDFile=/home/pi/.vnc/%H%i.pid
  #ExecStartPre=/usr/bin/vncserver -kill %i
  ExecStart=/usr/bin/vncserver -geometry 1600x900 %i
  ExecStop=/usr/bin/vncserver -kill %i

  [Install]
  WantedBy=multi-user.target

I’ve left a few lines in there that are commented out that seemed to cause issues (or were unnecessary) for me, but seemed like it may help in some configurations. As a note, you will probably want to configure the line that starts with “ExecStart” to match the geometry (resolution), depth (color depth), etc. that you may need. My main machine is 1920x1080, so I opted for a slightly smaller display for the VNC client. The “%i” parameter in this case is equal to the “:1” (the display option) that we will pass to the service. So our next steps are to allow that file to be executed on start:

sudo chmod +x  /etc/systemd/system/vncserver@:1.service  
sudo systemctl daemon-reload
sudo systemctl enable vncserver@:1
sudo systemctl start vncserver@:1

If you want to have a shared clipboard (so you can cut/copy/paste between your host machine and your Pi), then you need to install “autocutsel”:

sudo apt-get install autocutsel

Then add this line to your “.vnc/xstartup”:

autocutsel -fork
# Be sure to put this above: /etc/X11/Xsession

The last step is to download the TightVNC client on your main machine, enter the IP and password, and connect! If you still have any issues, the Raspberry Pi site has a decent resource (although I could not seem to get their autostart instructions working on my Pi). Make sure to uncheck “Disable clipboard transfer” on your VNC client’s configuration to enable clipboard sharing.

Installing Samba for remote file sharing

One thing we’ll be doing a lot with Home Assistant (at least initially), is editing the configuration file. Even with TightVNC, sometimes it’s easier to open up the files on your local machine. As a result, we will set up file sharing for the Pi so other machines on the network can edit the files.

First we will want to install Samba:

sudo apt-get install samba samba-common-bin

Then we’ll need to configure it by uncommenting/adding a couple of lines for Windows support, adding a block of text of our own, and adding a couple lines if we need symlink support:

sudo nano /etc/samba/smb.conf

# Ensure the file has:
  workgroup = WORKGROUP

  wins support = yes

# At the bottom add:
[pi]
   comment= Pi
   path=/home/pi/folder # Change this to whatever folder you want to share
   browseable=Yes
   writeable=Yes
   only guest=no
   create mask=0777
   directory mask=0777
   public=no

# Add to enable symlinks:
  follow symlinks = yes
  unix extensions = no

Symlink support is useful if you plan on having a single “Share” or “Public” folder, and linking (“ln -s src dest”) folders that you want to share into it.

Lastly we will set a password:

sudo smbpasswd -a pi

Then you can install/configure a client to access the files. If you have a Windows machine and configured the share for it, then your Pi’s files should show up under the “Network” setting.

Now we can change the Pi’s files whenever we want!

Installing Home Assistant

Ok, hopefully the previous steps weren’t (too) bad, and we’re now ready to dive into the fun stuff… installing our home automation framework!

As usual, our first step is to install and run Home Assistant:

sudo pip3 install homeassistant
hass --open-ui # Will create config, etc.

Running the “hass —open-ui” command will generate a lot of files that will be useful (and also display an intro message), so be sure to do that even if you plan on automatically starting Home Assistant on boot. At this point, feel free to open up your hass page (on port 8123 of your Pi’s IP) and play around with it.

Next we’ll set it to boot on start very similarly to how we did for TightVNC:

sudo nano /lib/systemd/system/home-assistant@pi.service

# Paste this into the file:
  [Unit]
  Description=Home Assistant
  After=network.target

  [Service]
  Type=simple
  User=%i
  ExecStart=/usr/local/bin/hass

  [Install]
  WantedBy=multi-user.target

Note that you may need to change the “ExecStart” to point at your hass install. Mine was in a different location than what Home Assistant had listed on their site. Finally, if you changed your username, then be sure that is what follows the ”@” in the file name.

And again we will need to configure it to autostart:

sudo chmod +x /lib/systemd/system/home-assistant@pi.service
sudo systemctl --system daemon-reload
sudo systemctl enable home-assistant@pi
sudo systemctl start home-assistant@pi

You can call “sudo systemctl stop home-assistant@pi.service” to stop the service, or with “start” to boot it up again. “restart” is useful if you made changes and need to restart the server. Finally, you can run “sudo journalctl -f -u home-assistant@pi” to view a log of your Home Assistant service. I like to keep this in its own terminal for easy debugging through the VNC.

If you have any issues, the Home Assistant site actually has some very good instructions for general setup and autostarting.

At this point, you should have everything you need running! No devices/sensors are yet configured, but you can look over the ”Components” page on Home Assistant to see what suits your needs. I’m personally a fan of Z-Wave as it does not require any third-party services.

I’m excited about home automation and willing to share what knowledge I have. I am including part of a copy of my configuration (working as of Home Assistant 0.17.2). The only notable feature thus far is that I have it configured to send me a text when the washer/dryer is done, thanks to Google Voice, a Gen5 Z-Wave Z-Stick, and a couple of Z-Wave Energy Switches. It may not be perfect (and I should probably move it into a couple of scripts), but again, I’m eager to share and contribute to the open-source home automation community.

# As of version 0.17.x

####################################################
#                                                  #
#                  Basic Settings                  #
#                                                  #
####################################################

###  Global configuration  ###
homeassistant:
  name: Home
  temperature_unit: F
  time_zone: America/Chicago
  latitude: <redacted>
  longitude: <redacted>

  customize:
    # Washer
    switch.aeotec_smart_energy_switch_switch_3:
      friendly_name: Washer Switch
      hidden: true
    sensor.aeotec_smart_energy_switch_power_3:
      friendly_name: Washer (W)
      hidden: false
    sensor.aeotec_smart_energy_switch_energy_3:
      friendly_name: Washer (kWh)
      hidden: true
    sensor.aeotec_smart_energy_switch_previous_reading_3:
      friendly_name: Washer Previous(kWh)
      hidden: true
    input_select.washer_status:
      hidden: true
    # Dryer
    switch.aeotec_smart_energy_switch_switch_2:
      friendly_name: Dryer Switch
      hidden: true
    sensor.aeotec_smart_energy_switch_power_2:
      friendly_name: Dryer (W)
      hidden: false
    sensor.aeotec_smart_energy_switch_energy_2:
      friendly_name: Dryer (kWh)
      hidden: true
    sensor.aeotec_smart_energy_switch_previous_reading_2:
      friendly_name: Dryer Previous(kWh)
      hidden: true
    input_select.dryer_status:
      hidden: true
    # yr weather
    sensor.yr_symbol:
      friendly_name: Weather
    sensor.yr_temperature:
      friendly_name: Temperature

###  Toggles  ###

#introduction: # Show links to resources in log and frontend
#sun:          # Track the sun
updater:       # Checks for available updates
frontend:      # Enables the frontend
history:       # Enables support for tracking state changes over time.
logbook:       # View all events in a logbook
discovery:     # Discover some devices automatically
conversation:  # Allows you to issue voice commands from the frontend

####################################################
#                                                  #
#                     Devices                      #
#                                                  #
####################################################

### Track who is home ###
device_tracker:
  platform: asuswrt
  host: 192.xxx.x.x
  username: <redacted>
  password: <redacted>

  track_new_devices: no
  interval_seconds: 30
  consider_home: 300

### Send messages ###
notify:
  platform: googlevoice
  username: <redacted>
  password: <redacted>
  name: gvoice

### Weather ###
sensor:
  - platform: yr
    monitored_conditions:
      - temperature
      - symbol
  - platform: template
    sensors:
      washer_display:
        value_template: "{{ states('input_select.washer_status') }}"
        friendly_name: 'Washer'
  - platform: template
    sensors:
      dryer_display:
        value_template: "{{ states('input_select.dryer_status') }}"
        friendly_name: 'Dryer'

### IP Webcam ###
camera:
  platform: mjpeg
  mjpeg_url: http://192.xxx.x.x:xxxx/video
  name: Nexus Camera
  username: <redacted>
  password: <redacted>

## Z-Wave Washer Energy Switch ##

# Washer Switch
zwave:
  usb_path: /dev/ttyACM0
  config_path: /path/to/python-openzwave/openzwave/config
  polling_interval: 30000
  customize:
    # Washer
    # Polling for Z-Wave doesn't seem to work unless we set these
    sensor.aeotec_smart_energy_switch_power_3:
      polling_intensity: 1
    sensor.aeotec_smart_energy_switch_switch_3:
      polling_intensity: 1
    sensor.aeotec_smart_energy_switch_previous_reading_3:
      polling_intensity: 1
    switch.aeotec_smart_energy_switch_switch_3:
      polling_intensity: 1
    # Dryer  
    sensor.aeotec_smart_energy_switch_power_2:
      polling_intensity: 1
    sensor.aeotec_smart_energy_switch_switch_2:
      polling_intensity: 1
    sensor.aeotec_smart_energy_switch_previous_reading_2:
      polling_intensity: 1
    switch.aeotec_smart_energy_switch_switch_2:
      polling_intensity: 1

####################################################
#                                                  #
#                  Groups                          #
#                                                  #
####################################################
group:
  media:
    name: Media
    entities:
      - media_player.chromecast1
      - media_player.chromecast2

  laundry:
    name: laundry
    entities:
      # Washer
      - sensor.washer_display
      - input_select.washer_status
      - switch.aeotec_smart_energy_switch_switch_3
      - sensor.aeotec_smart_energy_switch_energy_3
      - sensor.aeotec_smart_energy_switch_power_3
      - sensor.aeotec_smart_energy_switch_previous_reading_3
      # Dryer
      - sensor.dryer_display
      - input_select.dryer_status
      - switch.aeotec_smart_energy_switch_switch_2
      - sensor.aeotec_smart_energy_switch_energy_2
      - sensor.aeotec_smart_energy_switch_power_2
      - sensor.aeotec_smart_energy_switch_previous_reading_2

####################################################
#                                                  #
#                  Automation                      #
#                                                  #
####################################################
automation:
  ###  Washer/Dryer  ###
  ###  - Washer state machine  ###
  - alias: 'Washer status - Off'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_3
      below: 0.5
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.washer_status
        option: 'Off'

  - alias: 'Washer status - On'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_3
      below: 5
      above: 0.5
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.washer_status
        option: 'On'

  - alias: 'Washer status - Running'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_3
      above: 5
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.washer_status
        option: 'Running'

  ###  - Washer actions  ###
  - alias: 'Washer done'
    trigger:
      platform: state
      entity_id: input_select.washer_status
      from: 'Running'
    action:
      service: notify.gvoice
      data:
        message: 'Washer done!'
        target:
          - <redacted>

  ###  - Dryer state machine  ###
  - alias: 'Dryer status - Off'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_2
      below: 1
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.dryer_status
        option: 'Off'

  - alias: 'Dryer status - On'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_2
      below: 20
      above: 1
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.dryer_status
        option: 'On'

  - alias: 'Dryer status - Running'
    trigger:
      platform: numeric_state
      entity_id: sensor.aeotec_smart_energy_switch_power_2
      above: 20
    action:
      service: input_select.select_option
      data:
        entity_id: input_select.dryer_status
        option: 'Running'

  ###  - Dryer actions  ###
  - alias: 'Dryer done'
    trigger:
      platform: state
      entity_id: input_select.dryer_status
      from: 'Running'
    action:
      service: notify.gvoice
      data:
        message: 'Dryer done!'
        target:
          - <redacted>

####################################################
#                                                  #
#                 Custom Inputs                    #
#                                                  #
####################################################
input_select:
  washer_status:
    name: Washer Status
    options:
      - 'Off'
      - 'On'
      - 'Running'
    initial: 'Off'
    icon: mdi:water
  dryer_status:
    name: Dryer Status
    options:
      - 'Off'
      - 'On'
      - 'Running'
    initial: 'Off'
    icon: mdi:weather-windy

Igor Shults

Share this Post

Related Blog Posts

Unknown

Using OAuth 2.0 With Google APIs

January 21st, 2016

Google has been updating their APIs to require OAuth 2.0. One of our clients makes considerable use of the Google Webmaster Tools APIs instrumented for 14,629 individual websites (and growing). I recently had the opportunity to help this client…

Object Partners
Unknown

Celebrating our 20th year in business!

January 6th, 2016

At the end of January, Object Partners will have officially been in business for 20 years. While that sounds like a very long time, it’s gone by quickly for some of us old timers. When we started OPI, we wanted it to be the kind of place where…

Chris Spurgat
Unknown

My JavaOne Experience

November 11th, 2015

Last week I had the opportunity to attend my second JavaOne conference. It was my first since 2009 and thus my first since Oracle took the reigns from Sun. It was also the first where I was invited as a “speaker”. The reason for the quotes around…

Object Partners

About the author

Igor Shults

Sr. Consultant

Igor is a self-driven developer with a desire to apply and expand his current skill set.  He has experience working with companies of all sizes on the whole application stack, from the database to the front-end.  He enjoys working in collaborative environments involving discussion and planning around data modeling and product development.