MQTT in Ember.js
Tags: ember, javascript, webdev, beginners
Published: 2021-07-12 14:43:16

Less than 2 years ago I started a new project with the company I work for that requires to an [Ember Octane](https://emberjs.com/editions/octane/ "Ember.js Octane edition") app to control several connected IoT devices around the world. We choosed the [MQTT](https://en.wikipedia.org/wiki/MQTT "MQTT on Wikipedia") publish/subscribe network protocol to interact with our on-field devices for its lightweight message structure and its limited network bandwith requirements.

After googling for a javascript MQTT library I’ve found the [MQTT.js](https://github.com/mqttjs/MQTT.js "MQTT.js") client. At the moment of my search the [asynchronous version](https://github.com/mqttjs/async-mqtt "Async MQTT.js") was not yet released, so I had to wrap the event based client into an Ember service and transform it into a Promise based client.

This is a mandatory requirement because I need broker connection before subscribing to a topic or I need topic subscription before publishing on it. Sometimes you had retain messages on a topic for receiving last published value after the subscription. Other times you need publishing an empty value on a topic to request the status of a given device. So you need working subscribtion on a topic before sending a message. That said javascript [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Javascript Promise") are the only way to accomplish this tasks.

When I wrote this service I didn't find an Ember addon ready to do this things. Therefore I decided to dive into the [docs](https://cli.emberjs.com/release/writing-addons/intro-tutorial/ "Writing your first Ember.js addon") and learn how to build an addon. The [ember-mqttjs](https://github.com/domoticalabs/ember-mqttjs "ember-mqttjs GitHub page") addon is my first Ember addon!

## The code

This service extends the [Evented](https://api.emberjs.com/ember/release/classes/Evented "Evented Ember object") Ember object for raising events on new messages as well as connect, disconnect events and many others you can find on its [readme](https://github.com/domoticalabs/ember-mqttjs/blob/master/README.md "Readme for ember-mqttjs"). In addition of raising this events it returns a Promise for connect, subscribe, unsubscribe and publish methods.

This is an example of another service that uses the ember-mqttjs service:

```javascript
import Service, { inject as service } from '@ember/service';
import { bind } from '@ember/runloop';

export default class YourService extends Service {
  @service mqtt;
  constructor() {
    super(...arguments);
    //...
    let _fOnMessage = bind(this, this._onMessage);
    this.mqtt.on('mqtt-message', _fOnMessage); 
  }

  _onMessage(sTopic, sMessage) {
    //code to manage messages received on a certain topic
  }

  async subscribeAndPublish(sTopic, sMessage) {
    try {
      await this.mqtt.connect(HOST, USERNAME, PASSWORD)
    } catch (oError) {
      //code on connection error
    }
    try {
      await this.mqtt.subscribe(sTopic);
    } catch (oError) {
      //code for subscription error
    }
    try {
      await this.mqtt.publish(sTopic, sMessage);
    } catch (oError) {
      //code for message publish error
    }
    return Promise.resolve();
  }
//...
}
```

I've just refactored the addon code to use async/await features and I moved the [CI](https://en.wikipedia.org/wiki/Continuous_integration "Continuos integration on Wikipedia") from travis to github action (thanks to this Jeldrik Haschke's [repo](https://github.com/jelhan/create-github-actions-setup-for-ember-addon)).  
Many improvements can be done in the future starting from writing more tests to cover other cases.  
If you have any suggestions or proposal to improve the code as well as the tests you are welcome!

[Contact me](https://blog.davideferrero.com/contacts/ "Contact me") or start contributing on [GitHub project repo](https://github.com/domoticalabs/ember-mqttjs "GitHub project repository")!