Inek

Configurar arduino un formulario para ingresar nuestras credenciales WiFi

¡Tu mensaje fue recibido! Una vez que sea aprobado, estará visible para los demás visitantes.

Cerrar

15 Nov 2022

¿Te ha sucedido que tenés tu arduino operativo, conectado al WiFi, y necesitas cambiar las credenciales de conexión? En este post voy a dejar apuntado una manera de hacer que nuestro arduino nos presente un formulario web para poder cambiar las credenciales de conexión. En un post siguiente, añadiré el código necesario para almacenar en la EEPROM las últimas credenciales ingresadas, de modo que podamos recuperarlas cuando se reinicie nuestro dispositivo.

Ya sea porque cambies la contraseña en tu módem o tengas que conectarte a otra WiFi, en esos casos, generalmente toca recompilar nuestro dispositivo Arduino con nuevas credenciales. Si el dispositivo está instalado en alguna posición incómoda, o con poco espacio, será de mucha utilidad poder reconfigurar la conexión, sin tener que desarmar nada ni hacer contorsionismo para conectar un cable.

Al iniciar nuestro Arduino, el dispositivo creará su propia WiFi, a la que nos podremos conectar con nuestro teléfono. Luego con el navegador podremos conectarnos a una ip donde veremos el formulario para seleccionar una señal de WiFi e ingresar la contraseña.

Sketch principal

Este será el sketch principal, en donde dejo la lógica general:

#include "wifi_connection_manager.h"
#include "web_server.h"

WifiConnectionManager wifi();
WebServer server(wifi);

void setup()
{
  Serial.begin(115200);

  if (!wifi.setup()) {
    Serial.println("Error while setup softAP");
  }

  server.setup();
}

void loop()
{
}

La clase WifiConnectionManager es la encargada de abstraer el proceso de configuración de la conexión. Luego la clase WebServer es donde vamos a pintar el formulario web y procesar la interacción con éste.

WebServer

Esta clase encapsula el procesamiento de requests http y las respuestas al navegador.

En el método setup es donde configuraremos los handlers que será capaz de atender el propio servidor.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
  request->send_P(200, "text/html", index_html);
});

Aquí estamos indicando que si llega una petición http de tipo GET a nuestro servidor, indicando el path “/”, éste se responderá con el texto html alojado en la variable index_html declarada y definida en el archivo html.h.

En esta clase WebServer también definimos las respuestas para otras peticiones http:

Cada uno de los endpoints listados arriba se corresponden con una función en el javascript inyectado en nuestra página principal:

Nombre de función Propósito
startScan Invoca al endpoint POST /scan y se ejecuta cada vez que cargamos la página.
addNetworks Es invocada tras obtener la respuesta a la llamada http que se origina en startScan. Se dispara una y otra vez hasta obtener un código http 200 con el listado de redes encontradas.
startConnection Esta función maneja el envío del formulario una vez que elegimos un SSID y una contraseña
checkIfConnected Invocaremos esta función de manera recursiva hasta obtener una respuesta exitosa o agotemos el número de intentos definido (en este ejemplo, 20).

WiFiConnectionManager

En esta clase vamos a gestionar nuestra conexión. Este es el contenido de wifi_connection_manager.h:

#ifndef WIFI_CONNECTION_MANAGER_H
#define WIFI_CONNECTION_MANAGER_H

#include <vector>
#include <string>

class WifiConnectionManager
{
  const char *apSSID = "MyESP8266";
  int networksFound = 0;

  public: 
    bool setup();
    bool connected();
    void scanNetworksAsync();
    bool scanIsDone();
    std::vector<std::string> getNetworks();
    void connect(const char * ssid, const char * password);
};

#endif

En el método setup establecemos el modo de conexión, WIFI_AP_STA, que es Soft Access Point + Station. Este modo permite que nuestro arduino tenga un SSID, en nuestro caso MyESP8266, al que nos podremos conectar (Access Point) usando la IP predefinida 192.168.4.1 y a la vez será capaz de conectarse a una WIFI (Station). La idea de este funcionamiento dual es poder conectarnos al SSID del dispositivo para que actúe como servidor independiente. Por otra parte queremos que, tras indicar a qué Wifi nos queremos conectar, el dispositivo sea capaz de conectarse a esa red.

// ...

bool WifiConnectionManager::setup()
{
  WiFi.mode(WIFI_AP_STA);
  return WiFi.softAP(apSSID); // apSSID está definido en nuestro .h
}

// ...

El método connected simplemente nos indica si estamos conectados o no a alguna Wifi:

// ...

bool WifiConnectionManager::connected()
{
  return WiFi.status() == WL_CONNECTED;
}

// ...

Vamos a implementar ahora el método scanNetworks, utilizado por nuestro objeto de tipo WebServer para iniciar la búsqueda asíncrona de redes:

// ...

void WifiConnectionManager::scanNetworksAsync()
{
  WiFi.scanNetworks(true);
  networksFound = -1;
}

// ...

El método define scanIsDone actualiza nuestra variable privada networksFound. Si ésta es mayor o igual a 0, entonces es que el scan terminó. Con el método getNetworks ponemos los SSID encontrados en un vector que será consumido por la clase WifiConnectionManager para responder con la lista de redes encontradas en el scan.

Finalmente, tenemos el método connect, también invocado desde nuestro WebServer para conectarnos al SSID elegido:

// ...

bool WifiConnectionManager::connect(const char* ssid, const char* password)
{
  return WL_CONNECTED == WiFi.begin(ssid, password);
}

// ...

Uso de nuestro dispositivo

Una vez que compilamos nuestro código y lo subimos a nuestro dispositivo, podemos conectarnos con nuestro móvil, seleccionando nuestro SSID en el listado de WiFi:

Wifi list

Tras conectarnos a Arduino, podremos desplegar el formulario en el navegador del teléfono, cargando la dirección web http://192.168.1.4:

Select Wifi form

Una vez que seleccionamos una red e introducimos la contraseña correcta, nuestro dispositivo se conectará a ella.

Aquí dejo el link al repoositorio con el código de este post.

¿Qué te pareció el post?

No hay comentarios.