ภาพพื้นหลังปกบทเรียน

บทเรียน 4.4 — MQTT: pub/sub topic QoS และงบข้อมูล

Telemetry ขาออก และ Command ขากลับ บน broker ของเราเอง

โมดูล 4 — เชื่อมต่อแพลตฟอร์ม IoT

คาถาประจำบทเรียน: ส่งข้อมูลออกไปได้ ยังไม่พอ — ต้องรับคำสั่งกลับมาได้ด้วย ถึงจะเรียกว่าระบบ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ดูของจริงก่อน — บอร์ดคุยกับคอมพิวเตอร์คนละเครื่อง

บอร์ดของเรา อ่านเซนเซอร์ แล้ว publish LED ที่ถูกสั่ง Broker พอร์ต 1883 ตัวกลางเพียงตัวเดียว ไม่เก็บ ไม่ตัดสิน แค่ส่งต่อ MQTT Explorer บนคอมของเรา เห็นทุกข้อความ และพิมพ์คำสั่งกลับได้ PUBLISH — ค่าเซนเซอร์ JSON ทุก 5 วินาที คำสั่ง toggle LED — เดินสวนทางกลับมาที่บอร์ด

บทเรียน 4.1–4.3 บอร์ดของเราต่อเน็ตได้แล้ว รู้ IP ของตัวเอง และ ping ออกไปข้างนอกได้ แต่ยังไม่มีใครที่ปลายทาง

วันนี้เราจะเพิ่มปลายทางให้มัน — คอมพิวเตอร์อีกเครื่องที่อยู่คนละมุมห้อง ที่เห็นค่าจากบอร์ดเรา และสั่งงานกลับมาได้ โดยที่ทั้งสองเครื่องไม่เคยรู้จักที่อยู่ของกันและกันเลย

วันนี้บอร์ดเลิกเป็นเครื่องมือวัดที่อยู่ตัวคนเดียว แล้วกลายเป็นสมาชิกของระบบ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ทำไม · คืออะไร · ทำยังไง — แผนที่ของชุดบทเรียนนี้

คำถาม คำตอบของชุดบทเรียนนี้ อยู่ช่วงไหน
Why บทเรียน 4.1–4.3 บอร์ดมี IP และ ping ออกไปได้แล้ว ทำไมยังไม่พอ เพราะ ping พิสูจน์ได้แค่ว่าสายดี ยังไม่มีใครที่ปลายทางรับข้อมูลของเรา · และของที่ส่งออกได้อย่างเดียวยังไม่เรียกว่าระบบ ระบบต้องรับคำสั่งกลับมาได้ด้วย · ชื่อ topic กับรูปร่าง payload คือ สัญญากับทุกคนที่จะใช้ข้อมูลนี้ต่อ เปลี่ยนทีหลังแปลว่าพังทุกฝั่งพร้อมกัน ครึ่งแรก · pub/sub · topic และ payload
What มีอะไรให้ใช้บ้าง โมดูล mqtt มีหกชื่อ เท่านี้จริง ๆ — และเพดานสี่ข้อที่ต้องจำคู่กันไป: ช่องรับ 1 ข้อความ · payload 255 ไบต์ · topic 127 ไบต์ · client_id 31 ตัวอักษร สไลด์บัญชีหกชื่อ + สไลด์ get_message() ช่องเดียว
How ประกอบยังไงให้ใช้งานได้จริง ต่อ WiFi → ต่อ broker → publish() ค่าจริงทุก 5 วินาที โดยที่ลูปเดียวกันยังฟัง get_message() อยู่ แล้วเอาคำสั่งที่รับมาสั่ง LED บนบอร์ด แปดไฟล์ตัวอย่าง + ไฟล์ฝึก + ติดตั้ง CE ด้วย Docker

ปลายทางที่จับต้องได้ — MQTT Explorer บนคอมเห็นค่าจากบอร์ดทุก 5 วินาที และเราพิมพ์คำสั่งจากคอมกลับไปให้ LED บนบอร์ดสลับสถานะได้

