一、准备工作
1.1 获得平台授权信息
云端服务器地址:
- 测试环境:dev-cm.xlink.cn:1883
- 公有云:mqtt.xlink.cn:1883
- 私有云:私有云运维人员提供。
授权证书获取途径:
- 途径一:【登录管理台】->【开发平台】->【网关授权】-> 【新建网关授权】→【关联要对接的产品】→【完成】
- 途径二:由对接协调人员提供。
连接器类型获取途径:
- 途径一:【登录管理台】->【开发平台】->【物联网连接器】->【连接器管理】->【创建连接器】->得到【连接器ID】->完成。 注:连接器ID等同于这里的连接器类型。
- 途径二:由对接协调人员提供
物模型获取途径:
- 途径一:【登录管理台】->【进入设备中心】→找到对应【物模型】
- 途径二:由对接协调人员提供。
二、代码示例片段
2.1 初始化客户端
根据平台授权信息,初始化客户端。
- 客户端对象在Xagent程序中应为单例模式。
- 连接器类型用于标识Xagent的类型,如区分是停车系统Xagent、门禁系统Xagent等等
- 在订阅物模型服务处理时,根据产品ID进行订阅,产品ID用于区分不同物模型的服务
代码示例
public final static String CERT_ID = "****************";//网关Cid
public final static String CERT_KEY = "*******************";//网关CKey
public final static String DEVICE_ENDPOINT = "*******";//mqtt地址
public final static String CONNECTOR_TYPE = "*****"; // 连接器类型,用于标识连接器类别
public final static String PRODUCT_ID = "******************************";// 产品ID
private static XlinkCmMqttClient xlinkMqttClient; //定义全局的客户端
/**
* 初始化Xagent 客户端
*/
private static void init() throws Exception {
//构造器配置
xlinkMqttClient = XlinkMqttBuilderParams.builder()
.certId(CERT_ID) //配置授权证书ID
.certKey(CERT_KEY) //配置授权证书密钥
.endpoint(DEVICE_ENDPOINT)//云端CM服务器地址
.connectorType(CONNECTOR_TYPE)//配置连接器类型
.isOpenLog(true) //开启调试日志
.addSubscribeServiceName(PRODUCT_ID, "open_door", "close_door")//订阅物模型服务处理
.build(); //构造XlinkMqttBuilderParams实例
//建立连接及认证
xlinkMqttClient.start();
}
2.2 设备上线
一般情况下,对接接入都必须进行设备上线,这里提供通过产品ID、Mac信息进行设备上线。
- 产品ID获取方式:在物联网管理台->开发平台->产品信息->得到。
- Mac获取方式::在物联网管理台->开发平台->产品信息-> 设备列表>中获取。设备由【设备注册】进行添加,Mac需在产品下唯一。
方法:xlinkMqttClient.deviceLogin()提供多个重载,可以指定IP,或指定设备在平台的版本信息
代码示例
/**
* 示例一:在平台进行上线,一般在进行设备初始化时,必须调用
*
* @param productId
* @param mac
*/
private static int deviceLogin(String productId, String mac) throws ExecutionException, InterruptedException {
//在平台登录上线,并得到返回
DeviceLoginResultMessage deviceLoginResultMessage = xlinkMqttClient.deviceLogin(productId, mac).get();
//得到返回结果
if (deviceLoginResultMessage.getRetCode() == DeviceLoginRetCodeType.SUCCESS) {
//上线成功,得到平台唯一的设备ID、在物模型下,可以当做thing id使用
int deviceId = deviceLoginResultMessage.getDeviceId();
//建议将设备ID在内存保存起来,在后续的操作,会经常使用到。
//自定义代码..
return deviceId;
} else {
//上线失败,从RetCode读取错误信息及类型
DeviceLoginRetCodeType retCode = deviceLoginResultMessage.getRetCode();
//自定义代码..
return 0;
}
}
2.3 发布物属性
发布属性将属性最新信息上报到物联网平台,平台将保存最新的属性信息。
使用场景:
- 当具体环境监测设备传感器监测到气象信息发生变化了,可以通过发布属性信息如:温度、湿度、PM2.5等。
- 某设备的最新状态,如设备的开关状态、模式等。
代码示例
/**
* 示例二:发布物属性,引起平台的最新的物属性变化
*
* @param deviceId 设备上线后得到的设备ID
* @throws Exception
*/
private static void publishAtrribute(int deviceId) throws Exception {
//物模型的版本号
int version = 0;
xlinkMqttClient.publishAttribute(deviceId, version,
new HashMap() {{
put("state", "open"); //属性字段
put("color", "red");//属性字段
}}, new Date());
}
2.4 发布事件
事件是物模型中定义的某一个事件,并且在实际过程中,设备根据事件的定义进行发布到物联网平台,如物模型定义了一个设备故障事件,在设备运行过程中,如果达到”故障“状态,设备发布该”设备故障事件“到云端,并在事件中包含该事件的具体信息(事件字段)。
使用场景:
- 门禁开门事件
- 道闸通行事件
- 视频检测事件
- 等等
相关:在2.3 发布物属性后,物联网平台会自动触发“物属性变化事件”。
代码示例
/**
* 示例三:发布事件
*
* @param deviceId 设备上线后得到的设备ID
*/
private static void publishEvent(int deviceId) throws Exception {
//设备上线后得到的设备ID
//物模型的版本号
int version = 0;
//物模型中的事件名
String eventName = "xxx";
xlinkMqttClient.publishEvent(deviceId, version, eventName,
new HashMap() {{
put("state", "open"); //事件字段
put("color", "red");//事件字段
}}, new Date());
}
2.5 属性设置回调
属性设置回调是云端主动下发的设置属性请求,由终端进行处理后返回告知设置的结果,注:当终端接收了云端的属性设置后,需通过发布物属性将最新属性发布到云端,云端才会更新最新的属性信息。
如使用场景:
- 将电灯的“颜色”属性设置为红色或蓝色
- 将风扇的运行模式属性设置中档、高档。
- 设置门禁的密码信息。
- 等等
相关:属性设置是系统内置的特殊服务
代码示例
/**
* 示例四:监听服务端的属性设置请求,并应答服务端
*/
private static void setAttributeCallback() {
//监听服务端属性设置回调方法,注意:多个设备ID的属性设置回调方法实现可以为同一个
xlinkMqttClient.setSetAttributeHandler(request -> {
//服务端设置下发的属性信息
Map<String, Object> attribute = request.getAttributes();
//服务端设置下发的设备ID
int setDeviceId = request.getDeviceId();
//自定义代码
//构建应答包错误码
String code = "200";
//构建应答包
SetAttributeResponse response = new SetAttributeResponse(code);
//通过方法返回值进行应答,如方法返回值null,则不会应答。
return response;
});
}
2.6 属性获取回调
属性获取回调是云端主动下发的获取属性请求,由终端进行处理后返回属性列表结果,从而使上层应用在读取属性时,会有两种不同数据源:
- 一种是通过发布物属性,储存在云端的属性信息,
- 一种是通过本方法回调,直接从终端返回具体是属性信息。
代码示例
/**
* 示例五:监听服务端的属性获取请求,并应答服务端
*
*/
private static void getAttributeCallback() {
//监听服务端属性获取回调方法,注意:多个设备ID的属性获取回调方法实现可以为同一个
xlinkMqttClient.setGetAttributeHandler(reqeust -> {
//得到服务端属性获取的设备ID
int getDeviceId = reqeust.getDeviceId();
//自定义代码
//构建应答的信息属性
Map<String, Object> attributes = new HashMap() {{
put("f1", 1);
put("f2", "str..");
}};
//构建应答包错误码
String code = "200";
//构建应答包
GetAttributeResponse response = new GetAttributeResponse(code, attributes);
//通过方法返回值进行应答,如方法返回值为null,则不会应答
return response;
});
}
2.7 服务调用回调
服务是物模型下描述某种行为或能力,设置该服务调用函数,当平台进行服务调用时,会回调该方法,由终端处理后返回。
使用场景:
- 门禁物模型可定义开门、关门、设置密码等服务,服务由上层应用调用,下发到客户端进行回调处理后返回。
注:订阅某个服务的回调下发需要在初始化客户端时配置好,服务必须是在物模型定义的服务列表内,并且有严格的输入、输出参数和返回错误码。
代码示例
/**
* 示例六:监听服务端的服务调用下发,并应答服务端
*/
private static void serviceInvokeCallback() {
//物模型中的服务名
//监听服务端服务调用的回调方法,注意:多个设备ID、多个不同服务的服务调用回调方法实现可以为同一个。
xlinkMqttClient.setServiceInvokeHandler(request -> {
//得到服务调用的设备ID
int invokeDeviceId = request.getDeviceId();
//得到服务调用的服务名
String invokeServiceName = request.getServiceName();
//得到服务调用的输入参数
Map<String, Object> input = request.getInput();
//自定义代码
switch (invokeServiceName) {
case "open_door": {
//...
break;
}
case "close_door": {
//...
break;
}
}
//构建应答包错误码
String code = "200";
//构建应答包输出参数
Map<String, Object> output = new HashMap() {{
put("f1", 4);
put("f2", "str");
}};
//构建应答包
ServiceInvokeResponse serviceInvokeResponse = new ServiceInvokeResponse(code, output);
//通过方法返回值进行应答,如方法返回值为null,则不会应答
return serviceInvokeResponse;
});
}
2.8 上报自定义调试日志
上报自定义调试日志,可在物联网管理台中可以看到具体的日志打印,便于实时查看设备的运行日志。
注:本身设备的基本行为如:上线、上报数据、接收数据都默认在调试日志里会展现。
代码示例
/**
* 示例七:自定义上报调试日志
*/
xlinkMqttClient.deviceLog(deviceId, "日志内容。。。。");
三、完整代码示例
Maven POM 文件(需在物联云平台内部私有Maven服务下,如不在该访问范围,可联系对接协调人员单独提供。)
pom.xml
<dependency>
<groupId>cn.xlink</groupId>
<artifactId>xlink-iot-sdk</artifactId>
<version>3.5.4-pg</version>
<scope>compile</scope>
</dependency>
依赖库文件:
代码示例
代码示例
import cn.xlink.iot.sdk.XlinkMqttBuilderParams;
import cn.xlink.iot.sdk.mqtt.client.cm.XlinkCmMqttClient;
import cn.xlink.iot.sdk.mqtt.client.subscribe.message.GetAttributeResponse;
import cn.xlink.iot.sdk.mqtt.client.subscribe.message.ServiceInvokeResponse;
import cn.xlink.iot.sdk.mqtt.client.subscribe.message.SetAttributeResponse;
import xlink.cm.message.DeviceLoginResultMessage;
import xlink.cm.message.type.DeviceLoginRetCodeType;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* Xagent SDK 3.5 Demo
*
* @Author shenweiran
* @Date 2019-08-24 17:51
*/
public class Demo_v3_5 {
public final static String CERT_ID = "****************";//网关Cid
public final static String CERT_KEY = "*******************";//网关CKey
public final static String DEVICE_ENDPOINT = "*******";//mqtt地址
public final static String CONNECTOR_TYPE = "*****"; // 连接器类型,用于标识连接器类别
public final static String CONNECTOR_TYPE = "*****************"; // 连接器类型,用于标识连接器类别
public final static String PRODUCT_ID = "******************************";// 产品ID
//Xagent客户端
private static XlinkCmMqttClient xlinkMqttClient;
/**
* 程序启动入口方法
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//定义Mac地址,或者一个能唯一的标识设备的字符,该Mac信息应该在预先导入对应的产品信息下,否则会发生错误
String mac = "AB*******CC";
//初始化客户端
init();
//示例一:在平台进行上线,一般在进行设备初始化、上线时是必须调用,会返回设备唯一标识ID
int deviceId = deviceLogin(PRODUCT_ID, mac);
//示例二:发布物属性,引起平台的最新的物属性变化
publishAttribute(deviceId);
//示例三:发布事件
publishEvent(deviceId);
//示例四:监听服务端的属性设置请求,并应答服务端
setAttributeCallback();
//示例五:监听服务端的属性获取请求,并应答服务端
getAttributeCallback();
//示例六:监听服务端的服务调用下发,并应答服务端
serviceInvokeCallback();
//示例七:设备离线
xlinkMqttClient.deviceOffline(deviceId);
//示例八:SDK与云端断开并重连时,回调方法设置
xlinkMqttClient.setReconnectHandler(() -> {
//这里一般可以会处理设备的重新上线操作。
});
}
/**
* 初始化Xagent 客户端
*/
private static void init() throws Exception {
//构造器配置
xlinkMqttClient = XlinkMqttBuilderParams.builder()
.certId(CERT_ID) //配置授权证书ID
.certKey(CERT_KEY) //配置授权证书密钥
.endpoint(DEVICE_ENDPOINT)//云端CM服务器地址
.connectorType(CONNECTOR_TYPE)//配置连接器类型
.addSubscribeServiceName(PRODUCT_ID, "open_door", "close_door")//订阅物模型服务处理
.build(); //构造XlinkMqttBuilderParams实例
//建立连接及认证
xlinkMqttClient.start();
}
/**
* 示例一:在平台进行上线,一般在进行设备初始化时,必须调用
*
* @param productId
* @param mac
*/
private static int deviceLogin(String productId, String mac) throws ExecutionException, InterruptedException {
//在平台登录上线,并得到返回
DeviceLoginResultMessage deviceLoginResultMessage = xlinkMqttClient.deviceLogin(productId, mac).get();
//得到返回结果
if (deviceLoginResultMessage.getRetCode() == DeviceLoginRetCodeType.SUCCESS) {
//上线成功,得到平台唯一的设备ID、在物模型下,可以当做thing id使用
int deviceId = deviceLoginResultMessage.getDeviceId();
//建议将设备ID在内存保存起来,在后续的操作,会经常使用到。
//自定义代码..
return deviceId;
} else {
//上线失败,从RetCode读取错误信息及类型
DeviceLoginRetCodeType retCode = deviceLoginResultMessage.getRetCode();
//自定义代码..
return 0;
}
}
/**
* 示例二:发布物属性,引起平台的最新的物属性变化
*
* @param deviceId 设备上线后得到的设备ID
* @throws Exception
*/
private static void publishAttribute(int deviceId) throws Exception {
//物模型的版本号
int version = 0;
xlinkMqttClient.publishAttribute(deviceId, version,
new HashMap() {{
put("state", "open"); //属性字段
put("color", "red");//属性字段
}}, new Date());
}
/**
* 示例三:发布事件
*
* @param deviceId 设备上线后得到的设备ID
*/
private static void publishEvent(int deviceId) throws Exception {
//设备上线后得到的设备ID
//物模型的版本号
int version = 0;
//物模型中的事件名
String eventName = "xxx";
xlinkMqttClient.publishEvent(deviceId, version, eventName,
new HashMap() {{
put("state", "open"); //事件字段
put("color", "red");//事件字段
}}, new Date());
}
/**
* 示例四:监听服务端的属性设置请求,并应答服务端
*/
private static void setAttributeCallback() {
//监听服务端属性设置回调方法,注意:多个设备ID的属性设置回调方法实现可以为同一个
xlinkMqttClient.setSetAttributeHandler(request -> {
//服务端设置下发的属性信息
Map<String, Object> attribute = request.getAttributes();
//服务端设置下发的设备ID
int setDeviceId = request.getDeviceId();
//自定义代码
//构建应答包错误码
String code = "200";
//构建应答包
SetAttributeResponse response = new SetAttributeResponse(code);
//通过方法返回值进行应答,如方法返回值null,则不会应答。
return response;
});
}
/**
* 示例五:监听服务端的属性获取请求,并应答服务端
*
*/
private static void getAttributeCallback() {
//监听服务端属性获取回调方法,注意:多个设备ID的属性获取回调方法实现可以为同一个
xlinkMqttClient.setGetAttributeHandler(reqeust -> {
//得到服务端属性获取的设备ID
int getDeviceId = reqeust.getDeviceId();
//自定义代码
//构建应答的信息属性
Map<String, Object> attributes = new HashMap() {{
put("f1", 1);
put("f2", "str..");
}};
//构建应答包错误码
String code = "200";
//构建应答包
GetAttributeResponse response = new GetAttributeResponse(code, attributes);
//通过方法返回值进行应答,如方法返回值为null,则不会应答
return response;
});
}
/**
* 示例六:监听服务端的服务调用下发,并应答服务端
*/
private static void serviceInvokeCallback() {
//物模型中的服务名
//监听服务端服务调用的回调方法,注意:多个设备ID、多个不同服务的服务调用回调方法实现可以为同一个。
xlinkMqttClient.setServiceInvokeHandler(request -> {
//得到服务调用的设备ID
int invokeDeviceId = request.getDeviceId();
//得到服务调用的服务名
String invokeServiceName = request.getServiceName();
//得到服务调用的输入参数
Map<String, Object> input = request.getInput();
//自定义代码
switch (invokeServiceName) {
case "open_door": {
//...
break;
}
case "close_door": {
//...
break;
}
}
//构建应答包错误码
String code = "200";
//构建应答包输出参数
Map<String, Object> output = new HashMap() {{
put("f1", 4);
put("f2", "str");
}};
//构建应答包
ServiceInvokeResponse serviceInvokeResponse = new ServiceInvokeResponse(code, output);
//通过方法返回值进行应答,如方法返回值为null,则不会应答
return serviceInvokeResponse;
});
}
}
四、注意事项
4.1 SDK异常处理
在使用sdk的各种api过程中,有可能会抛出各种XlinkIotException,需要使用者进行捕捉和处理。
- 上报缺少参数异常:XlinkIotPublishLackException类,可以通过getFieldName()方法获取具体缺少参数的是哪一个字段。
- 客户端认证失败异常:XlinkNotAuthException类,表示客户端的连接是不合法的。
- 服务端不可用异常:XlinkIotServiceException类,表示服务端不存在,或者服务端没有回应。
4.2 断线重连
在Xagent重启时,会与云端断开,此时原先在Xagent上线的失败会因重启导致离线,在每次Xagent重启时,需要重新将设备进行上线。
4.3 Xagent多机部署问题
在云端服务器当前的机制下,多个Xagent同时上线同一个设备时会导致互踢,因此,在Xagent进行多机部署时,需让每个Xagent负责上线的设备相互隔离,或者采集简单的主备模式部署。
五、SDK & Demo下载
资源名称 | 下载地址 |
---|---|
XAgent SDK | 点此下载 |
XAgent DEMO | 点此下载 |
六、更新日志
日期 | 版本号 | 编写人 | 更新内容 |
---|---|---|---|
2019/08/22 | 1.0 | 沈伟然 | 文档创建 |
2019/08/27 | 1.1 | 沈伟然 | 完成初稿 |
2019/08/29 | 1.2 | 沈伟然 | 初始化参数重复Connector Type |
2019/09/05 | 1.3 | 沈伟然 | 更新SDK 3.5.1,更新内容:支持调试日志显示,见【初始化客户端配置】,默认不开启支持自定义上报调试日志 |
2019/09/18 | 1.4 | 沈伟然 | 更新SDK 3.5.2,内容:支持设备离线 |
2019/10/23 | 1.5 | 沈伟然 | 更新SDK3.5.3,内容:当Xagent SDK与云端断开并成功重连时,提供回调方法供告知SDK使用者 |
2019/10/24 | 1.6 | 沈伟然 | 更新SDK3.5.4,内容:支持新的设备登录返回错误码(新增的自动注册设备特性) |
2019/11/11 | 1.7 | 沈伟然 | 补充jar文件 |