微信小程序使用MQTT.js连接阿里云IoT物联网平台[通俗易懂]

微信小程序使用MQTT.js连接阿里云IoT物联网平台[通俗易懂]前言最近公司要做物联网控制,觉得写app不能够兼容Android和iOS,于是选定了微信小程序来作为控制端,为了能够实时的监听到设备的状态变化,需要服务器能够主动推消息给小程序,一开始考虑了websocket,由服务器进行上报的数据监听,小程序使用websocket连接服务器接收消息,虽然能实现,但是加上业务逻辑之后就太复杂终归不好(因为服务器也是自己写–泪奔)于是想着,websocket既然…………………

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

官方已经开源了一个SDK版本,也是基于mqtt.js,进行了各种封装:

https://github.com/aliyun/alibabacloud-iot-device-sdk
·

阅读以下内容需要你具备相应的基础知识,包括JavaScript,微信小程序,css,html等,不要私信我询问一些基础的比如全局变量,json数据怎么解析,微信小程序语法等等基础知识问题

·
esp8266连接可参考我的另一篇文章Esp8266 nodemcu 使用PubSubClient连接阿里云物联网平台

如果你不想使用官方sdk,或者想了解下连接服务器的流程,可以继续往下看

准备工作

  1. 去Github下载MQTT.js 库;一开始没注意,搞了很久,还把项目下下来自己编译,各种报错,最终也编译出来了,可后来发现其实有现成的单文件可用的,https://unpkg.com/mqtt/dist/mqtt.min.js,点击打开链接然后右键另存为即可(当前版本:2.18.8,)。——-ps:4.2.0版本以上(不包括4.2.0)目前似乎是存在问题,会连接不上
  2. 官方早期仅支持web端的aliyun-iot-client-sdk下载hmac-sha1算法库hex_hmac_sha1.js(当然也可以使用其他的库,比如crypto-js),点击打开链接然后右键另存为即可(其实官方库就是用的mqtt.js库,只是没有针对小程序,无法直接在小程序上使用)
  3. 下载微信开发者工具,并新建一个项目
  4. 拷贝刚刚下载的两个mqtt.min.js和hex_hmac_sha1.js到utils目录中去
  5. 勾选微信开发工具—-【不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书】选项或者配置开发者后台socket 合法域名 为:wss://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com(替换productKey为自己的产品key,还有注意区域是不是cn-shanghai,不是也要替换)

温馨提醒:因为缓存原因,如果你配置开发者后台socket 合法域名后导致程序无法连接服务器(模拟器可正常连接),请试试手动删掉手机上的小程序后重新编译安装即可(或者调试模式下可以连接服务器,退出调试模式就连接不了,也可以试试删掉小程序重新运行安装重试)

开始编码(如果你不懂什么是后端服务云开发,新建项目请勾选【不使用云服务】)

随便在一个页面的js文件中加入以下代码,注意替换参数为自己产品和设备的参数

特别注意:不要使用同一组参数(即三元组:ProductKey,DeviceName,DeviceSecret)在多个地方同时进行连接,即一组三元组同一时间只能存在一个连接,否则会相互挤掉线反复重连!!!(常见情形为:模拟打开运行同时又真机调试运行或者小程序和硬件设备使用同一组参数等等),不要想着用一组参数同时在小程序和硬件设备上使用,然后进行通信,这是错误的做法。

在这里插入图片描述

更多限制请查看官方文档

var mqtt = require('../../utils/mqtt.min.js') //根据自己存放的路径修改
const crypto = require('../../utils/hex_hmac_sha1.js'); //根据自己存放的路径修改
Page({ 
   
  data: { 
   
   
  },
  onLoad: function () { 
   
  	//注意:这里在程序运行后会直接进行连接,如果你要真机调试,记得关掉模拟器或者使用一个按钮来控制连接,以避免模拟器和真机同时进行连接导致两边都频繁断线重连!
    this.doConnect()
  },
  doConnect(){ 
   
    const deviceConfig = { 
   
      productKey: "替换",
      deviceName: "替换",
      deviceSecret: "替换",
      regionId: "cn-shanghai"//根据自己的区域替换
    };
    const options = this.initMqttOptions(deviceConfig);
    console.log(options)
    //替换productKey为你自己的产品的(注意这里是wxs,不是wss,否则你可能会碰到ws不是构造函数的错误)
    const client = mqtt.connect('wxs://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com',options)
    client.on('connect', function () { 
   
      console.log('连接服务器成功')
      //注意:订阅主题,替换productKey和deviceName(这里的主题可能会不一样,具体请查看控制台-产品详情-Topic 类列表下的可订阅主题),并且确保改主题的权限设置为可订阅
      client.subscribe('/productKey/deviceName/user/get', function (err) { 
   
        if (!err) { 
   
           console.log('订阅成功!');
        }
      })
    })
	//接收消息监听
    client.on('message', function (topic, message) { 
   
      // message is Buffer
      let msg = message.toString();
      console.log('收到消息:'+msg);
     //关闭连接 client.end()
    })
  },
  //IoT平台mqtt连接参数初始化
 initMqttOptions(deviceConfig) { 
   

    const params = { 
   
      productKey: deviceConfig.productKey,
      deviceName: deviceConfig.deviceName,
      timestamp: Date.now(),
      clientId: Math.random().toString(36).substr(2),
    }
    //CONNECT参数
    const options = { 
   
      keepalive: 60, //60s
      clean: true, //cleanSession不保持持久会话
      protocolVersion: 4 //MQTT v3.1.1
    }
    //1.生成clientId,username,password
    options.password = this.signHmacSha1(params, deviceConfig.deviceSecret);
    options.clientId = `${ 
     params.clientId}|securemode=2,signmethod=hmacsha1,timestamp=${ 
     params.timestamp}|`;
    options.username = `${ 
     params.deviceName}&${ 
     params.productKey}`;

    return options;
  },

/* 生成基于HmacSha1的password 参考文档:https://help.aliyun.com/document_detail/73742.html?#h2-url-1 */
 signHmacSha1(params, deviceSecret) { 
   

    let keys = Object.keys(params).sort();
    // 按字典序排序
    keys = keys.sort();
    const list = [];
    keys.map((key) => { 
   
      list.push(`${ 
     key}${ 
     params[key]}`);
    });
    const contentStr = list.join('');
    return crypto.hex_hmac_sha1(deviceSecret, contentStr);
  }
})

运行代码在控制台设备Topic列表(注意:现在这里只有成功订阅设备主题后才会显示对应的主题)发布消息:
在这里插入图片描述
即可看到如下,那么最基础的连接和接收消息已经完成了(自定义主题和数据透传)
在这里插入图片描述

更多的参数设置请查看mqtt.js文档和阿里物联网Iot官方文档,上面的示例代码仅供参考,其中的api接口随时间可能会有变动的,具体查看最新的官方文档。

PS:如果你仅仅是简单的写个demo或者小需求,不一定非得使用官方Alink JSON的物模型,这样反倒会把问题复杂化(相信大多数人第一次看文档基本上做不到完全理解透),转而完全可以使用自定义格式的json数据(即新建产品时数据格式选择=》透传/自定义)和自定义主题或者默认的xx/xx/user/get和xx/xxx/user/update主题就能实现大部分的需求(不借助服务器也可以实现简单双向通信控制–规则引擎),官方的[ICA 标准数据格式]Alink JSON的物模型本质上也是规定了相应的json格式数据和主题等,这些内容官方文档里都有说明,你认真去看了就会发现这里的内容绝大部分都是出自官方文档。

