产品定价 立即试用
云平台
欧洲地区
文档 > 核心概念 > 对设备的远程命令
入门
指南 API 常见问题
目录

使用RPC能力

ThingsBoard允许您在服务端应用与设备之间进行远程过程调用(RPC)的双向通信。 简而言之,该功能允许您向设备发送命令或从设备接收命令,并获取命令执行结果。 本指南介绍ThingsBoard的RPC能力。阅读后将熟悉以下主题:

  • RPC类型;
  • 基本RPC使用场景;
  • RPC客户端与服务端API;
  • RPC部件。

ThingsBoard的RPC功能可根据远程过程调用的发起方分为两种类型:设备发起和服务端发起的RPC。 为便于理解,我们将设备发起的RPC调用称为客户端RPC,服务端发起的RPC称为服务端RPC。

客户端RPC

客户端RPC功能允许您从设备向平台发送请求,并将响应返回给设备。

让我们了解客户端RPC调用的典型使用场景:

  • 灌溉系统通过平台从在线服务获取天气预报。
  • 无系统时钟的受限设备向平台请求当前时间戳。
  • 门禁读卡器向第三方安防系统发送请求,以决定是否开门并记录访问。

在底层,设备向平台发送消息,由规则引擎处理。 规则引擎可使用设备属性、遥测数据或平台中存储的任何其他数据进行计算。 规则引擎也可在需要时调用外部系统。消息处理完成后,结果将发送回设备。 如下图所示:

image

客户端RPC请求包含两个必填字段:

  • method - 用于区分RPC调用的方法名称。 例如 “getCurrentTime” 或 “getWeatherForecast”。该参数值为字符串。
  • params - 用于处理请求的额外参数。值为JSON。若无需参数则使用空JSON “{}”。

RPC请求示例:

1
2
3
4
{
   "method": "getCurrentTime",
   "params": {}
}

RPC响应可以是任意数字、字符串或JSON。例如:

1
1631881236974

从设备发送客户端RPC

ThingsBoard提供从设备发送RPC命令的API。 该API针对每种支持的网络协议有专门实现。 您可在相应参考页面查看API及示例:

LwM2M和SNMP协议尚不支持客户端RPC。

平台对客户端RPC的处理

客户端RPC命令会转换为规则引擎消息,消息类型为 “TO_SERVER_RPC_REQUEST”。 消息包含基于UUID的唯一标识符,存储在 “requestId” 元数据字段中。 您可以设计规则链, 使用转换、丰富或其他规则节点类型处理传入消息。 将传入消息转换为响应消息后,应使用RPC调用回复节点向设备发送回复。

例如,修改根规则链以处理 “getCurrentTime” 客户端RPC并以毫秒级当前时间回复。 我们将使用 “Script” 转换节点配合以下JavaScript代码:

1
2
3
4
5
6
7
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请求不需要设备提供任何回复。

    image

  • 双向RPC请求期望在可配置的超时时间内收到设备的响应。

    image

3.3版本之前,ThingsBoard仅支持轻量级RPC。 轻量级RPC调用生命周期短,通常在30秒内(即平台REST API调用的默认超时)。 因其短暂,无需存入数据库。 它们保存在服务端内存中,假设若服务端宕机,仪表板部件会向集群中的其他ThingsBoard服务端发送相同请求。 轻量级RPC资源消耗低,因其处理不涉及除审计日志和规则引擎消息之外的任何I/O操作。

自3.3版本起,ThingsBoard支持持久化 RPC调用。 持久化RPC具有可配置的生命周期并存储在数据库中。 当设备可能长期不可达时,持久化RPC尤为有用。 这种情况通常发生在网络状况差或处于省电模式(PSM)时。

服务端RPC结构

服务端RPC请求体包含多个字段:

  • method - 必填,用于区分RPC调用的方法名称。例如 “getCurrentTime” 或 “getWeatherForecast”。参数值为字符串。
  • params - 必填,用于处理请求的参数。值为JSON。若无参数则使用空JSON “{}”。
  • timeout - 可选,处理超时毫秒数。默认10000(10秒)。最小5000(5秒)。
  • expirationTime - 可选,纪元时间毫秒数(UTC)。若存在则覆盖 timeout
  • persistent - 可选,参见[持久化]与[轻量级]RPC。默认为 “false”。
  • retries - 可选,定义网络和/或设备侧失败时持久化RPC的重发次数。
  • additionalInfo - 可选,定义将添加至[持久化RPC事件]的持久化RPC元数据。

RPC请求示例:

1
2
3
4
5
6
7
8
{
   "method": "setGPIO",
   "params": {
     "pin": 4,
     "value": 1
   },
  "timeout": 30000
}

