对设备的远程命令
YiCONNECT 允许您从服务器端应用程序向设备发送远程过程调用 (RPC),反之亦然。基本上,此功能允许您向设备发送命令或从设备发送命令并接收命令执行结果。本指南涵盖 YiCONNECT RPC 功能。阅读本指南后,您将熟悉以下主题:
- RPC 类型;
- 基本 RPC 用例;
- RPC客户端和服务器端API;
- RPC 小部件。
YiCONNECT RPC 功能根据远程过程执行的发起者可以分为两种类型:设备发起的 RPC 和服务器发起的 RPC。为了使用更熟悉的名称,我们将设备发起的 RPC 调用命名为客户端RPC,将服务器发起的 RPC 命名为服务器端RPC。
客户端 RPC
客户端 RPC 功能允许您将请求 从设备发送到平台 ,并将响应返回给设备。
让我们回顾一下客户端 RPC 调用的典型用例:
- 灌溉系统通过平台从在线服务获取天气预报。
- 没有系统时钟的受限设备向平台请求当前时间戳。
- 门禁读卡器向第三方安全系统发送请求,以做出开门并记录访问的决定。
在底层,设备向平台发送一条消息,该消息由规则引擎处理。规则引擎可以使用设备属性、遥测或存储在平台中的任何其他数据来应用一些计算。如果需要,规则引擎还可以调用外部系统。处理消息后,结果将发送回设备。
客户端 RPC 请求由两个字段组成,这两个字段都是必填的:
- method - 用于区分 RPC 调用的方法名称。例如,“getCurrentTime”或“getWeatherForecast”。参数的值是一个字符串。
- params - 用于处理请求的附加参数。该值是 JSON。如果不需要参数,请保留空 JSON“{}”。
RPC 请求示例:
{
"method":"getCurrentTime",
"params":{}
}
RPC 响应可以是任何数字、字符串或 JSON。例如:
1631881236974
从设备发送客户端 RPC
YiCONNECT 提供了一个 API 来从设备发送 RPC 命令。该 API 特定于每个受支持的网络协议。
LwM2M 和 SNMP 协议尚不支持客户端 RPC。
平台处理客户端RPC
客户端 RPC 命令转换为消息类型为“TO_SERVER_RPC_REQUEST”的规则引擎消息。该消息包含基于唯一 UUID 的标识符,该标识符存储在“requestId”元数据字段中。您可以设计规则链以使用转换、丰富或任何其他规则节点类型来处理传入消息。一旦传入消息转换为响应消息,就应该使用RPC Call Reply节点向设备发送回复。
例如,让我们修改根规则链以处理“getCurrentTime”客户端 RPC 并回复当前时间(以毫秒为单位)。我们将使用“Script”转换节点和以下 JS 代码:
var rpcResponse;
if (msg.method === "getCurrentTime"){
rpcResponse = new Date().getTime();
} else {
rpcResponse = "Unknown RPC request method: " + msg.method;
}
return {msg: rpcResponse, metadata: metadata, msgType: msgType};
服务器端 RPC
服务器端 RPC 功能允许您将请求 从平台发送到设备 ,并可选择将响应返回到平台。
服务器端 RPC 调用的典型用例是各种远程控制:重新启动、打开/关闭引擎、更改 GPIO/执行器的状态、更改配置参数等。
服务器端RPC分为单向和双向:
- 单向 RPC 请求不需要设备提供任何回复。
- 双向 RPC 请求期望在可配置的超时时间内收到设备的响应。
在 3.3 版本之前,YiCONNECT 仅支持轻量级RPC。轻量级 RPC 调用是短暂的,通常在 30 秒内,这是对平台的任何 REST API 调用的默认超时。由于它们的生命周期很短,因此没有理由将它们存储到数据库中。它们存在于服务器的内存中,假设如果服务器挂掉,仪表板小部件将向集群中的其他 YiCONNECT 服务器发送相同的请求。轻量级 RPC 消耗少量资源,因为它们的处理不会调用任何输入/输出操作,接受审计日志和规则引擎消息的存储。
从 3.3 版本开始,YiCONNECT 提供了对持久RPC 调用的支持。持久 RPC 具有可配置的生命周期并存储在数据库中。当您的设备可能长时间无法访问时,持久 RPC 非常有用。这种情况通常发生在网络连接不良或节能模式的情况下。
服务器端RPC结构
服务器端RPC请求体由多个字段组成:
- method - 强制,用于区分 RPC 调用的方法名称。例如,“getCurrentTime”或“getWeatherForecast”。参数的值是一个字符串。
- params - 强制,用于处理请求的参数。该值是 JSON。如果不需要参数,请保留空 JSON“{}”。
- timeout - 可选,处理超时值(以毫秒为单位)。默认值为 10000(10 秒)。最小值为 5000(5 秒)。
- 过期时间 - 可选,纪元时间值(以毫秒为单位,UTC 时区)。如果存在超时,则覆盖 该超时 。
- 持久性 - 可选,请参阅[持久性]与[轻量级]RPC。默认值为“false”。
- 重试 - 可选,定义在网络或设备端发生故障时将重新发送持久 RPC 的次数。
- extraInfo - 可选,定义将添加到[持久 RPC 事件]的持久 RPC 的元数据。
RPC 请求示例:
{
"method":"setGPIO",
"params":{
"pin":4,
"value":1
},
"timeout":30000
}
RPC 响应可以是任何 JSON。例如:
{
"pin":4,
"value":1,
"changed":true
}
发送服务器端RPC
服务器端 RPC 通常使用 REST API 或仪表板小部件发送。事实上,仪表板小部件使用相同的 REST API。一旦平台收到 RPC,它就会验证有效负载并运行权限检查。然后,服务器端RPC命令被转换为规则引擎消息。规则引擎可以用附加参数来丰富命令,并最终将命令传送到设备。
我们来详细回顾一下如何发送命令:
使用 REST API
为了发送 RPC 请求,您需要对以下 URL 执行 HTTP POST 请求:
http(s)://host:port/api/plugins/rpc/{callType}/{deviceId}
在哪里
- http(s)://host:port是您的 YiCONNECT 服务器基本 URL。例如,https://yiqisoft.cloud
- callType可以是oneway或 twoway ;
- deviceId是您的目标设备 ID。
请求正文应该是带有我们上面讨论的 RPC 请求对象的有效 JSON 。
curl -v -X POST -d @set-gpio-request.json http://localhost:8080/api/plugins/rpc/twoway/$DEVICE_ID \
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
请注意 ,为了执行此请求,您需要将JWT_TOKEN替换为有效的JWT访问令牌。此令牌应属于具有TENANT_ADMIN或CUSTOMER_USER角色且拥有DEVICE_ID标识的设备的用户。
当用户通过 REST API 发送轻量级RPC 时,API 调用包含来自设备的回复或错误代码。例如:
{
"pin":4,
"value":1,
"changed":true
}
当用户通过 REST API 发送持久RPC 时,响应包含唯一标识符“rpcId”。例如:
{
"rpcId":"b10bb1a0-0afd-11ec-a08f-1b3182194747"
}
您可以使用此标识符来跟踪命令的状态。
使用仪表板
控制小部件用于向设备发送 RPC 命令。最流行的小部件是“RPC 按钮”、“圆形开关”、“开关控制”和“旋钮控制”。这些小部件的高级设置允许您定义 RPC 方法名称和参数。您还可以开发自定义小部件并使用控制 api发送 RPC 命令。
使用规则引擎
从小部件或 REST API 发送的所有服务器端 RPC 命令最终都会转换为消息类型为“RPC_CALL_FROM_SERVER_TO_DEVICE”的规则引擎消息。
该消息包含基于唯一 UUID 的标识符,该标识符存储在“requestUUID”元数据字段中。您可以设计规则链以使用转换、丰富或任何其他规则节点类型来处理传入消息。最后,应该使用RPC Call Request节点将消息发送到设备。
您还可以使用生成器节点创建 RPC:
var msg = { method: "rpcCommand", params: {} };
var metadata = {
expirationTime: new Date().getTime() + 60000,
oneway: true,
persistent: false
};
var msgType = "RPC_CALL_FROM_SERVER_TO_DEVICE";
return { msg: msg, metadata: metadata, msgType: msgType };
在设备上处理服务器端RPC
YiCONNECT 提供了方便的 API 来接收和处理设备上的服务器端 RPC 命令。此 API 特定于每个受支持的网络协议。
持久性RPC
状态
YiCONNECT 跟踪持久 RPC 的状态。有 7 种可用状态:
- QUEUED - RPC 已创建并保存到数据库;尚未尝试将 RPC 发送到设备;当设备在线或已经在线时,YiCONNECT 将尝试立即发送 RPC;默认情况下,平台将尝试立即发送所有待处理的 RPC 调用。在极少数情况下,设备受限且队列中有多个消息,这可能会导致网络或设备过载。为了避免过载,您可以使用“ACTORS_RPC_SEQUENTIAL”配置参数启用 RPC 调用的顺序传递。
- SENT - YiCONNECT 尝试将 RPC 发送到设备。
- DELIVERED - 设备确认 RPC 已交付;这是单向RPC处理的最后一步;
- 成功 - YiCONNECT 收到双向RPC的回复;
- 超时 - YiCONNECT 传输层(MQTT/CoAP/LwM2M 等)检测到 RPC 传输超时;超时使用相应的配置参数之一进行控制:MQTT_TIMEOUT(默认为 10 秒)、COAP_TIMEOUT(默认为 10 秒)、LWM2M_TIMEOUT(默认为 120 秒) 默认情况下,平台不会重试 RPC 的传递,并且状态将更改为“失败”。您可以在 RPC 主体中配置重试次数。最大重试次数由“ACTORS_RPC_MAX_RETRIES”配置参数控制(默认为 5)。
- EXPIRED - RPC 未下发或平台在配置的过期时间内未收到设备的回复;
- 失败 - 在可配置的重试次数期间未能交付 RPC,或者设备固件不支持此类命令。
配置顺序 RPC 传送并结合增加的过期时间、传送超时和重试次数时要小心。如果启用顺序 RPC 传送并且您的设备将无法处理特定的双向 RPC 命令,则其他命令将不会发送到该设备。
规则链事件
对RPC状态的更改将作为独立的消息推送到规则引擎。每个RPC状态都有相应的消息类型。见下图:
该消息包含有关 RPC 请求的详尽信息,包括 RPC 请求正文中的实体 ID 和“additionalInfo”。“RPC 成功”消息还包含来自设备的回复。如果您想在外部系统中处理来自设备的回复,这些消息非常有用。
请参阅下面的成功 RPC 消息示例:
{
"id":{
"entityType":"RPC",
"id":"bea26301-1aec-11ec-9441-73a37bbb7cd2"
},
"createdTime":1632236465459,
"tenantId":{
"entityType":"TENANT",
"id":"ab937a40-3f98-11eb-a8d6-f5a87f07d4be"
},
"deviceId":{
"entityType":"DEVICE",
"id":"3e46db70-e480-11eb-9d0e-1f8899a6f9b3"
},
"expirationTime":1632236525354,
"request":{
"id":"bea26301-1aec-11ec-9441-73a37bbb7cd2",
"tenantId":{
"entityType":"TENANT",
"id":"ab937a40-3f98-11eb-a8d6-f5a87f07d4be"
},
"deviceId":{
"entityType":"DEVICE",
"id":"3e46db70-e480-11eb-9d0e-1f8899a6f9b3"
},
"oneway":false,
"expirationTime":1632236525354,
"body":{
"method":"rpcCommand",
"params":"{}"
},
"persisted":true,
"retries":null
},
"response":{
"test":"passed"
},
"status":"SUCCESSFUL",
"additionalInfo":"{\"param1\":\"value1\",\"param2\":\"value2\"}"
}
TTL配置
持久 RPC 的生存时间由系统管理员在租户配置文件中使用RPC TTL 天配置参数进行配置。系统管理员可以使用SQL_TTL_RPC_ENABLED 配置参数完全禁用从数据库清除持久 RPC 。RPC 清理过程的频率是使用SQL_RPC_TTL_CHECKING_INTERVAL参数控制的,默认设置为 2 小时。