9.4. Få länken uppe¶
Länklagret som behandlades på föregående sida är mestadels automatiskt, men det finns ett ställe där ett Python-skript måste gripa in: att berätta för kameran vilket nätverk den ska ansluta till. Tills det steget lyckas kommer ingen av nätverksfunktionerna som resten av detta avsnitt behandlar att fungera.
9.4.1. Modulen network¶
Modulen network exponerar kamerans nätverkshårdvara för Python. Den exakta uppsättningen gränssnitt beror på kortet: många kameror har ett trådlöst chip och exponerar en WLAN-klass (uppkallad efter Wireless Local Area Network); vissa kort har också en inbyggd Ethernet-port och exponerar en LAN-klass (uppkallad efter Local Area Network, dvs. den trådbundna versionen). Användningsmönstret är detsamma för båda, med en viktig skillnad: ett trådlöst gränssnitt måste få veta vilket nätverk det ska ansluta till, medan Ethernet hämtar vad som än finns på kabeln.
9.4.2. Wi-Fi-flödet¶
Att ansluta till ett Wi-Fi-nätverk är tre steg: konstruera gränssnittet, ta upp det, be det ansluta till ett namngivet nätverk med ett lösenord. Gränssnittet förhandlar med accesspunkten i bakgrunden; ett isconnected()-anrop rapporterar när länken har kommit upp:
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")
Argumentet IF_STA väljer station-läge – kameran ansluter till ett nätverk som någon annan är värd för. Det motsatta läget, IF_AP, gör att kameran är värd för sitt eget lilla nätverk som andra enheter kan ansluta till; användbart för konfigurationsgränssnitt och installation på plats, men inte det vanliga fallet.
När isconnected() returnerar True är kameran på nätverket. Allt annat som de högre lagren behövde för att sätta upp sig själva har skett automatiskt medan länken kom upp; sidorna som följer förklarar dessa delar en i taget.
9.4.3. Vad som kan gå fel¶
Några praktiska felscenarier dyker upp i detta steg.
Fel nätverksnamn eller lösenord. Anslutningsförsöket försöker tyst igen tills applikationen ger upp. Omslut väntan med en timeout så att loopen ovan inte blockerar för alltid:
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)
Utanför räckvidd. Kameran och accesspunkten måste vara tillräckligt nära att signalen är stark nog att hålla en länk.
status()returnerar en kod som anger varför länken inte är uppe;scan()returnerar listan över nätverk som radion kan se, vilket är diagnostiken att köra närconnectinte lyckas.Accesspunkten ber om mer än ett lösenord. Öppna nätverk (inget lösenord) och de vanliga lösenordsskyddade täcks av
connectsom visas ovan. Större nätverk på arbetsplatser och skolor använder ibland ett annat schema där kameran måste autentisera mot en separat inloggningsserver; de behöver extra argument tillconnect. Se class WLAN – styr inbyggda WiFi-gränssnitt för hela ytan.
9.4.4. Att förbli ansluten¶
Att få länken uppe är halva problemet. Att förbli ansluten är den andra halvan – accesspunkter startar om, kameran roamar utanför räckvidd, DHCP-leasingar löper ut, radions fasta programvara fastnar ibland. En kamera som ska leva på nätverket i månader måste märka det och återhämta sig på egen hand.
Detekteringsmönstret är att anropa isconnected() en gång per huvudloopiteration och reagera när den returnerar False. isconnected() kan ljuga kortvarigt när en anslutning har brutits utan att radion har märkt det än – en socket-sändning som misslyckas när länken ”borde” vara uppe är applikationens andra bevis på ett avbrott. status() är den mer auktoritativa källan när de två är oeniga.
Återanslutningsmönstret är disconnect() följt av connect() med samma autentiseringsuppgifter, med väntan omsluten i en timeout som vid den initiala anslutningen. Backa av mellan försöken – en sekund, två, fyra, fördubblande upp till en minut eller så – så att ett långt avbrott inte hamrar på accesspunkten och inte bränner radions effektbudget på spinnloopar:
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
När den hjälparen fortsätter att returnera False kan radions fasta programvara själv ha hängt sig. Den sista utvägen är att strömcykla radion: active(False), en kort paus, active(True), återanslut från grunden. Detta för radions fasta programvara tillbaka till ett känt tillstånd till priset av några extra sekunders driftstopp:
def radio_power_cycle(wlan, ssid, password):
wlan.active(False)
time.sleep(1)
wlan.active(True)
return reconnect(wlan, ssid, password)
En kamera som har varit utanför nätverket i flera minuter är ett riktigt fel som applikationen måste se. Återhämtningskoden bör synliggöra det tillståndet – markera nätverket som ohälsosamt i en flagga som huvudloopen kontrollerar, och låt applikationen hoppa över de nätverkssändningar den skulle ha gjort medan flaggan inte är satt – så att ett långt avbrott inte stoppar applikationen i väntan på sockets som aldrig kommer att skriva.
9.4.5. Ethernet, när det finns¶
Kort med inbyggt Ethernet exponerar samma mönster utan connect-steget. Gränssnittet LAN tas upp med active(), och så snart kabeln är inkopplad är gränssnittet redo att användas:
import network
lan = network.LAN()
lan.active(True)
print("link up")
Efter denna punkt gäller resten av detta avsnitts sidor på samma sätt oavsett vilket gränssnitt som förde kameran på nätverket. De högre lagren bryr sig inte om huruvida länken under dem är Wi-Fi eller Ethernet – ”ansluten” är ”ansluten”.
För den fullständiga WLAN- och LAN-referensen, inklusive de konfigurationsrattar som inte fick plats här, se network — nätverkskonfiguration.