Implementando Formulários Web para Controle no ESP32
Marcelo V. Souza
1s 312ms
Introdução🔗
O ESP32 é uma poderosa plataforma que combina conectividade Wi-Fi e Bluetooth com um microcontrolador de alto desempenho. Isso o torna ideal para uma variedade de projetos de IoT e automação residencial. Uma das funcionalidades mais interessantes do ESP32 é a capacidade de hospedar um servidor web, permitindo que você controle e monitore dispositivos remotamente através de uma interface web.
Neste artigo, vamos explorar como implementar formulários web no ESP32 para controlar dispositivos. Vamos construir um servidor web que apresenta um formulário ao usuário, processa os dados enviados e executa ações com base nesses dados.
Formulários web são uma forma intuitiva e acessível de interagir com sistemas eletrônicos. Ao implementar formulários no ESP32, você pode:
- Controlar dispositivos remotamente: Ligar/desligar LEDs, motores, relés, etc.
- Receber inputs do usuário: Ajustar configurações, selecionar modos de operação e muito mais.
- Criar interfaces amigáveis: Facilitar a interação mesmo para usuários com pouca experiência técnica.
Utilizar formulários web elimina a necessidade de aplicações móveis ou interfaces físicas complicadas. Tudo o que você precisa é de um navegador web, tornando o acesso ao seu dispositivo simples e universal.
Preparando o Ambiente🔗
Antes de começarmos, certifique-se de ter o seguinte:
- Placa ESP32: Pode ser qualquer modelo compatível.
- Cabo USB: Para programar a placa.
- Arduino IDE: Ambiente de desenvolvimento configurado para o ESP32.
- Conexão Wi-Fi: Para conectar o ESP32 à rede.
Configurando o Arduino IDE
Se você ainda não configurou o ESP32 na Arduino IDE, siga estes passos:
1. Abra a Arduino IDE.
2. Vá em Arquivo > Preferências.
3. No campo URLs Adicionais para Gerenciadores de Placas, adicione:
https://dl.espressif.com/dl/package_esp32_index.json
4. Clique em OK.
5. Vá em Ferramentas > Placa > Gerenciador de Placas.
6. Pesquise por ESP32 e instale a opção "esp32" by Espressif Systems.
Conectando o ESP32 à Rede Wi-Fi🔗
Para que o ESP32 possa hospedar um servidor web acessível pela rede, ele precisa estar conectado ao Wi-Fi.
#include <WiFi.h>
const char* ssid = "NOME_DA_SUA_REDE";
const char* password = "SENHA_DA_SUA_REDE";
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Conectando ao Wi-Fi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("\nConectado com sucesso!");
Serial.print("Endereço IP: ");
Serial.println(WiFi.localIP());
}
void loop()
{
// Código principal
}
Explicação:
- Inclusão da biblioteca WiFi: Necessária para as funcionalidades Wi-Fi.
- Credenciais da rede: Substitua
"NOME_DA_SUA_REDE"
e "SENHA_DA_SUA_REDE"
pelas suas credenciais.
- Conectando ao Wi-Fi: O ESP32 tenta se conectar e exibe o endereço IP obtido.
Criando um Servidor Web Simples🔗
Vamos agora configurar um servidor web básico que servirá uma página ao ser acessado.
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "NOME_DA_SUA_REDE";
const char* password = "SENHA_DA_SUA_REDE";
WebServer server(80);
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid, password);
// Aguarda conexão
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("\nConectado ao Wi-Fi.");
Serial.print("Endereço IP: ");
Serial.println(WiFi.localIP());
// Define a rota raiz
server.on("/", handleRoot);
// Inicia o servidor
server.begin();
Serial.println("Servidor HTTP iniciado.");
}
void loop()
{
server.handleClient();
}
void handleRoot()
{
server.send(200, "text/plain", "Bem-vindo ao servidor web do ESP32!");
}
Explicação:
- Configuração do servidor: Usamos a biblioteca
WebServer
para criar um servidor na porta 80.
- Definição da rota: A função
handleRoot()
será chamada quando a raiz ("/"
) for acessada.
- Resposta ao cliente: Enviamos uma mensagem simples de texto.
Agora, vamos criar um formulário web que permita ao usuário controlar um LED conectado ao ESP32.
Montagem do Circuito
Para este exemplo, usaremos o LED embutido da placa (geralmente no pino GPIO 2). Se a sua placa não tiver um LED embutido, você pode conectar um LED externo ao GPIO 2 através de um resistor de 220Ω.
Atualizando o Código
Variáveis Globais e Configuração
const int ledPin = 2; // Pino do LED
void setup()
{
// ... código anterior ...
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW); // Inicialmente desligado
// Define as rotas
server.on("/", handleRoot);
server.on("/led", HTTP_POST, handleLED);
// Inicia o servidor
server.begin();
}
Função handleRoot()
Vamos servir uma página HTML com um formulário.
void handleRoot()
{
String html = "<!DOCTYPE html><html>";
html += "<head><title>Controle de LED</title></head>";
html += "<body>";
html += "<h1>Controle de LED</h1>";
html += "<form action=\"/led\" method=\"POST\">";
html += "<label for=\"estado\">Estado do LED:</label><br><br>";
html += "<input type=\"radio\" id=\"ligar\" name=\"estado\" value=\"ligar\">";
html += "<label for=\"ligar\">Ligar</label><br>";
html += "<input type=\"radio\" id=\"desligar\" name=\"estado\" value=\"desligar\">";
html += "<label for=\"desligar\">Desligar</label><br><br>";
html += "<input type=\"submit\" value=\"Enviar\">";
html += "</form>";
html += "</body></html>";
server.send(200, "text/html", html);
}
Explicação:
- Construção da página HTML: Utilizamos uma
String
para concatenar o conteúdo HTML.
- Formulário: O formulário envia uma requisição
POST
para a rota /led
.
Função handleLED()
Esta função processa os dados enviados pelo formulário.
void handleLED()
{
if (server.hasArg("estado"))
{
String estado = server.arg("estado");
if (estado == "ligar")
{
digitalWrite(ledPin, HIGH);
}
else if (estado == "desligar")
{
digitalWrite(ledPin, LOW);
}
}
// Redireciona de volta para a página inicial
server.sendHeader("Location", "/");
server.send(303);
}
Explicação:
- Verificação dos argumentos: Utilizamos
server.hasArg()
para verificar se o parâmetro estado
foi enviado.
- Leitura do valor:
server.arg("estado")
retorna o valor selecionado pelo usuário.
- Controle do LED: Dependendo do valor, ligamos ou desligamos o LED.
- Redirecionamento: Após processar o formulário, redirecionamos o usuário de volta para a página inicial.
Testando a Aplicação🔗
1. Carregue o código no ESP32.
2. Abra o Monitor Serial para verificar o endereço IP atribuído.
3. Acesse o endereço IP do ESP32 pelo navegador (por exemplo, http://192.168.1.100
).
4. Utilize o formulário para ligar ou desligar o LED.
Aprimorando a Interface Web🔗
Vamos melhorar a experiência do usuário exibindo o estado atual do LED na página.
Atualizando handleRoot()
void handleRoot()
{
String estadoLED = digitalRead(ledPin) ? "Ligado" : "Desligado";
String html = "<!DOCTYPE html><html>";
html += "<head><title>Controle de LED</title></head>";
html += "<body>";
html += "<h1>Controle de LED</h1>";
html += "<p>O LED está atualmente: <strong>" + estadoLED + "</strong></p>";
html += "<form action=\"/led\" method=\"POST\">";
html += "<label for=\"estado\">Alterar estado:</label><br><br>";
html += "<input type=\"radio\" id=\"ligar\" name=\"estado\" value=\"ligar\">";
html += "<label for=\"ligar\">Ligar</label><br>";
html += "<input type=\"radio\" id=\"desligar\" name=\"estado\" value=\"desligar\">";
html += "<label for=\"desligar\">Desligar</label><br><br>";
html += "<input type=\"submit\" value=\"Enviar\">";
html += "</form>";
html += "</body></html>";
server.send(200, "text/html", html);
}
Explicação:
- Estado atual do LED: Lemos o estado do pino
ledPin
e exibimos na página.
- Melhoria da interface: Adicionamos informações úteis para o usuário.
É importante validar os dados enviados pelo usuário para evitar comportamentos inesperados.
Atualizando handleLED()
void handleLED()
{
if (server.hasArg("estado"))
{
String estado = server.arg("estado");
if (estado == "ligar")
{
digitalWrite(ledPin, HIGH);
}
else if (estado == "desligar")
{
digitalWrite(ledPin, LOW);
}
else
{
server.send(400, "text/plain", "Valor inválido.");
return;
}
}
else
{
server.send(400, "text/plain", "Parâmetro 'estado' não encontrado.");
return;
}
// Redireciona de volta para a página inicial
server.sendHeader("Location", "/");
server.send(303);
}
Explicação:
- Validação do valor: Verificamos se o valor de
estado
é válido.
- Respostas de erro: Enviamos uma resposta HTTP 400 (Bad Request) em caso de erro.
Melhorando a Segurança🔗
Para evitar que qualquer pessoa na rede controle o seu dispositivo, podemos adicionar uma autenticação simples.
Adicionando um Campo de Senha
Atualize o formulário para incluir um campo de senha.
void handleRoot()
{
// ... código anterior ...
html += "<label for=\"senha\">Senha:</label><br>";
html += "<input type=\"password\" id=\"senha\" name=\"senha\"><br><br>";
html += "<input type=\"submit\" value=\"Enviar\">";
html += "</form>";
html += "</body></html>";
server.send(200, "text/html", html);
}
Atualizando handleLED()
const String senhaCorreta = "123456";
void handleLED()
{
if (server.hasArg("senha"))
{
String senha = server.arg("senha");
if (senha != senhaCorreta)
{
server.send(401, "text/plain", "Senha incorreta.");
return;
}
}
else
{
server.send(400, "text/plain", "Parâmetro 'senha' não encontrado.");
return;
}
// ... código anterior de validação e controle do LED ...
// Redireciona de volta para a página inicial
server.sendHeader("Location", "/");
server.send(303);
}
Explicação:
- Senha fixa: Definimos
senhaCorreta
como uma constante.
- Verificação da senha: Antes de processar o estado do LED, validamos a senha fornecida.
- Respostas adequadas: Enviamos os códigos de status HTTP apropriados em caso de erro.
Estilos CSS para Melhorar a Aparência🔗
Vamos adicionar estilos simples para tornar a página mais agradável.
void handleRoot()
{
// ... código anterior ...
String html = "<!DOCTYPE html><html>";
html += "<head>";
html += "<title>Controle de LED</title>";
html += "<style>";
html += "body { font-family: Arial, sans-serif; text-align: center; }";
html += "h1 { color: #333; }";
html += "form { display: inline-block; margin-top: 20px; }";
html += "input[type=submit] { padding: 10px 20px; }";
html += "</style>";
html += "</head>";
// ... restante do código ...
}
Explicação:
- Estilos embutidos: Utilizamos a tag
para adicionar CSS diretamente no HTML.
- Melhoria visual: Ajustamos fontes, cores e espaçamentos.
Expandindo o Projeto para Controlar Múltiplos Dispositivos🔗
Você pode adaptar este exemplo para controlar vários dispositivos, como múltiplos LEDs ou relés.
Atualizando o Código
Variáveis e Configuração
const int ledPin1 = 2; // Primeiro LED
const int ledPin2 = 4; // Segundo LED
void setup()
{
// ... código anterior ...
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
}
Atualizando o Formulário
void handleRoot()
{
// ... código anterior ...
html += "<h2>LED 1</h2>";
html += "<input type=\"checkbox\" id=\"led1\" name=\"led1\"";
if (digitalRead(ledPin1)) html += " checked";
html += ">";
html += "<label for=\"led1\">Ligar</label><br><br>";
html += "<h2>LED 2</h2>";
html += "<input type=\"checkbox\" id=\"led2\" name=\"led2\"";
if (digitalRead(ledPin2)) html += " checked";
html += ">";
html += "<label for=\"led2\">Ligar</label><br><br>";
// ... campo de senha e botão enviar ...
}
Atualizando handleLED()
void handleLED()
{
// ... verificação de senha ...
// Controle do LED 1
if (server.hasArg("led1"))
{
digitalWrite(ledPin1, HIGH);
}
else
{
digitalWrite(ledPin1, LOW);
}
// Controle do LED 2
if (server.hasArg("led2"))
{
digitalWrite(ledPin2, HIGH);
}
else
{
digitalWrite(ledPin2, LOW);
}
// Redireciona de volta para a página inicial
server.sendHeader("Location", "/");
server.send(303);
}
Explicação:
- Checkboxes: Usamos checkboxes para permitir que o usuário ligue ou desligue cada LED individualmente.
- Leitura dos parâmetros: Se o parâmetro existe, o LED é ligado; caso contrário, é desligado.
Considerações de Segurança🔗
Embora tenhamos adicionado uma senha, é importante notar que:
- A senha é enviada em texto plano: Sem criptografia, a senha pode ser interceptada em redes não seguras.
- Sem autenticação real: Este método é simples e não deve ser usado em ambientes onde a segurança é crítica.
- HTTPS não é trivial: Implementar HTTPS no ESP32 é complexo devido às limitações de recursos.
Para projetos onde a segurança é essencial, considere implementar métodos de autenticação mais robustos ou utilizar uma rede isolada.
Para que as configurações persistam após reinicializações, você pode armazenar os dados em memória flash usando SPIFFS ou LittleFS.
Introdução ao SPIFFS
SPIFFS (SPI Flash File System) permite que você armazene arquivos na memória flash do ESP32, semelhante a um sistema de arquivos.
Exemplo de Uso:
- Salvar estado do LED: Armazene o estado atual para que ele seja restaurado após uma reinicialização.
- Armazenar configurações do usuário: Como senhas ou preferências.
Implementação Básica
Devido à complexidade e ao foco deste artigo, não entraremos em detalhes, mas você pode explorar essa funcionalidade em projetos futuros.
Conclusão🔗
Neste artigo, exploramos como implementar formulários web para controle no ESP32. Começamos com um servidor web básico e avançamos até uma interface interativa que permite o controle de múltiplos dispositivos. Apesar da simplicidade do exemplo, os conceitos apresentados são poderosos e podem ser expandidos para criar aplicações complexas de IoT e automação.
Principais aprendizados:
- Como configurar um servidor web no ESP32.
- Como criar e servir páginas HTML dinâmicas.
- Como processar dados enviados por formulários web.
- Noções básicas de segurança e autenticação.
Próximos Passos🔗
- Explorar AJAX e WebSockets: Para atualizações em tempo real sem recarregar a página.
- Implementar autenticação robusta: Utilizando tokens ou outros métodos seguros.
- Criar interfaces mais complexas: Incorporando JavaScript e bibliotecas de frontend.
A prática é fundamental. Experimente modificar o código, adicionar novas funcionalidades e adaptar os conceitos apresentados aos seus projetos pessoais. O ESP32 é uma plataforma versátil e, com criatividade, você pode desenvolver soluções inovadoras para o mundo real.
Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.
Tags