本文介绍如何进行 SDK 初始化,建立设备与云端的连接。

设备认证

Java SDK目前只支持设备证书方式对设备进行身份认证,也即使用ProductKey、DeviceName、DeviceSecret来认证设备。也支持动态注册的预注册方式来动态获取DeviceSecret,但Java SDK目前只支持在物联网平台的华东2站点进行动态注册

若使用动态注册,那么开发者需要先使用动态注册获取设备的DeviceSecret,将其持久化存在本地后再连接物联网平台。若设备已通过动态注册获取到了设备的DeviceSecret,那么设备重启不能再执行动态注册,而是从持久化存储中获取三元组,然后执行初始化建联。

动态注册

下面是动态注册的代码说明:LinkKitInitParams 初始化参数。

//  #######  一型一密动态注册接口开始 ######
/**
 * 注意:动态注册成功,设备上线之后,不能再次执行动态注册,云端会返回已注册。
 */
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = "xx"; //必填
deviceInfo.deviceName = "xx"; //必填
deviceInfo.productSecret = "xx"; //必填

LinkKitInitParams params = new LinkKitInitParams();
IoTMqttClientConfig config = new IoTMqttClientConfig();
config.productKey = deviceInfo.productKey;
config.deviceName = deviceInfo.deviceName;

params.mqttClientConfig = config;
params.deviceInfo = deviceInfo;

final CommonRequest request = new CommonRequest();
request.setPath("/auth/register/device");
LinkKit.getInstance().deviceRegister(params, request, new IoTCallback() {
    public void onFailure(CommonRequest commonRequest, Exception e) {
        ALog.e(TAG, "动态注册失败 " + e);
    }

    public void onResponse(CommonRequest commonRequest, CommonResponse commonResponse) {
        if (commonResponse == null || StringUtils.isEmptyString(commonResponse.getData())) {
            ALog.e(TAG, "动态注册失败 response=null");
            return;
        }
        try {
            ResponseModel<Map<String, String>> response = new Gson().fromJson(commonResponse.getData(), new TypeToken<ResponseModel<Map<String, String>>>() {
            }.getType());
            if (response != null && "200".equals(response.code)) {
                ALog.d(TAG, "动态注册成功" + (commonResponse == null ? "" : commonResponse.getData()));
                /**  获取 deviceSecret, 存储到本地,然后执行初始化建联
                 * 这个流程只能走一次,获取到 secret 之后,下次启动需要读取本地存储的三元组,
                 * 直接执行初始化建联,不可以再走动态初始化
                 */
                // deviceSecret = response.data.get("deviceSecret");
                // init(pk,dn,ds);
                return;
            }
        } catch (Exception e) {

        }
        ALog.d(TAG, "动态注册失败" + commonResponse.getData());
    }
});
//  ####### 一型一密动态注册接口结束  ######
            

SDK 初始化

SDK初始化,即使用设备的证书连接物联网平台。设备如果初始化失败,比如网络不通导致连接失败,根据业务场景开发者可以选择是否再次进行初始化连接物联网平台,SDK此时不会自动尝试连接物联网平台;若SDK初始化成功之后,设备与云端的连接异常断开,那么SDK将负责自动重新连接物联网平台。onInitDone表示初始化成功,onError表示初始化失败。

设备可以接入物联网平台的公共实例或者企业实例,SDK初始化时需要根据实例类型来指定设备连接的域名:
  • 公共实例

    公共实例的域名类似:{productKey}.iot-as-mqtt.RegionID.aliyuncs.com",其中的RegionID即代表相应的站点,其取值可以从“地域和可用区”中查看,需要注意的是物联网平台这个服务并不是所有的阿里云地域都进行了部署,因此这里填入的RegionID一定要和产品创建的地域相同,比如“华东2(上海)”的RegionID是cn-shanghai,假设产品的productKey是abc,那么最终的域名为:abc.iot-as-mqtt.cn-shanghai.aliyuncs.com。SDK中的默认域名为华东2,若设备接入阿里云华东2站点,那么可以不用指定域名。

  • 企业实例
    用户需要在企业实例中查看实例的接入URL,请参见文档“实例管理”中的“查看实例终端节点”章节了解如何查看实例详情,其中MQTT接入的域名如下图所示,用户无需在域名前添加productKey:mqtt_url

下面的代码演示设备接入华东2站点时SDK初始化的代码:

LinkKitInitParams params = new LinkKitInitParams();
/**
 * 设置 Mqtt 初始化参数
 */
