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 вибирає режим станції – камера приєднується до мережі, яку хтось інший хостить. Протилежний режим, IF_AP, робить камеру хостом власної невеликої мережі, до якої можуть підключатися інші пристрої; корисно для інтерфейсів конфігурації та налаштування на місці, але не є типовим випадком.
Після того, як isconnected() повертає True, камера перебуває в мережі. Все інше, що потрібне вищим рівням для налаштування себе, відбулося автоматично під час підняття каналу; наступні сторінки пояснюють ці частини по одній.
9.4.3. Що може піти не так¶
На цьому кроці з’являється кілька практичних причин відмов.
Неправильна назва мережі або пароль. Спроба підключення мовчки повторюється, поки застосунок не здасться. Оберніть очікування тайм-аутом, щоб цикл вище не блокував назавжди:
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. Дивіться клас WLAN – керування вбудованими WiFi-інтерфейсами для повного опису.
9.4.4. Підтримка з’єднання¶
Підняти канал – це половина проблеми. Утримати з’єднання – інша половина: точки доступу перезавантажуються, камера виходить за межі зони дії, DHCP-оренди закінчуються, мікропрограма радіо іноді зависає. Камера, що буде в мережі місяцями, має помічати це і відновлюватися самостійно.
Схема виявлення: викликати isconnected() раз за ітерацію основного циклу і реагувати, коли повертається False. isconnected() може ненадовго брехати, коли з’єднання впало, але радіо ще не помітило – відмова відправки через сокет, коли канал «мав би» бути піднятим, є іншим доказом відключення для застосунку. status() є більш авторитетним джерелом, коли вони розходяться.
Схема повторного підключення – disconnect() з наступним connect() з тими самими обліковими даними, з очікуванням, обгорнутим у тайм-аут, як і при початковому підключенні. Відступайте між спробами – одна секунда, дві, чотири, подвоюючи до хвилини чи близько того – щоб тривале відключення не навантажувало AP і не витрачало бюджет енергії радіо на spin-цикли:
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 — налаштування мережі.