RPC响应可以是任意JSON。例如:

1
2
3
4
5
{
   "pin": 4,
   "value": 1,
   "changed": true
}

发送服务端RPC

服务端RPC通常通过REST API或仪表板部件发送。实际上,仪表板部件使用的是同一REST API。 平台收到RPC后会验证载荷并执行权限检查。 随后,服务端RPC命令被转换为规则引擎消息。 规则引擎可为命令添加额外参数,并最终将命令下发至设备。

下面详细说明如何发送命令:

使用REST API

要发送RPC请求,需向以下URL发起HTTP POST请求:

1
http(s)://host:port/api/plugins/rpc/{callType}/{deviceId}

其中

  • http(s)://host:port 为ThingsBoard服务器基础URL。例如eu.thingsboard.cloud
  • callTypeonewaytwoway
  • deviceId 为目标设备ID

请求体应为上文所述RPC请求对象的有效JSON。

For example:

1
2
3
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"
1
2
3
4
5
6
7
{
  "method": "setGpio",
  "params": {
    "pin": "23",
    "value": 1
  }
}

请注意,要执行此请求,需将 $JWT_TOKEN 替换为有效的JWT访问令牌。 该令牌应属于拥有 $DEVICE_ID 所标识设备的 TENANT_ADMINCUSTOMER_USER 角色用户。 请使用以下指南获取令牌。

用户通过REST API发送轻量级RPC时,API调用会包含设备回复或错误码。例如:

1
2
3
4
5
{
   "pin": 4,
   "value": 1,
   "changed": true
}

用户通过REST API发送持久化RPC时,响应会包含唯一标识符 “rpcId”。例如:

1
2
3
{
   "rpcId": "b10bb1a0-0afd-11ec-a08f-1b3182194747"
}

您可使用此标识符跟踪命令状态。详见持久化RPC 状态

使用仪表板

控制部件用于向设备发送RPC命令。 最常用的部件有 “RPC按钮”、”圆形开关”、”开关控件” 和 “旋钮控件”。 这些部件的高级设置允许您定义RPC方法名和参数。 您也可开发自定义部件并使用控制API发送RPC命令。

使用规则引擎

所有从部件或REST API发送的服务端RPC命令最终都会转换为规则引擎消息, 消息类型为 “RPC_CALL_FROM_SERVER_TO_DEVICE”。

消息包含存储在 “requestUUID” 元数据字段中的基于UUID的唯一标识符。 您可以设计规则链, 使用转换、丰富或其他规则节点类型处理传入消息。 最后,应使用RPC调用请求节点将消息发送至设备。

您也可以使用生成器节点创建RPC:

1
2
3
4
5
6
7
8
9
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

ThingsBoard提供便于在设备上接收和处理服务端RPC命令的API。 该API针对每种支持的网络协议有专门实现。 您可在相应参考页面查看API及示例:

持久化RPC

状态

ThingsBoard跟踪持久化RPC的状态。共有7种状态:

  • QUEUED - RPC已创建并保存到数据库;尚未尝试向设备发送;当设备上线或已在线时,ThingsBoard会立即尝试发送;默认情况下平台会同时尝试发送所有待处理RPC;在受限设备且队列中消息较多时,可能导致网络或设备过载。
  • SENT - ThingsBoard已尝试向设备发送RPC。
  • DELIVERED - 设备已确认RPC送达;这是单向RPC处理的最后一步。
  • SUCCESSFUL - ThingsBoard已收到双向RPC的回复。
  • TIMEOUT - ThingsBoard传输层(MQTT/CoAP/LwM2M等)检测到RPC投递超时;超时由对应配置参数控制:MQTT_TIMEOUT(默认10秒)、COAP_TIMEOUT(默认10秒)、LWM2M_TIMEOUT(默认120秒);默认平台不会重试,状态会变为FAILED;可在RPC体中配置重试次数;默认最大重试次数为5。
  • EXPIRED - 在配置的过期时间内RPC未送达或平台未收到设备回复;
  • FAILED - 在可配置次数的重试后仍无法送达,或设备固件不支持该命令。
文档信息图标

在配置顺序RPC投递时,若同时增加过期时间、投递超时和重试次数需格外小心。 若启用了顺序RPC投递且设备无法处理某个双向RPC命令,其他命令将无法发送至该设备。

规则链事件

RPC状态的变化会作为独立消息推送到规则引擎。 每种RPC状态都有对应的消息类型。如下图所示:

消息包含RPC请求的完整信息,包括实体id及请求体中的 “additionalInfo”。 “RPC Successful” 消息还会包含设备回复。 若要在外部系统中处理设备回复,这些消息很有用。

成功RPC消息示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
    "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’ 参数。