基于开源MQTT自主接入阿里云IoT平台(Java)

简介:

本文由 GXIC 作者 wongxmig 完成,欢迎关注 IoT 开发者社区

1. 准备工作

1.1 注册阿里云账号

使用个人淘宝账号或手机号,开通阿里云账号,并通过__实名认证(可以用支付宝认证)__

1.2 免费开通IoT物联网套件

产品官网 https://www.aliyun.com/product/iot

Screen Shot 2018-06-01 at 13.53.55.png | center | 569x357

1.3 软件环境

JDK安装
编辑器 IDEA

2. 开发步骤

2.1 云端开发

1) 创建高级版产品

image.png | left | 747x253

2) 功能定义,产品物模型添加属性

添加产品属性定义

属性名 标识符 数据类型 范围
温度 temperature float -50~100
湿度 humidity float 0~100

image.png | left | 747x186

物模型对应属性上报topic

/sys/替换为productKey/替换为deviceName/thing/event/property/post

物模型对应的属性上报payload

{
    id: 123452452,
    params: {
        temperature: 26.2,
        humidity: 60.4
    },
    method: "thing.event.property.post"
}

3) 设备管理>注册设备,获得身份三元组

image.png | left | 747x188

2.2 设备端开发

我们以java程序来模拟设备,建立连接,上报数据。

1) pom.xml添加sdk依赖

<dependencies>
        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        
</dependencies>

2) AliyunIoTSignUtil工具类


import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Map;

/**
 * AliyunIoTSignUtil
 */

public class AliyunIoTSignUtil {
    public static String sign(Map<String, String> params, String deviceSecret, String signMethod) {
        //将参数Key按字典顺序排序
        String[] sortedKeys = params.keySet().toArray(new String[] {});
        Arrays.sort(sortedKeys);

        //生成规范化请求字符串
        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (String key : sortedKeys) {
            if ("sign".equalsIgnoreCase(key)) {
                continue;
            }
            canonicalizedQueryString.append(key).append(params.get(key));
        }

        try {
            String key = deviceSecret;
            return encryptHMAC(signMethod,canonicalizedQueryString.toString(), key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * HMACSHA1加密
     *
     */
    public static String encryptHMAC(String signMethod,String content, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), signMethod);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        byte[] data = mac.doFinal(content.getBytes("utf-8"));
        return bytesToHexString(data);
    }

    public static final String bytesToHexString(byte[] bArray) {

        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

}

3) 模拟设备IoTDemo.java代码

public class IoTDemo {

    public static String productKey = "替换productKey";
    public static String deviceName = "替换deviceName";
    public static String deviceSecret = "替换deviceSecret";
    public static String regionId = "cn-shanghai";

    //物模型-属性上报topic
    private static String pubTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post";
    //高级版 物模型-属性上报payload
    private static final String payloadJson =
            "{" +
            "    \"id\": %s," +
            "    \"params\": {" +
            "        \"temperature\": %s," +
            "        \"humidity\": %s" +
            "    }," +
            "    \"method\": \"thing.event.property.post\"" +
            "}";

    private static MqttClient mqttClient;
    private static Random random = new Random();
    private static DecimalFormat df = new DecimalFormat("0.#");

    public static void main(String [] args) {

        initAliyunIoTClient();

        ScheduledExecutorService scheduledThreadPool = new ScheduledThreadPoolExecutor(1,
                new ThreadFactoryBuilder().setNameFormat("thread-runner-%d").build());

        scheduledThreadPool.scheduleAtFixedRate(()->postDeviceProperties(), 10,10, TimeUnit.SECONDS);

    }

    private static void initAliyunIoTClient() {

        try {
            String clientId = "java" + System.currentTimeMillis();

            Map<String, String> params = new HashMap<>(16);
            params.put("productKey", productKey);
            params.put("deviceName", deviceName);
            params.put("clientId", clientId);
            String timestamp = String.valueOf(System.currentTimeMillis());
            params.put("timestamp", timestamp);

            // cn-shanghai
            String targetServer = "tcp://" + productKey + ".iot-as-mqtt."+regionId+".aliyuncs.com:1883";

            String mqttclientId = clientId + "|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|";
            String mqttUsername = deviceName + "&" + productKey;
            String mqttPassword = AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");

            connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword);

        } catch (Exception e) {
            System.out.println("initAliyunIoTClient error " + e.getMessage());
        }
    }

    public static void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception {

        MemoryPersistence persistence = new MemoryPersistence();
        mqttClient = new MqttClient(url, clientId, persistence);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // MQTT 3.1.1
        connOpts.setMqttVersion(4);
        connOpts.setAutomaticReconnect(false);
        connOpts.setCleanSession(true);

        connOpts.setUserName(mqttUsername);
        connOpts.setPassword(mqttPassword.toCharArray());
        connOpts.setKeepAliveInterval(60);

        mqttClient.connect(connOpts);

    }


    private static void postDeviceProperties() {

        try {

            //上报数据
            String payload = String.format(payloadJson, System.currentTimeMillis(), df.format(25+random.nextFloat()*10), df.format(50+random.nextFloat()*30));

            System.out.println("post :"+payload);

            MqttMessage message = new MqttMessage(payload.getBytes("utf-8"));
            message.setQos(1);

            mqttClient.publish(pubTopic, message);

        } catch (Exception e) {

        }

    }


}

