Files
mixly3-server/mixly/mixly-sw/mixly-modules/web-socket/socket.js

254 lines
7.3 KiB
JavaScript

(() => {
goog.require('Mixly.Env');
goog.require('Mixly.Config');
goog.require('Mixly.MJson');
goog.require('Mixly.WebSocket');
goog.require('Mixly.LayerExt');
goog.require('Mixly.Command');
goog.provide('Mixly.WebSocket.Socket');
const {
Env,
Config,
MJson,
LayerExt,
Command
} = Mixly;
const { SOFTWARE } = Config;
const { Socket } = Mixly.WebSocket;
Socket.obj = null;
Socket.url = '';
Socket.jsonArr = [];
Socket.connected = false;
Socket.initFunc = null;
Socket.debug = SOFTWARE.debug;
Socket.disconnectTimes = 0;
Socket.updating = false;
// 构建 Socket.io 连接 URL (和后端统一使用 Socket.io)
let { hostname, protocol, port } = window.location;
if (protocol === 'http:') {
Socket.protocol = 'ws:';
} else {
Socket.protocol = 'wss:';
}
Socket.url = Socket.protocol + '//' + hostname + (port ? ':' + port : '');
Socket.IPAddress = hostname;
let lockReconnect = false;
let timeoutFlag = true;
let timeoutSet = null;
let reconectNum = 0;
const timeout = 5000;
function reconnect() {
if (lockReconnect) return;
lockReconnect = true;
setTimeout(function () {
timeoutFlag = true;
Socket.init();
console.info(`正在重连第${reconectNum + 1}`);
reconectNum++;
lockReconnect = false;
}, timeout);
}
// 心跳检测
const heartCheck = {
timeout,
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearInterval(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
const self = this;
let count = 0;
this.timeoutObj = setInterval(() => {
if (count < 3) {
if (Socket.connected) {
// Socket.io 自带心跳,这里可以发送自定义心跳
console.info(`HeartBeat第${count + 1}`);
}
count++;
} else {
clearInterval(this.timeoutObj);
count = 0;
if (Socket.obj && !Socket.connected) {
Socket.obj.disconnect();
}
}
}, self.timeout);
}
}
Socket.init = (onopenFunc = (data) => { }, doFunc = () => { }) => {
if (Socket.connected) {
if (Socket.initFunc) {
Socket.initFunc();
Socket.initFunc = null;
}
doFunc();
return;
}
timeoutSet = setTimeout(() => {
if (timeoutFlag && reconectNum < 3) {
console.info(`重连`);
reconectNum++;
Socket.init();
}
}, timeout);
// 使用 Socket.io 客户端连接(和后端统一)
Socket.obj = io(`${Socket.url}/all`, {
path: '/mixly-socket/',
reconnection: true,
reconnectionDelayMax: 10000,
transports: ['websocket']
});
Socket.obj.on('connect', () => {
console.log('已连接' + Socket.url);
Socket.connected = true;
Socket.initFunc = doFunc;
reconectNum = 0;
timeoutFlag = false;
clearTimeout(timeoutSet);
heartCheck.reset().start();
onopenFunc(Socket);
Socket.reload();
if (Socket.updating) {
Socket.updating = false;
}
});
// Socket.io 消息接收
Socket.obj.onAny((eventName, ...args) => {
heartCheck.reset().start();
// 构造兼容原有 Command 格式的消息
const command = { event: eventName, data: args };
if (Socket.debug) {
console.log('receive -> ', eventName, args);
}
// 尝试使用原有 Command 系统处理
try {
Command.run(MJson.decode(command));
} catch (e) {
// 如果 Command 系统不能处理,忽略
}
});
Socket.obj.on('connect_error', (error) => {
console.log('WebSocket error: ', error);
reconnect();
});
Socket.obj.on('disconnect', (reason) => {
Socket.connected = false;
Socket.disconnectTimes += 1;
if (Socket.disconnectTimes > 255) {
Socket.disconnectTimes = 1;
}
console.log('已断开' + Socket.url);
console.info(`关闭`, reason);
if (reason !== 'io client disconnect') {
timeoutFlag = false;
clearTimeout(timeoutSet);
reconnect();
} else {
clearInterval(heartCheck.timeoutObj);
clearTimeout(heartCheck.serverTimeoutObj);
}
});
}
Socket.sendCommand = (command) => {
if (!Socket.connected) {
layer.msg('未连接' + Socket.url, { time: 1000 });
return;
}
try {
const encodedCommand = MJson.encode(command);
if (Socket.debug) {
console.log('send -> ', encodedCommand);
}
// 使用 Socket.io emit 发送命令
Socket.obj.emit('command', encodedCommand);
} catch (e) {
console.log(e);
return;
}
}
Socket.clickConnect = () => {
if (Socket.connected) {
Socket.disconnect();
} else {
Socket.connect((WS) => {
layer.closeAll();
layer.msg(WS.url + '连接成功', { time: 1000 });
});
}
}
Socket.openLoadingBox = (title, successFunc = () => { }, endFunc = () => { }) => {
layer.open({
type: 1,
title: title,
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_ALL,
closeBtn: 0,
success: function () {
$("#webusb-cancel").css("display", "none");
$(".layui-layer-page").css("z-index", "198910151");
successFunc();
},
end: function () {
$("#mixly-loader-div").css("display", "none");
$(".layui-layer-shade").remove();
$("#webusb-cancel").css("display", "unset");
if (Socket.connected)
endFunc();
}
});
}
Socket.connect = (onopenFunc = (data) => { }, doFunc = () => { }) => {
if (Socket.connected) {
doFunc();
return;
}
let title = '连接中...';
Socket.openLoadingBox(title, () => {
setTimeout(() => {
Socket.init(onopenFunc);
}, 1000);
}, doFunc);
}
Socket.disconnect = () => {
if (!Socket.connected)
return;
let title = '断开中...';
Socket.openLoadingBox(title, () => {
Socket.obj.disconnect();
});
}
Socket.reload = () => {
if (!Socket.updating && Socket.disconnectTimes) {
window.location.reload();
}
}
})();