Accessing Config Nodes data from Function Node

514 views
Skip to first unread message

Francois Vander Linden

unread,
Oct 15, 2017, 3:34:43 AM10/15/17
to Node-RED
Hello

as I understand, a Function Node cannot access the Node-Red API and so it cannot access stuff like Config Nodes.

Would it be possible to use the functionGlobalContext in settings.js to expose the Node-Red API in the global context ? and I suppose it needs to expose the current instance of Node-Red ?

Or is possible to access the Config Nodes using the Admin HTTP API ?

Thanks

Simon H

unread,
Oct 15, 2017, 4:45:04 AM10/15/17
to Node-RED
Hi Francois,

although not recommended, I expose 'require' in globals :).  Then you can do  pretty much anything you like in a function node....
For a very private installation of NR, I don't have any concerns at all about this exposure, if used with care.

to get access to the red API, 
var RED2 = require.main.require('node-red');
I'm not sure exactly how (my JS experience is not quite 'expert' level yet), but this seems to give access to the current instance (I think there can only be one?).
From there, you can do lots of things; but bear in mind that NR internals are not guaranteed to be static... most of what you can access is not a publicised API.
(note: the .main. is important).

Depending upon what you want to do, you could use node-red-contrib-flowman - with this you can read a current flow, update it's definition (e.g. change credentials), then delete the old one and add the new one, all from within NR.  Again with caveats that you are messing with NR internal structures; although these are basically the same as you would use with the HTTP Admin API.  The other caveat is that this nodeset DOES mess with the internals of NR, and so cannot be guaranteed to work with newer versions of NR - I'm not expecting the NR team to take my contrib node into account when making core changes!

best regards,

Simon



Francois Vander Linden

unread,
Oct 15, 2017, 4:53:08 AM10/15/17
to Node-RED
Thanks Simon, this seems like a good starting point !

Any additional input/experience is welcome :-)

Simon H

unread,
Oct 15, 2017, 4:59:40 AM10/15/17
to Node-RED
Hi Francois,
What are you wanting to change? i.e. a brief explanation of what is to be achieved will produce a flurry of suggestions :). 

Francois Vander Linden

unread,
Oct 15, 2017, 5:22:24 AM10/15/17
to Node-RED
Ok, maybe I'm thinking this the wrong way but here's what I want to do.

I have an undefined number of home automation controllers, accessible via HTTP requests (i.e. if you want to turn on a lamp you send an HTTP request to the controller linked to the lamp). It's using basic authentification.

I'd like to access those controllers using Node-Red via HTTP IN requests using a GET/POST parameter to specifiy which Home Controller you want to access. I want to users of the Node-red app to use the Node-red interface and not fiddle with internal JS code.

So I was thinking I could create a custom Config Node to hold each controller config (Name, IP, port, credentials) and then either a Function Node or another custom node to select the appropriate Controller, based on the name passed as a parameter and then send the request to the controller.

Node-red would receive a request like 

the custom node or Function node would parse all the Controllers Config Nodes to find the necessary info linked with "CTRL1" and send this as a payload to a HTTP Request node (although there is probably a problem with the credentials which are specified inside the HTTP Request Node and cannot use mustache).


HTTP IN --> Function to find config node for controller name as stored in the "controller" param and prepare a payload for the request --> HTTP REQUEST

If config nodes were accessible as a context, the function Node would look something like.

var configs = config.get('controller-type');    // would return an array of all the configs of type "controller-type"
for (i= 0;i<configs.length;i++) {
   if (configs[i].name == msg.payload.controller) break;
}
controller_config = configs[i];
// prepare the payload for the http request ...



As a workaround I thought about using the global context and maybe node-red-contrib-config but since the Config Nodes' purpose is to hold a Config, it seemed more in-key with NR philosophy.

Simon H

unread,
Oct 15, 2017, 7:07:52 AM10/15/17
to Node-RED
Hi Franois,
So I see two issues you need to overcome:
1/ the basic authentication for your controllers.  The authentication in NR is normally stored in the credentials store and associated with a single http request node?
2/ storing your list of devices.

