前言
最近公司要做物联网控制,觉得写app要兼容Android和iOS两端成本实在是高,于是选定了微信小程序来作为控制监控端,为了能够实时的监听到设备的状态变化,需要设备能够主动推消息给小程序,一开始考虑了websocket,由服务器进行上报的数据监听,小程序使用websocket连接服务器接收消息,虽然能实现,但是需要自己定义数据交互协议,心跳等等,加上业务逻辑之后就太复杂了,工作量也不是我一个人能承受的。
于是想着,websocket既然能够连接实现数据的收发,那无非就是在上面做一层协议了,转念一想,那现成mqtt理论上岂不是应该也是可以的,然后回去翻阿里云官方文档,果然发现了MQTT over WebSocket,可以直连阿里云物理网平台,找了许久才找到官方的一个库aliyun-iot-client-sdk,但是却不是针对小程序的,代码上也有出入,于是又花了两天的时间查找各种资料测试,走了不少的弯路(毕竟我不是专门搞前端,难为了我这搞Android的了),最终还是搞定了,到头来发现还是自己不够细心,以此为记,希望能给后来者提供点帮助。
准备工作
- 去Github下载MQTT.js 库;一开始没注意,搞了很久,还把项目下下来自己编译,各种报错,最终也编译出来了,可后来发现其实有现成的单文件可用的,https://unpkg.com/mqtt/dist/mqtt.min.js,点击打开链接然后右键另存为即可(当前版本:2.18.8)。
- 去官方库aliyun-iot-client-sdk下载hmac-sha1算法库hex_hmac_sha1.js(当然也可以使用其他的库,比如crypto-js),点击打开链接然后右键另存为即可(其实官方库就是用的mqtt.js库,只是没有针对小程序,无法直接在小程序上使用)
- 下载微信开发者工具,并新建一个项目
- 拷贝刚刚下载的两个mqtt.min.js和hex_hmac_sha1.js到utils目录中去
- 勾选微信开发工具----【不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书】选项或者配置开发者后台socket 合法域名 为:wss://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com(替换productKey为自己的产品key,还有注意区域是不是cn-shanghai,不是也要替换)
开始编码
随便在一个页面的js文件中加入以下代码,注意替换参数为自己产品和设备的参数
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
console.log('收到消息:'+message.toString())
//关闭连接 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官方文档,同时,mqtt.js支持其他小程序如支付宝小程序等,这里我没做测试,可自己查看mqtt.js文档(示例代码的api接口随时间可能会有变动的,具体查看最新的官方文本)
鉴于很多人加我问了挺多相同的问题,我这里就列出问的最多的问题,只要结合官方文档认认真真的看,然后看看评论区,基本能解决90%以上的问题。
-
问:为什么设备连上之后小程序就断开或者小程序连上之后设备就断开(或者反复断开和重连)?
答:这是因为同一时间使用了同一组设备参数【ProductKey,DeviceName】 连接了两次以上,通常表现为小程序进行了两次以上连接或者小程序和设备使用了**同一组设备参数【ProductKey,DeviceName】**导致的,mqtt协议里规定同一clientId只能有一个连接(具体请查看mqtt协议文档),但是阿里云物联网稍有不同,还会根据使用的参数【ProductKey,DeviceName】做判断;通常做法是我们在阿里云物联网控制台创建一个产品对应小程序端,另一个产品对应硬件设备端,然后分别在相应的产品下创建设备,之后分别获取设备参数设置小程序和硬件设备即可(即需要两组参数【ProductKey,DeviceName】)。 -
问:接上一问题,既然不能使用同一组设备参数【ProductKey,DeviceName】,那小程序和设备之间该如何通信?
答:
标准的mqtt协议里,我们一般相互通信是直接订阅双方相应的主题即可,但是阿里云物联网平台的主题订阅是设有权限的,并且在订阅主题之后还需要设定相应的规则去转发数据,否则即使你订阅了相应的主题,但还是不会收到控制端或其他的设备端发过来的消息的。具体的主题订阅权限和默认设置可查看对应产品详情里的Topic类列表即可,那么数据转发方式有以下几种:- 使用RRPC方式(此方式只能app主动发消息给设备,设备进行应答,设备无法主动向app发送消息,适用场景为app需要确认设备已经接收和处理好信息),但需要自建后台服务器,集成服务器端SDK(当然也是可以不用搭建服务器,直接本地调用,但是非常非常不推荐这样做,因为这样很容易暴露一些关键的配置信息,有着非常非常大的安全隐患)
- 使用规则引擎—云产品流转(推荐,可实现标准mqtt里的相互收发)或者路由转发(需要搭建后台服务器),具体使用方式可以参考官方的最佳实践文档:基于规则引擎的M2M设备间通信和基于Topic消息路由的M2M设备间通信,通常来说,实际的业务需求是离不开后台服务器的,所以基本上都是要搭建后台服务器的。
很重要的两点:1.认真看官方文档 2.了解mqtt协议。
参考:
微信小程序-MQTT模拟器 连接阿里云IoT物联网平台
有任何其他疑问,可以加我QQ一起交流:343672271(备注:mqtt),如果觉得有帮到你,可以左下角点个赞呀
如果你使用的是支付宝小程序,可以看看这一篇https://blog.csdn.net/ngl272/article/details/108164127
转载:https://blog.csdn.net/ngl272/article/details/87887885