Closing mqtt instance in a function node

I am trying to use a function node and the mqtt package in a function node.
So my code is executed on start (which is probably what's causing problems starting the flows here).
I do not have any code that handles closing mqtt connection/, the instance is started upon a deployment and never exited.
And what's even funnier , the code is doing console.log on connection. after first redeploy (restarting on docker, then redeploying), and after each redeploy i am seeing another connection in my EMQX dashboard.
And the message is received successfully and processed to the output (only one, a little bit slower than when we have only one client connected)

How can i successfully close a mqtt connection from a function node.
Tried saving the mqtt.connect object in context, and using it on stop, but no luck.

Here is the code:


    // If no existing client, create a new one
    var client = mqtt.connect(`${env.get('configuration').protocol}${env.get('configuration').url}`, {
        port: env.get('configuration').MQTTport,
        username: env.get('configuration').MQTTusername,
        password: env.get('configuration').MQTTpassword,
        clean: true
    });

    client.on("connect", function () {
        console.log("connected")
        node.status({fill:"green",shape:"dot",text:"connected"});
    
    });

client.on("error", function (error) {
    node.status({fill:"red",shape:"ring",text:"disconnected"});
    console.log(`modbus-calendar-MQTT:  ${env.get('configuration').hvacId} \n ${error}`);
    if (error.toString().includes('Authentication failed')) {
        var delay = Math.random() * (60000 - 20000) + 20000; 
        setTimeout(() => {
            console.log("Attempting to reconnect...");
            client.reconnect();
        }, delay);
    }
});
client.subscribe(`modbus-calendar/${env.get('configuration').hvacId}/#`, { qos: 2 });
    client.on('message', function (topic, message, packet) {
        msg.received = JSON.parse(message).Data;
        msg.topic = topic;
        node.send(msg);
    });

EDIT #1 I know i can turn on the Use Username as Client ID and only keep one connection for a username, but designing to run the flow on a raspberry pi, and actually have not tested if this haves a particular memory impact.

EDIT #2 When Use Username as Client ID is enabled after each deploy / restart flows memory memory usage is increased by 3.9-4.2mb (not happening when all flows disabled). The increase is 2.8-3.2mb when Use Username as Client ID is disabled.

Wouldn't it be simpler to use the MQTT nodes?

Yes, but then i do not have an option to dynamically pass any options in dynamically :confused:

Dynamic Subscription

The node can be configured to dynamically control the MQTT connection and its subscriptions. When enabled, the node will have an input and can be controlled by passing it messages.

Inputs

These only apply when the node has been configured for dynamic subscriptions.

action string
the name of the action the node should perform. Available actions are: "connect", "disconnect", "subscribe" and "unsubscribe".
topic string|object|array
For the "subscribe" and "unsubscribe" actions, this property provides the topic. It can be set as either:

  • a String containing the topic filter
  • an Object containing topic and qos properties
  • an array of either strings or objects to handle multiple topics in one

broker broker
For the "connect" action, this property can override any of the individual broker configuration settings, including:

  • broker
  • port
  • url - overrides broker/port to provide a complete connection url
  • username
  • password

If this property is set and the broker is already connected an error will be logged unless it has the force property set - in which case it will disconnect from the broker, apply the new settings and reconnect.

1 Like

mqtt-dyn

See here: Dynamic MQTT node's "actions->connect" guidance needed - #2 by Steve-Mcl

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.