บทเรียน 4.1–4.3 เราพิสูจน์ว่าสายดี · ชุดบทเรียนนี้เราหาคนที่ปลายสายเจอ และคุยกันได้สองทาง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เป้าหมายของชุดบทเรียนนี้

  1. อธิบายได้ว่า publish/subscribe ต่างจาก client–server ตรงไหน และทำไม IoT ถึงเลือกแบบแรก
  2. ออกแบบ topic ของทีม และ JSON payload ที่ขนาดพอเหมาะ พร้อมเหตุผลของทุกฟิลด์
  3. ใช้ mqtt.connect() / publish() / subscribe() / get_message() ได้ถูกต้องตามข้อจำกัดจริงของเฟิร์มแวร์
  4. ติดตั้ง TESAIoT Community Edition ด้วย Docker แล้วทำให้ข้อมูลของทีมขึ้นกราฟบนแพลตฟอร์มของตัวเอง

ปลายทางของวันนี้: MQTT Explorer เห็นค่าจากบอร์ดทุก 5 วินาที และเราพิมพ์คำสั่งจากคอมให้ LED บนบอร์ดสลับสถานะได้

ชุดบทเรียนนี้เป็นบทเรียนแรกที่ข้อมูลของเรา ออกจากบอร์ด ไปอยู่ในมือของโปรแกรมอื่น

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ปลายทางของชุดบทเรียนนี้ — บอร์ดรายงานตัวขึ้น broker

หน้าจอจาก BENTO Emulator ของ 03_connect_and_publish.py ที่ต่อ broker แล้วส่งข้อความ

หน้าจอจากการรัน 03_connect_and_publish.py บน BENTO Emulator ที่ 800x480 เท่าจอของทั้งสองบอร์ด — ไม่ใช่ภาพวาด ไม่ใช่ mock-up และไม่ใช่ภาพถ่ายจากบอร์ด · หน้าจอของไฟล์เฉลย (ไฟสี่ดวง · ลูกบิด · สามใบล่าสุด · ปุ่มเริ่ม/หยุดส่ง) ยังไม่ได้ถ่าย
  • การ์ดบนคือ บันไดสามขั้นก่อนส่งได้ — 1) WiFi ได้ IP · 2) broker ต่อแล้ว · 3) publish กำลังส่ง — ขั้นที่ผ่านแล้วต้องเห็นด้วยตา
  • การ์ดล่างนับใบที่ส่งไปแล้ว พร้อมแถบความคืบหน้าของ 10 ใบ — ส่งทุก 2 วินาที ดูเลขเดินขึ้น
  • ผลลัพธ์จริงของชุดบทเรียนนี้ไปโผล่ที่ เครื่องอื่น — จอนี้บอกได้แค่ว่าบอร์ด "สั่งส่ง" แล้ว

ถ้าจอบอกว่าส่งแล้ว แต่ฝั่งรับไม่เห็นอะไร แปลว่ายังไม่จบ — ชุดบทเรียนนี้ต้องดูสองจอพร้อมกัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ทบทวนบทเรียน 4.1–4.3 — เราหยุดไว้ตรงไหน

wifi.scan() รู้ว่ามีใครอยู่แถวนี้ wifi.connect() เข้าเครือข่ายได้ wifi.ip() มีที่อยู่เป็นของตัวเอง wifi.ping() ออกไปข้างนอกถึง วันนี้ mqtt.publish() mqtt.subscribe() บทเรียน 4.1–4.3 ต่อท่อได้ · บทเรียน 4.4–4.6 เริ่มมีของไหลในท่อ ping พิสูจน์แค่ว่า "เส้นทางถึง" — ไม่ได้แปลว่ามีโปรแกรมไหนรอรับข้อมูลของเราอยู่

สองอย่างจากชุดบทเรียนก่อนหน้าที่ต้องเอามาใช้วันนี้ทั้งคู่ — wifi.connect() บล็อกได้นานถึงราว 85 วินาทีถ้ารหัสผิด จึงต้องต่อ WiFi ให้ได้ก่อนเสมอแล้วค่อยเริ่มเรื่อง MQTT และ wifi.ping() รับเฉพาะหมายเลข IP ไม่รับชื่อโฮสต์ — เดี๋ยวเราจะใช้มันตรวจว่าเครื่องที่รัน broker อยู่ในระยะที่คุยได้จริงก่อนจะเสียเวลาต่อ

ถ้า wifi.is_connected() เป็น False อย่าเพิ่งไปหาสาเหตุที่ MQTT — ปัญหายังไม่เดินทางมาถึงชั้นนั้น

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

client–server กับ pub/sub ต่างกันตรงไหน

แผนภาพลำดับแบบ client–server: เบราว์เซอร์ถามแล้วเซิร์ฟเวอร์ตอบทีละคำขอ แผนภาพ publish/subscribe ที่ผู้ส่งกับผู้รับแยกจากกันด้วย topic

ซ้าย — ภาพ: Michel Bakni / Wikimedia Commons — CC BY-SA 4.0 · ขวา — ภาพ: Mathieu.clabaut / Wikimedia Commons — CC BY-SA 4.0

ซ้าย คือแบบที่เราคุ้น (client–server) เว็บเบราว์เซอร์ต้องรู้ชื่อเซิร์ฟเวอร์ ต้องถามก่อนถึงจะได้คำตอบ ผู้ถามกับผู้ตอบ ผูกกันตรง ๆ ถ้าอีกฝั่งย้ายที่อยู่ ทุกฝั่งต้องแก้ตาม

ขวา คือ publish/subscribe ผู้เขียน (writer) โยนข้อมูลใส่ ชื่อเรื่อง ผู้อ่าน (reader) ขอรับตาม ชื่อเรื่อง — ทั้งสองฝั่งไม่เคยรู้จักกัน รู้จักแค่ชื่อเรื่องเดียวกัน

ผลที่ตามมาสามข้อ ซึ่งเป็นเหตุผลที่ IoT เลือกแบบหลัง

  1. บอร์ดไม่ต้องมี IP ที่คนอื่นเข้าถึงได้ — บอร์ดเป็นฝ่ายวิ่งออกไปหา broker เอง จึงอยู่หลัง NAT หรือหลังไฟร์วอลล์ได้
  2. เพิ่มผู้รับได้โดยไม่แตะโค้ดบนบอร์ด — พรุ่งนี้อยากให้แดชบอร์ดตัวที่สองดูข้อมูลเดียวกัน แค่ subscribe เพิ่ม
  3. ผู้รับล่มไม่ทำให้ผู้ส่งล่ม — บอร์ดยิงเข้า broker เหมือนเดิม ไม่มีใครค้างรอใคร

คำที่ต้องจำ: pub/sub แยกผู้ส่งออกจากผู้รับ ทั้งในเชิงพื้นที่และเชิงเวลา

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

broker อยู่ตรงกลาง — และมีคำสั่งอยู่แค่ไม่กี่คำ

แผนภาพ MQTT publish: อุปกรณ์ส่งข้อความเข้า broker แล้ว broker ส่งต่อให้ผู้ที่ subscribe

ภาพ: Brivadeneira / Wikimedia Commons — CC BY-SA 4.0

CONNECT เข้าไปแนะนำตัว → SUBSCRIBE ขอรับ topic ที่สนใจ → PUBLISH ส่งข้อมูล → DISCONNECT บอกลา
สี่คำนี้คือทั้งหมดที่ผู้เรียนต้องใช้วันนี้ ที่เหลือ broker จัดการให้เอง

อะไรคือ MQTT ? — code maow maow | โค้ดแมวแมว · 8 นาที 26 วินาที · ไทย — ดูเพื่อเห็นภาพรวมของ broker/publisher/subscriber เป็นภาษาไทยก่อนลงมือ

