ARTICLE

ESP32 + MQTT + Home Assistant: ออกแบบ Topic, State และ Availability อย่างไรให้ระบบไม่หลอกตัวเอง.

คู่มือสถาปัตยกรรม ESP32 + MQTT + Home Assistant ตั้งแต่ Topic naming, state/command separation, availability, retained message, QoS, stale data, local automation และ broker failure สำหรับระบบ IoT จริง

IoTAutomationHome Assistantโดย Thospaakเผยแพร่ 10 ต.ค. 2569อัปเดต 10 ต.ค. 2569

การทำให้ ESP32 publish ค่าเข้า MQTT แล้ว Home Assistant เห็น entity ไม่ยาก แต่การทำให้ระบบไม่เข้าใจสถานะผิดเมื่อ node reboot, broker ล่ม, Wi-Fi หลุด หรือ message ซ้ำ ต้องออกแบบมากกว่าการตั้ง Topic อย่างเดียว

ภาพพื้นฐาน:

ESP32
  ↓ publish/subscribe
MQTT Broker
  ↓
Home Assistant

แต่ system contract ที่ดีควรมีอย่างน้อย:

State
Command
Availability
Timestamp / freshness
Payload schema
QoS / Retain policy

เริ่มจากแยก State กับ Command

อย่าใช้ Topic เดียวเพื่อทั้งสั่งและรายงานสถานะถ้า semantics ไม่ชัด

ตัวอย่าง:

home/pump/command
home/pump/state

flow:

Home Assistant
   ↓ command = ON
ESP32 validates
   ↓
Driver / Pump control
   ↓ feedback
ESP32
   ↓ state = ON
Home Assistant

Home Assistant ควรแสดง actual/confirmed state ไม่ใช่เปลี่ยน UI ตาม command อย่างเดียว

Desired State กับ Actual State ต่างกัน

ในระบบจริงอาจมี:

desired = ON
actual = OFF
fault = dry_run

นี่เป็น state ที่มีความหมายมากกว่า boolean เดียว

ถ้า Pump ไม่ทำงานเพราะ interlock ระบบต้องบอกว่า command ถูกปฏิเสธ/ล้มเหลว ไม่ใช่ค้าง ON บน dashboard

Topic Naming ควรเป็น Contract

ตัวอย่าง:

site/home/main-meter/power_kw
site/home/pump-01/state
site/home/pump-01/command
site/home/pump-01/availability

หลักที่ควรยึด:

  • stable naming
  • device ID ชัด
  • measurement name ชัด
  • unit อยู่ใน schema/documentation
  • แยก state/event/command
  • ไม่ฝังข้อมูลที่เปลี่ยนบ่อยใน topic ถ้าไม่จำเป็น

Payload ควรเรียบง่ายแต่ Versionable

scalar payload เหมาะกับค่าหนึ่งตัว:

4.23

JSON เหมาะเมื่อหลาย field ต้องถูกส่งเป็น transaction เดียว:

{
  "power_kw": 4.23,
  "voltage_v": 229.8,
  "quality": "good"
}

ถ้า schema มีโอกาสเปลี่ยน ควรมี versioning/documentation ไม่ให้ consumer เดา field

Availability สำคัญมาก

อุปกรณ์ online/offline ควรมี state แยกจาก measurement

ตัวอย่าง:

home/node-01/availability = online

เมื่อ node disconnect แบบผิดปกติ MQTT Last Will สามารถช่วยให้ broker publish offline ตาม configuration

แต่ระบบยังต้องคิดกรณี:

  • broker reboot
  • clean disconnect
  • Wi-Fi flap
  • node frozen แต่ TCP session ยังไม่ตัดทันที

availability จึงไม่ใช่ health check ทุกอย่าง

Last Value ไม่เท่ากับ Current Value

ถ้า Home Assistant ยังเห็น:

Tank level = 72%

แต่ node offline ไป 6 ชั่วโมง ค่า 72% ไม่ควรถูกใช้เป็นค่าปัจจุบันสำหรับ control

ต้องมี freshness policy เช่น:

last_update_age > 5 min
→ stale
→ inhibit automatic control

threshold จริงขึ้นกับ process

Retained Message ใช้กับอะไร

Retain เหมาะกับ state/configuration บางประเภทที่ subscriber ใหม่ควรรู้ค่าล่าสุดทันที

ตัวอย่าง:

current mode
latest desired setpoint
device metadata บางประเภท

แต่ retained command มีความเสี่ยงถ้า device reconnect แล้ว execute คำสั่งเก่าที่ไม่ควรถูกทำอีก

ดังนั้น command topic ต้องมี policy ชัดว่า:

  • retained หรือไม่
  • expiry หรือไม่
  • command ID/timestamp หรือไม่
  • replay ได้หรือไม่

QoS เลือกตาม Message Class

ตัวอย่างแนวคิด:

Telemetry ถี่

temperature every 10 s

QoS 0 อาจเพียงพอ ถ้า sample หายบางตัวไม่กระทบ

Event สำคัญ

fault event

อาจต้อง QoS สูงขึ้น พร้อม duplicate-safe consumer

