I'm not going to talk about the security side of things, you should be researching that before hand
But, the general idea will be this (and one I use often in my nodes, but how you design it, is up to you)
In a config Node, establish the connection, along with all the secret sauces that comes with it.
Then, in your config Node, create 2 methods and 1 collection.
(Note: I'm using hints of typescript here : Sorry @TotallyInformation )
const Listeners = {}
registerListener(NodeID: string, Callback: (data: buffer)) {
Listeners[NodeID] = Callback
}
deRegisterListener(NodeID: string) {
delete Listeners[NodeID]
}
node.ws.on('message', (data) => {
for (const [id, cb] of Object.entries(Listeners)) {
cb(data)
}
})
In all your nodes that use this config.
node.myConfigNode = RED.nodes.getNode(self.config.configId)
node.myConfigNode.registerListener(node.id,(data) =>{
node.send({payload:data})
})
and importantly
node.on('close',(removed,done) => {
node.myConfigNode.deRegisterListener(node.id)
done()
})
This is all boilerplate stuff - but should hint at the approach to take (at least one of)
Also remember to close the main socket in your config on the "close" callback, else you could end up with zombie web socket connections hogging resources
EDIT : The Web socket part.
in the ws npm package, you can submit headers along with the connection, and if you design your Config node to prompt for creds to facilitate these required headers you should get close.
Example (your config node):
module.exports = function(RED) {
function Init(config) {
RED.nodes.createNode(this, config);
const node = this;
node.ws = new WebSocket('wss://x.x.x.x/xxx', {
headers: {
someHeader: config.someValueKey
}
});
}
}