Richard Dunmow
ServiceNow Employee
ServiceNow Employee

IoT devices tend to be quite small and lightweight in both processing power, memory and power consumption. Depending on the application, sensors will either always be on all the time and broadcasting out messages over a network which could be a hardwired serial or ethernet type connector, or something like WiFi or LoRA which is a low power long-range radio protocol. These devices need to be able to wake up send some data and go back to sleep as quickly as possible to save battery power, so they tend to use protocols such as MQTT.

MQTT has been around for a long time. It is a lightweight protocol that is used mainly for machine to machine (or IoT to IoT device) communications applications using a broker. The device will "publish" information to the broker which then deals with sending that message out to all the applications that are listening for messages that the sensor has published to. Twitter is very similar to this, in that a user will tweet a short message that everyone who is interested in will be sent, the user is not sending the message to everyone that has asked for it.

In my home, I have been setting up a number of sensors using small Wifi Enabled Microcontrollers (ESP8266's and ESP32's) and I have been posting about I have done on my WordPress site https://richardscoding.wordpress.com/. I have been looking at the different ways to capture the information from the sensors and log it somehow. I looked at using direct REST communications, which worked, but was a point to point solution. Using MQTT I found that I could abstract the device communications and keep that as simple as possible, but using scripting in languages such as NodeJS I could then integrate those sensors into whatever I wanted. I have integrated the sensors into my Apple HomeKit environment for ease of monitoring, but what I really wanted to do was integrate them into Service Now so I could build a mobile application to capture that data and add workflows around that data.

Here is a simple diagram showing how the system works (simplified down)

find_real_file.png

As you can see, all my sensors send out MQTT posts to a central broker. Some are listening in for messages coming back from the MQTT broker which at the moment is just my Apple Homekit. I then created a  number of NodeJS scripts that listen for published MQTT messages and do different things.

I have created a NodeJS script to log the MQTT messages to a MariaDB database, but what I really wanted to do was to post that information to some CI's that I had defined on my Service Now CMDB. I took the script that captured the MQTT posts and published to the MariaDB and changed the target to be a REST call instead of a MariaDB update command.

This it turns out, is nice and simple to achieve. Within my CMDB, I created a new CI Class called IoT and then a subclass of Sensor, there are other ways to do this, but for my testing, this was nice and simple and kept the IoT devices in their own class. Using the standard REST API to update the CI's, 

I used the NodeJS Axios HTTP library for the communication with Service Now and the MQTT library for capturing the messages from the broker, here is an example of the script that I created, using the "forever" library in NodeJS I was able to get this script to run in the background on a Raspberry Pi.

This script is not perfect and by no means is a production-ready example, but as a proof of concept it works and I have had this running in my low volume environment for a number of months now without any issues, so please feel free to use this if it is useful.

var mqtt = require('mqtt');
const axios = require('axios');
 
//This version of the MQTT script will collect the data and send to Service now
//when the commit occurs.
 
//Connect to the MQTT Server
var client = mqtt.connect('mqtt://localhost');
 
//Define the array of data from the sensors
let deviceArray = [];
 
const postData = async (data, userName, passWord) => {
 
  try {
 
    const options = {
        headers: {
            'Content-Type': 'application/json'
        },
        auth: {
          username:userName,
          password:passWord
        }
    };
 
    console.log("Data = " + data);
    const res = await axios.post(url, data, options);
    console.log("Committed Data to " + res.data.result.attributes.sys_id);
 
  } catch (err) {
 
    console.error(err);
 
  }
 
}
 
function writeToServiceNow(data){
 
  console.log('sending');
 
  const myData = JSON.stringify({
    "attributes":
    {"chip_id":data.id,
      "name":data.id,
      "discovery_source":"Manual Entry",
      "temperature":data.temp.toString(),
      "humidity":data.humidity.toString(),
      "pressure":data.pressure.toString()},
    "source":""
  });
 
  postData(myData,'a_user','a_password!');
 
}
 
 
client.on ("connect",function(){
    client.subscribe('sensor/#');
    console.log('Connected to MQTT Server');
});
 
client.on ("message",function(topic,message,packet){
 
    var topicArray = topic.split("/");
    if (topicArray.length == 3){
 
      var sensorID = topicArray[1];
      var reading = topicArray[2];
 
      device = deviceArray.find(device => device.id == sensorID);
 
      if (reading == "commit"){
 
        if (device != undefined){
            console.log(device);
            writeToServiceNow(device);
        }
 
      } else {
 
        if (device == undefined){
 
          console.log("Creating Object " + sensorID);
          device = new Object();
          device.id = sensorID;
          device.temp=0;
          device.humidity=0;
          device.pressure=0;
          device.signal=0;
          eval("device." + reading + "=" + message);
          deviceArray.push(device);
 
        } else {
          console.log("Adding value " + reading + "=" + message + " to " + sensorID);
          eval("device." + reading + "=" + message);
 
        }
      }
 
    } else {
 
      console.log("message is " + message);
      console.log("topic is " + topic);
 
    }
 
});

Don't forget to update the instance URL and authentication token or username/password to be one that you want to post to. 

To understand more about what is going on and the message structures I have used, have a look at the posts I created on my site at https://richardscoding.wordpress.com/ . 

 

This is not something you would want to do for a large number of IoT sensors sending out vast amounts of data as that would not be good for your Service Now instance, but where there is a low volume of data, for example, a temperature sensor that only posts every 15 minutes and automation and alerts could be triggered off of that sensor reading then this is a simple way of integrating Service Now into an IoT network using MQTT.

In a future post, I am going to look at how Service Now could send out using a REST call (Via a MID server) to a web server running in NodeJS that could then translate that message and publish over MQTT to update sensor thresholds or sensor configurations for example.

Let me know if you found this useful and/or interesting.

 

Comments
Alex Radu
Kilo Explorer

Thank you so much for sharing information about how MQTT works and even being able to present a diagram that explains the entire MQTT system in more detail. I just need it now because I'm going to defend my thesis on the latest technologies. I decided to give a little more information about MQTT and MQTT Broker. Now I understand the logic of the processes associated with MQTT and MQTT Broker. By the way, when I started testing and configuring MQTT Broker, my choice fell on MQTT Broker: Pro Edition for Eclipse Mosquitto https://cedalo.com/mqtt-broker-pro-mosquitto/. I think it is the best MQTT Broker that stabilizes and improves data transfer between devices.

Samuel O_Connel
Tera Contributor

I'm a big fan of the Home Assistant Project, which has a framework for ESP-based devices called ESPHome. The framework allows the devices to be easily integrated into Home Assistant, with data collected and written into its SQLite database. Home Assistant allows the use of other DBs, such as MariaDB, where a JDBC connection can be set up. A scripted REST API could be made in SN, and Home Assistant could push the data using Node-RED, which has similarities to Flow Designer. This is, of course, an alternate solution to what you have implemented.  

Version history
Last update:
‎07-03-2020 03:07 PM
Updated by: