คู่มือสำคัญเกี่ยวกับ MQTT: หัวข้อ (Topics) และตัวแทน (Wildcards)

ณ จุดนี้ คุณคงทราบแล้วว่า การส่งข้อความผ่าน MQTT เกี่ยวข้องกับสามฝ่ายหลัก ได้แก่ ผู้เผยแพร่ (Publisher), ตัวกลางส่งข้อความ (Message Broker) และ ผู้รับข้อมูล (Subscriber) อย่างน้อยหนึ่งราย นอกจากนี้ ยังมีสองกระบวนการส่งข้อมูล ได้แก่ การส่งจากผู้เผยแพร่ไปยังตัวกลาง และ การส่งจากตัวกลางไปยังผู้รับข้อมูล

โปรโตคอล MQTT ใช้รูปแบบการรับ-ส่งข้อความแบบ Publish/Subscribe (pub/sub) ซึ่งเป็นการสื่อสารแบบ อะซิงโครนัส (Asynchronous) กล่าวคือ เมื่อ ผู้เผยแพร่ (Publisher) ส่งข้อความออกไป ตัวกลางส่งข้อความ (Broker) จะทำหน้าที่ส่งต่อข้อความนั้นไปยัง ผู้รับข้อมูล (Subscriber) ทุกคนที่สมัครรับหัวข้อนั้นไว้

อยากรู้เพิ่มเติมเกี่ยวกับโครงสร้างของหัวข้อ (Topic) ใน MQTT, การตั้งชื่อหัวข้อ และการใช้ตัวแทน (Wildcard) อย่างถูกต้องหรือไม่? อ่านบทความนี้เพื่อหาคำตอบ!

หากคุณต้องการข้อมูลพื้นฐานเกี่ยวกับ MQTT แนะนำให้ดูบทความของเราที่อธิบาย พื้นฐานของ MQTT และ ระดับคุณภาพของบริการ (QoS) ใน MQTT

MQTT Topic คืออะไร?

MQTT Topic คือ ตัวกรองที่ตัวกลางส่งข้อความ (Broker) ใช้ในการจัดส่งข้อความในระบบ MQTT กล่าวง่าย ๆ ก็คือ ตัวกลางจะกรองไคลเอ็นต์ทั้งหมดที่เชื่อมต่ออยู่ตามการสมัครรับของพวกเขา และส่งต่อข้อความไปยังผู้รับข้อมูล (Subscribers) ที่เกี่ยวข้อง

ทั้ง ผู้เผยแพร่ (Publisher) และ ผู้รับข้อมูล (Subscriber) สามารถสร้างหัวข้อ (Topic) ได้ โดยหัวข้อจะคงอยู่ตราบใดที่ยังมีไคลเอ็นต์สมัครรับข้อมูล แต่หากไม่มีผู้สมัครรับข้อมูลอีกต่อไป หัวข้อนั้นจะถูกลบออกไป โดยอัตโนมัติ หาก Subscriber สุดท้ายตัดการเชื่อมต่อ และไม่มีเซสชันคงอยู่ (Persistent Session) หัวข้อนั้นก็จะถูกละทิ้งไป

เซสชันคงอยู่ (Persistent Session) หมายความว่า ข้อความจะถูกเก็บไว้ใน Broker แม้ว่า Subscriber จะขาดการเชื่อมต่อ เพื่อให้แน่ใจว่าจะไม่มีข้อความสูญหาย หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับเซสชันคงอยู่ สามารถดูได้จากบทความในบล็อกของเรา

ารออกแบบโครงสร้างและการตั้งชื่อ MQTT Topic

แม้ว่า MQTT Topic จะเป็นเพียงสตริงข้อความธรรมดา แต่ก็ต้องปฏิบัติตามโครงสร้างที่กำหนดไว้ MQTT ใช้โครงสร้างแบบลำดับชั้น (Hierarchical Structure) คล้ายกับระบบไฟล์ในคอมพิวเตอร์ และใช้เครื่องหมาย เครื่องหมายทับ (/) เป็นตัวคั่น (Delimiter)

ในระบบไฟล์ของคอมพิวเตอร์ เครื่องหมายทับ (/) ใช้ระบุตำแหน่งของโฟลเดอร์หรือไฟล์ ขณะที่ใน MQTT เครื่องหมายนี้ใช้แบ่งระดับของหัวข้อ (Topic Levels) โดยที่ ชื่อหัวข้อ (Topic Name) เป็นป้ายกำกับที่ใช้กำหนดระดับของหัวข้อ และช่วยให้ Broker สามารถกำหนดเส้นทางของข้อความได้อย่างแม่นยำ

เมื่อเข้าใจโครงสร้างและหลักการตั้งชื่อของ MQTT Topic แล้ว เราจะไปเจาะลึกเกี่ยวกับการสร้างหัวข้อในระบบนี้ต่อไป โดยข้อกำหนดสำคัญ ได้แก่

  • Topic จะถูกต้องตามหลัก MQTT ก็ต่อเมื่อใช้ตัวอักษรที่เข้ารหัสแบบ UTF-8
  • ชื่อของ Topic ต้องมีความยาวอย่างน้อย 1 ตัวอักษร

รายละเอียดเพิ่มเติมเกี่ยวกับการสร้างและใช้ MQTT Topic จะถูกอธิบายในหัวข้อต่อไป

ข้อควรระวังในการสร้าง MQTT Topic

1. ความแตกต่างระหว่างตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (Case Sensitivity)

MQTT แยกแยะความแตกต่างระหว่างตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ซึ่งหมายความว่า หัวข้อที่มีตัวอักษรต่างกันแม้เพียงตัวเดียวก็ถือเป็นคนละหัวข้อกัน

ตัวอย่างเช่น:
Abc/outlet01/alert02
abc/outlet01/alert02

