在另一个 websocket 连接中发送 Websocket 数据
Posted
技术标签:
【中文标题】在另一个 websocket 连接中发送 Websocket 数据【英文标题】:Send Websocket data in another websocket connection 【发布时间】:2021-09-23 08:50:48 【问题描述】:我们有一个 loxone 服务器,它通过 loxone websocket (https://github.com/Loxone/lxcommunicator) 将数据发送到我们的 Web 服务器。然后,该网络服务器也通过 websocket 将数据发送到客户端。我们选择了这种设置,因此我们只有 1 个与 loxone 服务器本身的连接,并且只需验证一次。
现在的问题是,在连接到 loxone 服务器之前,必须在 config 变量中声明从 loxone 服务器接收事件的函数。但是,在那个范围 (socketOnEventReceived) 中,我们没有连接到客户端的 websocket。
我们也不能在 loxone-socket 定义周围添加 client-websocket,因为这样它会为每个客户端创建一个新的 loxone-websocket 连接。
这是我们当前的代码(ws/wss = client-socket, socket = loxone-socket)——这种方式的问题是它为每个接收到的事件创建一个新的 websocket(显然也不可行)。
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);
);
【问题讨论】:
您可以为您创建的所有 WebSocket 创建一个全局数组或对象,并根据需要访问和操作它们。 @Rojo 会是什么样子? “我们也不能在 loxone-socket 定义周围添加 client-websocket,因为那样它会为每个客户端创建一个新的 loxone-websocket 连接” 每个客户端都需要一个WebSocket 连接吗?或者每个客户端都有一个 WebSocket 服务器? (提示:您可以为每个客户端拥有一台服务器,但每个客户端都需要自己的连接!) 那么您是在一切启动之前遇到配置错误,还是因为 websocket 那时为空而导致运行时错误? 【参考方案1】:为所有连接保留索引,然后使用可用的连接。
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]
)
)
然后像下面这样更新你的方法。
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));
// )
);
因为我不能在我这边运行你的代码。我不能说 100% 有效。
【讨论】:
【参考方案2】:创建集中式数据存储并共享数据,以下三个选项
Singleton JS Object RxJS Subject Redux【讨论】:
以上是关于在另一个 websocket 连接中发送 Websocket 数据的主要内容,如果未能解决你的问题,请参考以下文章