Beginner questions on IF expressions and wildcard usage in function node

I keep resolving to leave this topic alone but it's somehow compelling.

In these two quotes you turn your back on the normal, non procedural solution because you want different behaviour based on two seperate message properties.
You seem to be missing a trick. Concatenate msg.topic and msg.Time into one more property msg.topictime.
Mind you, if you had not insisted on splitting your processing into "tasmota: Power[0]Delta", "tasmota: Power[1]Delta" and "tasmota: Power[2]Delta" you wouldn't need to rejoin them.

====================================================================

Regarding MQTT

I believe that the dynamic subscription feature of the MQTT node lets you do that.
However, it seems bad form to use the MQTT broker as a data store simply because you can't adequately manage your context variables.

Oh, I will test that :slight_smile:

@Colin
I merged the three PowerDeltas during the weekend for better processing.

I have everything up and running now but I need to handle the discovery before it is finished.

The problem is that I changed the Prefix to prevent Home Assistant from receiving the unprocessed data. But tasmota writes this Prefix to the discovery message and Home Assistant then changes the subscription on the next restart.

So now I need to change the discovery message.

Missing piece of the puzzle right now is how to use dynamic subscription to first unsubscribe and then subscribe.

I can subscribe. I can unsubscribe. But how do i create a sequence of first unsubscribing and then subscribing a few milliseconds later?

I hesitate to suggest this, but a trigger node.

Or of course in a function node

node.send (unsubscribemessage)
do something to waste a few milliseconds
node.send(subscribemessage)

You are missing the point. There is no need to if you organise your data better

However, for the 3rd yuk of the day...

I am trying to not disconnect/connect but to unsubscribe/subscribe because that will only affect the one node I am triggering.

But I cannot figure out how to change msg properties with a trigger node. I seem to only be able to change the msg.payload, not msg. topic and msg.action.

EDIT:
Think I got it to work with

[{"id":"70e9b55ef7ca2f55","type":"delay","z":"c36d205f4de85948","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":420,"y":440,"wires":[["a5eeb4cb3f73c925","b50de04198753bc2"]]},{"id":"a5eeb4cb3f73c925","type":"debug","z":"c36d205f4de85948","name":"debug 332","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":560,"y":360,"wires":[]}]

Is it possible to share just one flow in a project?
So far Node-RED shared all my flows in my github repo.

For public sharing I would like to share just his one... and not my playground mess :smiley:

You need to select the nodes and then export.

I meant when using the Node-RED github projects feature.

I don't believe you can, AFAIK, each project has a flow file. That file encapsulates all of the flows.

1 Like

Just to keep you updated:
I am currently in the testing phase to find bugs or pitfalls and make sure that only the data I want is received by Home Assistant.
I will share with information as soon as I think I have found all the bugs :slight_smile:

The unsubscribe/subscribe routine is bugging me.

The manual triggering just does not seem to work, or at least it does not cause an update of all subscribed topics (I do not know which).

Steve-McI posted a nice flow with subscription methods but it seems some of it is deprecated.
The action get Subscriptions is no longer a known action.

Is there a replacement? I would really like to figure out why

