开发手册
开发 - 数据操作
应用之间共享数据时,需要向提平台操作数据,或者从平台订阅数据。数据操作方面,这里主要涉及4个接口:新增数据、查询数据、删除数据、修改数据。详见后面的API参考。同时,为了便于应用开发,平台提供了SDK,简化开发。
SDK介绍
一. Java SDK
1. 依赖
<dependency> <groupId>com.aliyun.api.gateway</groupId> <artifactId>sdk-core-java</artifactId> <version>1.0.4</version></dependency>
2. 示例代码
SyncApiClientsyncClient=SyncApiClient.newBuilder().appKey("1234567").appSecret("6726732dsfdsdsfdsfds").build();IoTApiRequestrequest=newIoTApiRequest();//设置api的版本request.setApiVer("0.1.0");// 接口参数request.putParam("json","{}");request.putParam("productKey","a1ILGykZVhP");request.putParam("deviceName","Dxb3lv1E78mg5dsVLUQW");request.putParam("serviceName","kkp");//请求参数域名、path、requestApiResponseresponse=syncClient.postBody("test123-cn-shanghai.alicloudapi.com","/invokeThingService",request);System.out.println("response code = "+response.getStatusCode()+" response content = "+newString(response.getBody(),"utf-8"));
二. Python SDK
1. 依赖:无
2. 示例代码 Step 1:下载示例工程代码。示例工程在基于Python 2.7,Python3请自行适配。
Step 2:修改signature_composer.py文件第49行
修改前:string_to_sign.append(_build_resource(uri=uri,body=body))修改后:string_to_sign.append(uri)
Step 3: 修改ClientDemo.py如下,执行调用
#!/usr/bin/env python# -*- coding: utf-8 -*-importosimportsysimportjsonsys_path=sys.path[0]ifnotos.path.isdir(sys_path):sys_path=os.path.dirname(sys_path)os.chdir(sys_path)fromcom.aliyun.api.gateway.sdkimportclientfromcom.aliyun.api.gateway.sdk.httpimportrequestfromcom.aliyun.api.gateway.sdk.commonimportconstanthost="https://api.link.aliyun.com"url="/data/model/data/query"cli=client.DefaultClient(app_key="1234567",app_secret="abcdefghijklmnopq")req_post=request.Request(host=host,protocol=constant.HTTPS,url=url,method="POST",time_out=30000)req_post.set_content_type(constant.CONTENT_TYPE_STREAM)body={ "request": "apiVer":"0.0.2 "params":{ "modelId":"EMPLOYEE", "returnFields":["employee_no","name"], "conditions":[{"fieldName":"id","value":"1","operate":"mt"}], "pageSize":100, "pageNum":1 }, "version":"1.0"}bb=json.dumps(body).encode("utf-8")req_post.set_body(bb)print'==================================================='printstr(cli.execute(req_post)).decode('string_escape')print'==================================================='
三. JS SDK
1. 依赖
$# save into package.json dependencies with -S$ npm install aliyun-api-gateway-S$# you can use cnpm for fast install$ cnpm install aliyun-api-gateway-S
2. 示例代码
'use strict';constco=require('co');constClient=require('aliyun-api-gateway').Client;constclient=newClient('YOUR_APP_KEY','YOUR_APP_SECRET');co(function*(){ varurl='http://apiqingdaohttps.foundai.com/test1234'; varresult=yield client.post(url,{ data:{ 'testtest':'query1Value' }, headers:{ accept:'application/json' } }); console.log(JSON.stringify(result));});
数据操作API
一. API 描述
API名称 | 描述 | Path | 版本 |
新增数据 | 基于已经创建且被授权写入的模型,进行数据的新增。 | /data/model/data/insert | 0.0.3 |
删除数据 | 基于已经创建且被授权删除的模型,进行数据的更新。 | /data/model/data/delete | 0.0.2 |
修改数据 | 基于已经创建且被授权更新的模型,进行数据的更新。 | /data/model/data/update | 0.0.2 |
查询数据 | 基于已经创建且被授权查询的模型,进行数据的查询。 | /data/model/data/query | 0.0.3 |
获取文件上传地址 | 对于模型中指定为“图片”标签的字段,在该字段需要填写文件名,并且文件名需要通过该接口获取,该接口同时还会返回一个URL供用户上传文件。该地址有效期是10秒。 | /data/model/data/upload | 0.0.1 |
获取文件下载地址 | 对于模型中指定为“图片”标签的字段,在该字段的内容是一个系统分配的文件名,用户可以通过本接口,传入这个文件名,获取真实的文件下载地址。该地址有效期是10秒。 | /data/model/data/download | 0.0.1 |
二. API 约定
日期类型的参数传入格式:当前时间到格林威治时间1970年01月01日00时00分00秒的毫秒数。
数量查询的一些约定:
单次查询最多返回200条数据,未指定分页参数情况下,查询返回满足条件的前200条,可根据返回参数中的hasNext判断是否有更多数据。
若需要按照指定条件返回数据总数,则指定返回参数为COUNT,API返回参数中会带有COUNT以及对应的值。
若需要按照指定条件,及按照字段分组进行数量查询,则指定返回参数为COUNT(分组字段1,分组字段2),API返回参数中会带有COUNT以及对应的值。
更新删除的约定:单次操作,最多支持200条数据。
运算符定义:
算符 | 含义 | 备注 |
eq | equals | 相等 |
neq | not equals | 不相等 |
lt | less than | 小于 |
lteq | less than or equals | 小于等于 |
mt | more than | 大于 |
mteq | more than or equals | 大于等于 |
bt | between | 在..之间 |
in | in | 在..之内 |
nin | not in | 不在..之内 |
nul | is null | 为空 |
nnul | is not null | 不为空 |
数据包括系统属性,API中不允许赋值和更新系统属性,系统属性如下:
属性 | 描述 |
id | 数据主键 |
creator | 数据创建者 |
modifier | 数据修改者 |
gmt_create | 数据创建时间 |
gmt_modified | 数据修改时间 |
三. 数据新增API
1. 请求参数:
参数 | 类型 | 描述 | 是否必传 |
modelId | String | 数据模型id | 是 |
properties | JSON | 数据字段键值对,增加的字段的键只能是模型包含的字段,否则会报错,其中 Boolean属性的property传入”true”和”false”或者0和1。如:{“name”:”xxx”,”age”:18} | 是 |
scopeId | String | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 | 否 |
appId | String | 对于SaaS应用,需要填该值 | 否 |
2. 返回参数
参数 | 类型 | 描述 |
data | Long | 数据主键id |
3. 请求示例
{ "request":{ "apiVer":"0.0.3"//api版本号 }, "id":1508212818676,//request里的全局唯一id透传 "params":{ "modelId":"XXX123",//数据模型id "scopeId":"fdbsdj1dfjdubgxxx",//数据模型id "properties":{ "BRAND":"BMW", "MODE":"5", "CREATE_DATE":1526969423, "LONG_SIZE":3.3, "LONG_SIZE":2.2 } }, "version":"1.0"//请求协议版本}
4. 返回示例
{ "code":200, "message":"success", "localizedMsg":null, "data":12345}
5. 返回码
状态码 | 描述 | 其他说明 |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 | |
52005 | 找不到目标存储 | |
52009 | 参数和模型定义不匹配 | |
52011 | 数据类型校验错误 |
四. 数据删除API
1. 请求参数
参数 | 类型 | 是否必传 | 描述 |
modelId | String | 是 | 数据模型id |
conditions | JSON | 否 | 数据条件,由字段名、运算符、比较值组成一个condition。如:[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}] |
appId | String | 否 | 对于SaaS应用,需要填该值 |
scopeId | String | 否 | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 |
其中condition针对不同类型的属性支持的运算符:
属性 | 支持的运算符 |
Integer | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull |
String | eq,neq,,nnul,in,nin |
Double | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull |
Boolean | eq,nnul |
Date | eq,neq,lt,lteq,mt,mteq,bt,nnul |
2. 返回参数
参数 | 类型 | 描述 |
data | Integer | 删除数据的条数 |
3. 请求示例
{"request":{"apiVer":"0.1.0"//api版本号},"id":1508212818676,//request里的全局唯一id透传"params":{"modelId":"XXX123","conditions":[{"fieldName":"BRAND","value":"BMW","operate":"eq"},{"fieldName":"MODE","value":"X5","operate":"eq"}]},"version":"1.0"//请求协议版本}
4. 返回示例
{"code":200,"message":"success","localizedMsg":null,"data":100}
5. 返回码
状态码 | 描述 | 说明 |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 |
五. 数据修改API
1. 请求参数
参数 | 类型 | 是否必传 | 描述 |
modelId | String | 是 | 数据模型id |
updateDetails | JSON | 是 | 更新的具体字段和值,字段需要是模型中包含的字段,否则会报错,其中 Boolean属性的property传入”true”和”false”或者0和1。如:{“name”:”xxxx”,”age”:20} |
conditions | JSON | 否 | 条件,由字段名、运算符、比较值组成一个condition,格式如下:[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}]fieldName表示 字段的名称operate表示操作符,操作符见上表value表示值 |
appId | String | 否 | 对于SaaS应用,需要填该值 |
scopeId | String | 否 | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 |
其中condition针对不同类型的属性支持的运算符:
属性 | 支持的运算符 | |
Integer | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull | |
String | eq,neq,,nnul,in,nin | |
Double | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull | |
Boolean | eq,nnul | |
Date | eq,neq,lt,lteq,mt,mteq,bt,nnul |
2. 返回参数
参数 | 类型 | 描述 |
data | Integer | 更新数据的条数 |
3. 请求示例
{ "request":{ "apiVer":"0.0.3"//api版本号 }, "id":1508212818676,//request里的全局唯一id透传 "params":{ "modelId":"XXX123", "conditions":[ {"fieldName":"BRAND","value":"BMW","operate":"eq"}, {"fieldName":"MODE","value":"X5","operate":"eq"} ], "updateDetails":{ "LONG_SIZE":4, "WIDTH_SIZE":3 } }, "version":"1.0"//请求协议版本}
4. 返回示例
{ "code":200, "message":"success", "localizedMsg":null, "data":100}
5. 返回码
状态码 | 描述 | |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 | |
52006 | 资源更新错误 | |
52011 | 数据类型校验错误 |
六. 数据查询API
1. 请求参数
参数 | 类型 | 是否必传 | 说明 |
modelId | String | 是 | 数据模型ID |
returnFields | JSON | 是 | 指定返回的字段1.若期望返回所有字段,则传入参数为{““}2.若期望返回数据总数,则传入参数为{“COUNT”}2.若期望按照字段分组返回数据总数,则传入参数为{“COUNT(分组字段1,分组字段2)”}。如:[““]或者[“name”,”age”][COUNT][COUNT(name)] |
conditions | JSON | 否 | 条件,由字段名、运算符、比较值组成一个condition。如:[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}] |
orderBy | JSON | 否 | 排序条件,由增序或降序以及排序字段组成。如:{“asc”:”true”,”orderByFields”:[“name”,”age”]} |
pageNum | Integer | 否 | 分页页数 |
pageSize | Integer | 否 | 分页每页数量 |
appId | String | 否 | 对于SaaS应用,需要填该值 |
scopeId | String | 否 | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 |
其中returnFields支持的函数类型:
函数名称 | 描述 | 实例 |
COUNT | 函数返回匹配指定条件的行数 | {“COUNT(分组字段1,分组字段2)”} |
DATE_FORMAT | 函数按照format字符串格式化字段值 | {“DATE_FORMAT(分组字段,format)”} |
SUM | 函数返回数值列的总数 | {“SUM(分组字段)”} |
AVG | 函数返回数值列的平均值 | {“AVG(分组字段)”} |
MIN | 函数返回数值列的最小值 | {“MIN(分组字段)”} |
MAX | 函数返回数值列的最大值 | {“MAX(分组字段)”} |
DATE_FORMAT支持的format修饰符
修饰符名称 | 描述 |
%Y | 年 |
%Y-%m | 年月 |
%Y-%m-%d | 年月日 |
%Y-%m-%d %H | 年月日时 |
%Y-%m-%d %H:%i | 年月日时分 |
%Y-%m-%d %H:%i:%s | 年月日时分秒 |
其中condition针对不同类型的属性支持的运算符:
属性 | 支持的运算符 |
Integer | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull |
String | eq,neq,,nnul,in,nin |
Double | eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull |
Boolean | eq,nnul |
Date | eq,neq,lt,lteq,mt,mteq,bt,nnul |
2. 返回参数
参数 | 类型 | 描述 |
data | String | 查询返回数据内容,其中,Boolean类型的属性返回值为0或1 |
3. 请求示例-1
{ "request":{ "apiVer":"0.0.2"//api版本号 }, "id":1508212818676,//request里的全局唯一id透传 "params":{ "modelId":"XXX123", "returnFields":["MODE","ENGINE"], "conditions":[ {"fieldName":"BRAND","value":"BMW","operate":"eq"}, {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"}, {"fieldName":"LONG_SIZE","value":"3","operate":"mt"} ], "orderBy":{ "asc":true, "orderByFields":["CREATE_DATA","MODE"] }, "pageNum":1, "pageSize":10 }, "version":"1.0"//请求协议版本}
4. 返回示例-1
{ "code":200, "localizedMsg":null, "data":"{\"count\":1, \"hasNext\":false, \"items\":[{\"gmt_create\":1551872701000,\"MODE\":\"33\",\"ENGINE\":\"44\",\"id\":2,\"gmt_modified\":1551872714000}], \"pageNum\":1, \"pageSize\":10}", "message":"success"}
5. 请求示例-2
{ "request":{ "apiVer":"0.1.0"//api版本号 }, "id":1508212818676,//request里的全局唯一id透传 "params":{ "modelId":"XXX123", "returnFields":["COUNT", "conditions":[ {"fieldName":"BRAND","value":"BMW","operate":"eq"}, {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"}, {"fieldName":"LONG_SIZE","value":"3","operate":"mt"} ], "pageNum":1, "pageSize":10 }, "version":"1.0"//请求协议版本}
6. 返回示例-2
{ "code":200, "localizedMsg":null, "data":"{ \"hasNext\":false, \"items\":[{ \"COUNT\":100 }] }" "message":"success"}
7. 请求示例-分组数量查询
{ "request":{ "apiVer":"0.1.0"//api版本号 }, "id":1508212818676,//request里的全局唯一id透传 "params":{ "modelId":"XXX123", "returnFields":["COUNT(BRAND,NAME)"], "conditions":[ {"fieldName":"BRAND","value":"BMW","operate":"eq"}, {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"}, {"fieldName":"LONG_SIZE","value":"3","operate":"mt"} ], "pageNum":1, "pageSize":10 }, "version":"1.0"//请求协议版本}
8. 返回示例分组数量查询
{ "code":200, "localizedMsg":null, "message":"success", "data":"{ \"hasNext\":false, \"items\":[ { \"COUNT\":100, \"BRAND\":\"BMW\", \"NAME\":\"X1\" },{ \"COUNT\":200, \"BRAND\":\"JEEP\", \"NAME\":\"M2\" }] }"}
9. 返回码
状态码 | 描述 | |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 | |
52005 | 目标存储未找到 |
七. 获取文件上传地址API
1. 请求参数
参数 | 类型 | 是否必传 | 描述 |
modelId | String | 是 | 数据模型id |
version | String | 是 | 数据模型的版本号 |
fileSize | Integer | 是 | 文件大小,以字节为单位,目前系统不支持5M以上文件 |
attrName | String | 是 | 属性名称,模型中包含的属性名称,不包含会报错进行提示 |
fileType | String | 是 | 文件类型,目前系统只支持bmp、png、gif、jpg |
appId | String | 否 | 对于SaaS应用,需要填该值 |
scopeId | String | 否 | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 |
2. 返回参数
参数 | 类型 | 描述 |
url | String | 数据上传的url,url有效时间10s |
fileName | String | 文件名称,系统随机分配的文件名称,用户在得到这个文件名之后,应该将其放在相应模型数据的文件类型的字段上,例如:xxxxx.jpg |
3. 请求示例
{ "request":{ "apiVer":"0.0.1"//api版本号 }, "id":1508212818671,//request里的全局唯一id透传 "params":{ "modelId":"XXX123",//数据模型id "fileSize":"3.2",//文件大小 "attrName":"name",//属性名称 "fileType":"jpg",//文件类型 "version":"1.0",//模型版本 }, "version":"1.0"//请求协议版本}
4. 返回示例
{ "code":200,//返回是否成功,只要不是200说明返回不成功 "message":"success",//如果失败会返回失败的信息描述 "localizedMsg":null, "data":{"url":"http://xxx.xxx.xx","fileName":"xxx.jpg"}返回的数据}
5. 返回码
状态码 | 描述 | |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 | |
52005 | 找不到目标存储 | |
52009 | 参数和模型定义不匹配 | |
52011 | 数据类型校验错误 | |
52064 | 属性字段没有相应的图片标签 | |
52063 | 文件大小不能大于5M |
八. 获取文件下载地址API
1. 请求参数
参数 | 类型 | 是否必传 | 描述 |
modelId | String | 是 | 数据模型id |
version | String | 是 | 数据模型的版本号 |
attrName | String | 是 | 属性名称,模型中包含的属性名称,不包含会报错进行提示 |
fileType | String | 是 | 文件类型,目前系统只支持bmp、png、gif、jpg |
appId | String | 否 | 对于SaaS应用,需要填该值 |
scopeId | String | 否 | 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。 |
2. 返回参数
参数 | 类型 | 描述 |
url | String | 数据上传的url,url有效时间10s |
3. 请求示例
{ "request":{ "apiVer":"0.0.1"//api版本号 }, "id":1508212818671,//request里的全局唯一id透传 "params":{ "modelId":"XXX123",//数据模型id "scopeId":"fdbsdj1dfjdubgxxx",//业务隔离id "attrName":"name",//属性名称 "fileName":"xdsfxv.jpg",//文件类型 "version":"1.0",//模型版本 }, "version":"1.0"//请求协议版本}
4. 返回示例
{ "code":200,//返回是否成功,只要不是200说明返回不成功 "message":"success",//如果失败会返回失败的信息描述 "localizedMsg":null, "data":{"url":"http://xxx.xxx.xx"}返回的数据下载查看的url}
5. 返回码
状态码 | 描述 | |
200 | 成功 | |
460 | 参数验证异常 | 会带有验证异常的详细说明 |
500 | 服务异常 | server error |
52002 | 无访问权限 | |
52005 | 找不到目标存储 | |
52009 | 参数和模型定义不匹配 | |
52011 | 数据类型校验错误 | |
52064 | 属性字段没有相应的图片标签 |
开发 - 数据订阅
应用可以通过HTTP2方式,订阅数据的变更消息(新增、删除、修改)。应用自身不需要发布数据的变更消息到通道中,这些消息的产生是由应用通过上面的数据操作API,对数据进行操作之后,由平台产生。平台产生时间之后,会将消息通过订阅关系发送到订阅方。
在这个消息通信中,每一个应用实例,由AppKey标识身份。对于单租户型的应用,每一个AppKey代表了一次应用分发的实例;但是,对于SaaS应用,他的一个AppKey代表了该应用对应的所有租户的身份,因此,在SaaS应用按照AppKey得到消息之后,需要自行根据订阅到的数据内容中的AppID字段,将数据对应到不用的用户中。
SDK 介绍
1. 依赖引用
在工程中添加 maven 依赖接入 SDK。
<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>iot-client-message</artifactId> <version>1.1.3</version></dependency><dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.7.1</version></dependency>
2. 身份认证
使用服务端订阅功能,需要基于AppKey进行身份认证并建立连接。该AppKey根据应用类型不同,有两种来源:
对于独立单租户托管并分发的应用,该AppKey是由托管平台在应用实例化分发部署应用时,自动产生,并注入在主机的环境变量中,应用事先并不知道该值,需要动态从环境变量中获取。
对于共享型应用,该AppKey是该SaaS应用在注册多租户接口时,从平台创建,并硬编码在应用中。
StringappKey="XXXXXX";StringappSecret="XXXXXXXXXXXXXXXXXXXXXXX";Stringendpoint=String.format("https://%s.iot-as-http2.cn-shanghai.aliyuncs.com:443",appKey);// 连接配置Profileprofile=Profile.getAppKeyProfile(endpoint,appKey,appSecret);// 构造客户端MessageClientclient=MessageClientFactory.messageClient(profile);// 数据接收client.connect(messageToken->{ System.out.println(messageToken.getMessage()); returnMessageCallback.Action.CommitSuccess;});Thread.sleep(1000000);
*注意:关于上述代码中的“connect”方法,需要额外说明的是该方法在未经过授权的情况下,会调用失败。所以请务必做好重试逻辑,以便应用一旦被授权之后,可以及时得到订阅消息。
3. 设置消息接受接口
连接建立后,服务端会立即向 SDK 推送已订阅的消息。因此,建立链接时,需要提供消息接收接口,用于处理未设置回调的消息。建议在connect
之前,调用 setMessageListener 设置消息回调。
您需要通过 MessageCallback 接口的consume
方法,和调用 messageClient
的setMessageListener()
方法来设置消息接收接口。consume
方法的返回值决定 SDK 是否发送 ACK。设置消息接收接口的方法如下:
MessageCallbackmessageCallback=newMessageCallback(){ @Override publicActionconsume(MessageTokenmessageToken){ Messagem=messageToken.getMessage(); log.info("receive : "+newString(messageToken.getMessage().getPayload())); // TODO: 处理消息逻辑 returnMessageCallback.Action.CommitSuccess; }};Stringtopic=String.format("/sys/appkey/%s/dop/model/data/change",appkey);messageClient.setMessageListener(topic,messageCallback);
其中,Message消息字段如下:
// 消息体byte[]payload;// TopicStringtopic;// 消息IDStringmessageId;// QoSintqos;
payload内容是一个JSON对象字符串,字段信息如下:
// 模型ID
StringmodelId;
// 变更数据的ID
List<Long>dataIds;
// 操作类型:insert/update/delete
StringoperateType;
// 订阅的appId, 以appKey授权时为空
StringappId;