MQTT Status Dashboard

Create a HTML (Javascript) Dashboard for MQTT-Devices based on the retained and last-will Messages of the MQTT-Protocol.

To monitor the status of MQTT-Devices (like my light-blubs, the doorbell ...) I want to create a solution based on the MQTT features "Last will and testament" and "Retained Messages". The idear is that all devices I build have some "Rules" to follow. Based on this rules I can create a Dashboard for all Devices.

First of all i defined a "Status" message.

{
  "status": 0, 
  "description": "This is just another example", 
  "criticalInfrastructure": false, 
  "extra": {
  }
}

After this i definded some rules for each value:

  • "status" can be 1 (online), 0 (offline), -1 (connecten to broker failed)
  • "description" just a string with a description for this device
  • "criticalInfrastructure" if this value is true the device is critical if the Status is 0 or -1 (if it false, only -1 is critical)
  • extra can be defined by each device

Based on this rules i create a "EchoBot" as example device. Its a small Python script:

 

import os
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    
    client.publish("admin/status/echoBot", '{"status": 1, "description": "Test Echo Bot", "criticalInfrastructure": true, "extra": {}}', 1, True)
    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    client.subscribe("admin/echo")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    client.publish("admin/echoresponse", 'You send: '+str(msg.payload), 0 , False)
    print(msg.topic+" "+str(msg.payload))

client = mqtt.Client()
client.will_set("admin/status/echoBot", '{"status": -1, "description": "Test Echo Bot", "criticalInfrastructure": true, "extra": {}}', 1, True);
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(os.environ["username"], os.environ["password"])
client.connect(os.environ["mqttserver"], 1883, 60)

# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()

This script can't disconnect on a "regular" way. So it just have the status 1 and -1. If I start the script it connect to a MQTT-Server. If the connection is established the Script send the message with "status" is 1. The QoS ist 1 and the last True defined that the message is retained. Befor the script connect it set the client.will_set the Last will and Testament Message. It contains the same Information like the connect message, just the status is -1. So if the device disconnect (without calling the disconnect function, which is not used in this script) the MQTT-Broker send this message. Also this message is retained.

Its importend to use retained Messages! This way the Server always saved the last Status. If each device use its own topic under admin/status/<NAME> I can subscribe to "admin/status/+" and get all status Messages for each device, the device name based on the topic.

To create a Web-Gui with the Status of each Device I used a Javascript MQTT Client which connect to a MQTT Broker via WebSockets.

The Page-Conent is really easy just include some Javascript and CSS (Bootstrap) Files from CDNs and create a div with the id "box" to add the Status-Cards inside. The Dashboard don't need to know which devices are avalible at the broker, it show the status of all devices.

<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<style type="text/css">
.card {
    margin-right: 10px;
}
</style>

<div class="container">
    <h1>MQTT-Device-Dashboard</h1>
    <div class="row" id="box">
    </div>
</div>

Just add some Javascript-Code to connect to the MQTT Server, create a Card if there is no Card for that Device and set the Background-Color of the Card based on the status:

client = new Paho.MQTT.Client("HOSTNAME", PORT, "/mqtt", "mqtt-dashboard");
client.onMessageArrived = function (message) {
    var msg = jQuery.parseJSON(message.payloadString)
    var name = message.destinationName.substring(message.destinationName.lastIndexOf("/") + 1);

    if (! $( "#"+name ).length ) {
        html = '<div id="'+name+'" class="card  mb-3" style="max-width: 20rem;"><div class="card-header"><b>'+name+'</b></div><div class="card-body"><p class="card-text">'+msg["description"]+'</p></div></div>';
        $("#box").append(html);
    }

    $("#"+name).removeClass("bg-success");
    $("#"+name).removeClass("bg-warning");
    $("#"+name).removeClass("bg-danger");
    if(msg["status"]==1) {
        $("#"+name).addClass("bg-success");
    }
    if(msg["status"]==0) {
        $("#"+name).addClass("bg-warning");
    }
    if(msg["status"]==0 && msg["criticalInfrastructure"] == true) {
        $("#"+name).removeClass("bg-warning");
        $("#"+name).addClass("bg-danger");
    }
    if(msg["status"]==-1) {
        $("#"+name).addClass("bg-danger");
    }
};

client.connect({
    "userName": "USERNAME",
    "password": "PASSWORT",
    "onSuccess": function() {
        client.subscribe('admin/status/#', {qos: 0});
        console.log("Connection Success");
    },
    "onFailure": function() {
        console.log("Connection Failed");
    }
});

 

Based on this code I get the following Output:

The complete Sourcode of the Dashboard is avalible at this Github Gist.




Veröffentlicht: 10.11.2017