阿里云物联网平台网关子设备接入JAVA Sample

简介: 子设备不直接连接物联网平台,而是通过网关接入物联网平台。首先,需在物联网平台上创建网关和子设备;然后,开发网关设备端SDK,实现网关直连物联网平台;再由网关向物联网平台上报网关与子设备的拓扑关系;通过网关上报子设备证书(一机一密方式)或者子设备动态注册的认证方式,物联网平台校验子设备的身份和该子设备与网关的拓扑关系。

概述

子设备不直接连接物联网平台,而是通过网关接入物联网平台。首先,需在物联网平台上创建网关和子设备;然后,开发网关设备端SDK,实现网关直连物联网平台;再由网关向物联网平台上报网关与子设备的拓扑关系;通过网关上报子设备证书(一机一密方式)或者子设备动态注册的认证方式,物联网平台校验子设备的身份和该子设备与网关的拓扑关系。所有校验通过,才会建立子设备逻辑通道,并绑定至网关物理通道上,实现子设备通过网关,与物联网平台建立连接,并进行通信。本文主要如何演示使用JAVA SDK实现相关过程。

关系图

_

操作步骤

1、创建网关和子设备,参考链接

2、子设备产品的物模型定义:
_

2、pom.xml

 <repositories>
        <repository>
            <id>alimaven</id>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>com.aliyun.alink.linksdk</groupId>
            <artifactId>iot-linkkit-java</artifactId>
            <version>1.2.0.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.40</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    
    <build>
        <finalName>iot-java-sdk</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

3、Code Sample

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.alink.dm.api.BaseInfo;
import com.aliyun.alink.dm.api.DeviceInfo;
import com.aliyun.alink.dm.api.InitResult;
import com.aliyun.alink.dm.api.SignUtils;
import com.aliyun.alink.dm.model.ResponseModel;
import com.aliyun.alink.linkkit.api.ILinkKitConnectListener;
import com.aliyun.alink.linkkit.api.IoTMqttClientConfig;
import com.aliyun.alink.linkkit.api.LinkKit;
import com.aliyun.alink.linkkit.api.LinkKitInitParams;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceActionListener;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceChannel;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceConnectListener;
import com.aliyun.alink.linksdk.cmp.connect.channel.MqttPublishRequest;
import com.aliyun.alink.linksdk.cmp.connect.channel.MqttSubscribeRequest;
import com.aliyun.alink.linksdk.cmp.core.base.AMessage;
import com.aliyun.alink.linksdk.cmp.core.base.ARequest;
import com.aliyun.alink.linksdk.cmp.core.base.AResponse;
import com.aliyun.alink.linksdk.cmp.core.base.ConnectState;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectNotifyListener;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSendListener;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSubscribeListener;
import com.aliyun.alink.linksdk.tools.AError;
import com.aliyun.alink.linksdk.tools.ALog;

import java.util.*;

import static com.aliyun.alink.linksdk.tools.ALog.LEVEL_DEBUG;

// 子设备测试
public class SubDeviceDemo {

    // 初始化参数
    private static String regionId = "cn-shanghai";
    private static final String TAG = "TOPO";

    //网关设备三元组信息
    private static String GWproductKey = "********";
    private static String GWdeviceName = "********";
    private static String GWdeviceSecret = "********";

    public static void main(String[] args) {

        LinkKitInitParams params = new LinkKitInitParams();
        /**
         * 设置 Mqtt 初始化参数
         */
        IoTMqttClientConfig config = new IoTMqttClientConfig();
        config.productKey = GWproductKey;
        config.deviceName = GWdeviceName;
        config.deviceSecret = GWdeviceSecret;
        config.channelHost = GWproductKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";
        /**
         * 是否接受离线消息
         * 对应 mqtt 的 cleanSession 字段
         */
        config.receiveOfflineMsg = false;
        params.mqttClientConfig = config;
        ALog.setLevel(LEVEL_DEBUG); // 设置日志打印级别
        ALog.i(TAG, "mqtt connetcion info=" + params);

        /**
         * 设置初始化,传入设备证书信息
         */
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.productKey = GWproductKey;
        deviceInfo.deviceName = GWdeviceName;
        deviceInfo.deviceSecret = GWdeviceSecret;
        params.deviceInfo = deviceInfo;

        /**建立链接**/
        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);

