Ejercicio 02 — Una vez conectado al WiFi, hacer una petición HTTP GET a una API…
Dificultad: verde · Módulo 09 (Salto a ESP32 + WiFi)
Enunciado
Una vez conectado al WiFi, hacer una petición HTTP GET a una API pública y mostrar la respuesta por Serial.
Montaje (ESP32 DevKit)
Ninguno (solo la placa)
Cómo se resuelve
Estar en la red no sirve de nada si no hablas con nadie. Este ejercicio da el segundo paso: la placa hace de cliente, es decir, es ella quien empieza la conversación, pide algo a otra máquina y lee lo que le contesta. Exactamente lo mismo que hace un navegador cuando abres una web.
Hay dos #include. WiFi.h ya lo conoces del ejercicio anterior; el nuevo es HTTPClient.h, que también viene con el core del ESP32. Es una capa de alto nivel: por debajo hay una conexión TCP, una petición con sus cabeceras y una respuesta que hay que parsear, pero HTTPClient te lo esconde todo detrás de tres o cuatro llamadas.
Lo primero que cambia respecto al ejercicio 01 es la organización. La conexión al WiFi se ha sacado a su propia función:
void conectarWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
Serial.print("Conectando WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println(" OK, IP: " + WiFi.localIP().toString());
}Es el mismo código de antes, con los mismos 250 ms entre comprobaciones, pero encerrado en un nombre. Esa es una decisión que vas a agradecer: a partir de aquí, en cada sketch del módulo, conectarse al WiFi es una línea (conectarWiFi();) en vez de siete, y setup() se lee de un vistazo. El detalle nuevo es WiFi.localIP().toString(): localIP() no devuelve texto sino un objeto IPAddress, y toString() lo convierte en un String para poder concatenarlo con + dentro de un solo Serial.println.
Las credenciales siguen siendo las de Wokwi: SSID es "Wokwi-GUEST" y PASSWORD la cadena vacía "", porque esa red simulada es abierta. En una placa real hay que sustituir ambos valores por los de tu red.
La novedad de verdad es la URL:
const char* URL = "http://worldtimeapi.org/api/timezone/Etc/UTC";Es una API pública que devuelve la hora actual en UTC como texto JSON. Fíjate en que es http://, no https://. No es un descuido: HTTPS obliga a negociar cifrado y a validar certificados, lo que en el ESP32 se hace con WiFiClientSecure y complica el ejercicio sin aportar nada al concepto que se quiere enseñar hoy. Con HTTP plano, HTTPClient resuelve la petición en tres líneas.
En setup(), tras arrancar el serie a 115200 y llamar a conectarWiFi(), viene la comprobación:
if (WiFi.status() == WL_CONNECTED) {Puede parecer redundante, porque conectarWiFi() no vuelve hasta estar conectada. Y en este sketch lo es. Pero es un buen hábito, y dice algo importante sobre la intención del código: no se lanza una petición de red sin comprobar antes que hay red. El día que cambies el bucle de espera por uno con límite de intentos, esa comprobación pasará de redundante a imprescindible sin que tengas que tocar nada más.
Dentro va la petición:
HTTPClient http;
http.begin(URL);
int codigo = http.GET();HTTPClient http; crea el objeto que gestiona la conexión. http.begin(URL) no envía nada todavía: solo prepara la petición, apuntándola a esa dirección. Quien la ejecuta es http.GET(), y ahí sí, la placa abre la conexión, manda la petición y espera la respuesta. GET es el método de HTTP que significa “dame esto”, el que usa el navegador para cargar una página.
El valor que devuelve GET() es el que hay que leer con cuidado, y por eso se guarda en codigo y se imprime inmediatamente. Puede ser de dos naturalezas distintas:
- Positivo: es el código de estado HTTP que ha respondido el servidor. 200 es “aquí lo tienes”, 404 es “esa ruta no existe”, 500 es “el servidor ha fallado”. Hubo conversación, aunque la respuesta no fuera la que querías.
- Negativo: no es un código HTTP en absoluto, sino un error de la propia librería. Significa que la petición ni siquiera llegó a hablar con un servidor: no hay red, el nombre del dominio no se resolvió, se agotó el tiempo de espera, la conexión se cortó.
De ahí la condición if (codigo > 0). Solo si hubo respuesta tiene sentido pedir el contenido:
String cuerpo = http.getString();getString() descarga el cuerpo de la respuesta entero y lo mete en un String, que aquí es el JSON con la hora. Para una respuesta pequeña es lo más cómodo, y en el ESP32 hay memoria de sobra para ello; en el UNO, con sus 2 KB de RAM, este mismo texto ya sería un problema serio. Merece la pena tenerlo presente: parte de lo que estás usando en este módulo es la memoria que la placa nueva te ha regalado.
Si el código fue negativo, el else imprime un mensaje de error y no se intenta leer nada, porque no hay nada que leer.
La última línea del bloque es http.end(), que libera la conexión y los recursos asociados. Se puede olvidar y el programa parecerá funcionar, porque aquí solo hay una petición. En un sketch que pida datos cada pocos segundos, no cerrar acaba agotando la memoria y colgando la placa. Es el equivalente a cerrar un fichero: no se nota hasta que se nota.
El loop() queda vacío otra vez, con la petición hecha una sola vez en setup(). Es una decisión deliberada para que el ejercicio se centre en el mecanismo. El paso natural siguiente es moverla al loop() y repetirla cada cierto tiempo, y ahí resurge una lección del módulo 06: no se hace con delay(60000), que congela la placa entera un minuto, sino comparando millis().
Una advertencia sobre la ejecución en el simulador. Wokwi tiene WiFi simulado con salida real a internet a través de la red Wokwi-GUEST, así que la petición sale de verdad y verás el JSON. Pero eso significa que el ejercicio depende de un servicio ajeno: si worldtimeapi.org está caído o tarda, verás un código negativo o un 5xx sin que tu código tenga nada malo. Cuando algo falle aquí, lo primero es mirar el número que imprime Codigo HTTP:, porque distingue en un segundo entre un problema tuyo y un problema del otro extremo.
Para practicar — cópialo y complétalo
Pega este esqueleto y completa los TODO. Es la mejor forma de aprender: inténtalo antes de mirar la solución.
/*
* Curso de Arduino — Módulo 09: ESP32 + WiFi
* Ejercicio 02 — PRÁCTICA (rellena los TODO)
* Enunciado: Una vez conectado al WiFi, hacer una petición HTTP GET a una API
* pública y mostrar la respuesta por Serial.
* Dificultad: verde
* Placa: ESP32 DevKit Montaje: ninguno (solo la placa)
* Correr: Arduino IDE / Wokwi (wokwi/ej02) / arduino-cli (ver README)
* NOTA: en Wokwi la red es SSID "Wokwi-GUEST" SIN contraseña.
*/
#include <WiFi.h>
// TODO: incluye el cliente HTTP -> #include <HTTPClient.h>
const char* SSID = "Wokwi-GUEST";
const char* PASSWORD = "";
const char* URL = "http://worldtimeapi.org/api/timezone/Etc/UTC";
void conectarWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
Serial.print("Conectando WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println(" OK, IP: " + WiFi.localIP().toString());
}
void setup() {
Serial.begin(115200);
delay(100);
conectarWiFi();
if (WiFi.status() == WL_CONNECTED) {
// TODO: crea el objeto -> HTTPClient http;
// TODO: apunta a la URL -> http.begin(URL)
// TODO: lanza el GET y guarda el código -> int codigo = http.GET()
// TODO: imprime el código HTTP por Serial
// TODO: si codigo > 0, descarga el cuerpo con http.getString() e imprímelo
// TODO: cierra la conexión -> http.end()
}
}
void loop() {
// nada en el bucle
}Solución — cópiala y ejecútala
/*
* Curso de Arduino — Módulo 09: ESP32 + WiFi
* Ejercicio 02 — MODELO (resuelto)
* Enunciado: Una vez conectado al WiFi, hacer una petición HTTP GET a una API
* pública y mostrar la respuesta por Serial.
* Dificultad: verde
* Placa: ESP32 DevKit Montaje: ninguno (solo la placa)
* Correr: Arduino IDE / Wokwi (wokwi/ej02) / arduino-cli (ver README)
* NOTA: en Wokwi la red es SSID "Wokwi-GUEST" SIN contraseña.
*/
#include <WiFi.h>
#include <HTTPClient.h> // cliente HTTP de alto nivel del core ESP32
const char* SSID = "Wokwi-GUEST";
const char* PASSWORD = "";
// API pública que devuelve la hora actual en texto JSON
const char* URL = "http://worldtimeapi.org/api/timezone/Etc/UTC";
void conectarWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
Serial.print("Conectando WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println(" OK, IP: " + WiFi.localIP().toString());
}
void setup() {
Serial.begin(115200);
delay(100);
conectarWiFi();
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(URL); // prepara la petición a la URL
int codigo = http.GET(); // ejecuta el GET; devuelve el código HTTP (200, 404...)
Serial.print("Codigo HTTP: ");
Serial.println(codigo);
if (codigo > 0) { // código positivo = hubo respuesta del servidor
String cuerpo = http.getString(); // descarga el cuerpo de la respuesta
Serial.println("Respuesta:");
Serial.println(cuerpo);
} else {
Serial.println("Error en la peticion.");
}
http.end(); // libera la conexión
}
}
void loop() {
// petición única en setup(); nada en el bucle
}Cómo ejecutar la simulación
Sin instalar nada, en el navegador
- Abre wokwi.com y crea un proyecto nuevo de la placa que pide el ejercicio.
- Pega la solución (o tu intento) en la pestaña
sketch.ino. - Abre la pestaña
diagram.json, borra lo que haya y pega el circuito de aquí abajo. - Dale al play. Verás el circuito funcionando: LEDs, pantallas y monitor serie.
Circuito del ejercicio (diagram.json)
{
"version": 1,
"author": "ESIBot",
"editor": "wokwi",
"parts": [
{ "type": "board-esp32-devkit-c-v4", "id": "esp", "top": 0, "left": 0, "attrs": {} }
],
"connections": [],
"dependencies": {}
}En VS Code, con el repo del curso
El paquete de simulación de este ejercicio está en practica/09-esp32-wifi/wokwi/ej02/. Con la extensión Wokwi instalada y la licencia activada (lo cuenta el onboarding del curso):
make sim EJ=09-esp32-wifi/ej02y después, en VS Code, Ctrl+Shift+P → Wokwi: Start Simulator. La extensión no compila: simula un firmware ya compilado, y de compilarlo se encarga ese make.
Cómo usarlo
Con placa: abre el .ino en el Arduino IDE, elige placa y puerto y pulsa Subir. Sin placa: simulalo en Wokwi con cualquiera de las dos vias de arriba. Antes de mirar la solucion, intenta completar tu el esqueleto: es la mejor forma de aprender.