แต่ QoS 1/2 ไม่ได้ทำให้ business action exactly-once อัตโนมัติ

อ่านพื้นฐานที่ MQTT คืออะไร

Command ต้อง Idempotent เมื่อทำได้

สมมติ command:

set_mode = AUTO

ส่งซ้ำแล้วยังได้ state เดิม จึงปลอดภัยกว่า command แบบ:

toggle

เพราะถ้า duplicate toggle อาจกลับไปสถานะเดิมโดยไม่ตั้งใจ

สำหรับ control ควร prefer desired-state command เมื่อเหมาะสม:

set relay = ON

มากกว่า:

toggle relay

Command ID ช่วย Debug และ Deduplicate

payload อาจมี:

{
  "command_id": "abc-123",
  "desired_state": "ON"
}

controller สามารถ log ว่า command ไหนถูก execute/rejected และลดผลจาก duplicate ตาม architecture

Home Assistant Discovery ใช้ได้แต่ต้องรู้ Source of Truth

MQTT Discovery ช่วยสร้าง entity อัตโนมัติ แต่ discovery config ไม่ได้กำหนด system ownership ให้เรา

ยังต้องรู้ว่า:

  • device state มาจาก topic ไหน
  • command topic ไหน
  • availability topic ไหน
  • unit/device class คืออะไร
  • retained policy คืออะไร

ใช้ ESPHome ทำ MQTT ได้ไหม

ได้ ESPHome มี MQTT Client component

เอกสาร:

ถ้าใช้ Home Assistant เป็น consumer หลัก ESPHome docs ยังชี้ว่าควรพิจารณา Native API ด้วย เพราะอาจไม่จำเป็นต้องมี MQTT broker ใน architecture นั้น

อ่านเปรียบเทียบที่ ESPHome Native API vs MQTT

Local Automation ยังสำคัญแม้มี MQTT

ตัวอย่าง Pump:

Home Assistant → MQTT command
               ↓
ESP32 local validation
  ├─ source water OK?
  ├─ sensor fresh?
  ├─ fault lockout?
  └─ manual override?
               ↓
           execute

ไม่ควรให้ MQTT command bypass local interlock ที่จำเป็น

Broker ล่มแล้วระบบควรทำอะไร

ต้องตอบก่อน production:

Monitoring node

อาจ buffer/continue sensing และ reconnect ภายหลัง

Smart Home light

manual/local control ควรยังใช้ได้

Irrigation/Pump

local control policy/protection ต้องไม่หายเพียงเพราะ broker unavailable

ดังนั้น broker เป็น integration backbone ได้ แต่ไม่ควรเป็น safety controller

Multiple Controllers ระวัง Fighting

ถ้า Pump ถูกสั่งจาก:

Home Assistant
Node-RED
Cloud service
Local scheduler
Manual switch

และทุกตัว publish command ได้ จะเกิด race/conflict

ต้องกำหนด owner/mode เช่น:

MANUAL
LOCAL_AUTO
REMOTE_AUTO
MAINTENANCE
FAULT

แล้วอนุญาต command ตาม mode

Energy Monitoring Example

ESP32 / Gateway
  ↓
home/main-meter/power_kw
home/main-meter/energy_kwh
home/main-meter/availability
  ↓
MQTT Broker
  ├─ Home Assistant
  ├─ Database
  └─ EMS

Power realtime กับ Energy cumulative ต้องแยก semantics และ unit ชัด

Smart Farm Example

Field ESP32
  ├─ soil moisture state
  ├─ tank level state
  ├─ flow state
  ├─ pump availability/fault
  └─ command subscription
        ↓
MQTT Broker
        ↓
HA / Dashboard

แต่ Pump logic สำคัญอยู่ local controller ตาม requirement

Security

MQTT deployment ควรคิดเรื่อง:

  • broker authentication
  • per-device credentials
  • ACL per topic
  • TLS เมื่อ network trust ต้องการ
  • certificate validation
  • secret rotation
  • remote access architecture

อย่า expose broker public โดยเปิด anonymous write เพราะ “แค่บ้าน”

Checklist ก่อนถือว่าระบบพร้อม

  1. state/command แยกกันหรือไม่
  2. availability มีหรือไม่
  3. stale timeout คืออะไร
  4. retained topic มีเหตุผลหรือไม่
  5. command replay/duplicate จะเกิดอะไร
  6. QoS เหมาะกับ message class หรือไม่
  7. broker ล่มแล้ว local function อะไรยังทำงาน
  8. controller owner คือใคร
  9. credentials/ACL แยก device หรือไม่
  10. actual feedback ถูกส่งกลับหรือไม่

สรุป

ESP32 + MQTT + Home Assistant ที่ดีไม่ใช่ระบบที่ “publish ได้” แต่เป็นระบบที่รู้ความแตกต่างระหว่าง:

Command
Desired state
Actual state
Availability
Freshness
Fault

เมื่อ contract พวกนี้ชัด MQTT จะกลายเป็น backbone ที่ดีสำหรับ Smart Home, Smart Farm และ Energy Monitoring โดยไม่ทำให้ Dashboard เข้าใจโลกจริงผิดเพราะ message เก่าหรือ command ที่ยังไม่เกิดผล