To connect a Raspberry Pi to Google Home for direct hardware control, you must bridge the Pi's GPIO pins to Google's ecosystem using a middleware protocol. Direct Google Actions for hobbyists are largely deprecated in favor of local bridges. The most reliable 2026 architecture uses a local MQTT broker (via Home Assistant) to translate Google Home voice commands into GPIO signals. This guide walks you through building a Python-based MQTT relay controller that exposes your Pi's hardware to Google Assistant.
Project Specifications and Hardware Requirements
| Parameter | Specification |
|---|---|
| Difficulty | Intermediate (Requires basic Linux and Python knowledge) |
| Estimated Time | 45–60 minutes |
| Estimated Cost | ~$65 USD (assuming you own a monitor/keyboard for initial setup) |
| Target Board | Raspberry Pi 4 Model B (4GB or 8GB variant) running Raspberry Pi OS 64-bit |
Exact Parts List
- Microcomputer: Raspberry Pi 4 Model B (4GB RAM minimum recommended for running background MQTT services smoothly).
- Relay Module: Songle 4-Channel 5V Relay Module (Must be optocoupler-isolated and Active LOW).
- Storage: 32GB SanDisk Extreme microSD Card (UHS-I U3 rating for OS longevity).
- Power Supply: Official Raspberry Pi 27W USB-C Power Supply (5.1V / 5A).
- Wiring: 20cm Female-to-Female Dupont jumper wires.
- Load (for testing): 12V DC LED strip (Do not test with mains AC voltage until the logic is verified).
Pin Mapping and Wiring Procedure
The Raspberry Pi's 3.3V logic pins cannot directly drive a 5V relay coil. We use the Pi's 5V rail to power the relay module's VCC, while the 3.3V GPIO pins safely trigger the optocoupler inputs. Below is the exact pin mapping based on the official Raspberry Pi BCM GPIO numbering.
| Raspberry Pi Pin (BCM) | Physical Pin # | Relay Module Pin | Wire Color (Suggested) |
|---|---|---|---|
| 5V Power | 2 or 4 | VCC | Red |
| GND | 6, 9, or 14 | GND | Black |
| GPIO 17 | 11 | IN1 | Yellow |
| GPIO 27 | 13 | IN2 | Green |
Numbered Wiring Steps
- De-energize: Ensure the Raspberry Pi is completely powered down and unplugged from the USB-C supply.
- Connect Power: Plug the Red jumper from Physical Pin 2 (5V) to the Relay Module VCC.
- Connect Ground: Plug the Black jumper from Physical Pin 6 (GND) to the Relay Module GND.
- Connect Logic: Plug the Yellow jumper from Physical Pin 11 (GPIO 17) to IN1, and Green from Pin 13 (GPIO 27) to IN2.
- Verify: Gently tug each Dupont connector to ensure a solid mechanical grip on the male header pins before applying power.
Python Environment and Control Code
This code targets the Raspberry Pi 4 Model B. It uses the paho-mqtt library to listen for commands from a local Home Assistant MQTT broker (which acts as the bridge to Google Home). When Google Home sends an "ON" command, Home Assistant publishes a payload to the MQTT topic, and the Pi toggles the GPIO pin.
First, install the required dependencies on your Pi:
sudo apt update
sudo apt install python3-pip python3-rpi.gpio
pip3 install paho-mqtt --break-system-packages
Save the following code as pi_google_home_relay.py:
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time
import json
import logging
# --- CONFIGURATION & PIN DEFINITIONS ---
RELAY_PIN_1 = 17 # BCM 17 / Physical Pin 11
RELAY_PIN_2 = 27 # BCM 27 / Physical Pin 13
MQTT_BROKER_IP = "192.168.1.50" # Replace with your Home Assistant/Mosquitto IP
MQTT_PORT = 1883
MQTT_USER = "mqtt_user"
MQTT_PASS = "your_secure_password"
TOPIC_CMD_1 = "homeassistant/switch/pi_relay_1/set"
TOPIC_STATE_1 = "homeassistant/switch/pi_relay_1/state"
TOPIC_CMD_2 = "homeassistant/switch/pi_relay_2/set"
TOPIC_STATE_2 = "homeassistant/switch/pi_relay_2/state"
# --- LOGGING SETUP ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# --- GPIO SETUP ---
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Active LOW relays require GPIO.HIGH to turn OFF, and GPIO.LOW to turn ON
GPIO.setup(RELAY_PIN_1, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(RELAY_PIN_2, GPIO.OUT, initial=GPIO.HIGH)
def on_connect(client, userdata, flags, rc, properties=None):
if rc == 0:
logging.info("Connected to MQTT Broker successfully.")
client.subscribe(TOPIC_CMD_1)
client.subscribe(TOPIC_CMD_2)
# Publish initial OFF state
client.publish(TOPIC_STATE_1, "OFF", retain=True)
client.publish(TOPIC_STATE_2, "OFF", retain=True)
else:
logging.error(f"MQTT Connection failed with result code {rc}")
def on_message(client, userdata, msg):
payload = msg.payload.decode('utf-8').strip().upper()
topic = msg.topic
try:
if topic == TOPIC_CMD_1:
if payload == "ON":
GPIO.output(RELAY_PIN_1, GPIO.LOW) # Active LOW
client.publish(TOPIC_STATE_1, "ON", retain=True)
logging.info("Relay 1 turned ON")
elif payload == "OFF":
GPIO.output(RELAY_PIN_1, GPIO.HIGH)
client.publish(TOPIC_STATE_1, "OFF", retain=True)
logging.info("Relay 1 turned OFF")
elif topic == TOPIC_CMD_2:
if payload == "ON":
GPIO.output(RELAY_PIN_2, GPIO.LOW)
client.publish(TOPIC_STATE_2, "ON", retain=True)
logging.info("Relay 2 turned ON")
elif payload == "OFF":
GPIO.output(RELAY_PIN_2, GPIO.HIGH)
client.publish(TOPIC_STATE_2, "OFF", retain=True)
logging.info("Relay 2 turned OFF")
except Exception as e:
logging.error(f"Error processing message: {e}")
# --- MAIN EXECUTION LOOP ---
if __name__ == "__main__":
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(MQTT_USER, MQTT_PASS)
# Set Last Will and Testament (LWT) so Google Home knows if Pi drops offline
client.will_set("homeassistant/switch/pi_relay_1/availability", "offline", retain=True)
client.on_connect = on_connect
client.on_message = on_message
try:
client.connect(MQTT_BROKER_IP, MQTT_PORT, 60)
client.publish("homeassistant/switch/pi_relay_1/availability", "online", retain=True)
client.loop_forever()
except KeyboardInterrupt:
logging.info("Shutting down gracefully...")
except ConnectionRefusedError:
logging.error("Connection refused. Check broker IP and firewall.")
finally:
# CRITICAL: Always clean up GPIO to prevent pin lockouts on next run
GPIO.output(RELAY_PIN_1, GPIO.HIGH)
GPIO.output(RELAY_PIN_2, GPIO.HIGH)
GPIO.cleanup()
client.publish("homeassistant/switch/pi_relay_1/availability", "offline", retain=True)
client.disconnect()
Debugging Common Connection and GPIO Errors
When bridging local hardware to cloud voice assistants, failures usually happen at the GPIO layer or the network layer. If your relay fails to trigger via Google Home, check these exact error strings in your terminal output.
1. The "Channel Already in Use" Warning
Exact Error String: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
- Cause: A previous instance of your Python script crashed or was force-killed (via
kill -9) without executing theGPIO.cleanup()function. The OS still thinks the pin is allocated. - Fix: The code above includes
GPIO.setwarnings(False)to suppress this, but to truly fix the hardware state, runsudo killall python3to clear zombie processes, then restart your script. Always rely on thefinally:block to handle cleanup.
2. MQTT Connection Refused
Exact Error String: ConnectionRefusedError: [Errno 111] Connection refused
- Cause: The Mosquitto broker on your Home Assistant machine is either down, listening on a different port, or blocking the Pi's IP address via Access Control Lists (ACLs).
- Fix: SSH into your broker machine and run
sudo systemctl status mosquitto. Verify thatlistener 1883andallow_anonymous false(with correct credentials) are set in yourmosquitto.conf.
3. Relay Clicks but Load Doesn't Turn On
Symptom: You hear the mechanical "click" of the Songle relay, but your 12V LED strip remains dark.
- Cause: You wired the load to the Normally Closed (NC) terminal instead of the Normally Open (NO) terminal, or your external power supply shares a ground improperly.
- Fix: Move your load's positive wire to the NO terminal. Ensure the Pi's GND and the 12V power supply's GND are tied together (common ground) if you are using a logic-level MOSFET instead of a relay.
- Ping the Broker: Run
ping 192.168.1.50from the Pi. If it times out, your network isolation (VLAN) is blocking IoT traffic. - Verify Pin Conflicts: Ensure no other service (like
pigpiodor a backgroundgpiozeroscript) is hogging BCM 17 or 27. - Check MQTT ACLs: Use an MQTT explorer app on your phone to manually publish "ON" to the topic. If the Pi reacts, the issue is in Home Assistant's Google Home integration, not the Pi.
Extending or Simplifying Your Build
How to Simplify: If managing Python scripts, systemd services, and raw MQTT topics feels like overkill, abandon Raspberry Pi OS entirely. Flash your microSD card with Home Assistant OS. Home Assistant has a native "Raspberry Pi GPIO" integration that handles the pin toggling via a simple YAML configuration, completely eliminating the need for custom Python code while maintaining the Google Home bridge.
How to Extend: Turn this from a simple switch into a smart environment monitor. Wire a BME280 I2C sensor to the Pi's SDA (GPIO 2) and SCL (GPIO 3) pins. You can modify the Python script to read temperature and humidity every 60 seconds and publish it to an MQTT sensor topic. Google Home can then read out your room's exact temperature when you ask, "Hey Google, what's the temperature in the workshop?"
Frequently Asked Questions
Can I use Raspberry Pi Google Home integration without Home Assistant?
Yes, but it is significantly harder. You would need to write a custom Smart Home Action in the Google Home Developer Console, host a public-facing HTTPS web server (using Flask or Node.js) to handle the OAuth and EXECUTE intents, and manage SSL certificates. Home Assistant acts as a free, local middleware that handles all the Google API handshakes for you. For 95% of makers in 2026, running Home Assistant on the Pi (or a separate box) is the only practical route.
Why does my Raspberry Pi Google Home voice command have a 3-second delay?
A 2-to-4-second delay is normal when using cloud-based MQTT bridges because the voice command travels from your Google Nest speaker to Google's cloud servers, then to Home Assistant's cloud webhook, down to your local router, and finally to the Pi. To achieve sub-500ms local execution, you must configure Home Assistant to use Local Execution for Google Assistant, which keeps the command routing strictly on your LAN.
How do I fix the "Device is offline" error in the Google Home app for my Pi?
This happens when Google loses visibility of the device state. In the Python code provided above, we implemented an MQTT Last Will and Testament (LWT). If the Pi loses power or crashes, the MQTT broker automatically publishes an "offline" payload. Ensure your Home Assistant MQTT switch configuration includes the availability_topic matching the LWT topic in the Python script so Google Home accurately reflects the offline status rather than timing out.
Is it better to use Matter or MQTT for Raspberry Pi Google Home projects?
Matter is the future standard for local, cross-platform smart home control, and Google natively supports it. However, as of 2026, building custom Matter devices on a Raspberry Pi requires compiling the heavy C++ Matter SDK and dealing with complex Thread/Wi-Fi border router provisioning. MQTT remains the most reliable, lightweight, and easily debuggable protocol for custom DIY Pi hardware projects today. Use MQTT for now, but keep an eye on Python Matter server wrappers as they mature.






