Http Server 驱动
该驱动会启动一个 http server
, 允许每个 表
注册一个 路径
. 客户端通过不同的 路径
向不同的表推送数据.
驱动配置说明
- 请求路径: 定义当前表接收数据的访问路径, 可以包含多层级的路径. 例如:
/data
,/api/data
等, 也可以使用占位符/api/data/{deviceId}
, 占位符的值可以从request.pathVariables
获取. - 前缀匹配: 启用后, 可接收所有请求路径以该路径为前缀的请求. 例如:
/api/data
, 可以接收/api/data
,/api/data/1
,/api/data/device/设备编号1
等请求. - 请求方式: 即接收哪些请求方式, 可多选.
- 是否注册不带前缀的请求路径: 不勾选该选项时, 驱动默认创建的接口路径默认带有
/http-server-driver
前缀. 例如, 设置的 请求路径 为/device/data
, 实际访问路径为/http-server-driver/device/data
. 如果勾选了该选项后, 会同时注册/http-server-driver/device/data
和/device/data
两个访问路径. 可通过http://平台IP:3030/http-server-driver/device/data
或http://平台IP:驱动端口/http-server-driver/device/data
或http://平台IP:驱动端口/device/data
方式访问.
注: 通过平台
3030
或31000
端口访问http server
驱动接口时, 必须添加/http-server-driver
前缀. 如果平台为多项目版本时, 必须在请求头中添加x-request-project
, 值为该驱动实例所在项目的ID
.
脚本说明
脚本语言: JavasScript ECMAScript 5.1
驱动使用时要求提供 数据处理脚本
脚本函数来处理接收客户端推送过来的数据.
除此之外, 还内置了 lodash
, crypto-js
, moment
, xml-js
和 formulajs(Excel函数)
包.
注: 所有的脚本的函数名必须为
handler
.
平台接口
在 数据处理脚本
和 指令处理脚本
函数的参数中提供了内置 client
对象参数, 在脚本中可以通过使用 client
中提供的函数调用平台接口.
该对象提供了以下函数:
向表中保存一条数据
/**
* 向表中保存一条数据
* @param {string} table 表标识
* @param {object} row 数据对象. JSON 对象, key 为表中字段的名称, value 为字段的值
* @param {boolean} closeRequired 是否关闭必填校验. 如果设置为 true, 则表定义中字段设置的必填属性不生效
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function saveWorkTableRow(table, row, closeRequired)
示例:
function handler() {
const result = client.saveWorkTableRow("student", {"name": "小明", "age": 15, "gender": "male"}, false);
if(result.success) {
// 保存成功时, result.data 为新增记录的 ID
console.log("数据保存成功,", result.data);
} else {
// 保存失败时, message 为失败的原因
console.error("数据保存失败,", result.message)
}
}
根据记录ID查询记录信息
/**
* 向表中保存一条数据
* @param {string} table 表标识
* @param {string} rowId 记录ID
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function getWorkTableRowById(table, rowId)
示例:
function handler() {
const result = client.getWorkTableRowById("student", "小明001");
if(result.success) {
console.log("数据查询成功,", result.data);
} else {
console.error("数据查询失败,", result.message)
}
}
根据记录ID更新记录信息
/**
* 向表中保存一条数据
* @param {string} table 表标识
* @param {string} rowId 记录ID
* @param {object} rowData 更新的内容. JSON 对象, key 为表中字段的名称, value 为字段的值
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function updateWorkTableRowById(table, rowId, rowData)
示例:
function handler() {
const result = client.updateWorkTableRowById("student", "小明001", {"age": 14, "gender": "female"});
if(result.success) {
console.log("数据更新成功");
} else {
console.error("数据更新失败,", result.message)
}
}
查询表记录信息
/**
* 向表中保存一条数据
* @param {string} table 表标识
* @param {string} query 记录ID. JSON 对象, key 为表中字段的名称, value 为字段的值
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function queryWorkTable(table, query)
query
参数格式说明见 Query参数格式说明
示例:
function handler() {
const result = client.queryWorkTable("student", {"project": {"name": 1, "age": 1, "gender": 1}, "filter": {"age": {"$gte": 14}}});
if(result.success) {
// 查询成功, result.data 为 数组, 但可能为空
console.log("数据查询成功, 学生信息列表:", result.data);
} else {
console.error("数据更新失败,", result.message)
}
}
根据记录ID删除指定的记录
/**
* 向表中保存一条数据
* @param {string} table 表标识
* @param {string} rowId 记录ID
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function deleteWorkTableRowById(table, query)
示例:
function handler() {
const result = client.deleteWorkTableRowById("student", "小明001");
if(result.success) {
console.log("数据删除成功");
} else {
console.error("数据删除失败,", result.message)
}
}
上传媒体库文件
/**
* 将指定 url 的文件上传到平台的媒体库
*
* @param {string} fileUrl 文件的 url, 例如: http://www.demo.com/files/file1.png
* @param {string} mediaLibraryPath 上传到媒体库的目录. 例如: a/b/c
* @param {string} saveFileName 保存到媒体库内的文件名. 例如: bg1.png
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function saveFileFromUrl(fileUrl, mediaLibraryPath, saveFileName)
示例:
function handler() {
const result = client.saveFileFromUrl("http://www.demo.com/files/file1.png", "学生信息/学生照片", "小明.png");
if(result.success) {
console.log("文件上传成功");
} else {
console.error("文件上传失败,", result.message)
}
}
将 base64 文件上传到媒体库
/**
* 将指定 url 的文件上传到平台的媒体库
*
* @param {base64Str} base64Str 文件转换为 base64 后数据
* @param {string} mediaLibraryPath 上传到媒体库的目录. 例如: a/b/c
* @param {string} saveFileName 保存到媒体库内的文件名. 例如: bg1.png
* @return {object} 数据保存结果. {success: boolean; data?: any, message: string}
*/
function saveImageFromBase64(base64Str, mediaLibraryPath, saveFileName)
示例:
function handler() {
const result = client.saveImageFromBase64("data:image/png;base64,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", "学生信息/学生照片", "小明.png");
if(result.success) {
console.log("文件上传成功");
} else {
console.error("文件上传失败,", result.message)
}
}
表上下文
每个表有一个独立的上下文对象, 用于在脚本中存储一些数据, 这些数据会在该表的所有脚本中共享. 上下文对象 context
提供以下方法:
put
用于向上下文中存储数据.
注: 存入的数据需要自行清理, 否则可能导致
OOM
等问题.
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
key | string | 数据项的 key |
value | any | 数据项的值 |
返回值
无
示例
function handler(context, request) {
// 向上下文中存储一个字符串
context.put("string", "this is a string");
// 向上下文中存储一个数值
context.put("number", 3.141);
// 向上下文中存储一个对象
context.put("object", {name: "张三", age: 18});
}
containsKey
判断上下文中是否存在指定的 key
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
key | string | 数据项的 key |
返回值
bool
. true
表示 key
存在, false
表示 key
不存在
示例
function handler(context, request) {
// 向上下文中存储一个字符串
context.put("string", "this is a string");
// 返回 true
context.containsKey("string");
// 返回 false
context.containsKey("string1");
}
get
从上下文中获取指定的 key
对应的数据. 如果 key
不存在则返回 undefined
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
key | string | 数据项的 key |
返回值
any
或 undefined
. 返回 put
时写入的数据.
示例
function handler(context, request) {
// 向上下文中存储一个字符串
context.put("string", "this is a string");
// 返回 "this is a string"
context.get("string");
// 返回 undefined
context.containsKey("string1");
}
getAndRemove
从上下文中获取指定的 key
对应的数据并且在返回后 删除 该 key
. 如果 key
不存在则返回 undefined
.
注: 该函数返回后, 再使用
get
或getAndRemove
均返回undefined
.
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
key | string | 数据项的 key |
返回值
any
或 undefined
. 返回 put
时写入的数据.
示例
function handler(context, request) {
// 向上下文中存储一个字符串
context.put("string", "this is a string");
// 返回 "this is a string"
context.getAndRemove("string");
// 返回 undefined
context.get("string");
// 返回 undefined
context.getAndRemove("string");
}
remove
从上下文中删除指定的 key
, 如果 key
不存在则不执行任何操作.
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
key | string | 数据项的 key |
返回值
无
示例
function handler(context, request) {
// 向上下文中存储一个字符串
context.put("string", "this is a string");
// 数据被删除
context.remove("string");
// 不执行任何操作
context.remove("string");
}
reportCommand
上传指令执行结果. 有些场景指令的执行结果是异步通知的, 或者指令通知与实时数据上传为同一接口. 此时,
可以通过 reportCommand
上报指令执行结果.
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
serialNo | string | 平台指令序号, 每次下发指令的序号不同 |
state | string | 指令最终执行状态. 可取值为 success , failure 和 pending 分别代表执行成功 , 失败 和 未完成 |
result | string | 指令执行结果或失败说明 |
返回值
无
示例
function handler(context, request) {
// 向平台上报指令 "cmd_001" 执行结果, 状态为 "success", 结果为 "成功"
context.reportCommand("cmd_001", "success", "成功");
// 向平台上报指令 "cmd_001" 执行结果, 状态为 "failure", 失败原因为 "设备不可用"
context.reportCommand("cmd_001", "failure", "设备不可用");
}
数据处理脚本
该脚本用于处理从客户端发送的数据, 然后将数据解析为平台规定的格式并返回.
函数定义如下:
/**
* /**
* 数据处理脚本, 用于解析客户端推送过来的数据
* @param {Object} context 表上下文
* @param {Object} request 请求对象, 可以获取请求的相关信息
* @returns {{result: [{values: {}, id: string, time: number}], headers: {}, message: string, statusCode: number}}
*/
function handler(context, request) {
// 数据包处理逻辑
// statusCode 返回给客户端的状态码
// message 返回给客户端的响应数据
// headers 响应头
// result 从请求中解析出来的数据, 要求必须为数组. 如果请求不是上报实时采集数据时, 返回空数组即可.
return {
"statusCode": 200,
"message": "ok",
"headers": {"Content-Type": "application/json"},
"result": [{
"id": deviceId,
"time": timestamp,
"values": {"SignalPower": SignalPower, "SNR": SNR, "TxPower": TxPower}
}]
};
}
参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
context | object | 表上下文 |
request | object | 请求对象 |
url | string | 请求 url |
method | string | 请求方式, 例如: GET, POST, PUT 等 |
remoteAddr | string | 客户端地址 |
path | string | 请求路径 |
headers | object | 请求头信息. 注: 值为字符串数组 |
cookies | object | cookie 信息. 注: 值为字符串数组 |
pathVariables | object | 路径参数. 注: 值为字符串数组 |
query | object | url 中的请求参数. 注: 值为字符串数组 |
rawQuery | string | url 中参数部分内容 |
body | string | 请求体 |
示例
以 curl
命令请求为例, 说明 request
中各字段的含义, 表注册的 path
为 /demo/{deviceId}
curl -XPOST -H "x-request-project:62c4f8aaa0f974f96cca7ddc" -H "Content-Type:application/json" -d '{"deviceId":"2d1f1a708b5d4cef880937d67b5e5842","IMEI":"","IMSI":"","deviceType":"","tenantId":"1","productId":"1503","messageType":"dataReport","topic":"v1/up/ad","assocAssetId":"","timestamp":1528183784371,"payload":{"SignalPower":-792,"SNR":-55,"TxPower":50,"CellId":66966098,"Length":3,"Updata":"REVG"},"upPacketSN":-1,"upDataSN":-1,"serviceId":"","protocol":"tup"}' 'http://localhost:9505/demo/123456?a=123&b=abc'
字段名 | 数据类型 | 值 |
---|---|---|
url | string | /demo/123456?a=123&b=abc |
method | string | POST |
remoteAddr | string | [::1]:62298 |
path | string | /demo/123456 |
headers | object | {"Accept": ["/"],"Content-Length": ["368"],"Content-Type": ["application/json"],"Cookie": ["Idea-7de7665d=c0b98b36-3396-41dd-b3a2-84e996a7155c"],"User-Agent": ["curl/7.68.0"],"X-Request-Prooject ": ["62 c4f8aaa0f974f96cca7ddc "]} |
cookies | object | {"Idea-7de7665d":"c0b98b36-3396-41dd-b3a2-84e996a7155c"} |
pathVariables | object | {"deviceId":"123456"} |
query | object | {"a":["123"],"b":["abc"]} |
rawQuery | string | a=123&b=abc |
body | string | {"deviceId":"2d1f1a708b5d4cef880937d67b5e5842","IMEI":"","IMSI":"","deviceType":"","tenantId":"1","productId":"1503","messageType":"dataReport","topic":"v1/up/ad","assocAssetId":"","timestamp":1528183784371,"payload":{"SignalPower":-792,"SNR":-55,"TxPower":50,"CellId":66966098,"Length":3,"Updata":"REVG"},"upPacketSN":-1,"upDataSN":-1,"serviceId":"","protocol":"tup"} |
注: 部分请求头信息由
curl
命令自动添加.
返回值说明
参数名 | 参数类型 | 必填 | 参数说明 | 示例值 |
---|---|---|---|---|
statusCode | number | 是 | 返回给客户端的 http 响应码 | 200 |
message | string | 否 | 返回给客户端的响应内容 | "success" |
headers | object | 否 | 返回给客户端的响应头 | {"Content-Type": "application/json", "custom-header": ["value1", "value2"]} |
result | object[] | 否 | 在请求中解析得到的实时数据 | [{"id":"d01","time":1665999863637,"values":{"temperature":17.5,"humidity":35.7}}] |
.id | string | 是 | 资产编号或设备标识 | d01 |
.time | number | 是 | 时间戳(ms) | 1664256913000 |
.values | object | 是 | 数据点信息 | {"temperature":17.5,"humidity":35.7} |
注: 响应头的值可以为
string
或Array<string>
两种类型。
示例
function handler(context, request) {
// 以请求体内容为 json 格式为例, 例如: {"id":"d01","time":"2022-10-17 17:57:32","values":[{"name":"temperature","data":17.5},{"name":"humidity","data":35.7}]}
// 示例, 从表上下文中获取数据
const valueFromContext = context.get("id");
// 获取请求体的内容并转换为 json 对象
const jsonData = JSON.parse(request.body);
// 从对象中提取时间信息
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;
}
// 响回给客户端的响应码为 200
// 响应内容为 success
// 从请求中解析得到的实时数据为 [{id: jsonData.id, values: values, time: time.valueOf()}]
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"message": "success",
"result": [{id: jsonData.id, values: values, time: time.valueOf()}]
};
}
指令处理脚本
HTTP Server
驱动是通过 http
请求实现指令下发. 当下发指令时, 驱动会将指令内容传递给 指令处理脚本
.
由脚本从指令中解析出要调用的目标 http server
以及传递哪些参数、请求头和请求体信息, 然后驱动会根据这些信息最终发起请求.
指令脚本中包含两个函数, 分别为 handler
和 callback
.
- handler 用于解析平台指令, 并转化为请求信息
- callback 用于处理平台发送指令请求后响应处理, 可实现从响应信息提取出指令执行结果上报给平台. **注:
callback
为可选函数,
未定义时直接将指令请求响应结果作为指令结果**
有些系统指令执行结果的反馈是异步通知的, 或者目标系统有自己的指令标识. 因此需要将目标系统中的指令标识与平台的指令序号建立映射关系,
或者在接收到异步通知时再将执行结果上报给平台.
此时, 需要使用 callback
函数和 表上下文
来实现.
指令处理流程:
- 手动触发指令下发
- 驱动接收到指令下发请求时, 会调用
handler
函数. - 根据
handler
返回的请求信息, 发起请求 - 如果定义了
callback
函数, 则将步骤3
中的响应信息交给callback
处理 - 上报平台指令处理结果
注: 需要在指令配置中的
数据写入
部分配置自定义表单, 然后在发送指令时填写发送内容, 在脚本中command
参数即为填写的内容.
函数定义如下:
/**
* 指令处理脚本, 将指令内容解析为 http 请求数据格式.
*
* @param {Object} context 表上下文
* @param {string} serialNo 平台指令序号, 每个指令都有唯一的序号
* @param {string} tableId 设备所属表的标识
* @param {string} deviceId 设备标识
* @param {Object} command 指令信息
* @return {Object} 请求信息
*/
function handler(context, serialNo, deviceId, command) {
// 解析指令内容, 并返回请求相关信息
return {
url: `http://192.168.100.123/command/${deviceId}?time=${new Date().getTime()}`,
method: 'POST',
headers: {
"Content-Type": "application/json"
},
options: {
"timeout": 15000,
},
body: "the request body"
};
}
/**
* 指令请求回调函数. 接收 handler 函数对应请求的响应信息, 并转换为平台指令响应结果
*
* @param {Object} context 表上下文
* @param {string} serialNo 平台指令序号, 每个指令都有唯一的序号
* @param {string} tableId 设备所属表的标识
* @param {string} deviceId 设备标识
* @param {Object} command 指令信息
* @returns {{result: string, state: string}}
*/
function callback(context, tableId, deviceId, serialNo, response) {
// 根据响应信息执行相关操作
return {state: "success", result: "指令返回结果"};
}
handler 参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
context | object | 表上下文 |
serialNo | string | 平台指令序号, 每个指令都有唯一的序号 |
tableId | string | 设备所属表的标识 |
deviceId | string | 自定义设备标识 |
command | object | 指令信息, 格式如下 |
指令格式如下:
{
"name": "demo",
"showName": "示例指令",
"params": {
"demo": {
"productId": 100123,
"operator": "张三",
"ttl": 7200,
"payload": [
{
"key": "status",
"value": "1"
},
{
"key": "temperature",
"value": "26"
}
]
}
}
}
字段名 | 参数类型 | 参数说明 |
---|---|---|
name | 字符串 | 指令名称 |
showName | 字符串 | 指令显示名称 |
params | 对象 | 数据写入配置, 格式由 数据写入 的配置决定 |
defaultValue | 对象 | 数据写入配置中各字段的默认值 |
handler 返回值说明
字段名 | 参数类型 | 必填 | 参数说明 | 示例值 |
---|---|---|---|---|
url | string | 是 | 请求地址 | http://192.168.100.123:8080/command/sn10032?seq=000123&delay=0 |
method | string | 是 | 请求方式 | 可以为 GET , POST , PUT 等 |
headers | object | 否 | 请求头 | {"Content-Type": "application/json", "Custom-Header": ["value1", "value2"]} |
options | object | 否 | 配置项 | {"Content-Type": "application/json", "Custom-Header": ["value1", "value2"]} |
timeout | number | 否 | 请求超时(ms) | 单位: ms, 默认: 15000 |
options | object | 否 | 配置项 | {"Content-Type": "application/json", "Custom-Header": ["value1", "value2"]} |
body | string | object | 否 | 请求体 |
callback 参数说明
参数名 | 参数类型 | 参数说明 |
---|---|---|
context | object | 表上下文 |
serialNo | string | 平台指令序号, 每个指令都有唯一的序号 |
tableId | string | 设备所属表的标识 |
deviceId | string | 自定义设备标识 |
response | object | 响应信息, 格式如下 |
响应信息格式如下:
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "消息体"
}
字段名 | 参数类型 | 参数说明 |
---|---|---|
statusCode | number | 响应码. 例如: 200 |
headers | object | 响应头. 例如: {"Content-Type": "application/json"} |
body | string | 消息体. 例如: {"code": 0, "message": "success"} |
callback 返回值说明
字段名 | 参数类型 | 必填 | 参数说明 | 示例值 |
---|---|---|---|---|
state | string | 是 | 指令执行状态 | 枚举值. success , failure , pending |
result | string | 是 | 指令执行结果 | 成功 |
callback state 枚举状态说明
值 | 说明 |
---|---|
success | 指令执行成功 |
failure | 指令执行失败 |
pending | 指令未完成. 用于异步反馈指令执行结果情况 |
示例1
该示例, 未定义 callback
函数. 驱动直接使用请求的响应结果作为执行结果.
如果响应码为 200
, 表示指令执行成功, 消息体作为指令执行结果.
function handler(context, serialNo, deviceId, command) {
const {productId, operator, ttl, payload} = command.params.demo;
const content = {};
for (let i = 0; i < payload.length; i++) {
const data = payload[i];
content[data.name] = data.value;
}
return {
url: "http://192.168.50.12:8080/command",
method: "POST",
headers: {
"Content-Type": "application/json"
},
options: {
"timeout": 15000
},
body: {
"deviceId": deviceId,
"productId": productId,
"operator": operator,
"ttl": ttl,
"content": {
payload: content
}
}
};
}
示例2
该示例, 使用 callback
从响应信息中提取指令执行结果信息.
function handler(context, serialNo, deviceId, command) {
const {productId, operator, ttl, payload} = command.params.demo;
const content = {};
for (let i = 0; i < payload.length; i++) {
const data = payload[i];
content[data.name] = data.value;
}
return {
url: "http://192.168.50.12:8080/command",
method: "POST",
headers: {
"Content-Type": "application/json"
},
options: {
"timeout": 15000
},
body: {
"deviceId": deviceId,
"productId": productId,
"operator": operator,
"ttl": ttl,
"content": {
payload: content
}
}
};
}
/**
* 从响应信息中提取指令执行结果.
*/
function callback(context, serialNo, deviceId, response) {
// 例如, 消息体内容为 {"code": 200, "message": "success"}
const {code, message} = JSON.parse(response.body);
return {state: code == 200 ? "success" : "failure", result: "message"};
}
示例3
该示例中, 假设指令执行结果为异步通知, 并且目标系统有独立的指令标识
function handler(context, serialNo, deviceId, command) {
const {productId, operator, ttl, payload} = command.params.demo;
const content = {};
for (let i = 0; i < payload.length; i++) {
const data = payload[i];
content[data.name] = data.value;
}
return {
url: "http://192.168.50.12:8080/command",
method: "POST",
headers: {
"Content-Type": "application/json"
},
options: {
"timeout": 15000
},
body: {
"deviceId": deviceId,
"productId": productId,
"operator": operator,
"ttl": ttl,
"content": {
payload: content
}
}
};
}
function callback(context, serialNo, deviceId, response) {
// 例如, 消息体内容为 {"commandId": "cmd_001"}
const {commandId} = JSON.parse(response.body);
// 从消息体中提取出目标系统的指令标识, 并与平台指令序号建立映射关系
context.put(commandId, serialNo);
// 返回 state 为 pending, 表示指令未完成
return {state: "pending", result: "处理中"};
}
/**
* 数据处理脚本. 接收到目标系统推送的指令执行结果. 此时处理未完成的指令并上报到平台
*/
function handler(context, request) {
// 根据请求中的一些信息判断该请求为指令执行结果通知请求
if (request.headers["type"] === "command") {
// 从请求消息体中提取出命令标识以及指令执行结果
// 例如, 消息体格式为 {"commandId": "cmd_001", "code": 200, "message": "success"}
const {commandId, code, message} = JSON.parse(request.body);
// 根据目标系统的指令标识获取平台指令序号
const serialNo = context.getAndRemove(commandId);
// 通过表上下文上报指令执行结果
context.reportCommand(serialNo, code === 200 ? "success" : "failure", message);
// 返回空对象
return {};
}
}