9.4. การเปิดใช้งานลิงก์¶
เลเยอร์ลิงก์ที่กล่าวถึงในหน้าก่อนหน้านั้นส่วนใหญ่เป็นอัตโนมัติ แต่มีจุดหนึ่งที่ Python script ต้องเข้ามาดำเนินการ: บอกกล้องว่าจะเข้าร่วมเครือข่ายใด จนกว่าขั้นตอนนั้นจะสำเร็จ ฟีเจอร์เครือข่ายทั้งหมดที่ส่วนที่เหลือของบทนี้ครอบคลุมจะไม่ทำงาน
9.4.1. โมดูล network¶
โมดูล network เปิดเผย hardware ระบบเครือข่ายของกล้องให้ Python ใช้งานได้ ชุด interface ที่แน่นอนขึ้นอยู่กับบอร์ด: กล้องหลายตัวมีชิปไร้สายและเปิดเผยคลาส WLAN (ตั้งชื่อตาม Wireless Local Area Network); บางบอร์ดยังมีพอร์ต Ethernet ในตัวและเปิดเผยคลาส LAN (ตั้งชื่อตาม Local Area Network คือเวอร์ชันที่ใช้สาย) รูปแบบการใช้งานเหมือนกันทั้งคู่ โดยมีความแตกต่างสำคัญหนึ่งประการ: wireless interface ต้องบอกว่าจะเข้าร่วมเครือข่ายใด ในขณะที่ Ethernet รับอะไรก็ตามที่อยู่บนสาย
9.4.2. ขั้นตอน Wi-Fi¶
การเข้าร่วม Wi-Fi มีสามขั้นตอน: สร้าง interface เปิดใช้งาน แล้วขอให้เชื่อมต่อกับเครือข่ายที่ระบุชื่อพร้อม password interface จะเจรจากับ access point ในพื้นหลัง การเรียก isconnected() จะรายงานเมื่อลิงก์เชื่อมต่อสำเร็จ:
import network
import time
wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
wlan.connect("my-network", "my-password")
while not wlan.isconnected():
time.sleep_ms(100)
print("link up")
อาร์กิวเมนต์ IF_STA เลือกโหมด station -- กล้องเข้าร่วมเครือข่ายที่คนอื่นเป็นผู้โฮสต์ โหมดตรงข้าม IF_AP ทำให้กล้องโฮสต์เครือข่ายขนาดเล็กของตัวเองที่อุปกรณ์อื่นสามารถเข้าร่วมได้ ซึ่งมีประโยชน์สำหรับ interface การกำหนดค่าและการตั้งค่าในพื้นที่ แต่ไม่ใช่กรณีทั่วไป
เมื่อ isconnected() คืนค่า True กล้องจะอยู่บนเครือข่าย ทุกสิ่งที่เลเยอร์ที่สูงกว่าต้องการเพื่อตั้งค่าตัวเองเกิดขึ้นโดยอัตโนมัติขณะที่ลิงก์กำลังเชื่อมต่อ หน้าต่อไปจะอธิบายส่วนเหล่านั้นทีละส่วน
9.4.3. สิ่งที่อาจผิดพลาด¶
รูปแบบความล้มเหลวในทางปฏิบัติบางประการปรากฏขึ้นในขั้นตอนนี้
ชื่อเครือข่ายหรือ password ผิด การพยายามเชื่อมต่อจะลองใหม่อย่างเงียบๆ จนกว่าแอปพลิเคชันจะหยุด ห่อการรอด้วย timeout เพื่อไม่ให้ loop ข้างต้นบล็อกตลอดไป:
start = time.ticks_ms() while not wlan.isconnected(): if time.ticks_diff(time.ticks_ms(), start) > 10000: raise OSError("Wi-Fi did not come up in 10 s") time.sleep_ms(100)
อยู่นอกระยะสัญญาณ กล้องและ access point ต้องอยู่ใกล้พอที่สัญญาณแรงพอที่จะรักษาลิงก์ไว้ได้
status()คืนค่า code ที่บ่งบอกว่าทำไมลิงก์ไม่ขึ้นscan()คืนรายการเครือข่ายที่วิทยุสามารถเห็นได้ ซึ่งเป็นการวินิจฉัยที่ควรเรียกเมื่อconnectไม่สำเร็จAccess point ต้องการมากกว่า password เครือข่ายเปิด (ไม่มี password) และเครือข่ายที่ป้องกันด้วย password ทั่วไปรองรับโดย
connectตามที่แสดงข้างต้น เครือข่ายขนาดใหญ่ในที่ทำงานและโรงเรียนบางครั้งใช้รูปแบบที่แตกต่างออกไปซึ่งกล้องต้องพิสูจน์ตัวตนกับ login server แยกต่างหาก ซึ่งต้องการอาร์กิวเมนต์เพิ่มเติมสำหรับconnectดู คลาส WLAN -- ควบคุมอินเทอร์เฟซ WiFi ในตัว สำหรับ surface ที่สมบูรณ์
9.4.4. การรักษาการเชื่อมต่อ¶
การเปิดใช้งานลิงก์เป็นครึ่งหนึ่งของปัญหา การรักษาการเชื่อมต่อเป็นอีกครึ่งหนึ่ง -- access point รีบูต กล้องเคลื่อนออกนอกระยะสัญญาณ DHCP lease หมดอายุ radio firmware อาจค้างบางครั้ง กล้องที่จะอยู่บนเครือข่ายเป็นเวลาหลายเดือนต้องตรวจจับสิ่งเหล่านั้นและกู้คืนด้วยตัวเอง
รูปแบบการตรวจจับคือการเรียก isconnected() ในแต่ละรอบของ main loop และตอบสนองเมื่อคืนค่า False isconnected() อาจให้ข้อมูลที่ไม่ถูกต้องช่วงสั้นๆ เมื่อการเชื่อมต่อหลุดแต่วิทยุยังไม่ได้สังเกตเห็น -- การส่ง socket ที่ล้มเหลวเมื่อลิงก์ "ควร" จะขึ้นอยู่เป็นหลักฐานอีกชิ้นหนึ่งของการหลุดของแอปพลิเคชัน status() เป็นแหล่งที่มีอำนาจมากกว่าเมื่อทั้งสองไม่ตรงกัน
รูปแบบการเชื่อมต่อใหม่คือ disconnect() ตามด้วย connect() ด้วย credentials เดิม โดยมี timeout ห่อการรอเช่นเดียวกับการเชื่อมต่อเริ่มต้น ถอยหลังระหว่างการพยายาม -- หนึ่งวินาที สอง สี่ เพิ่มสองเท่าจนถึงประมาณหนึ่งนาที -- เพื่อไม่ให้การหยุดทำงานนานโจมตี AP และไม่เผาผลาญงบประมาณพลังงานของวิทยุกับ spin loop:
import network
import time
_BACKOFF_S = (1, 2, 4, 8, 16, 32, 60)
def reconnect(wlan, ssid, password):
for delay in _BACKOFF_S:
wlan.disconnect()
wlan.connect(ssid, password)
deadline = time.ticks_add(time.ticks_ms(), 10_000)
while not wlan.isconnected():
if time.ticks_diff(deadline, time.ticks_ms()) < 0:
break
time.sleep_ms(100)
if wlan.isconnected():
return True
time.sleep(delay)
return False
เมื่อ helper นั้นคืนค่า False ต่อเนื่อง radio firmware อาจค้างเอง ทางเลือกสุดท้ายคือการปิดและเปิด radio ใหม่: active(False) หยุดสั้นๆ active(True) แล้วเชื่อมต่อใหม่ตั้งแต่ต้น วิธีนี้นำ radio firmware กลับสู่สถานะที่รู้จักโดยแลกกับเวลาหยุดทำงานพิเศษสักไม่กี่วินาที:
def radio_power_cycle(wlan, ssid, password):
wlan.active(False)
time.sleep(1)
wlan.active(True)
return reconnect(wlan, ssid, password)
กล้องที่ออฟไลน์มาหลายนาทีถือเป็นความล้มเหลวจริงที่แอปพลิเคชันต้องรับรู้ โค้ดกู้คืนควรแสดงสถานะนั้น -- ทำเครื่องหมายเครือข่ายว่าไม่แข็งแรงใน flag ที่ main loop ตรวจสอบ และให้แอปพลิเคชันข้ามการส่งเครือข่ายที่ควรทำในขณะที่ flag ยังชัดเจน -- เพื่อไม่ให้การหยุดทำงานนานหยุดแอปพลิเคชันที่รอ socket ที่จะไม่มีวันเขียน
9.4.5. Ethernet เมื่อมี¶
บอร์ดที่มี Ethernet ในตัวเปิดเผยรูปแบบเดียวกันโดยไม่มีขั้นตอน connect อินเทอร์เฟซ LAN จะถูกเปิดใช้งานด้วย active() และทันทีที่เสียบสายอินเทอร์เฟซก็พร้อมใช้งาน:
import network
lan = network.LAN()
lan.active(True)
print("link up")
หลังจากจุดนี้ หน้าที่เหลือของส่วนนี้จะใช้ได้เหมือนกันไม่ว่า interface ใดจะนำกล้องเข้าสู่เครือข่าย เลเยอร์ที่สูงกว่าไม่สนใจว่าลิงก์ด้านล่างจะเป็น Wi-Fi หรือ Ethernet -- "connected" ก็คือ "connected"
สำหรับ reference แบบสมบูรณ์ของ WLAN และ LAN รวมถึง configuration knob ที่ไม่ได้ใส่ไว้ที่นี่ ดูที่ network --- การกำหนดค่าเครือข่าย