El desarrollo de aplicaciones web modernas ha impulsado la necesidad de comunicación bidireccional y en tiempo real. WebSocket, estandarizado como RFC 6455, proporciona un canal de comunicación dúplex completo sobre una única conexión TCP, permitiendo que los navegadores interactúen con servidores de forma eficiente. En el ecosistema del Internet de las Cosas (IoT), esto facilita la integración del protocolo MQTT directamente en entornos web.
Selección de bibliotecas para JavaScript
Para trabajar con MQTT mediante WebSockets en el navegador o entornos Node.js, existen dos opciones principales:
- Paho JavaScript Client: Una implementación de la Fundación Eclipse. Aunque funcional, su desarrollo ha sido menos dinámico en comparación con alternativas modernas.
- MQTT.js: Es actualmente la biblioteca de referencia. Escrita íntegramente en JavaScript, ofrece soporte para Node.js, navegadores y entornos específicos como miniprogramas de WeChat. Es compatible con conexiones TCP, TLS y WebSockets.
Instalación de la biblioteca
Para proyectos basados en Node.js, la instalación se realiza mediante el gestor de paquetes npm:
npm install mqtt --save
En entornos de navegador, es posible utilizar un CDN para cargar la biblioteca directamente:
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
Configuración de la conexión
Para ilustrar el proceso, utilizaremos un servidor público de prueba. Los parámetros típicos de conexión para WebSockets suelen diferir de los puertos estándar de MQTT (1883/8883).
const identificador = `cliente_web_${Math.random().toString(36).slice(5)}`;
const urlServidor = 'ws://broker.emqx.io:8083/mqtt';
const opciones = {
keepalive: 45,
clientId: identificador,
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
reconnectPeriod: 2000,
connectTimeout: 15 * 1000,
will: {
topic: 'notificaciones/sistema',
payload: 'Cliente fuera de línea',
qos: 0,
retain: false
},
};
console.log('Iniciando conexión MQTT...');
const gestorMqtt = mqtt.connect(urlServidor, opciones);
gestorMqtt.on('error', (error) => {
console.error('Fallo en la conexión:', error);
gestorMqtt.end();
});
gestorMqtt.on('reconnect', () => {
console.log('Intentando reconexión...');
});
Estructura de la URL de conexión
La dirección de conexión se compone de varios elementos críticos: protocolo://host:puerto/ruta.
- Protocolo: Se debe especifciar
wspara conexiones estándar owsspara conexiones seguras sobre TLS. - Puerto: A diferencia de MQTT sobre TCP, no hay un puerto único estándar para WebSockets. Comúnmente se usa el 8083 para tráfico no cifrado y el 8084 para tráfico cifrado.
- Ruta (Path): La mayoría de los brokers MQTT requieren una ruta específica para las actualizaciones de protocolo WebSocket, usualmente
/mqtt. - Restricciones de seguridad: Si el sitio web se sirve bajo HTTPS, el navegador bloqueará cualquier intento de conexión vía
ws. En estos casos, es obligatorio el uso dewss.
Operaciones principales: Suscripción y Publicación
Debido a la naturaleza asíncrona de JavaScript, es fundamental esperar al evento de conexión antes de realizar operaciones.
Suscripción a canales
gestorMqtt.on('connect', () => {
console.log('Conexión establecida exitosamente');
gestorMqtt.subscribe('sensores/temperatura', { qos: 1 }, (err) => {
if (!err) {
console.log('Suscripción activa');
}
});
});
Envío y recepción de mensajes
// Publicar un mensaje
const cargaUtil = JSON.stringify({ valor: 24.5, unidad: 'C' });
gestorMqtt.publish('sensores/temperatura', cargaUtil, { qos: 0, retain: false });
// Escuchar mensajes entrantes
gestorMqtt.on('message', (tema, mensaje) => {
console.log(`Mensaje recibido en ${tema}: ${mensaje.toString()}`);
});
Seguridad mediante TLS/SSL
Para entornos de producción, el uso de wss es indispensable. Esto requiere la configuración de certificados válidos en el broker. Los certificados autofirmados suelen ser rechazados por los navegadores por motivos de seguridad.
Los requisitos básicos para una conexión segura incluyen:
- Un nombre de dominio vinculado a la dirección IP del servidor MQTT.
- Un certificado emitido por una Autoridad de Certificación (CA) de confianza.
- Uso del nombre de dominio (no la IP) en la URL de conexión para que el navegador pueda validar el certfiicado.
Configuración de Proxy Inverso con Nginx
Utilizar Nginx como terminación TLS y proxy inverso permite centralizar la gestión de certificados y reducir la carga computacional en el broker MQTT.
server {
listen 443 ssl;
server_name mqtt.ejemplo.com;
ssl_certificate /ruta/al/cert.pem;
ssl_certificate_key /ruta/al/key.pem;
location /mqtt {
proxy_pass http://backend_mqtt_emqx:8083;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}