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() с теми же учётными данными, причём ожидание обёрнуто тайм-аутом, как при первоначальном подключении. Делайте задержки между попытками – одна секунда, две, четыре, удваивая примерно до минуты – чтобы длительный сбой не нагружал точку доступа и не расходовал энергетический бюджет радиомодуля на циклы ожидания:
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 — настройка сети.