MQTT-nodes with dynamic topics

My use case is having a bunch of identical devices, which communicate via MQTT.

They have a few "channel", which communicate via the same topic structure:

* devices/device1/infoTopic1
* devices/device1/infoTopic2
* devices/device1/infoTopic3
* devices/device1/infoTopic4
* devices/device1/infoTopic25
* devices/device1/commandTopic1
* devices/device1/commandTopic2
* devices/device1/commandTopic12 

and

* devices/device2/infoTopic1
* devices/device2/infoTopic2
* devices/device2/infoTopic3
* devices/device2/infoTopic4
* devices/device2/infoTopic25
* devices/device2/commandTopic1
* devices/device2/commandTopic2
* devices/device2/commandTopic12

What I want to achieve is

  1. copy the flow for device1 to one for device2
  2. change a flow.variable ("device1" or "device2", ...)
  3. be happy

If I use "dynamic subscription", then I have to add a for all 25 info-topics and 12 command-topics for each read or write action. Can I somehow use the "MQTT in"-node with some kinda logic so, that it just replaces the second part of the topic structure?

You can hardcode the topic using a combination of variables (I think)

  1. Set an environment variable on a group : MY_TOPIC = 'device1'
  2. Add your MQTT Node(s), to this group
  3. Set the topic name in the MQTT Node(s)

The below will subscribe to all topics of device1

devices/$(MY_TOPIC)/#

See : Subscribe to a topic : Node-RED

NOTE: I may have this completely wrong - I apologies if so (I don't do much MQTT)

Environment Variable substitution only works for the whole field, it can not be used for part of a field

Thanks @hardillb

Should still be able to use that method still right?

MY_TOPIC = 'devices/device1/#'

You can't use devices/$(MY_TOPIC)/# but I think there's nothing to stop you setting MY_TOPIC to "devices/device1/#" Not sure, I don't use environment variables like that.

How many MQTT-in and out nodes do you have - one for each device or one for each topic for each device? Are you using the + and # wildcards?

Just guessing that devices/device1/infoTopicnn is for messages from the device and devices/device1/commandTopicnn is for messages sent to it?

In this case I think your topics are not well structured because an MQTT-in node subscribing to devices/device1/# will get both kinds of message. You will need some way to filter out.
It might be worth considering something like info/device1/01 ... info/device1/25 and command/device1/01 ... command/device1/12

1 Like

Thanks for your help so far.

I've got more or less two main use cases:

  1. A bunch of Tasmota devices
  2. My two Kia EV6 electric cars, same model, same API, same everything

All of which more or less work the same, but (of course) should react to different topics for both info and command. So my thinking was initially simple: copy the flows and have them only differentiate with a variable aka "device name" in the topics. (Regardless the /info/# problem, that's a side quest so to speak! :wink: ).

As I can see, the current possibilities within MQTT-nodes are not prepared for this, so I either have to stick with my copied flows and change everything accordingly on ALL the flows. or to built a sophisticated entry for my both use cases, whithin one flow and distinguish the flows there. First one is kinda dull, because in case of changes, I'll have to do them in ALL as I said. Second one is kinda heavy-lifting to avoid changing them all.....

As Marcus suggest you can us # or also + to subscribe to multiple topics.

devices/+/+

]
you can then spilit the topic

myDevice = msg.topic.split("/")

You can then use myDevice[1] to route to various flows using link call nodes, by setting

msg.target = myDevice[1]
1 Like

you can also just use a switch node:

msg.topic includes "device2" ---> output 1.

After thinking about it for a moment. I did the following:

  1. added the environment variable for each flow adding the name of the device to the flow
  2. adding a function to build the writing and/or listening topics after each flow start
  3. injecting the names to the "mqtt in"-nodes and used them for the "mqtt out" ones.

So I'm happy... for now, because I noticed, the node-red-contrib-bluelinky nodes for the car don't allow for dynamic subscription of cars ... yet. :wink: So, I do have to change each "car action" nevertheless per flow. But my logic is now able to use variables, which is good. No more messing around with JS-code nodes. at least that. Thanks for your help!

1 Like