Introdução ao Angular e MQTT
Angular é uma robusta plataforma de desenvolvimento baseada em TypeScript, ideal para a construção de aplicações web escaláveis. Ela oferece um framework de compnoentes, um conjunto de bibliotecas bem integradas para funcionalidades como roteamento, gerenciamento de formulários e comunicação cliente-servidor, além de ferramentas completas para o ciclo de vida do desenvolvimento.
O MQTT (Message Queuing Telemetry Transport) destaca-se como um protocolo de mensagens leve e eficiente, utilizando o padrão de publicação/assinatura, o que o torna uma escolha excelente para cenários de Internet das Coisas (IoT). Ele facilita a distribuição de mensagens um-para-muitos, desacopla aplicações e minimiza o tráfego de rede, oferecendo ainda diferentes níveis de Qualidade de Serviço (QoS) para atender a diversas necessidades de entrega.
Este artigo demonstrará como incorporar o protocolo MQTT em projetos Angular, cobrindo desde a conexão com um servidor MQTT até a publicação, subscrição de mensagens e o gerenciamento de inscrições.
Preparação do Ambiente de Desenvolvimento
Criação de um Novo Projeto Angular
Para iniciar, crie uma nova aplicação Angular utilizando o Angular CLI. Se o CLI não estiver instalado, você pode instalá-lo globalmente via npm.
ng new nome-do-projeto
cd nome-do-projeto
Instalação da Biblioteca Cliente MQTT
Para interagir com o MQTT em Angular, utilizaremos a biblioteca ngx-mqtt. Esta é uma camada sobre o MQTT.js, adaptada para Angular (versões 2 e superiores), que faz um excelente uso de Observables e gerencia o ciclo de vida das subscrições e o roteamento de mensagens, sendo particularmente útil em aplicações complexas com múltiplos componentes e subscritores.
Instale ngx-mqtt via npm ou yarn:
npm install ngx-mqtt --save
# ou
yarn add ngx-mqtt
Utilização do Protocolo MQTT
Configuração e Conexão ao Servidor MQTT
Para os exemplos a seguir, utilizaremos um servidor MQTT público e gratuito, oferecido pela EMQX, que é uma plataforma de mensagens MQTT distribuída de alta performance, ideal para conectar uma vasta gama de dispositivos IoT.
Detalhes do Broker Público:
- Broker: broker.emqx.io
- Porta TCP: 1883
- Porta WebSocket: 8083
Para estabelecer a conexão no seu projeto Angular, configure um serviço ou componente conforme o exemplo abaixo. Neste trecho, definimos os parâmetros de conexão e tratamos os eventos de conexão, erro e recebimento de mensagens.
import { Component } from '@angular/core';
import { IMqttMessage, IMqttServiceOptions, MqttService, IPublishOptions } from 'ngx-mqtt';
import { IClientSubscribeOptions } from 'mqtt-browser';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-mqtt-dashboard',
templateUrl: './mqtt-dashboard.component.html',
styleUrls: ['./mqtt-dashboard.component.scss'],
})
export class MqttDashboardComponent {
private activeSubscription: Subscription | undefined;
private mqttClientService: MqttService;
public isClientConnected: boolean = false;
public subscriptionEstablished: boolean = false;
public connectionParameters = {
brokerHost: 'broker.emqx.io',
webSocketPort: 8083,
basePath: '/mqtt',
cleanSession: true, // Manter sessão limpa
connectionTimeoutMs: 4000, // Tempo limite para conexão
reconnectIntervalMs: 4000, // Intervalo para tentativas de reconexão
clientId: 'angular_client_' + Math.random().toString(16).substr(2, 8), // ID de cliente único
authUsername: 'emqx_user',
authPassword: 'emqx_password',
protocolType: 'ws' as 'ws', // Protocolo WebSocket
};
public subscriptionSettings = {
topicToSubscribe: 'angular/data',
qosLevel: 0,
};
public messagePublisher = {
targetTopic: 'angular/command',
qosLevel: 0,
payloadData: '{ "action": "ping", "timestamp": ' + Date.now() + ' }',
};
public receivedMessagesLog: string[] = [];
public qualityOfServiceOptions = [
{ label: 'QoS 0 (No Ack)', value: 0 },
{ label: 'QoS 1 (At Least Once)', value: 1 },
{ label: 'QoS 2 (Exactly Once)', value: 2 },
];
constructor(private mqttService: MqttService) {
this.mqttClientService = mqttService;
}
// Função para estabelecer a conexão MQTT
public initiateMqttConnection(): void {
const opts: IMqttServiceOptions = {
hostname: this.connectionParameters.brokerHost,
port: this.connectionParameters.webSocketPort,
path: this.connectionParameters.basePath,
clean: this.connectionParameters.cleanSession,
connectTimeout: this.connectionParameters.connectionTimeoutMs,
reconnectPeriod: this.connectionParameters.reconnectIntervalMs,
clientId: this.connectionParameters.clientId,
username: this.connectionParameters.authUsername,
password: this.connectionParameters.authPassword,
protocol: this.connectionParameters.protocolType,
};
try {
this.mqttClientService.connect(opts);
} catch (error) {
console.error('Falha ao tentar conectar ao MQTT:', error);
this.isClientConnected = false;
}
this.mqttClientService.onConnect.subscribe(() => {
this.isClientConnected = true;
console.log('Conexão MQTT realizada com êxito!');
});
this.mqttClientService.onError.subscribe((error: any) => {
this.isClientConnected = false;
console.error('Erro na conexão MQTT:', error);
});
this.mqttClientService.onMessage.subscribe((packet: IMqttMessage) => {
const msgContent = packet.payload.toString();
this.receivedMessagesLog.push(`[${new Date().toLocaleTimeString()}] Tópico: ${packet.topic}, Mensagem: ${msgContent}`);
console.log(`Mensagem recebida do tópico ${packet.topic}: ${msgContent}`);
});
}
}
Inscrição em um Tópico
Após uma conexão bem-sucedida, você pode se inscrever em um tópico específico para receber mensagens. O método observe da biblioteca ngx-mqtt retorna um Observable, permitindo gerenciar o fluxo de mensagens de forma reativa.
// Dentro da classe MqttDashboardComponent
public subscribeToMqttTopic(): void {
const { topicToSubscribe, qosLevel } = this.subscriptionSettings;
const subscribeOptions: IClientSubscribeOptions = { qos: qosLevel };
this.activeSubscription = this.mqttClientService.observe(topicToSubscribe, subscribeOptions).subscribe({
next: (message: IMqttMessage) => {
this.subscriptionEstablished = true;
console.log(`Inscrição no tópico '${message.topic}' ativa. Última mensagem: ${message.payload.toString()}`);
},
error: (error) => {
console.error('Erro ao subscrever o tópico:', error);
this.subscriptionEstablished = false;
},
complete: () => {
console.log('Ciclo de subscrição completado.');
this.subscriptionEstablished = false;
}
});
}
Cancelamento da Inscrição
Para parar de receber mensagesn de um tópico, você deve cancelar a inscrição. O método unsubscribe() no objeto Subscription liberará os recursos associados.
// Dentro da classe MqttDashboardComponent
public unsubscribeFromMqttTopic(): void {
if (this.activeSubscription) {
this.activeSubscription.unsubscribe();
this.subscriptionEstablished = false;
console.log('Inscrição no tópico foi cancelada.');
} else {
console.warn('Não há nenhuma subscrição ativa para cancelar.');
}
}
Publicação de Mensagens
Para enviar dados para um tópico MQTT, utilize o método unsafePublish. Este método permite especificar opções adicionais como QoS e Retain.
// Dentro da classe MqttDashboardComponent
public publishMqttMessage(): void {
const { targetTopic, qosLevel, payloadData } = this.messagePublisher;
const publishOptions: IPublishOptions = { qos: qosLevel };
if (this.mqttClientService) {
this.mqttClientService.unsafePublish(targetTopic, payloadData, publishOptions).subscribe({
next: () => console.log(`Mensagem publicada no tópico '${targetTopic}' com sucesso.`),
error: (error) => console.error('Falha ao publicar a mensagem:', error)
});
} else {
console.warn('Cliente MQTT não inicializado; incapaz de publicar mensagens.');
}
}
Desconexão do Cliente
Para finalizar a sessão MQTT, chame o método disconnect. Passar true como parâmetro garante uma desconexão forçada.
// Dentro da classe MqttDashboardComponent
public terminateMqttConnection(): void {
try {
if (this.mqttClientService) {
this.mqttClientService.disconnect(true); // Forçar desconexão
this.isClientConnected = false;
this.subscriptionEstablished = false;
console.log('Cliente MQTT desconectado com sucesso!');
}
} catch (error) {
console.error('Falha ao desconectar o cliente MQTT:', error);
}
}
Teste de Funcionalidade
Com o código implementado no Angular, é possível desenvolver uma interface de usuário simples que exponha as funcionalidades de conectar, subscrever, publicar, cancelar subscrição e desconectar. Para testar a comunicação de ponta a ponta, pode-se usar uma ferramenta cliente MQTT como o MQTT X.
Ao conectar o aplicativo Angular e o MQTT X ao mesmo broker, é possível:
- Publicar mensagens do Angular para um tópico e visualizá-las no MQTT X.
- Publicar mensagens do MQTT X para um tópico e recebê-las no Angular (se o Angular estiver subscrito a esse tópico).
- Validar o cancelamento da subscrição: submeta o Angular a um tópico, envie algumas mensagens do MQTT X, cancele a subscrição no Angular e, em seguida, tente enviar mais mensagens do MQTT X. O Angular não deverá mais receber essas últimas mensagens, confirmando que a subscrição foi corretamente encerrada.