MQTT Data in HTML panel

Hi,
I’ve been playing around trying to get some mqtt interaction into a panel and was wondering if there is anyone else looking at doing this as well?

My first pass is to use the Paho javascript client, it kind of works but disconnects and reconnects a lot. (still tracking this down).

I would really like a panel plug-in maybe I’ll give it a go when I get some spare time.

Here my attempt, all suggestions/comments are welcome. I just added to following to a text panel as html. (with my details of my broker)

<h1>MQTT</h1>
<div id="mqtt_panel01">
    <div>Topic: <span id="topic01">#</span><span>, Status: </span><span id="status01">#</span></div>
    <button class="btn btn-inverse" type="button" onclick="publish('on','test/grafana/panel/status', 0)">On</button>
    <button class="btn btn-inverse" type="button" onclick="publish('off','test/grafana/panel/status', 0)">Off</button>
    <div><span id="request01">#</span></div>
</div>

<script>
    var mqtt;
    var reconnectTimeout = 5000;
    var host = 'mqtt.example.com';
    var port = 8883;
    var topic = 'test/grafana/panel/status';
    var useTLS = true;
    var username = "user";
    var password = "user1234";
    var cleansession = true;
    var path = "";
    var buttons = $('[type=button]');

    buttons.prop('disabled', true);

    function MQTTconnect() {
        if (typeof path == "undefined") {
            path = '/mqtt';
        }
        mqtt = new Paho.MQTT.Client(
            host,
            port,
            path,
            "web_grafanaPanel" + parseInt(Math.random() * 10000, 10)
        );
        var options = {
            timeout: 3,
            useSSL: useTLS,
            cleanSession: cleansession,
            onSuccess: onConnect,
            onFailure: function (message) {
                $('#status01').html("Connection failed: " + message.errorMessage + "Retrying");
                setTimeout(MQTTconnect, reconnectTimeout);
            }
        };
        mqtt.onConnectionLost = onConnectionLost;
        mqtt.onMessageArrived = onMessageArrived;
        if (username != null) {
            options.userName = username;
            options.password = password;
        }
        // console.log("Host=" + host + ", port=" + port + ", path=" + path + " TLS = " + useTLS + " username=" + username + " password=" + password);
        mqtt.connect(options);
    }

    function onConnect() {
        $('#status01').html('Connected to ' + host + ':' + port + path);
        // Connection succeeded; subscribe to our topic(s)
        mqtt.subscribe(topic, {
            qos: 0
        });
        $('#topic01').html(topic);
        buttons.prop('disabled', false);
    }

    function onConnectionLost(response) {
        setTimeout(MQTTconnect, reconnectTimeout);
        $('#status01').html("connection lost: " + response.errorMessage + ". Reconnecting");
        buttons.prop('disabled', true);
    };

    function onMessageArrived(message) {
        var topic = message.destinationName;
        var payload = message.payloadString;
        $('#request01').html(payload);
    };

    var publish = function (payload, topic, qos) {
        // console.log('Sending: ' + JSON.stringify(payload));
        var message = new Paho.MQTT.Message(payload);
        message.destinationName = topic;
        message.qos = qos;
        mqtt.send(message);
    }

    if (typeof Paho === 'undefined') {
        var script = document.createElement('script');
        document.body.appendChild(script);
        script.onload = function () {
            MQTTconnect();
        }
        script.src = 'https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.2/mqttws31.min.js';
    } else {
       MQTTconnect();
    }
</script>

Regards,

2 Likes

Dear @yendor,

while I find your idea to display live data from MQTT directly in a panel interesting, I would like to point out a more conventional way where measurement data arriving over MQTT will get ingested into a timeseries database (here: InfluxDB) before being accessed by Grafana.

We answered a question coming from a similar context over here at

With kind regards,
Andreas.

Thanks @amotl for your comment,
I agree normally we display data that is in a timeseries database, but I was toying with the idea of using Grafana for control as well.

In this case I would like to send commands via MQTT and see feedback / status. At the moment we use the Node-Red UI for this function but it would by nice to do it all from one interface.

I suppose we could embed Grafana in a Node-Red HTML element or vice versa.

Regards,

1 Like

Dear @yendor,

Thanks, now I am getting your whole point. I probably should have scanned your code better.

This very much resonates with some thoughts we also already had when discussing the command & control channel to communicate back to upstream nodes within the Hiveeyes Project and how that would be operated exactly on top of the MQTT substrate.

While Node-RED is really powerful, we haven’t yet got friends as we wouldn’t know how to operate a multi-tenant non-interactive setup with it. As we just recently started to get better friends with Grafana and its internal interfaces in the course of [1-4], we would go for the “native way” of connecting the Browser to MQTT by MQTT over WebSockets, which in the best case would yield a Panel Plugin which can be operated in a standalone manner without depending on Node-RED. However, it still could interact with Node-RED using MQTT like with any other bus member.

In fact, this would be pretty much what you implemented and shared already. Thanks!

The reason for that is probably because the panel gets refreshed by the Grafana machinery on each refresh interval and maybe on additional conditions. So, by just folding all the connection management into a real Grafana plugin should already solve that issue.

Good to hear from people having similar ideas about how to bring MQTT closer to Grafana in a sensible way. Maybe we can find some time to work on a basic implementation which would go into that direction. Would you be able to share a screenshot of what your Node-RED interface for sending MQTT messages and displaying status information currently looks like to get an idea about where we should aim at interface-wise?

With kind regards,
Andreas.

[1] Giving the Grafana Worldmap Panel some love
[2] Ingesting hourly data from a JSON API
[3] Use "grafana-wtf" to search through all entities of a Grafana instance
[4] https://github.com/daq-tools/grafanimate

There not much to the interface just the standard buttons and a SVG, the colour of the svg change to show state currently stop and in manual.

A typical pump control and status
image

More than happy to help out, but I am very time poor right now (trying to get a Lorawan network setup and stable)

Regards,

1 Like

This looks clean and reasonable, thanks for sharing!

Good luck!

Dear @yendor,

We found others are looking into the same topic, so we tried to summarize our findings appropriately.

With kind regards,
Andreas.