fix(mqtt): 固定设备 clientId,修复连接堆积与消息重复处理

- clientId 由随机改为 localStorage 固定,避免刷新产生新连接
- 修复重连后 message 监听器重复注册,防止消息重复触发
- led 页面销毁时断开 MQTT 连接
- 消息体判空保护
- MQTT 连接改用 wss

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
17792275749
2026-08-19 18:01:54 +08:00
co-authored by Claude Opus 4.7
parent fdb8dd4adf
commit 1abe5c6876
3 changed files with 27 additions and 17 deletions
+6 -10
View File
@@ -32,6 +32,12 @@ export const initMqtt = (clientId, topic, type, {username='sw_mqtt', password='1
const entry = { client, callback: null };
clients[type] = entry;
client.on('message', (topic, message) => {
if (entry.callback) {
entry.callback({ topic, message: JSON.parse(message.toString()) });
}
});
client.on("connect", () => {
console.info("MQTT 连接成功_clientId" + clientId);
@@ -39,11 +45,6 @@ export const initMqtt = (clientId, topic, type, {username='sw_mqtt', password='1
if (err) {
reject("订阅失败_clientId" + clientId);
} else {
if (entry.callback) {
client.on('message', (topic, message) => {
entry.callback({ topic, message: JSON.parse(message.toString()) });
});
}
resolve("订阅成功_clientId" + clientId);
}
});
@@ -59,11 +60,6 @@ export const callBackMqttMessage = (type, callback) => {
const entry = clients[type];
if (entry) {
entry.callback = callback;
if (entry.client) {
entry.client.on('message', (topic, message) => {
callback({ topic, message: JSON.parse(message.toString()) });
});
}
}
};
+9 -3
View File
@@ -274,10 +274,16 @@ export default {
},
methods: {
initMqttConnect() {
const clientId = 'db-' + Math.random().toString(16).substring(2, 8);
let clientId = localStorage.getItem('dbDeviceId');
if (!clientId) {
const bytes = new Uint8Array(8);
crypto.getRandomValues(bytes);
clientId = 'db-' + Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
localStorage.setItem('dbDeviceId', clientId);
}
console.log(clientId);
initMqtt(clientId, 'yx/device/rankingScreen/needUpdate', 'db', {
head: 'ws',
head: 'wss',
username: process.env.VUE_APP_DB_MQTT_USERNAME,
password: process.env.VUE_APP_DB_MQTT_PASSWORD
})
@@ -286,7 +292,7 @@ export default {
console.log('[MQTT] 收到消息:', data.topic, dayjs().format('YYYY-MM-DD HH:mm:ss'), data.message);
if (data.topic === 'yx/device/rankingScreen/needUpdate') {
const msg = data.message;
if (msg.type === 'RANKING_UPDATE') {
if (msg && msg.type === 'RANKING_UPDATE') {
this.initData('');
}
}
+12 -4
View File
@@ -21,7 +21,7 @@
<script>
import RowDom from "./components/rowDom.vue";
import {httpRequest} from "@/XMLHttpRequest";
import {callBackMqttMessage, initMqtt} from "@/utils/mqtt";
import {callBackMqttMessage, disconnectMqtt, initMqtt} from "@/utils/mqtt";
export default {
name: "led",
@@ -36,7 +36,8 @@ export default {
deviceDataList: [],
}
},
mounted() {
beforeDestroy() {
disconnectMqtt('led');
},
created() {
for (let i = 1; i <= this.deviceNumber; i++) {
@@ -91,11 +92,18 @@ export default {
})
},
initMQ() {
const clientId = 'deviceId-' + Math.random().toString(16).substring(2, 8);
let clientId = localStorage.getItem('ledDeviceId');
if (!clientId) {
const bytes = new Uint8Array(8);
crypto.getRandomValues(bytes);
clientId = 'deviceId-' + Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
localStorage.setItem('ledDeviceId', clientId);
}
console.log(clientId);
initMqtt(clientId, 'yx/device/foodRecord/needUpdate', 'led', {
username: process.env.VUE_APP_LED_MQTT_USERNAME,
password: process.env.VUE_APP_LED_MQTT_PASSWORD,
head: 'ws'
head: 'wss'
}).then((res) => {
console.log(res);
callBackMqttMessage('led', (data) => {