简体   繁体   中英

Send Websocket data in another websocket connection

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);
});

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.

Create a centralized Data Store & share data, three options below

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM