You want to build a smart home system, and you’ve heard the Raspberry Pi is a good place to start. You’re right. In this guide, I’ll walk you through building a complete raspberry pi home automation hub from scratch using MQTT, temperature and motion sensors, and relay modules to control lights or appliances. By the end, you’ll have a working system that you can monitor and control from any device on your home network.
Why Build Your Own Smart Home Hub?
Off-the-shelf smart home systems like Philips Hue or TP-Link Kasa are convenient, but they lock you into their ecosystem, often require cloud accounts, and give you no control over the data your devices generate. Building your own hub means:
- Full local control — no internet required for core operations
- Privacy — your sensor data never leaves your home
- Flexibility — mix and match any sensor or actuator you can wire up
- Learning — you’ll understand exactly how MQTT, GPIO, and relay logic work under the hood
I’ve been building these systems for years, and the recipe hasn’t changed much: a Raspberry Pi running an MQTT broker, a few ESP8266 or Arduino nodes for sensors, and a web dashboard to tie it all together. We’ll cover the full stack.
What You’ll Need
Before we get into wiring and code, here’s the complete parts list. Most of these are available from any electronics distributor for under $50 total (excluding the Pi).
Hardware
| Component | Purpose | Approx Cost |
|---|---|---|
| Raspberry Pi 3B+, 4, or Zero 2 W | Central hub / MQTT broker | $15–$45 |
| 16GB+ microSD card | OS + data storage | $8 |
| DHT22 temperature/humidity sensor | Temp + humidity monitoring | $8 |
| HC-SR501 PIR motion sensor | Motion detection | $4 |
| 2-channel 5V relay module | Switch lights/appliances | $6 |
| Breadboard + jumper wires | Prototyping | $5 |
| 10kΩ resistor (for DHT22 pull-up) | Signal stability | $1 |
| USB micro power supply (5V 2.5A) | Power the Pi | $10 |
Software
- Raspberry Pi OS Lite (64-bit) — headless, minimal install
- Mosquitto — MQTT broker
- Node-RED — visual flow editor for dashboards and logic
- Mosquitto clients — for testing MQTT from the command line
Step 1: Set Up the Raspberry Pi as an MQTT Broker
MQTT is a lightweight publish/subscribe messaging protocol perfect for IoT. The broker lives on your Pi and relays messages between sensors (publishers) and your dashboard or scripts (subscribers).
Install Raspberry Pi OS
Flash Raspberry Pi OS Lite (64-bit) to your microSD card using the Raspberry Pi Imager. Enable SSH and set a hostname like smarthub during the flash process.
Boot the Pi, find its IP address (check your router’s DHCP list or use arp -a), and SSH in:
ssh pi@192.168.1.100
Update the system:
sudo apt update && sudo apt upgrade -y
Install Mosquitto MQTT Broker
sudo apt install -y mosquitto mosquitto-clients
Mosquitto starts automatically. Test it by publishing a test message from one terminal window:
mosquitto_pub -h localhost -t "test/topic" -m "Hello from Pi"
In another terminal, subscribe:
mosquitto_sub -h localhost -t "test/topic"
You should see the message appear. If you do, the broker is working.
Secure the Broker (Optional but Recommended)
Edit the Mosquitto config:
sudo nano /etc/mosquitto/mosquitto.conf
Add these lines:
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
Create a password for user maker:
sudo mosquitto_passwd -c /etc/mosquitto/passwd maker
Restart Mosquitto:
sudo systemctl restart mosquitto
Now all MQTT clients need the username and password to connect.
Step 2: Wire the Sensors and Relay to the Pi
We’ll wire the DHT22, PIR sensor, and relay module to the Pi’s GPIO pins. Disconnect power while wiring.
Wiring Table
| Component | Pi GPIO Pin | Notes |
|---|---|---|
| DHT22 VCC | Pin 1 (3.3V) | |
| DHT22 DATA | Pin 7 (GPIO 4) | Add 10kΩ pull-up between DATA and VCC |
| DHT22 GND | Pin 6 (GND) | |
| PIR VCC | Pin 2 (5V) | |
| PIR OUT | Pin 11 (GPIO 17) | |
| PIR GND | Pin 14 (GND) | |
| Relay IN1 | Pin 13 (GPIO 27) | Controls relay channel 1 |
| Relay IN2 | Pin 15 (GPIO 22) | Controls relay channel 2 |
| Relay VCC | Pin 4 (5V) | |
| Relay GND | Pin 20 (GND) |
Important note about relay modules: Many relay modules have an active-low trigger pin. That means writing GPIO 27 LOW closes the relay (turns on the connected appliance). Always check your module’s datasheet.
Step 3: Write the Python Code That Publishes Sensor Data
We’ll write a Python script that reads the DHT22 and PIR sensor every 5 seconds and publishes the data to MQTT topics.
Install required libraries:
sudo apt install -y python3-pip
pip3 install adafruit-circuitpython-dht
sudo apt install -y libgpiod2
Create the script:
nano ~/sensor_publisher.py
import time
import board
import adafruit_dht
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
# MQTT config
MQTT_BROKER = "localhost"
MQTT_PORT = 1883
MQTT_USER = "maker"
MQTT_PASS = "your_password"
TOPIC_TEMP = "home/sensor/temperature"
TOPIC_HUM = "home/sensor/humidity"
TOPIC_MOTION = "home/sensor/motion"
# Sensor pins
DHT_PIN = board.D4
PIR_PIN = 17
# Init sensors
dht_device = adafruit_dht.DHT22(DHT_PIN)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR_PIN, GPIO.IN)
# MQTT connect
client = mqtt.Client()
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
print("Sensor publisher started...")
try:
while True:
try:
temperature = dht_device.temperature
humidity = dht_device.humidity
if temperature is not None and humidity is not None:
client.publish(TOPIC_TEMP, f"{temperature:.1f}")
client.publish(TOPIC_HUM, f"{humidity:.1f}")
print(f"Published temp={temperature:.1f}C humidity={humidity:.1f}%")
except RuntimeError as e:
print(f"DHT read error: {e}")
motion = GPIO.input(PIR_PIN)
client.publish(TOPIC_MOTION, "ON" if motion else "OFF")
print(f"Motion: {'ON' if motion else 'OFF'}")
time.sleep(5)
except KeyboardInterrupt:
print("Exiting...")
GPIO.cleanup()
client.loop_stop()
client.disconnect()
Run it:
python3 ~/sensor_publisher.py
In another terminal, verify the data is flowing:
mosquitto_sub -h localhost -u maker -P your_password -t "home/sensor/#"
You should see messages like 23.5, 45.2, OFF scrolling by.
Step 4: Control Relays via MQTT
Now let’s add relay control. We’ll create a second script that subscribes to commands and toggles the relays.
nano ~/relay_controller.py
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
RELAY1_PIN = 27
RELAY2_PIN = 22
MQTT_BROKER = "localhost"
MQTT_PORT = 1883
MQTT_USER = "maker"
MQTT_PASS = "your_password"
TOPIC_RELAY1 = "home/relay/1/set"
TOPIC_RELAY2 = "home/relay/2/set"
GPIO.setmode(GPIO.BCM)
GPIO.setup(RELAY1_PIN, GPIO.OUT, initial=GPIO.HIGH) # HIGH = relay off
GPIO.setup(RELAY2_PIN, GPIO.OUT, initial=GPIO.HIGH)
def on_message(client, userdata, msg):
payload = msg.payload.decode()
topic = msg.topic
if topic == TOPIC_RELAY1:
GPIO.output(RELAY1_PIN, GPIO.LOW if payload == "ON" else GPIO.HIGH)
print(f"Relay 1 set to {payload}")
elif topic == TOPIC_RELAY2:
GPIO.output(RELAY2_PIN, GPIO.LOW if payload == "ON" else GPIO.HIGH)
print(f"Relay 2 set to {payload}")
client = mqtt.Client()
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.on_message = on_message
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.subscribe([(TOPIC_RELAY1, 0), (TOPIC_RELAY2, 0)])
client.loop_forever()
Run it in a second SSH session:
python3 ~/relay_controller.py
Now publish a command to turn on the light:
mosquitto_pub -h localhost -u maker -P your_password -t "home/relay/1/set" -m "ON"
You should hear the relay click, and the script prints confirmation.
Step 5: Build a Dashboard with Node-RED
Node-RED runs on the Pi and gives you a visual web interface to build dashboards without writing HTML. It runs as a service and is perfect for this.
Install Node-RED:
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
Enable it as a service:
sudo systemctl enable nodered.service
sudo systemctl start nodered.service
Access it at http://192.168.1.100:1880 (replace with your Pi’s IP). Install the dashboard nodes:
- Click the hamburger menu → Manage palette → Install
- Search for
node-red-dashboardand install
Now build the flow:
- Drag in three MQTT input nodes: subscribe to
home/sensor/temperature,home/sensor/humidity, andhome/sensor/motion - Drag in two MQTT output nodes: set topic to
home/relay/1/setandhome/relay/2/set - Drag in dashboard widgets:
- For temperature and humidity:
ui_gaugenodes - For motion:
ui_textnode showing ON/OFF - For relays:
ui_switchnodes (typeon/off, payload ON/OFF)
- For temperature and humidity:
- Wire them up: MQTT input → gauge/text; switch → MQTT output
Deploy the flow. Open the dashboard UI at http://192.168.1.100:1880/ui (or the port you configured). You’ll see live sensor data and toggles for your relays.
Step 6: Automate with Rules
Node-RED makes it easy to add automation. For example, turn on a relay when motion is detected after sunset. Here’s a simple rule flow:
- Add a
functionnode that checks if motion isONand time is between 18:00 and 06:00. - Wire motion MQTT input → function node → MQTT output to relay topic.
The function code:
var hour = new Date().getHours();
if (msg.payload === "ON" && (hour >= 18 || hour < 6)) {
return { payload: "ON" };
} else {
return null;
}
Deploy and test — walk in front of the PIR sensor and the relay should fire only in darkness hours.
Troubleshooting Common Issues
DHT22 returns None repeatedly
- Check the 10kΩ pull-up resistor between DATA and 3.3V
- Try a slower reading interval (2–3 seconds minimum)
- Some DHT22 clones are finicky; try a genuine Aosong part
Relay doesn’t click when publishing ON
- Double-check the pin number in the relay script
- Some modules are active-low, some active-high. Try publishing
OFFto see if the relay toggles - Use a multimeter to measure voltage between the relay’s trigger pin and GND when you publish
MQTT connection refused
- Ensure you created the password file and set
allow_anonymous false - Check that port 1883 is not blocked by a firewall
- Verify the username and password in your Python scripts
Node-RED dashboard can’t connect to MQTT
- Add an MQTT broker node in Node-RED (not the MQTT input nodes directly)
- Input nodes connect to a broker config node pointing to
localhost:1883with your credentials
Going Further
This system is the foundation. From here you can:
- Add more sensors: light sensors (LDR), soil moisture, air quality (PMS5003)
- Control more relays: wire up a multi-channel relay board for lamps, fans, or aquarium pumps
- Add remote access: set up a WireGuard VPN to your home network instead of exposing MQTT to the internet
- Log data: write sensor readings to a CSV file or InfluxDB for historical graphs
- Integrate voice control: connect your MQTT topics to a local voice assistant like Mycroft or Rhasspy
For inspiration, check out some of my other builds: GPS Module + Arduino: Does a Cheap Sensor Actually Work? or I Turned My Old Fan Into a Remote Control Fan (ESP8266 + Relay). Both use similar MQTT patterns but with different hardware.
Conclusion
You’ve just built a complete raspberry pi home automation hub that reads temperature, humidity, and motion data, publishes it over MQTT, and lets you control relays from a web dashboard. The stack — Mosquitto for messaging, Python for sensor logic, and Node-RED for the UI — scales from a single room to an entire house.
The best part? Everything runs locally, no cloud dependency, no monthly fees, and full control over your code and data. If you get stuck, the community on Discord is always helpful. Now go wire up that lamp.