How to make a Node with a Configuration Stream

174 views
Skip to first unread message

Jean-Philippe Encausse

unread,
Aug 30, 2016, 12:29:14 PM8/30/16
to Node-RED
Hi,

I made a node that start (let's say) an HTTP Server.

- Each Input request are forwarded to the following nodes it works great !
- I have some fields to configure the server

Now I would love an other output to plug middleware during configuration.

I create my server in a "register function:
RED.nodes.registerType("MyServer", register, {});

But I assume if I call node.send() now other nodes might not be ready ? How should I proceed ? A setTimeout() ? => don't like that

Thanks

Julian Knight

unread,
Aug 30, 2016, 4:18:08 PM8/30/16
to Node-RED
Is there a reason to use another HTTP server other than the existing one that NR creates?

Jean-Philippe Encausse

unread,
Aug 30, 2016, 4:27:42 PM8/30/16
to node...@googlegroups.com
Yes, I said HTTP Server to let everybody understand, in fact it's something else a kind of server.

In fact my question would work for any kind of "plugin architecture" where you want to add/remove behaviors throught at configuration step

--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to a topic in the Google Groups "Node-RED" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-red/zoWcWOyB-LQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-red+unsubscribe@googlegroups.com.
To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
For more options, visit https://groups.google.com/d/optout.



--
Jean-Philippe Encausse - R&D / IoT / Innovations
http://www.encausse.net - http://arm-avocats.fr
Twitter: @JpEncausse - Mob: +33 6 82 12 56 99 
Do it Once, Use it Twice ~ Do it Twice, Make It Once

Julian Knight

unread,
Aug 31, 2016, 3:04:40 AM8/31/16
to Node-RED, J...@encausse.net
I'm not sure that I fully understand your request but have you looked at some of the existing nodes that create servers? The TCP nodes for example?

Jean-Philippe Encausse

unread,
Aug 31, 2016, 3:26:17 AM8/31/16
to node...@googlegroups.com

For instance I made à module to wrap Microsoft BotFramework

When the bot connector receive a chat message it is forwarded to next nodes.

When a User add the bot to it's contact a custom event si triggered and I fire this "greeting" action throught an other output to let customize the greeting message.

And I want to add à third output when the bot is configured to plug custom middleware for instance ro handle geolocation or facebook profile, or...








Dave C-J

unread,
Aug 31, 2016, 3:50:29 AM8/31/16
to node...@googlegroups.com
IF this is your own node then you can have multiple outputs if you like - in th ehtml file you change
  outputs: 1,
and in the js node.send follows the rules for multiple outputs ie you send an array of msg objects
  [ msg, msg2, msg3 ]

Jean-Philippe Encausse

unread,
Aug 31, 2016, 3:55:50 AM8/31/16
to node...@googlegroups.com
Yes that is what I did (this feature is so cool !).

But when the UI is deployed, I assume all nodes are created calling the code:
RED.nodes.registerType("MyServer", register, {});

If I call node.send() at this moment I'm not sure other nodes will be ready ?
I assume the order of node's creation is unknown 

So I might call node.send() but may be "links" in the flow won't be already set ?




--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to a topic in the Google Groups "Node-RED" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-red/zoWcWOyB-LQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-red+unsubscribe@googlegroups.com.
To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
For more options, visit https://groups.google.com/d/optout.

Dave C-J

unread,
Aug 31, 2016, 4:59:26 AM8/31/16
to node...@googlegroups.com
Indeed they may not be... as the whole system is asynchronous and other nodes can start later (or indeed fail to start if in an error condition) - then it's up to you how to handle.
Only hint is that the nodes get called in the order they are in the flow file... so placing things on the first workspace tab will get called first. - And underlying global config nodes (eg the ones under mqtt broker connection) - automatically get put to the front of that list.

But apart from that ... then it's up to you.

sebasti...@gmail.com

unread,
Aug 31, 2016, 7:34:30 AM8/31/16
to Node-RED, J...@encausse.net
Hi Jean-Phillipe,

as it is an asynchronous system, you may use buffered messaging (e.g. a controlled message queue / FIFO)
may the node have the name "MQ" and it has two inputs: 1. the msg_in, 2. release and 1 output msg_out.
This node will buffer all incoming messages in list (FIFO) and will release them one by another on the output as long as the input release is set,

You can see an example flow here http://flows.nodered.org/flow/cea8afa28b7a93ebdc0f which is basically like node-red-contrib-hold with a buffer.
You may be the creator of node-red-contrib-queue :) 


On the other hand you may create some kind of mutex / synchronization mechanism.
Your sending node will have to check if it is allowed to send and will handle itself  if message will be hold or thrown away on release.

So how to check if it is allowed to send? Use another input or take a flow context variable which can be shared by the nodes.

Of course you will loose async in these path's - you it shall be used carefully and rare as you may create deadlock / buffer overflow.
So to make it more robust you will certainly introduce some kind of timeout / runout or watchdog.which will handle the case if the system stalls.


The advantage of the queue is that it is more easily to integrate into a flow and that you have no dependency in a node.  
The synchronization mechanism of courses reduces any work in the flow but is only easy to handle within your own nodes.

But you may combine the queue-node with synchronization-node (which may be basically some auto reset time e.g.)

This is basically a concept idea and I tried to create a demo flow - maybe this solves your issue: see comment node for more info and the source of the queue function node:

[{"id":"1338b8dc.d509e7","type":"debug","z":"56be16ab.4b3638","name":"sub node 2","active":true,"console":"false","complete":"true","x":1150,"y":140,"wires":[]},{"id":"a6c6c4f1.35c248","type":"inject","z":"56be16ab.4b3638","name":"sub node 1","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"x":350,"y":120,"wires":[["1ecda307.21832d"]]},{"id":"1ecda307.21832d","type":"function","z":"56be16ab.4b3638","name":"queue","func":"// initialize node static variables\n// the queue can hold a maximum of queue_max_size elements\n// on overflow older messages are deleted to create some kind of \n// ringbuffer\n// the queue is released to the output as an array if a msg with \n// topic \"release\" and payload value true is received and buffering\n// is disabed afterwards\n// if release is false, buffering is enabled again.\n\nconst queue_max_size = 10;\nvar queue = context.get('queue') || [];\ncontext.set('queue',  queue) ; // why isn't set returning the object? \nvar release = context.get('release') || false;\n// number of loosed items due to overflow\nvar dropped = context.get('dropped') || 0;\n\n// if msg.release is true then output queue content as an array\n// msg with property release set to true are NOT stored in the queue\n// if incoming message has a property clear set to true, the queue is rese\n\n\nif (msg.topic == \"release\") {\n    release = msg.payload;\n    context.set('release', release); \n    node.status({text:\"release = \" + release});\n    if (release === true) {\n        \n        context.set(\"dropped\", 0);\n        if (queue.length > 0) {\n            context.set('queue', []);\n            msg.payload = queue;\n            return msg;\n        }\n    }\n    return null;\n}\nelse\nif (msg.topic == \"clear\") {\n    if (msg.payload === true) {\n        context.set('queue', []);    \n        node.status({text:\"cleared queue\"});       \n        context.set(\"dropped\", 0);\n    }\n    return null;\n} else {\n    if (release === true)\n        return msg;\n    else {\n        var overflow = queue.length >= queue_max_size;\n        msg.overflow = overflow;\n        if (overflow === true) {\n            queue.shift();\n            dropped++;\n            context.set(\"dropped\", dropped);\n        }\n        queue.push(msg);\n        node.status({   fill : overflow ? \"red\" : \"green\", \n                        shape : \"ring\", \n                        text: queue.length + \" items \" + (overflow === true ? \"( \" + dropped + \" dropped)\" : \"\")\n                    });\n    }\n}\n\nreturn null;","outputs":1,"noerr":0,"x":650,"y":140,"wires":[["370ef0c8.ab3b9","1338b8dc.d509e7"]]},{"id":"815eba30.d40e08","type":"inject","z":"56be16ab.4b3638","name":"sub node ready","topic":"release","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"x":340,"y":360,"wires":[["1ecda307.21832d"]]},{"id":"e57ab09e.df062","type":"comment","z":"56be16ab.4b3638","name":"Synchronization","info":"Subnode 1 is creating arbitray messages,\nbut sub node 2 shall only get them if it is ready for it.\n\nyou can trigger readiness by the injection nodes.\n\nThe synchronization is done via simple FIFO buffer, \nwhich is limited to 10 items.\n\nThe buffer is released if the queue node receives a msg \nwith topic \"release\" and payload \"true\". Afterwards \nbuffering is done and the messages are passed through.\n\nIf release is false, buffering is switched on again.\n\nyou can check if the queue had overflowed my examing the msg.overflow property.\n\nTo clear the queue while operating, just send a msg with \ntopic \"clear\" and payload true to the queue\n\n","x":860,"y":280,"wires":[]},{"id":"370ef0c8.ab3b9","type":"split","z":"56be16ab.4b3638","name":"","splt":"\\n","x":910,"y":100,"wires":[["1338b8dc.d509e7"]]},{"id":"990aa43b.024b68","type":"inject","z":"56be16ab.4b3638","name":"clear queue","topic":"clear","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"x":350,"y":240,"wires":[["1ecda307.21832d"]]},{"id":"1bb47777.b2f059","type":"inject","z":"56be16ab.4b3638","name":"sub node not ready","topic":"release","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"x":330,"y":300,"wires":[["1ecda307.21832d"]]}]






unfortunately nodes are not allowed to have multiple inputs and there is standard node like "combine" or "merge"


To wait for several tasks at once you see an example flow here as well:



Am Mittwoch, 31. August 2016 09:55:50 UTC+2 schrieb Jean-Philippe Encausse:
Yes that is what I did (this feature is so cool !).

But when the UI is deployed, I assume all nodes are created calling the code:
RED.nodes.registerType("MyServer", register, {});

If I call node.send() at this moment I'm not sure other nodes will be ready ?
I assume the order of node's creation is unknown 

So I might call node.send() but may be "links" in the flow won't be already set ?



On Wed, Aug 31, 2016 at 9:50 AM, Dave C-J <dce...@gmail.com> wrote:
IF this is your own node then you can have multiple outputs if you like - in th ehtml file you change
  outputs: 1,
and in the js node.send follows the rules for multiple outputs ie you send an array of msg objects
  [ msg, msg2, msg3 ]

--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to a topic in the Google Groups "Node-RED" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-red/zoWcWOyB-LQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-red+u...@googlegroups.com.

To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
For more options, visit https://groups.google.com/d/optout.

sebasti...@gmail.com

unread,
Aug 31, 2016, 7:40:17 AM8/31/16
to Node-RED, J...@encausse.net
Just adding screenshot


Jean-Philippe Encausse

unread,
Sep 1, 2016, 5:00:32 AM9/1/16
to node...@googlegroups.com
Thanks, I understand

To unsubscribe from this group and all its topics, send an email to node-red+unsubscribe@googlegroups.com.

To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages