UNPKG

yimultiscreenserver-sdk-web

Version:

YiMultiScreenServer SDK for Web

157 lines 7.17 kB
import { MQTTLogic } from "../MQTTLogic"; import { MsgClientType } from "../message/MsgClientType"; import { MsgType } from "../message/MsgType"; import { WillMessage } from "../message/WillMessage"; import { Utils } from '../../../util/Utils'; import { SDKLog } from "../../../util/SDKLog"; import { SessionDestroyReason } from "../message/SessionDestroyReason"; export class ControllerMQTTImpl extends MQTTLogic { constructor(clientId, callback) { super(clientId); this.MYSELF_DISCONNECT_CALLBACK_GAP_MS = 500; // 0.5s this.callback = callback; this.accountId = -1; this.isSkipDisconnectCallbackOnce = false; this.lastDisconnectTime = 0; } // Override // 控制端需要覆写实现下父类的connect方法 // 因为控制端需要处理两种场景:1.先登录账户,再连接display;2.先连接display,再登录账户 async connect(displayCode) { if (this.isConnected) { // 此时就是场景1。用户先登录账户,再连接display // 必须先断开连接,因为登录账户时connect使用的option不包括will message // 所以要重新使用新的带有will message的option连接 this.isSkipDisconnectCallbackOnce = true; this.unsubscribeAccountTopic(this.accountId); await super.disconnect(displayCode) .then((result) => { this.isConnected = false; }) .catch((error) => { //不关注error }); } super.connect(displayCode); // 连接成功后,再次订阅上account相关的topic消息 if (-1 != this.accountId) { this.subscribeAccountTopic(this.accountId); } } // Override // 控制端需要覆写实现下父类的disconnect方法 // 因为控制端需要处理: 同时处于登录&连接display状态时,用户断开display后,如何处理账号topic消息的监听 async disconnect(displayCode) { // 用户断开display时,原逻辑是彻底断开mqtt连接,但此时用户还处于登录状态 return new Promise((resolve, reject) => { super.disconnect(displayCode) .then((result) => { resolve(result); }) .catch(reject); // 有必要判断此时是否订阅了账号topic消息,如果订阅了,则断开后需要重新连接上mqtt服务 if (-1 != this.accountId) { // 说明此时用户还处于登录状态,重新连接上mqtt服务订阅上账号相关的topic消息 this.subscribeAccountTopic(this.accountId); } }); } /** * 控制端单独增加的公开方法,用于控制端成功完成账号登录后,监听该账号topic下消息 * @param accountId 登录后拿到的账号唯一ID */ subscribeAccountTopic(accountId) { this.accountId = accountId; if (!this.isConnected) { super.connectWithOptions(super.createMqttOptions()); } let account = Utils.getTopicPrefix(MsgType.ACCOUNT) + accountId; let bindDevice = Utils.getTopicPrefix(MsgType.BIND_DEVICE) + accountId; let topics = [account, bindDevice]; super.getClient()?.subscribe(topics); } /** * 控制端单独增加的公开方法,用于控制端成功退出账号或注销账号后,解除对指定账号的topic消息监听 * @param accountId 登录后拿到的账号唯一ID */ unsubscribeAccountTopic(accountId) { this.accountId = -1; if (!this.isConnected) { return; } let account = Utils.getTopicPrefix(MsgType.ACCOUNT) + accountId; let bindDevice = Utils.getTopicPrefix(MsgType.BIND_DEVICE) + accountId; let topics = [account, bindDevice]; super.getClient()?.unsubscribe(topics); } isMessageFromSelf(message) { return MsgClientType.CONTROLLER == message.sender; } isMessageForMe(message) { return (MsgClientType.ANY == message.receiver || MsgClientType.CONTROLLER == message.receiver); } createMySelfWill(displayCode, clientId) { let ret = new WillMessage(MsgClientType.CONTROLLER, MsgClientType.ANY); ret.senderClientId = clientId; ret.timestamp = Date.now(); return ret; } subscribeInterestTopic(displayCode) { let will = Utils.getTopicPrefix(MsgType.WILL) + displayCode; let report = Utils.getTopicPrefix(MsgType.REPORT) + displayCode; let cast = Utils.getTopicPrefix(MsgType.CAST) + displayCode; let topics = [will, report, cast]; super.getClient()?.subscribe(topics); } unsubscribeAllTopics(displayCode) { let will = Utils.getTopicPrefix(MsgType.WILL) + displayCode; let report = Utils.getTopicPrefix(MsgType.REPORT) + displayCode; let cast = Utils.getTopicPrefix(MsgType.CAST) + displayCode; let topics = [will, report, cast]; super.getClient()?.unsubscribe(topics); } onWillMessageArrived(message) { // must be display or server died if (MsgClientType.DISPLAY == message.sender) { this.callback.onDisplayDied(); } else if (MsgClientType.SERVER == message.sender) { this.callback.onServerDied(); } } onDisplayReportMessageArrived(message) { this.callback.onDisplayReport(message.displayReport); } onCastSessionMessageArrived(message) { this.callback.onCastSession(message.castSession, message.action, message.mediaPayload, message.destroyReason ?? SessionDestroyReason.NONE); } onDataMessageArrived(message) { // we don't care about data msg } onUserHasBeenKickedMessageArrived(message) { this.callback.onUserHasBeenKicked(message.user); } onAccountBindDeviceMessageArrived(message) { this.callback.onAccountBindDevice(message.accountBindDevice, message.bindDeviceAction); } onConnectionLost(cause) { let now = Date.now(); if (now - this.lastDisconnectTime <= this.MYSELF_DISCONNECT_CALLBACK_GAP_MS) { // 自身断开连接回调做一个时间防抖,一定时长内连续触发我们都予以跳过 // 因为实操中发现前端使用的mtqq库会多次回调connectionLost SDKLog.d(this.TAG, "一定时长内连续触发connectionLost回调,跳过"); return; } this.lastDisconnectTime = now; if (this.isSkipDisconnectCallbackOnce) { // 此时,场景是用户先登录连接了mqtt,再connect display // 我们在connect时会先断开mqtt再重连,如果这次断开触发回调会导致上层不符合预期 SDKLog.d(this.TAG, "先登录再connect display,sdk主动触发一次重连,跳过这次回调"); this.isSkipDisconnectCallbackOnce = false; return; } this.callback.onMySelfDisconnected(cause); } } //# sourceMappingURL=ControllerMQTTImpl.js.map