ลงมือทำ: หน้าสถานะเครือข่ายของทีม
โมดูล 4 — เชื่อมต่อแพลตฟอร์ม IoT · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร
เติมช่องว่างหกจุดในไฟล์ฝึกจนได้หน้าสถานะเครือข่ายของทีมที่อัปเดตสด (ตารางวงเรียงแรงไปอ่อน SSID IP ไฟลิงก์ และ ping สองปลายทางทุก 3 วินาที) แล้วใช้มันวินิจฉัยได้ว่าลิงก์ขาดตรงไหน
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ:
- เติมช่องว่างหกจุดใน
s09_network_status.pyตามลำดับท่า 2 ถึง 5 จนตารางซ้ายขึ้นอย่างน้อย 3 วงเรียงจากแรงไปอ่อน ครบสี่คอลัมน์โดยไม่มีช่องไหนตัดบรรทัด และแผงขวาแสดง SSID ที่โปรแกรมส่งเข้าconnect()เอง เลข IP ที่ได้จาก DHCP และไฟสถานะลิงก์ติดถูกดวง - ทำให้บรรทัดเกตเวย์และอินเทอร์เน็ตแสดงเวลาเป็น ms และอัปเดตทุก 3 วินาทีต่อเนื่องอย่างน้อย 2 นาที ปุ่มสแกนใหม่ล้างตารางแล้วเทใหม่ ไม่เขียนทับซ้อน และแปลผล “เกตเวย์ผ่าน แต่อินเทอร์เน็ต timeout” ได้ว่าปัญหาอยู่ที่ไหน
- ใช้ตารางกับดักของบทเรียนหาสาเหตุของอาการได้อย่างน้อยสามอาการ รวมถึงอาการของ
ui.Tableที่ไม่มี error ให้จับ และตอบได้ด้วยปากเปล่าว่าทำไมผลwifi.scan()ต้องอ่านด้วยnet[1]ไม่ใช่net['rssi'] - รัน
09_link_gates_a_real_reading.pyบนบอร์ดจริง ตัดลิงก์ที่เราเตอร์แล้วต่อกลับ และอธิบายกติกา “วัดทุกรอบ เก็บใส่คิว ส่งทีละค่าเมื่อลิงก์กลับมา” จากเลขคิวที่เดินขึ้นและไหลออกบนจอ
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ต่อจากบทเรียน 4.2 ที่แกะห้าท่าของไฟล์นี้ไปแล้ว เปิด BENTO Playground บนบอร์ดค้างไว้ตลอดบทเรียน
แก้ WIFI_SSID กับ WIFI_PASS ที่หัวไฟล์เป็น WiFi บ้านหรือ Hotspot มือถือของคุณ วงนั้นต้องตั้งรหัสผ่านไว้ เพราะ connect() ต่อวงเปิดไม่ได้
และเช็กไว้ก่อนว่าเกตเวย์ของวงเป็นเลข .1 หรือไม่ ดูเลข gateway จริงได้จากโน้ตบุ๊กที่ต่อวงเดียวกัน (ipconfig บน Windows หรือ ip route บน Linux)
ระหว่างพิมพ์ จับเวลาและจดตัวเลขที่เห็นลงบันทึกการเรียน (ถ้าเรียนเป็นกลุ่ม สลับกันพิมพ์กับจด)
- อุปกรณ์: บอร์ด Eva Kit หรือ TESAIoT Dev Kit ที่ลงเฟิร์มแวร์ MicroPython ของ BENTO แล้ว หรือ BENTO Emulator ใน BENTO IDE (Emulator วาดหน้าจอของไฟล์ฝึกและตัวอย่างได้ครบ แต่ชื่อวง ค่า WiFi และสถานะลิงก์บนเครื่องโฮสต์เป็นค่าแทน ไม่ใช่ผลการวัดของบอร์ด การผ่าน MVP ที่ต้องได้ IP จาก DHCP จริงและ ping สดจึงต้องใช้บอร์ดจริง)
- เรียนมาก่อน: บทเรียน 4.2 — จอสถานะเครือข่าย: แกะโค้ดโมดูล wifi
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”ก่อนเติมอะไร กด Program to Device ไฟล์ฝึกได้เลย ไฟล์ตั้ง nets = [] และ ok = False ไว้ให้ จึงเห็นโครงหน้าจอครบ:
แถบหัวเรื่องพร้อมปุ่ม สแกนใหม่ ตารางว่างทางซ้าย ไฟลิงก์ ป้าย ping และมาตรวัด dBm ทางขวา แล้วจอจะขึ้น “ต่อไม่ติด”
ซึ่งเป็นหน้าตาเดียวกับตอนใส่รหัสผ่านผิดพอดี หน้าจอถูกวางไว้ให้ครบแล้ว งานของเราคือทำให้ข้อมูลจริงไหลเข้าไปในนั้น
MVP ของชุดบทเรียน 4.1–4.3 คือหน้าจอสถานะเครือข่ายของทีม (SSID, IP, ping ms) ที่อัปเดตสดบน HMI ต่อยอดจากแดชบอร์ดบทเรียน 3.7–3.9 และสิ่งที่วัดคือการวินิจฉัย ไม่ใช่ความยาวโค้ด
ลำดับห้าท่าคือลำดับการดีบัก แต่ละท่าพิสูจน์ท่าก่อนหน้า: 1 จอใช้ได้ · 2 วิทยุใช้ได้ (สแกนไม่ต้องใช้รหัสผ่าน เจอวงแปลว่าวิทยุทำงาน) ·
3 แปลข้อมูลถูก (บั๊ก tuple/dict โผล่ตรงนี้) · 4 มีที่อยู่แล้ว · 5 คุยกับคนอื่นได้ ถ้าท่า 3 พัง เรารู้แน่ว่าไม่เกี่ยวกับเครือข่าย
เพราะท่า 2 ผ่านไปแล้ว ไล่จากสิ่งที่พึ่งพาคนอื่นน้อยที่สุดไปหามากที่สุด ท่า 2 กับ 3 ถูกมัดเป็น rescan() ตัวเดียว
เพราะปุ่มบนจอต้องเรียกทั้งชุดซ้ำได้ นั่นคือความต่างระหว่างสคริปต์ที่รันครั้งเดียวกับหน้าจอที่คนใช้งานได้
ส่วน gateway_of() เดาเกตเวย์เป็น .1 เหมือนหน้าจอที่มากับเครื่อง แต่เราไม่หยุดแค่เดา เรายิง ping เพื่อพิสูจน์
ในเฉลยทุกการตัดสินใจมีเหตุผลที่วัดได้ ค่าที่แก้บ่อยอยู่บนสุด ตรรกะอยู่กลาง หน้าจออยู่ล่าง · ui.Table แทน Label
เรียงกันเพราะจัดคอลัมน์ให้เอง · ui.Led สองดวงแทนตัวอักษรเขียวแดงเพราะภาพขาวดำยังแยกไฟติดกับไฟหรี่ได้ (.value(0) คือหรี่
ไม่ใช่หาย) · ui.Bar วางทับ ui.Scale ให้ค่ากับพิสัยอยู่ด้วยกัน โดย ui.Scale เป็นไม้บรรทัดที่ไม่รับ .value() ·
เกณฑ์สี −60 / −75 หลวมกว่าเกณฑ์ห้าขีดของหน้าจอบอร์ดเพราะการ์ดมีสามระดับ และระดับปกติใช้สีฟ้า COL_RUN ไม่ใช่เขียว
เพราะสถานะปกติต้องเงียบ สีจัดสงวนไว้ให้เรื่องผิดปกติ · security == 0 เขียนเป็นคำ เปิด หรือ มีรหัส
ไม่ใช่ระบายสี · ssid[:12] ตัดชื่อโดยตั้งใจ และชื่อเต็มยังอยู่ที่ Console ทุกการตัดข้อมูลบนจอต้องรู้ตัวว่าตัดอะไร
ปิดวงจร: ลิงก์มีไว้พาของออกไป ไฟล์ 09 เอาค่าอุณหภูมิมาต่อท้ายลิงก์ วัดทุกรอบไม่ว่าเน็ตจะเป็นอย่างไร เก็บใส่คิวทุกครั้ง
และส่งเมื่อลิงก์กลับมาโดยปล่อยทีละค่า ถ้าเขียนว่า “วัดเมื่อเน็ตมา” ข้อมูลช่วงที่หลุดจะหายไปตลอดกาลโดยไม่มี error สักตัว
ส่วนไฟล์ 10 กับ 11 ตอบปัญหาที่เจอจริงเมื่อ 14 ส.ค. 2026 ว่ารหัสผ่าน WiFi ไม่ควรฝังอยู่ในโค้ด ให้พิมพ์บนจอด้วย
ui.Textarea กับ ui.Keyboard แทน
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”ต้องทำในบทเรียน (ราว 29 นาที ตามลำดับ) 01_scan_tuples.py (6 นาที) ดูผลของ scan() เป็น tuple สี่ช่องจริงก่อนเติมท่า 3 ·
03_connect_says_first.py (8 นาที) ก่อนรันให้ทายว่าป้าย “กำลังต่อ” ควรขึ้นก่อนหรือหลังจอนิ่ง แล้วรันดู ·
06_link_panel_hmi.py (15 นาที) การ์ด SSID · IP · ping ms ที่ทุกตัวเลขวัดมาจริง ไฟล์นี้ไม่มีแท่งความแรงสัญญาณโดยตั้งใจ
แท่งบนจอนั้นคือเวลา ping ยาวคือช้า เพราะ rssi ใน wifi.status() เป็น 0 เสมอ
ติดตรงไหน เปิดอันนั้น ต่อติดได้ IP แต่เปิดอะไรไม่ได้ ใช้ 04_ping_two_targets.py · เรียก status() หลายครั้งในรอบเดียว
แล้วได้ภาพที่ไม่เคยเกิดจริง ใช้ 05_status_dict.py (อ่านครั้งเดียวต่อรอบ) · ไม่รู้ว่าวงไหนอยู่ใกล้ที่สุด ใช้ 02_rank_by_rssi.py
ปิดวงจร 09_link_gates_a_real_reading.py บน Dev Kit อ่านอุณหภูมิห้องจริงจาก SHT40 ส่วนบน Eva Kit ลูกบิดเล่นบทแทน
(0–100 % = 15–45 °C) และ Console บอกตั้งแต่รอบแรกว่าค่ามาจากไหน ลองบนบอร์ดจริงเสมอ หัวไฟล์บันทึกไว้ว่าเคยผ่านบน Emulator
ที่ตอบทุกคีย์แต่พังบนบอร์ดจริง · 10_keyboard_types_the_password.py และ 11_two_fields_one_keyboard.py สร้าง Textarea ก่อน
Keyboard เสมอ เรียก kb.listen("ready", "cancel") ก่อนจึงจะได้เหตุการณ์ อ่านสิ่งที่พิมพ์ด้วย ta.text() ที่ไม่ใส่อาร์กิวเมนต์
ช่องรหัสผ่านแสดงดาวแต่ .text() คืนตัวจริง จึงห้ามพิมพ์มันลง Console
อ่านเสริมนอกเวลา: 03_reconnect_backoff.py ของบทเรียน 5.2 ตอบว่าลิงก์หลุดแล้วจะต่อใหม่อย่างไร เรื่องนี้อยู่นอกเกณฑ์ผ่านของชุดบทเรียนนี้
| ไฟล์ | ไฟล์นี้สอน |
|---|---|
| examples/01_scan_tuples.py | ผลของ wifi.scan() หน้าตาเป็นอย่างไร |
| examples/02_rank_by_rssi.py | เรียงวงจากแรงไปอ่อน แล้วแปลง dBm ให้คนอ่านออก |
| examples/03_connect_says_first.py | บอกก่อนแล้วค่อยรอ เพราะ connect() บล็อก |
| examples/04_ping_two_targets.py | เกตเวย์ตอบ แต่อินเทอร์เน็ตไม่ตอบ แปลว่าอะไร |
| examples/05_status_dict.py | อ่านสถานะครั้งเดียว แล้วใช้ค่าชุดนั้นทั้งรอบ |
| examples/06_link_panel_hmi.py | หน้าจอสถานะลิงก์ ที่ทุกตัวเลขบนจอวัดมาจริง |
| examples/09_link_gates_a_real_reading.py | ค่าจริงรออยู่ ลิงก์เป็นคนบอกว่าไปได้หรือยัง |
| examples/10_keyboard_types_the_password.py | รหัสผ่านควรพิมพ์บนจอ ไม่ใช่ฝังในโค้ด |
| examples/11_two_fields_one_keyboard.py | ฟอร์มสองช่อง แป้นพิมพ์เดียว และการอ่านค่ากลับ |
สไลด์ของบทเรียนนี้อ้างถึงไฟล์ที่อยู่ในบทเรียนอื่นด้วย:
- m02-ui-to-hardware/l06-touch-panel-lab/examples/09_scale_led_spinbox.py — สาม widget ที่แยกหน้าจอ HMI ออกจากหน้าจอเล่น ๆ
- m04-iot-connectivity/l02-network-status-code/examples/08_softap_fallback.py — ถ้าหาวงที่ตั้งไว้ไม่เจอ บอร์ดปล่อยวงของตัวเองได้
- m05-capstone/l02-capstone-starter/examples/03_reconnect_backoff.py — ต่อใหม่แบบถอยห่างขึ้นเรื่อย ๆ ไม่ใช่รัวติดกัน
ภาพจอจาก BENTO Emulator ของตัวอย่างในบทนี้ (คลิกชื่อไฟล์เพื่อเปิดโค้ด)

01_scan_tuples.py ผลของ wifi.scan() หน้าตาเป็นอย่างไร
02_rank_by_rssi.py เรียงวงจากแรงไปอ่อน แล้วแปลง dBm ให้คนอ่านออก
03_connect_says_first.py บอกก่อนแล้วค่อยรอ เพราะ connect() บล็อก
04_ping_two_targets.py เกตเวย์ตอบ แต่อินเทอร์เน็ตไม่ตอบ แปลว่าอะไร
05_status_dict.py อ่านสถานะครั้งเดียว แล้วใช้ค่าชุดนั้นทั้งรอบ
06_link_panel_hmi.py หน้าจอสถานะลิงก์ ที่ทุกตัวเลขบนจอวัดมาจริง
09_link_gates_a_real_reading.py ค่าจริงรออยู่ ลิงก์เป็นคนบอกว่าไปได้หรือยัง
10_keyboard_types_the_password.py รหัสผ่านควรพิมพ์บนจอ ไม่ใช่ฝังในโค้ด
11_two_fields_one_keyboard.py ฟอร์มสองช่อง แป้นพิมพ์เดียว และการอ่านค่ากลับฝึกเติม
หัวข้อที่มีชื่อว่า “ฝึกเติม”เปิด practice/s09_network_status.py ช่องว่างหกจุดมีคำใบ้ # เติม: กำกับทุกจุด จุดเดียวที่อยู่ระดับนอกสุดคือ wifi.connect()
ที่เหลือเยื้องอยู่ใน rescan() ในลูป หรือใน try ให้ดูการเยื้องเป็นตัวช่วยจำระดับ อย่าเติมครบหกจุดแล้วค่อยรันทีเดียว
เพราะการสแกนกับการต่อเน็ตพังคนละแบบ
- ท่า 2 และ 3 ใน
rescan():nets = wifi.scan()·nets.sort(key=lambda net: net[1], reverse=True)·ssid, rssi, security, channel = nets[i]เติมสามบรรทัดนี้ก่อนรัน เพราะบรรทัดtbl.add_row(ssid[:12], ...)ใช้ชื่อที่ท่า 3 แกะให้ ถ้าอยากเห็นจำนวนวงใน Console ให้เพิ่มprint("found", len(nets), "networks")แบบในเฉลย รันแล้วต้องเห็นสามแถวที่เลข dBm ไต่ลง - ท่า 4 (ระดับนอกสุด):
ok = wifi.connect(WIFI_SSID, WIFI_PASS)สังเกตว่าป้าย “กำลังต่อ 85 วิ” อยู่ก่อนบรรทัดนี้ รันแล้วไฟดวงบนติด ดวงล่างหรี่ และเลข IP ขึ้น ถ้าหน้าจอหายไปในราวสองวินาทีหลังจากนั้น ไม่ต้องตกใจ เป็นเพราะลูปยังไม่มีui.poll()ของท่า 5 - ท่า 5 ในลูป:
events = ui.poll()ต้นลูป และms_gw = wifi.ping(gw, PING_TIMEOUT_MS)ในtryรันแล้วบรรทัดเกตเวย์กับอินเทอร์เน็ตขึ้นเป็น ms และนับถอยหลัง “วัดใหม่ใน N วิ”
รู้ว่าเสร็จเมื่อผ่านรายการ MVP ในแล็บครบ ถ้าเกตเวย์ timeout ทั้งที่ IP ขึ้นปกติ แปลว่าวงนี้ไม่ได้ใช้ .1
ดูเลข gateway จริงได้จากโน้ตบุ๊กที่ต่อวงเดียวกัน (ipconfig บน Windows หรือ ip route บน Linux) แล้วแก้บรรทัด gw = ...
| ไฟล์ฝึก | เรื่อง |
|---|---|
| practice/s09_network_status.py | จอสถานะเครือข่ายของทีม (ฉบับฝึกเติมโค้ด) |
เปิดเฉลยหลังจากลองเองแล้วอย่างน้อยหนึ่งรอบ แล้วอ่าน วิธีใช้เฉลย ก่อน
| เฉลย | คู่กับ |
|---|---|
| solution/s09_network_status.py | practice/s09_network_status.py |
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ
-
เรียงห้าท่าของหน้าสถานะเครือข่ายตามสิ่งที่แต่ละท่าพิสูจน์ จากท่าแรกไปท่าสุดท้าย (เรียงลำดับ · เป้าหมายข้อ 1)
- ก) มีที่อยู่แล้ว (connect ได้ IP)
- ข) จอใช้ได้ (วาง widget ครบ)
- ค) คุยกับคนอื่นได้ (ping สองปลายทาง)
- ง) วิทยุใช้ได้ (scan เจอวง)
- จ) แปลข้อมูลถูก (แกะ tuple เรียงแรงไปอ่อน)
เฉลย
ข → ง → จ → ก → ค — แต่ละท่าพิสูจน์ท่าก่อนหน้า สแกนมาก่อนต่อเพราะไม่ต้องใช้รหัสผ่าน และแปลข้อมูลมาก่อนต่อเน็ตเพราะบั๊ก tuple/dict โผล่ตรงนั้น ถ้าท่า 3 พังจึงรู้แน่ว่าไม่เกี่ยวกับเครือข่าย
-
แผงขวาต้องแสดงชื่อวงที่บอร์ดต่ออยู่ ทำไมเฉลยจึงแสดงค่าจาก WIFI_SSID ไม่ใช่จาก wifi.status()[“ssid”] (เลือกหนึ่งข้อ · เป้าหมายข้อ 1)
- ก) เพราะ status() ช้าเกินไปสำหรับลูป 200 ms
- ข) เพราะช่อง ssid ของ status() คืนสตริงว่างเสมอ ทีมจึงต้องจำสตริงที่ตัวเองส่งเข้า connect()
- ค) เพราะ status() คืน tuple ไม่ใช่ dict
- ง) เพราะ status() ใช้ได้เฉพาะในโหมด softap
เฉลย
ข — ssid กับ rssi ใน status() เป็นค่าตายตัวในเฟิร์มแวร์ ได้ “” กับ 0 เสมอ บอร์ดตอบชื่อวงเองไม่ได้ ส่วนความแรงจริงต้องอ่านจาก wifi.scan()
-
หน้าจอของทีมแสดงเกตเวย์ 4 ms แต่อินเทอร์เน็ตไม่ตอบทุกครั้งตลอดสองนาที ทีมควรทำอย่างไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) แก้เลขเกตเวย์ในโค้ด เพราะ .1 น่าจะผิด
- ข) ไล่หาบั๊กใน rescan() เพราะตารางอาจเรียงผิด
- ค) จดผลลงบันทึกการเรียนแล้วทำงานต่อ เพราะปัญหาอยู่ที่ทางออกอินเทอร์เน็ตของวง ไม่ใช่บั๊กของเรา
- ง) เปลี่ยน NET_TEST_IP เป็น “google.com”
เฉลย
ค — เกตเวย์ตอบแปลว่าลิงก์ WiFi และเลขเกตเวย์ถูก ปัญหาอยู่หลังเราเตอร์ อาจเป็นทางออกของวงหรือถูกกรองไว้ ส่วน ping รับเฉพาะเลข IP ใส่ชื่อโฮสต์จะได้ ValueError
-
อาการใดต่อไปนี้ “ไม่มี error ให้จับ” มีแต่จอที่ดูผิด เลือกทุกข้อที่ถูก (เลือกได้หลายข้อ · เป้าหมายข้อ 3)
- ก) ข้อความยาวเกิน col_width แถวสูงสองเท่า แถวสุดท้ายตกขอบตาราง
- ข) ลืม tbl.clear_items() กดสแกนใหม่แล้วแถวเก่ายังค้าง
- ค) เขียน net[‘rssi’] กับผลของ wifi.scan()
- ง) เรียก bar_rssi.color() แล้วแท่งดูเต็มทั้งราง
- จ) เรียก wifi.ping(“google.com”)
เฉลย
ก, ข, ง — สามอาการของ ui.Table และ ui.Bar ไม่มี error ให้จับ ต้องตรวจด้วยตา ส่วน net[‘rssi’] ได้ TypeError เพราะผลสแกนเป็น tuple และ ping ด้วยชื่อโฮสต์ได้ ValueError
-
ในไฟล์ 09 ถ้าเปลี่ยนเป็น “วัดเฉพาะตอนที่เน็ตมา” จะเกิดอะไรขึ้นเมื่อลิงก์หลุดไปห้านาที (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) โปรแกรมโยน OSError แล้วหยุด
- ข) ค่าช่วงห้านาทีนั้นหายไปตลอดกาล โดยไม่มี error สักตัว ทั้งที่เซนเซอร์ยังทำงานปกติ
- ค) คิวจะเต็มแล้วบอร์ดรีเซ็ตตัวเอง
- ง) ไม่ต่างจากเดิม เพราะลิงก์กลับมาแล้วค่าจะถูกส่งย้อนหลังครบ
เฉลย
ข — วัดกับส่งต้องแยกขาดกัน วัดทุกรอบไม่ว่าเน็ตจะเป็นอย่างไร เก็บใส่คิว แล้วปล่อยทีละค่าเมื่อลิงก์กลับมา ค่าที่ไม่เคยถูกวัดไม่มีอะไรให้ส่งย้อนหลัง
MVP: หน้าจอสถานะเครือข่ายของทีม ทำบนบอร์ดจริง แล้วเก็บหลักฐานลงบันทึกการเรียน
- ตารางซ้ายขึ้นอย่างน้อย 3 วง เรียงจากแรงไปอ่อน ครบสี่คอลัมน์ และไม่มีช่องไหนตัดบรรทัด
- แผงขวาแสดง SSID ที่โปรแกรมส่งเข้า
connect()เอง และเลข IP ที่ได้จาก DHCP (ไม่ใช่ค่าที่พิมพ์ไว้ในโค้ด) - ไฟสถานะลิงก์ติดถูกดวง และมาตรวัด dBm ขยับตามวงของทีมจริง พร้อมพิสัย −90 ถึง −40 กำกับ
- กด สแกนใหม่ แล้วตารางถูกล้างและเทใหม่ ไม่ใช่เขียนทับซ้อนของเดิม
- บรรทัดเกตเวย์และอินเทอร์เน็ตแสดงเวลาเป็น ms และอัปเดตซ้ำทุก 3 วินาทีต่อเนื่องอย่างน้อย 2 นาที
- ทีมอธิบายได้ว่าถ้าเกตเวย์ผ่านแต่อินเทอร์เน็ต timeout แปลว่าปัญหาอยู่ที่ไหน (ตอบปากเปล่าได้)
- ทีมตอบได้ว่าทำไม
wifi.scan()ต้องอ่านด้วยnet[1]ไม่ใช่net['rssi'](ตอบปากเปล่าได้) - ถ่ายรูปหน้าจอตอนทำงานแนบในบันทึกการเรียน
เก็บโค้ดนี้ไว้ให้ดี บทเรียน 4.4–4.6 เพิ่ม mqtt ทับลงบนลิงก์ที่เพิ่งทำงาน บอร์ดจะเริ่มส่งข้อมูลออกไปจริงและรับคำสั่งกลับมาได้
ต่อยอด (เลือกหนึ่งข้อ ลงบันทึกการเรียน): แผนที่สัญญาณห้าจุดเทียบ FSPL · ping เกตเวย์ 100 ครั้งหา min/avg/max และเปอร์เซ็นต์ที่หาย ·
ลอง ping .1 .254 .100 เพื่อล่าเกตเวย์ตัวจริง · ปล่อยรันสิบนาทีแล้วนับครั้งที่ timeout
บทเรียนถัดไป: บทเรียน 4.4 — MQTT: pub/sub topic QoS และงบข้อมูล
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- ตัวเลขทุกตัวบนหน้าจอของทีมตอนนี้ บอกได้ไหมว่าวัดมาจากไหน ตัวไหนที่ยังเป็นการเดา
- ถ้าต้องติดเซนเซอร์ 200 ตัวในโรงงาน หน้าจอนี้ช่วยตัดสินใจอะไรก่อนติดตั้ง และต้องเพิ่มอะไรอีก
- ข้อมูลที่ตัดให้สั้นลงบนจอของทีม (เช่น ชื่อวง 12 ตัวอักษร) มีที่ให้ดูของเต็มหรือยัง
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
เรียงห้าท่าของหน้าสถานะเครือข่ายตามสิ่งที่แต่ละท่าพิสูจน์ จากท่าแรกไปท่าสุดท้าย (เป้าหมายข้อ 1)
- มีที่อยู่แล้ว (connect ได้ IP)
- จอใช้ได้ (วาง widget ครบ)
- คุยกับคนอื่นได้ (ping สองปลายทาง)
- วิทยุใช้ได้ (scan เจอวง)
- แปลข้อมูลถูก (แกะ tuple เรียงแรงไปอ่อน)
ดูเฉลย
ลำดับที่ถูก: B. จอใช้ได้ (วาง widget ครบ) → D. วิทยุใช้ได้ (scan เจอวง) → E. แปลข้อมูลถูก (แกะ tuple เรียงแรงไปอ่อน) → A. มีที่อยู่แล้ว (connect ได้ IP) → C. คุยกับคนอื่นได้ (ping สองปลายทาง)
แต่ละท่าพิสูจน์ท่าก่อนหน้า สแกนมาก่อนต่อเพราะไม่ต้องใช้รหัสผ่าน และแปลข้อมูลมาก่อนต่อเน็ตเพราะบั๊ก tuple/dict โผล่ตรงนั้น ถ้าท่า 3 พังจึงรู้แน่ว่าไม่เกี่ยวกับเครือข่าย
-
แผงขวาต้องแสดงชื่อวงที่บอร์ดต่ออยู่ ทำไมเฉลยจึงแสดงค่าจาก WIFI_SSID ไม่ใช่จาก wifi.status()["ssid"] (เป้าหมายข้อ 1)
- เพราะ status() ช้าเกินไปสำหรับลูป 200 ms
- เพราะช่อง ssid ของ status() คืนสตริงว่างเสมอ ทีมจึงต้องจำสตริงที่ตัวเองส่งเข้า connect()
- เพราะ status() คืน tuple ไม่ใช่ dict
- เพราะ status() ใช้ได้เฉพาะในโหมด softap
ดูเฉลย
คำตอบ: B. เพราะช่อง ssid ของ status() คืนสตริงว่างเสมอ ทีมจึงต้องจำสตริงที่ตัวเองส่งเข้า connect()
ssid กับ rssi ใน status() เป็นค่าตายตัวในเฟิร์มแวร์ ได้ "" กับ 0 เสมอ บอร์ดตอบชื่อวงเองไม่ได้ ส่วนความแรงจริงต้องอ่านจาก wifi.scan()
-
หน้าจอของทีมแสดงเกตเวย์ 4 ms แต่อินเทอร์เน็ตไม่ตอบทุกครั้งตลอดสองนาที ทีมควรทำอย่างไร (เป้าหมายข้อ 2)
- แก้เลขเกตเวย์ในโค้ด เพราะ .1 น่าจะผิด
- ไล่หาบั๊กใน rescan() เพราะตารางอาจเรียงผิด
- จดผลลงบันทึกการเรียนแล้วทำงานต่อ เพราะปัญหาอยู่ที่ทางออกอินเทอร์เน็ตของวง ไม่ใช่บั๊กของเรา
- เปลี่ยน NET_TEST_IP เป็น "google.com"
ดูเฉลย
คำตอบ: C. จดผลลงบันทึกการเรียนแล้วทำงานต่อ เพราะปัญหาอยู่ที่ทางออกอินเทอร์เน็ตของวง ไม่ใช่บั๊กของเรา
เกตเวย์ตอบแปลว่าลิงก์ WiFi และเลขเกตเวย์ถูก ปัญหาอยู่หลังเราเตอร์ อาจเป็นทางออกของวงหรือถูกกรองไว้ ส่วน ping รับเฉพาะเลข IP ใส่ชื่อโฮสต์จะได้ ValueError
-
อาการใดต่อไปนี้ "ไม่มี error ให้จับ" มีแต่จอที่ดูผิด เลือกทุกข้อที่ถูก (เป้าหมายข้อ 3)
- ข้อความยาวเกิน col_width แถวสูงสองเท่า แถวสุดท้ายตกขอบตาราง
- ลืม tbl.clear_items() กดสแกนใหม่แล้วแถวเก่ายังค้าง
- เขียน net['rssi'] กับผลของ wifi.scan()
- เรียก bar_rssi.color() แล้วแท่งดูเต็มทั้งราง
- เรียก wifi.ping("google.com")
ดูเฉลย
คำตอบ: A. ข้อความยาวเกิน col_width แถวสูงสองเท่า แถวสุดท้ายตกขอบตาราง · B. ลืม tbl.clear_items() กดสแกนใหม่แล้วแถวเก่ายังค้าง · D. เรียก bar_rssi.color() แล้วแท่งดูเต็มทั้งราง
สามอาการของ ui.Table และ ui.Bar ไม่มี error ให้จับ ต้องตรวจด้วยตา ส่วน net['rssi'] ได้ TypeError เพราะผลสแกนเป็น tuple และ ping ด้วยชื่อโฮสต์ได้ ValueError
-
ในไฟล์ 09 ถ้าเปลี่ยนเป็น "วัดเฉพาะตอนที่เน็ตมา" จะเกิดอะไรขึ้นเมื่อลิงก์หลุดไปห้านาที (เป้าหมายข้อ 4)
- โปรแกรมโยน OSError แล้วหยุด
- ค่าช่วงห้านาทีนั้นหายไปตลอดกาล โดยไม่มี error สักตัว ทั้งที่เซนเซอร์ยังทำงานปกติ
- คิวจะเต็มแล้วบอร์ดรีเซ็ตตัวเอง
- ไม่ต่างจากเดิม เพราะลิงก์กลับมาแล้วค่าจะถูกส่งย้อนหลังครบ
ดูเฉลย
คำตอบ: B. ค่าช่วงห้านาทีนั้นหายไปตลอดกาล โดยไม่มี error สักตัว ทั้งที่เซนเซอร์ยังทำงานปกติ
วัดกับส่งต้องแยกขาดกัน วัดทุกรอบไม่ว่าเน็ตจะเป็นอย่างไร เก็บใส่คิว แล้วปล่อยทีละค่าเมื่อลิงก์กลับมา ค่าที่ไม่เคยถูกวัดไม่มีอะไรให้ส่งย้อนหลัง
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"ลงมือทำ: หน้าสถานะเครือข่ายของทีม" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "Hands-on: your team's network status page" 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/l03-network-status-lab/
บทเรียนนี้ดัดแปลงจากต้นฉบับด้านล่าง เมื่ออ้างอิงให้คงเครดิตต้นฉบับไว้ด้วย
https://github.com/Advance-Innovation-Centre-AIC/embedded-systems-for-aiot-developer/blob/a80bbe88a34bcb9bb8d991f42f9252b77cdab079/session-09.html (slides 29–49)
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA