Skip to main content

WebSocket 客户端驱动

该驱动会为每个模型建立一个连接, 驱动启动后主动建立连接并接收服务端发送的数据, 同时也可以向客户端发送数据.

脚本说明

脚本语言: JavasScript ECMAScript 5.1

驱动使用时要求提供  连接处理脚本, 解析处理脚本, 指令处理脚本心跳处理脚本 4 个脚本函数来处理接收和发送数据过程中的协议和数据格式问题.

在脚本的上下文中内置了 Buffer 包, 可用于处理接收或发送二进制数据.

除此之外, 还内置了 lodash, crypto-js, moment, xml-jsformulajs(Excel函数) 包.

注: 所有的脚本的函数名必须为 handler.

客户端对象

在每次脚本中的参数中提供了 client 对象, 该对象为当前 WebSocket 连接客户端对象, 可以通过该对象实现向客户端发送数据的功能. 例如: 向客户端发送 ack 信息等. 该对象提供了以下函数:

send(Buffer)

用于向客户端发送数据. 例如: 在接收到数据时向客户端发送 ack 信息.

参数说明
参数名参数类型参数说明示例值
bufferBuffer要发送的内容Buffer.from("hello") 表示要发送 "hello"

注: 参数必须为 Buffer 类型.

返回值

stringundefined 如果参数不正确(字节数组为空或空数组)或发送失败则返回 string 内容为错误说明, 如果发送成功则返回 undefined.

连接处理脚本

当连接状态发生变化时会调用该函数. 例如: 当连接建立时向服务端发送数据.

说明:

  1. 当连接断开时, 会调用该函数, 此时 state 的值为 false, 此时无法通过 client 发送数据.
  2. 当驱动启动或者重连建立连接时, 会调用该函数, 此时 state 的值为 true.
  3. 当重启驱动时, 该函数会调用两次, 第一次 state 的值为 false, 第二次为 true.
函数定义如下:
function handler(client, state) {
// ...
}
参数说明
参数名参数类型参数说明
clientobject客户端连接对象
statebool当前连接状态, true: 表示连接已建立, false: 表示连接已断开
返回值说明

示例

// 在连接建立后向服务端发送 "hello" 数据
function handler(client, state) {
// 连接已建立
if (state) {
client.send(Buffer.from("hello"));
}
}

数据处理脚本

该脚本用于处理从服务端接收到的数据, 然后将数据解析为平台规定的格式并返回.

函数定义如下:

function handler(client, data) {
// 数据包处理逻辑

// 返回结果必须为数组, 数组中每个元素为一个设备的实时数据信息
return [
{
"id": "d01", // 设备标识
"time": 1665999863637, // 数据采集时间(ms), unix 时间戳
"values": {"key1": "str", "key2": 123} // 数据点, key 为数据点的标识, value: 为数据点的值
}
];
}
参数说明
参数名参数类型参数说明
clientobject客户端连接对象
dataBufferBuffer 对象
返回值
参数名参数类型参数说明示例值
array[object]对象数组返回值[{"id":"d01","time":1665999863637,"values":{"temperature":17.5,"humidity":35.7}}]
id字符串资产编号或设备标识d01
time数值时间戳(ms)1664256913000
values对象数据点信息{"temperature":17.5,"humidity":35.7}
key字符串数据点标识"temperature"
valueany数据点的值17.5
示例
function handler(client, data) {
// 以 json 格式为例, 例如: {"id":"d01","time":"2022-10-17 17:57:32","values":[{"name":"temperature","data":17.5},{"name":"humidity","data":35.7}]}

// 将 data 解析为 json 对象
const jsonData = JSON.parse(data.toString());
// 从对象中提取时间信息
const time = moment(jsonData.time, "YYYY-MM-DD HH:mm:ss");

// 将 values 字段解析为平台规定的格式 {"key1": value1, "key2": "value2", ...}
const values = {};
for (let i = 0; i < jsonData.values.length; i++) {
const value = jsonData.values[i];
values[value.name] = value.data;
}

// 返回解析后的结果数据
return [
{id: jsonData.id, values: values, time: time.valueOf()}
]
}

指令处理脚本

该脚本用于将发送的指令内容转换为字节数组, 当向设备发送指令时, 驱动会将要发送的内容先经过 handler 函数处理, 返回结果作为实际发送的内容.

函数定义如下:

function handler(client, data) {
// 数据转换处理, 将待发送内容转换为字节数组

// 返回结果必须为 Buffer 对象
return Buffer.from("hello"); // 表示发送 "hello"
}
参数说明
参数名参数类型参数说明
clientobject客户端连接对象
dataobject指令信息, 格式如下

指令格式如下:

{
"name": "test",
"showName": "测试",
"ops": [
{
"value": "123"
}
],
"params": {
"test": "123"
},
"defaultValue": {
"test": "123"
}
}
字段名参数类型参数说明
name字符串指令名称
showName字符串指令显示名称
ops.value字符串指令中配置的发送内容
params对象数据写入配置
defaultValue对象数据写入配置中各字段的默认值

注: ops.value 通常为实际发送的内容, 该字段为必填值. opts 为数组, 目前长度固定为 1.

返回值
参数名参数类型参数说明示例值
object对象返回值{"messageType":1, "data": Buffer.from("hello")}
messageType数值消息类型1: 文本消息, 2: 二进制消息
dataBuffer发送内容Buffer.from("hello")
示例
// 发送文本消息
function handler(client, data) {
// 从指令信息中取出要发送的内容, 格式为 base64
const value = data.ops[0].value;
// 将要发送的内容做 base64 解码
return {"messageType": 1, "data": Buffer.from(value, 'hex')};
}

心跳处理脚本

心跳处理脚本用于定义驱动发送心跳时携带的数据内容, 如果无返回值或返回 undefined 表明发送心跳时不携带任何内容.

当开启心跳功能时, 驱动会定时向服务端发送心跳. 当超过设定的时间内未接收到服务端的心跳响应时会判定为连接不可用, 此时驱动断开连接并尝试重新建立建接.

函数定义
function handler(client) {
// 返回要携带的数据或者 undefined
return Buffer.from("ping");
}
参数说明
参数名参数类型参数说明
clientobject客户端连接对象
返回值说明
参数名参数类型参数说明示例值
bufferBuffer要发送的内容Buffer.from("hello") 表示要发送 "hello"
示例
// 发送心跳时携带自定义数据 "hello"
function handler(client) {
return Buffer.from("hello");
}

// 发送心跳时不携带数据
function handler(client) {

}