命令下发
概述
为能有效地对设备进行管理,设备的产品模型中定义了物联网平台可向设备下发的命令,应用服务器可以调用物联网平台应用侧API接口向设备下发命令,以实现对设备的远程控制。
物联网平台有同步命令下发和异步命令下发两种命令下发机制,如下表所示。
命令下发机制 |
定义 |
适用场景 |
LwM2M/CoAP协议设备 |
MQTT协议设备 |
---|---|---|---|---|
同步命令下发 |
应用服务器可调用同步命令下发接口向指定设备下发命令,以实现对设备的同步控制。平台负责将命令以同步方式发送给设备,并将设备执行命令结果在HTTP请求中同步返回, 如果设备没有响应,平台会返回给应用服务器超时。 |
同步命令下发适合对命令实时性有要求的场景,比如路灯开关灯,燃气表开关阀。使用同步命令下发时,命令下发的时机需要由应用服务器来保证。 |
不适用 |
适用 |
异步命令下发 |
应用服务器可调用异步命令下发接口向指定设备下发命令,以实现对设备的控制。平台负责将命令发送给设备,并将命令执行结果异步推送给应用。 异步命令下发又分为缓存下发和立即下发。
|
|
适用 |
不适用 |
使用场景
- 同步下发适合对命令实时性有要求的场景。异步用于实现对设备的控制。
- 需要通过数据转发规则转发到华为云其他云服务上进行存储和处理的场景。
使用限制
- 单个消息内容不大于256KB。
- 需要定义产品模型。
- 同步命令设备响应时间为20秒以内。
- 设备异步命令缓存数量为20个。
- 设备异步命令缓存时间支持配置,最长不超过48小时。
同步命令下发概述
同步命令下发主要用于MQTT设备,分为单个MQTT设备同步命令下发与批量MQTT设备同步命令下发。
类型 |
描述 |
适用场景 |
使用示例 |
---|---|---|---|
单个MQTT设备命令下发 |
平台向单个设备下发设备控制命令。 |
对单个设备进行下发设备控制命令。 |
|
批量MQTT设备命令下发 |
平台向多个设备下发设备控制命令。可创建批量处理任务,对多个设备进行批量操作 |
对多个设备进行批量下发设备控制命令。 |
单个MQTT设备同步命令下发
- 应用调用下发设备命令接口,下发请求到物联网平台,命令下发消息样例如下:
POST https://{Endpoint}/v5/iot/{project_id}/devices/{device_id}/commands Content-Type: application/json X-Auth-Token: ******** { "service_id" : "WaterMeter", "command_name" : "ON_OFF", "paras" : { "value" : "ON" } }
- 物联网平台根据协议规范下发命令给设备。消息样例如下:
Topic: $oc/devices/{device_id}/sys/commands/request_id={request_id} 数据格式: { "object_device_id": "{object_device_id}", "command_name": "ON_OFF", "service_id": "WaterMeter", "paras": { "value": "ON" } }
- 设备执行命令后通过平台命令下发上行接口返回命令执行结果,消息样例如下:
Topic:$oc/devices/{device_id}/sys/commands/response/request_id={request_id} 数据格式: { "result_code": 0, "response_name": "COMMAND_RESPONSE", "paras": { "result": "success" } }
- 应用侧收到发送HTTP下发命令的同步响应结果。消息样例如下:
Status Code: 200 OK Content-Type: application/json { "command_id" : "b1224afb-e9f0-4916-8220-b6bab568e888", "response" : { "result_code" : 0, "response_name" : "COMMAND_RESPONSE", "paras" : { "result" : "success" } } }
批量MQTT设备同步命令下发
平台支持通过调用创建批量任务接口,对多个MQTT协议设备下发同步命令。下面介绍如何调用创建批量任务下发批量命令。
- 应用调用创建批量任务接口,下发请求到物联网平台,下发消息样例如下。
POST https://{Endpoint}/v5/iot/{project_id}/batchtasks Content-Type: application/json X-Auth-Token: ******** { "app_id": "********", "task_name": "task123", "task_type": "createCommands", "targets": [ "********", "********" ], "document": { "service_id": "water", "command_name": "ON_OFF", "paras": { "value": "ON" } } }
- 物联网平台向应用返回“201 Created”。
- 设备接收命令,并通过上行topic向平台响应命令结果,参考平台命令下发。
- 通过调用查询批量任务列表接口查询批量命令下发任务执行情况。
异步命令立即下发
按照上述使用流程,进行对应步骤的示例如下:
- 应用调用下发异步设备命令接口,下发请求到物联网平台,携带send_strategy为immediately。消息样例如下:
POST https://{endpoint}/v5/iot/{project_id}/devices/{device_id}/async-commands Content-Type: application/json X-Auth-Token: ******** { "service_id" : "WaterMeter", "command_name" : "ON_OFF", "paras" : { "value" : "ON" }, "expire_time": 0, "send_strategy": "immediately" }
- 物联网平台调用编解码插件对命令请求进行编码后,会通过LwM2M协议定义的设备管理和服务实现接口的Execute操作下发命令,消息体为二进制格式。
- 物联网平台向应用返回200 OK,携带命令状态为SENT。(如果设备不在线或者设备没收到指令则下发失败,命令状态为FAILED)
- 设备收到命令后返回ACK响应。
- 若应用订阅了命令的状态变更通知,物联网平台通过命令状态更新通知接口推送消息给应用,携带命令状态为DELIVERED。消息样例如下:
Method: POST request: Body: { "resource": "device.commmad.status", "event": "update", "event_time": "20200811T080745Z", "notify_data": { "header": { "app_id": "********", "device_id": "********", "node_id": "test0001", "product_id": "********", "gateway_id": "********", "tags": [] }, "body": { "command_id": "********", "created_time": "20200811T080738Z", "sent_time": "20200811T080738Z", "delivered_time": "20200811T080745Z", "response_time": "", "status": "DELIVERED", "result": null } } }
- 设备执行命令后通过205 Content响应返回命令执行结果。
- 若应用订阅了命令的状态变更通知,物联网平台会调用编解码插件对设备响应进行解码,然后通过命令状态更新通知接口推送消息给应用,携带命令状态为SUCCESSFUL。消息样例如下:
Method: POST request: Body: { "resource": "device.commmad.status", "event": "update", "event_time": "20200811T080745Z", "notify_data": { "header": { "app_id": "********", "device_id": "********", "node_id": "test0001", "product_id": "********", "gateway_id": "********", "tags": [] }, "body": { "command_id": "********", "created_time": "20200811T080738Z", "sent_time": "20200811T080738Z", "delivered_time": "20200811T080745Z", "response_time": "20200811T081745Z", "status": "SUCCESSFUL", "result": { "resultCode":"SUCCESSFUL", "resultDetail": { "value": "ON" } } } } }
LwM2M/CoAP设备命令执行状态说明
命令执行状态以及状态变化机制如下所示。
命令执行状态 |
说明 |
---|---|
等待(PENDING) |
|
超期(EXPIRED) |
|
已发送(SENT) |
|
超时(TIMEOUT) |
LwM2M/CoAP设备收到命令后,物联网平台在180秒内未收到设备反馈的收到命令响应,此时状态会变为“超时”。 |
已送达(DELIVERED) |
物联网平台收到设备反馈的已收到下发命令响应后,状态变为“已送达”。 |
成功(SUCCESSFUL) |
如果设备在执行完命令后,会给物联网平台反馈命令执行成功的结果,将任务状态变更为“成功”。 |
失败(FAILED) |
|
平台命令下发使用示例
- 访问设备接入服务,单击 进入设备接入控制台。选择您的实例,单击实例卡片进入。
- 选择左侧导航栏的 ,在设备列表中,单击具体的设备进入到设备的详情页面。
- 在
页签,根据设备协议的不同,界面也有所不同。
- MQTT设备仅支持同步命令下发,单击右侧的“命令下发”,在弹出的窗口中选择需要下发的命令并设置命令参数。
图5 命令下发-同步命令下发
- LwM2M/CoAP设备仅支持异步命令下发,单击右侧的“命令下发”,在弹出的窗口中选择需要下发的命令并设置命令参数。您可以选择立即下发或者缓存下发。
图6 命令下发-异步命令下发
- MQTT设备仅支持同步命令下发,单击右侧的“命令下发”,在弹出的窗口中选择需要下发的命令并设置命令参数。
配置应用侧使用JAVA SDK进行同步命令下发的开发步骤如下,本示例使用的开发环境为JDK 1.8及以上版本。SDK代码获取:SDK下载
- 配置Maven依赖。
<dependency> <groupId>com.huaweicloud.sdk</groupId> <artifactId>huaweicloud-sdk-core</artifactId> <version>[3.0.40-rc, 3.2.0)</version> </dependency> <dependency> <groupId>com.huaweicloud.sdk</groupId> <artifactId>huaweicloud-sdk-iotda</artifactId> <version>[3.0.40-rc, 3.2.0)</version> </dependency>
- 以同步命令下发为例,样例如下:
public class CommandSolution { // REGION_ID:如果是上海一,请填写"cn-east-3";如果是北京四,请填写"cn-north-4";如果是华南广州,请填写"cn-south-4" private static final String REGION_ID = "<YOUR REGION ID>"; // ENDPOINT:请在控制台的"总览"界面的"平台接入地址"中查看“应用侧”的https接入地址。 private static final String ENDPOINT = "<YOUR ENDPOINT>"; // 标准版/企业版:需自行创建Region对象 public static final Region REGION_CN_NORTH_4 = new Region(REGION_ID, ENDPOINT); public static void main(String[] args) { String ak = "<YOUR AK>"; String sk = "<YOUR SK>"; String projectId = "<YOUR PROJECTID>"; // 创建认证 ICredential auth = new BasicCredentials().withDerivedPredicate(AbstractCredentials.DEFAULT_DERIVED_PREDICATE) .withAk(ak) .withSk(sk) .withProjectId(projectId); // 创建IoTDAClient实例并初始化 IoTDAClient client = IoTDAClient.newBuilder().withCredential(auth) // 基础版:请选择IoTDARegion中的Region对象 //.withRegion(IoTDARegion.CN_NORTH_4) // 标准版/企业版:需自行创建Region对象 .withRegion(REGION_CN_NORTH_4).build(); // 实例化请求对象 CreateCommandRequest request = new CreateCommandRequest(); request.withDeviceId("<YOUR DEVICE_ID>"); DeviceCommandRequest body = new DeviceCommandRequest(); body.withParas("{\"value\":\"1\"}"); request.withBody(body); try { CreateCommandResponse response = client.createCommand(request); System.out.println(response.toString()); } catch (ConnectionException e) { e.printStackTrace(); } catch (RequestTimeoutException e) { e.printStackTrace(); } catch (ServiceResponseException e) { e.printStackTrace(); System.out.println(e.getHttpStatusCode()); System.out.println(e.getRequestId()); System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } }
表6 参数说明 参数
说明
ak
您的华为云账号访问密钥ID(Access Key ID)。请在华为云控制台访问密钥。
页面上创建和查看您的AK/SK。更多信息请查看sk
您的华为云账号秘密访问密钥(Secret Access Key)。
projectId
项目ID。获取方法请参见 获取项目ID。
IoTDARegion.CN_NORTH_4
请替换为您要访问的物联网平台的区域,当前物联网平台可以访问的区域,在SDK代码IoTDARegion.java中已经定义。
您可以在控制台上查看当前服务所在区域名称,区域名称、区域和终端节点的对应关系,具体步骤请参考平台对接信息。
REGION_ID
如果是上海一,请填写“cn-east-3”;如果是北京四,请填写“cn-north-4”;如果是华南广州,请填写“cn-south-4”。
ENDPOINT
请在控制台的“接入信息”中查看“应用接入”的https接入地址。
界面的DEVICE_ID
下发消息的设备ID,用于唯一标识一个设备,在注册设备时由物联网平台分配获得。 取值范围:长度不超过128,只允许字母、数字、下划线(_)、连接符(-)的组合。
配置设备侧使用JAVA SDK进行同步命令下发的开发步骤如下,本示例使用的开发环境为JDK 1.8及以上版本。
- 配置设备侧SDK的Maven依赖。
<dependency> <groupId>com.huaweicloud</groupId> <artifactId>iot-device-sdk-java</artifactId> <version>1.1.4</version> </dependency>
- 配置设备侧SDK,设备连接参数。
//加载iot平台的ca证书,获取连接参考:https://support.huaweicloud.com/devg-iothub/iot_02_1004.html#section3 URL resource = BroadcastMessageSample.class.getClassLoader().getResource("ca.jks"); File file = new File(resource.getPath()); //注意格式为:ssl://域名信息:端口号。 //域名获取方式:登录华为云IoTDA控制台左侧导航栏“总览”页签,在选择的实例基本信息中,单击“接入信息”。选择8883端口对应的接入域名。 String serverUrl = "ssl://localhost:8883"; //在IoT平台创建的设备ID。 String deviceId = "deviceId"; //设备ID对应的密钥。 String deviceSecret = "secret"; //创建设备 IoTDevice device = new IoTDevice(serverUrl, deviceId, deviceSecret, file); if (device.init() != 0) { return; }
- 设置命令下发回调函数、发送响应。
client.setCommandListener(new CommandListener() { @Override public void onCommand(String requestId, String serviceId, String commandName, Map<String, Object> paras) { log.info("onCommand, serviceId = " +serviceId); log.info("onCommand , name = " + commandName); log.info("onCommand, paras = " + paras.toString()); //处理命令用户自定义 //发送命令响应 device.getClient().respondCommand(requestId, new CommandRsp(0)); } });
测试验证步骤如下:
- 在设备接入控制台,选择您的实例,单击实例卡片进入。选择左侧导航栏的
,在设备列表中,单击具体设备 进入设备详情,在 页签内,启动 。图7 消息跟踪-启动消息跟踪
- 先运行设备侧 SDK代码,使设备上线。
- 运行应用侧代码,当设备接收到设备下发的命令后,进行数据处理及响应。设备侧收到的命令下发样例如下:
图8 设备侧命令下发成功结果
-
显示结果如下:图9 消息跟踪-命令下发