IoT Hardware - Kết nối ESP32 & MQTT để điều khiển đèn thật

AI Hunter

Member
Hôm nay chúng ta sẽ làm việc với cả phần mềm và phần cứng.
  • Phần cứng: 1 mạch ESP32 (khoảng 100k), 1 module Relay, vài dây nối.
  • Giao thức: MQTT (Message Queuing Telemetry Transport).
IoT Hardware - Kết nối ESP32 & MQTT để điều khiển đèn thật.jpg

1. Bước 1: Dựng MQTT Broker (Bưu điện)​


Jarvis và ESP32 không nói chuyện trực tiếp với nhau. Chúng cần một "người đưa thư" ở giữa, gọi là MQTT Broker. Chúng ta sẽ dùng Mosquitto.

Mở file docker-compose.yml và thêm service này vào:

Mã:
  mosquitto:
    image: eclipse-mosquitto
    ports:
      - "1883:1883" # Cổng MQTT
      - "9001:9001" # Cổng Web (nếu cần)
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log

Tiếp theo, tạo file cấu hình mosquitto/config/mosquitto.conf (tạo thư mục nếu chưa có):

Mã:
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log

# Quan trọng: Cho phép kết nối không cần mật khẩu (để test cho nhanh)
listener 1883
allow_anonymous true

Sau đó chạy lại Docker:
Mã:
docker-compose up -d

2. Bước 2: Dạy Jarvis gửi lệnh (Backend)​


Jarvis cần biết cách gửi tin nhắn đến Broker.
Mở file backend/requirements.txt thêm:
Mã:
paho-mqtt

Mở file backend/server.py, thêm code kết nối MQTT:

Python:
import paho.mqtt.client as mqtt

# --- CẤU HÌNH MQTT ---
MQTT_BROKER = "mosquitto" # Tên service trong docker-compose
MQTT_PORT = 1883
MQTT_TOPIC = "jarvis/home/livingroom/light"

mqtt_client = mqtt.Client()

def on_connect(client, userdata, flags, rc):
    print(f"📡 Đã kết nối MQTT Broker! Code: {rc}")

mqtt_client.on_connect = on_connect

try:
    mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)
    mqtt_client.loop_start() # Chạy ngầm
except Exception as e:
    print(f"⚠️ Không thể nối MQTT: {e}")

# --- API ĐIỀU KHIỂN ---
class DeviceControl(BaseModel):
    state: str # "ON" hoặc "OFF"

@app.post("/device/light")
async def control_light(cmd: DeviceControl):
    # Gửi lệnh xuống MQTT
    payload = cmd.state.upper()
    mqtt_client.publish(MQTT_TOPIC, payload)
   
    return {"status": "success", "message": f"Đã gửi lệnh {payload} xuống đèn."}

3. Bước 3: Nạp code cho ESP32 (Arduino)​


Đây là lúc bạn cần tải Arduino IDE và cài thư viện PubSubClient (để dùng MQTT).

Sơ đồ nối dây (Cực kỳ cẩn thận):
  • Pin D2 của ESP32 -> Chân IN của Relay.
  • 3.3V/5V -> VCC Relay.
  • GND -> GND Relay.
  • Bóng đèn 220V: Cắt đôi 1 dây nóng, nối 2 đầu đó vào cổng COM và NO của Relay. (Nếu sợ điện giật, hãy dùng đèn LED 5V để test trước cho an toàn!).

Code Arduino (ESP32):

C++:
#include <WiFi.h>
#include <PubSubClient.h>

// --- CẤU HÌNH ---
const char* ssid = "TEN_WIFI_NHA_BAN";
const char* password = "MAT_KHAU_WIFI";
const char* mqtt_server = "192.168.1.X"; // IP máy tính chạy Docker của bạn
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

// Chân điều khiển Relay (Ví dụ GPIO 2 - Đèn LED có sẵn trên mạch)
const int relayPin = 2;

void setup() {
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
 
  // Kết nối Wifi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWifi connected!");

  // Kết nối MQTT
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void callback(char* topic, byte* message, unsigned int length) {
  String messageTemp;
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  Serial.print("📩 Nhận lệnh: ");
  Serial.println(messageTemp);

  // Xử lý lệnh
  if (messageTemp == "ON") {
    digitalWrite(relayPin, HIGH); // Bật đèn
  } else if (messageTemp == "OFF") {
    digitalWrite(relayPin, LOW);  // Tắt đèn
  }
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Đang nối MQTT...");
    // Tạo ID ngẫu nhiên
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
   
    if (client.connect(clientId.c_str())) {
      Serial.println("Đã kết nối!");
      // Đăng ký nhận tin từ kênh này
      client.subscribe("jarvis/home/livingroom/light");
    } else {
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

4. Chạy thử nghiệm (Moment of Truth)​


  1. Cắm điện ESP32, mở Serial Monitor trên Arduino IDE để xem nó kết nối Wifi và MQTT thành công chưa.
  2. Mở Postman hoặc Terminal, gửi lệnh bật đèn:
    Mã:
    curl -X POST http://localhost:8000/device/light \
         -H "Content-Type: application/json" \
         -d '{"state": "ON"}'
  3. Kết quả: Bạn sẽ nghe tiếng "Tạch" từ Relay, đèn sáng lên, và trên màn hình Jarvis báo "Đã gửi lệnh ON".

Tổng kết​


Chúc mừng! Bạn vừa phá vỡ bức tường giữa thế giới ảo và thực.
Giờ đây, bạn có thể tích hợp lệnh này vào:
  • Voice: "Jarvis, bật đèn" -> Gọi API /device/light.
  • UI React: Vẽ thêm một cái nút to đùng trên màn hình để bấm bật tắt.
  • Automation: Khi Camera Vision phát hiện có người -> Tự động gọi API bật đèn.

Dự án Jarvis của chúng ta đã đi một chặng đường rất dài và gần như đầy đủ các món ăn chơi.
Để kết thúc Series này một cách trọn vẹn, chúng ta cần đưa "đứa con tinh thần" này ra ngoài Internet để bạn bè cùng trầm trồ, thay vì chỉ chạy localhost.
 
Back
Top