Mqtt in subflow

I'm using mqtt for rpc calls from Thingsboard. Basically request/response.

Every incoming topic is on this format:
msg.topic: "v1/devices/me/rpc/request/X"

and the response must update to:
msg.topic: "v1/devices/me/rpc/response/X"

Since this is universal and used many different places, I wanted to make a subflow of it to apply the topic once and for all. However, the subflow always stays disconnected! Normal mqtt out node works fine. I also tried moving broker config to subflow env, but still disconnected. Anyone have any good ideas here?

Example subflow:

[
    {
        "id": "f95ab49ee1f58ce2",
        "type": "subflow",
        "name": "tb mqtt response",
        "info": "Automatically set response topic.\r\n\r\nInput:\r\nmsg.topic: \"v1/devices/me/rpc/request/15\"\r\n\r\nSend to TB mqtt response:\r\nmsg.topic: \"v1/devices/me/rpc/response/15\"\r\n",
        "category": "network",
        "in": [
            {
                "x": 120,
                "y": 120,
                "wires": [
                    {
                        "id": "724cba2270fcda01"
                    }
                ]
            }
        ],
        "out": [],
        "env": [],
        "meta": {},
        "color": "#D8BFD8",
        "icon": "node-red/bridge.svg",
        "status": {
            "x": 420,
            "y": 200,
            "wires": [
                {
                    "id": "fbd497cf63e7ba7a",
                    "port": 0
                }
            ]
        }
    },
    {
        "id": "9d81d107b4711d9d",
        "type": "mqtt out",
        "z": "f95ab49ee1f58ce2",
        "name": "",
        "topic": "",
        "qos": "0",
        "retain": "false",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "c032668b54c22629",
        "x": 390,
        "y": 120,
        "wires": []
    },
    {
        "id": "724cba2270fcda01",
        "type": "function",
        "z": "f95ab49ee1f58ce2",
        "name": "topic response",
        "func": "msg.topic = msg.topic.replace(\"/request/\", \"/response/\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 240,
        "y": 120,
        "wires": [
            [
                "9d81d107b4711d9d"
            ]
        ]
    },
    {
        "id": "fbd497cf63e7ba7a",
        "type": "status",
        "z": "f95ab49ee1f58ce2",
        "name": "",
        "scope": [
            "9d81d107b4711d9d"
        ],
        "x": 320,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "c032668b54c22629",
        "type": "mqtt-broker",
        "name": "Thingsboard",
        "broker": " ",
        "port": "",
        "clientid": "",
        "autoConnect": false,
        "usetls": false,
        "protocolVersion": "5",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]

this is an odd value - should be a node reference.

UPDATE: ignore. I read the wrong part of flow.

Oh right, I wasn't happy with hardcoding config & credentials, so I set connection dynamically. Empty space is perhaps just to avoid error message.

Connection is still green for both normal mqtt in and out nodes.

well, looking at your very minimal (and TBH totally unnecessary in this instance) subflow, i cannot tell if you are ever sending a msg with the necessary pieces of information to make it connect to anything. The MQTT node inside is set to "not auto connect" and the address is empty - so i assume you are sending the appropriate message with necessary props in?

Why is it totally unnecessary?

The connection to this config is handled in another flow:

It's mostly the set connection node that does the work here:


const output = {
    action: "connect", // "connect" / "subscribe"
    topic: "v1/devices/me/rpc/request/+",

    broker: {
        broker: env.get("TB_MQTT_BROKER"),
        port: 1883,
        
        force: false, 
        cleansession: false,
        protocolVersion: 5,

        clientid: env.get("TB_MQTT_CLIENT_ID"),
        username: env.get("TB_MQTT_USER"),
        password: env.get("TB_MQTT_PASS")
    }
};

const connectMsg = RED.util.cloneMessage(output);
const subscribeMsg = RED.util.cloneMessage(output);
subscribeMsg.action = "subscribe";

return [[connectMsg, subscribeMsg]];

I started with this setup where I had single mqtt in and single mqtt out, then use links to everywhere it was needed. But has since discovered I can use duplicates of the mqtt in/out nodes directly instead. This works for mqtt in without hassle, but mqtt out needs this one line of javascript to update topic from request to response.

It is unnecessary because it complicates matters just as you see here.

The flow you sent embeds a broker. That broker is completely separate to the one you are instructing to connect.

Either stick with link call (my recommendation) or pass the config into subflow as an env var.

1 Like

Link call must have an output. I don't want an output :smiley: Link calls are far too limited to replace the flexibility of subflows.

However, I did pass config as env var to subflow, but that stays disconnected as well :frowning:

I also tried moving broker config to subflow env, but still disconnected.

Edit:
It is slightly confusing to me how I'm able to select a mqtt broker inside the subflow, but at the same time it is completely separate. If it is separate, it shouldn't be available in the dropdown list IMO. I know each time the subflow is used, it creates a new instance. But it isn't clear to me that each subflow instance also creates a clone of any selected config instance?

When using normal mqtt in/out nodes, it looks like all of them attaches to the same, single mqtt config node. So if that one config is connected, all mqtt in/out nodes that is configured to use it are also connected? And same with disconnected. Likewise, why isn't this true when used inside a subflow? How does the subflow create another config? Is this "virtual"? The new mqtt config won't be selectable outside the subflow? Will it be the same for multiple mqtt nodes inside the subflow that is configured to use the same "virtual" clone. Or will each mqtt node inside a single subflow create their own separate clone?

Deployed using "full" and now they are all connected (pressumably using the same mqtt config instance). Seems like every time I add a new instance of the subflow or edit the subflow, I need to redploy fully for it to connect. Sorry for the confusion.