Good way to duplicate flow for multiple, almost identical devices

I have an application for a join node, which needs to be duplicated for a dozen identical flows (except one branch of their mqtt topic is unique).
farm/fans/[device1:device2:etc]/cmd/#

[{"id":"53f6c7f2.440858","type":"inject","z":"4c195d90.05acd4","name":"Mode 3","topic":"farm/fans/test/cmd/mode","payload":"3","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":200,"y":660,"wires":[["213bd5df.55d40a"]]},{"id":"b63ead4.c02a15","type":"inject","z":"4c195d90.05acd4","name":"Min Speed Drying 10","topic":"farm/fans/test/cmd/minspddrying","payload":"10","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":160,"y":720,"wires":[["213bd5df.55d40a"]]},{"id":"48849e20.dab9f","type":"inject","z":"4c195d90.05acd4","name":"Temperature 5","topic":"weather/tempc","payload":"5","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":880,"wires":[["213bd5df.55d40a"]]},{"id":"213bd5df.55d40a","type":"join","z":"4c195d90.05acd4","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"5","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":430,"y":780,"wires":[["c1b70fb8.3fbe5"]]},{"id":"5ceae7e3.d32c18","type":"function","z":"4c195d90.05acd4","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":730,"y":780,"wires":[["4d02cf2.fd7033"]]},{"id":"4d02cf2.fd7033","type":"debug","z":"4c195d90.05acd4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":770,"y":840,"wires":[]},{"id":"ce13bb5b.7e8158","type":"inject","z":"4c195d90.05acd4","name":"Max Speed Drying 75","topic":"farm/fans/test/cmd/maxspddrying","payload":"75","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":160,"y":780,"wires":[["213bd5df.55d40a"]]},{"id":"28a5da98.a897b6","type":"inject","z":"4c195d90.05acd4","name":"Temperature 0","topic":"weather/tempc","payload":"0","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":840,"wires":[["213bd5df.55d40a"]]},{"id":"f93bfb37.2f5408","type":"inject","z":"4c195d90.05acd4","name":"Temperature 25","topic":"weather/tempc","payload":"25","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":920,"wires":[["213bd5df.55d40a"]]},{"id":"76d60153.366b3","type":"inject","z":"4c195d90.05acd4","name":"Temperature 30","topic":"weather/tempc","payload":"30","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":960,"wires":[["213bd5df.55d40a"]]},{"id":"b4357583.d03f48","type":"inject","z":"4c195d90.05acd4","name":"Humidity 30","topic":"weather/humidity","payload":"30","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1020,"wires":[["213bd5df.55d40a"]]},{"id":"6b6d7524.25a44c","type":"inject","z":"4c195d90.05acd4","name":"Humidity 40","topic":"weather/humidity","payload":"40","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1060,"wires":[["213bd5df.55d40a"]]},{"id":"1af4bdfd.095f32","type":"inject","z":"4c195d90.05acd4","name":"Humidity 85","topic":"weather/humidity","payload":"85","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1100,"wires":[["213bd5df.55d40a"]]},{"id":"94bec3ca.b9a8f","type":"inject","z":"4c195d90.05acd4","name":"Humidity 95","topic":"weather/humidity","payload":"95","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1140,"wires":[["213bd5df.55d40a"]]},{"id":"c1b70fb8.3fbe5","type":"switch","z":"4c195d90.05acd4","name":"","property":"payload[\"farm/fans/test/cmd/mode\"]","propertyType":"msg","rules":[{"t":"eq","v":"3","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":570,"y":780,"wires":[["5ceae7e3.d32c18"],["279eb0f4.8e0ff"]]},{"id":"279eb0f4.8e0ff","type":"debug","z":"4c195d90.05acd4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":590,"y":840,"wires":[]},{"id":"638a0b06.5b4c94","type":"inject","z":"4c195d90.05acd4","name":"Mode 1","topic":"farm/fans/test/cmd/mode","payload":"1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":620,"wires":[["213bd5df.55d40a"]]}]

What is a good way to duplicate the flow so that if I change one flow, they all change? If I create a sub flow, it would only include the join and function nodes and I still have to modify each mqtt node when I duplicate the flow?

I envision I could use one flow if the join node could be setup in a two tier system. What I mean is, can it join 5 payloads from each device separately in the same join node?

You could subscribe to farm/fans/+/cmd/# then follow that with a Switch node to route based on the device code. Then put the Join node and as much of the rest of the logic as you can in a Subflow and have multiple instances of that, one for each device. Not perfect I know but I can't think of anything else using the Join node.

The alternative would be to write a DIY Join node which copes with the multiple levels, which would not be that difficult, but not trivial.

I think I probably leave out the switch node then, add the join node to the subflow and just duplicate the mqtt in node with a copy of the subflow for each device.

I think you are right, I was sent down the wrong track by the test flow with multiple injects, but in fact you can get everything from one mqtt node per device so that is the simplest way to do it.

I suppose another alternative would be to have one Join node joining all the topics from all devices then split it up afterwards based on the individual topics. You can tell which device the most recent message came from as the topic of the current message is passed through the Join node.

1 Like

I suppose another alternative would be to have one Join node joining all the topics from all devices then split it up afterwards based on the individual topics.

So if I have 5 devices * 5 topics, the join node would need to be set wait for 25 parts, and if I add a 6th device, I'd need to update the join node for 30 parts? I'm trying to setup my flow(s) so that there's the least amount of modification needed when adding devices or making changes to my main function node, doesn't clutter up my flow area/tab/sheet and isn't difficult to understand the flow.

You can tell which device the most recent message came from as the topic of the current message is passed through the Join node.

This way my function node would know which device to update. Sounds like I could use one mqtt in node like you suggested for all devices, one super join node and one function node to process all my devices. The only change needed when adding devices would be the join node?

You could set the number of parts to 1 so it will start giving you partial data straight away, then in the function node test that you have all you need for that device and do nothing if not, or perhaps you can do something even if you haven't got everything for the device

Quick question:

Your original post......

I can't see the line between the remote device and the central one.

I also can't see where the farm/fans/[device1 (etc) is.

So if you have a lot of remote devices (Raspies I'm guessing) there isn't much of a simple way to change one: change them all.
As each device is separate.

At best you have another remote device and you update it's flow.
When that is updated, it updates the other remote machines.
But that will require more code to do all that.

@Trying_to_learn
I don't understand your comment about the line between remote and central device

farm/fans/device1/cmd will be an mqtt input node in place of all those inject nodes on the left side. I'm actually leaning towards trying Colin's suggestion of using a one mqtt in node for all the devices with a topic of farm/fans/+/cmd/#

You're correct, in some cases I won't need all the data. What's the best way to check if I have the necessary topics & payloads in my function node? I've come across the hasOwnProperty method in the past. I'm thinking as many nested
if (msg.payload.hasOwnProperty("farm/fans/test/cmd/mode"))
as needed?

The first flow you posted.... To me it is a lot of nodes who's messages are joined together to make a message.

Nice. But where does that happen? On the remote machine or the local machine?

There isn't (or I can't see it) any farm/fans/device1/cmd shown anywhere other than in the text you posted.

So I am having difficulty understanding - from the original post- what is what and where it is.

You didn't exactly say that in the post.

Yes, I agree with Colin's approach.

That will simplify message segregation easier than parsing them with other nodes.

That is as good a way as any other I think. You could also test for undefined but hasOwnProperty is possibly clearer.

Is that really in the payload ? looks more like an mqtt topic (msg.topic) to me...

Yes, it is mqtt into Join node in key/value mode, so the values are in payload["mqtt/topic"]

1 Like

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