Changing global variable inside the function node

I am trying to keep the info about Sonoff state in the memory, than compare it with the incoming messages and the result I am sending to the ui switch node.
For example I am sending mqtt cmnd/sonoffs/STATE request to get responses from all switches on the network. I have default switch state values stored in the global variables and I am rewriting it by the returning mqtt infos. Sometimes, some of the switches do not respond. After 3 second delay, I am sending the result to the switch. (see inject node named cmnd/sonoffs/STATE)
https://pastebin.com/embed_js/ssMuYPM3"

I am still ready to re-think the design. Maybe wrong philosophy from the early begging.
Some sources recommend the use of the globals, BTW
See, for example, Pete Scargill here: https://tech.scargill.net/handy-node-red-date/

Do not the Sonoff devices send their switch state to MQTT every time it changes? If you drive your dashboard switch from that MQTT topic then you will not need to poll them.

What about situation when network is down? What about situation when some of the devices does not respond (failure)?

What about situation when network is down? What about situation when some of the devices does not respond (failure)?

Then your values in memory would also be wrong...

If you only listen to the msgs from the actor like Colin suggests, it's easier and you can also switch the actor from any source you want.

If the msg from listener does not come back, then I will not keep the "last known values" as "actual values" and switches will be set to default (switch disabled).
But I am ready to "re-think"...

For the network down you should use the LWT mqtt topic then you can display that on the dashboard and set the switches as you need.

I will study, thanks...
What about: Handy Node-Red Date - Scargill's Tech Blog as mentioned above?

I don't know why one would want the current date/time in string form in many places in the flow.

Maybe because strftime formating is not built in NR. But I am not an expert...
Discussed here, for example: Date/Time formatting

That doesn't address what I said, I don't know why one would need the datetime as a string in numerous places in the flows.

HI Petr,
My reading is that you are in doubt if it is a correct approach to use context (global or flow) in your use case. Let me quote how Nick explained the context in the video release of version 0.19:

Context is a feature we have had for a while in Node-RED that allows you to store state in your flow outside of the messages that pass through it.

As an aside remark, version 019 introduced persistent context in the file system as opposed of memory only available in previous versions.

So after a really quick view of the flow you shared, It seems to me that you are using context in the good way: to store state.

Anyway, it is worth to investigate ColinĀ“s suggestions regarding MQTT. As you may already notice, storing state in two different places brings an additional challenge that is how to keep them in sync. For me, it makes sense that the source of truth is the device itself so if I had to make a design decision I would prefer to poll the device whenever necessary.

The link you shared shows the use of the global context in a slightly different way. It uses global context as a kind of "helper" to deliver (via global.get statement) the current time formatted in a customized way (that is not available in the standard Date module of Node.js). I find it very creative, but people provided alternatives approaches in the comments' session of that blog post that seems more interesting (do the same without spending additional cpu cycles to run the code every second).

1 Like

There is no need to poll it, the device sends the status each time it changes.

Chaps, it is usually me confusing the heck out of newcomers so perhaps I can respectfully say here that we are getting a little deep.

Keeping state is a perfectly respectable design pattern that works well. Coupled with permanent storage even takes away from having to juggle MQTT retained messages or a database making Node-RED even more useful than in the past.

If you need to compare a previous value with a new one, variables are absolutely the right tool to use. Minimising the scope is good practice (context rather than flow rather than global) but coupled with sensible variable naming, name clashes should never be an issue anyway. That leaves the only issues of memory utilisation and design complexity. Both are generally manageable as long as you don't forget about them complete

So while I agree in principle that minimising variables is sensible, as always there is a limit and we shouldn't need to jump through logic hoops when there is a simple answer.

Urm, if the network was truly down, then Node-RED wouldn't be able to receive an LWT message either? :slight_smile: The LWT message is, of course, a great help when your ESP8266 device decides that it has had enough and refuses to talk. I generally try to ensure that my networked IoT devices have some restart logic for the case where they can't reach the network any more. I generally use a heartbeat message from my devices that sends "Online" periodically, the matching LWT creates an "Offline" message (the broker creates LWT messages, not the device). That way, I don't have to add complexity to actual data messages and i have a quick reference for all devices as to whether they are on or offline.

That works.

2 Likes

I disagree.

Keeping state is a perfectly respectable design pattern that works well. Coupled with permanent storage even takes away from having to juggle MQTT retained messages or a database making Node-RED even more useful than in the past.

Keeping states is much more a hassle, than just subscribing to the actors topic. There is no juggling with retained msgs and no need for a database - as soon as the actor has changed it's state, it publishes a msg.

The mechanism, that the actor is the source of truth, is really a progress and makes things a lot easier.

Hi Julian,

Indeed the example you have shown above works fine but the question was different: How to reference a message property inside the theTypedInput field.

I have even consulted the best source of information before answering :slight_smile:

r-01

I am loving this thread and I am learning a lot. For instance, if you have asked me if this statement was possible I would say (wrongly) : no way. It turns out that it is valid and works perfectly (to my surprise).

global.set("obed07.payload.template","bar")

It surprises me as it works even if you never created the object "obed07" upfront.
I can remember from the top of my head perhaps 5 or 6 different ways of creating objects in Javascript. I was not expecting that Node-RED would give us a new way.

1 Like

I am not sure if this is a good semantic. I would prefer one way only ... :smiley:

Haha, serves me right for trying to answer a question as I was leaving work. Lost track of the thread of course.

Of course, not suggesting otherwise - only that we've probably lost the most important audience member :exploding_head: