MQTT: pub/sub topic QoS และงบข้อมูล
โมดูล 4 — เชื่อมต่อแพลตฟอร์ม IoT · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร
เข้าใจว่าทำไม IoT เลือก publish/subscribe ผ่าน broker แล้วออกแบบ topic, payload, QoS และงบข้อมูลต่อรอบของทีม โดยรู้เพดานเงียบสี่ข้อของโมดูล mqtt บนบอร์ดก่อนเขียนโค้ดบรรทัดแรก
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ:
- อธิบายความต่างของ client–server กับ publish/subscribe ได้ และบอกผลที่ตามมาสามข้อที่ทำให้ IoT เลือกแบบหลัง (บอร์ดไม่ต้องมี IP ที่คนอื่นเข้าถึงได้ · เพิ่มผู้รับได้โดยไม่แตะโค้ดบนบอร์ด · ผู้รับล่มไม่ทำให้ผู้ส่งล่ม)
- ออกแบบ topic ของทีมได้ทั้งสองแบบ (
bento/<รหัสของคุณ>/telemetryบน broker สาธารณะ และdevice/<device_id>/telemetryบน TESAIoT CE ที่ช่องที่สองต้องเท่ากับ device_id) ตามกติกาตั้งชื่อสี่ข้อ และบอกได้ว่า subscription ที่มี+หรือ#รับ topic ใดบ้าง - เลือก QoS ของแต่ละ topic ด้วยคำถาม “ถ้าข้อความนี้หายไปหนึ่งใบ ใครเดือดร้อน” และคำนวณงบข้อมูลต่อรอบได้ เช่น payload 80 ไบต์ทุก 5 วินาทีคือ 16 B/s พร้อมเขียน JSON ที่ทุกค่าที่ต้องขึ้นกราฟเป็นตัวเลข
- บอกเพดานเงียบสี่ข้อของโมดูล mqtt บนบอร์ดได้ครบ (ช่องรับ 1 ข้อความ · payload ขาเข้า 255 ไบต์ · topic 127 ไบต์ · client_id / username / password 31 ตัวอักษร) พร้อมอาการเมื่อเกิน และอธิบายว่าทำไมลูปต้องฟังคำสั่งทุก 100 ms ไม่ใช่ทุก 5 วินาที
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ทบทวนสองเรื่องจากบทเรียน 4.1–4.3: wifi.connect() บล็อกได้ราว 85 วินาทีถ้ารหัสผิด จึงต้องต่อ WiFi ให้ได้ก่อนเริ่มเรื่อง MQTT
และ wifi.ping() รับเฉพาะเลข IP ซึ่งเราจะใช้ตรวจว่าเครื่องที่รัน broker คุยได้จริง ถ้า wifi.is_connected() เป็น False
อย่าเพิ่งไปหาสาเหตุที่ MQTT บทเรียนนี้ยังไม่ต้องเขียนโค้ด เตรียมบันทึกการเรียนไว้ออกแบบ topic และ payload ของทีม
- อุปกรณ์: บอร์ด Eva Kit หรือ TESAIoT Dev Kit ที่ลงเฟิร์มแวร์ MicroPython ของ BENTO แล้ว หรือ BENTO Emulator ใน BENTO IDE (บทเรียนนี้ยังไม่มีโค้ดให้รัน ภาพหน้าจอในสไลด์มาจากการรันไฟล์
03_connect_and_publish.pyของบทเรียน 4.5 บน Emulator ซึ่งบอกได้แค่ว่าบอร์ด “สั่งส่ง” แล้ว ผลจริงต้องดูที่เครื่องฝั่งรับ) - เรียนมาก่อน: บทเรียน 4.3 — ลงมือทำ: หน้าสถานะเครือข่ายของทีม
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”ดูภาพแรกของสไลด์: บอร์ดอ่านเซนเซอร์แล้ว publish ค่า JSON ทุก 5 วินาทีเข้า broker ที่พอร์ต 1883 ซึ่งเป็นตัวกลางเพียงตัวเดียว ไม่เก็บ ไม่ตัดสิน แค่ส่งต่อ ส่วน MQTT Explorer บนคอมเห็นทุกข้อความและพิมพ์คำสั่ง toggle LED เดินสวนกลับมาที่บอร์ดได้ โดยที่สองเครื่องไม่เคยรู้ที่อยู่ของกันเลย ภาพหน้าจอจาก Emulator ถัดมาแสดงบันไดสามขั้นก่อนส่งได้ (WiFi ได้ IP · broker ต่อแล้ว · publish กำลังส่ง) ถ้าจอบอกว่าส่งแล้วแต่ฝั่งรับไม่เห็นอะไร แปลว่ายังไม่จบ ชุดบทเรียนนี้ต้องดูสองจอพร้อมกัน
ping พิสูจน์ได้แค่ว่าสายดี ยังไม่มีใครที่ปลายทาง และของที่ส่งออกได้อย่างเดียวยังไม่เรียกว่าระบบ ต้องรับคำสั่งกลับมาได้ด้วย
แบบ client–server ที่เราคุ้น ผู้ถามต้องรู้ชื่อผู้ตอบและถามก่อนถึงได้คำตอบ ทั้งสองฝั่งผูกกันตรง ๆ ส่วน publish/subscribe
ผู้ส่งโยนข้อมูลใส่ topic ผู้รับขอรับตาม topic ทั้งสองฝั่งรู้จักแค่ topic เดียวกัน pub/sub จึงแยกผู้ส่งออกจากผู้รับทั้งเชิงพื้นที่
และเชิงเวลา ผลคือบอร์ดวิ่งออกไปหา broker เองจึงอยู่หลัง NAT ได้ เพิ่มผู้รับได้โดยไม่แตะโค้ดบนบอร์ด และผู้รับล่มไม่ทำให้ผู้ส่งล่ม
broker ไม่ใช่ฐานข้อมูล มันคือที่ทำการไปรษณีย์ที่รับแล้วส่งต่อทันที คำสั่งที่เราใช้มีแค่ CONNECT SUBSCRIBE PUBLISH DISCONNECT
topic เป็นต้นไม้ ไม่ใช่ชื่อแบน ๆ + แทนหนึ่งชั้นพอดี ส่วน # แทนทุกอย่างที่อยู่ใต้ลงไปกี่ชั้นก็ได้และต้องเป็นตัวสุดท้าย
ในภาพของสไลด์ แล็ปท็อปที่ subscribe /plug1/# ได้ทุกค่าของปลั๊กตัวที่หนึ่ง มือถือที่ subscribe /+/current ได้กระแสของทุกปลั๊ก
topic ไม่ต้องประกาศล่วงหน้า publish ไปชื่อไหนชื่อนั้นก็เกิด จึงต้องมีวินัยเอง: เรียงจากกว้างไปแคบ ห้ามขึ้นต้นด้วย /
ห้ามใส่ช่องว่างหรือภาษาไทย และอย่าใส่ค่าที่เปลี่ยนบ่อยลงในชื่อ topic บน broker สาธารณะเรากันชนด้วยรหัสที่ไม่ซ้ำใคร เช่น
bento/team03/telemetry กับ bento/team03/cmd/led (ของจริงให้ใช้รหัสของตัวเองแทน team03
เช่นชื่อเล่นภาษาอังกฤษตัวเล็กต่อด้วยเลขสุ่ม 4 หลักอย่าง nok4821 เพราะผู้เรียนคนอื่นก็ใช้ broker เดียวกัน) ส่วนบน TESAIoT CE แพลตฟอร์มล็อกรูปแบบเป็น device/team03/telemetry
กับ device/team03/commands ช่องที่สองต้องเท่ากับ device_id เป๊ะ ไม่งั้น ACL ปฏิเสธ payload ส่งแค่ก้อนข้อมูล เพราะบริดจ์เติม
device_id และ timestamp ให้เอง ค่าซ้อน {"accel":{"x":1}} ถูกแบนเป็น accel_x และเฉพาะค่าตัวเลขเท่านั้นที่กลายเป็นเส้นกราฟ
{"status":"ok"} เก็บได้แต่ไม่ขึ้นกราฟ ต้องแปลงเป็น {"ok": 1} ชื่อ topic กับรูปร่าง payload คือสัญญากับทุกคนที่ใช้ข้อมูลนี้ต่อ
บนบอร์ด WiFi และ MQTT อยู่บน CM33_NS คอร์เดียวกับโค้ด Python ส่วน CM55 ที่วาดจอและอ่านเซนเซอร์ไม่แตะเครือข่ายเลย
ภาพนี้จริงทั้ง Eva Kit และ Dev Kit โมดูล mqtt ส่งข้อมูลรับรอง TLS เป็นค่าว่างเสมอ จึงต่อได้เฉพาะพอร์ตข้อความเปล่า 1883
ส่วน TLS อยู่ในบทเรียน 4.7–4.9 ข้อที่ต้องจำให้แม่นคืองานเครือข่ายวางข้อความขาเข้าลงช่องรับ “เมื่อไรก็ได้” ไม่รอให้เราเรียก
get_message() และช่องรับมีช่องเดียว สองข้อความที่มาติดกันก่อนเราเรียก ข้อความหลังทับข้อความแรกเงียบ ๆ ไม่มี error ไม่มีธงบอก
เพดานเงียบอีกสามข้อ: payload ขาเข้าเกิน 255 ไบต์ถูกตัดจน JSON parse ไม่ผ่าน · topic ขาเข้าเกิน 127 ไบต์ถูกตัด ·
client_id username password เกิน 31 ตัวอักษรถูกตัด แพลตฟอร์มหาอุปกรณ์ไม่เจอแล้วปฏิเสธการเชื่อมต่อ ทางแก้ที่ใช้ได้จริงคือ
poll ให้ถี่กว่าคนพิมพ์คำสั่ง sleep_ms(100) ในลูป ไม่ใช่ sleep(5) ซึ่งเหมาะกับคำสั่งจังหวะคนกด ไม่เหมาะกับสตรีมที่ไหลตลอด
QoS คือราคาของคำว่าแน่ใจ QoS 0 ส่งครั้งเดียว เน็ตหลุดก็หาย ถูกที่สุด · QoS 1 ส่งอย่างน้อยหนึ่งครั้งด้วย PUBACK ถ้า ack หาย
จะส่งซ้ำ ผู้รับจึงอาจได้ซ้ำ · QoS 2 ครั้งเดียวเป๊ะด้วยสี่ขั้นไป-กลับ ช้าและกินหน่วยความจำที่สุด mqtt.publish(topic, payload, qos)
และ mqtt.subscribe(topic, qos) รับ qos เป็นอาร์กิวเมนต์ตำแหน่ง telemetry ทุก 5 วินาทีใช้ QoS 0 เพราะค่าถัดไปมาอยู่แล้ว
ส่วนคำสั่งควรใช้ QoS 1 เพราะคำสั่งที่หายคือคำสั่งที่ผู้ใช้กดแล้วไม่เกิดอะไรขึ้น
งบข้อมูลต่อรอบ $\frac{80\ \text{B}}{5\ \text{s}} = 16\ \text{B/s}$ payload ขาออกราว 80 ไบต์ยังห่างเพดานที่ปลอดภัย 1000 ไบต์มาก ส่วนคำสั่งขาเข้าราว 26 ไบต์ต้องไม่เกินเพดานแข็ง 255 ไบต์ ส่วนหัวคงที่ของ MQTT มีแค่ 2 ไบต์ ขณะที่ HTTP มีหัวเป็นข้อความหลายร้อยไบต์ ต่อคำขอ ซึ่งคือค่าไฟกับค่าเน็ตของอุปกรณ์ที่ส่งทุกห้าวินาทีเป็นปี (MQTT 3.1.1 เป็นมาตรฐาน OASIS เมื่อ 2014-10-29 และ 5.0 เมื่อ 2019-03-07 อุปกรณ์ฝังตัวส่วนใหญ่ยังใช้ 3.1.1) รอบการส่งเลือกจากว่าค่าที่วัดเปลี่ยนเร็วแค่ไหน อุณหภูมิห้องส่งทุก 5 วินาทีก็เกินพอ ส่วนความสั่นของมอเตอร์ควรให้บอร์ดสรุปก่อน (ค่าสูงสุด RMS หรือจำนวนครั้งที่เกินเกณฑ์) “ส่งให้ถี่ที่สุด” เป็นการออกแบบที่แย่เสมอ
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”สไลด์ของบทเรียนนี้อ้างถึงไฟล์ที่อยู่ในบทเรียนอื่นด้วย:
- m04-iot-connectivity/l05-mqtt-platform/examples/03_connect_and_publish.py — ต่อ broker แล้วส่งค่าขึ้นไปหนึ่งชุด
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ
-
ข้อใดเป็นเหตุผลที่ IoT เลือก publish/subscribe แทน client–server เลือกทุกข้อที่ถูก (เลือกได้หลายข้อ · เป้าหมายข้อ 1)
- ก) บอร์ดไม่ต้องมี IP ที่คนอื่นเข้าถึงได้ เพราะบอร์ดวิ่งออกไปหา broker เอง จึงอยู่หลัง NAT ได้
- ข) เพิ่มผู้รับรายใหม่ได้ด้วยการ subscribe เพิ่ม โดยไม่แตะโค้ดบนบอร์ด
- ค) broker เก็บทุกข้อความไว้เป็นฐานข้อมูลให้ค้นย้อนหลังได้เสมอ
- ง) ผู้รับล่มไม่ทำให้ผู้ส่งล่ม เพราะไม่มีใครค้างรอใคร
เฉลย
ก, ข, ง — pub/sub แยกผู้ส่งออกจากผู้รับทั้งเชิงพื้นที่และเชิงเวลา ส่วน broker ไม่ใช่ฐานข้อมูล มันคือที่ทำการไปรษณีย์ ที่รับแล้วส่งต่อทันที ไม่เก็บไว้ให้เว้นแต่สั่งให้เก็บ
-
ทีมหนึ่ง publish ไปที่ bento/team03/telemetry และ bento/team03/cmd/led subscription ใดรับได้ทั้งสอง topic (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) bento/+/telemetry
- ข) bento/team03/#
- ค) bento/team03/+
- ง) #/team03
เฉลย
ข — # แทนทุกชั้นที่อยู่ใต้ลงไปกี่ชั้นก็ได้ จึงครอบทั้ง telemetry และ cmd/led ส่วน + แทนหนึ่งชั้นพอดี bento/team03/+ จึงไม่ถึง cmd/led ที่ลึกสองชั้น และ # ต้องเป็นตัวสุดท้ายเสมอ
-
อุปกรณ์ขึ้นทะเบียนบน TESAIoT CE ด้วย device_id ว่า team03 topic ใดที่แพลตฟอร์มยอมให้ publish telemetry (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) /device/team03/telemetry
- ข) telemetry/team03/device
- ค) device/team03/telemetry
- ง) device/ทีม03/telemetry
เฉลย
ค — CE ล็อกรูปแบบเป็น device/<device_id>/telemetry และช่องที่สองต้องเท่ากับ device_id เป๊ะ ไม่งั้น ACL ปฏิเสธ ส่วนการขึ้นต้นด้วย / หรือใส่ภาษาไทยผิดกติกาตั้งชื่อ
-
ทีมส่ง telemetry ทุก 5 วินาที และรับคำสั่งเปิดปิด LED จากผู้ใช้ ควรเลือก QoS อย่างไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)
- ก) QoS 2 ทั้งคู่ เพราะแน่ใจที่สุด
- ข) telemetry QoS 0 และคำสั่ง QoS 1
- ค) telemetry QoS 1 และคำสั่ง QoS 0
- ง) QoS 0 ทั้งคู่ เพราะถูกที่สุด
เฉลย
ข — telemetry หายหนึ่งใบไม่เสียหายเพราะค่าถัดไปมาใน 5 วินาทีอยู่แล้ว แต่คำสั่งที่หายคือคำสั่งที่ผู้ใช้กดแล้วไม่เกิดอะไรขึ้น QoS 2 ช้าและกินหน่วยความจำที่สุด จึงไม่ใช่ค่าตั้งต้นที่ดี
-
ผู้ใช้กด on แล้ว off ติดกันเร็ว ๆ ขณะที่โค้ดบนบอร์ด sleep(5) อยู่ก่อนเรียก get_message() จะเกิดอะไรขึ้น (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) บอร์ดได้ทั้งสองคำสั่งตามลำดับ เพราะ broker ต่อคิวไว้ให้
- ข) บอร์ดได้แค่ off ส่วน on หายไปเงียบ ๆ เพราะช่องรับมีช่องเดียวและข้อความใหม่เขียนทับ
- ค) get_message() โยน error ว่าช่องรับเต็ม
- ง) บอร์ดได้แค่ on เพราะข้อความแรกจองช่องไว้แล้ว
เฉลย
ข — งานเครือข่ายวางข้อความลงช่องรับเมื่อไรก็ได้ และช่องรับมีหนึ่งช่องที่เขียนทับเสมอ ไม่มี error ไม่มีธงบอก ทางแก้คือ poll ให้ถี่กว่าคนพิมพ์คำสั่ง เช่น sleep_ms(100) ในลูป
ออกแบบสัญญาข้อมูลของทีม (ราว 15 นาที) บนกระดาษหรือในบันทึกการเรียน ยังไม่ต้องเขียนโค้ด
- วาดภาพบอร์ด · broker · MQTT Explorer พร้อมลูกศรทิศของ telemetry ขาออกและคำสั่งขากลับ
- เขียน topic ของทีมทั้งสองแบบ (broker สาธารณะที่กันชนด้วยรหัสที่ไม่ซ้ำใคร และ TESAIoT CE ที่ช่องที่สองคือ device_id) แล้วตรวจกับกติกาตั้งชื่อสี่ข้อ
- เขียน subscription หนึ่งบรรทัดที่รับทุก topic ของทีม และอีกบรรทัดที่รับ telemetry ของทุกทีม ด้วย
#หรือ+ - เขียน JSON payload ที่มีค่าเซนเซอร์เป็นตัวเลขอย่างน้อยสามฟิลด์ นับไบต์ แล้วคำนวณ B/s ที่รอบละ 5 วินาที เทียบกับถ้าส่งทุก 100 ms
- เขียน payload ของคำสั่งที่ไม่เกิน 255 ไบต์ และตั้ง client_id ที่ไม่เกิน 31 ตัวอักษร
- เลือก QoS ของแต่ละ topic พร้อมคำตอบของคำถาม “ถ้าหายไปหนึ่งใบ ใครเดือดร้อน”
บทเรียน 4.5 แกะโมดูล mqtt ทั้งหกชื่อ ติดตั้ง TESAIoT Community Edition ด้วย Docker และส่ง telemetry กับรับคำสั่งจริงจากบอร์ด
บทเรียนถัดไป: บทเรียน 4.5 — MQTT กับแพลตฟอร์มที่ติดตั้งเอง: telemetry และ command
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- ถ้าพรุ่งนี้มีแดชบอร์ดตัวที่สองอยากดูข้อมูลของทีม ต้องแก้อะไรบนบอร์ดบ้าง และคำตอบนี้บอกอะไรเรื่อง pub/sub
- ค่าที่ทีมจะส่งเปลี่ยนเร็วแค่ไหน รอบการส่งที่เลือกมาจากคำถามนั้นหรือจากความรู้สึก
- ความล้มเหลวแบบเงียบข้อไหนในสี่ข้อที่คุณคิดว่าจะเจอก่อน และจะรู้ตัวได้อย่างไร
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
ข้อใดเป็นเหตุผลที่ IoT เลือก publish/subscribe แทน client–server เลือกทุกข้อที่ถูก (เป้าหมายข้อ 1)
- บอร์ดไม่ต้องมี IP ที่คนอื่นเข้าถึงได้ เพราะบอร์ดวิ่งออกไปหา broker เอง จึงอยู่หลัง NAT ได้
- เพิ่มผู้รับรายใหม่ได้ด้วยการ subscribe เพิ่ม โดยไม่แตะโค้ดบนบอร์ด
- broker เก็บทุกข้อความไว้เป็นฐานข้อมูลให้ค้นย้อนหลังได้เสมอ
- ผู้รับล่มไม่ทำให้ผู้ส่งล่ม เพราะไม่มีใครค้างรอใคร
ดูเฉลย
คำตอบ: A. บอร์ดไม่ต้องมี IP ที่คนอื่นเข้าถึงได้ เพราะบอร์ดวิ่งออกไปหา broker เอง จึงอยู่หลัง NAT ได้ · B. เพิ่มผู้รับรายใหม่ได้ด้วยการ subscribe เพิ่ม โดยไม่แตะโค้ดบนบอร์ด · D. ผู้รับล่มไม่ทำให้ผู้ส่งล่ม เพราะไม่มีใครค้างรอใคร
pub/sub แยกผู้ส่งออกจากผู้รับทั้งเชิงพื้นที่และเชิงเวลา ส่วน broker ไม่ใช่ฐานข้อมูล มันคือที่ทำการไปรษณีย์ ที่รับแล้วส่งต่อทันที ไม่เก็บไว้ให้เว้นแต่สั่งให้เก็บ
-
ทีมหนึ่ง publish ไปที่ bento/team03/telemetry และ bento/team03/cmd/led subscription ใดรับได้ทั้งสอง topic (เป้าหมายข้อ 2)
- bento/+/telemetry
- bento/team03/#
- bento/team03/+
- #/team03
ดูเฉลย
คำตอบ: B. bento/team03/#
# แทนทุกชั้นที่อยู่ใต้ลงไปกี่ชั้นก็ได้ จึงครอบทั้ง telemetry และ cmd/led ส่วน + แทนหนึ่งชั้นพอดี bento/team03/+ จึงไม่ถึง cmd/led ที่ลึกสองชั้น และ # ต้องเป็นตัวสุดท้ายเสมอ
-
อุปกรณ์ขึ้นทะเบียนบน TESAIoT CE ด้วย device_id ว่า team03 topic ใดที่แพลตฟอร์มยอมให้ publish telemetry (เป้าหมายข้อ 2)
- /device/team03/telemetry
- telemetry/team03/device
- device/team03/telemetry
- device/ทีม03/telemetry
ดูเฉลย
คำตอบ: C. device/team03/telemetry
CE ล็อกรูปแบบเป็น device/<device_id>/telemetry และช่องที่สองต้องเท่ากับ device_id เป๊ะ ไม่งั้น ACL ปฏิเสธ ส่วนการขึ้นต้นด้วย / หรือใส่ภาษาไทยผิดกติกาตั้งชื่อ
-
ทีมส่ง telemetry ทุก 5 วินาที และรับคำสั่งเปิดปิด LED จากผู้ใช้ ควรเลือก QoS อย่างไร (เป้าหมายข้อ 3)
- QoS 2 ทั้งคู่ เพราะแน่ใจที่สุด
- telemetry QoS 0 และคำสั่ง QoS 1
- telemetry QoS 1 และคำสั่ง QoS 0
- QoS 0 ทั้งคู่ เพราะถูกที่สุด
ดูเฉลย
คำตอบ: B. telemetry QoS 0 และคำสั่ง QoS 1
telemetry หายหนึ่งใบไม่เสียหายเพราะค่าถัดไปมาใน 5 วินาทีอยู่แล้ว แต่คำสั่งที่หายคือคำสั่งที่ผู้ใช้กดแล้วไม่เกิดอะไรขึ้น QoS 2 ช้าและกินหน่วยความจำที่สุด จึงไม่ใช่ค่าตั้งต้นที่ดี
-
ผู้ใช้กด on แล้ว off ติดกันเร็ว ๆ ขณะที่โค้ดบนบอร์ด sleep(5) อยู่ก่อนเรียก get_message() จะเกิดอะไรขึ้น (เป้าหมายข้อ 4)
- บอร์ดได้ทั้งสองคำสั่งตามลำดับ เพราะ broker ต่อคิวไว้ให้
- บอร์ดได้แค่ off ส่วน on หายไปเงียบ ๆ เพราะช่องรับมีช่องเดียวและข้อความใหม่เขียนทับ
- get_message() โยน error ว่าช่องรับเต็ม
- บอร์ดได้แค่ on เพราะข้อความแรกจองช่องไว้แล้ว
ดูเฉลย
คำตอบ: B. บอร์ดได้แค่ off ส่วน on หายไปเงียบ ๆ เพราะช่องรับมีช่องเดียวและข้อความใหม่เขียนทับ
งานเครือข่ายวางข้อความลงช่องรับเมื่อไรก็ได้ และช่องรับมีหนึ่งช่องที่เขียนทับเสมอ ไม่มี error ไม่มีธงบอก ทางแก้คือ poll ให้ถี่กว่าคนพิมพ์คำสั่ง เช่น sleep_ms(100) ในลูป
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"MQTT: pub/sub topic QoS และงบข้อมูล" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "MQTT: pub/sub, topics, QoS and the data budget" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/aiot-micropython/m04-iot-connectivity/l04-mqtt-concepts/
บทเรียนนี้ดัดแปลงจากต้นฉบับด้านล่าง เมื่ออ้างอิงให้คงเครดิตต้นฉบับไว้ด้วย
https://github.com/Advance-Innovation-Centre-AIC/embedded-systems-for-aiot-developer/blob/a80bbe88a34bcb9bb8d991f42f9252b77cdab079/session-10.html (slides 1–15)
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA