【微信小程序控制硬件⑧ 】微信小程序以 websocket 链接阿里云IOT物联网平台mqtt服务器,封装起来使用就是这么简单!(附带Demo)

【微信小程序控制硬件①】 全网首发,借助 emq 消息服务器带你如何搭建微信小程序的mqtt服务器,轻松控制智能硬件!
【微信小程序控制硬件②】 开始微信小程序之旅,导入小程序Mqtt客户端源码,实现简单的验证和通信于服务器!
【微信小程序控制硬件③】 从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通信协议,为面试职位和比赛项目加分!
【微信小程序控制硬件④】 深度剖析微信公众号配网 Airkiss 原理与过程,esp8266如何自定义回调参数给微信,实现绑定设备第一步!
【微信小程序控制硬件⑤ 进阶篇 】理清接下来必须走的架构思想,学习下 JavaScript 的观察者模式,在微信小程序多页面同时接收到设备推送事件!
【微信小程序控制硬件⑥ 进阶篇 】服务器如何集成七牛云存储SDK,把用户自定义设备图片存储在第三方服务器!
【微信小程序控制硬件⑦ 进阶篇 】动起来作一个微信小程序Mqtt协议控制智能硬件的框架,为本身内心全栈工程师梦想浇水!!
【微信小程序控制硬件⑧ 进阶篇 】微信小程序以 websocket 链接阿里云IOT物联网平台mqtt服务器,封装起来使用就是这么简单!css



1、前言;


            今天是6月12号,高考过完刚刚不久,我也想起五年前那个夏天了。虽没有汗流浃背备考,但也有面对将来的种种幻想以及迷茫。html

            回想到如今工做了,本身学到的东西不少,还真的应了课本的一句话 “人的一辈子都是在学习中!学习如逆水行舟,不进则退!”,当我看到身边的一些人懒懒散散的,看博文学习不动手作小项目,个人心是有点 “嫌弃”的,我也但愿在一个优秀的团队,能够彼此进步,不论是大型企业或者小公司!当身边的人优秀,你也会必定反思本身,有所行动。前端

            感悟最深的是 ”学会投资本身“ ,无论在生活的衣食住行中,买些舒服的衣服,抑或是天天每周作些美食犒劳本身,仍是在职业生涯中,买教程,买课本,消化知识,提高本身。总结我在网上买了几乎几千块的视频,其中也有些乏味的教学视频,也有不少实实在在的干货,的确回味无穷,那是一种心灵上的快心。git


2、微信小程序 websocket;


            微信小程序都不陌生了,一句话:依靠在微信客户端的一个小程序,其开发语言不是原生的,而是采用 html+JavaScript+css 这样相似的前端代码,接近原生体验!github

            既然是一种相似 ”寄生虫“ 附属在微信客户端 ”宿主“ 里生存,那就不得不按照 ”宿主“ 的生存习惯,因此必须对于在微信小程序上实现 websocket链接阿里云IOT物联网平台服务器,那就必须遵循如下重要的准则:web

  1. 链接的端口号必须是 443 ,必须是 https协议;这里采用原生的便可。
  2. websocket之上再实现 mqtt 协议数据发送和接受,便可实现以 mqtt 协议通信;而我这里采用的是这个很出名的库:https://github.com/mqttjs/MQTT.js 来实现对数据的处理。

3、阿里云IOT物联网平台 websocket;


            阿里云IOT物联网平台支持基于WebSocket的MQTT协议。您能够首先使用WebSocket创建链接,而后在WebSocket通道上,使用 MQTT 协议进行通讯,即MQTT over WebSocket面试

  1. 证书准备。

            WebSocket可使用ws和wss两种方式,ws就是普通的WebSocket链接,wss就是增长了TLS加密。若是使用wss方式进行安全链接,须要使用和TLS直连同样的根证书。而我本次提供给你们的不须要根证书的。算法

  1. 链接说明:小程序

    使用WebSocket方式进行链接,区别主要在MQTT链接URL的协议和端口号,MQTT链接参数和TCP直接链接方式彻底相同,其中要注意securemode参数,使用wss方式链接时securemode=2,使用ws方式链接时 securemode=3。微信小程序

    • 链接域名(服务器地址),华东2节点(即上海节点):
      ${YourProductKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com:443

      其中 ${YourProductKey} 是个变量,请替换为您的产品key。

      Connect指令中须要设置 Keep Alive(保活时间)。保活心跳时间取值范围为30至1200秒。若是心跳时间不在此区间内,物联网平台会拒绝链接。建议取值300秒以上。若是网络不稳定,将心跳时间设置高一些。

      设备端在保活时间间隔内,至少须要发送一次报文,包括 PING 请求。

      若是物联网平台在保活时间内没法收到任何报文,物联网平台会断开链接,设备端须要进行重连。

    • MQTT链接参数参数以下:

      mqttClientId: clientId+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"
      mqttUsername: deviceName+"&"+productKey
      mqttPassword: sign_hmac(deviceSecret,content)sign签名须要把如下参数按字典序排序后,再根据signmethod加签。
      content=提交给服务器的参数(productKey,deviceName,timestamp,clientId), 按照字母顺序排序, 而后将参数值依次拼接

      其中,

      • clientId:表示客户端ID,建议mac或sn,64字符内。
      • timestamp:表示当前时间毫秒值,可选。
      • mqttClientId:格式中||内为扩展参数。
      • signmethod:表示签名算法类型。
      • securemode:表示目前安全模式,可选值有2 (wss协议)和3(ws协议)。
        参考示例,若是预置前提以下:
    clientId = 12345,deviceName = device, productKey = pk, timestamp = 789,signmethod=hmacsha1,deviceSecret=secret
    • 使用ws方式

      • 链接域名

        ws://pk.iot-as-mqtt.cn-shanghai.aliyuncs.com:443
      • 链接参数

        mqttclientId=12345|securemode=3,signmethod=hmacsha1,timestamp=789|
        mqttUsername=device&pk
        mqttPasswrod=hmacsha1("secret","clientId12345deviceNamedeviceproductKeypktimestamp789").toHexString();
    • 使用wss方式

      • 链接域名

        wss://pk.iot-as-mqtt.cn-shanghai.aliyuncs.com:443
      • 链接参数

        mqttclientId=12345|securemode=2,signmethod=hmacsha1,timestamp=789|
        mqttUsername=device&pk
        mqttPasswrod=hmacsha1("secret","clientId12345deviceNamedeviceproductKeypktimestamp789").toHexString();

4、如何移植和封装使用;


            由于我作过设备端的 Mqtt协议链接阿里云物联网平台,对协议比较熟悉,因此对于怎么实如今微信小程序上是很是简单的。

            上面已经详细地说明了阿里云物联网平台 websocket 的协议,那么总的来讲就是一个 加密算法,由于我以前已经开源了一个在微信小程序上实现 Mqtt协议链接服务器,这只要拿到了链接的一些参数,那就不成问题了!

            上面反复提到 hmacsha1 加密算法,那我就去找一个呗。还好,去官网 GitHub找了一个:点击访问 , 拿到了加密算法文件,按照上面说明,分别生成:mqttclientId、mqttUsername、mqttPasswrod、port端口号、url域名,就能够实现连接啦!


4.1 为了简单实用,下降耦合,我一度封装起来生成的算法,其封装源码以下:

exports.getAliyunIotMqttClient = function(opts) {

    //是否传入三元组
    if (!opts || !opts.productKey || !opts.deviceName || !opts.deviceSecret) {
        throw new Error('options need productKey,deviceName,deviceSecret');
    }

    if (opts.protocol === 'mqtts' && !opts.ca) {
        throw new Error('mqtts need ca ');
    }
    //是否传入区域
    if (!opts.host && !opts.regionId) {
        throw new Error('options need host or regionId (aliyun regionId)');
    }

    const deviceSecret = opts.deviceSecret;
    delete opts.deviceSecret;

    let secureMode = (opts.protocol === 'mqtts') ? 3 : 2;

    var options = {
        productKey: opts.productKey,
        deviceName: opts.deviceName,
        timestamp: Date.now(),
        clientId: Math.random().toString(36).substr(2)
    }
    let keys = Object.keys(options).sort();
    // 按字典序排序
    keys = keys.sort();
    const list = [];
    keys.map((key) => {
        list.push(`${key}${options[key]}`);
    });
    const contentStr = list.join('');
    //加密算法生成 password
    opts.password = crypto.hex_hmac_sha1(deviceSecret, contentStr);
    opts.clientId = `${options.clientId}|securemode=${secureMode},signmethod=hmacsha1,timestamp=${options.timestamp}|`;
    opts.username = `${options.deviceName}&${options.productKey}`;

    opts.port = opts.port || 1883;
    //生成域名
    opts.host = opts.host || `${opts.productKey}.iot-as-mqtt.${opts.regionId}.aliyuncs.com`;
    
    return (opts); //返回给上层
}

4.2 如何使用呢?


            很是简单,只须要调用 getAliyunIotMqttClient(option) 传进一些参数便可获取所有东西;

            option 对象的定义以下:

参数 含义
productKey 三元组信息 productKey
deviceName 三元组信息 deviceName
deviceSecret 三元组信息 deviceSecret
regionId 可选域,目前国内仅支持上海,因此是 cn-shanghai
port 443 不可修改,惟一!

            返回的对象的定义以下:

参数 含义
clientId 链接参数
password 链接参数
username 链接参数
host 链接的域名
  • 示范:
data: {
    aliyunInfo: {
      productKey: 'a1o3SXAACTs23', 
      deviceName: 'rgb2812',
      deviceSecret: 'RurAqmlt0duwMilKv6Oa856WDcQ279685a', 
      regionId: 'cn-shanghai', 
    }
  }
  
    var that = this
    
    //传进去三元组等信息,拿到mqtt链接的各个参数
    let clientOpt = aliyunOpt.getAliyunIotMqttClient({
      productKey: that.data.aliyunInfo.productKey,
      deviceName: that.data.aliyunInfo.deviceName,
      deviceSecret: that.data.aliyunInfo.deviceSecret,
      regionId: that.data.aliyunInfo.regionId,
      port: that.data.aliyunInfo.port,
    });

    //获得链接域名
    let host = 'wxs://'+clientOpt.host;
    this.setData({
      'options.clientId': clientOpt.clientId,
      'options.password': clientOpt.password,
      'options.username': clientOpt.username,
    })
 
    //开始链接
    this.data.client = mqtt.connect(host, this.data.options);
    this.data.client.on('connect', function(connack) {
      wx.showToast({
        title: '链接成功'
      })
    })

5、其余;


            看起来是否是很是简单呢?对的,下面我已经传到了我 GitHub 仓库了,欢迎你们给个星星啦!是对我最大的支持! 我将一直维护:https://github.com/xuhongv/WeChatMiniEsp8266

            更多的使用技巧,你须要具有必定的微信小程序开发经验哦!结合个人代码,让你轻松链接阿里云IOT物联网平台!与你共勉!!


  • 不少人怎么联系我一块儿学习进步,下面打个小小公告和干货无偿分享:

玩转esp8266 & esp32带你飞、加群付费QQ群,干货多多,提供免费Mqtt服务器,提升门槛,不喜的朋友勿喷勿加:434878850
esp8266源代码免费学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
esp32源代码免费学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32