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 จริง
การทำให้ 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 ก่อนถือว่าระบบพร้อม
- state/command แยกกันหรือไม่
- availability มีหรือไม่
- stale timeout คืออะไร
- retained topic มีเหตุผลหรือไม่
- command replay/duplicate จะเกิดอะไร
- QoS เหมาะกับ message class หรือไม่
- broker ล่มแล้ว local function อะไรยังทำงาน
- controller owner คือใคร
- credentials/ACL แยก device หรือไม่
- 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 ที่ยังไม่เกิดผล