9.4. הקמת הקישור¶
שכבת הקישור שכוסתה בדף הקודם היא בעיקר אוטומטית, אך יש מקום אחד שבו סקריפט Python חייב להתערב: לומר למצלמה לאיזו רשת להצטרף. עד שצעד זה מצליח, אף אחת מתכונות הרשת ששאר חלק זה מכסה לא תעבוד.
9.4.1. מודול network¶
מודול network חושף את חומרת הרשת של המצלמה ל-Python. הסט המדויק של הממשקים תלוי בלוח: למצלמות רבות יש שבב אלחוטי והן חושפות מחלקת WLAN (על שם Wireless Local Area Network); בחלק מהלוחות יש גם יציאת Ethernet מובנית והם חושפים מחלקת LAN (על שם Local Area Network, כלומר הגרסה הקווית). דפוס השימוש זהה עבור שניהם, עם הבדל חשוב אחד: לממשק אלחוטי צריך לומר לאיזו רשת להצטרף, בעוד ש-Ethernet קולט את מה שיש על הכבל.
9.4.2. זרימת ה-Wi-Fi¶
הצטרפות לרשת Wi-Fi היא שלושה שלבים: בניית הממשק, הקמתו, ובקשה ממנו להתחבר לרשת נקובה בשם עם סיסמה. הממשק מנהל משא ומתן עם נקודת הגישה ברקע; קריאת 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, גורם למצלמה לארח רשת קטנה משלה שהתקנים אחרים יכולים להצטרף אליה; שימושי עבור ממשקי הגדרה והקמה באתר, אך לא המקרה הנפוץ.
ברגע ש-isconnected() מחזיר True, המצלמה נמצאת על הרשת. כל שאר מה שהשכבות הגבוהות יותר נזקקו לו כדי להקים את עצמן קרה אוטומטית בזמן שהקישור עלה; הדפים שלפנינו מפרטים את הרכיבים הללו אחד אחד.
9.4.3. מה יכול להשתבש¶
כמה מצבי כשל מעשיים מופיעים בשלב זה.
שם רשת או סיסמה שגויים. ניסיון החיבור חוזר על עצמו בשקט עד שהאפליקציה מוותרת. עטוף את ההמתנה ב-timeout כך שהלולאה למעלה לא תיחסם לנצח:
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)
מחוץ לטווח. המצלמה ונקודת הגישה צריכות להיות קרובות מספיק כך שהאות חזק מספיק כדי להחזיק קישור.
status()מחזיר קוד המציין מדוע הקישור אינו פעיל;scan()מחזיר את רשימת הרשתות שהרדיו יכול לראות, וזה האבחון שיש להריץ כאשרconnectלא מצליח.נקודת הגישה מבקשת יותר מסיסמה. רשתות פתוחות (ללא סיסמה) ואלו הנפוצות המוגנות בסיסמה מכוסות על ידי
connectכפי שמוצג למעלה. רשתות גדולות יותר במקומות עבודה ובבתי ספר משתמשות לעיתים בסכמה שונה שבה המצלמה צריכה לאמת מול שרת התחברות נפרד; אלו דורשות ארגומנטים נוספים ל-connect. ראה class WLAN – שליטה בממשקי WiFi מובנים למשטח המלא.
9.4.4. להישאר מחובר¶
הקמת הקישור היא חצי מהבעיה. להישאר מחובר הוא החצי השני – נקודות גישה מאותחלות, המצלמה נודדת מחוץ לטווח, חכירות DHCP פוקעות, קושחת הרדיו לעיתים נתקעת. מצלמה שעתידה לחיות על הרשת במשך חודשים חייבת לשים לב לכך ולהתאושש בעצמה.
תבנית הזיהוי היא לקרוא ל-isconnected() פעם אחת בכל איטרציה של הלולאה הראשית ולהגיב כאשר הוא מחזיר False. isconnected() יכול לשקר לרגע קצר כאשר חיבור נפל מבלי שהרדיו שם לב עדיין – שליחת סוקט שנכשלת כאשר הקישור ”אמור“ להיות פעיל היא הראיה הנוספת של האפליקציה לנפילה. status() הוא המקור הסמכותי יותר כאשר השניים אינם מסכימים.
תבנית ההתחברות מחדש היא disconnect() ולאחריה connect() עם אותם פרטי הזדהות, כאשר ההמתנה עטופה ב-timeout כמו בחיבור הראשוני. השתהה בין ניסיונות – שנייה אחת, שתיים, ארבע, מכפיל עד דקה בערך – כך שתקלה ממושכת לא תרעיש את ה-AP ולא תשרוף את תקציב ההספק של הרדיו על לולאות סרק:
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
כאשר אותו עוזר ממשיך להחזיר False, ייתכן שקושחת הרדיו עצמה תקועה. המוצא האחרון הוא איפוס חשמלי של הרדיו: active(False), השהיה קצרה, active(True), התחברות מחדש מאפס. זה מחזיר את קושחת הרדיו למצב ידוע במחיר של כמה שניות נוספות של השבתה:
def radio_power_cycle(wlan, ssid, password):
wlan.active(False)
time.sleep(1)
wlan.active(True)
return reconnect(wlan, ssid, password)
מצלמה שהייתה מחוץ לרשת במשך דקות היא כשל אמיתי שהאפליקציה חייבת לראות. קוד ההתאוששות צריך לחשוף מצב זה – לסמן את הרשת כלא תקינה בדגל שהלולאה הראשית בודקת, ולתת לאפליקציה לדלג על שליחות הרשת שהייתה מבצעת בעוד הדגל לא פעיל – כך שתקלה ממושכת לא תתקע את האפליקציה בהמתנה לסוקטים שלעולם לא יכתבו.
9.4.5. Ethernet, כשהוא קיים¶
לוחות עם Ethernet מובנה חושפים את אותה תבנית ללא צעד ה-connect. ממשק LAN מוקם עם active(), וברגע שהכבל מחובר הממשק מוכן לשימוש:
import network
lan = network.LAN()
lan.active(True)
print("link up")
לאחר נקודה זו שאר הדפים בחלק זה חלים באותו אופן ללא קשר לאיזה ממשק הביא את המצלמה אל הרשת. השכבות הגבוהות יותר אינן מתעניינות אם הקישור שמתחתיהן הוא Wi-Fi או Ethernet – ”מחובר“ הוא ”מחובר“.
עבור ההפניה המלאה של WLAN ו-LAN, כולל כפתורי התצורה שלא נכנסו כאן, ראה network — הגדרת רשת.