ถึงแม้โครงสร้างจะเหมือนกัน แต่เนื่องจาก “Abc” และ “abc” ต่างกัน ระบบ MQTT จะมองว่านี่คือ สองหัวข้อที่แตกต่างกัน

ข้อควรระวัง:
หากคุณเผยแพร่ (Publish) ข้อความไปที่ Abc/outlet01/alert02 แต่ผู้รับข้อมูล (Subscriber) สมัครรับที่ abc/outlet01/alert02 พวกเขาจะไม่ได้รับข้อความเลย แม้ว่าหัวข้อจะดูคล้ายกันก็ตาม

ดังนั้น ควรตรวจสอบความถูกต้องของตัวอักษร และกำหนดมาตรฐานการตั้งชื่อให้ชัดเจนเพื่อหลีกเลี่ยงข้อผิดพลาดในการส่งข้อมูลผ่าน MQTT

หมายเหตุ:
ชื่อของ MQTT Topic ต้องตรงกันอย่างสมบูรณ์

เนื่องจาก MQTT แยกแยะตัวพิมพ์เล็ก-พิมพ์ใหญ่ และถือว่าหัวข้อที่ต่างกันแม้เพียงตัวอักษรเดียวเป็นคนละหัวข้อ ดังนั้น Publisher และ Subscriber ต้องใช้ชื่อ Topic ที่ตรงกัน 100% เพื่อให้สามารถส่งและรับข้อความได้อย่างถูกต้อง

หัวข้อ (Topic) ในแพ็กเก็ต PUBLISH ต้องตรงกับหัวข้อที่ผู้รับข้อมูล (Subscribers) สมัครรับไว้

หากหัวข้อไม่ตรงกัน Subscriber จะไม่ได้รับข้อความ แม้ว่าจะดูคล้ายกันก็ตาม ดังนั้น Publisher และ Subscriber ต้องใช้ชื่อ Topic ที่ตรงกัน 100% เพื่อให้สามารถส่งและรับข้อความได้อย่างถูกต้อง

การตั้งชื่อ MQTT Topic ให้สอดคล้องกัน (Consistent MQTT Topic Names)

การรักษาความสอดคล้องของ โครงสร้างและการตั้งชื่อ MQTT Topic มีความสำคัญมาก โดยนอกจากต้อง ใช้ตัวอักษรให้ตรงกัน (Case Sensitivity) แล้ว ควรใช้โครงสร้างหัวข้อที่เป็นมาตรฐานภายในโปรเจกต์เดียวกัน เพื่อให้การส่งและรับข้อมูลเป็นระบบและจัดการได้ง่ายขึ้น

วางแผนโครงสร้าง MQTT Topic ล่วงหน้า

ก่อนที่จะเริ่มส่งข้อความผ่าน MQTT ควรออกแบบโครงสร้างของ Topic ให้เป็นมาตรฐานและมีรูปแบบที่สม่ำเสมอ

ตัวอย่าง:
หากต้องการเผยแพร่ข้อความแจ้งเตือน (alert02) สำหรับ outlet01 เราอาจใช้หัวข้อ:
abc/outlet01/alert02

เมื่อมีการแจ้งเตือนใหม่ (alert03) สำหรับ outlet01 ก็ควรใช้โครงสร้างหัวข้อที่เหมือนกัน เช่น:
abc/outlet01/alert03

หากใช้โครงสร้างที่สอดคล้องกัน ระบบจะทำงานได้มีประสิทธิภาพขึ้น และช่วยลดข้อผิดพลาดในการเผยแพร่และสมัครรับข้อมูล (Publish/Subscribe)

การกำหนดโครงสร้างและรูปแบบของ MQTT Topic อย่างสม่ำเสมอ

เพื่อป้องกันข้อผิดพลาดในการส่งข้อความหรือการพลาดรับข้อความ คุณควรกำหนดโครงสร้างของหัวข้อ (Topic Structure) และรูปแบบตัวอักษร (Casing) ให้เป็นมาตรฐานภายในโปรเจกต์ของคุณ

เราได้กล่าวถึงเรื่องนี้ไปแล้วก่อนหน้านี้ แต่เราขอย้ำอีกครั้ง เพราะ นี่เป็นปัจจัยสำคัญมากในระบบ MQTT การมีโครงสร้างที่สม่ำเสมอช่วยให้ระบบทำงานได้อย่างถูกต้องและลดปัญหาที่อาจเกิดขึ้นจากการใช้ชื่อหัวข้อที่ไม่เป็นมาตรฐาน

ตัวอักษรที่อนุญาตให้ใช้ใน MQTT Topic

ตามที่ได้กล่าวไปแล้ว MQTT Topic ต้องใช้ตัวอักษรแบบ UTF-8 และต้องมีความยาวอย่างน้อย 1 ตัวอักษรจึงจะถือว่าเป็นหัวข้อที่ถูกต้อง

MQTT อนุญาตให้ใช้ เกือบทุกตัวอักษรและสัญลักษณ์บนแป้นพิมพ์ของคุณ รวมถึงช่องว่าง (Blank Space)

🚨 ข้อควรระวัง:

แม้ว่า MQTT จะรองรับช่องว่าง (Space) แต่ ขอแนะนำอย่างยิ่งให้หลีกเลี่ยงการใช้ช่องว่างในชื่อหัวข้อ เพราะอาจทำให้เกิดความสับสนและปัญหาในการจัดการข้อความ

อักขระที่ต้องหลีกเลี่ยงใน MQTT Topic

