| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- // 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<MqttClient | null>(null)
- const isConnected = ref(false)
- const message = ref<any>(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
- }
- }
|