MQTT JavaScript Example

The following example describes how to develop a simple MQTT client in JavaScript with Node.js. We use the opensource library mqtt.js that implements a MQTT layer for Node.js. You can use the npm (node.js package manager) to install it:

  npm install mqtt

You are free to use any MQTT library written in any programming language to connect your Production Things with the CloudPlugs MQTT server. Please refer to the MQTT API Overview page for additional details on our MQTT API.

Connecting an existing device

With a few lines of code we can connect an existing device such as a Production Thing or Controller to the CloudPlugs IoT platform:

   var mqtt = require('mqtt');
   
   var USER = 'dev-XXXXXXXXXXXXXXXXXXXXXXXX'; // enter a valid Plug-ID for a Thing or Controller.
   var PASS = '********';                     // enter the **Connection password** (see Enrolling a Thing below) for the Thing or Controller.
   
   var url  = 'mqtts://'+USER+':'+PASS+'@api.cloudplugs.com';
   var opts = { keepalive: 299 };             // to send a PING request every 4 minutes 59 seconds
   
   var client = mqtt.connect(url, opts);      // connect to the CloudPlugs server
   
  client.on('connect', function() {
      console.log('MQTT client connected');
      doMyStuff();   // now we are connected: let's publish or subscribe...
  });

Publishing data

The following function is used to publish data to CloudPlugs. Note that “device Plug-ID”/data/ must precede the target topic:

  // publish data (consisting of any valid JSON value) to a channel with an (optional) timestamp
  function pubData(client, channel, msg) {
      client.publish('dev-yyyyyyyyyyyyyyyyyyyyy/data/'+channel, JSON.stringify(msg));  // we must send the payload as JSON and include the device Plug-ID
  }

If you have enough permissions to publish data in the name of another Plug-ID (as in the case of a Controller which has WRITE permissions over a given Thing), such data will be published exactly as if it was published by the Thing Plug-ID. If the permission level is READ ONLY or DENY, the PUBLISH command will be discarded by the server and the data won’t be published.

We can then invoke the function we defined previously:

  function doMyStuff() {
      var plugID = 'dev-YYYYYYYYYYYYYYYYYYYYYYYY'; // enter a valid Plug-ID
      pubData(client, plugID+'/data/any/given/channel', { data: 'any value', at: Date.now() });
      pubData(client, plugID+'/data/another/channel', 100);  // publish the value 100 in the name of another device
  }

Subscribing to read data

Per the previous section, any MQTT topic for subscribing or publishing data must contain a “/data/” string followed by the channel:

  client.subscribe('+/data/#');  // subscribe to all channels published by any device

