作者:哈行小DWW_421 | 来源:互联网 | 2023-08-11 14:40
前言
最近公司要做物联网控制,觉得写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)
开始编码
随便在一个页面的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)
const client = mqtt. connect ( 'wxs://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com' , options)
client. on ( 'connect' , function ( ) {
console. log ( '连接服务器成功' )
client. subscribe ( '/productKey/deviceName/get' , function ( err) {
if ( ! err) {
console. log ( '订阅成功!' ) ;
}
} )
} )
client. on ( 'message' , function ( topic, message) {
console. log ( '收到消息:' + message. toString ( ) )
} )
} ,
initMqttOptions ( deviceConfig) {
const params = {
productKey: deviceConfig. productKey,
deviceName: deviceConfig. deviceName,
timestamp: Date. now ( ) ,
clientId: Math. random ( ) . toString ( 36 ) . substr ( 2 ) ,
}
const options = {
keepalive: 60 ,
clean: true ,
protocolVersion: 4
}
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;
} ,
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文档
鉴于很多人加我问了挺多相同的问题,我这里就列出来常见的几个问题
问:为什么设备连上之后小程序就断开或者小程序连上之后设备就断开?
答:这是因为小程序和设备使用了同一组参数导致的,这是mqtt协议里的规定,同一clientId只能有一个连接(具体请查看mqtt协议文档);通常这是因为不够了解mqtt协议想设备和小程序之间直接通信才会这样使用,从而导致问题的发生。
问:接上一问题,既然不能使用同一组参数,那小程序和设备如何通信?
答:
使用RRPC方式,但需要自建后台服务器,集成服务器SDK(理论上也是可以不用搭建服务器,但是非常非常不推荐这样做,因为这样很容易暴露一些关键的信息,有着非常大的安全隐患)
使用规则引擎或者路由转发(需要搭建后台服务器),具体使用方式可以参考官方的最佳实践文档:基于规则引擎的M2M设备间通信和基于Topic消息路由的M2M设备间通信,通常来说,实际的业务需求是离不开后台服务器的,所以基本上都是要搭建后台服务器的。
最后很重要的一点:一定一定要先了解好mqtt协议,这个很重要,因为不管是阿里云物联网还是百度、华为等物联网平台,最基础的都是基于mqtt协议,其他的大同小异,万变不离其宗。
参考:微信小程序-MQTT模拟器 连接阿里云IoT物联网平台
有任何其他疑问,可以加我QQ一起交流:343672271(备注:mqtt)