npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

expressify-mqtt

v1.0.3

Published

Transport strategy for Expressify REST mechanisms over MQTT.

Downloads

17

Readme

expressify-mqtt

An Expressify strategy enabling RESTful application over an MQTT(S) transport.

CodeFactor

Current version: 1.0.3

Lead Maintainer: Halim Qarroum

Table of contents

Install

npm install --save expressify-mqtt

Features

  • Natively supports the MQTT.js and the AWS IoT SDK libraries.
  • Usage of an MQTT query-response pattern optimized for minimizing message exchanges and costs.
  • Supports observation of resources using dedicated MQTT topics.
  • Supports Node.js and the Browser (using MQTT-over-Websockets).
  • Automatically detects disconnected observers to stop emitting resource updates.

Usage

In order to use expressify-mqtt, you need to create an instance of the strategy using a backend such as MQTT.js or the AWS IoT SDK. The strategy requires that the MQTT backend follows the same interface as MQTT.js.

Creating a client

When initializing the expressify-mqtt strategy, you need to pass it a supported MQTT backend, as well as a topic mountpoint indicating the base topic which the strategy will use to create its topic architecture.

// Injecting the `mqtt.js` library.
const mqtt = require('mqtt');

// Creating the client instance.
const client = new Expressify.Client({
  strategy: new MqttStrategy({
    mqtt: backend,
    topic: 'my/topic'
  })
});

Note that given the used MQTT service, there might be limitations on the number of forward slashes you can use. For example, on AWS IoT the maximum amount of forward slashes is 7 as of today. Also, have a read on how the query-response pattern over MQTT works in expressify-mqtt to understand the maximum number of forward slashes you can use on a topic mountpoint.

Creating a server

The below example shows you how to create an instance of an Expressify server using the mqtt strategy. Similarly to Creating a client, you need to pass to the strategy an MQTT backend and the MQTT topic mountpoint which must be the same as for the client.

// Injecting the `mqtt.js` library.
const mqtt = require('mqtt');

// Creating the server instance.
const server = new Expressify.Server({
  strategy: new MqttStrategy({
    mqtt: backend,
    topic: 'my/topic'
  })
});

// Listening for incoming requests.
server.listen().then(() => {
  console.log(`[+] The server is listening on mount point '${server.strategy.opts.topic}' !`);
});

Connecting the back-end

In order for an expressify-mqtt client or server to be able to start subscribing or publishing on MQTT topics using the backend instance, it should be configured and connected before using expressify. See the examples available in this repository to see more in details how to connect the back-ends before using either the client or the server.

The configuration object

As you will see it in the examples, The MQTT.js and the AWS IoT SDK requires a configuration object to be passed in order to specify the configuration properties (server, certificates, connection parameters, etc.) to use while connecting to an MQTT server.

An example of such a configuration object is available here, replace the placeholders between diamonds with the correct values. The referenced certificate paths (keyPath, certPath and caPath) should be placed in the common/certs directory for the examples to properly work.

For more information on the values you can put in the config.json file, please read the associated documentation on the AWS IoT SDK for Javascript.

Implementation details

In this section will be detailed implementation details about the inner workings of the expressify-mqtt module.

Query-Response pattern

To enable a stateless query-response model over MQTT, this module is based on the establishment of a topic nomenclature which is optimized in terms performance and costs.

When issuing a request or a response, expressify-mqtt builds its query and response topics on top of the topic mountpoint documented in the previous sections and uses it as a mounting point for the rest of the topic schema.

Anatomy of a transaction

When an expressify-mqtt client queries a remote server, it will transmit the standard expressify query payload over the following topic :

${"topic-mount-point"}/${"query-transaction-id"}/request

Where topic-mount-point is the topic mountpoint given by the user of the strategy when instantiating it,query-transaction-id is a UUID v4 generated per query, and request is a string literal indicating the type of the transaction.

Before sending this request, the expressify client will subscribe to the following topic (the same nomenclature as for the request is used for variable names) :

${"topic-mount-point"}/${"query-transaction-id"}/response

When the server responds to the request, it will send it on the above MQTT topic using the same transaction identifier as for the request.

Anatomy of event notifications

Since Expressify offers the ability for clients to observe a remote resource on the server, and be notified whenever this resource has been modified, the expressify-mqtt strategy bases the event notification flow upon the following topic model.

When a client wishes to subscribe to a remote resource, it sends a request (as for a regular request) to the server indicating the resource it would like to subscribe to.

Once acknowledge by the server, subsequent updates and notifications associated with the observed resource will be sent by the server on the below topic.

${"topic-mount-point"}/${"resource-name"}/events

Message ordering

By default, the expressify-topic when publishing a message on an MQTT broker will do so using a QoS of 1 to avoid lost messages. This can be overriden by the user of the module when instanciating the strategy :

// Using a `QoS` of `0`.
new MqttStrategy({
  mqtt: backend,
  topic: 'my/topic',
  mqttOpts: { qos: 0 }
})

Unless the used MQTT broker supports QoS 2, there is a chance that your messages will not arrive in the same order they have been sent initially by the client. Since some applications might require message ordering to be guaranteed, it is possible to activate this feature on expressify-mqtt for events, but not for query-responses since those are supposed to be stateless.

Below is an example of how to send events in an ordered manner from a server instance when notifying the client about a change on one of the resource it exposes.

server.publish(`/my/resource`, { foo: 'bar' }, { ordered: true });

A sequence number will be sent by the server on each .publish() to allow the client to re-order the messages. Note that the client will wait for a short period of time to receive an expected message after having received subsequent messages. Once the timeout has been reached, the message is considered lost, and expressify-mqtt will continue ordering subsequent messages to avoid the client to be trapped into a 'hanged' situation.

Examples

Two functional examples involving the expressify-mqtt strategy are available in the examples directory :

  • Remote storage - Demonstrates how to use expressify-mqtt to expose a REST interface on the server which can store in memory a set of key-value pairs, and on the client on how to query this service remotely over MQTT.
  • System monitoring - Shows you how to use expressify-mqtt to expose system metrics on the server and to display them to the user on the client.

See also