We need to set up a callback for getting the messages received by CloudPlugs server:

   client.on('message', function(topic, payload) { // this callback is called everytime a data is received
      var parts = topic.split('/');
      var plugID = parts[0];   // the device has published this received data
      var channel = parts.slice(2).join('/');  // channel where data has been published
      var msg = JSON.parse(payload);  // payload is a JSON value containing information about the published data
      var id = msg.id;                // unique identifier of this data (it can be used to modify this published data)
      var at = new Date(msg.at);      // when the data has been published
      var data = msg.data;            // the published data
      console.log('received data of Plug-ID '+plugID+' from channel "'+channel+'": '+JSON.stringify(data));
  }

Enrolling a Thing

We can enroll a new Thing and retrieve its Plug-ID and Connection password in the following way:

   var idModel = 'mod-XXXXXXXXXXXXXXXXXXXXXXXX';  // enter the Plug-ID of the Thing's Production Template
   var hwid = 'ZZZZZZZZZZZ';                      // enter the thing hardware-id or serial number of the Thing
   var pass = '********';                         // enter the Enrollment password of the Thing
   
   // we are connecting with an empty username and connection password because we want to enroll;
   // note that the MQTT client ID must be the hardware ID or serial number of the device to enroll
   var client = mqtt.connect('mqtts://api.cloudplugs.com', { keepalive:299, clientId:hwid });
   
   client.on('connect', function() {
      client.subscribe(idModel+'/thing/'+pass);  // request to enroll the thing!
      client.on('message', onEnroll);
   });
   
  function onEnroll(topic, payload) {
      client.removeListener('message', onEnroll);  // enroll phase finished: we don't need this listener anymore
      var msg = JSON.stringify(payload);           // get the response message of enrollment
      if(msg.err) {
          console.error('Enrollment failed!');
      } else {
          var plugID = msg.id;
          var pass   = msg.auth;
          console.log('Enrollment successful: now the Plug-ID of this device is '+plugID
                     +' with the Connection password "'+pass+'"');
          // we should now store plugID and pass in a persistent way to use them in future connections;
          // we can now subscribe and publish data to the cloud
          doMyStuff();
      }
  }

Enrolling a Controller

The enrollment of a Controller is similar to the enrollment of a Thing:

   var idModel = 'mod-XXXXXXXXXXXXXXXXXXXXXXXX';  // enter the ID of the Production Template of the thing to control
   var thingHwid = 'WWWWWWWWWWW';                 // enter the thing hardware-id or serial number
   var ctrlHwid = 'ZZZZZZZZZZZ';                  // enter the controller hardware-id
   var pass = '********';                         // enter the control password of the controller as defined in the thing Production Template
   
   // we are connecting with an empty username and password because we want to enroll;
   // note that the MQTT client ID must be the hardware ID of the Controller device to enroll
   var client = mqtt.connect('mqtts://api.cloudplugs.com', { keepalive:299, clientId:ctrlHwid });
   
  client.on('connect', function() {
      client.subscribe(idModel+'/ctrl/'+thingHwid+'/'+pass);   // request to enroll the controller!
      client.on('message', onEnroll);
  });
   
  function onEnroll(topic, payload) {
      client.removeListener('message', onEnroll);  // enroll phase finished: we don't need this listener anymore
      var msg = JSON.stringify(payload);           // get the response message of enrollment
      if(msg.err) {
          console.error('Enrolling failed!');
      } else {
          var plugID = msg.id;
          var pass   = msg.auth;
          console.log('Enrollment success: now the Plug-ID of this device is '+plugID
                     +' with the Connection password "'+pass+'"');
          // we should now store plugID and pass in a persistent way to use them in future connections;
          // we can now subscribe and publish data to the cloud
          doMyStuff();
      }
  }

A Full example

Here’s a complete example for subscribing to CloudPlugs IoT and publishing data:

  var mqtt = require('mqtt');
   
  var USER = 'dev-XXXXXXXXXXXXXXXXXXXXXXXX'; // enter a valid Plug-ID
  var PASS = '********';                     // enter the Connection authentication password of the device
   
  var url  = 'mqtts://'+USER+':'+PASS+'@api.cloudplugs.com';
  var opts = { keepalive: 540 };             // to send a PING request every 9 minutes
   
  var client = mqtt.connect(url, opts);      // connect to CloudPlugs server
   
  client.on('connect', function() {
      console.log('MQTT client connected');
      doMyStuff();
  });
   
  client.on('message', function(topic, payload) {
      var msg = JSON.parse(payload);
      console.log('received data from topic "'+topic+'" at '+new Date(msg.at)+' : '+JSON.stringify(msg.data));
  });
   
  client.on('close', function() {
      console.log('MQTT connection closed, now exiting.');
      process.exit(0);
  });
   
  function doMyStuff() {
      client.subscribe('+/data/#');    // let's receive data from all channels of any allowed device
      pubData(client, '/data/my/temperature', 40);
      pubData(client, '/data/complex/value', { sampledData: [0,1,2,3,4,'to','test'], subObject:{ 'just': 'for example' }});
  }
  
  function pubData(client, channel, data, at) {
      client.publish(USER+'/data/'+channel, JSON.stringify({ data: data, at: at||Date.now() });
  }
Still need help? Get in touch!
Last updated on 6th May 2021