เมื่อกำหนดชื่อ MQTT Topic ควรหลีกเลี่ยงการใช้ อักขระพิเศษบางตัว เนื่องจากมีความหมายเฉพาะในโปรโตคอล MQTT ได้แก่:

  1. + และ #ใช้เป็น Wildcard เท่านั้น
    • + และ # เป็น ตัวแทน (Wildcards) ที่ใช้สำหรับสมัครรับข้อความแบบครอบคลุมหัวข้อหลายระดับ (ซึ่งเราจะอธิบายในหัวข้อต่อไป)
    • หากใช้ผิดที่ อาจทำให้การสมัครรับข้อมูลเกิดข้อผิดพลาด
  2. $เป็นอักขระที่สงวนไว้
    • หัวข้อที่ขึ้นต้นด้วย $ เป็น หัวข้อระบบ (System Topics) ที่กำหนดโดย Broker เท่านั้น
    • ตัวอย่าง: $SYS/ ใช้สำหรับสื่อสารข้อมูลเกี่ยวกับสถานะของ MQTT Broker
    • ผู้ใช้ทั่วไปไม่ควรกำหนดหัวข้อที่ขึ้นต้นด้วย $ เนื่องจากไม่สามารถใช้ในการสื่อสารข้อมูลปกติได้

สรุป

ใช้ตัวอักษร UTF-8 และกำหนดโครงสร้างหัวข้อที่สม่ำเสมอ
หลีกเลี่ยงช่องว่าง (Space) ในชื่อหัวข้อ เพื่อป้องกันความสับสน
อย่าใช้ + และ # ในชื่อหัวข้อโดยตรง (ใช้สำหรับ Wildcards เท่านั้น)
อย่ากำหนดชื่อหัวข้อที่ขึ้นต้นด้วย $ (Broker เท่านั้นที่ใช้ได้)

