[New Experimental Node] node-red-contrib-events: Alternative to link nodes

Please note that this is an EXPERIMENT. Not at all sure whether it would be worth publishing.

The event-in and event-out nodes are an alternative take on the core link nodes.

Whereas the link nodes link up via the source and destination node id, these nodes link up via the msg.topic instead.

This means that you can have a event-in node to which you can send any messages as long as they have a msg.topic defined.

Then you add 1 or more instances of the event-out node with a pre-defined topic. Those nodes then listen for that topic and output the msg.

Why?

Well, I find myself creating a very large number of identical MQTT listeners simply to listen for change events for specific topics. This seems unnecessary. I could create links of course but then would have to define all of the source and destination links manually and who wants to do that right?

So Instead, I can have a single MQTT listener connected to a single event-in and as many matching event-out nodes as I like.

Just seems a lot neater that way don't you think? Or is that just me stressing over my OCD?

Anyway, it was also a good excuse to try out my new deconstructed layout for a node's .js file as well.

Let me know if you think this is worth publishing - or indeed, let me know if you think this is a bad idea :slight_smile:

Installation

For now, you have to install from GitHub:

npm install TotallyInformation/node-red-contrib-events

Enjoy :grinning:

PS

Nearly forgot. I have used the Node-RED core event handler for this. However, I have prefixed all event names with TotallyInfo-Contrib-Events: then followed by the msg.topic. So you can be sure that the event names are unique and cannot possibly clash with any internal Node-RED event names.

5 Likes

Non-visible wiring is an anti-pattern for a visual wiring tool. You may as well just write javascript.

1 Like

I like the idea, i have been using topics with arrays and switch node to route messages to 1 or multiple link in nodes. The in out, out in is a bit confusing can we have it the same as the link nodes? Is it also possible to send an array of event nodes to link to?

Doesn't appear to be working for me.
Should this work, or have I misunderstood the description?

totally

[{"id":"510c3ff9a8e4bca6","type":"event-in","z":"f8cf7ea5344d6287","name":"","topic":"test","x":670,"y":375,"wires":[]},{"id":"39398dfcc42e0b7a","type":"event-out","z":"f8cf7ea5344d6287","name":"","topic":"test","x":530,"y":420,"wires":[["d338139a904f2ec1"]]},{"id":"26c5ceb780bfb360","type":"inject","z":"f8cf7ea5344d6287","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":520,"y":375,"wires":[["510c3ff9a8e4bca6"]]},{"id":"d338139a904f2ec1","type":"debug","z":"f8cf7ea5344d6287","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":420,"wires":[]}]

No errors in NR log or browser console.

EDIT - Ahh, so the originating message also needs to share the same topic (now working)

totally

While non-visible wiring may be an anti-pattern, event-driven programming certainly isn't.

In any case, I've always been a fan of pragmatism over perfectionism and event-driven systems are a highly pragmatic approach in my view.

And I respectfully disagree that the only alternative is to write just JavaScript :slight_smile:

Indeed many of my flows do consist of a lot of small pieces of JavaScript since the combined approach of a visual framework and focused bits of code I find to be an immensely effective way of working.

It is one of Node-RED's great strengths - in my view - that you can so easily combine both. Where I've used visual programming tools in the past, they have often fallen down in this respect and so become victims of their own too-tightly held beliefs.

:slight_smile: That is, indeed the whole purpose since anything else would just be a link node

Oops! My bad, I did it in a hurry and got them the wrong way round! I was thinking "into" the in node and "out of" the out node - rather than the target node sending "out" the event and the listener node taking "in" the msg :rofl: They certainly need to match the terminology of all of the many other event nodes (MQTT, HTTP, TCP, UDP, databases, files, ...).

I will change them.

Not sure what you mean there?

The nodes are deliberately very simple. The target node takes any topic and creates events. The listener node takes a fixed topic and outputs the msg.

If you mean that you would like the listener node to allow multiple topics? That might be considered as a future enhancement. Perhaps wild-cards as well more like the MQTT nodes.

I also intend to add an optional through-port for the target node so that you can have it in-line with another flow if you want to. Save having to have two wires out of a source node with the consequential node copy process.

I'm sure we had someone else create a similar set of nodes using topics a while ago.

And of course we could have had a discussion about dynamic routing with the link nodes....

An array of topic names ["topic1", "topic2"] that feed into event out node, that would be routed to all in nodes with said topic names.
@knolleary Same functionality in possible dynamic link nodes, if possible.

Love the through port idea, some othe standard nodes and dashboard nodes could do with that to, I.e. gauge nodes etc, so a payload object could populate multiple nodes and no cloning.

I couldn't find anything in the flows site, I did do a trawl.

And I would certainly welcome a discussion about link nodes and dynamic routing. Indeed, that would be great. The whole thing only took less than an hour and partly was an excercise in using the new layout for the .js file so I wouldn't be at all unhappy about throwing it away.

I did also take a quick look at the link nodes themselves but their UI is significantly different and the event nodes are very simple.

So, would you be open to folding this kind of feature into the link nodes?

Sorry, being a bit slow here. Do you mean being able to send a msg like this to the target node:

{
    "topic": ["topic1", "topic2"],
    "payload": "something"
}

Because I don't think that would be a good idea since the assumption about msg.topic is that it is a string not an array. Also, I don't see that it would be that useful since you can simply send multiple msgs?

However, being able to add a wild-card and/or array of strings to the listener node would be not so far away from how the MQTT listener node works.

Yes, seems like a small but useful tweak - I don't think it would work well if combined with the link node though as the UI elements would clash.

Yes send an array or comma seperated string of topics. Then the event node would send the payload to the the individual topics, removing the other topics in said string/array. There maybe need for a sending node property to

{
    "topic": ["topic1", "topic2"],
    "payload": "something",
    "sender": "topic1"
}
// target node recieves 
{
    "topic": "topic1",
    "payload": "something",
    "sender": "topic1"
}

An interesting idea, and I can see several uses for something like this.

I do have one slight concern/quibble with your current design though, and that's the naming of "event-in" and "event-out". They seem to be the opposite of what I would expect for those names, since the "in" node actually sends and event out, and the "out" node takes one in.

Perhaps names like "event-generate" and "event-listen" would be better?

As I say, I don't believe that to be a good idea simply because I've not come across any other nodes that treat msg.topic as anything but a string in keeping with its origin with MQTT.

Haha, yes that was already spotted. I'll push another version shortly but unfortunately, it will do weird things to an existing flow :slight_smile:

The new version uses the same naming as other event-based nodes.

1 Like

There had to be a first for every thing.
All moot if there is subscription like mqtt # +.

Julian, if you are interested, the topic matching code in this subflow is fairly well tested - you are free to use it if it helps.

https://flows.nodered.org/flow/e38554543a8cdec6c44eacfc68a0c149

It was off when I'd tried to have topic filtering added to switch node.

I think the one that already exists is node-red-contrib-sub-link

Thanks Steve. I certainly would need to put a basic sanity check on the topic name (probably a string no more than 255 characters). That node might be helpful if I extend the out node to support wild-cards.

Thanks Dave, I've done a quick check of that node. It isn't really clear to me why it needs to be so complex or why it needs a config node. Unusually for me, I was aiming for simplicity in this node. :slight_smile:

One thing I don't know about using events and I don't know how I can test - is the output from an event listener function a CLONE of the input or is it a REFERENCE?

I'd strongly recommend against doing that. You should create your own EventEmitter object that is shared by your nodes and nothing else.

This came up in a thread recently that you contributed to, and I made the same recommendation there: Node Developers: How To use setMaxListeners() using RED.events - #2 by knolleary

No problem Nick, I will change it. It was just quick & dirty to get something going with minimal effort.

Shame though as it would make it available to all nodes as well :slight_smile:


Ah, I remember the other reason now - using the RED event emitter avoids having to create another shared library and allows all nodes, including function nodes I believe, to make use of the evets.

If I have a separate event handler, this is not possible. Which makes the whole thing rather less useful.

But other nodes should not be able to trigger your nodes directly, so that isn't an issue.

I have no issue with your nodes bypassing the wiring to pass messages amongst themselves - but this should not become a shadow-messaging system between arbitrary nodes.

OK, no problem. Changes will be done today.

On balance of this discussion, I think I will probably pubish the package but I'll give it a bit more thought.