                //获取网关下topo关系,查询网关与子设备是否已经存在topo关系
                //如果已经存在,则直接上线子设备,不存在则需要添加网关子设备
                LinkKit.getInstance().getGateway().gatewayGetSubDevices(new IConnectSendListener() {
                    @Override
                    public void onResponse(ARequest request, AResponse aResponse) {
                        ALog.i(TAG, "获取网关的topo关系成功 : " + JSONObject.toJSONString(aResponse));

                        // 1、获取子设备列表结果
                        try {
                            ResponseModel<List<DeviceInfo>> response = JSONObject.parseObject(aResponse.data.toString(), new TypeReference<ResponseModel<List<DeviceInfo>>>() {
                            }.getType());
                            // TODO 根据实际应用场景处理
                            Integer subDeviceCounts = response.data.size();
                            System.out.println("topo下子设备的数目:" + subDeviceCounts);// topo网管下子设备的数目

//                            // 2、如果topo下面的子设备数目为0,则通过动态注册获取子设备Secret信息
//                            if (subDeviceCounts == 0)
//                            {
//                                /**
//                                 * 子设备动态注册获取设备deviceSecret,如果设备已知三元组则忽略此步
//                                 * 预注册设备时,可以使用设备的MAC地址或SN序列号等作为DeviceName
//                                 */
//                                List<BaseInfo> subDevices = new ArrayList<>();
//                                BaseInfo baseInfo1 = new BaseInfo();
//                                // 未激活的子设备的信息
//                                baseInfo1.productKey = "********";
//                                baseInfo1.deviceName = "********";
//                                subDevices.add(baseInfo1);
//
//                                LinkKit.getInstance().getGateway().gatewaySubDevicRegister(subDevices, new IConnectSendListener() {
//
//                                    @Override
//                                    public void onResponse(ARequest request, AResponse response) {
//                                        ALog.i(TAG, "子设备动态注册成功 : " + JSONObject.toJSONString(response));
//
//                                        // 通过动态注册获取的子设备信息,供后续添加子设备到网关设备使用
//                                        //{\"iotId\":\"********\",\"deviceSecret\":\"********\",\"productKey\":\"********\",\"deviceName\":\"********\"}
//                                    }
//                                    @Override
//                                    public void onFailure(ARequest request, AError error) {
//                                        ALog.i(TAG, "子设备注册失败 : " + JSONObject.toJSONString(error));
//                                    }
//                                });
//                            }

                            // 3、使用子设备动态注册获取完子设备三元组信息后,添加到网关设备
                            List<BaseInfo> subDevices = new ArrayList<>();
                            BaseInfo baseInfo2 = new BaseInfo();
                            // 未激活的子设备三元组信息,可以通过上面的注释代码获取
                            baseInfo2.productKey = "********";
                            baseInfo2.deviceName = "********";
                            String deviceSecret = "********";
                            subDevices.add(baseInfo2);
                            LinkKit.getInstance().getGateway().gatewayAddSubDevice(baseInfo2, new ISubDeviceConnectListener() {
                                @Override
                                public String getSignMethod() {
                                    // 使用的签名方法
                                    return "hmacsha1";
                                }

                                @Override
                                public String getSignValue() {
                                    // 获取签名,用户使用 deviceSecret 获得签名结果
                                    Map<String, String> signMap = new HashMap<>();
                                    signMap.put("productKey", baseInfo2.productKey);
                                    signMap.put("deviceName", baseInfo2.deviceName);
                                    // signMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
                                    signMap.put("clientId", getClientId());
                                    return SignUtils.hmacSign(signMap, deviceSecret);
                                }

                                @Override
                                public String getClientId() {
                                    // clientId 可为任意值
                                    return "id";
                                }

                                @Override
                                public Map<String, Object> getSignExtraData() {
                                    return null;
                                }

                                @Override
                                public void onConnectResult(boolean isSuccess, ISubDeviceChannel iSubDeviceChannel, AError aError) {

                                    // 添加结果
                                    if (isSuccess) {
                                        // 子设备添加成功,接下来可以做子设备上线的逻辑
                                        ALog.i(TAG, "topo关系添加成功 : " + JSONObject.toJSONString(iSubDeviceChannel));

                                        // 子设备添加成功后,代理子设备上线
                                        LinkKit.getInstance().getGateway().gatewaySubDeviceLogin(baseInfo2, new ISubDeviceActionListener() {
                                            @Override
                                            public void onSuccess() {
                                                System.out.println("代理子设备上线成功!");

                                                // 基本信息设置
                                                System.out.println("使用网关的通道执行子设备的数据上下行");
                                                String topic = "/******/******/user/datapubandsub"; // 子设备自定义Topic
                                                String sysSubTopic = "/sys/******/******/thing/event/property/post";// 子设备系统属性设置Topic
                                                String payLoad = "{\"id\":\"123\",\"method\":\"thing.event.property.post\",\"params\":{\"RoomHumidity\":19},\"version\":\"1.0\"}"; //注意此处和第二步子设备物模型定义相关

                                                // 发布系统消息测试
                                                MqttPublishRequest request1 = new MqttPublishRequest();
//                                              // topic 用户根据实际场景填写
                                                request1.topic = sysSubTopic;
                                                request1.payloadObj = payLoad;

                                                LinkKit.getInstance().publish(request1, new IConnectSendListener(){
                                                    @Override
                                                    public void onResponse(ARequest aRequest, AResponse aResponse) {

                                                        System.out.println("发送成功");
                                                    }

                                                    @Override
                                                    public void onFailure(ARequest aRequest, AError aError) {
                                                        System.out.println("发送失败");

                                                    }
                                                });

                                                // 订阅
                                                MqttSubscribeRequest request = new MqttSubscribeRequest();
                                                // topic 用户根据实际场景填写
                                                request.topic = topic;
                                                request.isSubscribe = true;

                                                // 直接做Topic的订阅,注意自定义Topic需要使用这种方式,否则会出现订阅失败的情况,SDK有Bug,系统Topic没有问题
                                                LinkKit.getInstance().subscribe(request, new IConnectSubscribeListener(){
                                                    @Override
                                                    public void onSuccess() {
                                                        System.out.println("直接订阅成功");
                                                    }

                                                    @Override
                                                    public void onFailure(AError aError) {
                                                        System.out.println("直接订阅失败" + aError.getMsg());

                                                    }
                                                });

                                                // 注册下行监听
                                                LinkKit.getInstance().registerOnNotifyListener(new IConnectNotifyListener() {
                                                    @Override
                                                    public void onNotify(String s, String s1, AMessage aMessage) {
                                                        System.out.println("下行消息Topic:" + s);
                                                        System.out.println("下行消息:" + new String((byte[])aMessage.getData()));
                                                    }
                                                    @Override
                                                    public boolean shouldHandle(String s, String s1) {
                                                        return false;
                                                    }

                                                    @Override
                                                    public void onConnectStateChange(String s, ConnectState connectState) {
                                                        System.out.println("连接状态发生变化 :" + s + connectState);
                                                    }
                                                });
                                                System.out.println("---取消订阅---");
                                                // 取消订阅  参考订阅方法  request.isSubscribe = false; 即可
                                            }

                                            @Override
                                            public void onFailed(AError aError) {
                                                ALog.d(TAG, "onFailed() called with: aError = [" + aError + "]");
                                                System.out.println(aError.getMsg());
                                            }
                                        });
                                    } else {
                                        ALog.i(TAG, "topo关系添加失败 : " + JSONObject.toJSONString(aError));
                                    }
                                }

                                @Override
                                public void onDataPush(String s, AMessage aMessage) {
                                }
                            });
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(ARequest request, AError error) {
                        ALog.i(TAG, "获取网关的topo关系失败 : " + JSONObject.toJSONString(error));
                    }
                });
            }
        });
    }
}

说明

1、首先初始化网关设备,建立连接;
2、检查当前网关设备拓扑关系,获取现有子设备信息,示例演示网关设备尚未添加子设备;
3、动态注册获取网关子设备DeviceSecret,本部分注释,第一次运行需要取消注释;
4、添加子设备三元组信息到网关设备;
5、网关代理子设备进行Topic的订阅、消息的发布及下行监听注册。

注意

替换网关设备三元组信息、子设备三元组信息、子设备Topic信息。

4、运行结果

_

更多参考

设备安全认证
网关接入物联网平台
子设备接入物联网平台

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
存储 运维 监控
物联网平台常见类别及对应平台(一)
物联网平台常见类别及对应平台(一)
951 0
|
7月前
|
消息中间件 DataWorks 物联网
MQTT问题之接入阿里云物联网平台如何解决
MQTT接入是指将设备或应用通过MQTT协议接入到消息服务器,以实现数据的发布和订阅;本合集着眼于MQTT接入的流程、配置指导以及常见接入问题的解决方法,帮助用户实现稳定可靠的消息交换。
447 1
|
2月前
|
存储 边缘计算 物联网
阿里云物联网平台:推动万物互联的智能化解决方案
随着物联网技术的快速发展,阿里云物联网平台为企业提供了一体化的解决方案,包括设备接入、数据管理和智能应用等核心功能。平台支持海量设备接入、实时数据采集与存储、边缘计算,并具备大规模设备管理、高安全性和开放生态等优势。广泛应用于智能制造、智慧城市和智能家居等领域,助力企业实现数字化转型。
263 5
|
5月前
|
存储 运维 监控
阿里云物联网平台的优势
【7月更文挑战第19天】阿里云物联网平台的优势
89 1
|
7月前
|
消息中间件 存储 JavaScript
阿里云IOC物联网异步处理基础概念
该内容介绍了异步处理基础和消息队列的相关概念。首先,同步处理指任务完成后才能执行其他操作,而异步则允许任务并行执行,不阻塞程序。异步能提高系统并发性和响应性,但也增加复杂性和资源消耗。接着,提到了消息队列,包括生产者、消费者、队列、broker和topic等概念,并指出在IoT中,设备作为生产者发送消息到特定topic,消费者从队列获取数据。最后,简要介绍了AMQP协议,它是用于应用程序间消息传递的开放标准,常用于分布式系统和物联网,如RabbitMQ和Apache Qpid。课程将以Apache Qpid为例接收IoT数据。
237 6
阿里云IOC物联网异步处理基础概念
|
7月前
|
Cloud Native 安全 物联网
【阿里云云原生专栏】云边端一体化:阿里云如何利用云原生技术赋能物联网
【5月更文挑战第22天】阿里云借助云原生技术赋能物联网,实现云边端一体化,提升系统弹性与敏捷性。通过容器化部署,保证高可用性与可靠性。在智能交通等领域,阿里云提供高效解决方案,实现实时数据分析与决策。代码示例展示如何使用阿里云服务处理物联网数据。同时,阿里云重视数据安全,采用加密和访问控制保障数据隐私。丰富的工具和服务支持开发者构建物联网应用,推动技术广泛应用与发展。
403 1
|
存储 机器学习/深度学习 监控
物联网平台常见类别及对应平台(二)
物联网平台常见类别及对应平台(二)
369 0
|
7月前
|
存储 安全 物联网
安防摄像头IPC如何快速接入阿里云Link Visual视频服务(阿里云生活物联网)
Link Visual是生活物联网平台针对视频产品推出的增值服务,提供视频数据上云、存储、转发、AI计算等能力。 大白话就是:通过阿里云的Link Visual视频服务,可以让你的IPC摄像头设备完成上云功能,并快速实现如下功能介绍中的功能。其中可以享受阿里云P2P协议支持,帮助企业节省流量服务器流量带宽。
728 7
|
7月前
|
消息中间件 网络协议 物联网
MQTT协议问题之阿里云物联网服务器断开如何解决
MQTT协议是一个轻量级的消息传输协议,设计用于物联网(IoT)环境中设备间的通信;本合集将详细阐述MQTT协议的基本原理、特性以及各种实际应用场景,供用户学习和参考。
514 1
|
消息中间件 物联网 Java
[笔记]阿里云物联网之业务服务端(java、php)接入阿里云平台(一)
[笔记]阿里云物联网之业务服务端(java、php)接入阿里云平台
380 1

热门文章

最新文章

相关产品

  • 物联网平台