云端开发指南

一、概述

本文档用于指导北向应用开发者,通过物联云平台API接口,获取设备实时数据、设备告警数据、设备事件和服务调用实现业务应用接入开发。

应用接入主要分为设备实时数据查询、设备实时控制、设备告警数据接收。物联云平台通过提供Https Rest API和DDQ SDK用于设备数据查询、设备实时控制和设备实时数据推送、设备告警数据接收。开发者可根据本文档说明基于物联云平台进行北向应用对接。

二、数据流转过程示意图

数据流转过程示意图

数据流转过程说明:

1、设备上报数据到IoT平台;

2、数据通过规则引擎,存储在数据库;

3、数据通过DDQ 流转到企业的应用服务器;详见订阅设备数据(DDQ)章节

4、企业的应用系统调用IoT平台API,下发设备控制或配置指令;详见设备物模型接口章节;

三、API接口调用规范

3.1 API说明

物联云平台接口访问域名为api2.xlink.cn(如果是私有云,则需单独提供私有云访问地址)。

API网关是物联网平台面向开发者接口定义转发的服务,提供接口为Restful风格的HTTP接口。协议版本为HTTPS 1.1,HTTP 1.1(HTTPS暂不需要使用证书双向认证)。

物联云平台API接口为REST风格的HTTP接口,其资源访问路径结构为 协议://域名/API路径。

HTTP Request以及Response都采用JSON格式字符串作为消息实体。

注意:文件上传或其他流式数据传输另作讨论。

采用HTTP协议的GET、POST、PUT、DELETE Method作为资源操作动作。操作原则为:

  1. GET:进行数据获取;
  2. POST:数据添加。或者是复杂的数据查询,需要以Request Body作为查询参数的;
  3. PUT:数据修改;
  4. DELETE:数据删除。

3.2 请求鉴权

3.2.1 鉴权说明

  • HTTP请求API必须带上鉴权信息,平台通过鉴权信息来决定该请求能访问API范围以及数据范围。

  • 鉴权信息放入HTTP请求的Header中,Header字段为:“Access-Token”。

3.2.2 权限类型

  • HTTP请求API必须带上鉴权信息,平台通过鉴权信息来决定该请求能访问API范围以及数据范围。

  • 鉴权机制有两种,以具体的API以及业务为准

鉴权方式 适用范围 说明
AccessToken机制 Web/App端管理平台API 鉴权信息存入HTTP Header字段为:“Access-Token”
Signature机制 SaaS服务云云对接 鉴权信息存入HTTP Header字段为:“Signature”

3.2.3 鉴权信息类型

  • 注意:Access-Token为API网关北向应用调用时所需要传递的参数,但是SaaS应用本身设计API接口时,无需加入Access-Token字段。
  • 鉴权信息优先以AccessToken为准,即是在请求头发现Access-Token标识会进入Access-Token的鉴权逻辑,仅在请求头未发现Access-Token标识且发现Signature标识才会进入Signature鉴权逻辑。
  • 针对AccessToken鉴权机制和Signature机制鉴权机制,请求所需传的鉴权信息主要分为一下三种类型,不同的类型所能访问的权限结构不同,具体类型说明如下:
序号 类型 鉴权机制 获取方式 权限概述
1 Corp 见企业登录验证 AccessToken机制 企业B端用户权限,主要用于管理台访问平台数据,包括不限于创建获取设备数据等
2 User 见用户登录验证 AccessToken机制 企业C端用户权限,主要用于C端APP访问平台数据,包括不限于订阅设备、获取个人信息等
3 App 见应用网关登录验证 Signature机制 应用网关权限,主要用于平台对接时,访问平台数据,可限制具体接口,包括不限于用户管理类数据、产品设备管理类数据等

3.3 请求头

  • 根据不同的鉴权机制所需传输的请求头有所不同

3.3.1 AccessToken机制

字段 说明 是否必须
Group 前端API标识 是
Stage 前端API所属环境, RELEASE:正式环境 TEST:测试环境 PRE_RELEASE:预发布环境 是
Content-Type application/json 是
Access-Token 调用凭证,一般为用户登录后平台下发的用户Token 否,以具体接口为准
Request-Base API网关解析Token后加入到Header中的基础字段 否,请求通过API网关后自动加入

3.3.2 Signature机制