IoTMqttClientConfig config = new IoTMqttClientConfig();
config.productKey = pk;
config.deviceName = dn;
config.deviceSecret = ds;
/*
 *是否接受离线消息
 *对应 mqtt 的 cleanSession 字段
 */
config.receiveOfflineMsg = false;
params.mqttClientConfig = config;
/**
 *设置初始化三元组信息,用户传入
 */
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = pk;
deviceInfo.deviceName = dn;
deviceInfo.deviceSecret = ds;
params.deviceInfo = deviceInfo;

/**
 * 设置设备当前的初始状态值,属性需要和云端创建的物模型属性一致
 *如果这里什么属性都不填,物模型就没有当前设备相关属性的初始值。
 *用户调用物模型上报接口之后,物模型会有相关数据缓存。
*/
Map propertyValues = new HashMap(); // 示例// propertyValues.put(“LightSwitch”, new ValueWrapper.BooleanValueWrapper(0));params.propertyValues = propertyValues;
LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
    public void onError(AError aError) {
        ALog.e(TAG, “Init Error error = ”+aError);
    }

    public void onInitDone(InitResult initResult) {
        ALog.i(TAG, "onInitDone result=" + initResult);
    }
});
            
若设备连接的不是华东2站点的公共实例,而是连接企业实例或者其它站点的公共实例,那么需要对连接的实例的域名进行设置:
// 设置 Mqtt 请求域名 LinkKitInitParams 初始化参数
IoTMqttClientConfig clientConfig = new IoTMqttClientConfig();
clientConfig.channelHost = "xxx";
linkKitInitParams.mqttClientConfig = clientConfig;
            

SDK 反初始化

如果需要注销初始化,调用如下接口。

// 取消注册 notifyListener,notifyListener对象需和注册的时候是同一个对象
LinkKit.getInstance().unRegisterOnNotifyListener(notifyListener);
LinkKit.getInstance().deinit();

其他设置

日志开关

打开SDK内部日志输出开关:

ALog.setLevel(ALog.LEVEL_DEBUG);
            

连接状态监听

如果需要监听设备的上下线信息,云端下发的所有数据,可以设置以下监听器。

IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
    @Override
    public void onNotify(String connectId, String topic, AMessage aMessage) {
        // 云端下行数据回调
        // connectId 连接类型 topic 下行 topic; aMessage 下行数据
        //String pushData = new String((byte[]) aMessage.data);
        // pushData 示例  {"method":"thing.service.test_service","id":"123374967","params":{"vv":60},"version":"1.0.0"}
        // method 服务类型; params 下推数据内容    
}

    @Override
    public boolean shouldHandle(String connectId, String topic) {
        // 选择是否不处理某个 topic 的下行数据
        // 如果不处理某个topic,则onNotify不会收到对应topic的下行数据
        return true; //TODO 根基实际情况设置
    }

    @Override
    public void onConnectStateChange(String connectId, ConnectState connectState) {
        // 对应连接类型的连接状态变化回调,具体连接状态参考 SDK ConnectState
    }
}
// 注册下行监听,包括长连接的状态和云端下行的数据
LinkKit.getInstance().registerOnNotifyListener(notifyListener);
            
  • 设置Mqtt Keep-Alive 时间
interval 单位秒 MqttConfigure.setKeepAliveInterval(int interval);
- qos设置
MqttPublishRequest request = new MqttPublishRequest();
// 支持 0 和 1, 默认0
request.qos = 0;
request.isRPC = false;
request.topic = topic.replace("request", "response");
String resId = topic.substring(topic.indexOf("rrpc/request/")+13);
request.msgId = resId;
// TODO 用户根据实际情况填写 仅做参考
request.payloadObj = "{\"id\":\"" + resId + "\", \"code\":\"200\"" + ",\"data\":{} }";
  • cleanSession 设置

/**
 * 设置 Mqtt 初始化参数
 */
IoTMqttClientConfig config = new IoTMqttClientConfig();
config.productKey = deviceInfoData.productKey;
config.deviceName = deviceInfoData.deviceName;
config.deviceSecret = deviceInfoData.deviceSecret;
config.channelHost = pk + ".iot-as-mqtt." + deviceInfoData.region + ".aliyuncs.com:1883";
/**
 * 是否接受离线消息
 * 对应 receiveOfflineMsg = !cleanSession, 默认不接受离线消息
 */
config.receiveOfflineMsg = false;
params.mqttClientConfig = config;