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
⚠️ Mains Voltage Safety Warning: If you intend to switch 120V/240V AC mains loads (like a desk lamp or ceiling fan), stop here. Mains wiring requires proper gauge wire, enclosed junction boxes, and compliance with local electrical codes. For this tutorial, we assume you are switching a safe, low-voltage DC load like a 12V LED strip or a 5V PC fan.

Numbered Wiring Steps

  1. De-energize: Ensure the Raspberry Pi is completely powered down and unplugged from the USB-C supply.
  2. Connect Power: Plug the Red jumper from Physical Pin 2 (5V) to the Relay Module VCC.
  3. Connect Ground: Plug the Black jumper from Physical Pin 6 (GND) to the Relay Module GND.
  4. Connect Logic: Plug the Yellow jumper from Physical Pin 11 (GPIO 17) to IN1, and Green from Pin 13 (GPIO 27) to IN2.
  5. 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 the GPIO.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, run sudo killall python3 to clear zombie processes, then restart your script. Always rely on the finally: 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 that listener 1883 and allow_anonymous false (with correct credentials) are set in your mosquitto.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.
💡 The First 3 Things to Check When It Fails:
  1. Ping the Broker: Run ping 192.168.1.50 from the Pi. If it times out, your network isolation (VLAN) is blocking IoT traffic.
  2. Verify Pin Conflicts: Ensure no other service (like pigpiod or a background gpiozero script) is hogging BCM 17 or 27.
  3. 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.