This cheatsheet shows the steps to a DIY project and was used to make my heater smart. This guide is only readable to technical people.
In the past I worked with primitive setups like Arduino or tried to get an ESP8266 wifi relay working. In my opinion, too limited and only worth considering if you need analog or economies of scale. Therefor, all my DIY home automation have a Linux kernel.
To understand this cheatsheet, this is my point of view;
- Love cheap solutions for home automation
- Love being able to write custom code
- Hate it when stuff is dependent on the vendors’ server (most smart products)
- Don’t like the physical aspect, get me the CLI over SSH ASAP
Step00: hardware
Get the required hardware.
- USB to TTL
- Board with wifi
- dupont cables
- power supply
- relay
- SD card
- Laptop
- etc.
Step01: bootable
To get the board up and running, we need the server version of the OS booting from the SD card.
Download it and dd
or xz
it to the SD card.
(google ‘create bootable sd card YOUR-BOARD-NAME’)
Get a local CLI, via HDMI, usb serial console (build in or a separate USB to TTL). Confirm that it is booting.
GND --- GND
RX -v- RX
TX -^- TX
I made this picture very unclear to highlight that RX connects to TX.
screen $(ls -tr /dev/tty*|grep -i usb|tail -1) 115200
step02 SSH
We will now configure the wifi. Since I want it to be static, I defined it via MAC to IP mapping in my router.
apt install -y wpasupplicant
cat << EOF >> /etc/wpa_supplicant/wpa_supplicant.conf
network={
ssid="testing"
psk="testingPassword"
}
EOF
And the wireless section of
/etc/network/interfaces
auto wlan2
iface wlan2 inet dhcp
wpa-driver wext
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
OPTIONAL. Read the
Debian manual
when wanting to use the interfaces
file
or if wpa_supplicant
is missing:
The name of the interface can be found using ip link
,
mine is called wlan0
.
On the sd card, add the following to /etc/network/interfaces
:
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid "my wifi network name"
wpa-psk MyPlainTextPassWord
address 192.168.1.110/24
gateway 192.168.1.1
step03 install
Install the basics
apt update
apt dist-upgrade -y
apt install -y python-dev git python3-pip vim tree
step04 GPIO
We now find the right GPIO library for our board, for the OrangePI Zero we do:
# https://opi-gpio.readthedocs.io/en/latest/api-documentation.html
pip3 install OPi.GPIO
We search on google for ‘BOARD-NAME BOARD-VERSION pinout’, from which we learn the pin numbers to use.
The following code is based on the example code that came with OPi.GPIO:
root@OrangePI:~# cat /usr/local/bin/set-relay.py
#!/usr/bin/env python3
import OPi.GPIO as GPIO
import sys
pin = 24 #which is PA13 on pinout
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
val = sys.argv[-1:][0]
if val == '1':
GPIO.output(pin,False)
else:
GPIO.output(pin,True)
print(val)
Don’t forget to:
chmod +x /usr/local/bin/set-relay.py
We can now test this script with:
set-relay.py 1 # turn on
set-relay.py 0 # turn off
Hardware:
- connect the jumper on the relay board between ‘VCC’ and ‘JD VCC’
- connect the ‘VCC’ near the ‘in1’ to 5V on the controller board
- connect GND to GND
- connect ‘in1’ to the GPIO using a resistor
step05 create
Create whatever you like.
Example: Smart heater controlled via Dropbox
This example controls a heater. The heater unit is located on the attic, while the thermostat is located in the living room.
We keep the thermostat in place, enabling us to control the temperature there, but we make a cut in the line to insert the wifi relay. This enables us to turn the heater on or off, which will heat until the desired temperature set on the thermostat.
This makes the heater smart; we can control it from the web or set a timer, but not control the temperature.
We create the timer script, which will turn it on during specific times. Outside these time frames, we check a shared (with housemates) dropbox file, which contains either a ‘1’ or ‘0’.
#!/bin/sh
# The following can be a link to a shared dropbox file or a file on your server
FILELOC="https://www.dropbox.com/s/dl/SECRET-TOKEN/filename.txt?dl=1"
TIME=`date +%H%M`
# during the following time blocks
# we always want the heater on
if [ $TIME -gt 0430 ] && [ $TIME -lt 0615 ]
then
# morning
echo 1
exit
fi
if [ $TIME -gt 1530 ] && [ $TIME -lt 2045 ]
then
# evening
echo 1
exit
fi
curl --silent -L $FILELOC \
| grep 1 \
|| echo 0
pay attention to dl=1.
This script is saved and tested:
root@OrangePI:~# vi /usr/local/bin/get-heater-val.sh
root@OrangePI:~# chmod +x /usr/local/bin/get-heater-val.sh
root@OrangePI:~# get-heater-val.sh
1
We connect the ‘get-value’ with ‘set-relay’:
root@OrangePI:~# cat /usr/local/bin/trigger-relay-update.sh
#!/bin/sh
/usr/local/bin/set-relay.py `/usr/local/bin/get-heater-val.sh`
root@OrangePI:~# chmod +x /usr/local/bin/trigger-relay-update.sh
We would like to have a systemd timer, but since we are on an old machine, we will use a cron job:
root@OrangePI:~# cat /etc/issue
Ubuntu 14.04.5 LTS \n \l
root@OrangePI:~# mkdir -p /etc/cron.d
root@OrangePI:~# apt install cron
root@OrangePI:~# vi /etc/cron.d/relay
root@OrangePI:~# cat /etc/cron.d/relay
*/3 * * * * root /usr/local/bin/trigger-relay-update.sh 2>&1
We now have a smart heater, controlled by time and multiple people can change the dropbox file, turning the heater on.
This is a very simple example, a better way would be ifttt or using Google Assistant.
NOTE: you may want to google ‘/etc/timezone’
actual implementation
The example above was to illustrate how one could do it, the actual code:
/etc/cron.d/heater
# turn on during these times
30 5,16 * * * root echo 1 > /run/relay
# turn off during these times
15 7 * * * root echo 0 > /run/relay
45 21,23 * * * root echo 0 > /run/relay
# dropbox only checked when current state is off
*/3 * * * * root /usr/local/bin/check-dropbox.sh
# set state
* * * * * root /usr/local/bin/set-relay.py `cat /run/relay`
/etc/cron.d/reboot
# this allows the device to reconnect after a possible router reboot
4 4 * * * root /bin/sleep 60; reboot
# had some issue with the static IP i set on the router
#7 * * * * root /sbin/dhclient -v wlan2
#* * * * * root /usr/bin/arping -U -c 1 -I wlan2 192.168.1.110
/usr/local/bin/check-dropbox.sh
#!/bin/sh
# The following can be a link to a shared dropbox file or a file on your server
FILELOC="https://www.dropbox.com/s/dl/SECRET-TOKEN/filename.txt?dl=1"
grep 0 /run/relay \
&& curl --silent -L $FILELOC | grep -q 1 \
&& echo 1 > /run/relay
/usr/local/bin/run-relay-webserver.py
#!/usr/bin/env python3
from flask import Flask
from flask import request
app = Flask(__name__)
homepage = '''
<html>
<head></head>
<body>
Turn the heater
<a href="/setrelay/1">on</a>
or turn it
<a href="/setrelay/0">off</a>
</body>
</html>
'''
@app.route('/', methods=['GET'])
def serve_homepage():
return(homepage,200)
@app.route('/setrelay/<int:value>', methods=['GET'])
def update_relay(value):
# print(request) # debug
inp = str(value)
with open('/run/relay', 'w') as f:
f.write(inp)
return(inp,200)
if __name__ == '__main__':
app.run(debug=True, port=80, host='0.0.0.0')
deps.:
pip3 install setuptools wheel #needed to install flask
pip3 install flask
The server is started in a tmux
session.
Or one could make it reboot proof:
# Old Ubuntu, systemd is used nowadays
tail -2 /etc/rc.local
/usr/local/bin/run-relay-webserver.py &
exit 0