|
@@ -0,0 +1,122 @@
|
|
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
|
|
+import mqtt, { MqttClient, IClientOptions, IClientSubscribeOptions } from 'mqtt' // 静态导入 mqtt
|
|
|
|
|
+
|
|
|
|
|
+// 定义 MQTT 配置类型接口
|
|
|
|
|
+interface MqttConfig {
|
|
|
|
|
+ host: string
|
|
|
|
|
+ options: IClientOptions
|
|
|
|
|
+ topic: string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 定义消息回调函数类型
|
|
|
|
|
+type MessageCallback = (data: { topic: string; message: Record<string, any> }) => void
|
|
|
|
|
+
|
|
|
|
|
+// MQTT 连接配置
|
|
|
|
|
+const MQTT_CONFIG: MqttConfig = {
|
|
|
|
|
+ // 替换为你的 MQTT 服务器地址(ws/wss 协议)
|
|
|
|
|
+ host: 'ws://172.21.10.65:8083/mqtt',
|
|
|
|
|
+ // MQTT 连接选项
|
|
|
|
|
+ options: {
|
|
|
|
|
+ username: 'yanfan', // 替换为你的用户名(无则省略)
|
|
|
|
|
+ password: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY0YmM2NjJlLWZhMjQtNGY1Ny1hOTk1LWZiMGM2YjNhYzI4OCJ9.9nxoDUNGTk1szRlZHHG0AcWZctLrzJ16UA5rsBagHNcD10PC-LIMTgAr2CK1Ppafa6cW5XPdn7RqBF6iZjHtww', // 替换为你的密码(无则省略)
|
|
|
|
|
+ clean: true,
|
|
|
|
|
+ reconnectPeriod: 5000, // 重连间隔 5 秒
|
|
|
|
|
+ clientId: 'web-' + Math.random().toString(16).substr(2),
|
|
|
|
|
+ connectTimeout: 10000, // 连接超时 10 秒
|
|
|
|
|
+ },
|
|
|
|
|
+ // 要监听的主题
|
|
|
|
|
+ topic: '/657/YF1562/property/post'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 创建 MQTT 客户端实例(添加类型注解)
|
|
|
|
|
+let client: MqttClient | null = null
|
|
|
|
|
+// 消息回调函数
|
|
|
|
|
+let messageCallback: MessageCallback | null = null
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 初始化 MQTT 连接
|
|
|
|
|
+ * @param callback 接收消息的回调函数
|
|
|
|
|
+ */
|
|
|
|
|
+export const initMqtt = (callback: MessageCallback): void => {
|
|
|
|
|
+ // 保存消息回调
|
|
|
|
|
+ messageCallback = callback
|
|
|
|
|
+
|
|
|
|
|
+ // 避免重复连接
|
|
|
|
|
+ if (client && client.connected) {
|
|
|
|
|
+ ElMessage.info('MQTT 已连接')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 直接使用静态导入的 mqtt 创建连接(核心修复点)
|
|
|
|
|
+ client = mqtt.connect(MQTT_CONFIG.host, MQTT_CONFIG.options)
|
|
|
|
|
+
|
|
|
|
|
+ // 连接成功
|
|
|
|
|
+ client.on('connect', () => {
|
|
|
|
|
+ ElMessage.success('MQTT 连接成功')
|
|
|
|
|
+ // 订阅指定主题
|
|
|
|
|
+ const subscribeOptions: IClientSubscribeOptions = { qos: 0 }
|
|
|
|
|
+ client?.subscribe(MQTT_CONFIG.topic, subscribeOptions, (err) => {
|
|
|
|
|
+ if (err) {
|
|
|
|
|
+ ElMessage.error(`订阅主题失败:${err.message}`)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.info(`已订阅主题:${MQTT_CONFIG.topic}`)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 接收消息
|
|
|
|
|
+ client.on('message', (topic: string, payload: Buffer) => {
|
|
|
|
|
+ if (topic === MQTT_CONFIG.topic) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const messageStr = payload.toString()
|
|
|
|
|
+ const messageObj = JSON.parse(messageStr) as Record<string, any>
|
|
|
|
|
+ // 调用回调函数,将消息传递给组件
|
|
|
|
|
+ messageCallback?.({
|
|
|
|
|
+ topic,
|
|
|
|
|
+ message: messageObj
|
|
|
|
|
+ })
|
|
|
|
|
+ } catch (parseErr) {
|
|
|
|
|
+ ElMessage.error(`消息解析失败:${(parseErr as Error).message}`)
|
|
|
|
|
+ // 解析失败时直接返回字符串
|
|
|
|
|
+ messageCallback?.({
|
|
|
|
|
+ topic,
|
|
|
|
|
+ message: { raw: payload.toString() }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 连接断开
|
|
|
|
|
+ client.on('close', () => {
|
|
|
|
|
+ ElMessage.warning('MQTT 连接已断开')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 连接错误
|
|
|
|
|
+ client.on('error', (err: Error) => {
|
|
|
|
|
+ ElMessage.error(`MQTT 连接错误:${err.message}`)
|
|
|
|
|
+ client?.end()
|
|
|
|
|
+ })
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ const error = err as Error
|
|
|
|
|
+ ElMessage.error(`MQTT 初始化失败:${error.message}`)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 断开 MQTT 连接
|
|
|
|
|
+ */
|
|
|
|
|
+export const disconnectMqtt = (): void => {
|
|
|
|
|
+ if (client) {
|
|
|
|
|
+ client.end()
|
|
|
|
|
+ client = null
|
|
|
|
|
+ ElMessage.info('MQTT 已断开连接')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取当前 MQTT 连接状态
|
|
|
|
|
+ */
|
|
|
|
|
+export const getMqttStatus = (): boolean => {
|
|
|
|
|
+ return !!client?.connected
|
|
|
|
|
+}
|