I remember that night when I was awakened by the heat from the air conditioner. I fumbled in the dark looking for the remote control but couldn’t find it after a long search.
At that moment, I thought how great it would be if I could control all the devices in my home with my phone. Later, after getting to know the ESP32 and MQTT, I realized that this idea could really be implemented.
01
The ESP32 development board is truly a treasure. It has both WiFi and Bluetooth, and the GPIO pins are sufficient. Developing with MicroPython is simply delightful.
The MQTT protocol is a fantastic tool for the Internet of Things. It acts like an information relay station where all devices send messages and receive commands. Imagine the feeling of a post office, where each device has its own mailbox address.
Let’s take a look at the basic connection code:
import network
import time
from umqtt.simple import MQTTClient
# WiFi connection function
def connect_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('Connecting to WiFi...')
wlan.connect(ssid, password)
while not wlan.isconnected():
time.sleep(1)
print('WiFi connected successfully!')
print('IP address:', wlan.ifconfig()[0])
# MQTT connection configuration
MQTT_SERVER = "your_MQTT_server_address"
MQTT_PORT = 1883
CLIENT_ID = "esp32_home_control"
TOPIC_SUB = "home/control"
TOPIC_PUB = "home/status"
This code provides the basic framework. Once connected to WiFi, it can communicate with the MQTT server.
02
The most common issue encountered in actual projects is connection stability. What if the network goes down? What if the MQTT server crashes?
My solution is to add a heartbeat detection mechanism:
def mqtt_callback(topic, msg):
print(f"Received message: {topic.decode()} -> {msg.decode()}")
# Parse control commands
if topic.decode() == "home/control":
command = msg.decode()
if command == "light_on":
# Control LED light to turn on
led_pin.on()
client.publish("home/status", "Light is ON")
elif command == "light_off":
led_pin.off()
client.publish("home/status", "Light is OFF")
def reconnect_mqtt():
while True:
try:
client = MQTTClient(CLIENT_ID, MQTT_SERVER, MQTT_PORT)
client.set_callback(mqtt_callback)
client.connect()
client.subscribe(TOPIC_SUB)
print("MQTT reconnected successfully")
return client
except:
print("MQTT connection failed, retrying in 5 seconds")
time.sleep(5)
This way, even if the network is unstable, the program can automatically reconnect.
03
The temperature and humidity sensor is fundamental to smart homes. The DHT22 sensor offers great value for money and sufficient accuracy.
import dht
from machine import Pin
# Initialize DHT22 sensor
dht_sensor = dht.DHT22(Pin(4))
def read_sensor_data():
try:
dht_sensor.measure()
temperature = dht_sensor.temperature()
humidity = dht_sensor.humidity()
# Package data for sending
data = f"temp: {temperature}, humi: {humidity}"
client.publish("home/sensors", data)
print(f"Temperature: {temperature}°C")
print(f"Humidity: {humidity}%")
return temperature, humidity
except:
print("Failed to read sensor")
return None, None
# Periodically send sensor data
def sensor_loop():
while True:
read_sensor_data()
time.sleep(30) # Send data every 30 seconds
Data collection is that simple.
However, note that the reading interval for the DHT22 should not be too frequent. The official recommendation is at least 2 seconds. I generally set it to 30 seconds, which allows for real-time monitoring without overloading the sensor.
04
Relay control is the main event. Through relays, you can control 220V household appliances.
from machine import Pin
# Initialize relay pins
relay1 = Pin(2, Pin.OUT) # Control light
relay2 = Pin(5, Pin.OUT) # Control fan
relay3 = Pin(18, Pin.OUT) # Control socket
def control_device(device, action):
devices = {
'light': relay1,
'fan': relay2,
'socket': relay3
}
if device in devices:
if action == 'on':
devices[device].on()
status = f"{device} is ON"
elif action == 'off':
devices[device].off()
status = f"{device} is OFF"
else:
status = "Invalid command"
# Send status feedback
client.publish("home/status", status)
print(status)
else:
print("Device does not exist")
# Parse MQTT message and execute control
def parse_control_message(msg):
try:
# Message format: device:action (e.g., light:on)
device, action = msg.decode().split(':')
control_device(device, action)
except:
print("Message format error")
Make sure to choose a low-level triggered relay module. High-level triggered ones can be accidentally triggered when the ESP32 starts up.
05
Here comes the complete main loop code:
def main():
# Connect to WiFi
connect_wifi("your_WiFi_name", "WiFi_password")
# Connect to MQTT
global client
client = reconnect_mqtt()
# Start heartbeat detection
last_ping = time.time()
while True:
try:
# Check MQTT messages
client.check_msg()
# Periodically send sensor data
if time.time() - last_sensor_read > 30:
read_sensor_data()
last_sensor_read = time.time()
# MQTT heartbeat
if time.time() - last_ping > 60:
client.ping()
last_ping = time.time()
time.sleep(0.1)
except Exception as e:
print(f"Main loop exception: {e}")
client = reconnect_mqtt()
if __name__ == "__main__":
main()
This system has been running for over six months with good stability.
The biggest takeaway is learning the importance of exception handling. IoT devices need to run 24/7, and any small bug can lead to system crashes.
Now I can remotely control the lights, fan, and air conditioner in my home. Did I forget to turn off the lights when I went out? Just a tap on my phone solves it. Is it too hot at night? No need to get up to find the remote; I can just turn on the air conditioner directly.
MQTT is truly a great thing. It’s simple to use and highly extensible. If I want to add a new device, I just need to subscribe to the corresponding topic.
Next, I plan to add a camera module to achieve remote monitoring functionality. The world of IoT is really fascinating!