Skip to content

Instantly share code, notes, and snippets.

@narutaro
Last active September 19, 2024 12:59
Show Gist options
  • Save narutaro/6461c0524f7d7ff01e21c2ecb0be84ca to your computer and use it in GitHub Desktop.
Save narutaro/6461c0524f7d7ff01e21c2ecb0be84ca to your computer and use it in GitHub Desktop.
MQTT in your browser

MQTT in your browser

MQTT is probably best known as a lightweight messaging protocol implemented for small sensors, but there is actually a JavaScript implementation called MQTT.js. It's a JavaScript implementation, so of course it works in a browser. I think it's a great option for front-end engineers who are working with MQTT/IoT-related projects (for example, creating a dashboard to visualize MQTT data). In this article, I'd like to write about what I did when I tried to connect MQTT.js to the test server (broker) of Mosquitto™.

Sample code

It's very simple, but the following code should work. You should see {"name": "sensor1", "temp": 10} in your browser console. As a scenario, I made it so that sensor1 in floor1/room1 is sending the temperature. MQTT topics are generally hierarchical with /.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MQTT</title>.
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>
<body>

<script>
let client = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"
let metric = '{"name": "sensor1", "temp": 10}'

client.subscribe(topic);
client.publish(topic, metric);

client.on('message', function (topic, message) { // message is Buffer
  console.log(message.toString());
});

client.end();
</script>

</body
</html>
  • When throwing MQTT from a browser, it is common to use MQTT over WebSocket since you can't throw it directly.
  • Therefore, the protocol specification in the URI should be wss://test.mosquitto.org:8081.

Publish periodically, like a sensor.

Change the code to send data periodically.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MQTT DASH</title>.
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>

<body> 

<script>
let client = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"

client.subscribe(topic);

pubLoop = setInterval(() => {
  const time = Date.now().toString();
  const temp = Math.floor( Math.random() * 11 );
  let metric = '{"time":' + time + ', "name": "sensor1", "temp":' + temp + '}'
  client.publish(topic, metric);
}, 1000);

client.on('message', function (topic, message) { // message is Buffer
  console.log(message.toString());
});

setTimeout(function() { clearInterval( pubLoop ); }, 10000); // stop after 10sec

</script>

</body>
</html>

Console output. Well, it's starting to look like sensor data.

{"time":1588127649527, "name": "sensor1", "temp":6}
{"time":1588127650532, "name": "sensor1", "temp":4}
{"time":1588127651530, "name": "sensor1", "temp":6}
{"time":1588127652529, "name": "sensor1", "temp":1}
{"time":1588127653531, "name": "sensor1", "temp":3}
{"time":1588127654530, "name": "sensor1", "temp":8}
{"time":1588127655528, "name": "sensor1", "temp":10}
{"time":1588127656529, "name": "sensor1", "temp":10}
{"time":1588127657530, "name": "sensor1", "temp":4}

It might be easier to separate pub / sub.

It might be easier to separate the pub and sub instances like this:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MQTT DASH</title>.
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>

<body>

<script>

let pub = mqtt.connect('wss://test.mosquitto.org:8081');
let sub = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"


sub.subscribe(topic);

pubLoop = setInterval(() => {
  const time = Date.now().toString();
  const amp = Math.floor( Math.random() * 11 );
  const tem = Math.floor( Math.random() * 11 );
  const hum = Math.floor( Math.random() * 11 );
  let metric = '{"time":' + time + ', "name": "sensor1", "amp":' + amp + ', "temp":' + tem + ', "hum":' + hum + '}'
  pub.publish(topic, metric);
  console.log("pub: " + metric);
}, 1000);

sub.on('message', function (topic, message) { // message is Buffer
  console.log("sub: " + message.toString());
});

setTimeout(function() {
  clearInterval( pubLoop );
  pub.end();
  sub.end();
}, 10000); // stop after 10sec

</script>

</body
</html>

Now your browser should work as sensors which do publish and subscription

That's it for today, see you later.

@chimiwangchuk
Copy link

but can we do certificates based authentication for IOT?

@narutaro
Copy link
Author

narutaro commented Sep 18, 2024

Check out the options for tls.connect()

@chimiwangchuk
Copy link

chimiwangchuk commented Sep 19, 2024

I believe tls will work only on low level environments that can access file systems like Node and Python

@narutaro
Copy link
Author

It's not for browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment