If you are trying to connect a Raspberry Pi with Google Home in 2026, skip the outdated cloud-based IFTTT webhooks and the high-maintenance Google Actions SDK. The most robust, zero-latency method is to run a local MQTT broker bridged through Home Assistant. This setup keeps your traffic off the public internet, survives router reboots, and responds to voice commands in under 50 milliseconds.
This guide walks through building a 5V relay controller on a Raspberry Pi 4 Model B (4GB) running Raspberry Pi OS Bookworm. We will use Python and the Paho MQTT library to listen for state changes, which Home Assistant then exposes directly to the Google Home app.
The Verdict: Choosing Your Integration Path
Before wiring anything, you need to decide how the Pi talks to Google. Here is the decision matrix for embedded projects in 2026:
| Integration Method | Latency | Local Control | Maintenance | Verdict |
|---|---|---|---|---|
| Google Actions SDK (Cloud) | 200-500ms | No | High (Requires Node.js, SSL certs, static IP) | Avoid for DIY |
| IFTTT / Webhooks | 1-3s | No | Medium (API limits, subscription costs) | Avoid |
| Home Assistant + MQTT | <50ms | Yes | Low (Set and forget, local network only) | Use This |
Default Recommendation: Use Home Assistant as the bridge. You will install Home Assistant OS on a separate device (or a VM), run Mosquitto MQTT on your Pi, and link the two. Google Home natively integrates with Home Assistant via the Google Assistant integration.
Hardware Specs and Pin Mapping
This build targets the Raspberry Pi 4 Model B (4GB) or Pi 5 (4GB) running Raspberry Pi OS (Bookworm 64-bit). Do not use legacy Buster or Bullseye images; the GPIO subsystem changed drastically in Bookworm.
Parts List
- Microcontroller: Raspberry Pi 4 Model B (4GB) with official 27W USB-C power supply.
- Relay Module: 5V 1-Channel Relay with Optocoupler (Songle SRD-05VDC-SL-C). Must have the JD-VCC jumper.
- Wiring: 4x Female-to-Female jumper wires (22 AWG).
- Storage: 32GB Class 10 MicroSD (SanDisk Extreme).
Pin Mapping Table
| Pi Function | BCM GPIO | Physical Pin | Relay Module Pin | Notes |
|---|---|---|---|---|
| 5V Power | N/A | Pin 2 | VCC | Powers the relay coil |
| Ground | N/A | Pin 6 | GND | Common ground reference |
| GPIO 17 | 17 | Pin 11 | IN | Control signal (3.3V logic) |
Most 5V relay modules have a jumper labeled JD-VCC. If you are powering the relay VCC from the Pi's 5V pin, leave the jumper ON. However, if you experience Pi brownouts when the relay clicks, remove the jumper and power the relay VCC from a dedicated external 5V supply, connecting only the Pi GND to the relay GND. The optocoupler will safely bridge the 3.3V GPIO signal to the 5V coil without back-feeding voltage into your Pi.
Wiring and Environment Setup
- Wire the Hardware: Connect Pin 2 to VCC, Pin 6 to GND, and Pin 11 to IN. Double-check that the IN pin is receiving 3.3V logic from the Pi, not 5V.
- Flash the OS: Use Raspberry Pi Imager to flash Raspberry Pi OS Lite (64-bit, Bookworm). Enable SSH and configure WiFi in the advanced settings.
- Install Dependencies: SSH into the Pi and install the modern GPIO backend and MQTT client. Bookworm deprecated
RPi.GPIOin favor oflgpio. Run:sudo apt update sudo apt install python3-paho-mqtt python3-gpiozero python3-lgpio - Install Mosquitto Broker: If you aren't using an external broker, install it locally:
sudo apt install mosquitto mosquitto-clients
The Python MQTT Control Script
This script uses gpiozero (backed by lgpio) and the Eclipse Paho MQTT library. It listens to a specific topic and toggles the relay. It includes robust error handling and auto-reconnect logic.
import paho.mqtt.client as mqtt
from gpiozero import OutputDevice
import time
import logging
import sys
# --- Configuration & Pin Definitions ---
RELAY_PIN = 17 # BCM 17 / Physical Pin 11
MQTT_BROKER = '127.0.0.1' # Change to HA IP if broker is external
MQTT_PORT = 1883
MQTT_TOPIC = 'home/livingroom/fan/set'
CLIENT_ID = 'pi_relay_controller_01'
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s'
)
# Initialize Relay
# active_high=False is critical: most 5V relay modules trigger on LOW (0V)
try:
relay = OutputDevice(RELAY_PIN, active_high=False, initial_value=False)
logging.info(f'Relay initialized on BCM GPIO {RELAY_PIN} (Active LOW)')
except Exception as e:
logging.critical(f'GPIO Initialization failed: {e}')
sys.exit(1)
# --- MQTT Callbacks ---
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code == 0:
logging.info('Connected to MQTT Broker successfully.')
client.subscribe(MQTT_TOPIC)
logging.info(f'Subscribed to topic: {MQTT_TOPIC}')
else:
logging.error(f'Connection failed with code: {reason_code}')
def on_message(client, userdata, msg):
payload = msg.payload.decode('utf-8').strip().upper()
logging.info(f'Received payload: {payload} on {msg.topic}')
try:
if payload in ['ON', '1', 'TRUE']:
relay.on()
logging.info('Relay state: CLOSED (ON)')
elif payload in ['OFF', '0', 'FALSE']:
relay.off()
logging.info('Relay state: OPEN (OFF)')
else:
logging.warning(f'Unknown command received: {payload}')
except Exception as e:
logging.error(f'Error toggling relay: {e}')
def on_disconnect(client, userdata, flags, reason_code, properties):
logging.warning(f'Disconnected from broker (Code: {reason_code}). Attempting auto-reconnect...')
# --- Main Execution Loop ---
if __name__ == '__main__':
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.reconnect_delay_set(min_delay=1, max_delay=60)
try:
client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
logging.info('Starting MQTT loop...')
client.loop_forever()
except KeyboardInterrupt:
logging.info('Shutting down gracefully...')
relay.off()
client.disconnect()
except ConnectionRefusedError:
logging.critical('Broker refused connection. Check Mosquitto config.')
sys.exit(1)
Debugging: First 3 Checks and Exact Error Strings
When integrating embedded Linux with cloud ecosystems, things will break. If your relay isn't clicking when you issue a Google Home voice command, run through this exact decision path.
The First 3 Things to Check
- Broker Reachability: Run
mosquitto_pub -h 127.0.0.1 -t 'home/livingroom/fan/set' -m 'ON'directly on the Pi. If the relay clicks, your Python script and hardware are fine; the issue is in Home Assistant's MQTT discovery payload. - Relay Logic Inversion: If the relay state is backwards (ON when it should be OFF), your module is Active HIGH. Change
active_high=Falsetoactive_high=Truein the Python script. - Home Assistant Entity Mapping: Ensure your Home Assistant
configuration.yamlcorrectly maps the MQTT state topic to a switch entity, and that the Google Assistant integration is filtering for that specific entity domain.
Exact Error Strings and Fixes
RuntimeError: No access to /dev/mem. Try running as root!Cause: You are using legacy
RPi.GPIO code on Bookworm, or running the script incorrectly.Fix: Stop using
RPi.GPIO. The gpiozero library with the lgpio backend (used in our script) accesses GPIO via the standard /dev/gpiochip character device and does not require root privileges. Ensure you installed python3-lgpio.
ConnectionRefusedError: [Errno 111] Connection refusedCause: Mosquitto 2.0+ changed its default security posture. It no longer listens on all interfaces without explicit configuration.
Fix: Edit your Mosquitto config (
sudo nano /etc/mosquitto/conf.d/default.conf) and add:listener 1883
allow_anonymous trueThen restart the service:
sudo systemctl restart mosquitto.
Scaling: When to Extend or Simplify the Build
A single Raspberry Pi controlling one relay is overkill for most smart home tasks. Before you build this, evaluate your end goal using this scaling framework:
- Simplify (The 1-Relay Scenario): If you only need to control a single desk fan or LED strip, ditch the Pi. Use an ESP32-C3 SuperMini ($4) running ESPHome. ESPHome integrates directly with Home Assistant via native API (no MQTT broker required) and exposes perfectly to Google Home with a fraction of the power draw and setup time.
- Extend (The 8+ Relay Scenario): If you are building a whole-home irrigation controller or a multi-zone HVAC damper system, do not wire 16 individual relays to the Pi's GPIO header. You will run out of pins and risk ground-loop noise. Instead, use a 74HC595 Shift Register or an MCP23017 I2C GPIO Expander. The MCP23017 gives you 16 extra I/O pins using only the Pi's I2C bus (Pins 3 and 5), keeping your wiring clean and electrically isolated.
By anchoring your Raspberry Pi with Google Home integration on local MQTT and modern Bookworm-compatible GPIO libraries, you eliminate the cloud latency and API deprecations that plague older tutorials. Wire the optocoupler correctly, respect the Mosquitto 2.0 listener configs, and your local voice-controlled relays will run indefinitely.






