01 · Punto de partida
Contar y preguntar
En el tema 19 viste cómo es una conversación HTTP y cómo leerla. Ahora usamos los dos métodos con los que un dispositivo hace casi todo su trabajo. Con POST, el dispositivo cuenta: envía sus lecturas, sus eventos y el resultado de sus acciones. Con GET, el dispositivo pregunta: cuál es su configuración, si hay un comando para él, qué hora es, si existe un firmware nuevo.
Esta asimetría tiene una consecuencia profunda que arrastramos desde el tema 17: el servidor no puede iniciar una conversación con el dispositivo, que está detrás de un NAT. Si el servidor tiene algo para decirle (cambiar un parámetro, abrir una válvula), tiene que esperar a que el dispositivo pregunte. Todo el diseño de este tema gira en torno a ese hecho: cuánto tarda el dispositivo en enterarse y cuánto le cuesta preguntar.
Como en el tema anterior, los fragmentos de C++ siguen el estilo Arduino para ESP32 y los números de costo salen de modelos que podés ejecutar y modificar.
02 · Leer
GET: leer
GET pide un recurso y no cambia nada en el servidor. Es seguro (no tiene efectos secundarios) e idempotente (repetirlo da el mismo resultado), por lo que se puede reintentar sin riesgo. En un dispositivo IoT se usa para:
- Descargar su configuración: el período de medición, los umbrales de alarma, el servidor al que reportar.
- Consultar comandos pendientes: «abrir la válvula 10 minutos», «reiniciar», «actualizar el firmware».
- Obtener la hora, con la cabecera
Datede la respuesta, para validar certificados y poner marcas de tiempo. - Comprobar si hay una versión de firmware nueva (tema 43).
Los parámetros de un GET viajan en la URL, después del signo de interrogación, como pares nombre=valor separados por &. Como una URL solo admite ciertos caracteres, los demás (espacios, tildes, :, /) se codifican con porcentaje: cada byte se escribe como %XX con su valor en hexadecimal. El espacio se escribe %20 o +, y la «á» (dos bytes en UTF-8) es %C3%A1. Por eso cámara 07 se transmite como c%C3%A1mara+07. Un firmware serio no arma las URL concatenando cadenas a mano: usa una función de codificación, o se limita a parámetros de caracteres simples.
Tres cuidados con GET:
- Nada sensible en la URL. Las URL se guardan en registros de servidores, de proxies y de navegadores. Un token o una clave en la URL queda escrito en texto en muchos lugares. Las credenciales van en la cabecera
Authorization. - Longitud acotada. Las URL muy largas (más de unos 2000 caracteres) son rechazadas por muchos servidores y consumen memoria. Para enviar datos, no se usa GET.
- Sin efectos. Un GET nunca debe cambiar el estado del servidor: puede ser repetido, precargado o reintentado automáticamente por un intermediario. «Marcar un comando como ejecutado» no es un GET.
03 · Enviar
POST: enviar
POST envía datos al servidor en el cuerpo de la petición, para que los procese: típicamente, para crear un recurso nuevo (una lectura). El formato del cuerpo se declara con Content-Type, que en IoT es casi siempre application/json (el tema 21 se ocupa de JSON). A diferencia del GET, el cuerpo no tiene el límite de longitud de la URL y los datos no quedan escritos en los registros de direcciones.
POST no es idempotente: enviar dos veces la misma petición puede crear dos recursos. Y en un dispositivo, los duplicados son inevitables, porque cuando se pierde una respuesta el firmware no sabe si el servidor recibió el dato y, ante la duda, reenvía (tema 18). Las dos soluciones habituales son:
- Un identificador en el mensaje (el dispositivo y un número de secuencia, o la marca de tiempo de la medición): el servidor descarta lo que ya tiene.
- Un método idempotente como PUT sobre una ruta que incluya el identificador (
PUT /api/v1/dispositivos/c07/lecturas/1794061920): repetirlo reemplaza el mismo recurso y no crea otro.
La respuesta de un POST también merece diseño. Lo habitual es 201 Created o 200 OK. Para ahorrar bytes, un 204 No Content (sin cuerpo) alcanza si el dispositivo solo necesita saber que llegó. Y, como veremos enseguida, el cuerpo de la respuesta puede aprovecharse para llevar al dispositivo información útil.
| Tarea | Método | Dónde van los datos | ¿Se puede reintentar? |
|---|---|---|---|
| Enviar una lectura | POST | Cuerpo (JSON) | Sí, si la lectura lleva identificador |
| Descargar la configuración | GET | Respuesta; parámetros en la URL | Sí, siempre |
| Consultar comandos pendientes | GET | Respuesta | Sí, siempre |
| Informar el resultado de un comando | PUT (o POST con identificador) | Cuerpo | Sí, es idempotente |
| Reportar una alarma | POST | Cuerpo | Sí, con identificador de evento |
| Obtener la hora del servidor | GET (o HEAD) | Cabecera Date de la respuesta | Sí, siempre |
04 · Diseño de la interfaz
Diseñar las rutas desde el dispositivo
La interfaz del servidor suele diseñarla alguien pensando en navegadores y aplicaciones. Un dispositivo tiene otras prioridades: memoria escasa, tráfico caro y mucha menos capacidad de adaptación. Algunas reglas para que la interfaz sea «amable con el firmware»:
- Rutas por recurso y con versión:
POST /api/v1/dispositivos/c07/lecturas,GET /api/v1/dispositivos/c07/configuracion. La versión permite evolucionar sin romper a los equipos instalados, que no se actualizan todos a la vez. - Respuestas mínimas: devolver solo los campos que el dispositivo usa, con nombres cortos, y un
204cuando no hay nada que decir. Un servidor que devuelve 5 KB de JSON cuando el dispositivo lee 3 campos obliga al firmware a recibirlos, guardarlos y descartarlos. - Un solo lugar para la configuración: un recurso que reúna todos los parámetros del dispositivo, con un número de versión, en lugar de diez rutas para diez parámetros.
- Errores comprensibles: el código correcto (tema 19) y, en el cuerpo, un mensaje breve y un código propio para que el firmware registre el motivo.
- Tolerancia: el servidor acepta campos que no conoce y completa con valores por defecto los que faltan, para convivir con dispositivos de distintas versiones.
El efecto de estas reglas se acumula: una respuesta de 300 bytes en lugar de 3000 multiplicada por 96 consultas diarias de 10.000 equipos es la diferencia entre 288 MB y 2,9 GB diarios de tráfico solo para la configuración.
05 · No repetir lo que no cambió
Preguntar sin repetir: consultas condicionales
La configuración de un dispositivo cambia pocas veces: tal vez dos por día, tal vez dos por mes. Si el dispositivo la descarga completa cada vez que pregunta, casi todas las respuestas repiten lo que ya tiene. HTTP resuelve esto con las consultas condicionales.
El mecanismo es simple. Cuando el servidor entrega un recurso, agrega una cabecera ETag con una huella o un número de versión (ETag: "v17"). El dispositivo la guarda. En la próxima consulta envía If-None-Match: "v17", que significa «dame el recurso solo si ya no es el v17». Si no cambió, el servidor responde 304 Not Modified, sin cuerpo y con unos pocos bytes. Si cambió, responde 200 con la versión nueva y un ETag nuevo.
Cuando el servidor no soporta ETag, se logra lo mismo con una convención propia: una consulta con la versión que el dispositivo tiene (GET /configuracion?version=17) y una respuesta 204 No Content si no hay nada nuevo, o el recurso completo si lo hay. Lo importante es la idea: el dispositivo dice qué versión tiene y el servidor contesta solo la diferencia.
Pero atención con las expectativas: una consulta condicional ahorra los bytes de la respuesta, y en una conexión nueva esos bytes son una fracción pequeña del total. El apretón de manos de TLS (unos 4700 bytes en el modelo del tema 17) pesa mucho más que una configuración de 300 bytes. La consulta condicional rinde de verdad cuando la conexión se reutiliza, o cuando la respuesta es grande. El laboratorio de este tema lo muestra con números.
06 · El costo de preguntar
Polling: cuánto cuesta preguntar
Como el servidor no puede avisar al dispositivo, la solución más simple es que éste pregunte cada cierto tiempo: es el polling. Su diseño es un compromiso con tres puntas: latencia (cuánto tarda el dispositivo en enterarse), energía (cada pregunta enciende la radio) y datos (cada pregunta mueve bytes). Si el dispositivo pregunta cada T segundos, un cambio en el servidor tarda en llegar, en promedio, T/2, y como máximo T.
Con una conexión nueva en cada consulta (lo normal en un dispositivo con batería), el costo es alto y se ve en las cuentas: cada 60 segundos son 1440 consultas por día, y en el modelo gastan 24 mAh diarios; una batería de 2000 mAh dura 83 días. Cada 5 minutos, la batería rinde más de un año, pero un comando urgente puede tardar hasta 5 minutos. Y la alternativa de mantener la conexión abierta para consultar más barato deja la radio encendida todo el día: 480 mAh por día, cuatro días de batería.
Hay tres maneras de mejorar la situación sin cambiar de protocolo:
- Combinar el envío y la consulta. El dispositivo ya se conecta cada tanto para enviar sus lecturas. Si la respuesta del POST lleva los comandos pendientes y la versión de la configuración, no hace falta un GET aparte: una sola conexión hace las dos cosas. Es la técnica más rentable y casi gratuita.
- Preguntar al despertar. Un dispositivo que duerme y se despierta cada 15 minutos para medir puede aprovechar ese despertar para enviar y recibir. Su latencia de comando es el período de sueño, y no consume nada más.
- Pasar a un canal persistente si hace falta respuesta rápida: MQTT o WebSocket (bloques siguientes) mantienen una conexión abierta por la que el servidor puede empujar el comando al instante. Con alimentación eléctrica son económicos; con batería, siguen costando el mantener la conexión.
La idea de «llevar el comando en la respuesta» tiene un precio de diseño: el servidor tiene que tener listos los comandos pendientes en el momento en que llega el POST, y el dispositivo debe tratar la respuesta como un mensaje que puede traer instrucciones, validándolas y confirmando su ejecución en el próximo envío. A cambio, convierte cada envío en una oportunidad gratuita de recibir órdenes.
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
String etagConfig = ""; // versión de la configuración que ya tenemos
// GET condicional: devuelve 1 si hay configuración nueva, 0 si no cambió, -1 si falló.
int pedirConfiguracion(WiFiClientSecure &cliente, String &cuerpoNuevo) {
HTTPClient http;
http.setTimeout(5000);
http.begin(cliente, "https://datos.ejemplo.com/api/v1/dispositivos/c07/configuracion");
http.addHeader("Authorization", String("Bearer ") + TOKEN_DISPOSITIVO);
if (etagConfig.length()) http.addHeader("If-None-Match", etagConfig); // "dame solo si cambió"
const char *cabecerasAGuardar[] = {"ETag"};
http.collectHeaders(cabecerasAGuardar, 1); // pedir a la biblioteca que recuerde esta cabecera
int codigo = http.GET();
int resultado = -1;
if (codigo == 304) {
resultado = 0; // sin cambios: no se descargó nada
} else if (codigo == 200) {
cuerpoNuevo = http.getString(); // configuración chica (unos 300 bytes)
etagConfig = http.header("ETag"); // recordar la versión
resultado = 1;
}
http.end();
return resultado;
}
El fragmento muestra el patrón: el dispositivo recuerda la ETag en una variable (guardada en memoria no volátil para sobrevivir a los reinicios) y la manda en cada consulta. Si el servidor responde 304, el firmware sigue con lo que tiene sin descargar ni procesar nada.
07 · Analogía con programación
Calcular el costo del polling en Python
El programa modela un dispositivo que consulta su configuración cada cierto intervalo. Una consulta cuesta 150 bytes de petición (32 más si es condicional), y la respuesta es de 420 bytes si trae la configuración o de 95 si es un 304. La configuración cambia dos veces por día. Con una conexión nueva, cada consulta paga además 4700 bytes de apretón de manos TCP y TLS 1.3 y 0,6 s de radio; con una conexión reutilizada paga solo 0,1 s, pero la radio queda atenta todo el día (480 mAh por día). Al final muestra cómo se codifican los parámetros de un GET.
Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.
BATERIA_MAH = 2000
SUENO_MAH_DIA = 0.24
CORRIENTE_MA = 100 # radio activa
RADIO_ATENTA_MAH_DIA = 480 # mantener la conexión abierta: 20 mA durante 24 h
PETICION_B = 150 # GET con cabeceras mínimas
CONDICIONAL_B = 32 # cabecera If-None-Match con la versión que el dispositivo ya tiene
RESPUESTA_200_B = 420 # cabeceras y 300 bytes de configuración
RESPUESTA_304_B = 95 # "no cambió": solo cabeceras
HANDSHAKE_B = 4700 # TCP + TLS 1.3 de una conexión nueva
CONSULTA_NUEVA_S = 0.6 # 3 viajes de 100 ms + 300 ms de cálculo de cifrado
CONSULTA_REUTILIZADA_S = 0.1 # un solo viaje
CAMBIOS_POR_DIA = 2 # veces que la configuración cambia de verdad
def evaluar(intervalo_s, conexion, condicional):
consultas = 86400 / intervalo_s
cambios = min(CAMBIOS_POR_DIA, consultas)
if condicional:
bytes_dia = consultas * (PETICION_B + CONDICIONAL_B) + (consultas - cambios) * RESPUESTA_304_B + cambios * RESPUESTA_200_B
else:
bytes_dia = consultas * (PETICION_B + RESPUESTA_200_B)
if conexion == "nueva":
bytes_dia += consultas * HANDSHAKE_B
mah_dia = SUENO_MAH_DIA + consultas * CORRIENTE_MA * CONSULTA_NUEVA_S / 3600
else:
mah_dia = RADIO_ATENTA_MAH_DIA + consultas * CORRIENTE_MA * CONSULTA_REUTILIZADA_S / 3600
return consultas, bytes_dia, mah_dia, BATERIA_MAH / mah_dia
print("intervalo conexión condicional consultas/día MB/mes mAh/día batería demora media")
for intervalo in (10, 60, 300):
for conexion in ("nueva", "reutilizada"):
for condicional in (False, True):
c, b, mah, dias = evaluar(intervalo, conexion, condicional)
bat = f"{dias / 365:.1f} años" if dias >= 365 else f"{dias:.0f} días"
print(f"{intervalo:>6} s {conexion:<12} {'sí' if condicional else 'no':<11} {c:>13.0f} {b * 30 / 1e6:>8.1f} {mah:>9.2f} {bat:<13} {intervalo / 2:>6.0f} s")
# Cómo viajan los parámetros de un GET: se codifican con %XX para que la URL sea válida
from urllib.parse import urlencode
consulta = urlencode({"dispositivo": "cámara 07", "desde": "2026-11-07T14:32:00Z", "max": 50})
print()
print("GET /api/v1/lecturas?" + consulta)
Resultado con los valores iniciales. Consultando cada 10 segundos con conexión nueva: 8640 consultas por día, 1366 MB por mes, 144 mAh por día y 14 días de batería; con consulta condicional baja apenas a 1290 MB. Con la conexión reutilizada y condicional, los datos caen a 72 MB al mes, pero el consumo es de 504 mAh por día (4 días). Cada 60 segundos: con conexión nueva, 228 MB por mes (215 con condicional), 24,2 mAh por día y 83 días; reutilizada, 25 MB (12 con condicional) y 4 días. Cada 5 minutos: con conexión nueva, 46 MB (43), 5,04 mAh por día y 1,1 años, con una demora media de 150 s. Los parámetros dispositivo=cámara 07 y desde=2026-11-07T14:32:00Z se transmiten como dispositivo=c%C3%A1mara+07&desde=2026-11-07T14%3A32%3A00Z.
Tres lecciones. Una: con batería, el intervalo de consulta manda sobre todo lo demás: de 10 segundos a 5 minutos, la autonomía pasa de dos semanas a más de un año. Otra: la consulta condicional ahorra bytes de respuesta, no de apretón de manos: en una conexión nueva solo reduce el tráfico un 6 %. Y una más: mantener la conexión abierta baja los datos 9 veces pero vacía la batería; es una solución para equipos conectados a la red eléctrica.
08 · Exploración interactiva
¿Cada cuánto pregunto?, de extremo a extremo
Este laboratorio ejecuta el mismo modelo del código anterior. Elegí cada cuánto consulta el dispositivo, si abre una conexión nueva o reutiliza una abierta y si la consulta es condicional. Las barras comparan las cuatro combinaciones con el mismo intervalo: a la izquierda los datos por mes y a la derecha la duración de la batería (las barras rojas duran menos de un año). Los costos son valores didácticos.
Polling de la configuración
Elegí los parámetros y presioná «Calcular».
Recorrido guiado
- Con los valores iniciales (cada 60 segundos, conexión nueva, sin condicional), calculá. 1440 consultas por día, 228 MB al mes, 24,24 mAh por día y 83 días de batería: «Gasta demasiado». La demora media es de 30 s.
- Activá la consulta condicional: 215 MB al mes. Solo un 6 % menos. Cada consulta paga 4700 bytes de apretón de manos para recibir unos 95 de «no cambió».
- Subí el intervalo a 5 minutos: 288 consultas, 5,04 mAh por día y 1,1 años: «Viable con batería». A cambio, un comando tarda en promedio 150 s en llegar y hasta 300 s.
- Probá 10 segundos con conexión nueva: 144 mAh por día y 14 días. Una latencia de 5 segundos cuesta 28 veces más energía que una de 2,5 minutos.
- Cambiá a Reutilizada con 60 segundos: los datos caen a 25 MB al mes (12 con condicional), pero el consumo sube a 484 mAh por día y la batería dura 4 días: «Solo con alimentación eléctrica».
- Con Reutilizada, condicional y 10 segundos: solo 72 MB al mes para una latencia media de 5 s, la mejor relación entre datos y respuesta. Es una buena configuración para un equipo enchufado, y una pésima para uno con pila.
Desafío: combinar el envío con la consulta
Un dispositivo envía su lectura cada 15 minutos (96 POST por día) y consulta la configuración con la misma frecuencia (96 GET por día), cada uno con su conexión nueva a 0,0167 mAh (modelo del laboratorio). Con dos conexiones: 192 × 0,0167 = 3,2 mAh por día. Si la respuesta del POST trae la configuración o la indicación de que no cambió, el GET desaparece: 96 × 0,0167 = 1,6 mAh por día, la mitad. La latencia para recibir un comando es igual (hasta 15 minutos) pero con la mitad de energía y de tráfico. Lo que queda por resolver es del lado del servidor: guardar los comandos pendientes hasta que el dispositivo se conecte, y descartarlos cuando vencen (tema 11). No hay consulta más barata que la que no se hace.
09 · Método de trabajo
Cómo diseñar el diálogo con el servidor
- Listá qué cuenta y qué pregunta el dispositivo, y asignale a cada cosa su método: POST para lo que envía, GET para lo que lee, PUT para fijar un estado.
- Calculá la latencia aceptable de los comandos: cuánto puede tardar un cambio en llegar. De eso sale el intervalo de consulta.
- Combiná envío y consulta: que la respuesta del POST lleve la configuración o los comandos pendientes.
- Usá consultas condicionales (ETag o versión explícita), sobre todo si la conexión se reutiliza o la respuesta es grande.
- Diseñá la interfaz para el firmware: rutas por recurso y con versión, respuestas mínimas, un recurso único de configuración.
- Garantizá la idempotencia de lo que se puede reenviar: identificadores en las lecturas, PUT para estados.
- Cuidá la URL: sin secretos, con parámetros codificados y de largo acotado.
- Calculá el costo de toda la flota (bytes y mAh por día) y comparalo con el presupuesto antes de fijar los intervalos.
Si después de estos pasos la latencia exigida sigue siendo incompatible con la batería disponible, no hay truco de HTTP que lo resuelva: es la señal para pasar a un protocolo con conexión persistente y publicación y suscripción, que empezamos a ver en el bloque 5.
10 · Comprensión
Confusiones frecuentes
«Puedo mandar los datos en la URL con un GET, que es más simple»
Funciona para valores chicos, pero la URL queda escrita en registros, tiene un largo máximo y un GET no debe tener efectos sobre el servidor. Los datos que se envían van por POST (o PUT), en el cuerpo.
«Con una consulta condicional, preguntar cada pocos segundos es barato»
Ahorra los bytes de la respuesta, no el costo de abrir la conexión ni el de mantener la radio encendida. Con batería, preguntar seguido sigue siendo caro aunque la respuesta sea un 304.
«Si el servidor tiene un comando urgente, lo envía al dispositivo»
No puede: el dispositivo está detrás de un NAT y solo recibe respuestas a conexiones que él abrió. El comando espera hasta la próxima consulta, o hay que mantener una conexión persistente.
«Un POST repetido es inofensivo»
No: crea el recurso otra vez. Los reintentos de un dispositivo son normales, así que el cuerpo lleva un identificador para que el servidor descarte duplicados, o se usa PUT sobre un recurso con identificador.
«Los parámetros de la URL se pueden concatenar a mano»
Un espacio, una tilde o un símbolo sin codificar pueden romper la URL o alterar su significado, y abrir la puerta a errores y ataques de inyección. Se usa una función de codificación, o se restringen los valores a caracteres seguros.
«Mantener la conexión abierta es la solución al polling»
Lo es para equipos con alimentación eléctrica. Con batería, la radio atenta cuesta cientos de mAh por día y deja el equipo sin energía en días. Hay que elegir según la fuente de energía.
11 · Práctica guiada
Predecí antes de comprobar
1. Elegir el método
Indicá GET, POST o PUT para: (a) obtener la hora del servidor; (b) enviar una lectura nueva; (c) informar que un comando se ejecutó, con identificador de comando; (d) descargar la configuración; (e) reportar una alarma.
Ver solución
(a) GET (la hora viene en la cabecera Date). (b) POST, con identificador en el cuerpo. (c) PUT sobre /comandos/{id}/resultado: idempotente, se puede reenviar. (d) GET, preferentemente condicional. (e) POST, con identificador del evento.
2. Codificar una URL
Armá la consulta con dispositivo=cámara 07 y max=50. ¿Cómo se escribe cada carácter especial?
Ver solución
La «á» ocupa dos bytes en UTF-8 y se escribe %C3%A1; el espacio, + (o %20). Resulta dispositivo=c%C3%A1mara+07&max=50. Los dos puntos de una hora (14:32) se escriben %3A.
3. El costo de preguntar
Con conexión nueva en cada consulta, el modelo da 24,24 mAh por día consultando cada 60 s y 5,04 cada 5 minutos. ¿Cuánto dura una batería de 2000 mAh en cada caso y cuál es la demora promedio de un comando?
Ver solución
60 s: 2000 / 24,24 ≈ 83 días, demora media 30 s. 5 minutos: 2000 / 5,04 ≈ 397 días, 1,1 años, demora media 150 s. Cinco veces menos consultas: casi cinco veces más batería a cambio de cinco veces más demora.
4. Ahorrar una conexión
Un dispositivo envía una lectura y consulta su configuración cada 15 minutos, cada una con conexión nueva de 0,0167 mAh. ¿Cuánto ahorra si el POST devuelve la configuración?
Ver solución
Separadas: 2 × 96 × 0,0167 = 3,2 mAh por día. Combinadas: 96 × 0,0167 = 1,6 mAh por día. Ahorra la mitad de energía y de tráfico, con la misma latencia de comandos.
5. ETag y 304
Una consulta pide la configuración completa (420 bytes de respuesta) y una condicional recibe un 304 (95 bytes, más 32 de la cabecera). ¿Cuánto ahorra por consulta si no hay apretón de manos? ¿Y con apretón de 4700 bytes?
Ver solución
Sin apretón: sin condicional, 150 + 420 = 570 bytes; con condicional, 150 + 32 + 95 = 277: ahorra 293 bytes, el 51 %. Con apretón: 5270 contra 4977 bytes: ahorra el 5,6 %. La consulta condicional vale mucho en una conexión reutilizada y poco en una nueva.
6. Un secreto en la URL
Un firmware pide GET /api/config?token=abc123 por HTTPS. ¿Qué problema hay aunque la conexión esté cifrada y cómo se corrige?
Ver solución
HTTPS protege la URL en tránsito, pero el servidor, los proxies, los balanceadores y los registros de acceso la guardan en texto, y cualquiera con acceso a esos archivos obtiene el token. Se corrige enviando el token en la cabecera Authorization: Bearer …, que los registros normalmente no almacenan.
12 · Síntesis
Ideas para recordar
- El dispositivo cuenta con POST y pregunta con GET; como el servidor no puede iniciar la conversación, los cambios esperan a la próxima consulta.
- GET es seguro e idempotente y sus parámetros van en la URL, codificados con porcentaje; nunca lleva secretos ni datos para guardar.
- POST envía en el cuerpo y no es idempotente: las lecturas llevan identificador, o se usa PUT sobre un recurso con identificador.
- La interfaz se diseña para el firmware: rutas por recurso y con versión, respuestas mínimas, un recurso único de configuración y tolerancia a versiones.
- Las consultas condicionales (ETag y 304) evitan repetir lo que no cambió, pero solo ahorran los bytes de la respuesta, no los del apretón de manos.
- El polling es un compromiso entre latencia, energía y datos: un cambio tarda en promedio la mitad del intervalo, y con batería cada consulta enciende la radio.
- Con conexión nueva por consulta, bajar el intervalo de 5 minutos a 10 segundos pasa la batería de más de un año a dos semanas.
- Mantener la conexión abierta reduce los datos pero deja la radio atenta; solo conviene con alimentación eléctrica.
- La técnica más rentable es combinar: la respuesta del POST que envía las lecturas lleva la configuración y los comandos pendientes, y ahorra una conexión completa.
¿Listo para el tema 21?
Antes de avanzar, listá todas las interacciones de tu dispositivo con el servidor y asignale a cada una un método y una ruta. Calculá cuántas conexiones hace por día y cuáles se pueden combinar. Si podés llevar todo a una sola conexión por ciclo, ya diseñaste un diálogo eficiente.
En el próximo tema aprendemos JSON para intercambiar datos: cómo armar y leer mensajes JSON con poca memoria, tanto el cuerpo de los POST como las respuestas de configuración y comandos.