9.4. Ativando o enlace¶
A camada de enlace abordada na página anterior é, em grande parte, automática, mas há um ponto em que um script Python precisa intervir: dizer à câmera a qual rede se juntar. Até que esse passo tenha sucesso, nenhum dos recursos de rede que o restante desta seção aborda funcionará.
9.4.1. O módulo network¶
O módulo network expõe o hardware de rede da câmera ao Python. O conjunto exato de interfaces depende da placa: muitas câmeras têm um chip sem fio e expõem uma classe WLAN (nomeada em alusão a Wireless Local Area Network); algumas placas também têm uma porta Ethernet embutida e expõem uma classe LAN (nomeada em alusão a Local Area Network, ou seja, a versão cabeada). O padrão de uso é o mesmo para ambas, com uma diferença importante: uma interface sem fio precisa ser informada de qual rede se juntar, enquanto a Ethernet pega o que quer que esteja no cabo.
9.4.2. O fluxo do Wi-Fi¶
Juntar-se a uma rede Wi-Fi tem três passos: construir a interface, ativá-la e pedir a ela que se conecte a uma rede nomeada com uma senha. A interface negocia com o ponto de acesso em segundo plano; uma chamada a isconnected() informa quando o enlace terminou de ser estabelecido:
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")
O argumento IF_STA seleciona o modo station – a câmera se junta a uma rede que outra pessoa está hospedando. O modo oposto, IF_AP, faz a câmera hospedar sua própria pequena rede à qual outros dispositivos podem se juntar; útil para interfaces de configuração e instalação em campo, mas não é o caso comum.
Uma vez que isconnected() retorna True, a câmera está na rede. Todo o resto de que as camadas superiores precisavam para se configurar aconteceu automaticamente enquanto o enlace estava sendo estabelecido; as páginas a seguir detalham essas partes uma a uma.
9.4.3. O que pode dar errado¶
Alguns modos de falha práticos aparecem neste passo.
Nome de rede ou senha errados. A tentativa de conexão tenta novamente silenciosamente até que a aplicação desista. Envolva a espera com um timeout para que o laço acima não bloqueie para sempre:
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)
Fora de alcance. A câmera e o ponto de acesso precisam estar próximos o suficiente para que o sinal seja forte o bastante para manter um enlace.
status()retorna um código indicando por que o enlace não está ativo;scan()retorna a lista de redes que o rádio consegue ver, que é o diagnóstico a ser executado quando oconnectnão tem sucesso.O ponto de acesso pede mais do que uma senha. Redes abertas (sem senha) e as comuns protegidas por senha são cobertas pelo
connectcomo mostrado acima. Redes maiores em locais de trabalho e escolas às vezes usam um esquema diferente, no qual a câmera precisa se autenticar contra um servidor de login separado; essas precisam de argumentos extras para oconnect. Consulte classe WLAN – controle das interfaces WiFi integradas para a superfície completa.
9.4.4. Mantendo a conexão¶
Ativar o enlace é metade do problema. Manter a conexão é a outra metade – pontos de acesso reiniciam, a câmera sai do alcance, as concessões de DHCP expiram, o firmware do rádio ocasionalmente trava. Uma câmera que vai viver na rede por meses precisa perceber isso e se recuperar sozinha.
O padrão de detecção é chamar isconnected() uma vez por iteração do laço principal e reagir quando ele retornar False. O isconnected() pode mentir brevemente quando uma conexão caiu sem que o rádio ainda tenha notado – um envio de socket que falha quando o enlace “deveria” estar ativo é a outra evidência de queda da aplicação. status() é a fonte mais autoritativa quando os dois discordam.
O padrão de reconexão é disconnect() seguido de connect() com as mesmas credenciais, com a espera envolta em um timeout, como na conexão inicial. Aplique um recuo (back off) entre as tentativas – um segundo, dois, quatro, dobrando até cerca de um minuto – para que uma interrupção longa não martele o AP e não gaste o orçamento de energia do rádio em laços de espera ativa:
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
Quando esse auxiliar continua retornando False, o próprio firmware do rádio pode estar travado. O último recurso é desligar e religar o rádio: active(False), uma breve pausa, active(True), reconectar do zero. Isso traz o firmware do rádio de volta a um estado conhecido ao custo de alguns segundos extras de indisponibilidade:
def radio_power_cycle(wlan, ssid, password):
wlan.active(False)
time.sleep(1)
wlan.active(True)
return reconnect(wlan, ssid, password)
Uma câmera que ficou fora da rede por minutos é uma falha real que a aplicação precisa enxergar. O código de recuperação deve expor esse estado – marcar a rede como não saudável em uma flag que o laço principal verifica, e deixar a aplicação pular os envios de rede que teria feito enquanto a flag está limpa – para que uma interrupção longa não trave a aplicação esperando por sockets que nunca escreverão.
9.4.5. Ethernet, quando presente¶
Placas com Ethernet embutida expõem o mesmo padrão sem o passo connect. A interface LAN é ativada com active(), e assim que o cabo é conectado a interface está pronta para uso:
import network
lan = network.LAN()
lan.active(True)
print("link up")
A partir deste ponto, o restante das páginas desta seção se aplica da mesma forma, independentemente de qual interface trouxe a câmera para a rede. As camadas superiores não se importam se o enlace abaixo delas é Wi-Fi ou Ethernet – “conectado” é “conectado”.
Para a referência completa de WLAN e LAN, incluindo os ajustes de configuração que não couberam aqui, consulte network — configuração de rede.