通过阿里的的微消息队列MQTT监测客户端状态,后端把状态通过MQTT传到前端实时更新客户端状态
1、在vue状态管理里面创建mqtt客户端连接,用来接收后端传来的要更新的客户端状态;
store/index.js主要代码
const mqttClient = localStorage.getItem("mqttClient")
export default new Vuex.Store({
state: {
mqttClient
},
mutations: {
changeMqtt(state, mqtt) {
state.mqttClient = mqtt
}
},
actions: {
mqttServer({
commit
}) {
var cid = "客户端id";
var pwd = CryptoJS.HmacSHA1(cid, "阿里Access Key Secret").toString(CryptoJS.enc.Base64);
var mqttOptions = {
username: "Signature|阿里AccessKey ID|MQTT实例ID",
password: pwd,
clientId: cid,
keepalive: 90,
connectTimeout: 3000
}
console.log('mmmm', 'password:'+pwd+"clientId:"+cid)
var client = mqtt.connect('ws://MQTT地址:80', mqttOptions)
client.on('connect', function() {
localStorage.setItem("mqttClient", client);
console.log("连接mqtt成功!" + userInfo.id);
commit('changeMqtt', client)
})
}
}
2、在客户端显示页面获取MQTT对象并订阅相关推送状态主题;
mapPage.vue主要代码
import { mapState } from "vuex"
var devises=new Map();
computed: {
...mapState(["mqttClient"])
},
addMarker(lng, lat,status,module) {
var marker;
var that=this
var iconimg=null
if(status==0){
iconimg=iotOffline
}else if(status==1){
iconimg=iotOnline
}else if(status==2){
iconimg=iotError
}
var endIcon = new AMap.Icon({
size: new AMap.Size(68, 68),
image: iconimg ,
imageSize: new AMap.Size(68,68 ),
imageOffset: new AMap.Pixel(-5, 3)
});
marker = new AMap.Marker({
position: new AMap.LngLat(lng, lat),
offset: new AMap.Pixel(-25, -10),
icon: endIcon, // 添加 Icon 实例
zoom: 12
});
marker.setExtData(module.id)
AMap.event.addListener(marker, 'mouseover', function(e) {
var param = {
moduleId: module.id
};
getModleDataApi(param, that.userInfo.token)
.then(res => {
status=res.data.online
var info = [];
info.push("<div><h2 style='color:#0068A6'><strong>模块信息</strong></h2>");
if(res.data.online==0){
info.push("<p class='input-item'><strong>状态 :</strong><span style='color:red'>离线</span></p>");
info.push("<p class='input-item'><strong>离线时间 :</strong>"+res.data.offline_date+"</p>");
}else if(res.data.online==1){
var onlineDate= new Date(res.data.online_date)
var d=onlineDate.getTime()
var n= (new Date()).getTime()
var sc= ((n-d)/(3600*1000)).toFixed(2)
info.push("<p class='input-item'><strong>状态 :</strong><span style='color:green'>在线</span></p>");
info.push("<p class='input-item'><strong>在线时长 :</strong><span >"+sc+"小时</span></p>");
}else if(res.data.online==2){
info.push("<p class='input-item'><strong>状态 :</strong><span style='color:red'>告警</span></p>");
}
info.push("<p class='input-item'><strong>使用单位 :</strong> "+module.unit+"</p>");
info.push("<p class='input-item'><strong>所属项目 :</strong> "+module.project_name+"</p>");
info.push("<p class='input-item'><strong>编号 :</strong> "+module.id+"</p>");
info.push("<p class='input-item'><strong>地址 :</strong>"+module.address+"</p></div></div>");
infoWindow = new AMap.InfoWindow({
content: info.join("") //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(map, marker.getPosition());
})
});
AMap.event.addListener(marker, 'dblclick', function(e) {
map.setZoomAndCenter(20, marker.getPosition());
});
// marker.on('mouseover', that.openInfoWin);
marker.on('mouseout', that.closeInfoWin);
map.add(marker);
devises.set(module.id,marker)
},
getModelInfo(){
var that = this;
getModleForMapApi(null,this.userInfo.token).then(res =>{
console.log("data",res)
if(res){
for(var i=0;i<res.data.length;i++){
that.addMarker(
res.data[i].longitude,
res.data[i].latitude,
res.data[i].online,
res.data[i]
)
}
}
})
setTimeout( that.connectMqtt, 1000)
},
connectMqtt(){
var that=this
that.mqttClient.subscribe("要订阅的主题", {'qos':1})
that.mqttClient.on('message', function (topic, message) {
console.log('mes', message.toString())
var d=JSON.parse(message.toString())
if(devises.has(d.id)){
var mar=devises.get(d.id)//根据id从map里取出对应的markker
var iconimg=null
if(mar.getExtData()==d.id){
if(d.lineStatus==0){
iconimg=iotOffline
}else if(d.lineStatus==1){
iconimg=iotOnline
}
var endIcon = new AMap.Icon({
size: new AMap.Size(68, 68),
image: iconimg ,
imageSize: new AMap.Size(68,68 ),
imageOffset: new AMap.Pixel(0, 3)
});
mar.setIcon(endIcon)//根据状态更改marker图标
//mar.setExtData(d.lineStatus)
}
}
})
},
注意:在获取mqtt连接对象时,要设置大概1秒的延迟,mqtt在状态里是异步加载的,不然获取的mqtt对象为null。
3、模拟测试
新建一个页面模拟MQTT上线和下线
下线
经测试 几乎连接成功的时候地图上标记点状态就发生变化,并且每个设备的状态都是独立控制,无需轮询和异步刷新