IFTS 14 2025 TS SEIC Protocolo de IoT
-
Clase 13 - 4/11/2025
-
Claro, vamos a explorar el protocolo CoAP (Constrained Application Protocol), un protocolo fundamental en el contexto de IoT, especialmente útil para redes con recursos limitados.
🧩 ¿Qué es CoAP?
CoAP (RFC 7252) es un protocolo de aplicación diseñado para dispositivos con recursos limitados, funcionando sobre UDP en lugar de TCP. Es comparable a HTTP, pero optimizado para el entorno IoT.
🔧 Características principales:
-
Usa UDP, por lo tanto es ligero y rápido.
-
Basado en el modelo cliente-servidor.
-
Soporta operaciones tipo REST:
GET
,POST
,PUT
,DELETE
. -
Puede usar confirmaciones y reintentos para asegurar entrega (similar a QoS).
-
Diseñado para funcionar incluso en redes intermitentes y de baja potencia.
-
Soporte para observación de recursos (push, notificación).
📦 Estructura de un mensaje CoAP
Un mensaje CoAP está compuesto por un encabezado fijo seguido de posibles campos opcionales, token, opciones y carga útil.
✉️ Formato básico (Header de 4 bytes):
Byte(s) Campo Detalle 1 Versión (2 bits) Siempre "01" para CoAP 1.0 Tipo (2 bits) Confirmable, No confirmable, ACK, Reset Token Length (4 bits) Longitud del campo token 2 Código (8 bits) Ej: 0.01 = GET, 0.02 = POST 3-4 Message ID (16 bits) Para emparejar mensajes y respuestas Luego se incluye:
-
Token: identificador de solicitud/respuesta.
-
Opciones: URI, formato de contenido, etc.
-
Payload: datos en texto o binario, precedido por
0xFF
.
🧪 Ejemplo práctico básico: Sensor de temperatura
Escenario: Un ESP32 con sensor DHT22 publica la temperatura a un servidor CoAP.
📍 Cliente (ESP32) envía:
POST coap://192.168.1.100/sensor/temp Payload: {"valor": 23.5}
🖥️ Servidor CoAP recibe:
-
Tipo: Confirmable (CON)
-
Código: 0.02 (POST)
-
URI-Path:
sensor/temp
-
Payload:
{"valor": 23.5}
El servidor podría responder con:
-
Tipo: Acknowledgement (ACK)
-
Código: 2.01 (Created)
🛠️ Aplicación con Python y
aiocoap
from aiocoap import * import asyncio async def main(): context = await Context.create_client_context() request = Message(code=POST, uri='coap://192.168.1.100/sensor/temp', payload=b'{"valor":23.5}') response = await context.request(request).response print('Respuesta:', response.code, response.payload) asyncio.run(main())
📚 ¿Dónde se usa CoAP?
-
Redes 6LoWPAN (IPv6 sobre redes personales de bajo consumo).
-
Sistemas con contiki-ng, RIOT OS, ESP-IDF con libcoap.
-
Dispositivos que deben funcionar en redes sin Wi-Fi ni Internet.
-
Aplicaciones en salud, agricultura, ciudades inteligentes.
✅ Ventajas vs MQTT
Característica CoAP MQTT Transporte UDP TCP Modelo Cliente-Servidor (REST) Publicador-Suscriptor Ligereza Muy alto Alta Soporte HTTP Compatible No nativamente Ideal para Comunicación punto a punto, comandos Eventos, streaming No, CoAP no necesita un broker de datos. A diferencia de MQTT, que es un protocolo basado en el modelo publicador/suscriptor y requiere un broker (como Mosquitto, EMQX, HiveMQ, etc.) para enrutar los mensajes entre clientes, CoAP está basado en un modelo cliente-servidor directo, muy similar a HTTP.
🔍 Comparación directa:
Característica MQTT CoAP Modelo Publicador / Suscriptor Cliente / Servidor Requiere broker ✅ Sí ❌ No Protocolo subyacente TCP (normalmente) o WebSocket UDP Estilo de comunicación Asíncrono Síncrono (aunque soporta notificación) Direccionamiento Tópicos URLs / URIs Ideal para Grandes redes con centralización Comunicación directa entre nodos
📌 En CoAP, el cliente se comunica directamente con el servidor.
Por ejemplo:
-
El nodo A (cliente) envía un
GET
al nodo B (servidor) para leer/sensor/temp
. -
El nodo B responde directamente, sin intermediarios.
🟢 CoAP con Observe (modo "push")
CoAP incluye una extensión opcional llamada Observe, que permite a un cliente "suscribirse" a cambios en un recurso. En este caso, el servidor envía actualizaciones automáticamente cuando hay cambios. Pero sigue sin haber un broker, el servidor gestiona las notificaciones.
Si deseas implementar una red IoT distribuida sin depender de infraestructura central (como un broker), CoAP es una excelente opción por su simplicidad y eficiencia para redes locales o entre nodos de baja potencia.
¡Perfecto! A continuación te muestro un ejemplo completo de cómo montar un sistema simple de comunicación CoAP entre un servidor en una Raspberry Pi (usando Python con
aiocoap
) y un cliente en ESP32 (usando Arduino IDE con la libreríaCoAP-simple-library
). Este sistema simula un sensor que envía datos de temperatura desde el ESP32 al servidor CoAP en la Raspberry Pi.
🖥️ Parte 1: Servidor CoAP en Raspberry Pi (Python)
🔧 Requisitos
sudo apt update sudo apt install python3-pip pip3 install aiocoap[all]
📄 Código:
coap_server.py
import asyncio from aiocoap import * class TemperatureResource(resource.Resource): def __init__(self): super().__init__() self.set_content(b"Sin datos") async def render_post(self, request): print("Dato recibido:", request.payload.decode()) self.set_content(request.payload) return Message(code=CHANGED, payload=b"Dato recibido correctamente") def set_content(self, data): self.content = data async def render_get(self, request): return Message(payload=self.content) def main(): root = resource.Site() root.add_resource(['sensor', 'temperatura'], TemperatureResource()) asyncio.Task(Context.create_server_context(root)) print("Servidor CoAP iniciado en puerto 5683") asyncio.get_event_loop().run_forever() if __name__ == "__main__": main()
▶️ Ejecución
python3 coap_server.py
📡 Parte 2: Cliente CoAP en ESP32 (Arduino IDE)
🔧 Requisitos
-
Arduino IDE
-
Placa ESP32 instalada
-
Librería CoAP-simple-library
Instálala manualmente desde ZIP en el menú:
Sketch > Include Library > Add .ZIP Library
📄 Código: Cliente ESP32
#include <WiFi.h> #include <CoapSimple.h> const char* ssid = "NOMBRE_WIFI"; const char* password = "CONTRASEÑA_WIFI"; const char* coapServer = "192.168.1.100"; // IP de tu Raspberry Pi Coap coap(coapServer, 5683); void setup() { Serial.begin(115200); WiFi.begin(ssid, password); Serial.print("Conectando"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Conectado a WiFi"); } void loop() { String temperatura = "24.7"; // Simula un valor de sensor Serial.println("Enviando temperatura: " + temperatura); coap.post("/sensor/temperatura", temperatura.c_str()); delay(10000); // Espera 10 segundos antes del próximo envío }
🔁 Comunicación esperada
-
El ESP32 conecta al WiFi y cada 10 segundos hace un
POST
al recurso/sensor/temperatura
. -
El servidor en la Raspberry Pi imprime los datos recibidos.
-
También podrías usar otro cliente CoAP (como
coap-client
desde Linux) para hacer unGET
al servidor y ver el último valor recibido.
✅ Pruebas útiles desde Raspberry Pi
sudo apt install libcoap2-bin coap-client -m get coap://localhost/sensor/temperatura
🔒 Notas de seguridad
-
CoAP puede funcionar sobre DTLS para cifrado (no cubierto aquí, pero es posible).
-
Si estás en una red abierta o insegura, evita mandar datos sensibles sin cifrado.
Se puede agregar cómo visualizar los datos en un dashboard como ThingsBoard o Node-RED.
La cabecera HTTP (HTTP header) es una parte esencial de las solicitudes y respuestas HTTP. Contiene metadatos que indican al servidor o cliente cómo debe interpretarse el contenido, establecer conexiones, autenticarse, controlar el caché, entre otros.
🧱 Estructura de la Cabecera HTTP
🔹 1. Línea de inicio
-
Para solicitudes HTTP (cliente → servidor):
GET /index.html HTTP/1.1
-
GET
: método HTTP -
/index.html
: recurso solicitado -
HTTP/1.1
: versión del protocolo
-
-
Para respuestas HTTP (servidor → cliente):
HTTP/1.1 200 OK
-
200 OK
: código de estado y mensaje
-
🔹 2. Encabezados generales (headers)
Los encabezados están en formato
clave: valor
y pueden incluir:Encabezado Descripción Host
Dominio del servidor ( Host: www.example.com
)Content-Type
Tipo de contenido ( application/json
,text/html
)Content-Length
Tamaño del cuerpo del mensaje (en bytes) User-Agent
Info del cliente que hace la solicitud Accept
Tipos MIME que el cliente acepta Authorization
Autenticación básica o tokens Cache-Control
Instrucciones de caché Connection
Mantener o cerrar la conexión ( keep-alive
,close
)Date
Fecha y hora del mensaje Server
Info sobre el servidor web usado Set-Cookie
Define cookies que se almacenarán en el cliente
🔹 3. Línea en blanco
Una línea vacía marca el fin de los encabezados y el inicio del cuerpo del mensaje (payload), si lo hay.
🔹 4. Cuerpo del mensaje (opcional)
Solo presente en métodos como
POST
,PUT
, etc.
📦 Ejemplo de solicitud HTTP (cliente → servidor)
POST /api/sensores HTTP/1.1 Host: iot.servidor.com Content-Type: application/json Content-Length: 33 {"temp":25.3,"humedad":40.1}
📤 Ejemplo de respuesta HTTP (servidor → cliente)
HTTP/1.1 201 Created Content-Type: application/json Content-Length: 28 {"estado":"dato recibido"}
Perfecto. Aquí tenés una comparación entre las cabeceras de HTTP y CoAP, mostrando cómo difieren en tamaño, estructura y propósito, especialmente pensadas para aplicaciones IoT donde los recursos suelen ser limitados.
🔄 Comparativa: Cabeceras HTTP vs CoAP
Característica HTTP CoAP (Constrained Application Protocol) Protocolo base TCP (normalmente en puerto 80 o 443) UDP (por defecto en puerto 5683) Tamaño de cabecera Grande (al menos 200-800 bytes típicos) Muy pequeña (4 bytes mínimos + opciones) Formato Texto (legible para humanos) Binario compacto (eficiente para máquina) Métodos GET, POST, PUT, DELETE, etc. GET, POST, PUT, DELETE (idénticos) Encabezado inicial Línea de solicitud ( GET / HTTP/1.1
)Código compacto (ex: 0x41
→ Confirmable GET)Encabezados comunes Host, User-Agent, Content-Type, etc. Opciones binarias como Uri-Path, Content-Format Cuerpo del mensaje Texto/JSON/XML, según Content-Type
Igual, pero opcional y en binario o texto Seguridad TLS (HTTPS) DTLS (Datagram TLS) o certificados LwM2M/OSCORE Extensiones WebSockets, HTTP/2, etc. Observe (subscripción), Blockwise, etc.
📦 Ejemplo de cabecera HTTP
POST /sensor HTTP/1.1 Host: myiotserver.com Content-Type: application/json Content-Length: 29 {"temp":22.5,"hum":40.0}
Tamaño total típico: ~250 bytes
🧱 Ejemplo de trama CoAP equivalente (resumido):
-
Cabecera fija (4 bytes):
-
Version: 1
-
Tipo: Confirmable (0b00)
-
Código: 0.02 (POST)
-
Message ID: 0x1234
-
-
Opciones (Uri-Path, Content-Format): 10–20 bytes
-
Payload:
{"temp":22.5,"hum":40.0}
(igual)
Tamaño total típico: ~40–60 bytes
🎯 Conclusión
Uso recomendado Protocolo Web, dashboards, apps móviles HTTP IoT embebido, sensores de baja potencia CoAP CoAP fue diseñado específicamente para ambientes IoT donde se necesita eficiencia en ancho de banda, bajo consumo y comunicación en redes ruidosas o intermitentes.
Perfecto. A continuación te presento un ejemplo concreto con valores numéricos donde se justifica el uso de CoAP en lugar de HTTP, tanto desde lo técnico como lo práctico.
🧪 Caso de Estudio: Red de sensores de temperatura y humedad en campo agrícola remoto
🟢 Escenario
-
100 nodos distribuidos en 50 hectáreas.
-
Cada nodo:
-
Sensor DHT22 (temperatura y humedad).
-
Microcontrolador ESP32 con radio LoRa.
-
Envío de datos cada 5 minutos.
-
-
No hay acceso a WiFi ni 4G.
-
Los datos son enviados a un Gateway LoRa + Raspberry Pi que actúa como servidor y concentrador de datos.
-
El Gateway guarda los datos y los reenvía a la nube cuando tiene conectividad.
📊 Comparación: HTTP vs CoAP
✅ Con HTTP:
-
Cada envío genera una solicitud POST como esta:
POST /data HTTP/1.1 Host: gateway.local Content-Type: application/json Content-Length: 32 {"temp":21.8,"hum":56.2,"id":12}
-
Tamaño estimado del paquete completo (con encabezado TCP/IP + HTTP):
-
HTTP: ~350 bytes por transmisión.
-
Con 100 nodos → 100 × 350 = 35,000 bytes cada 5 minutos
-
Consumo energético: mayor, por handshake TCP + latencia.
-
LoRa no es compatible con TCP sin túneles o capas adicionales.
-
✅ Con CoAP:
-
Se envía un paquete UDP-CoAP con los siguientes campos:
-
Header de 4 bytes
-
Opciones Uri-Path (
/data
, ~6 bytes), Content-Format -
Payload:
{"temp":21.8,"hum":56.2,"id":12}
(~30 bytes)
-
-
Total estimado: ~55 bytes por mensaje
-
100 nodos → 100 × 55 = 5,500 bytes cada 5 minutos
-
Consumo energético: mucho menor
-
Compatible con LoRa (basado en UDP, no requiere handshake)
📉 Reducción de carga y consumo
Métrica HTTP CoAP Tamaño por nodo ~350 bytes ~55 bytes Total por 5 min (100 nodos) ~35 KB ~5.5 KB Reintentos por pérdida Costoso (TCP handshake) Ligero (Confirmable + retransmisión) Energía consumida Alta Baja Compatibilidad con LoRa Pobre (requiere TCP tunneling) Nativa (UDP)
🎯 Conclusión del caso
En este escenario HTTP no es viable por el ancho de banda, el consumo energético y la incompatibilidad con LoRa sin complejidad adicional.
En cambio, CoAP permite:-
Envíos cortos y eficientes.
-
Funcionar sobre UDP directamente (ideal para LoRa).
-
Comunicación confirmable con reintentos ligeros.
-
Implementación simple en recursos limitados (ESP32, RPi).
-
-