最近在一个物联网项目中用到了MQTT协议通信。在开发过程中网页端通过websocket连接到MQTT服务器后,不停的弹出“连接成功”的提醒。
由于网页中同时采用layui,use()和require.js加载了一些外部扩展,所以首先排查了是否是JS冲突导致的。
经过一番排查,最终问题锁定在了client_id上。发现造成客户端不断重连的原因竟然是由于client_id造成的。即:网页写死client_id后,若建立连接时clean设置为true(清理会话)。则会造成此类问题。因此最后的解决办法就是在client_id后增加了一个随机数。
附MQTT网页代码:
- let device_id = '{$device.id}';
- //MQTT通讯,正式上线后要将配置文件放到后端处理,以防止网页爬虫
- require(['mqtt'],function (mqtt){
- var ws_opt = '';
- var ws_url = '';
- var gateway = 0;
- $.ajax({
- url:'{:url("/admin/api/websockets")}',
- data:{device_id:device_id},
- dataType:'json',
- async:false, //必须同步请求,不能异步
- method:'POST',
- success:function (res) {
- if(res.code == 200){
- ws_url = res.data.url;
- ws_opt = {clean: true,connectTimeout: res.data.connectTimeout,clientId:res.data.clientId+Math.round(Math.random()*800+100),username:res.data.username,password:res.data.password};
- gateway = res.data.gateway;
- }else{
- console.log("初始化失败:"+res.msg);
- }
- }
- })
- if(ws_url == '' || ws_opt.length < 5){
- return false;
- }
- const client = mqtt.connect(ws_url,ws_opt);
- client.on('connect',(success)=>{
- client.subscribe('at/data',{qos:0},function (err) {
- if(!err){
- $.msg.tips("服务器连接成功");
- }else{
- $.msg.error(err);
- }
- })
- });
- client.on('error',(error)=>{
- $.msg.error(error);
- })
- client.on('message',(topic,message)=>{
- var msg = JSON.parse(message.toString());
- //判断网关ClientID
- if(msg.a == gateway && msg.d == device_id ){
- //核心逻辑开始-begin
- var msgArr = msg.vs;
- msgArr.forEach(function (item,key) {
- var inname = "data"+key;
- var tmp_val = item.toString().split(",");
- $("input[name='"+ inname +"']").val(tmp_val[1]);
- })
- //核心逻辑结束-end
- }
- })
- });
由于MQTT采用订阅和发布模式,因此在数据处理方面要区分网关或客户端发布的消息。