# SDK 快速入门

# 概述

本文档帮助您使用Java-SDK接入瀚云进行相关体验。为了更好理解相关概念,建议请先阅读平台概念和术语。点击这里

# 前期准备

# 帐号创建

如果您还没有Hanclous账号,请先注册 (opens new window),拥有瀚云帐号后才可进行后续创建产品操作。

# 创建项目

登录瀚云平台 (opens new window),选择【控制台】 -> 【创建项目】,在弹出页面中按照提示信息创建项目,为了方便您对项目的管理,请尽可能填写完整。

# 创建产品

登录瀚云平台 (opens new window),选择【控制台】 -> 【创建新产品】,在弹出页面中按照提示信息创建产品,为了方便您对产品的管理,请尽可能填写完整。

创建产品成功后,点击新创建的产品名,点击接入鉴权下的【查看】,记录该产品productKey和四组产品鉴权信息:

  1. accessKey/accessSecret
  2. cmdKey/cmdSecret
  3. uploadKey/uploadSecret
  4. queryKey/querySecret

关于平台的鉴权体系,请点击这里

# 创建设备

创建设备有两种方式。

第一种在瀚云官网上创建设备。 点击产品名,选择【设备管理】 -> 【添加设备】。输入设备 基础信息设备序列号 (sn)。

第二种通过瀚云OpenAPI进行设备创建。 后续会描述如何通过SDK创建DEMO。

关于平台上所有API使用,请参考API文档

创建设备成功后,点击【设备管理】 -> 【详情】,点击接入鉴权下的【查看】,记录设备类型Device Key序列号(sn),点击 【获取鉴权信息】,记录鉴权信息:queryToken、cmdToken、uploadToken、deviceSecret。

# 使用SDK

我们推荐使用JitPack的方式引入瀚云SDK,以下教程均基于MavenJitPack,如您需要其它集成方案,请下载Jar包 (opens new window)或源代码自行编译。

# 依赖引入

pom.xml文件中加入以下依赖。

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.hanclouds</groupId>
        <artifactId>java-sdk-httpapi</artifactId>
        <version>2.2.16-RELEASE</version>
    </dependency>
</dependencies>

# 创建设备代码

productKey, accessKey, accessSecret均为创建产品时所产生的鉴权码信息。

/**
 * 产品级鉴权创建设备
 */
public void createDevice(){
    HanCloudsClient hanCloudsClient = new HanCloudsClient("https://api.hanclouds.com/api/v1");
    hanCloudsClient.putProductAuthParams(productKey, accessKey , accessSecret );
    DeviceCreateRequest deviceCreateRequest = new DeviceCreateRequest();
    
    //设置调用参数。
    /**
     * 为什么我们授权那里设置了ProductKey,这里还需要设置呢?
     * 这里只是个巧合,我们不光可以使用产品授权,也可以使用用户授权创建设备。
     * 所以授权参数与调用参数要独立分开,互不影响。
     */
    deviceCreateRequest.setProductKey(productKey);
    deviceCreateRequest.setSn(sn);
    deviceCreateRequest.setDeviceName(deviceName);
    deviceCreateRequest.setDeviceType(deviceType);
    try {
        DeviceCreateResponse response =  hanCloudsClient.execute(deviceCreateRequest);
        if (response.isSucceed()) {
            //成功后处理代码
        }
        
        //response可以获取其它信息,具体请查看方法列表。
    } catch (HanCloudsException e) {
    }
}

# 下发命令

/**
 * 产品级鉴权下发命令
 */
public void deviceCommandSend(){
        DeviceCommandSendRequest deviceCommandSendRequest = new DeviceCommandSendRequest();
        HanCloudsClient hanCloudsClient = new HanCloudsClient("https://api.hanclouds.com/api/v1");
        hanCloudsClient.putProductAuthParams(productKey, cmdKey, cmdSecret);
        
        //设置调用参数。
        deviceCommandSendRequest.setDeviceKey(deviceKey);
        /**
         * 数据类型主要影响如何解析Content数据。
         * 服务器会解析上报的String数据,并按DataType类型下发数据给设备。
         */
        deviceCommandSendRequest.setDataType(DataTypeEnum.STRING);
        deviceCommandSendRequest.setContent("我是第一个命令");
        try {
            StringResponse response =  hanCloudsClient.execute(deviceCommandSendRequest);
            if (response.isSucceed()) {
                //成功后处理代码
            }
        } catch (HanCloudsException e) {
        }
    }