broker ไม่ใช่ฐานข้อมูล มันคือ ที่ทำการไปรษณีย์ — รับเข้ามาแล้วส่งต่อทันที ไม่เก็บไว้ให้ (เว้นแต่สั่งให้เก็บ)

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

topic คือที่อยู่ — และมันเป็นต้นไม้ ไม่ใช่ชื่อแบน ๆ

แผนภาพ broker ตัวเดียวกับผู้ฟังหลายราย ที่ subscribe topic เป็นลำดับชั้นและใช้ wildcard

ภาพ: Ademant / Wikimedia Commons — CC BY-SA 4.0 — ในภาพมีทั้งลำดับชั้น topic และ wildcard ทั้งสองแบบ

ในภาพ ปลั๊กสองตัวส่ง /plug1/voltage, /plug2/current ส่วนแล็ปท็อป subscribe /plug1/# และมือถือ subscribe /+/current
# = ทุกอย่างที่อยู่ใต้ลงไปกี่ชั้นก็ได้ (ต้องเป็นตัวสุดท้าย) · + = แทนที่ หนึ่งชั้นพอดี

MQTT Essentials Part 6 — Topic Best Practices — HiveMQ · 5 นาที 50 วินาที · อังกฤษ — ดูเพื่อเข้าใจว่าทำไม topic ที่ออกแบบดีทำให้ระบบขยายได้โดยไม่ต้องแก้โค้ดฝั่งอุปกรณ์

topic ไม่ต้องประกาศล่วงหน้า — พิมพ์ publish ไปที่ชื่อไหน ชื่อนั้นก็เกิดขึ้นเดี๋ยวนั้น จึงต้องมีวินัยตั้งชื่อเอง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เข้าใจฮาร์ดแวร์ · MQTT วิ่งอยู่ตรงไหนบนบอร์ด

CM33_NS — คอร์ที่รัน MicroPython โค้ด Python ของเรา ลูป publish/poll งานเครือข่าย TCP บัฟเฟอร์ 2048 ไบต์ ไดรเวอร์ WiFi — วิทยุตัวเดียวของทั้งบอร์ด MPY heap 64 KB CM55 — คอร์ที่วาดจอและอ่านเซนเซอร์ อ่าน CapSense / pot ให้เรา · BMI270 ด้วยบน Eva วาดผลบนจอผ่าน LVGL ไม่แตะเครือข่ายเลยแม้แต่นิดเดียว ค่าเซนเซอร์เดินข้ามมาทาง IPC ก่อนจะถูก publish ข้อความขาเข้าถูกวางในช่องรับโดยงานเครือข่าย ไม่ว่าโค้ด Python ของเราจะอยู่บรรทัดไหนก็ตาม โมดูล mqtt ต่อได้เฉพาะพอร์ตข้อความเปล่า — ทั้ง Eva และ Dev Kit นี่คือเหตุผลที่ชุดบทเรียนนี้เป็นพอร์ต 1883 ล้วน ยังไม่ใช่ 8883/8884 — TLS อยู่ชุดบทเรียนถัดไปในโมดูล tesaiot

ทั้ง WiFi และ MQTT ทำงานอยู่บน CM33_NS คอร์เดียวกับที่รันโค้ด Python ของเรา ส่วน CM55 ที่วาดจอกับอ่านเซนเซอร์ไม่แตะเครือข่ายเลย — ทั้งสองบอร์ดจงใจอย่างนั้น เพราะสองคอร์แย่งอุปกรณ์ตัวเดียวกันเคยทำให้เครื่องล้มมาแล้ว · ภาพนี้จริงทั้ง Eva Kit และ Dev Kit เพราะโค้ด Wi-Fi/MQTT เป็นชุดเดียวกัน ต่างกันแค่ใครอ่าน IMU (Eva: คอร์จออ่านให้ · Dev Kit: CM33 อ่านเองจาก I2C) · เหตุผลที่ชุดบทเรียนนี้ใช้ 1883 ไม่ใช่เรื่องหน่วยความจำ แต่เพราะโมดูล mqtt ส่งข้อมูลรับรอง TLS เป็นค่าว่างเสมอ (ดูตารางหกชื่อ) จึงต่อได้เฉพาะพอร์ตข้อความเปล่าบนบอร์ดไหนก็ตาม