鉴于很多人加我问了挺多相同的问题,我这里就列出问的最多的问题,只要结合官方文档认认真真的看,然后看看评论区,基本能解决90%以上的问题。

  1. 问:为什么硬件设备连上之后小程序就断开或者小程序连上之后硬件设备就断开(或者反复断开和重连)?
    答:这是因为同一时间使用了同一组设备参数【ProductKey,DeviceName,DeviceSecret】 连接了两次以上,通常表现为小程序进行了两次以上连接(例如模拟器和真机调试一起运行)或者小程序和硬件设备使用了**同一组设备参数【ProductKey,DeviceName,DeviceSecret】**导致的,mqtt协议里规定同一clientId只能有一个连接(具体请查看mqtt协议文档),但是阿里云物联网稍有不同,还会根据使用的参数【ProductKey,DeviceName,DeviceSecret】做判断;通常做法是我们在阿里云物联网控制台创建一个产品对应小程序端,另一个产品对应硬件设备端,然后分别在相应的产品下创建设备,之后分别获取各自三元组参数设置到小程序和硬件设备即可(即需要两组参数【ProductKey,DeviceName,DeviceSecret】)。

  2. 问:接上一问题,既然不能使用同一组设备参数【ProductKey,DeviceName,DeviceSecret】,那小程序和硬件设备之间该如何通信?
    答:
    标准的mqtt协议里,我们一般相互通信是直接订阅双方相应的主题,然后往主题发布消息即可,但是阿里云物联网平台的主题的订阅和发布都是设有权限的,并且在订阅主题之后还需要设定相应的规则去转发数据,否则即使你订阅了相应的主题,但还是不会收到控制端或其他的硬件设备端发过来的消息的。具体的主题订阅权限和默认设置可查看对应产品详情里Topic类列表即可,那么数据转发方式有以下几种:

    1. 使用RRPC方式(此方式只能app主动发消息给设备,设备进行应答,设备无法主动向app发送消息,适用场景一般为app需要确认设备已经接收和处理好信息),但需要自建后台服务器,集成服务器端SDK(当然也是可以不用搭建服务器,直接本地调用,但是非常非常不推荐这样做,因为这样很容易暴露一些关键的配置信息,有着非常非常大的安全隐患)
    2. 使用规则引擎—云产品流转推荐,可实现标准mqtt里的相互收发)或者路由转发(一般需要搭建后台服务器),具体使用方式可以参考官方的最佳实践文档:基于规则引擎的M2M设备间通信基于Topic消息路由的M2M设备间通信
  3. 问:出现closeSocket:fail WebSocket is not connected错误
    这个错误一般是调用end方法断开连接时出现,一般情况下不影响,可以忽略

  4. 问:订阅主题不成功
    排查步骤:

    1. 请在产品topic类列表下查看该主题是否存在
    2. 该主题操作权限是否为可订阅权限(特别注意:设备只能订阅属于自己的主题,无法订阅其他设备的主题
    3. 查看代码主题书写是否正确
      在这里插入图片描述

很重要的两点:1.认真看官方文档,绝大部分问题都能在文档里找到答案 2.了解mqtt协议的机制和工作原理。

参考:
微信小程序-MQTT模拟器 连接阿里云IoT物联网平台

如果觉得有帮到你,可以右下角顺手点个赞支持一下。

如果你使用的是支付宝小程序,可以看看这一篇https://blog.csdn.net/ngl272/article/details/108164127

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185305.html原文链接:https://javaforall.net

(1)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • IdeaVim 基本操作[通俗易懂]

    IdeaVim 基本操作[通俗易懂]IdeaVim基本操作安装插件ideaVim剪贴板与系统剪贴板同步CapsLock键映射为Esc键光标的移动安装插件File-Settings-Plugins,BrowseRepositories,输入ideavim,安装2.重启IntelliJIDEAideaVim剪贴板与系统剪贴板同步在ideavimrc文件中添加一行:setclipboard=unnamedplus,unnamed保存并退出:wq重启IntelliJIDEACaps

    2022年10月1日
    2
  • wireshark过滤规则及使用方法

    wireshark过滤规则及使用方法Wireshark基本语法,基本使用方法,及包过滤规则:1.过滤IP,如来源IP或者目标IP等于某个IP例子:ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107或者ip.addr eq 192.168.1.107 // 都能显示来源IP和目标IPLinux上运行的wireshark图形窗口截图示例,

    2022年7月13日
    23
  • uart串口通信编程_verilog调用模块端口对应方式

    uart串口通信编程_verilog调用模块端口对应方式1.发送模块moduleuart_tx(clk,rst,start,tx_data_in,tx,tx_active,done_tx);parameterclk_freq=50000000;//MHzparameterbaud_rate=19200;//bitspersecondinputclk,rst;inputstart;input[7:0]tx_…

    2022年9月14日
    2
  • ringbuffer的常规用法_likewise用法

    ringbuffer的常规用法_likewise用法C/C++Linux服务器开发/后台架构师知识体系整理环形缓冲区(RINGBUFFER)的实现原理环形缓冲区通常有一个读指针和一个写指针(一个入指针和一个出指针)。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。如果仅仅有一个读用户和一个写用户,那么不需要添加互斥保护机制就可以保证数据的正确性。如果有多个读写用户访问环形缓冲区,那么必须添加互斥保护机

    2022年9月10日
    1
  • 连接共享打印机显示0x000bcb_0x00004005打印机连接

    连接共享打印机显示0x000bcb_0x00004005打印机连接以win7为例,在局域网中,安装共享打印机时,会出现安装失败,打开详细信息显示为0x000000bcb,重新安装也不行,具体操作如下:连接共享打印机出现0x000000bcb问题的解决方法1打开控制面板,点击卸载程序,如下:2点击”查看已安装的更新“如下:3点击右上角“搜索已安装更新”,输入:”KB4022722“,点击搜索,会在下面的找到”KB4022722“的更新,点击卸载就…

    2022年10月7日
    3
  • 脚手架专项施工方案范本_手写react项目脚手架

    脚手架专项施工方案范本_手写react项目脚手架前言如何快速搭建一个httprunner项目呢?我们可以使用脚手架,脚手架就是自动地创建一些目录,形成一个项目的架构,不需要我们再手动的去创建查看创建新项目的命令先来查看一下帮助命令httpr

    2022年7月30日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号