import MQTT from "@/components/mqttClient/WebMqtt"; import { Message } from 'element-ui'; import store from "@/store/index"; class MQTTService { constructor() { this.client = null; this.isInitialized = false; this.lat = 0; this.lon = 0; this.sendName = '' } /** * 初始化MQTT客户端 * @param {Object} account - 账号信息 */ async initClient(account) { console.log('MQTTService initClient-----', account); // 如果已经初始化且客户端存在,直接返回 // if (this.isInitialized && this.client) { // return this.client; // } // 清理之前的客户端 if (this.client) { this.client.destroy(); } const { name, password, uid, id, createBy } = account; localStorage.setItem("bindingUserId", uid); try { this.client = new MQTT({ username: name, password, roomId: uid, mqttId: createBy, }); // 设置客户端事件监听 this.setupClientEvents(); this.isInitialized = true; return this.client; } catch (e) { console.error(e); Message.error(e); throw e; } } /** * 获取MQTT实例 * @returns {Object} - 返回已初始化的MQTT实例 */ getMqttInstance() { if (!this.client) { throw new Error('MQTT实例未初始化'); } return this.client; } /** * 设置客户端事件监听 */ setupClientEvents() { // 处理初始化事件 this.client.on("init", () => { store.commit("showMessage", { message: '客户端已创建' }); }); // 处理错误事件 this.client.on("error", (error) => { console.error(error); store.commit("showMessage", { message: error, type: "error", }); }); // 处理连接事件 this.client.on("connect", (message) => { console.log('connect',message) }); // 处理消息事件 this.client.on("message", (message) => { console.log('message',message) this.handleMessage(message); }); } /** * 处理MQTT消息 * @param {Object} message - 消息对象 */ handleMessage({ topic, response }) { console.log("MQTT message received:", topic, response); // 根据topic类型处理不同消息 if (topic.includes("target/pc/qos0/msg")) { console.log("Online/offline status update:", response); if (response.remark === "Signal SOS") { this.lat = response.data.lat; this.lon = response.data.lon; this.sendName = response.data.sendName } } else if (topic.includes("target/media/signal")) { // 媒体信令处理 console.log("Media signal received"); this.handleMediaSignal(response); } else { console.warn("Unknown MQTT topic:", topic); } } /** * 处理媒体信令 * @param {Object} response - 响应数据 */ handleMediaSignal(response) { // 实现媒体信令处理逻辑 const { from, data, cmd } = response; if (cmd === "report") { this.handleSOSReport({...response, lat: this.lat, lon: this.lon, sendName: this.sendName}); } else if (cmd === "bye") { this.handleSOSExit(from); } else if (from && data && data.action === 3) { this.updateMemberList(from); } // 延迟拉取视频 setTimeout(() => { this.client.pullOnVideo(response); }, 1000); } /** * 处理SOS报告 * @param {Object} response - 响应数据 */ handleSOSReport(response) { const yarman = { type: "2", callType: "dispatch", video: true, audio: true, isMutedAudio: false, isCallVideo: true, }; store.dispatch('setYardman', yarman); const event = new CustomEvent('sos-event', { detail: response }); window.dispatchEvent(event); } /** * 处理SOS退出 * @param {String} from - 用户ID */ handleSOSExit(from) { console.log("退出SOS"); // const videoElem = document.getElementById(`remote-video-${from}`); // if (videoElem) videoElem.remove(); const event = new CustomEvent('sos-exit'); window.dispatchEvent(event); } /** * 更新成员列表 * @param {String} from - 用户ID */ updateMemberList(from) { const memberList = store.state.memberList || []; const updatedMemberList = memberList.map((member) => { if (member.dispatchUid.toString() === from.toString()) { member.handUp = true; } return member; }); if (memberList.length > 0) { store.commit("SET_MEMBER_LIST", updatedMemberList); } } /** * 发布本地视频流 * @param {Object} options - 选项 * @param {Boolean} options.isAudio - 是否包含音频 * @param {Boolean} options.isVideo - 是否包含视频 */ publishLocalVideo({ isAudio, isVideo }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.publishLocalVideo({ isAudio, isVideo }); } /** * 打开本地视频 * @param {Object} options - 选项 * @param {Boolean} options.isAudio - 是否包含音频 * @param {Boolean} options.isVideo - 是否包含视频 */ openLocalVideo({ isAudio, isVideo }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.openLocalVideo({ isAudio, isVideo }); } /** * 关闭本地视频 */ closeLocalVideo() { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.closeLocalVideo(); } /** * 离开会话 * @param {Boolean} isCallVideo - 是否是视频通话 * @param {String} toId - 目标用户ID */ leave(isCallVideo, toId) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.leave(isCallVideo, toId); } /** * 邀请成员 * @param {Object} options - 选项 * @param {Boolean} options.audioonly - 是否仅音频 * @param {Boolean} options.isCallVideo - 是否是视频通话 * @param {String} options.toId - 目标用户ID */ invite({ audioonly, isCallVideo, toId }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.invite({ audioonly, isCallVideo, toId }); } /** * 切换摄像头 * @param {Object} options - 选项 * @param {String} options.toId - 目标用户ID * @param {Boolean} options.isFront - 是否前置摄像头 */ switchCamera({ toId, isFront }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.switchCamera({ toId, isFront }); } /** * 静音本地音频 */ muteAudio() { if (!this.client?.pushVideoObj) { throw new Error('MQTT client or video object not initialized'); } this.client.pushVideoObj.getLocalAudioEnabledTrack(); } /** * 取消静音本地音频 */ unmuteAudio() { if (!this.client?.pushVideoObj) { throw new Error('MQTT client or video object not initialized'); } this.client.pushVideoObj.getLocalAudioTrack(); } /** * 关闭本地视频 */ muteVideo() { if (!this.client?.pushVideoObj) { throw new Error('MQTT client or video object not initialized'); } this.client.pushVideoObj.getLocalCameraEnabledTrack(); } /** * 开启本地视频 */ unmuteVideo() { if (!this.client?.pushVideoObj) { throw new Error('MQTT client or video object not initialized'); } this.client.pushVideoObj.getLocalCameraTrack(); } /** * 踢出成员 * @param {Object} options - 选项 * @param {String} options.toId - 目标用户ID */ kickOut({ toId }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.kickOut({ toId }); } /** * 处理举手请求 * @param {String} dispatchUid - 用户ID */ handUpRemote(dispatchUid) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.publish({ action: 5, toId: dispatchUid }); } /** * 拉取远程视频 * @param {String} id - 用户ID */ pullRemoteVideo(id) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.pullRemoteVideo(id); } /** * 删除远程流 * @param {String} id - 用户ID */ deleteRemote(id) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.deleteRemote(id); } /** * 处理视频拉取请求 * @param {Object} response - 响应数据 */ pullOnVideo(response) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.pullOnVideo(response); } /** * 发送麦克风控制 * @param {Object} options - 选项 * @param {String} options.toId - 目标用户ID */ toSendMic({ toId }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.toSendMic({ toId }); } /** * 取消麦克风控制 * @param {Object} options - 选项 * @param {String} options.toId - 目标用户ID */ toCancelMic({ toId }) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.toCancelMic({ toId }); } /** * 添加事件监听 * @param {String} eventName - 事件名称 * @param {Function} callback - 回调函数 */ on(eventName, callback) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.on(eventName, callback); } /** * 移除事件监听 * @param {String} eventName - 事件名称 * @param {Function} callback - 回调函数 */ off(eventName, callback) { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.off(eventName, callback); } /** * 移除所有事件监听 */ removeAllListeners() { if (!this.client) { throw new Error('MQTT client not initialized'); } this.client.off(); } /** * 处理错误 * @param {Error} error - 错误对象 */ handleError(error) { console.error('MQTT Service Error:', error); store.commit("showMessage", { message: error.message, type: "error", }); // 触发错误事件 if (this.client) { this.client.emit('error', error); } } } // 导出单例实例 export default new MQTTService();