9.4. 링크 올리기¶
이전 페이지에서 다룬 링크 계층은 대부분 자동이지만, Python 스크립트가 개입해야 하는 한 가지 지점이 있습니다: 카메라에게 어느 네트워크에 접속할지 알려주는 것입니다. 그 단계가 성공하기 전까지는 이 섹션의 나머지에서 다루는 어떤 네트워크 기능도 동작하지 않습니다.
9.4.1. network 모듈¶
network 모듈은 카메라의 네트워킹 하드웨어를 Python에 노출합니다. 정확히 어떤 인터페이스 집합을 사용할 수 있는지는 보드에 따라 다릅니다: 많은 카메라가 무선 칩을 가지고 있어 WLAN 클래스(Wireless Local Area Network에서 따온 이름)를 노출하며, 일부 보드는 내장 이더넷 포트도 가지고 있어 LAN 클래스(Local Area Network, 즉 유선 버전에서 따온 이름)를 노출합니다. 사용 패턴은 둘 다 동일하지만 한 가지 중요한 차이가 있습니다: 무선 인터페이스는 어느 네트워크에 접속할지 알려주어야 하는 반면, 이더넷은 케이블에 있는 것이 무엇이든 그것을 받아들입니다.
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에 추가 인수가 필요합니다. 전체 표면에 대해서는 class WLAN – 내장 WiFi 인터페이스 제어 을 참고하세요.
9.4.4. 연결 유지하기¶
링크를 올리는 것은 문제의 절반입니다. 연결을 유지하는 것이 나머지 절반입니다 – 액세스 포인트가 재부팅되고, 카메라가 범위 밖으로 이동하고, DHCP 리스가 만료되고, 무선 펌웨어가 가끔 멈춥니다. 몇 달 동안 네트워크에 상주할 카메라는 그것을 알아차리고 스스로 복구할 수 있어야 합니다.
탐지 패턴은 메인 루프 반복마다 한 번씩 isconnected() 를 호출하고 False 를 반환할 때 대응하는 것입니다. isconnected() 는 무선 장치가 아직 알아차리지 못한 채 연결이 끊겼을 때 잠시 거짓을 말할 수 있습니다 – 링크가 “올라와 있어야 할” 때 실패하는 소켓 전송이 끊김에 대한 애플리케이션의 또 다른 증거입니다. 둘이 일치하지 않을 때는 status() 가 더 권위 있는 소스입니다.
재연결 패턴은 disconnect() 에 이어 동일한 자격 증명으로 connect() 를 호출하는 것이며, 초기 연결에서처럼 대기를 타임아웃으로 감쌉니다. 시도 사이에는 백오프하세요 – 1초, 2초, 4초, 1분 정도까지 두 배씩 늘리며 – 그래야 긴 장애가 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. 이더넷이 있을 때¶
내장 이더넷이 있는 보드는 connect 단계 없이 동일한 패턴을 노출합니다. LAN 인터페이스는 active() 로 올리며, 케이블이 꽂히는 즉시 인터페이스를 사용할 준비가 됩니다:
import network
lan = network.LAN()
lan.active(True)
print("link up")
이 시점 이후로는 어느 인터페이스가 카메라를 네트워크에 올렸든 상관없이 이 섹션의 나머지 페이지들이 동일하게 적용됩니다. 상위 계층은 그 아래의 링크가 Wi-Fi인지 이더넷인지 신경 쓰지 않습니다 – “연결됨”은 “연결됨”일 뿐입니다.
여기에 다 담지 못한 구성 노브를 포함한 전체 WLAN 및 LAN 레퍼런스는 network — 네트워크 구성 를 참고하세요.