# 上传数据点

/**
 * 产品级鉴权上传数据
 */
public void deviceDataStreamUploadData(){
        DeviceDataStreamUploadDataRequest    deviceDataStreamUploadDataRequest = new  DeviceDataStreamUploadDataRequest();
        HanCloudsClient hanCloudsClient = new HanCloudsClient("https://api.hanclouds.com/api/v1");
        hanCloudsClient.putProductAuthParams(productKey, uploadKey, uploadSecret);
        
        //设置调用参数。
        deviceDataStreamUploadDataRequest.setDeviceKey(deviceKey);
        deviceDataStreamUploadDataRequest.setDataName(dataStreamName);
        deviceDataStreamUploadDataRequest.setDataType(DataTypeEnum.STRING);
        /**
         * 数据类型主要影响如何解析Content数据。
         * 服务器会解析上报的String数据,并按DataType类型上传数据点
         */
        deviceDataStreamUploadDataRequest.setContent("第一次上传数据");
        try {
            BooleanResponse response =  hanCloudsClient.execute(deviceDataStreamUploadDataRequest);
            if (response.isSucceed()) {
            }
        } catch (HanCloudsException e) {
        }
    }

# 找到其它API

以上只是几个比较典型的案例,您可以在API文档中查找到更多的API通过对应的xxxRequest类进行调用。

# SDK升级

随着平台的迭代发展,API数据会随着功能逐渐增加,API具体参数也会随着功能进行修改。我们会保证重大版本的API兼容性。意味着您使用1.0-RELEASE版本的SDK,如果您没有其它功能需求,在v1版本API废弃前均可使用,即使SDK有额外版本升级。

唯一例外条件是SDK或平台出现Bug或安全漏洞不得不对某些SDK进行调整,请关注我们研发社区和官方站点。

# 常见问题与分析

瀚云工业互联网平台是一个开放平台,平台始终坚持把安全放在第一位,对外开放基于HTTP协议的Restful API(简称API)。为避免相关操作被恶意调用,平台对所有相关操作都进行了权限控制,只有鉴权通过才可以进一步操作。常见问题如下:

# 常见问题一:

问题场景:
通过签名鉴权请求API时,有时能鉴权通过,有时候会鉴权失败,常见Restful签名鉴权点击这里

问题分析:
http的GET请求时,url中签名参数或其他参数如果出现【+】号,在服务端会被urldecode替换成空格 同样的签名算法会导致客户端与服务端生成的签名参数不一致

解决方案:
http的GET请求时,将url中签名参数或其他参数进行urlencode编码,然后在发起请求就能避免这个问题 java示例:

public class Test{
    public static void main(String[] args) {
        String url="https://api.hanclouds.com/api/v1/devices/xxx/datastreams?";
        String requestParam = "page=1&pageSize=10&signature=qwerljalajsdf+";
        String encodeParam = URLEncoder.encode(requestParam, "UTF-8");
        String finalUrl = url+encodeParam;
        //encode之后发起请求
        client.post(finalUrl);
    }
}

# 常见问题二:

问题场景:
通过签名鉴权频繁请求API时,有时会返回请求频繁日志,如:

Too Many Requests,Please try again later

问题分析:
瀚云用户创建后,平台会自动给用户限定每分钟600次API请求,当请求频繁了就提示了频繁请求

解决方案:
出现此类问题,联系瀚云科技工作人员修改限流方案 电话:023-67302223

# 常见问题三:

问题场景:
通过签名鉴权请求API时,有时会返回请求时间异常日志,如:

time or nonce error,sendTime=%s,receiveTime=%d,requestHeader=%s

问题分析:
用户通过签名鉴权调用API,传入的 ts 时间戳为自己内部服务器的系统时间,如果通过请求的时间和我们服务器的时间大于5分钟就提示这个错误

解决方案:
http的GET,POST请求时,请求的时间戳通过调用API的方式获取瀚云内部服务器的时间 java示例:

public class Test{
    public static void main(String[] args) {
        String url="https://api.hanclouds.com/api/v1/now?f=std&u=ms";
        //encode之后发起请求
        String ts = client.post(url);
        //返回示例 1529660469123  毫秒
    }
}