When we are building a website that needs to be updated in real-time, our first thought is probably to add WebSockets to our application.

However Websockets is a low-level protocol and to use it, we will need to add another layer on top to manage the information we want to get. This is where MQTT protocol is handy, as it’s a higher-level protocol that simplifies working with data streams.

What is MQTT?

MQTT means Message Queuing Telemetry Transport. It’s a connectivity protocol used in the IoT world to communicate between machines.

Architecture

An MQTT protocol ecosystem has the following components:

  • Publisher: Responsible for publishing MQTT messages to the system. Usually an IoT device.
  • MQTT Broker: The server that gets the published data and sends it to the corresponding subscribers.
  • Subscriber: The device that is listening for incoming data from devices.

Publish/Subscribe Model

As we have seen in the architecture overview, MQTT uses the publish/subscribe methodology. So they don’t know each other, they just need to agree on how data is going to be sent. It also allows the use of multiple publishers or subscribers, so various clients can create an MQTT connection and subscribe to data from a single device.

MQTT Topics

An MQTT Topic is the concept used to communicate between publishers and subscribers. When a subscriber wants to get data from a device, it subscribes to a specific topic, which will be where the device publishes its data. A Topic is a hierarchical UTF-8 string, and here you have an example: “local/command/mmi/camera/state”

MQTT Over Websockets

MQTT is a high-level protocol and the great thing is that it can use different protocols to get its job done. It can adopt its own MQTT protocol, but this protocol is not supported by web browsers; however MQTT can also be used over WebSockets connection, so we can easily use MQTT on any web browser that supports WebSockets.

Which MQTT Broker Should I Use?

There are various MQTT brokers we can use for our project. On one hand we can use cloud/hosted solutions; alternatively we can choose an on-premise option, either by installing on our own servers or using through Docker.

You can see a comprehensive list of the existing brokers in this Github repo. In our case we have used the open source Eclipse Mosquitto with great success.

MQTT Client on Angular Apps

Now let’s see how can we use MQTT protocol on an Angular app. The easiest way to do it is to use some of the existing Javascript libraries. In this case, we will use the ngx-mqtt library. This offers support for Javascript/Typescript observables, so it’s really helpful when writing an MQTT client on an Angular app.

Installing ngx-mqtt

npm install ngx-mqtt --save

Configuration

Once the library is installed, you need to initialize it. You can follow the instructions on the ngx-mqtt site, but you will probably have multiple environments in your Angular code, so you will need a different configuration for each environment. So let’s create an mqtt section in our environment files. Here’s an example: src/environments/environment.prod.ts

export const environment = {
  production: true,
	hmr: false,
	http: {
		apiUrl: '<https://api.myweb.com>',
	},
	mqtt: {
		server: 'mqtt.myweb.com',
		protocol: "wss",
		port: 1883
	}
};

You can edit all other environment configuration files to set the right values for each one. Now we need to initialize the MQTT library, and for this we recommend changing to app.module.ts:

...
import { IMqttServiceOptions, MqttModule } from "ngx-mqtt";
import { environment as env } from '../environments/environment';

const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = {
    hostname: env.mqtt.server,
    port: env.mqtt.port,
    protocol: (env.mqtt.protocol === "wss") ? "wss" : "ws",
    path: '',
};

@NgModule({
    declarations: [AppComponent],
    imports: [
        ...
        MqttModule.forRoot(MQTT_SERVICE_OPTIONS),
    ],
    ...
})
export class AppModule { }

Creating Services

It is recommend to create a service class which manage the differents Topics we are going to use. Let’s create a service that subscribes to a topic , where the Topic name is similar to /local/data/temperature. For this we create the Typescript file src/app/services/event.mqtt.service.ts with the following code:

import { Injectable } from '@angular/core';
import { IMqttMessage, MqttService } from "ngx-mqtt";
import { Observable } from "rxjs";

@Injectable()
export class EventMqttService {

  constructor(
private _mqttService: MqttService)

  topic(topicName: string): Observable<IMqttMessage> {
   
    return this._mqttService.observe(topicName);
  }
}

Using this service class, we have all the MQTT-related code in a single file and now we only need to use this service when it’s needed.

PS: Remember to add all the services files to the providers section of your AppModule, otherwise you won’t be able to use them.

Using the MQTT Services

Now it’s time to use the MQTT services we have created. So, for example, let’s create an EventStream component that prints all the events that a device generates. The code of this file will be similar to:

import { Component, OnInit } from '@angular/core';
import { EventDataModel } from 'app/models/event.model';
import { Subscription } from 'rxjs';
import { EventMqttService } from 'app/services/api/event.mqtt.service';
import { IMqttMessage } from "ngx-mqtt";

@Component({
    selector: 'event-stream',
    templateUrl: './event-stream.component.html',
    styleUrls: ['./event-stream.component.scss'],
})
export class EventStreamComponent implements OnInit {
    events: any[];
    private deviceId: string;
    subscription: Subscription;

    constructor(
        private readonly eventMqtt: EventMqttService,
    ) {
    }

    ngOnInit() {
        this.subscribeToTopic();
    }

    ngOnDestroy(): void {
        if (this.subscription) {
            this.subscription.unsubscribe();
        }
    }

    private subscribeToTopic() {
        this.subscription = this.eventMqtt.topic(this.deviceId)
            .subscribe((data: IMqttMessage) => {
                let item = JSON.parse(data.payload.toString());
		this.events.push(item);
            });
    }
}

It’s important to remember that we need to unsubscribe from the subscription when we destroy the component.

Now, we should have an Angular app that can subscribe to MQTT topics and show the user the information every time a device generates an MQTT message.

Reference:

https://bugfender.com/

By Shabazz

Software Engineer, MCSD, Web developer & Angular specialist

Leave a Reply

Your email address will not be published. Required fields are marked *