字段 说明 必填
Group 前端API标识 true
Stage 前端API所属环境
RELEASE:正式环境
TEST:测试环境
PRE_RELEASE:预发布环境
true
Content-Type application/json true
Signature 签名 true
App-ID 应用标识 true
Timestamp 时间戳 true
Request-ID 请求标识 true
Content-MD5 请求内容MD5散列值 false
当请求为POST和PUT请求时必传

3.5 通用返回结果

{
  "code": 4081001,
  "status": 408,
  "msg": "Request Timeout",
  "data": {
    "name":"xlink"
  }
}
字段 类型 描述
code Integer 业务错误码,业务错误码由各个接口来具体定义。
status Integer 通用HTTP状态码,200表示执行成功。 其他表示错误或其他返回,看附录的HTTP状态码定义。
msg String 错误的详细信息描述。
data Object 具体的接口响应数据。 无实际响应数据时,该字段为空。 其他数据以具体接口为准。

3.6 错误码定义

3.6.1 HTTP状态码

值 描述
200 请求成功
302 重定向跳转
400 请求字段不合法
401 缺少调用凭证
403 授权不通过
404 资源不存在
408 请求超时
405 方法不支持
502 响应超时
503 参数解析错误
504 服务器异常

3.6.2 业务错误码(示例)

  • 业务错误码由各个接口来具体定义,以下为通用示例:
值 描述
4001002 参数不能为空
4011001 请求头缺少Access-Token
4031003 无效Access-Token
4041001 接口找不到
4051001 Http方法不允许
5021001 网关异常
5031002 服务降级
5041001 访问超时

四、 订阅设备数据(DDQ)

DDQ(Data Dispath Queue)数据调度队列是物联网平台面向外部数据调度分发的服务,是物联云平台通过队列的方式对外数据输出的方式,外部系统通过DDQ能以数据流的方式接收到物联网数据。

目前DDQ在传输协议上,采用http2协议。物联云平台提供了DDQ
SDK便于应用开发者进行开发和接入,能够实时接收物联网平台设备数据,数据包含设备在线状态变化数据、设备属性变化数据、设备事件上报数据、设备告警数据。

4.1 DDQ物模型数据格式说明

通过DDQ SDK,
可以接收设备在线状态变化数据、物模型属性变化数据、设备事件上报数据,设备告警数据。
下列说明具体的事件主题和数据格式。

4.1.1 设备在线状态变化

当设备在线状态发生变化时,如设备从在线变化为离线,DDQ
SDK会接收到如下格式的消息。

{
    "topic": "/device-biz/state/product",
    "message_id": "消息ID",
    "payload": {
        "device_id": "设备ID",
        "is_online": "是否在线",
        "product_id": "产品ID",
        "corp_id": "企业ID",
        "create_time": "时间,yyyy-MM-dd'T'HH:mm:ss.SS'Z'",
        "project_id": "设备所属的项目ID"
    }
}

字段说明

字段 必填 类型 备注
product_id True String 产品ID
device_id True Int 设备ID
corp_id False Stirng 企业ID
create_time False String 创建时间
project_id False String 所属项目ID

4.1.2 设备属性上报

当设备通过物模型属性上报数据时,DDQ SDK会接收到如下的消息内容。

{
    "topic": "thing/event/{product_id}/device_attribute_sync_event",
    "message_id": "消息ID",
    "payload": {
        "version": 1,
        "time": "触发时间",
        "type": "tml",
        "event": "device_attribute_sync_event",
        "thing_id": "设备ID",
        "corp_id": "企业ID",
        "product_id": "产品ID",
        "attributes": [
            {
                "field": "mode",
                "value": 1
            }
        ]
    }
}

字段说明:

字段 必填 类型 备注
version True Int 消息版本号
time True Long 触发时间,毫秒时间戳
type True String 消息类型,固定为:tml
event True String 固定为:device_attribute_sync_event
thing_id True Int 设备ID
corp_id False String 企业ID
product_id False String 产品ID
thing_model_group False String 品类分组
thing_model_category False String 品类分类
thing_model_type False String 品类类型
attributes True List<Object> 物模型属性集合
attributes.field True String 属性字段名
attributes.value True String 物模型属性值

4.1.3 设备事件上报

当设备通过物模型上报事件时,DDQ SDK会接收到如下的消息内容。

{
    "topic": "thing/event/{product_id}/event_report",
    "message_id": "消息ID",
    "payload": {
        "version": 1,
        "time": "触发时间",
        "type": "tml",
        "event": "....",
        "thing_id": "设备ID",
        "corp_id": "企业ID",
        "product_id": "产品ID",
        "events": [
            {
                "field": "mode",
                "value": 1
            }
        ]
    }
}
字段 必填 类型 备注
version True Int 消息版本号
time True Long 触发时间,毫秒时间戳
type True String 消息类型,固定为:tml
event True String 事件名
thing_id True Int 设备ID
corp_id False String 企业ID
product_id False String 产品ID
thing_model_group False String 品类分组
thing_model_category False String 品类分类
thing_model_type False String 品类类型
events True List<Object> 事件信息集合
events.field True String 事件字段名
events.value True String 事件字段值

4.1.4 设备告警事件

当设备状态或者设备上报的物模型属性、事件满足管理台或者用户配置的告警条件时, DDQ SDK会接收到如下的消息内容。 {
    "topic": "/device/alert/product/{product_id}",
    "message_id": "消息ID",
    "payload": {
        "product_id": "产品ID",
        "corp_id": "企业ID",
        "device": {
            "id": "设备ID",
            "mac": "设备MAC"
        },
        "alert": {
            "exception": "当前是否异常,否则为恢复",
            "time": "异常/恢复时间, yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
            "rules": [
                {
                    "id": "异常规则ID",
                    "status": " 异常状态,1报警2恢复3已手动处理",
                    "notify": "异常规则通知类型,1通知2告警",
                    "current": "当前值",
                    "count": "本次累计异常次数",
                    "new_time": "本次异常触发时间,yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                    "start_time": "本地异常开始时间,yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                    "recover_time": "本此异常恢复时间,yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                    "processed_time": "本此异常处理时间,yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                    "exception_describe": "异常描述",
                    "notification_content": "本次异常报警内容"
                }
            ]
        }
    }
}
字段 必填 类型 备注
product_id True String 产品ID
device.id True Int 设备ID
device.mac False Stirng 设备MAC
corp_id True String 企业ID
alert.exception True Boolean 是否异常
alert.time True String 异常/恢复时间
alert.rules False List<Object> 相关规则列表
alert.rules.id False String 规则ID
alert.rules.status False Int 异常状态
alert.rules.notify False Int 通知类型
alert.rules.current False String 当前置
alert.rules.count False Int 累计异常次数
alert.rules.new_time False String 异常触发最新时间
alert.rules.start_time False String 异常触发开始时间
alert.rules.recover_time False String 异常恢复时间
alert.rules.processed_time False String 异常处理时间
alert.rules.exception_describe False String 异常描述
alert.rules.notification_content False String 异常内存

4.2 DDQ SDK关键参数说明

DDQ SDK初始化完成,发起连接时,需要提供用于连接和认证的必要参数,具体说明如下:

参数 参数说明 备注
host DDQ服务器访问地址(IP或域名) 公有云为h2-ddq.xlink.cn
port DDQ服务访问端口 公有云为:80
authUrl 客户端认证URL,客户端通过该url向DDQ服务器进行AppId、Token,成为有效客户端 公有云为: https://api2.xlink.cn
appId 应用ID 通过管理台,应用中心->应用详情中查看
accessToken 通过应用管理的AppId和AppSecret换取的AccessToken 接口见下面获取AccessToken凭证说明

4.3 获取AccessToken凭证

AccessToken是用于DDQ
SDK连接服务端时的凭证。本接口可以根据应用中心创建的AppId和AppSecre换取AccessToken。接口说明如下:

请求

POST /v2/plugin/app_auth

Header

Content-Type:application/json

Content

{  
"app_id": "应用网关标识",  
"app_secret": "应用网关密钥"  
}

响应

HTTP/\`\`1.1\` \`200\` \`OK

Content

{  
"access_token": "平台授予应用网关token",  
"refresh_token": "平台授予应用网关刷新token",  
"expire_in": "平台授予应用网关token过期时间"  
}

4.4 DDQ SDK使用示例代码

4.4.1 DDQ SDK初始化

private static void connect() throws Exception {
// 创建http2客户端,构造参数1为心跳间隔,参数2为判断超时时间,单位皆为毫秒  
        Http2Client http2Client = new Http2Client(1000, 15000);
//建立远程连接  
        Connection connection = http2Client.connect(socketAddress).get();
//设置接收数据回调  
        connection.setDefaultStreamListener(new Http2DataReceiver());
        connection.setConnectionListener(new Http2ConnectionListener());

		....
      	....
    }

4.4.2 发起连接认证

private static void connect() throws Exception {

//建立连接  
....
....
//客户端认证  
        Http2Headers headers = new DefaultHttp2Headers();
        headers.path(authUrl).scheme("http").method("POST").authority("xlink.cn");
//构建request data  
        JSONObject body = new JSONObject();
        body.put("app_id", appId);
        body.put("access_token", accessToken);
        body.put("auth_type", "accesskey");
        byte[] data = body.toJSONString().getBytes();
//发起认证请求  
        connection.writeHeaders(headers, false, new Http2StreamListener() {
            @Override
            public void onDataRead(Connection connection, Http2Stream streamData, byte[]
                    data, boolean endOfStream) {
                String dataString = new String(data);
                JSONObject json = JSONObject.parseObject(dataString);
                log.info("info {} ", json.toJSONString());
            }

            @Override
            public void onHeadersRead(Connection connection, Http2Stream stream,
                                      Http2Headers headers, boolean endOfStream) {
                log.info("info {} ", connection.getStatus());
            }

            @Override
            public void onStreamError(Connection connection, Http2Stream stream, IOException
                    e) {
                log.info("info {} ", connection.getStatus());
            }
        }).get().writeData(data, true).get();

    ....
    ....
    }

4.4.3 订阅数据

private static void connect() throws Exception{

//建立连接  
....  
....

//客户端认证  
....  
....

//订阅消息  
        Http2Headers headersSub = new DefaultHttp2Headers();
        JSONObject subData = new JSONObject();
        subData.put("topic", topic);
        headersSub.path(subscribeUrl).scheme("http").method("POST").authority("xlink.cn");

//发起订阅  
        connection.writeHeaders(headersSub, false, new Http2StreamListener() {
            @Override
            public void onDataRead(Connection connection, Http2Stream stream, byte[] data,
                                   boolean endOfStream) {
                String dataString = new String(data);
                JSONObject json = JSONObject.parseObject(dataString);
                log.info("info {} ", json.toJSONString());
            }

            @Override
            public void onHeadersRead(Connection connection, Http2Stream stream,
                                      Http2Headers headers, boolean endOfStream) {
                log.info("info {} ", connection.getStatus());
            }

            @Override
            public void onStreamError(Connection connection, Http2Stream stream, IOException
                    e) {
                log.info("info {} ", connection.getStatus());
            }
        }).get().writeData(subData.toJSONString().getBytes(), true).get();

    }

4.4.4 接收数据回调

 /**
     * 接收数据处理
     */
    public static class Http2DataReceiver extends AbstractHttp2StreamDataReceiver {

        @Override
        public void onDataRead(Connection connection, Http2Stream stream, StreamData
                streamData) {
            Http2Response response = new Http2Response(streamData.getHeaders(),
                    streamData.readAllData());
//接收到的数据  
            String content = new String(response.getContent());
            log.info("receiver data {}", content);
            JSONObject json = JSONObject.parseObject(content);
//...  
            String topic = json.getString("topic");
            String msgId = json.getString("msgId");
            JSONObject payload = json.getJSONObject("payload");

        }

        @Override
        public void onStreamError(Connection connection, Http2Stream stream, IOException
                e) {

        }
    }

4.4.5 连接状态监听

 /**
     * 连接状态监听
     */
    public static class Http2ConnectionListener implements ConnectionListener {

        @Override
        public void onSettingReceive(Connection connection, Http2Settings settings) {

        }

        @Override
        public void onStatusChange(ConnectionStatus status, Connection connection) {
//连接断开  
            if (status == ConnectionStatus.CLOSED){
                log.error("http/2 connection disconnected. ");
//当前连接断开时,进行重连  
                connection.close();
//开启重连线程  
                new ReconnectThread().start();
            }
        }
    }

4.4.6 当连接断开时,定时重连

/**
     * 重连线程
     */
    private static class ReconnectThread extends Thread{


        @Override
        public void run() {
            for(;;){
                try {
//每5秒进行重连  
                    Thread.sleep(5000L);
                    connect();
//没有异常说明连接成功,跳出定时重连  
                    break;
                }catch (Exception e){
                    log.error("", e);
                }
            }
        }
    }
没找到需要的文档?
你可以提交工单反馈 或 阅读常见问题