Examples that publish/subscribe MQTT?

I'm trying to create a couple of nodes that are basically publishing and subscribing to MQTT.

I've got them configured so that I get the MQTT broker info. But I am not getting the 'connect' event. My code basically looks like:
module.exports = function (RED) {
'use strict';

    function STCONFIG(config) {
        RED.nodes.createNode(this, config);
        this.broker = config.broker;
        this.brokerConn = RED.nodes.getNode(this.broker);
        const node = this;
        if (this.brokerConn) {
            this.status({fill: 'red', shape: 'ring', text: 'node-red:common.status.disconnected'});
            this.brokerConn.register(this);
            console.log("registered")
            this.brokerConn.on("connect", () => {
                console.log("CONNECTED")
                node.status({fill: 'green', shape: 'dot', text: 'node-red:common.status.connected'});
                publish(this.brokerConn,config.map)
                node.on('input', function(message) {
                    publish(this.brokerConn,msg.payload)
                });
            })
            this.on('close', done => {
                if (node.brokerConn) {
                    node.brokerConn.deregister(node, done);
                }
            });
            this.brokerConn.connect();
        } else {
            this.error(RED._('mqtt.errors.missing-config'));
        }
    }
    RED.nodes.registerType('st-presence-config', STCONFIG);
};

On my output, I get the 'registered' line, but NOT the 'CONNECTED'. I'm clearly doing something wrong. I am assuming that what I am getting here with brokerConn is an instance of mqtt?

Is there some documentation that describes how to build nodes that work with the MQTT brokers?

Is the built-in mqtt node somehow deficient for your purposes?

1 Like

Yes, I am building my own nodes that use MQTT in it's implementation.

(well, technically I could, but I want to build my own nodes to make things simpler...)

Basically is there anything documented (or examples) of nodes that use the embedded MQTT client?

You will need to do a code review of the built-in MQTT nodes. They have everything you need in order to get started.

On GitHub (mqtt.js) there is a very simply example:

https://github.com/mqttjs/MQTT.js#example

Interesting use of the word,given how existing NodeRED nodes are the simplest to use things for MQTT on the planet :slight_smile:

2 Likes

Thanks, I tried to do exactly that in my code above (though I actually added the connect statement like in that example). But I still never seem to get the "connect" event.

I also took a look at the built-in node it never actually calls connect. But in my case when it enters my function the brokerConn is never connected. What is odd is that the status on the flow shows up as green and connected. But that doesn't appear to be because of my code...

I'm clearly missing something...

Building more of a turn-key solution.

Oh, I should say that what I am attempting to do is to leverage the (apparent) MQTT connection pooling that (appears) to be built into NodeRed.

I'm pretty sure I could just "roll my own" connection but that seems like the wrong approach...

I'm no expert (at all) but I think that some things that are available to core nodes might not be available to contrib ones

So its possible you might come against a hard wall trying to reuse core code into a contrib one

Nope - the core nodes are on a pretty level playing field with anything else. The only exceptions are the Link, Status and Catch nodes are they have more fundamental runtime behaviour.

The challenge here is more the mqtt-broker node hasn't been written to be a generically reusable mqtt client node. It serves the needs of the mqtt-in and mqtt-out nodes, which may or may not be all that is needed.

Having spoken to Scott on slack, his node needs to know specifically when the connection comes and goes - something the core mqtt nodes don't care about themselves. So the mqtt-broker node doesn't expose it directly. I have shown him how to access the raw mqtt client used by the mqtt-broker node to access the finer-grained events he needs.

That does put more of a burden on us not to change the internal implementation of the node; I'd prefer it if this was raised as a more general requirement and a proper design put in place that we could have confidence of in the longer term...

1 Like

Thanks. Yea, I am not in favor of just leveraging the implementation directly.

I suppose one option would be to expose some functionality (like events for 'connect'). But even then it would be pretty hard for someone to write a node that leveraged it since it is possible for the connection to be established before the node is called (seems unlikely, but there is basically a race condition).

I think for my particular case I may as well just manage my own connection since I shouldn't need it around for very long so I think I can take care of it.

So I had some thought on my drive in (it's not a long drive, so I haven't thought this through completely!).

It is clear that there is an attempt to allow custom nodes to share MQTT connections within Node Red; I think this is great. But for reasons above it is not possible for custom nodes to know when the connection changes.

I think this could be addressed by doing just two things:

  1. Promoting connection related events to all registered nodes
  2. When a node is registered, fire the current connection state to the newly registered node.

Thoughts?

Nick, thanks for the clarification. I think I ran into this while trying to embed the link node functionality in a custom node. The ui looked ok, but no events were passed. Is this a deliberate design choice? likely to be a permanent limitation?

Wow, so I refactored my node to basically manage it's own mqttjs client (I create my client after obtaining the brokerConn URL & options).

I basically connect, and once I get the connected event I publish my message.

To test, I have a simple flow with my config node, along with an MQTT In node on the topic so I can verify it's posting properly:

I am connecting to the MQTT on the local host.

What is happening when I run is I can basically see my connections ping-ponging between the two. One connects and the other disconnects, then it switches. Back and forth...

Any idea what's going on with that?

That typically happens if you use the same clientid for both connections

Yup. fixed!

I hate to wake an old thread, but this is the only info I've found accessing the MQTT broker client connection inside of a custom node.
I have a similar requirement as the OP. I'm not quite following what you were talking about in your post about talking to Scott and helping him get to a solution.

Is there a way for me to publish/subscribe from within a custom node's code-behind?
My entire project is based around MQTT, and having to string dozens, or even hundreds, of MQTT in/out nodes everywhere, is far too much boilerplate. I would love to be able to roll my own nodes, and just access the existing MQTT client connection to let it handle the work.

Is this possible or am I just missing the solution in the above conversations?

Thanks!

I think that what Nick was saying was simply that currently, you have to replicate what the mqtt in/out nodes do internally. If you use the same MQTT library, you can reuse much of the code through copy/paste into your own node.

Just make sure that you make the client id unique for every node instance.

Yep, makes perfect sense.
At least I can reuse the configuration node connection.
Thanks!

1 Like