Controlling Relays With A Raspberry Pi From Your Phone

Recently I’ve discovered the power of controlling relays with a Raspberry Pi and have been putting it to good use. I have a Raspberry Pi 2 setup in my shed doing a few things including controlling 3 relays. 2 of them are for my shed roller doors (check out my YouTube Video on that) and I have the 3rd controlling my water tank pump. On top of this the old Pi 2 is doing daily backups of my NAS as semi-offsite storage.

To control the relays from my phone I am running running a python script on the Pi. Using MQTT the Pi connects to my Home Assistant server which connects to Apple’s HomeKit. Also this can be setup with Google Assistant if you run Android. If you don’t know what MQTT or Home Assistant is don’t worry, I’ll cover that for you here.

Using Relays With A Raspberry Pi's GPIO

First up, you can’t control relays directly. You will need to use a relay board that triggers on 5v. These 5v boards have no trouble triggering on the Raspberry Pi’s 3.3v GPIO.

These relay boards work with the Raspberry Pi (affiliate link).

Controlling a relay from your Pi’s GPIO using Python and Raspbian is rather simple. You need to use 5V Power, Ground and one GPIO pin.

				
					import RPi.GPIO as GPIO
import time
# BCM Pin No
relay = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(relay, GPIO.OUT)
while True:
    GPIO.output(relay, GPIO.HIGH)
    time.sleep(1)
    GPIO.output(relay, GPIO.LOW)
    time.sleep(1)
				
			

This code will turn the relay on and off every second, effectively making a ticking clock.

Home Assistant & MQTT

While it’s great to control your relay with Python we need to connect the link between your smart phone and the python code. Here is what the communication flow looks like.

  1. Smart Phone (Apply HomeKit or Google Assistant)
  2. Home Assistant (Running MQTT Server)
  3. Python Code (MQTT Client & Relay Trigger)

Installing Home Assistant

How you get home assistant up and running is going to depend on your situation. Do you have a home server? Run it in a VM or Container. However if you don’t have a home server then you can run it on a Raspberry Pi 4 and performance is pretty good. Home Assistant themselves have guides for installation on many platforms including running on windows directly. Here is a link to their installation page.

Home Assistant and your Smart Phone

If you have an iPhone I’ve already made a guide on using Home Assistant with Apple HomeKit here. This lets you get buttons directly on your drop down screen and allows voice control with Siri.

If you’re using an Android phone here is a good guide to follow. Alternatively you can run the Home Assistant app directly on either platform, however you need to open the app to control anything.

Using MQTT and Adding Buttons

We need two install two addons here from the addon store. These are Mosquitto Broker and Visual Studio Code.

You can click on the addon once it’s installed to configure basic settings like Auto Start and Watchdog (auto restart if addon crashes). Read through Documentation tab for Mosquitto Broker to complete the setup. It gives clear steps that aren’t worth repeating here.

On the left you will have Visual Studio Code now. Go in here and click on configeration.yaml

You can add code here that will create a button in home assistant. This button will trigger MQTT event based on the name and topics. The below code is what I will use to control a relay to turn on/off my water tank pump.

				
					switch:
  - platform: mqtt
    name: "Pump"
    state_topic: "/shed/pump"
    command_topic: "/shed/pump"
    qos: 2
    retain: true
				
			

Raspberry Pi, MQTT & Python

Paho MQTT is the module we will use to get MQTT working in Python on a Raspberry Pi. Install it with this command:

				
					pip3 install paho-mqtt
				
			

Once you have that installed you can modify the below python code to suit yourself. The IP, topic, username and password need changing. Also you need to change the actions under the subscribe function. I am leaving my code as an example for different situations. It’s specific to my use however it may give you ideas on how to handle MQTT communications and do different things.

				
					import random
import time
import RPi.GPIO as GPIO
from paho.mqtt import client as mqtt_client
time.sleep(10)
port = 1883
client_id = f'python-mqtt-{random.randint(0, 1000)}'
#Change These
broker = '192.168.40.3'
topic = "/shed/#"
username = 'mqttuser'
password = 'password'
door_pin_1 = 17
door_pin_2 = 18
pump_pin = 27
GPIO.setmode(GPIO.BCM)
GPIO.setup(door_pin_1, GPIO.OUT)
GPIO.setup(door_pin_2, GPIO.OUT)
GPIO.setup(pump_pin, GPIO.OUT)
GPIO.output(door_pin_1, GPIO.LOW)
GPIO.output(door_pin_2, GPIO.LOW)
GPIO.output(pump_pin, GPIO.LOW)
# Set start time
start_time = time.time()
def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)
    # Set Connecting Client ID
    client = mqtt_client.Client(client_id)
    client.username_pw_set(username, password)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client
         
def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
        if (time.time() - start_time) > 10:
            if msg.topic == '/shed/door1':
                GPIO.output(door_pin_1, GPIO.HIGH)
                time.sleep(0.25)
                GPIO.output(door_pin_1, GPIO.LOW)
                time.sleep(0.25)
            elif msg.topic == '/shed/door2':
                GPIO.output(door_pin_2, GPIO.HIGH)
                time.sleep(0.25)
                GPIO.output(door_pin_2, GPIO.LOW)
                time.sleep(0.25)
            elif msg.topic == '/shed/pump':
                if msg.payload.decode() == "ON":
                    GPIO.output(pump_pin, GPIO.HIGH)
                    pump_state = True
                    print("Pump ON")
                if msg.payload.decode() == "OFF":
                    GPIO.output(pump_pin, GPIO.LOW)
                    pump_state = False
                    print("Pump OFF")
    client.subscribe(topic)
    client.on_message = on_message
    
def receive():
    client = connect_mqtt()
    subscribe(client)
    client.loop_forever()
receive()

				
			

Share this post

Leave a Reply