Real-time web app with Node JS, Lit-element, GraphQL, and MQTT pub/sub subscription

Ezequiel Miranda
Devjam
Published in
5 min readNov 11, 2021

This article is part of a series. Check out the series: Part 1 and Part 2

What are we building?

We are back to the third part of the IoT experiments series. In this part, we are going to create a real-time web app with lit-element, NodeJS, GraphQL, and an MQTT pub/sub subscription.

The service will be listening for data from our sensors using the MQTT protocol.

Applications on Glitch:

I’ve hosted the application codes used in this article on Glitch so you can see it all in action.

MQTT broker

In this example, I’m using an open MQTT broker mqtt://broker.hivemq.com

You can choose another MQTT broker or create your own. If you follow my previous articles, you can use the AWS IoT Core instance.

Repository with examples:

You can find the different project examples in the following repository:

https://github.com/ezequielmiranda87/iot-experiments

If you want to run the examples locally, each of them has an npm script to start it:

npm start

MQTT Client

In order to send MQTT messages to the MQTT broker, I’ve created this small NodeJS script that simulates sending sensor data every 3 seconds.

iot-client-mqtt/index.js

What is GraphQL:

GraphQL is an open-source data query language developed by Facebook in 2012 and open-sourced in 2015. It was designed to be used in mobile application development but is increasingly being adopted for use in front-end development. It is frequently compared to RESTful JSON APIs since it exposes data in a similar way.

GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

GraphQL Subscriptions:

To add real-time functionality to our web app, we implement GraphQL subscriptions.

Subscriptions in GraphQL are a way for a server to send data to its clients when a specific event happens on a GraphQL server. To achieve this, the server maintains a WebSocket connection open with the client. Every time this particular event happens, the server uses the connection to push the event data to the subscribed client.

In this case, we subscribe our GraphQL server to MQTT messages, using a pub/sub subscription. So this means we can listen to a certain MQTT topic, and if we receive a new message (sensor data) we communicate the data payload to the client and the client application doesn’t need to ask the server if there are new events or data to show.

graphql-mqtt-subscriptions:

https://github.com/davidyaha/graphql-mqtt-subscriptions

This package implements the AsyncIterator and PubSubEngine interfaces from the graphql-subscriptions package.

Set up GraphQL Server:

It’s time to set up our GraphQL Server using NodeJS. First, we need to create a web-socket server and then add the GraphQL layer using NPM’s graphql-ws package.

This is the stack we are using:

ws (web-socket server): is a simple, blazingly fast, thoroughly tested WebSocket client/server implementation.

https://github.com/websockets/ws](https://github.com/websockets/ws

graphql-ws: A coherent, feature-full, zero-dependency, plug-n-play, lazy, simple, client/server implementation of the new, security-first GraphQL over WebSocket Protocol with full support for all three GraphQL operations: queries, mutations, and subscriptions.

https://github.com/enisdenjo/graphql-ws

graphql-mqtt-subscription: This package implements the AsyncIterator and PubSubEngine interfaces from the GraphQL subscriptions package. It allows you to connect your subscription-manager to an MQTT-enabled pub-sub broker to support.

https://github.com/davidyaha/graphql-mqtt-subscriptions

GraphQL Schema

Let’s start with the schema definition. A schema in GraphQL describes the functionality available to the client applications that connect to it.

For this example, the schema is quite simple. We define a “hello world” query, a type for the sensorData, and a subscription that will receive a “sensorData“ object. We put this last item together in the schema object.

iot-server-graphql/src/schema/index.js

Subscriptions

Here we are going to implement a GraphQL Subscriptions system. This allows anyone who is subscribed through GraphQL to get updates from your server.

For this case, we add an MQTT PubSub subscription to a GraphQL server using the plugin graphql-mqtt-subscriptions

This setup enables the client to be informed of certain events. In this case, we receive notification of new sensor data arriving at an MQTT Broker and a specific MQTT topic: ezex-test/sensor1

iot-server-graphql/src/resolvers/index.js

Server Script

In the following script, we set up a simple web socket server. Then we add GraphQL support with the schema and resolvers definitions.

Once we have set up the server, we can use a GraphQL client to subscribe to it.

iot-server-graphql/server.js

Web app with lit-elements and Graphql client

Now I will show you how to build a real-time web app with web components and a GraphQL subscription.

We’ll use “lit-elements” on the front end.

LitElement is a simple base class for creating fast, lightweight web components that work in any web page with any framework.

We will also set up the GraphQL client and subscribe to the server events and update the IU whenever it receives a new MQTT message from the “sensor.”

GraphQL client

To connect the front-end app to the GraphQL client, we will use the package graphql-ws, which provides the client.

iot-web-consumer/src/js/graphql-client.js

my-thing component

At this step, we create a simple web component with lit elements. This component will use the GraphQL client that is subscribed to the GraphQL server, and we will be notified when a new message arrives.

Each time the client receives a new message from the server, the client-subscriber will trigger a custom event and update the data. In this way, our web app receives real-time data from the sensors.

This is how our web component looks:

my-thing component

iot-web-consumer/src/components/my-thing.js

Wrapping up

In this part of the IoT experiments series, we have created a Real-time web app with lit-element, NodeJS, GraphQL, and an MQTT pub/sub subscription.

The Server listens for data from our sensors using the MQTT protocol. In addition, we hosted our app on Glitch so you can see it all in action.

Thank you for your interest! Any feedback is welcome.

I work at Sytac.io; We are a consulting company in the Netherlands, we employ around ~100 developers across the country at A-grade companies like KLM, ING, ABN-AMRO, TMG, Ahold Delhaize, and KPMG. Together with the community, we run DevJam, check it out and subscribe if you want to read more stories like this one. Alternatively, look at our job offers if you are seeking a great job!

--

--