Ir al contenido principal
Todas las coleccionesGuías de desarrollador
Agregar tiempo real usando MQTT + WebSockets
Agregar tiempo real usando MQTT + WebSockets

Construyendo un widget de Lienzo HTML para visualización de datos en tiempo real con MQTT y WebSockets

Santiago Pachon Robayo avatar
Escrito por Santiago Pachon Robayo
Actualizado hace más de 4 meses

MQTT sobre WebSockets se está estableciendo rápidamente como una tecnología crucial para aplicaciones IoT, proporcionando una forma fluida, eficiente y dinámica de interactuar con los datos IoT. Este protocolo facilita la comunicación de datos en tiempo real directamente a través de navegadores web, haciendo que IoT sea más accesible para un público más amplio.

En Ubidots, hemos integrado MQTT a través de WebSockets en nuestra infraestructura central, permitiendo la recuperación y el almacenamiento inmediatos de datos dentro de cualquier variable de JavaScript. A diferencia de otras tecnologías como Socket.io, donde podrías tener que esperar a que lleguen nuevos datos o escribir código adicional para obtener el valor más reciente, MQTT ofrece una instantánea inmediata del estado más reciente de la variable. Mantener una suscripción abierta permite a los usuarios recibir actualizaciones continuas en tiempo real sin necesidad de mecanismos de recuperación adicionales.

Esta guía demostrará cómo crear un widget de lienzo HTML que muestre datos de una variable en tiempo real, utilizando MQTT.js y WebSockets para actualizar un gráfico de medidor de la biblioteca Apache E-charts.

Importa las siguientes bibliotecas de terceros:

https://unpkg.com/mqtt/dist/mqtt.min.jshttps://fastly.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js

Crea el elemento HTML en el que se mostrarán los datos:

<div id="chart-container"></div>

Agrega estilo CSS al gráfico

* {
margin: 0;
padding: 0;
}
#chart-container {
position: relative;
height: 100vh;
overflow: hidden;
}

Agrega la lógica del widget utilizando el siguiente código JavaScript:

// Define the host to connect to the Ubidots MQTT broker
const host = 'wss://industrial.api.ubidots.com:8084/mqtt';

// Retrieve the token from the built-in library and use it as username to autheticate to the broker.
const username = ubidots.token;

// Define the device and variable labels
const deviceLabel = '<device_label>'; // Replace <device_label> with your device label
const variableLabel = '<variable_label>'; // Replace <variable_label> with your variable label

// Define the topic to subscribe to the last value of the variable
const topic = `/v1.6/devices/${deviceLabel}/${variableLabel}/lv`;

// Generate a random client ID
const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8);

// Define the connection options
const options = {
keepalive: 60,
clientId: clientId,
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
reconnectPeriod: 1000,
connectTimeout: 30 * 1000,
username: username,
will: {
topic: 'WillMsg',
payload: 'Connection Closed abnormally..!',
qos: 0,
retain: false
},
};

// Create an MQTT client instance
const client = mqtt.connect(host, options);

// Connect to the client
client.on("connect", function () {
console.log("Connected to broker");
client.subscribe(topic, function (err) {
if (!err) {
console.log(`Successfully subscribed to the topic: ${topic}`);
} else {
console.error("Subscription error:", err);
}
});
});

// Handle incoming messages from the broker and update the chart
client.on("message", function (topic, message) {
console.log(`Received message: ${message.toString()} on topic: ${topic}`);
const formattedValue = parseFloat(message.toString()).toFixed(2);
const newValue = parseFloat(formattedValue);
if (!isNaN(newValue)) {
myChart.setOption({
series: [
{
data: [
{
value: newValue,
name: "Variable name",
},
],
},
],
});
}
});

// Handle errors and connection close events
client.on('error', function(err) {
console.error('Connection error:', err);
document.getElementById('status').textContent = 'Connection Error!';
});

client.on('close', function() {
console.log('Connection closed');
document.getElementById('status').textContent = 'Connection Closed';
});

// Initialize the Apache e-chart
let dom = document.getElementById('chart-container');
let myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});

// Set the chart options
let option = {
series: [{
type: 'gauge',
center: ['50%', '50%'],
radius: '75%',
startAngle: 200,
endAngle: -20,
min: 0,
max: 60,
splitNumber: 12,
itemStyle: {
color: '#FFAB91'
},
progress: {
show: true,
width: 30
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 30
}
},
axisTick: {
distance: -45,
splitNumber: 5,
lineStyle: {
width: 2,
color: '#999'
}
},
splitLine: {
distance: -52,
length: 14,
lineStyle: {
width: 3,
color: '#999'
}
},
axisLabel: {
distance: -20,
color: '#999',
fontSize: 20
},
detail: {
valueAnimation: true,
offsetCenter: [0, '40%'],
fontWeight: 'bolder',
formatter: '{value} °C',
color: 'inherit'
},
data: [{
value: 20
}]
}]
};

myChart.setOption(option);

// Resize the chart when the window is resized
window.addEventListener('resize', function() {
myChart.resize();
});

Este es el resultado:

¿Ha quedado contestada tu pregunta?