// useMqtt.ts import { ref, onUnmounted } from 'vue' import mqtt, { MqttClient, IClientOptions } from 'mqtt' import { ElMessage } from 'element-plus' type MessageCallback = (topic: string, payload: any) => void // 基础配置 (建议移至环境变量 import.meta.env.VITE_MQTT_HOST) const BASE_OPTIONS: IClientOptions = { clean: true, reconnectPeriod: 5000, connectTimeout: 10000, username: 'yanfan', password: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY0YmM2NjJlLWZhMjQtNGY1Ny1hOTk1LWZiMGM2YjNhYzI4OCJ9.9nxoDUNGTk1szRlZHHG0AcWZctLrzJ16UA5rsBagHNcD10PC-LIMTgAr2CK1Ppafa6cW5XPdn7RqBF6iZjHtww' } export function useMqtt() { const client = ref(null) const isConnected = ref(false) const message = ref(null) // 响应式消息数据 let customMessageCallback: MessageCallback | null = null // 初始化连接 const connect = (host: string, options: IClientOptions = {}, onMessage?: MessageCallback) => { if (client.value && client.value.connected) { console.warn('当前实例已连接 MQTT,跳过初始化') return } if (onMessage) { customMessageCallback = onMessage } // 合并配置,生成唯一 ClientId const finalOptions = { ...BASE_OPTIONS, clientId: `web-${Math.random().toString(16).substr(2)}`, ...options } try { client.value = mqtt.connect(host, finalOptions) client.value.on('connect', () => { isConnected.value = true ElMessage.success('MQTT 连接成功') }) client.value.on('error', (err) => { console.error('MQTT Error:', err) ElMessage.error(`MQTT 错误: ${err.message}`) isConnected.value = false }) client.value.on('close', () => { isConnected.value = false }) // 全局消息监听,更新响应式数据 client.value.on('message', (topic, payload) => { let parsedData: any try { parsedData = JSON.parse(payload.toString()) } catch (e) { parsedData = payload.toString() } message.value = { topic, payload: parsedData } if (customMessageCallback) { customMessageCallback(topic, parsedData) } }) } catch (err) { ElMessage.error(`MQTT 初始化异常: ${(err as Error).message}`) isConnected.value = false } } // 订阅主题 (支持泛型) const subscribe = (topic: string) => { if (client.value && client.value.connected) { client.value.subscribe(topic, { qos: 0 }, (err) => { if (err) ElMessage.error(`订阅失败: ${err.message}`) else console.log(`已订阅: ${topic}`) }) } } // 发布消息 const publish = (topic: string, message: string | object) => { if (client.value && client.value.connected) { const payload = typeof message === 'string' ? message : JSON.stringify(message) client.value.publish(topic, payload) } } // 销毁连接 const destroy = () => { if (client.value) { client.value.end() client.value = null isConnected.value = false } } // 组件卸载时自动断开 (防止内存泄漏) onUnmounted(() => { destroy() }) return { client, isConnected, message, // 组件内可以直接 watch 这个变量 connect, subscribe, publish, destroy } }