ข้อที่ต้องจำให้แม่น: งานเครือข่ายวางข้อความขาเข้าลงช่องรับ "เมื่อไรก็ได้" ไม่ได้รอให้โค้ดเราเรียก get_message() ก่อน — สไลด์ถัดไปทั้งสไลด์มาจากข้อเท็จจริงข้อนี้

เครือข่ายกับหน้าจออยู่คนละคอร์ — ถ้าจอค้าง MQTT อาจยังวิ่งอยู่ และในทางกลับกันด้วย

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เกร็ด: หัวข้อความสองไบต์ กับมาตรฐานที่ใช้เวลาสิบห้าปี

โครงสร้างแพ็กเก็ต MQTT PUBLISH ตั้งแต่หัวข้อความสองไบต์จนถึง payload

ภาพ: Blacktron / Wikimedia Commons — CC BY-SA 4.0 — โครงสร้างแพ็กเก็ต PUBLISH

ดูแถวบนสุดของภาพ: 16 บิต = 2 ไบต์ นั่นคือส่วนหัวคงที่ของ MQTT ทั้งหมด — ชนิดแพ็กเก็ต, ธง DUP, ระดับ QoS, ธง RETAIN และความยาว อัดอยู่ในสองไบต์นั้น

เทียบกับ HTTP ที่ส่วนหัวเป็นข้อความยาวหลายร้อยไบต์ต่อคำขอหนึ่งครั้ง ("GET /… HTTP/1.1", "Host:", "User-Agent:", …) ความต่างนี้ไม่ใช่เรื่องความสวยงาม แต่คือ ค่าไฟกับค่าเน็ตของอุปกรณ์ที่ต้องส่งข้อมูลทุกห้าวินาที เป็นปี

มาตรฐานเองก็ไม่ได้เกิดในวันเดียว: MQTT 3.1.1 ถูกอนุมัติเป็นมาตรฐาน OASIS เมื่อ 2014-10-29 และ 5.0 เมื่อ 2019-03-07 เวอร์ชันที่อุปกรณ์ฝังตัวใช้กันแพร่หลายที่สุดจนถึงวันนี้ยังเป็น 3.1.1

เชื่อมกับวันนี้: payload ของเราจะยาวราว 80 ไบต์ ส่วนหัว MQTT กินเพิ่มแค่หลักหน่วยไบต์ — ถ้าเราเลือก HTTP แทน ข้อมูลจริงจะกลายเป็นส่วนน้อยของสิ่งที่ส่งออกไป และแบตเตอรี่จะหมดไปกับการส่ง "ชื่อหัวข้อ" ของข้อมูล ไม่ใช่ตัวข้อมูล

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

กลไกหลักของชุดบทเรียน — get_message() มีช่องรับเพียงช่องเดียว

สถานการณ์: สองข้อความมาถึงติด ๆ กัน ก่อนที่เราจะเรียก get_message() ข้อความ A {"cmd":"on"} ข้อความ B {"cmd":"off"} ช่องรับ 1 ช่อง ≤ 255 ไบต์ เขียนทับเสมอ B ทับ A เงียบ ๆ ไม่มี error ไม่มีธงบอก get_message() ได้ B อย่างเดียว A หายไปโดยไม่มีใครรู้ ทางแก้ที่ใช้ได้จริง: poll ให้ถี่กว่าคนพิมพ์คำสั่ง — sleep_ms(100) ในลูป ไม่ใช่ sleep(5) เหมาะกับคำสั่งจังหวะคนกด · ไม่เหมาะกับสตรีมข้อมูลที่ไหลตลอด