[{"id":"1657173e48fb201c","type":"function","z":"c36d205f4de85948","g":"a226a0e21c332e03","name":"unsubscribe & re-subscribe \\n to tasmota/discovery/+/#","func":"msg.action=\"unsubscribe\"\nmsg.topic=\"tasmota/discovery/+/#\"\nnode.send(msg)\nmsg.action=\"subscribe\"\nmsg.topic=\"tasmota/discovery/+/#\"\nnode.send(msg)","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":220,"wires":[["70e9b55ef7ca2f55"]]},{"id":"70e9b55ef7ca2f55","type":"delay","z":"c36d205f4de85948","g":"a226a0e21c332e03","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":760,"y":220,"wires":[["b50de04198753bc2"]]},{"id":"b50de04198753bc2","type":"mqtt in","z":"c36d205f4de85948","g":"a226a0e21c332e03","name":"Update discovery topics \\n on manual triggering","topic":"","qos":"0","datatype":"json","broker":"0d7f426189a0c8d3","nl":false,"rap":true,"rh":0,"inputs":1,"x":1000,"y":220,"wires":[["f932ad76700449cb"]]},{"id":"0d7f426189a0c8d3","type":"mqtt-broker","name":"MQTT RPi","broker":"192.168.0.2","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

with a rate limited does nothing but deploying always updated all subscriptions.

Pretty sure I said this was not the best solution and provided an alternative solution.

Only retained topics will be transmitted upon connection - perhaps some topics are not retained.

It is not depreciated, simply a hidden feature. There are no plans to remove it as of writing.

The local storage is great and I might tackle it in version 2, but right now it is more versatile to listen to the sources live and process on the fly.

I will try your unsubscribe/subscribe chain again. I am just surprised I would need to split it into to mqtt nodes.

When I tried the getSubscriptions action I got an error message in the debugger (sorry, not at home, cannot post) and the debug node behind the mqtt node did not show any output.

I dont understand what you mean by this?

Reading between the lines (your earlier comment about "being unreliable" and looking at the code in your function

msg.action="unsubscribe"
msg.topic="tasmota/discovery/+/#"
node.send(msg)
msg.action="subscribe"
msg.topic="tasmota/discovery/+/#"
node.send(msg)

Then perhaps you are a victim of async JavaScript + "by reference"

To avoid the chance of the msg objects properties being changed by reference, before it is actioned, your code should be:

const topic = "tasmota/discovery/+/#"
node.send({ topic, action: "unsubscribe" })
node.send({ topic, action: "subscribe" })
1 Like

According to the docs node.send() clones by default, but can take a second argument which can be set to false to prevent it cloning.

Yeah, valid point - stoopid failing brain!.

Somehow, I still feel more comfortable explicitly sending a brand new object.

I suppose I could argue, should that change at any point (or be buggy) my offering would still work (he says, tenuously clawing back credibility)

If nothing else, your code just looks way cooler :wink:

But I think that strangely I made a mistake because I was using tasmota/discovery/+/# and so it did not listen to the parallel topic on the third level. So I changed it to tasmota/discovery/# and now it seems to work. I have no idea if I typed that in after I had it working before or what happened there. But clearly a brain fart on my end!!!!

Oh boy, how embarrassing!

Doing some code cleaning based on what I have learned.

I am now trying to iterate through an object using i and would like to dynamically create msg properties.

But it seems that my syntax is incorrect. Is msg a dynamic object or a dictionary-like structure that allows dynamic property assignment?

msg.DeviceName = 1   // working
msg.PowerDelta[i] = 1  // not working "TypeError: Cannot set properties of undefined (setting '0')"
msg.PowerDelta1 = 1 // working

It is difficult to be certain because you have not shown us what comes before that, but I suspect the problem is that you have not declared msg.PowerDelta to be an array before that line. You cannot use an array variable until after it has been declared. So probably you want
msg.PowerDelta = []
before that line.

The fact that you are not using the js convention for variable names makes it hard work answering your questions as my muscle memory wants to type msg.powerDelta.

Another possibility is that i is unknown at that point, but I think it would be a different error in that case.

Thank you, Colin.

Yes, i is of course known at this point and successfully used. I still lack a lot but I have gotten good and finding my causes... just still need help in solving some of them :wink:

Declaring as array first instead of just initializing the array with the "normal" syntax seems a bit strange, but then I will need to declare them first. :slight_smile:

I have mixed feelings about lowerCamelCase, because it is not real CC and it then means I will either have lower case variables/arrays etc. or artificially CCed ones.

msg.Update // clearly user made due to captial letter
msg.update // unknown because could be lCC or system
msg.upDate // artificial

I will maybe switch everything to lowerCC once I am done :slight_smile: