I’ve started a Raspberry Pi Smart Home system using an old Raspberry Pi model B I had laying around. This post is a work in progress, but I will upload all scripts and materials as I get them finished. My goals were honestly pretty simple in starting this. I sleep in a Hammock. Not many people realize how much of a nightmare it is to get nice and cozy in your hammock reading a book before bed… and then have to get out, fix your bedding, turn off the light, get in, and get comfy again. And if you forgot to grab something, you do it all again. So, I wanted to make a voice activated lamp.

Being a man of vision, I couldn’t stop there. If I make a voice activated lamp, I can make a set of voice activated outlets. And if I can make a set of outlets work on voice command, I can make more… soon, my whole house can be voice commands (or web-enabled). But I had two very strict restrictions:

  • The entire project needed to cost less than $25. This can be accomplished with a pi zero in the final version.
  • Any and all voice recognition needed to be done offline. Sorry, but this is my home. I would rather not snippets of my voice get transferred across the world to be analyzed. That’s why a pi has a processor, right? (Yeah, yeah… linux offline speech to text is as accurate as soap flavored ice cream is delicious… But I’m lazy AND paranoid)

This project is in three stages. First, I needed to assemble the hardware. Then I needed to write scripts to handle the turning on and off of the relays. Lastly, the user interface (which I’m hoping to use an offline Speech to Text software like Julius) to control.

As an optional 4th phase, I’d like to sync a number of these via bluetooth with one Raspberry Pi dedicated to the task of voice recognition and task assignment to the other nodes.

I’m using a Raspberry Pi Model B and a SainSmart 8 Channel 5V relay board for the hardware at this time. I will later update this list to include an inexpensive USB microphone that will pick up the entire room, as well as explain the pinout and show pictures.

The software is handled by three files: One script that watches a file (in this case /etc/outlet-control/live) which is a simple comma separated array of 8 1’s and 0’s. Each bit represents one of the relays on the SainSmart board. When slot 4 is set to 1, the relay opens. When it’s set to 0, the relay closes.

py-olcont.py:

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
pinList = [2, 3, 4, 17, 27, 22, 10, 9]
for i in pinList:
	GPIO.setup(i, GPIO.OUT)
	GPIO.output(i, GPIO.HIGH)
	
while True:
	try:
		file = open("/etc/outlet-control/live", "r")
		lines = file.read().split(',')
		for index, outlet in enumerate(lines):
			if outlet == '1':
				GPIO.output(pinList[index], GPIO.LOW)
			if outlet == '0':
				GPIO.output(pinList[index], GPIO.HIGH)
		time.sleep(1)
	except KeyboardInterrupt:
		GPIO.cleanup()

Next, a simple BASH script to control our live file:
olcont:

#!/bin/bash
if [[ ! -f /etc/outlet-control/live ]]; then
    mkdir /etc/outlet-control
    echo "0,0,0,0,0,0,0,0," > /etc/outlet-control/live
fi

active=$(cat /etc/outlet-control/live)
IFS=', ' read -r -a outlets <<< "$active"
 
if [[ "$1" == "-all" ]]; then
        newactive="1,1,1,1,1,1,1,1,"
        echo "1,1,1,1,1,1,1,1,"
elif [[ "$1" == "-none" ]]; then
        newactive="0,0,0,0,0,0,0,0,"
        echo "0,0,0,0,0,0,0,0,"
else
        for a in "$@"
        do
                test=${a#-}
                test=${test#+}
                test=$(( $(($test)) - 1 ))
 
                if [[ $a == *"-"* ]]; then
                        outlets[$test]="0"
                        echo "$test changed to ${outlets[$test]}"
                else
                        outlets[$test]="1"
                        echo "$test changed to ${outlets[$test]}"
                fi     
        done
        for i in "${outlets[@]}"
        do
                if [[ "$newactive" == "" ]]; then
                        newactive="$i,"
                else
                        newactive="$newactive$i,"
                fi
        done
 
fi
 
echo "$newactive" > /etc/outlet-control/live

This script accepts any number of arguments, and the way it works is simple, and the relays are labelled 1-8:
olcont +4 #Turn on relay 4
olcont -4 #Turn off relay 4
olcont +4 +2 -7 #Turn relay 4 and 2 on, turn relay 7 off
olcont -all #Turn on all relays
oldcont -none #Turn off all relays

Set permissions and throw them into /usr/local/bin/

chmod 755 py-olcont.py olcont
chmod +x py-olcont.py olcont
cp -pa py-olcont.py olcont /usr/local/bin

You can now start the monitor with:
py-olcont.py
(Recommended to nohup this with nohup py-olcont.py &)

and you can adjust the relays like so:
olcont +1 +4 -3