OneNET物联网平台11 使用OneNET平台提供的API向设备发送命令

1、API介绍

使用onenet平台提供的设备命令API,直接向设备下发指令,当设备收到指令并进行应答时,API返回设备应答内容

请求API:POST

http://api.heclouds.com/v1/synccmds?device_id=866760442&timeout=30

请求体body中携带:用户自定义命令数据内容

  • device_id:设备id
  • timeout:同步API最长等待时间,取值范围 5-30, 单位秒

访问接口得到的返回语法:

Content-type: application/json

{
    "errno": 0,
    "error": "success",
    "data": {
        "cmd_uuid": "3b6ab6e6-f729-4825-83e6-397d8c27c284",
        "cmd_resp": "cmVjZWl2ZSBjbWQuLi4="
    }
}

返回参数:

  • errno:错误码
  • error: 错误描述
  • cmd_uuid: 命令ID
  • cmd_resp:设备应答内容,base64编码格式

返回错误码

错误码 错误描述 说明
12 device not found 设备不存在
13 device not online 设备不在线
15 sync cmd timeout 设备命令应答超时

返回错误示例

{
    "errno": 15,
    "error": "sync cmd timeout"
}

使用限制

  • 命令请求body数据长度必须 小于1k
  • 设备应答时payload长度必须 小于1k

2、新建访问URL工具类

package com.wzkj.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;

/**
 * HTTP工具
 *
 * @author hyh
 */
public class HttpUtils {
    /**
     * 发送数据到POST请求路径
     *
     * @param url     请求路径
     * @param headers 请求头
     * @param params  请求参数
     * @return String
     */
    @SuppressWarnings("unchecked")
    public static String SendPost(String url, JSONObject headers, JSONObject params) {
        String ret = "";
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(url);

        for (Map.EntryString, Object> entry : headers.entrySet()) {
            String key = entry.getKey();
            method.addRequestHeader(key, headers.getString(key));
        }

        for (Map.EntryString, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            method.addParameter(key, params.getString(key));
        }

        try {
            client.executeMethod(method);
            BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
            StringBuffer stringBuffer = new StringBuffer();
            String str = "";
            while ((str = reader.readLine()) != null) {
                stringBuffer.append(str);
            }
            ret = stringBuffer.toString();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            method.releaseConnection();
        }

        return ret;
    }

    /**
     * 发送数据到POST请求
     *
     * @param url     发送设备命令的http地址
     * @param headers 请求头
     * @param params  请求参数
     * @return String 返回结果
     */
    @SuppressWarnings({"unchecked", "deprecation"})
    public static String SendPost(String url, net.sf.json.JSONObject headers, String params) {
        String ret = "";
        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(url);
        IteratorString> header = headers.keys();
        while (header.hasNext()) {
            String key = header.next();
            method.addRequestHeader(key, headers.getString(key));
        }

        method.setRequestBody(params);

        try {
            client.executeMethod(method);
            BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8"));
            StringBuffer stringBuffer = new StringBuffer();
            String str = "";
            while ((str = reader.readLine()) != null) {
                stringBuffer.append(str);
            }
            ret = stringBuffer.toString();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            method.releaseConnection();
        }

        return ret;
    }
}

3、生成访问授权方法

该方法在demo中就有,Token类就是生成授权的类,而在onenet中,token有两种,一种是API访问的token,一种是设备连接的token。

在其main方法中有个参数resourceName,其不同的设计格式可以生成不同的访问token

场景 res参数格式 示例 说明
API访问 products/{pid} products/123123
设备连接 products/{pid}/devices/{device_name} products/123123/devices/mydev 需使用设备级密钥

当前场景是使用API访问,所以resourceName的格式为products/{pid}

我的产品ID是480701accessKeyZQjnxxt0B5Rrdn17Kzz11+UOM3UhJePYMYEgkHtXpV4=,代码如下:productIdaccessKey参数改成自己的即可

public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
    // oneNet的产品ID
    String productId = "480701";
    // 产品的access_key
    String accessKey = "ZQjnxxt0B5Rrdn17Kzz11+UOM3UhJePYMYEgkHtXpV4=";

    // 版本号,无需修改
    String version = "2018-10-31";
    // API访问 访问资源
    String resourceName = "products/" + productId;
    // 访问过期时间
    String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";
    //签名方法,支持md5、sha1、sha256
    String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
    String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);

    System.out.println("Authorization: " + token);
}

运行后生成的token是:version=2018-10-31&res=products%2F480701&et=1653707690&method=sha1&sign=JahknKD6%2FXuvbPVA3fIj3A%2FoTiA%3D

4、访问API

HttpUtils提供了两种访问URL方式:

方式1:请求头使用com.alibaba.fastjson.JSONObject,请求体为JSON格式

@Test
public void dispatchOrders(){
    String deviceId = "866760442";
    String token = "version=2018-10-31&res=products%2F480701&et=1712112818&method=sha1&sign=89dqMv4ygwfq5dUZXEHsv88m%2BGI%3D";

    JSONObject headers = new JSONObject();
    headers.put("Authorization", token);
    JSONObject jsonObject = new JSONObject();
    // 发送给设备的命令参数
    jsonObject.put("color", "-101");

    String url = "http://api.heclouds.com/v1/synccmds?device_id=" + deviceId + "&timeout=30";
    System.out.println(jsonObject);
    String sendPost = HttpUtils.SendPost(url, headers, jsonObject);

    System.out.println(sendPost);
}