ต่อไปเราจะมาดูรายละเอียดเกี่ยวกับการใช้ MQTT Wildcards (+ และ #) อย่างถูกต้อง! 🚀

MQTT SYS Topics

MQTT SYS Topics เป็นหัวข้อที่ถูกสงวนไว้สำหรับ MQTT Broker ใช้เพื่อ เผยแพร่ข้อมูลระบบ (System Data) เช่น สถิติและเมตาดาต้าของตัว Broker

ตัวอย่างการใช้งาน SYS Topics คือ การตรวจสอบสถานะการทำงานของ MQTT Broker หรือ ดูข้อมูลเกี่ยวกับจำนวนลูกค้าทั้งหมดที่เชื่อมต่ออยู่


โครงสร้างของ MQTT SYS Topics

ถึงแม้ว่า MQTT Specification จะไม่ได้กำหนดโครงสร้างของ SYS Topics อย่างเป็นทางการ แต่โดยทั่วไป SYS Topics จะเริ่มต้นด้วย $ และมี $SYS เป็นระดับแรกของหัวข้อ

ตัวอย่างของ SYS Topics ได้แก่:

$SYS/broker/load/bytes/received → จำนวนไบต์ที่ Broker ได้รับ
$SYS/broker/clients/total → จำนวนลูกค้าที่เชื่อมต่ออยู่ทั้งหมด
$SYS/broker/messages/sent → จำนวนข้อความที่ถูกส่งโดย Broker

ตัวอย่างการตั้งค่า MQTT Topic

เราได้พูดถึงโครงสร้างและการตั้งชื่อ MQTT Topic ไปแล้ว ต่อไปเราจะมาดูตัวอย่างจริงเพื่อให้เข้าใจชัดเจนยิ่งขึ้น

สมมติว่า บริษัท ABC เป็นบริษัทผลิตรถยนต์ในสหรัฐอเมริกา ซึ่งมีหลายสาขาทั่วประเทศ และต้องการส่งการแจ้งเตือนไปยังทุกสาขา แต่ละสาขาจำเป็นต้องสมัครรับหัวข้อที่เกี่ยวข้องเพื่อรับการแจ้งเตือน

ตัวอย่างที่ไม่ถูกต้องของ MQTT Topic

การตั้งชื่อที่ไม่สม่ำเสมอ อาจทำให้เกิดข้อผิดพลาด

Abc/outlet1/alert01/audiQ3<br>abc/Outlet01/alert1/audiQ3<br>$Abc/alert01/audiQ3<br>abc/Outlet1/alert01/audiQ3

🔴 ปัญหาในตัวอย่างนี้:

  • ใช้ ตัวพิมพ์ใหญ่-เล็กไม่สม่ำเสมอ (Abc, abc, Outlet01, outlet1)
  • โครงสร้างหัวข้อไม่เป็นมาตรฐาน (alert01 กับ alert1 แตกต่างกัน)
  • ใช้ $ ซึ่งเป็นอักขระสงวน ($Abc/alert01/audiQ3)

📌 ผลกระทบ:

  • Outlet01 อาจพลาดข้อความสำคัญ เพราะต้องสมัครรับหลายหัวข้อที่แตกต่างกัน
  • การจัดการ MQTT Broker ซับซ้อนขึ้น เนื่องจากโครงสร้างไม่เป็นระบบ

ตัวอย่างที่ถูกต้องของ MQTT Topic

abc/outlet01/alert01/audiQ3<br>abc/outlet01/alert01/bmwx3<br>abc/outlet01/alert02/audiQ3<br>abc/outlet01/alert02/bmwx3<br>

🔵 สิ่งที่ทำถูกต้อง:

  • ใช้ตัวพิมพ์เล็กทั้งหมด (abc, outlet01, alert01) เพื่อป้องกันความสับสน
  • ใช้โครงสร้างที่สม่ำเสมอ (abc/outletXX/alertXX/carModel)
  • ไม่มีอักขระต้องห้าม เช่น $ หรือ + #

📌 ผลลัพธ์ที่ได้:

  • ง่ายต่อการสมัครรับข้อมูล (Subscription) และการกรองข้อความ
  • ลดข้อผิดพลาดจากการใช้หัวข้อที่ไม่เป็นมาตรฐาน
  • สามารถขยายโครงสร้างได้ง่ายขึ้น เมื่อต้องเพิ่มหัวข้อใหม่

💡 ข้อแนะนำ:
กำหนดมาตรฐานการตั้งชื่อ MQTT Topic ตั้งแต่แรก
ใช้ตัวพิมพ์เล็กทั้งหมดเพื่อหลีกเลี่ยงปัญหา Case Sensitivity
ออกแบบโครงสร้างให้สม่ำเสมอและง่ายต่อการจัดการ

ถัดไป เราจะมาดูวิธีใช้ MQTT Wildcards (+ และ #) อย่างมีประสิทธิภาพ! 🚀

ทำไมต้องใช้โครงสร้าง MQTT Topic ที่สม่ำเสมอ?

จากตัวอย่างก่อนหน้านี้ เราได้ใช้ โครงสร้างของ MQTT Topic ที่เป็นมาตรฐานและมีรูปแบบตัวอักษรที่สม่ำเสมอ ซึ่งช่วยให้ Outlet01 สามารถรับข้อความสำคัญจาก บริษัท ABC ได้ง่ายขึ้น โดยไม่ต้องจดจำโครงสร้างที่แตกต่างกันหลายรูปแบบ

ปัญหาของการสมัครรับหัวข้อจำนวนมาก

อย่างไรก็ตาม หาก Outlet01 ต้องสมัครรับการแจ้งเตือนมากกว่า 100 หัวข้อ การกำหนดตัวกรองหัวข้อ (Topic Filters) อาจเป็นเรื่องที่ยุ่งยากและซับซ้อน

ตัวอย่างเช่น:

abc/outlet01/alert01/audiQ3<br>abc/outlet01/alert01/bmwx3<br>abc/outlet01/alert02/audiQ3<br>abc/outlet01/alert02/bmwx3
...
(รายการยาวมาก อาจมีหลายร้อยหัวข้อ)

การต้องสมัครรับ ทีละหัวข้อ อาจใช้เวลามากและทำให้โค้ดยุ่งยาก

ทางออก: ใช้ MQTT Wildcards!

💡 ในกรณีนี้ “Wildcards” ใน MQTT สามารถช่วยให้การสมัครรับข้อมูลมีประสิทธิภาพมากขึ้น

🔹 MQTT Wildcards (+ และ #) ช่วยให้สมัครรับหลายหัวข้อได้ในครั้งเดียว
🔹 ลดจำนวน Topic Filters ที่ต้องกำหนดด้วยตนเอง
🔹 ทำให้โค้ดกระชับขึ้นและจัดการได้ง่ายขึ้น

📌 ถัดไป เราจะมาดูรายละเอียดของ MQTT Wildcards และวิธีใช้งานให้เกิดประโยชน์สูงสุด! 🚀

MQTT Wildcards คืออะไร?

MQTT Wildcards เป็น อักขระพิเศษ ที่ช่วยให้ Subscriber สามารถสมัครรับข้อมูลจากหลายหัวข้อได้พร้อมกัน โดยใช้รูปแบบที่กำหนด แทนที่จะต้องระบุทุกหัวข้อด้วยตนเอง

🔹 Wildcards ใช้ได้เฉพาะกับการสมัครรับข้อมูล (Subscription) เท่านั้น
🔹 ใช้ไม่ได้กับการเผยแพร่ข้อความ (Publishing)

ในระบบ MQTT มีเพียง 2 Wildcards ที่สามารถใช้ได้ ได้แก่:

  1. + (Single-Level Wildcard)
  2. # (Multi-Level Wildcard)

เมื่อไหร่ควรใช้ MQTT Wildcards?

Wildcards มีประโยชน์อย่างมาก เมื่อต้องสมัครรับหลายหัวข้อที่มีโครงสร้างคล้ายกัน

💡 ตัวอย่าง:
หาก Outlet01 ต้องสมัครรับข้อมูลจาก 50 สาขาอื่น ๆ ของ บริษัท ABC
หากสมัครทีละหัวข้อ จะใช้เวลามากและซับซ้อน
การใช้ Wildcards ช่วยลดจำนวน Topic Filters ที่ต้องกำหนดด้วยตนเอง

เมื่อไหร่ควรใช้ MQTT Wildcards?

Wildcards มีประโยชน์อย่างมาก เมื่อต้องสมัครรับหลายหัวข้อที่มีโครงสร้างคล้ายกัน

💡 ตัวอย่าง:
หาก Outlet01 ต้องสมัครรับข้อมูลจาก 50 สาขาอื่น ๆ ของ บริษัท ABC
หากสมัครทีละหัวข้อ จะใช้เวลามากและซับซ้อน
การใช้ Wildcards ช่วยลดจำนวน Topic Filters ที่ต้องกำหนดด้วยตนเอง

ประเภทของ MQTT Wildcards

1️⃣ เครื่องหมาย + (Single-Level Wildcard)

🔹 Wildcard + ใช้แทนชื่อหัวข้อใน “1 ระดับ” เท่านั้น
🔹 ช่วยลดความยุ่งยากในการสมัครรับหลายหัวข้อที่อยู่ในระดับเดียวกัน
🔹 ต้องใช้ + แทนทั้งระดับของหัวข้อ ไม่สามารถใช้เป็นส่วนหนึ่งของชื่อหัวข้อได้

ตัวอย่างการใช้ + Wildcard

โครงสร้างของ Topic:

abc/outlet01/alert01<br>abc/outlet02/alert01<br>abc/outlet03/alert01<br>...<br>

📌 หากต้องการสมัครรับการแจ้งเตือน alert01 จากทุกสาขา
👉 สามารถใช้ Wildcard + ได้ดังนี้:

Subscription:

abc/+/alert01<br>

📌 Wildcard + แทน outlet01, outlet02, outlet03 ในระดับที่สอง
📌 Subscriber จะได้รับข้อความจากทุกสาขาที่มี alert01

ข้อควรระวังเกี่ยวกับ + Wildcard

Wildcard + ต้องอยู่ในระดับของหัวข้อเท่านั้น
ไม่สามารถใช้เป็นคำต่อท้าย เช่น abc/outlet+01/alert01

ตัวอย่างที่ไม่ใช้ Wildcard +

หาก Outlet01 ต้องสมัครรับทุกการแจ้งเตือน โดยไม่ใช้ Wildcard + จะต้องระบุทุกหัวข้อแบบแยกกัน เช่น:

abc/outlet01/alert01/audiQ3
abc/outlet01/alert02/bmwx3
abc/outlet01/alert03/audiQ3
abc/outlet01/alert04/bmwx3
...

📌 ปัญหา:

  • ต้องสมัครรับหัวข้อที่แตกต่างกันหลายรายการ
  • ทำให้การตั้งค่าใช้เวลานานและเกิดข้อผิดพลาดได้ง่าย
  • ถ้าจำนวน Alert มีมากขึ้น จะจัดการได้ยากขึ้น

ตัวอย่างที่ใช้ Wildcard + อย่างไม่ถูกต้อง

bashCopyEditabc/outlet01/alert+/audiQ3  ❌ (ผิด)

📌 ข้อผิดพลาด:

  • ใช้ + เป็นส่วนหนึ่งของคำ (alert+) ซึ่งไม่ถูกต้อง
  • Wildcard + ต้องแทนที่ทั้งระดับของหัวข้อเท่านั้น

ตัวอย่างที่ใช้ Wildcard + อย่างถูกต้อง

1️⃣ สมัครรับการแจ้งเตือนทุกระดับสำหรับ audiQ3

bashCopyEditabc/outlet01/+/audiQ3  ✅

📌 หมายความว่า:

  • จะได้รับทุก Alert ที่เกี่ยวข้องกับ audiQ3
  • ตัวอย่างข้อความที่ Outlet01 จะได้รับ:
    abc/outlet01/alert01/audiQ3
    abc/outlet01/alert02/audiQ3
    abc/outlet01/alert03/audiQ3
    abc/outlet01/alert04/audiQ3

2️⃣ สมัครรับการแจ้งเตือน alert01 สำหรับรถยนต์ทุกยี่ห้อ

bashCopyEditabc/outlet01/alert01/+  ✅

📌 หมายความว่า:

  • Outlet01 จะได้รับทุกข้อความของ alert01 ไม่ว่าจะเป็นรถยนต์รุ่นไหนก็ตาม
  • ตัวอย่างข้อความที่ Outlet01 จะได้รับ:
    abc/outlet01/alert01/audiQ3
    abc/outlet01/alert01/bmwx3
    abc/outlet01/alert01/mercedesC200

📌 สรุป: ใช้ + Wildcard อย่างถูกต้อง

Wildcard + ใช้แทน “หนึ่งระดับของหัวข้อ” เท่านั้น
ต้องใช้ + แทนระดับของหัวข้อทั้งหมด ไม่สามารถใช้เป็นคำต่อท้าย (alert+) ได้
ช่วยให้สมัครรับหลายหัวข้อได้ง่ายขึ้นโดยไม่ต้องระบุทุกหัวข้อแยกกัน


📌 ถัดไป เราจะมาดู Wildcard # (Multi-Level Wildcard) และวิธีใช้เพื่อสมัครรับทุกหัวข้อในระดับลึก!

Wildcard # ใน MQTT (Multi-Level Wildcard)

เครื่องหมาย # เป็น Wildcard ที่สามารถจับคู่ได้มากกว่าหนึ่งระดับของหัวข้อ
แต่มีเงื่อนไขสำคัญที่ต้องจำ:
# ต้องใช้เป็น “ระดับสุดท้าย” ของหัวข้อเท่านั้น
# ต้องใช้แทนระดับหัวข้อทั้งหมด ไม่สามารถใช้เป็นส่วนหนึ่งของคำได้

📌 ใช้ # เพื่อสมัครรับหัวข้อที่มีโครงสร้างซับซ้อนและระดับหัวข้อหลายชั้น

🔹 ตัวอย่างการใช้ Wildcard #

💡 สถานการณ์สมมติ:
Outlet01 ของบริษัท ABC ต้องการรับการแจ้งเตือนทั้งหมดของ Audi Q3

ตัวอย่างที่ไม่ใช้ Wildcard #

หากต้องสมัครรับข้อมูล โดยไม่ใช้ Wildcard # จะต้องระบุทุกหัวข้อแยกกัน เช่น:

abc/outlet01/alert01/audiQ3<br>abc/outlet01/alert02/audiQ3<br>abc/outlet01/alert03/audiQ3<br>abc/outlet01/alert04/audiQ3<br>...<br>

📌 ปัญหา:

  • ต้องสมัครรับหัวข้อที่แตกต่างกันจำนวนมาก
  • ใช้เวลานานและจัดการได้ยาก

ตัวอย่างที่ใช้ Wildcard # อย่างไม่ถูกต้อง

abc/outlet01/alert#/audiQ3   ❌ (ผิด)<br>abc/outlet#/alert01/audiQ3   ❌ (ผิด)<br>abc/#/alert01/audiQ3         ❌ (ผิด)<br>

📌 ข้อผิดพลาด:

  • ใช้ # ในตำแหน่งที่ไม่ใช่ “ระดับสุดท้าย” ของหัวข้อ
  • ต้องใช้ # เป็นตัวแทนของทุกระดับที่อยู่ถัดจากจุดที่กำหนด

ตัวอย่างที่ใช้ Wildcard # อย่างถูกต้อง

1️⃣ สมัครรับทุกข้อความภายใต้ abc/

abc/#   ✅<br>

📌 หมายความว่า:

  • ได้รับ ทุกข้อความ ที่อยู่ภายใต้ abc/
  • ตัวอย่างข้อความที่ Outlet01 จะได้รับ:
    abc/outlet01/alert01/audiQ3
    abc/outlet03/alert05/audiQ3
    abc/outlet05/alert02/bmwx3

2️⃣ สมัครรับทุกข้อความที่เกี่ยวข้องกับ outlet01

abc/outlet01/#   ✅<br>

📌 หมายความว่า:

  • Outlet01 จะได้รับทุกข้อความที่เกี่ยวข้องกับตนเอง
  • ตัวอย่างข้อความที่ Outlet01 จะได้รับ:
    abc/outlet01/alert01/audiQ3
    abc/outlet01/alert03/bmwx3
    abc/outlet01/alert05/mercedesC200

3️⃣ สมัครรับทุกข้อความที่เกี่ยวข้องกับ alert01 ของ outlet01

abc/outlet01/alert01/#   ✅<br>

📌 หมายความว่า:

  • Outlet01 จะได้รับเฉพาะข้อความของ alert01 สำหรับรถทุกยี่ห้อ
  • ตัวอย่างข้อความที่ Outlet01 จะได้รับ:
    abc/outlet01/alert01/audiQ3
    abc/outlet01/alert01/bmwx3
    abc/outlet01/alert01/mercedesC200

📌 สรุป: ใช้ # Wildcard อย่างถูกต้อง

# ต้องอยู่เป็นระดับสุดท้ายของหัวข้อเท่านั้น
ช่วยให้สมัครรับข้อมูลได้ครอบคลุมโดยไม่ต้องระบุทุกหัวข้อแยกกัน
เหมาะสำหรับโครงสร้างที่มีหลายระดับและต้องการสมัครรับข้อมูลแบบกว้าง
ห้ามใช้ # เป็นคำต่อท้าย เช่น alert#/audiQ3


📌 ถัดไป เราจะสรุปแนวทางปฏิบัติที่ดีที่สุดในการใช้ MQTT Topics และ Wildcards ให้มีประสิทธิภาพสูงสุด! 🚀

ข้อควรระวังในการใช้ Wildcard # ใน MQTT

แม้ว่า Wildcard # จะมีประโยชน์มาก แต่ไม่ควรใช้เพื่อสมัครรับ “ทุกหัวข้อ” โดยไม่จำเป็น เพราะอาจทำให้ระบบทำงานหนักเกินไป (Overload)

🚨 ปัญหาของการสมัครรับทุกหัวข้อด้วย #

ลูกค้า (Client) จะได้รับทุกข้อความที่ถูกเผยแพร่จากทุกหัวข้อ

  • ทำให้ปริมาณข้อมูลที่ต้องประมวลผลเพิ่มขึ้นอย่างมาก
  • อาจทำให้ MQTT Client ใช้ทรัพยากรมากเกินไป และเกิดความล่าช้า

ระบบอาจต้องรับโหลดสูงเกินไป (High Load on System)

  • หากมี MQTT Broker ขนาดใหญ่ที่มีหัวข้อจำนวนมาก การสมัครรับทุกข้อความอาจทำให้ ระบบช้าลงหรือแม้กระทั่งล่มได้

✅ แนวทางที่แนะนำในการใช้ #

🔹 สมัครรับเฉพาะหัวข้อที่จำเป็นเท่านั้น
✅ แทนที่จะใช้ abc/# ซึ่งรับทุกข้อความ ควรใช้ abc/outlet01/# หากต้องการรับเฉพาะข้อมูลของ Outlet01

🔹 ใช้ระบบควบคุมสิทธิ์ (Access Control) ร่วมกับ MQTT
✅ ระบบ MQTT Broker ส่วนใหญ่มีฟังก์ชันควบคุมสิทธิ์ เพื่อให้แน่ใจว่า Client จะได้รับข้อความจากเฉพาะหัวข้อที่ได้รับอนุญาต

🔹 หลีกเลี่ยงการใช้ # หากไม่จำเป็น
✅ ใช้ Wildcard + เพื่อสมัครรับเฉพาะระดับที่ต้องการ แทนที่จะใช้ #

⚠️ หมายเหตุ: การสมัครรับทุกหัวข้อ (#) ไม่รวมถึงหัวข้อที่ขึ้นต้นด้วย $

📌 หากใช้ # เพื่อสมัครรับทุกหัวข้อ คุณจะไม่ได้รับข้อความจากหัวข้อที่ขึ้นต้นด้วย $

ตัวอย่าง:
Subscription:

#

📌 จะได้รับข้อความจากทุกหัวข้อ ยกเว้นหัวข้อที่ขึ้นต้นด้วย $ เช่น

  • abc/outlet01/alert01/audiQ3 ✅ (ได้รับ)
  • $SYS/broker/clients/total ❌ (ไม่ได้รับ)

📌 หากต้องการสมัครรับหัวข้อ $SYS ต้องสมัครรับแยก เช่น:

$SYS/#

Subscription นี้จะรับเฉพาะหัวข้อที่ขึ้นต้นด้วย $SYS/

📌 สรุป: วิธีใช้ Wildcard # อย่างมีประสิทธิภาพ

ใช้ # เท่าที่จำเป็น เพื่อลดภาระของระบบ
สมัครรับเฉพาะหัวข้อที่ต้องการข้อมูลจริง ๆ
ใช้ Wildcard + แทน หากต้องการจำกัดระดับของหัวข้อ
# ไม่สามารถใช้รับข้อมูลจากหัวข้อที่ขึ้นต้นด้วย $ ได้


📌 ถัดไป เราจะสรุปแนวทางปฏิบัติที่ดีที่สุดในการออกแบบโครงสร้าง MQTT Topics และใช้ Wildcards ให้เกิดประโยชน์สูงสุด! 🚀

การทำงานของ MQTT Wildcards ร่วมกับ QoS Levels

ใน MQTT ผู้เผยแพร่ (Publisher) และผู้รับข้อมูล (Subscriber) สามารถตั้งค่าระดับคุณภาพของบริการ (QoS – Quality of Service) ที่แตกต่างกันได้

📌 แต่! MQTT Broker จะเลือกใช้ QoS ที่ต่ำที่สุดระหว่าง Publisher และ Subscriber

📌 ข้อสำคัญเกี่ยวกับ MQTT Wildcards และ QoS

Wildcards ใช้ได้เฉพาะกับการสมัครรับข้อมูล (Subscription) เท่านั้น
Broker ยังคงปฏิบัติตามกฎ QoS และส่งข้อความตาม QoS ที่ต่ำที่สุด
หากไม่มี Subscriber สำหรับหัวข้อนั้น ข้อความจะถูกละทิ้ง (Discarded)

🔹 ตัวอย่างการทำงานของ MQTT Wildcards กับ QoS

💡 สถานการณ์สมมติ:

  • บริษัท ABC (Publisher) ตั้งค่า QoS = 1 (QoS1)
  • Outlet01 (Subscriber) ตั้งค่า QoS = 2 (QoS2)
  • Outlet01 สมัครรับหัวข้อ abc/outlet01/alert01/# ด้วย QoS2
  • บริษัท ABC ส่งข้อความไปที่ abc/outlet01/alert01/audiQ3 ด้วย QoS1

📌 ผลลัพธ์:
✅ Outlet01 จะได้รับข้อความด้วย QoS1 แม้ว่าจะสมัครรับด้วย QoS2
เหตุผล: Broker เลือกใช้ QoS ที่ต่ำที่สุด ระหว่าง Publisher และ Subscriber

📌 สิ่งที่ต้องจำเกี่ยวกับ MQTT Wildcards และ QoS

MQTT Wildcards ไม่เปลี่ยนกฎของ QoS → Broker ยังคงเลือก QoS ที่ต่ำที่สุด
หากไม่มี Subscriber ในหัวข้อที่กำหนด ข้อความจะถูกละทิ้งโดย Broker
แม้ว่า Subscriber จะสมัครรับด้วย QoS2 แต่ถ้า Publisher ใช้ QoS1 ข้อความที่ได้รับจะเป็น QoS1

📌 ถัดไป เราจะสรุปแนวทางที่ดีที่สุดในการออกแบบโครงสร้าง MQTT Topics และใช้ Wildcards ให้เกิดประโยชน์สูงสุด! 🚀

🔹 สรุปสาระสำคัญเกี่ยวกับ MQTT Topics, โครงสร้างหัวข้อ และ Wildcards

💡 ทบทวนทุกสิ่งที่เราได้เรียนรู้เกี่ยวกับ MQTT

📌 1. การมีอยู่ของ MQTT Topics

หัวข้อ (Topic) จะมีอยู่ก็ต่อเมื่อ:

  • มี Subscriber สมัครรับหัวข้อนั้น
  • มีข้อความที่ถูกเก็บไว้ในหัวข้อนั้น (เช่น ในกรณีที่ใช้ QoS 1 หรือ QoS 2)

📌 2. โครงสร้างของ MQTT Topics

MQTT ใช้เครื่องหมาย / เป็นตัวแบ่งหัวข้อ (Delimiter) คล้ายกับโครงสร้างไฟล์ในคอมพิวเตอร์
หัวข้อมีโครงสร้างแบบลำดับชั้น (Hierarchical Structure) เพื่อให้สามารถจัดหมวดหมู่ข้อมูลได้ง่าย

📌 3. กฎการตั้งชื่อ MQTT Topics

หัวข้อมีความไวต่ออักษรพิมพ์เล็ก-พิมพ์ใหญ่ (Case-Sensitive)
ควรตั้งชื่อหัวข้อให้เป็นมาตรฐานและสอดคล้องกันภายในโปรเจกต์
ชื่อหัวข้อ MQTT ต้องมีอย่างน้อย 1 ตัวอักษร
สามารถใช้ตัวอักษร UTF-8 ได้เกือบทั้งหมด แต่ต้องหลีกเลี่ยงอักขระพิเศษบางตัว

อักขระที่ห้ามใช้ในชื่อหัวข้อ MQTT:

  • $ → ใช้สำหรับ System Topics ($SYS/) ของ Broker
  • * → ไม่รองรับใน MQTT Topics
  • + และ # → ใช้เป็น Wildcards เท่านั้น ไม่สามารถใช้ในชื่อหัวข้อปกติได้

📌 4. ความหมายของ $, + และ # ใน MQTT

$ → ใช้สำหรับ System Topics ($SYS/) ที่ Broker ใช้ในการส่งข้อมูลระบบ เช่น สถานะการทำงานของ Broker
+Single-Level Wildcard ใช้แทนค่าหนึ่งระดับของหัวข้อ
#Multi-Level Wildcard ใช้แทนค่าทุกระดับที่อยู่ถัดจากจุดที่กำหนด

📌 5. การใช้ MQTT Wildcards

Wildcards ใช้ได้เฉพาะกับการสมัครรับข้อมูล (Subscription) เท่านั้น
ไม่สามารถใช้ Wildcards (+ หรือ #) ในการเผยแพร่ข้อความ (Publishing)
ช่วยลดจำนวน Topic Filters ที่ต้องกำหนดเอง ทำให้จัดการระบบได้ง่ายขึ้น

🚀 สรุปแนวทางที่ดีที่สุดในการใช้งาน MQTT Topics และ Wildcards

ออกแบบโครงสร้างหัวข้อให้เป็นมาตรฐานและสอดคล้องกัน
ใช้ตัวพิมพ์เล็กทั้งหมดเพื่อป้องกันความสับสนจาก Case Sensitivity
ใช้ Wildcards (+ และ #) ให้เหมาะสม เพื่อลดความยุ่งยากในการสมัครรับข้อมูล
หลีกเลี่ยงการสมัครรับทุกหัวข้อ (#) โดยไม่จำเป็น เพื่อลดภาระของระบบ
ใช้ QoS ที่เหมาะสมกับความต้องการของระบบ เพื่อลดการสูญหายของข้อความ

ตัวอย่างการตั้งชื่อ MQTT Topics สำหรับบ้าน 3 หลัง 🏡🏡🏡

💡 สถานการณ์สมมติ:

  • บ้านทั้ง 3 หลัง ใช้ระบบควบคุมอุปกรณ์ IoT ผ่าน MQTT
  • อุปกรณ์แต่ละชิ้นต้องมี โครงสร้างหัวข้อที่สม่ำเสมอ
  • ระบบควรสามารถขยายได้ง่ายหากมีการเพิ่มอุปกรณ์ใหม่

📌 โครงสร้างมาตรฐานของหัวข้อ MQTT

homeX/roomY/deviceZ/action

📌 รายละเอียดแต่ละส่วน
homeX → ระบุบ้านหลังที่ 1, 2 หรือ 3
roomY → ระบุห้อง เช่น ห้องนั่งเล่น ห้องครัว ห้องนอน
deviceZ → อุปกรณ์ที่ควบคุม เช่น หลอดไฟ แอร์ ทีวี
action → คำสั่ง เช่น เปิด (on), ปิด (off), อ่านค่า (status)

ตัวอย่างการตั้งชื่อ MQTT Topics สำหรับบ้าน 3 หลัง 🏡🏡🏡

💡 สถานการณ์สมมติ:

  • บ้านทั้ง 3 หลัง ใช้ระบบควบคุมอุปกรณ์ IoT ผ่าน MQTT
  • อุปกรณ์แต่ละชิ้นต้องมี โครงสร้างหัวข้อที่สม่ำเสมอ
  • ระบบควรสามารถขยายได้ง่ายหากมีการเพิ่มอุปกรณ์ใหม่

📌 โครงสร้างมาตรฐานของหัวข้อ MQTT

bashCopyEdithomeX/roomY/deviceZ/action

📌 รายละเอียดแต่ละส่วน
homeX → ระบุบ้านหลังที่ 1, 2 หรือ 3
roomY → ระบุห้อง เช่น ห้องนั่งเล่น ห้องครัว ห้องนอน
deviceZ → อุปกรณ์ที่ควบคุม เช่น หลอดไฟ แอร์ ทีวี
action → คำสั่ง เช่น เปิด (on), ปิด (off), อ่านค่า (status)


🏡 บ้านหลังที่ 1 (home1)

ห้องนั่งเล่น (living_room)

✅ ควบคุมหลอดไฟ

home1/living_room/light/on<br>home1/living_room/light/off<br>home1/living_room/light/status

✅ ควบคุมทีวี

home1/living_room/tv/on<br>home1/living_room/tv/off<br>home1/living_room/tv/volume_up<br>home1/living_room/tv/volume_down

✅ ควบคุมแอร์

home1/living_room/ac/on<br>home1/living_room/ac/off<br>home1/living_room/ac/temperature/set<br>home1/living_room/ac/temperature/status

ห้องครัว (kitchen)

✅ ควบคุมไฟในครัว

home1/kitchen/light/on<br>home1/kitchen/light/off<br>home1/kitchen/light/status

เครื่องดูดควัน

home1/kitchen/hood/on<br>home1/kitchen/hood/off<br>home1/kitchen/hood/speed/set

เซ็นเซอร์อุณหภูมิ

home1/kitchen/temperature/status

🏡 บ้านหลังที่ 2 (home2)

ห้องนอน (bedroom)

✅ ควบคุมไฟในห้องนอน

home2/bedroom/light/on<br>home2/bedroom/light/off<br>home2/bedroom/light/status

✅ ควบคุมแอร์

home2/bedroom/ac/on<br>home2/bedroom/ac/off<br>home2/bedroom/ac/temperature/set

🏡 บ้านหลังที่ 3 (home3)

สวน (garden)

✅ ควบคุมสปริงเกอร์รดน้ำ

home3/garden/sprinkler/on<br>home3/garden/sprinkler/off<br>home3/garden/sprinkler/status

✅ ตรวจสอบระดับความชื้นในดิน

home3/garden/soil_moisture/status

✅ ตรวจสอบอุณหภูมิภายนอก

home3/garden/temperature/status

📌 ตัวอย่างการใช้ MQTT Wildcards สำหรับสมัครรับข้อมูล

สมัครรับทุกข้อความของบ้านหลังที่ 1

bashCopyEdithome1/#

สมัครรับทุกข้อความของอุปกรณ์ในห้องนั่งเล่นของบ้านหลังที่ 1

home1/living_room/#<br>

สมัครรับข้อมูลสถานะของอุณหภูมิจากทุกบ้าน

home+/+/temperature/status<br>

สมัครรับทุกคำสั่งเปิด-ปิดของอุปกรณ์ในทุกบ้าน

home+/+/+/on<br>home+/+/+/off

🚀 สรุป

📌 ใช้โครงสร้างหัวข้อที่เป็นมาตรฐาน เพื่อให้จัดการง่ายและขยายระบบได้สะดวก
📌 ใช้ Wildcards (+ และ #) เพื่อสมัครรับข้อมูลอย่างมีประสิทธิภาพ
📌 ใช้ตัวพิมพ์เล็กทั้งหมดเพื่อป้องกันข้อผิดพลาดจาก Case Sensitivity

โครงสร้างนี้สามารถนำไปใช้ได้จริง และรองรับการเพิ่มอุปกรณ์ใหม่ได้ง่าย! 🔥🚀

Leave a Comment