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.
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.
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:
POST /scan
: Inicia una búsqueda asíncrona de redes wifi. Lo que quiero decir con “asíncrona” es que se inicia la búsqueda, pero el servidor no espera a que termine para dar la respuesta. Por eso usamos el código http 202 que sirve para indicar que una petición fue aceptada.GET /networks
: Verifica si el scan de redes wifi terminó, en cuyo caso obtiene el listado y lo retorna en formato json. Si el scan aún no terminó, retorna nuevamente un código 202.POST /connect
: Este endpoint recibe SSID y contraseña de una wifi desde nuestro formulario e intenta conectarse. Como la conexión también es asíncrona, retornamos un código 202.GET /connected
: Al intentar la conexión de manera asíncrona, necesitamos este método que será disparado un número de veces hasta detectar conexión o agotar la cantidad de intentos.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). |
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);
}
// ...
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:
Tras conectarnos a Arduino, podremos desplegar el formulario en el navegador del teléfono, cargando la dirección web http://192.168.1.4:
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.
¡Tu mensaje fue recibido! Una vez que sea aprobado, estará visible para los demás visitantes.
Cerrar