นี่คือข้อจำกัดที่เราต้อง สอน ไม่ใช่ซ่อน เพราะมันไม่ส่งเสียงเวลาเกิด

ค่า เพดานจริง เกินแล้วเป็นอย่างไร
ช่องรับข้อความ 1 ข้อความ ข้อความใหม่ทับของเก่าทันที ไม่มีสัญญาณเตือน
payload ขาเข้า 255 ไบต์ ถูกตัดเงียบ ๆ — JSON ที่ถูกตัดจะ parse ไม่ผ่าน
topic ขาเข้า 127 ไบต์ ถูกตัดเงียบ
client_id / username / password 31 ตัวอักษร ถูกตัดเงียบ → แพลตฟอร์มหาอุปกรณ์ไม่เจอ → ปฏิเสธการเชื่อมต่อ

ความล้มเหลวที่แย่ที่สุดสำหรับผู้เรียนคือความล้มเหลวที่เงียบ — จำสี่แถวนี้ไว้ แล้วจะประหยัดเวลาดีบักไปทั้งบทเรียน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

QoS 0/1/2 — ราคาของคำว่า "แน่ใจ"

ผู้ส่ง broker QoS 0 — ส่งแล้วแล้วกัน PUBLISH ครั้งเดียว · เน็ตหลุด = หายไปเลย · ถูกที่สุด QoS 1 — อย่างน้อยหนึ่งครั้ง PUBLISH + PUBACK · ถ้า ack หาย จะส่งซ้ำ — ผู้รับอาจได้ซ้ำ QoS 2 — ครั้งเดียวเป๊ะ สี่ขั้นตอนไป-กลับ · ช้าและกินหน่วยความจำที่สุด

mqtt.publish(topic, payload, qos) และ mqtt.subscribe(topic, qos) รับ qos เป็น อาร์กิวเมนต์ตำแหน่ง ไม่ใช่คีย์เวิร์ด
ชุดบทเรียนนี้ใช้ QoS 0 สำหรับ telemetry ทุก 5 วินาที (ค่าถัดไปมาใน 5 วิอยู่แล้ว หายหนึ่งใบไม่เสียหาย) และควรใช้ QoS 1 สำหรับคำสั่ง เพราะคำสั่งที่หายคือคำสั่งที่ผู้ใช้กดแล้วไม่เกิดอะไรขึ้น

MQTT Essentials Part 7 — QoS — HiveMQ · 5 นาที 41 วินาที · อังกฤษ — ดูเพื่อเห็นลำดับแพ็กเก็ตของ QoS 1 และ 2 แบบเต็ม

เลือก QoS จากคำถามเดียว: "ถ้าข้อความนี้หายไปหนึ่งใบ ใครเดือดร้อน"

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

งบข้อมูลต่อรอบ — ทำไมเป็น 5 วินาที ไม่ใช่ 100 มิลลิวินาที

งบขาออก — payload ของเราเทียบกับเพดานที่ปลอดภัย 1000 ไบต์ 80 ไบต์ — เหลือที่ว่างอีกมาก เพิ่มฟิลด์ได้สบาย งบขาเข้า — คำสั่งของเราเทียบกับเพดานแข็ง 255 ไบต์ 26 ไบต์ — เกิน 255 เมื่อไร ถูกตัดกลางคันเงียบ ๆ แล้ว JSON พัง ส่งถี่ขึ้นสองเท่า ข้อมูลโตสองเท่า — บนเครือข่ายมือถือหรือแบตเตอรี่ นี่คือค่าใช้จ่ายจริง

ปริมาณข้อมูล≈ขนาด payloadTpublish80 B5 s=16 B/spayload ขาเข้า≤255 B\text{ปริมาณข้อมูล} \approx \frac{\text{ขนาด payload}}{T_{\text{publish}}} \qquad \frac{80\ \text{B}}{5\ \text{s}} = 16\ \text{B/s} \qquad \text{payload ขาเข้า} \le 255\ \text{B}