方式二:请求头使用net.sf.json.JSONObject,请求体为String格式

@Test
public void dispatchOrders2(){
    net.sf.json.JSONObject headers = new net.sf.json.JSONObject();
    String token = "version=2018-10-31&res=products%2F480701&et=1712112818&method=sha1&sign=89dqMv4ygwfq5dUZXEHsv88m%2BGI%3D";
    headers.put("Authorization", token);

    String deviceId = "724860362";
    // 发送给设备的命令参数
    String param = "0";

    String params = String.format(""S1:%s"", param);
    String url = "http://api.heclouds.com/v1/synccmds?device_id=" + deviceId + "&timeout=30";
    String sendPost = HttpUtils.SendPost(url, headers, params);

    System.out.println(sendPost);
}

运行后的返回结果:

OneNET物联网平台11 使用OneNET平台提供的API向设备发送命令

设备应答内容为cmVjZWl2ZSBjbWQuLi4=,base64编码格式,将其解密为:receive cmd...,翻译过来就是收到命令

OneNET物联网平台11 使用OneNET平台提供的API向设备发送命令

5、解析请求结果

添加Base64解析工具类:

package com.yuyun.utils;

import sun.misc.BASE64Decoder;

import java.io.IOException;

/**
 * Base64工具类
 *
 * @author hyh
 */
public class Base64Utils {

    /**
     * Base64解码
     *
     * @param bytes Base64加密的字节码
     * @return String
     * @throws IOException IOException
     */
    public static String Base64Decode(byte[] bytes)
            throws IOException {
        BASE64Decoder base64decoder = new BASE64Decoder();
        byte[] bs = base64decoder.decodeBuffer(new String(bytes));
        return new String(bs, "UTF-8");
    }
}

解析sendPost:

JSONObject sp = JSONObject.parseObject(sendPost);
int errno = sp.containsKey("errno") ? sp.getInteger("errno") : -1;
String error = sp.containsKey("error") ? sp.getString("error") : "";
if (errno != 0 && StringUtils.isNotBlank(error)) {
    System.out.println(error);
}
JSONObject data = sp.containsKey("data") ? sp.getJSONObject("data") : new JSONObject();
if (data.containsKey("cmd_resp")) {
    String cmdResp = data.getString("cmd_resp");
    try {
        String str = Base64Utils.Base64Decode(cmdResp.getBytes());

        System.out.println("解码后的cmd_resp:" + str);
    } catch (Exception e) {
        System.out.println("解码失败!");
    }
}

输出结果:

OneNET物联网平台11 使用OneNET平台提供的API向设备发送命令

完整代码

@Test
public void dispatchOrders() {
    String deviceId = "866760442";
    String token = "version=2018-10-31&res=products%2F480701&et=1712112818&method=sha1&sign=89dqMv4ygwfq5dUZXEHsv88m%2BGI%3D";

    JSONObject headers = new JSONObject();
    headers.put("Authorization", token);
    JSONObject jsonObject = new JSONObject();

    // 发送给设备的命令参数
    jsonObject.put("color", "-101");

    String url = "http://api.heclouds.com/v1/synccmds?device_id=" + deviceId + "&timeout=30";
    System.out.println(jsonObject);
    String sendPost = HttpUtils.SendPost(url, headers, jsonObject);

    System.out.println(sendPost);

    JSONObject sp = JSONObject.parseObject(sendPost);
    int errno = sp.containsKey("errno") ? sp.getInteger("errno") : -1;
    System.out.println("errno:" + errno);

    String error = sp.containsKey("error") ? sp.getString("error") : "";
    System.out.println("error:" + error);

    if (errno != 0 && StringUtils.isNotBlank(error)) {
        System.out.println(error);
    }
    JSONObject data = sp.containsKey("data") ? sp.getJSONObject("data") : new JSONObject();
    System.out.println(data);

    if (data.containsKey("cmd_resp")) {
        String cmdResp = data.getString("cmd_resp");
        try {
            String str = Base64Utils.Base64Decode(cmdResp.getBytes());

            System.out.println("解码后的cmd_resp:" + str);
        } catch (Exception e) {
            System.out.println("解码失败!");
        }
    }
}

demo地址:https://gitee.com/hyh17808770899/spring-boot/tree/master/springboot-onenet

本文章来源于互联网,如有侵权,请联系删除!原文地址:OneNET物联网平台11 使用OneNET平台提供的API向设备发送命令

相关推荐: 支付宝被撤销高新技术企业资格?任正非痛失将才,通信业巨星陨落;苹果/谷歌/三星/亚马逊罕见联手推动智能家居统一标准|IoT周报

【物联网头条】 支付宝被撤销高新技术企业资格?蚂蚁集团回应 近期,上海市高新技术企业认定指导小组公告了2022年第一批撤销高新技术企业资格企业名单,撤销年份在2020年和2021年,其中就包括支付宝(中国)网络科技有限公司,由此引发多方关注。蚂蚁集团方面回应贝…