Reputation: 324
We have a loxone server that sends data to our Webserver via a loxone websocket (https://github.com/Loxone/lxcommunicator). This webserver then sends the data to the clients, also through a websocket. We chose this setup so we only have 1 connection to the loxone server itself and only have to authenticate once.
Now the problem is, the function for receiving events from the loxone server has to be declared in the config variable before the connection to the loxone server is even started. However, in that scope (socketOnEventReceived) we don't have the websocket that connects to the clients.
We also can't add the client-websocket around the loxone-socket definition, because then it would create a new loxone-websocket connection for each client.
This is our current code (ws/wss = client-socket, socket = loxone-socket) - the problem with this way is that it creates a new websocket for each event received (obviously also not viable).
if (typeof LxCommunicator === 'undefined') {
global.LxCommunicator = require('lxcommunicator');
}
//=== Node.js only ===
var fs = require('fs');
var WebSocket = require('ws');
var privateKey = ; //PkeyFile
var certificate = ; //CertFile
var credentials = { key: privateKey, cert: certificate };
var https = require('https');
var httpsServer = https.createServer(credentials);
httpsServer.listen(60088);
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({
server: httpsServer
});
// Prepare our variables
// uuid is used to identify a device
var uuid = getUUID(),
// delegateObj is contains all available delegate methods
delegateObj = {
socketOnDataProgress: function socketOnDataProgress(socket, progress) {
//console.log(progress);
},
socketOnTokenConfirmed: function socketOnTokenConfirmed(socket, response) {
//console.log(response);
},
socketOnTokenReceived: function socketOnTokenReceived(socket, result) {
//console.log(result);
},
socketOnTokenRefresh: function socketOnTokenRefresh(socket, newTkObj) {
//console.log(newTkObj);
},
socketOnConnectionClosed: function socketOnConnectionClosed(socket, code) {
process.exit(-1);
},
socketOnEventReceived: function socketOnEventReceived(socket, events, type) {
events.forEach(function(event) {
if(type === 2 || type ===3){ //2=lichtstatus 3=moodstatus
var data = {};
data["uuid"] = event.uuid;
data["value"] = event.value;
data['text'] = event.text;
wss.on('connection', ws => {
ws.send(JSON.stringify(data));
})
}
});
}
},
// deviceInfo is a device specific information like the userAgent of a Browser
deviceInfo;
// Node.js doesn't have a userAgent, lets use the hostname instead
if (typeof window !== "undefined") {
deviceInfo = window.navigator.userAgent;
} else {
deviceInfo = require('os').hostname();
}
// OPTIONAL
// If no version is set LxCommunicator.WebSocket will fetch the version on its own
// This version is needed to determine if the Miniserver supports encryption and tokens
//LxCommunicator.setConfigVersion("9.3.2.20");
// Get the LxCommunicator.WebSocketConfig constructor, to save some space
var WebSocketConfig = LxCommunicator.WebSocketConfig;
// Instantiate a config object to pass it to the LxCommunicator.WebSocket later
var config = new WebSocketConfig(WebSocketConfig.protocol.WS, uuid, deviceInfo, WebSocketConfig.permission.APP, false);
// OPTIONAL: assign the delegateObj to be able to react on delegate calls
config.delegate = delegateObj;
// Instantiate the LxCommunicator.WebSocket, it is our actual WebSocket
var socket = new LxCommunicator.WebSocket(config);
// Open a Websocket connection to a miniserver by just providing the host, username and password!
socket.open("loxoneserver", "loxoneuser", "loxonepassword").then(function() {
socket.send("jdev/sps/enablebinstatusupdate").then(function(respons) {
console.log("Successfully executed '" + respons.LL.control + "' with code " + respons.LL.Code + " and value " + respons.LL.value);
}, function(err) {
console.error(err);
process.exit(-1);
});
}, function(e) {
console.error(e);
});
Upvotes: 0
Views: 2527
Reputation: 6625
Create a centralized Data Store & share data, three options below
Upvotes: 0
Reputation: 2929
Keep an index for all connections then later use the available ones.
let connections = {};
wss.on('connection', ws => {
//Keep an index for incoming connections
const id = Math.random().toString(36).substr(2, 8);
connections[id] = ws;
//remove once its closed.
ws.on("close",()=>{
delete connections[id]
})
})
Then update your method like below.
socketOnEventReceived: (socket, events, type) => {
events.forEach(function(event) {
if(type === 2 || type ===3){ //2=lichtstatus 3=moodstatus
var data = {};
data["uuid"] = event.uuid;
data["value"] = event.value;
data['text'] = event.text;
Object.values(connections).forEach((conn)=>{
conn.send(JSON.stringify(data))
})
// wss.on('connection', ws => {
// ws.send(JSON.stringify(data));
// })
}
});
}
Since I can't run your code on my side. I can't say 100% works.
Upvotes: 1