Storing the list of devices is fairly easy; you can create and store an array in the flow context or in the global context; load this at start and save on change if you need to persist...

The credentials is a different matter.  If you wanted to use a single HTTP Request node, then this implies that you would want to be able to dynamically set the credentials on a per-call basis.
If you are happy to save the credentials outside of the credentials store, then this could be done with modification to the HTTP request node, similar to my MQTT node modification (part of this - although I've not looked into the same thing for the http nodes, it may be similar).  Or indeed, you could operate an http request outside of NR - i.e. create a function node which contains the http request code you need using native nodejs http functionality; which may be more palatable than changing a NR core function.

best regards,

Simon

p.s. I like your idea of credentials supporting moustache or another templating mechanism.  For nodes where the credentials are used on every call, this could work nicely, with username & password able to be derived from the incoming message.
Wrinkles come for things like MQTT or (http connection persistence?), where a change in credentials would require a reconnect.  For dynamic credentials on MQTT, I found managing the connection is the biggest headache.

Francois Vander Linden

unread,
Oct 15, 2017, 11:15:10 AM10/15/17
to Node-RED


Le dimanche 15 octobre 2017 13:07:52 UTC+2, Simon H a écrit :
Storing the list of devices is fairly easy; you can create and store an array in the flow context or in the global context; load this at start and save on change if you need to persist...


Well storing this in the flow/global context could easily be done but I want the user to do it from the node-red interface using a node-form (not by injecting JSON or another object to the context). That means I should create a custom node for that (and behind the scenes, it would send the data in the flow/global context). But it seems like re-doing stuff that was planned for the Config Nodes that's why, if possible and if it makes sense, I'd prefer to use Config Nodes ... except I can't access the data stored in the config nodes so easily ...

Julian Knight

unread,
Oct 15, 2017, 5:04:24 PM10/15/17
to Node-RED
A subset is available - see:

[{"id":"3a9e8041.8700a","type":"inject","z":"106ba95c.ff91e7","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":734.0729522705078,"y":420.9653091430664,"wires":[["f6e7fbf6.846998"]]},{"id":"35cf9671.8958da","type":"debug","z":"106ba95c.ff91e7","name":"","active":true,"console":"false","complete":"false","x":1034.073013305664,"y":426.5729446411133,"wires":[]},{"id":"f6e7fbf6.846998","type":"function","z":"106ba95c.ff91e7","name":"","func":"msg.payload = {}\nmsg.payload.RED = Object.keys(RED)\nmsg.payload.REDutil = Object.keys(RED.util)\nmsg.payload.node = Object.keys(node)\nmsg.payload.global = Object.keys(global)\nreturn msg;","outputs":1,"noerr":0,"x":875.0799102783203,"y":481.2778091430664,"wires":[["35cf9671.8958da"]]}]

Produces this:

{"RED":["util"],"REDutil":["ensureString","ensureBuffer","cloneMessage","compareObjects","generateId","getMessageProperty","setMessageProperty","evaluateNodeProperty","normalisePropertyExpression","normaliseNodeTypeName","prepareJSONataExpression","evaluateJSONataExpression"],"node":["log","error","warn","on","status","send"],"global":["set","get","keys"]}

Francois Vander Linden

unread,
Oct 17, 2017, 1:55:40 PM10/17/17
to Node-RED
Thanks, some subsets I didn't know of ! Is there anything in there that can help access config nodes ?

Nick O'Leary

unread,
Oct 17, 2017, 3:29:50 PM10/17/17
to Node-RED Mailing List
Is there anything in there that can help access config nodes 

No, because we don't intend for nodes to be able to randomly access other nodes.

Nick

--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, 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.
To view this discussion on the web, visit https://groups.google.com/d/msgid/node-red/622219ae-a84a-4e14-8e4f-51e3da00bd04%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages