Change msg.topic via function

So :slight_smile:

Always found this to be a nice way to start asking questions.

I have an mqtt topic with a message where I wan't to keep the message but change the topic into 8 different topics.

I have an incomming mqtt:

topic = first/second/third/fourth/0
message = HelloWorld

Put together for simplicity:
first/second/third/fourth/0->HelloWorld

How do I "convert" this into 8 messages, which only changes the last number in the string topic, but keeps the message

Like this:

first/second/third/fourth/1->HelloWorld
first/second/third/fourth/2->HelloWorld
first/second/third/fourth/3->HelloWorld
first/second/third/fourth/4->HelloWorld
first/second/third/fourth/5->HelloWorld
first/second/third/fourth/6->HelloWorld
first/second/third/fourth/7->HelloWorld
first/second/third/fourth/8->HelloWorld

Topics are not the same length everytime, so it need's to be something where the last character in the topic is changed there can be no counting (unless this can be done from the back)

Hello,
If you want to do this in a function node you will have to look at two concepts.
First is iterating over something for a specified number of times. You can use the for loop for this:


You can do this to do something eight times.
Secondly you want to do some string manipulation. You can have a look at regex for this. Javascript has some build in regex functions. Have a look at:

and:
https://www.rexegg.com/
and

Here you can learn about and test regular expressions. You will have to look at anchors, quantifiers and tokens.
A combination of those two. Eg a replace with a regex inside a for loop that looks for the numbers at the end of the string.
you will also have to have a look at the node.send() function to send things from the function node while in the loop:
https://nodered.org/docs/user-guide/writing-functions
If you have more questions or need help figuring it out just ask.
stay healthy and have fun, Johannes

Hmm, here I was hoping for a simple solution... Well

I came up with this:

original = msg.topic
var first = original.slice(0, original.length-1);
msg.topic = first + 1;
node.send (msg);

second = first
var second = second.slice(0, second.length-0);
msg.topic = second + 2;
node.send (msg);

third = second
var third = third.slice(0, third.length-0);
msg.topic = third + 3;
node.send (msg);

fourth = third
var fourth = fourth.slice(0, fourth.length-0);
msg.topic = fourth + 4;
node.send (msg);

fifth = fourth
var fifth = fifth.slice(0, fifth.length-0);
msg.topic = fifth + 5;
node.send (msg);

sixt = fifth
var sixt = sixt.slice(0, sixt.length-0);
msg.topic = sixt + 6;
node.send (msg);

seventh = sixt
var seventh = seventh.slice(0, seventh.length-0);
msg.topic = seventh + 7;
node.send (msg);

eight = seventh
var eight = eight.slice(0, eight.length-0);
msg.topic = eight + 8;

return msg

Now I will have to test to see if this actually does what I hope it will....

Have a look at this:

let newtopic = msg.topic;
for(i=0;i<8;i++){
    newtopic = newtopic.replace(/[0-9]*$/g, "")+(i+1);
    node.send({payload:msg.payload,topic:newtopic});
}
node.done();
return;

This is what I described above utilizing the methods i linked.
We use a for loop to do something eight times

for(i=0;i<8;i++)

we than use the regex replace to replace numbers at the back of the topic string with nothing hence the "" and use the counter var i of the for loop to add a new number to the string (we have to add 1 as the counter starts at 0)

newtopic = newtopic.replace(/[0-9]*$/g, "")+(i+1);

have a look here for what this specific regular expression does https://regex101.com/r/nA7x1m/2
Now we use the asynchronus node.send() to send the result of each loop.

node.send({payload:msg.payload,topic:newtopic});

after the loop we use the node.done() to tell the runtime that the function node is finished and return it without sending a further message.
I hope this makes sense.
Johannes

1 Like

If you just want to do this specific case then switch followed by eight parallel change nodes to change the topic

Hi

That works too, BUT: I have NO idea or do I understand how that worked.....

With <8 and 0-9

Could I change these into <20 and 0-21 if I wanted ot execute more topics?

@cymplecy This was what I did before, but required that I knew which topics were incomming.... I wanted a solution where I could handle all incomming topics (ofcause in specific topic levels)

Tried but that did not work :slight_smile:

Problem occured when there was 2 number which needed to be deleted, and this was not math.......

Its all explained in the links I posted. The [0-9] is part of the regular expression and just means only look for numbers. The only thing you need to change is the i<8 in the for loop.
So I ll explain what the things in the for loop definition do and what the regex does:

for(i=0;i<8;i++)

i is our counter var we give it a starting value, in this case 0 i=0
we want the loop to run eight times so this is what the second part does:
i<8 the loop will run as long as i is smaller than 8.
the third part defines something we do to i on every loop, in this case i++
++ is an increment operator https://codeburst.io/javascript-increment-and-decrement-8c223858d5ed
so it counts up i by one on every loop, so its the same as writing i+=1 or i=i+1
So i will be 0 than 1 than 2 than 3... but it will never reach eight as the loop will break as soon as it is >=8 because the second part wont be true anymore.

/[0-9]*$/g

is a regular expression which can be used to make rules to find stuff in strings. They are something that is used in allmost all programming languages.
This one has three main parts
[0-9] means were only looking for number characters in the string
* means dont stop after you find the first number because their might be more
$ anchors the search to the back of the string
So the regex will find any number characters at the back of a string.
https://regex101.com/r/nA7x1m/2 click on the link and play around with it, its great to understand this and this site is very good at showing you whats going on.

I hope this explains some of it. Those methods are great to have in your toolkit.
Best regards Johannes

[{"id":"e998f937.a449e8","type":"function","z":"f954564f.03e718","name":"","func":"let newtopic = msg.topic;\nfor(i=0;i<20;i++){\n    newtopic = newtopic.replace(/[0-9]*$/g, \"\")+(i+1);\n    node.send({payload:msg.payload,topic:newtopic});\n}\nnode.done();\nreturn;","outputs":1,"noerr":0,"x":470,"y":3620,"wires":[["1b24bd31.7fe503"]]},{"id":"ffe0d075.aa1f1","type":"inject","z":"f954564f.03e718","name":"","topic":"test/thisisatest/6089","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":320,"y":3620,"wires":[["e998f937.a449e8"]]},{"id":"1b24bd31.7fe503","type":"debug","z":"f954564f.03e718","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":630,"y":3620,"wires":[]}]

Have a look at this, the topic has 4 numbers at the end and the loop repeats 20 times

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