ตัวเลข 5 วินาทีไม่ได้มาจากความรู้สึก แต่มาจากคำถามว่า ค่าที่เราวัดเปลี่ยนเร็วแค่ไหน อุณหภูมิห้องเปลี่ยนช้ามาก ส่งทุก 5 วินาทีก็ละเอียดเกินพอ ส่วนความสั่นของมอเตอร์เปลี่ยนใน 10 มิลลิวินาที — ค่าแบบนั้นไม่ควรส่งดิบ ๆ ขึ้น MQTT แต่ควรให้บอร์ดสรุปก่อน (ค่าสูงสุด ค่า RMS หรือจำนวนครั้งที่เกินเกณฑ์ในช่วงนั้น) แล้วค่อยส่ง

"ส่งให้ถี่ที่สุดเท่าที่ทำได้" เป็นการออกแบบที่แย่เสมอ — ถามก่อนว่าใครจะใช้ค่านี้ทำอะไร

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ออกแบบ topic และ payload ของทีม

แบบที่ 1 — broker สาธารณะ : กันชนด้วยรหัสไม่ซ้ำ bento/ team03/telemetry team03/cmd/led publish ทุก 5 วิ subscribe รอคำสั่ง แบบที่ 2 — TESAIoT CE : แพลตฟอร์มล็อกรูปแบบให้ device/team03/telemetry device/team03/commands ช่องที่สองต้องเท่ากับ device_id เป๊ะ ไม่งั้น ACL ปฏิเสธ payload: ส่งแค่ก้อน data ก็พอ — บริดจ์เติม device_id และ timestamp ให้เอง {"ax": 0.12, "ay": -9.75, "az": 0.31, "pot": 48.2} ค่าซ้อนกัน {"accel":{"x":1}} ถูกแบนเป็น accel_x เฉพาะค่าตัวเลขเท่านั้นที่กลายเป็นเส้นกราฟ

กติกาการตั้งชื่อ topic ที่ใช้ได้ทั้งชีวิตการทำงาน: เรียงจากกว้างไปแคบ (bento/team03/telemetry ไม่ใช่ telemetry/team03/bento) · ห้ามขึ้นต้นด้วย / เพราะจะได้ช่องว่างเปล่าเป็นชั้นแรก · ห้ามใส่ช่องว่างหรือภาษาไทย · และ อย่าใส่ค่าที่เปลี่ยนบ่อยลงในชื่อ topic (เช่น .../temp/25.4) เพราะผู้รับจะ subscribe ไม่ถูก · บน broker สาธารณะ ใช้รหัสของตัวเองที่ไม่ซ้ำใครแทน team03 เช่นชื่อเล่นต่อด้วยเลขสุ่ม 4 หลัก (nok4821)

สตริงที่เป็นข้อความ เช่น {"status":"ok"} ส่งขึ้นไปได้และเก็บได้ แต่ จะไม่กลายเป็นเส้นกราฟ เพราะกราฟต้องการตัวเลข ถ้าอยากให้เห็นบนกราฟ ให้แปลงเป็นตัวเลขก่อน เช่น {"ok": 1}

ชื่อ topic กับรูปร่าง payload คือ สัญญาระหว่างทีมเรากับทุกคนที่จะใช้ข้อมูลนี้ต่อ เปลี่ยนทีหลังแปลว่าพังทุกฝั่งพร้อมกัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

หน่วยความจำ: บน Eva TLS ต้องการราว 8.8 KB ขณะที่ตอนจับมือมีที่ว่างจริงราว 7 KB ส่วนบน Dev Kit heap ของ MicroPython ถูกย้ายไปอยู่ใน SOCMEM จึงไม่บีบเท่ากัน — แต่นั่นไม่ใช่เหตุผลที่ชุดบทเรียนนี้ใช้ 1883