กลับไปบทความทั้งหมด
ทำ Smart Home ด้วย MQTT บน ESP32 และ Home Assistant
IoT

ทำ Smart Home ด้วย MQTT บน ESP32 และ Home Assistant

Vasin S.20 กุมภาพันธ์ 25683 min
#esp32#mqtt#smarthome#homeassistant

MQTT คืออะไร?

MQTT (Message Queuing Telemetry Transport) คือโปรโตคอลการสื่อสารแบบ Publish/Subscribe ที่ออกแบบมาสำหรับอุปกรณ์ IoT โดยเฉพาะ มีข้อดีคือ:

  • Lightweight: ใช้แบนด์วิดท์น้อยมาก เหมาะกับอุปกรณ์ที่มีทรัพยากรจำกัด
  • Low Latency: ส่งข้อความได้รวดเร็ว
  • Reliable: มี QoS (Quality of Service) 3 ระดับ
  • Scalable: รองรับอุปกรณ์จำนวนมากพร้อมกัน

หลักการทำงาน Publish/Subscribe

MQTT ทำงานบนหลักการ Publish/Subscribe ซึ่งแตกต่างจากการสื่อสารแบบ Request/Response ทั่วไป:

Broker: เซิร์ฟเวอร์กลางที่รับและส่งต่อข้อความ (เช่น Mosquitto)

Publisher: อุปกรณ์ที่ส่งข้อมูล เช่น ESP32 ที่อ่านค่าอุณหภูมิ

Subscriber: อุปกรณ์ที่รับข้อมูล เช่น Home Assistant ที่แสดงผล

Topic: ชื่อ "ช่อง" ที่ใช้จัดหมวดหมู่ข้อความ เช่น home/living_room/temperature

ติดตั้ง Mosquitto Broker

Mosquitto คือ MQTT Broker แบบ Open Source ที่นิยมใช้มากที่สุด สามารถติดตั้งบน Raspberry Pi หรือ Server ได้

ติดตั้งบน Raspberry Pi / Ubuntu

sudo apt update
sudo apt install mosquitto mosquitto-clients -y

# เปิด Mosquitto ทำงานอัตโนมัติเมื่อบูต
sudo systemctl enable mosquitto
sudo systemctl start mosquitto

# ตรวจสอบสถานะ
sudo systemctl status mosquitto

ตั้งค่า Authentication

# สร้างไฟล์ password
sudo mosquitto_passwd -c /etc/mosquitto/passwd mqttuser

# แก้ไขไฟล์ config
sudo nano /etc/mosquitto/mosquitto.conf

เพิ่มบรรทัดเหล่านี้:

listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd

เขียนโค้ด ESP32 สำหรับ MQTT

ก่อนอื่นต้องติดตั้ง Library PubSubClient ใน Arduino IDE:

  1. ไปที่ Tools → Manage Libraries
  2. ค้นหา "PubSubClient" โดย Nick O'Leary
  3. กด Install
#include <WiFi.h>
#include <PubSubClient.h>

// Wi-Fi credentials
const char* ssid = "WiFi_ของคุณ";
const char* password = "รหัส_WiFi";

// MQTT Broker
const char* mqtt_server = "192.168.1.100";  // IP ของ Raspberry Pi
const int mqtt_port = 1883;
const char* mqtt_user = "mqttuser";
const char* mqtt_pass = "รหัส_MQTT";

// Topics
const char* topic_temp = "home/living_room/temperature";
const char* topic_led = "home/living_room/led";

WiFiClient espClient;
PubSubClient client(espClient);

// Callback รับข้อความ
void callback(char* topic, byte* payload, unsigned int length) {
  String message = "";
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  Serial.printf("ได้รับข้อความจาก %s: %s\n", topic, message.c_str());
  
  // ควบคุม LED จาก MQTT
  if (String(topic) == topic_led) {
    if (message == "ON") {
      digitalWrite(2, HIGH);
    } else if (message == "OFF") {
      digitalWrite(2, LOW);
    }
  }
}

void connectMQTT() {
  while (!client.connected()) {
    Serial.print("กำลังเชื่อมต่อ MQTT...");
    String clientId = "ESP32-" + String(random(0xffff), HEX);
    
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
      Serial.println("เชื่อมต่อสำเร็จ!");
      // Subscribe รับคำสั่ง LED
      client.subscribe(topic_led);
    } else {
      Serial.printf("ล้มเหลว rc=%d รอ 5 วินาที\n", client.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(2, OUTPUT);
  
  // เชื่อมต่อ Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi เชื่อมต่อแล้ว");
  
  // ตั้งค่า MQTT
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) connectMQTT();
  client.loop();
  
  // ส่งค่าอุณหภูมิทุก 10 วินาที (ใช้ค่าจำลอง)
  static unsigned long lastMsg = 0;
  if (millis() - lastMsg > 10000) {
    lastMsg = millis();
    float temp = 25.5 + random(-20, 20) / 10.0;
    String payload = String(temp, 1);
    client.publish(topic_temp, payload.c_str());
    Serial.printf("ส่งอุณหภูมิ: %s°C\n", payload.c_str());
  }
}

ในโค้ดจริงควรใช้ DHT22 หรือ BMP280 แทนค่าจำลอง และควรเพิ่มการ handle reconnect Wi-Fi ด้วย

เชื่อมต่อกับ Home Assistant

Home Assistant รองรับ MQTT ได้โดยตรง ตั้งค่าใน configuration.yaml:

mqtt:
  broker: 192.168.1.100
  port: 1883
  username: mqttuser
  password: รหัส_MQTT

sensor:
  - platform: mqtt
    name: "อุณหภูมิห้องนั่งเล่น"
    state_topic: "home/living_room/temperature"
    unit_of_measurement: "°C"
    device_class: temperature

switch:
  - platform: mqtt
    name: "LED ห้องนั่งเล่น"
    command_topic: "home/living_room/led"
    payload_on: "ON"
    payload_off: "OFF"

ทดสอบด้วย MQTT Explorer

MQTT Explorer เป็นโปรแกรม GUI ที่ช่วยให้มองเห็น topic และข้อความได้ง่าย ดาวน์โหลดได้จาก mqtt-explorer.com

ใช้ mosquitto_pub/sub ทดสอบผ่าน command line:

# Subscribe ดู topic
mosquitto_sub -h 192.168.1.100 -u mqttuser -P รหัส -t "home/#" -v

# Publish ทดสอบ
mosquitto_pub -h 192.168.1.100 -u mqttuser -P รหัส -t "home/living_room/led" -m "ON"

ใช้ topic แบบ hierarchy เช่น home/floor1/living_room/temperature จะช่วยให้จัดการอุปกรณ์หลายตัวได้ง่ายขึ้น

สรุป

MQTT เป็นโปรโตคอลที่เหมาะสมอย่างยิ่งสำหรับการสร้างระบบ Smart Home ด้วย ESP32 เพราะใช้ทรัพยากรน้อย สื่อสารได้เร็ว และรองรับอุปกรณ์หลายตัวพร้อมกัน เมื่อรวมกับ Home Assistant ก็จะได้ระบบบ้านอัจฉริยะที่สมบูรณ์แบบ พร้อมหน้า Dashboard และการ Automation ที่หลากหลาย

ถ้าบทความนี้มีประโยชน์ แชร์ให้เพื่อนๆ ด้วยนะ