Make the status node have an input

Currently the status node outputs a message when the status of another node changes.

But it would be very useful in some of my flows if I could also poll the current status of a node at any time on demand.

If the status node had an optional input I could route a message through the status node and have it read the status of another node and attach it to my message. For example I could easily poll how many messages are currently queued in a certain delay node, I could poll the current state of a statemachine node, etc. There would be no need to make use of additional change nodes to read/write variables in the flow context.

1 Like

This sounds like a good request :slight_smile:

When the status node gives output, store the data. Then you can pole the store.
[edit] Or the status node would have to store me thinks.

3 Likes

I can see the value of something like this, but I doubt that NR can or should try to do it in the runtime or core nodes. I suspect that the node status does not actually exist except in the editor display and in the message that is sent when the status changes. This is another case where the fact that NR is flow-based rather than state-based requires a different approach. Although @prof7bit objects to the

it is really the cleanest way to manage this. One change node to update a status object
and one to retrieve it is all that is needed to track the status of as many nodes as you wish. Consider this flow:

[{"id":"c73cb128c57b0562","type":"tab","label":"status","disabled":false,"info":"","env":[]},{"id":"1d182830e00d6f74","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":250,"y":60,"wires":[["19cc7bcb4d06bef8"]]},{"id":"19cc7bcb4d06bef8","type":"debug","z":"c73cb128c57b0562","name":"device0","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":400,"y":80,"wires":[]},{"id":"6d4c7ef3ee78f294","type":"status","z":"c73cb128c57b0562","name":"","scope":null,"x":600,"y":140,"wires":[["b3d5e00767aaf762"]]},{"id":"838f8ce714d58962","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":250,"y":260,"wires":[["11852881256b574f"]]},{"id":"11852881256b574f","type":"debug","z":"c73cb128c57b0562","name":"device2","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":400,"y":280,"wires":[]},{"id":"e5c2d438ad08bdc3","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":250,"y":160,"wires":[["ea4e84ce496bf82b"]]},{"id":"ea4e84ce496bf82b","type":"debug","z":"c73cb128c57b0562","name":"device1","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":400,"y":180,"wires":[]},{"id":"0e0f5cb4cbd91a80","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":250,"y":100,"wires":[["19cc7bcb4d06bef8"]]},{"id":"2c7595d3c28c5dab","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":250,"y":200,"wires":[["ea4e84ce496bf82b"]]},{"id":"b9684ec4aceffb40","type":"inject","z":"c73cb128c57b0562","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":250,"y":300,"wires":[["11852881256b574f"]]},{"id":"6cc6e01ea8213dc7","type":"inject","z":"c73cb128c57b0562","name":"status","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":610,"y":201,"wires":[["90f8ee1e54812cb4"]]},{"id":"90f8ee1e54812cb4","type":"change","z":"c73cb128c57b0562","name":"get status","rules":[{"t":"set","p":"payload","pt":"msg","to":"status","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":201,"wires":[["bea2a356936103c7"]]},{"id":"bea2a356936103c7","type":"debug","z":"c73cb128c57b0562","name":"continue","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":920,"y":201,"wires":[]},{"id":"b3d5e00767aaf762","type":"change","z":"c73cb128c57b0562","name":"set status","rules":[{"t":"set","p":"status[msg.status.source.name]","pt":"global","to":"status.text","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":140,"wires":[[]]}]

Obviously, the status could be saved in flow instead of global context, and selected nodes could be monitored rather than all of them. Multiple status objects could be defined, and so on. Additionally, the status would be available immediately to any node type that can access context, including function nodes.

3 Likes

I geneally prefer to use a Join node in cases like this, joining the status with whatever it is that needs it. The advantage of that is that you automatically get informed if the status changes.

Good idea. More than one way to skin a cat, if we're allowed to say that nowadays.

Obviously the "set status" change node sends a message that can trigger a flow when a status changes. I guess it's more a question of which node wants to know the status of which other node, and when.

It is just that I am trying to avoid making my flow depend on state variables as much as possible. Because unfortunately one is forced to access these variables inside otherwise innocent looking nodes like "change" or "function" of "switch". The main problem I have identified with access to state variables is that these side effects are completely hidden to the eye when looking at a flow. There exists another invisible plane below the visible flow where global state is living and even "flowing".

This is why I am now trying to come up with patterns in my own flows to make all these spots where the flow becomes "impure" (to say it in functional lingo) clearly stick out in an unmistakable way, and if possible even make it visible (for example by grouping) to which nodes the state is supposed to be confined.

One of these impure nodes are the home assistant nodes, or also distinct stateful nodes like a counter or a state machine, they all clearly stick out by their distinct node type. But a change node or a switch node, or even a function node could be pure or impure, you don't see it on the outside (unless you clearly document or mark it somehow), and even if you open it you don't usually see which other nodes it side-effects with, you then only see that it does. This invisible net of side effects that connects some of the nodes remains invisible.

If the status node had an input I could avoid at least one such instance of hidden state and make it plain obvious that the flow is routed through an impure node.

IMHO the core nodes should be designed in such a way that they do not encourage or even force the usage of flow variables, instead they should provide an intuitive way to avoid them.


An alternative (but massive and probably impossible to implement) feature request would be to come up with a visual way to edit (or at least visualize) this hidden layer of interconnected side effects and impurities.


"globals are evil" - (unknown software engineer, 20th century)

While I see the usefulness of what you're proposing, I don't see why it needs to be integrated into the status node. In fact, writing a separate node could make it useful in a large number of other scenarios.

Unless I'm misunderstanding, what you're asking for is some form of recall node:

  • it receives messages and stores the last one internally
  • it also receives special "recall" messages that cause it to output the last stored message

In your use-case case, the messages received and stored are the status node output messages. You want to send it a recall message when you want to "poll the current status on demand".

WRT state, obviously many nodes are stateful. The status node itself is stateful (it remembers the last status update). There's nothing wrong with nodes being stateful. The recall node is obviously stateful, but it doesn't introduce any hidden state-based dependencies, which is the problem you're describing.

currently it isn't (which is the subject of this debate) - currently it purely acts as a source of status events from other nodes.

Personally I'm with you in that I don't think it should be specific to the status node - and indeed - nor should it be a core feature of an event based system - so a node that acts as a poll-able store could be envisaged... - or it could be an enhancement to the simple gate node node-red-contrib-simple-gate (node) - Node-RED

1 Like

Ah, yes, you're right, I conflated the status indicator in the flow editor and the status node.

1 Like

BTW, the recall node I described is a 2-liner in a function node:

if (msg._recall) return context.get('last')
else context.set('last', msg)

Indeed - to that ^^^
(likewise simple gate is also a very short function - but hey - people seem to like a node)

1 Like

Absolutely. That is why I generally use Join nodes instead.

Unfortunately though, just the fact of using HA with Node-RED means that you already have independent layers of flows - which is one of the reasons many of us don't use HA at all.

Right, but it solves only part of the problem. The status node can catch outputs from many nodes, so there should be a mechanism to save and recall these messages based on the source. Not a big deal, of course.

Give me a break :smiling_face_with_tear:. The node really does have some added functionality.

Indeed, Sorry yes, though the core functionality of gating one signal with another can be a simple function or a change and a switch node.

and being poll-able could be one of the extra features it offers

It doesn’t need to monitor all the statuses, the status node does that, it just needs to be poll-able. The separation of concerns is one of the tenets of a good node.

Not clear what you mean. The gate node is already "poll-able." From the documentation:

The status command (added in version 0.4.0) causes the node status to be refreshed, so that it can be caught by a status node.

This discussion has suggested possible improvements, but the node status is, in fact, available on demand.

ah no - not quite... that seems to refresh the status of the gate node... What I was thinking was this. Add a control command to your gate node, called poll (or refresh), that resends the last message received that wasn't a control message out the normal output.

(Ignore the word status - this is for any message... the fact that the input message happens in his instance to be from a status node is immaterial)

@dceejay, @drmibell, If I understand the requirement correctly, it can be done with the queue gate node. Set the queue size to 1, keep latest message, then the peek command passes on the latest message without removing it from the queue.