# Good way to duplicate flow for multiple, almost identical devices

**URL:** <https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191>\
**Category:** General\
**Created:** [16 March 2020 16:27 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191 "2020-03-16T16:27:12Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![m\_elias](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@m\_elias](https://discourse.nodered.org/u/m_elias)\
**Post date:** [16 March 2020 16:27 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/1 "2020-03-16T16:27:12Z")

</div>

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/#

 ![flow](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/9/09f9da7d15bfae6abdeffcfb414568ae1644bdcf.jpeg)

```auto
[{"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?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [16 March 2020 17:26 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/2 "2020-03-16T17:26:38Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![m\_elias](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@m\_elias](https://discourse.nodered.org/u/m_elias)\
**Post date:** [16 March 2020 19:36 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/3 "2020-03-16T19:36:32Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [16 March 2020 21:00 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/4 "2020-03-16T21:00:43Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![m\_elias](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@m\_elias](https://discourse.nodered.org/u/m_elias)\
**Post date:** [16 March 2020 21:43 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/5 "2020-03-16T21:43:30Z")

</div>

> 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?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [16 March 2020 22:07 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/6 "2020-03-16T22:07:09Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [16 March 2020 22:10 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/7 "2020-03-16T22:10:54Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![m\_elias](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@m\_elias](https://discourse.nodered.org/u/m_elias)\
**Post date:** [17 March 2020 03:25 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/8 "2020-03-17T03:25:03Z")

</div>

@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/#

---

<div class="post-metadata">

**Author:** ![m\_elias](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@m\_elias](https://discourse.nodered.org/u/m_elias)\
**Post date:** [17 March 2020 03:33 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/9 "2020-03-17T03:33:37Z")

</div>

> [@Colin](#):
>
> 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

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?

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [17 March 2020 04:43 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/10 "2020-03-17T04:43:02Z")

</div>

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.

> [@m\_elias](#):
>
> farm/fans/device1/cmd will be an mqtt input node in place of all those inject nodes on the left side.

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.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 March 2020 09:09 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/11 "2020-03-17T09:09:11Z")

</div>

> [@m\_elias](#):
>
> if (msg.payload.hasOwnProperty("farm/fans/test/cmd/mode"))

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

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [17 March 2020 09:14 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/12 "2020-03-17T09:14:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 March 2020 09:30 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/13 "2020-03-17T09:30:57Z")

</div>

> [@dceejay](#):
>
> Is that really in the payload ? looks more like an mqtt topic

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

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [16 May 2020 09:30 UTC](https://discourse.nodered.org/t/good-way-to-duplicate-flow-for-multiple-almost-identical-devices/23191/14 "2020-05-16T09:30:58Z")

</div>

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