3. 启动运行

3.1 设备启动

Run IoTDemo.main

3.2 云端查看设备运行状态

image.png | left | 602x225

4. 项目源码

download: therometer.zip

download: aliyun-iot-demo-java.zip


<a class="anchor" id="" href="#80ifpi"></a>


相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
3月前
|
设计模式 敏捷开发 Java
全网首发!Java界的四大名著之一:Java编程思想最新中文版已开源
老版《Java编程思想》(原书名《Thinking in Java》)得益作者开放深度研讨的创作方式,受到了全世界读者的追捧,被译为了十几种语言。但遗憾的是,在经历了 4 个版本的更新后,其最后一版发布于 2007 年,之后再无更新。
|
2月前
|
Java 关系型数据库 应用服务中间件
阿里云RDS购买Linux完整过程——安装java环境并跑起来tomcat
阿里云RDS购买Linux完整过程——安装java环境并跑起来tomcat
45 0
|
1月前
|
弹性计算 前端开发 小程序
微信小程序上传文件至阿里云OSS直传(java后端签名+前端直传)
当前的通用文件上传方式是通过前端上传到服务器,再由服务器转存至对象存储。这种方式在处理小文件时效率尚可,但大文件上传因受限于服务器带宽,速度较慢。例如,一个100MB的文件在5Mbps带宽的阿里云ECS上上传至服务器需160秒。为解决此问题,可以采用后端签名的方式,使微信小程序直接上传文件到阿里云OSS,绕过服务器中转。具体操作包括在JAVA后端引入相关依赖,生成签名,并在微信小程序前端使用这个签名进行文件上传,注意设置正确的请求头和formData参数。这样能提高大文件上传的速度。
|
2月前
|
监控 Java 测试技术
阿里云推出 3.x Java 探针,解锁应用观测与治理的全新姿势
阿里云推出 3.x Java 探针,解锁应用观测与治理的全新姿势
174249 6
|
3月前
|
人工智能 自然语言处理 开发者
书生·浦语2.0开源,阿里云魔搭首发
书生·浦语2.0开源,阿里云魔搭首发
61 0
|
1月前
|
Java Maven Android开发
java如何连接mqtt
java如何连接mqtt
38 0
|
3月前
|
设计模式 Java 程序员
感动哭了!Java界的四大名著之一:Java编程思想最新中文版已开源
还记得这本书吗?是不是已经在你的桌上铺满厚厚的一层灰了?随着 Java 8 的出现,这门语言在许多地方发生了翻天覆地的变化。最新版已经出来了,在新的版本中,代码的运用和实现上与以往不尽相同。
|
3月前
|
算法 Java 程序员
阿里P8大佬终于把春招面试必备的神级Java面试手册给开源了!
先说说Java Java 作为国人编程开发语言中的 NO.1,已经占比半壁江山,选择入行做 IT 做编程开发的人,基本都把它作为首选语言,进大厂拿高薪也是大多数小伙伴们的梦想。 以前Java 岗位人才的空缺,而需求量又大,所以这种人才供不应求的现状,就是 Java 工程师的薪资待遇相对优厚的原因所在。 但是随着这个从事行业的人数逐渐增多,行业竞争也越来越大,招聘的企业和程序员们都想招聘到自己需要的人才/找到自己理想的岗位,国内大厂尤其是阿里招聘Java岗位居多,导致现在 Java 面试越来越难,内卷早就是大势所趋,万物皆可卷,卷的我们都见怪不怪了。 那么,阿里Java面试难度大吗?
|
3月前
|
JSON fastjson 数据库
字符编码导致Rapidjson(腾讯开源的json解析库)到Fastjson(阿里开发的Java json解析库)转换失败的原因分析
最近在客户端的开发的过程中,使用到了RapidJson,公司的开发是客户端和数据库端都由不同的人进行开发,我负责的客户端的逻辑开发(使用c++),开发工具同时使用了VS2017和QT的编译环境,使用QT主要是为了客户端界面开发方便,而使用了VS环境主要是维护公司开发的数据库接口库,这个库的唯一作用就是作为一个中间桥梁,使用Rapidjson将数据库接口的json数据格式解析为结构体数据,从而在客户端界面进行展示,或者接收客户端的数据,使用Rapidjson将其转换为json数据,发送给数据库接口以保存数据使用 。不太明白的可以参考我上一篇文章说明Rapidjson的使用过程-Parse解析数组
49 0
|
3月前
|
设计模式 算法 NoSQL
阿里巴巴官方上线!号称国内Java八股文天花板(终极版)首次开源
真正有意义的就业与跳槽,是要进入到一个有绝对潜力的行业或者薪资能实现爆炸式增长的。这件事不容易,但也没有想象的遥不可及,现在大环境不好,机会也不如以前多,除了让自身技术能力过硬,面试更是要好好准备! 如何准备? 除了平时的技术积累与沉淀之外,剩下的就只能背八股了(虽然工作用不到,但面试就是要问,不背是不行的)。
79 0