Update: 更新WebSocket模式

This commit is contained in:
王立帮
2024-12-01 14:44:49 +08:00
parent 134f2c99ae
commit 9bbd0e6720
13 changed files with 611 additions and 520 deletions

View File

@@ -1,228 +1,216 @@
goog.loadJs('web', () => {
goog.require('layui');
goog.require('Mixly.Env');
goog.require('Mixly.LayerExt');
goog.require('Mixly.Config');
goog.require('Mixly.Title');
goog.require('dayjs.duration');
goog.require('Mixly.Boards');
goog.require('Mixly.MFile');
goog.require('Mixly.MArray');
goog.require('Mixly.Debug');
goog.require('Mixly.LayerExt');
goog.require('Mixly.Msg');
goog.require('Mixly.WebSocket.Socket');
goog.require('Mixly.Workspace');
goog.require('Mixly.WebSocket.Serial');
goog.provide('Mixly.WebSocket.ArduShell');
const {
Env,
LayerExt,
Title,
Boards,
MFile,
MArray,
Debug,
LayerExt,
Msg,
Config
Workspace,
WebSocket
} = Mixly;
const { BOARD, SOFTWARE, USER } = Config;
const {
Socket,
ArduShell,
Serial
} = Mixly.WebSocket;
const { Serial } = WebSocket;
/**
* @function 编译
* @description 开始一个编译过程
* @return void
*/
ArduShell.initCompile = () => {
Socket.connect((WS) => {
layer.closeAll();
}, () => {
ArduShell.compile();
});
}
/**
* @function 编译
* @description 开始一个编译过程
* @return void
*/
ArduShell.compile = () => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
mainStatusBarTabs.changeTo('output');
ArduShell.compiling = true;
ArduShell.uploading = false;
const boardType = Boards.getSelectedBoardCommandParam();
mainStatusBarTabs.show();
const layerNum = layer.open({
type: 1,
title: Msg.Lang['shell.compiling'] + "...",
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_NAV,
resize: false,
closeBtn: 0,
success: (layero, index) => {
$(".layui-layer-page").css("z-index", "198910151");
$("#mixly-loader-btn").off("click").click(() => {
$("#mixly-loader-btn").css('display', 'none');
layer.title(Msg.Lang['shell.aborting'] + '...', index);
ArduShell.cancel();
class WebSocketArduShell {
static {
this.socket = null;
this.shell = null;
this.init = function (socket) {
this.socket = socket;
this.shell = new WebSocketArduShell();
socket.on('arduino.dataEvent', (data) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
statusBarTerminal.addValue(data);
});
statusBarTerminal.setValue(Msg.Lang['shell.compiling'] + "...\n");
const code = MFile.getCode();
Socket.sendCommand({
obj: 'ArduShell',
func: 'compile',
args: [ index, boardType, code ]
});
},
end: () => {
$('#mixly-loader-div').css('display', 'none');
$("layui-layer-shade" + layerNum).remove();
$("#mixly-loader-btn").off("click");
$("#mixly-loader-btn").css('display', 'inline-block');
}
});
}
/**
* @function 初始化上传
* @description 关闭已打开的串口,获取当前所连接的设备数,然后开始上传程序
* @return void
*/
ArduShell.initUpload = () => {
Socket.connect((WS) => {
layer.closeAll();
}, () => {
ArduShell.compiling = false;
ArduShell.uploading = true;
const boardType = Boards.getSelectedBoardCommandParam();
const uploadType = Boards.getSelectedBoardConfigParam('upload_method');
let port = Serial.getSelectedPortName();
switch (uploadType) {
case 'STLinkMethod':
case 'jlinkMethod':
case 'usb':
port = 'None';
break;
}
if (port) {
ArduShell.upload(boardType, port);
} else {
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
time: 1000
socket.on('arduino.errorEvent', (data) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
statusBarTerminal.addValue(data);
});
}
});
}
/**
* @function 上传程序
* @description 通过所选择串口号开始一个上传过程
* @return void
*/
ArduShell.upload = (boardType, port) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
mainStatusBarTabs.changeTo("output");
const layerNum = layer.open({
type: 1,
title: Msg.Lang['shell.uploading'] + "...",
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_NAV,
resize: false,
closeBtn: 0,
success: function (layero, index) {
$(".layui-layer-page").css("z-index", "198910151");
$("#mixly-loader-btn").off("click").click(() => {
$("#mixly-loader-btn").css('display', 'none');
layer.title(Msg.Lang['shell.aborting'] + '...', index);
ArduShell.cancel();
});
this.initCompile = function () {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
mainStatusBarTabs.changeTo('output');
mainStatusBarTabs.show();
statusBarTerminal.setValue(Msg.Lang['shell.uploading'] + "...\n");
const code = MFile.getCode();
Socket.sendCommand({
obj: 'ArduShell',
func: 'upload',
args: [ index, boardType, port, code ]
});
},
end: function () {
$('#mixly-loader-div').css('display', 'none');
$("layui-layer-shade" + layerNum).remove();
$("#mixly-loader-btn").off("click");
$("#mixly-loader-btn").css('display', 'inline-block');
const mainWorkspace = Workspace.getMain();
const editor = mainWorkspace.getEditorsManager().getActive();
const code = editor.getCode();
statusBarTerminal.setValue(`${Msg.Lang['shell.compiling']}...\n`);
this.shell.compile(code)
.then((info) => {
this.endCallback(info.code, info.time);
})
.catch(Debug.error);
}
});
}
ArduShell.operateSuccess = (type, layerNum, port, baud, timeCostStr) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
layer.close(layerNum);
const value = statusBarTerminal.getValue();
let prefix = '';
if (value.lastIndexOf('\n') !== value.length - 1) {
prefix = '\n';
this.initUpload = function () {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
mainStatusBarTabs.changeTo('output');
mainStatusBarTabs.show();
statusBarTerminal.setValue(`${Msg.Lang['shell.uploading']}...\n`);
const port = Serial.getSelectedPortName();
const mainWorkspace = Workspace.getMain();
const editor = mainWorkspace.getEditorsManager().getActive();
const code = editor.getCode();
const statusBarSerial = mainStatusBarTabs.getStatusBarById(port);
const closePromise = statusBarSerial ? statusBarSerial.close() : Promise.resolve();
closePromise
.then(() => {
return this.shell.upload(port, code)
})
.then((info) => {
this.endCallback(info.code, info.time);
if (info.code || !Serial.portIsLegal(port)) {
return;
}
mainStatusBarTabs.add('serial', port);
mainStatusBarTabs.changeTo(port);
const statusBarSerial = mainStatusBarTabs.getStatusBarById(port);
statusBarSerial.open()
.then(() => {
const baudRates = code.match(/(?<=Serial.begin[\s]*\([\s]*)[0-9]*(?=[\s]*\))/g);
if (!baudRates.length) {
return statusBarSerial.setBaudRate(9600);
} else {
return statusBarSerial.setBaudRate(baudRates[0] - 0);
}
})
.catch(Debug.error);
})
.catch(Debug.error);
}
this.endCallback = function (code, time) {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
mainStatusBarTabs.changeTo('output');
let message = '';
if (code) {
message = (this.shell.isCompiling() ? Msg.Lang['shell.compileFailed'] : Msg.Lang['shell.uploadFailed']);
statusBarTerminal.addValue('==' + message + '==\n');
} else {
message = (this.shell.isCompiling() ? Msg.Lang['shell.compileSucc'] : Msg.Lang['shell.uploadSucc']);
statusBarTerminal.addValue(`==${message}(${Msg.Lang['shell.timeCost']} ${
dayjs.duration(time).format('HH:mm:ss.SSS')
})==\n`);
}
layer.msg(message, { time: 1000 });
}
}
statusBarTerminal.addValue(prefix);
const message = (type === 'compile' ? Msg.Lang['shell.compileSucc'] : Msg.Lang['shell.uploadSucc']);
statusBarTerminal.addValue("==" + message + "(" + Msg.Lang['shell.timeCost'] + " " + timeCostStr + ")==\n");
layer.msg(message, {
time: 1000
});
if (type === 'upload' && port) {
Serial.connect(port, baud - 0);
#running_ = false;
#upload_ = false;
#layerNum_ = null;
constructor() {}
async compile(code) {
return new Promise(async (resolve, reject) => {
this.#running_ = true;
this.#upload_ = false;
await this.showProgress();
const key = Boards.getSelectedBoardCommandParam();
const config = { key, code };
WebSocketArduShell.socket.emit('arduino.compile', config, (response) => {
const [error, result] = response;
this.hideProgress();
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
ArduShell.compiling = false;
ArduShell.uploading = false;
}
ArduShell.operateOnError = (type, layerNum, error) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
statusBarTerminal.addValue(error);
}
ArduShell.operateEndError = (type, layerNum, error) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
layer.close(layerNum);
const value = statusBarTerminal.getValue();
let prefix = '';
if (value.lastIndexOf('\n') !== value.length - 1) {
prefix = '\n';
async upload(port, code) {
return new Promise(async (resolve, reject) => {
this.#running_ = true;
this.#upload_ = true;
await this.showProgress();
const key = Boards.getSelectedBoardCommandParam();
const config = { key, code, port };
WebSocketArduShell.socket.emit('arduino.upload', config, (response) => {
const [error, result] = response;
this.hideProgress();
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
async kill() {
return new Promise(async (resolve, reject) => {
WebSocketArduShell.socket.emit('arduino.kill', (response) => {
const [error, result] = response;
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
async showProgress() {
return new Promise((resolve, reject) => {
this.#layerNum_ = layer.open({
type: 1,
title: `${this.isCompiling ? Msg.Lang['shell.compiling'] : Msg.Lang['shell.uploading']}...`,
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_NAV,
resize: false,
closeBtn: 0,
success: () => {
$('#mixly-loader-btn').off('click').click(() => {
$('#mixly-loader-btn').css('display', 'none');
layer.title(`${Msg.Lang['shell.aborting']}...`, this.layerNum);
this.kill().catch(Debug.error);
});
resolve();
},
end: function () {
$('#mixly-loader-btn').off('click');
$('#mixly-loader-btn').css('display', 'inline-block');
}
});
})
}
hideProgress() {
layer.close(this.#layerNum_);
}
isUploading() {
return this.#running_ && this.#upload_;
}
isCompiling() {
return this.#running_ && !this.#upload_;
}
statusBarTerminal.addValue(prefix);
error && statusBarTerminal.addValue(error + '\n');
const message = (type === 'compile' ? Msg.Lang['shell.compileFailed'] : Msg.Lang['shell.uploadFailed']);
statusBarTerminal.addValue("==" + message + "==\n");
ArduShell.compiling = false;
ArduShell.uploading = false;
}
/**
* @function 取消编译或上传
* @description 取消正在执行的编译或上传过程
* @return void
*/
ArduShell.cancel = function () {
Socket.sendCommand({
obj: 'ArduShell',
func: 'cancel',
args: []
});
}
ArduShell.addValue = function (data) {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
statusBarTerminal.addValue(data);
}
WebSocket.ArduShell = WebSocketArduShell;
});

View File

@@ -0,0 +1,316 @@
goog.loadJs('web', () => {
goog.require('Mixly.Serial');
goog.require('Mixly.Env');
goog.require('Mixly.Msg');
goog.require('Mixly.Debug');
goog.require('Mixly.Registry');
goog.require('Mixly.WebSocket');
goog.provide('Mixly.WebSocket.Serial');
const {
Serial,
Env,
Msg,
Debug,
Registry,
WebSocket
} = Mixly;
class WebSocketSerial extends Serial {
static {
this.eventRegistry = new Registry();
this.socket = null;
this.getConfig = function () {
return Serial.getConfig();
}
this.getSelectedPortName = function () {
return Serial.getSelectedPortName();
}
this.getCurrentPortsName = function () {
return Serial.getCurrentPortsName();
}
this.getPorts = async function () {
return new Promise((resolve, reject) => {
this.socket.emit('serial.getPorts', (response) => {
const [error, result] = response;
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
this.refreshPorts = function () {
this.getPorts()
.then((ports) => {
Serial.renderSelectBox(ports);
})
.catch(Debug.error);
}
this.init = function (socket) {
this.socket = socket;
socket.on('serial.attachEvent', () => {
this.refreshPorts();
});
socket.on('serial.detachEvent', () => {
this.refreshPorts();
});
socket.on('serial.bufferEvent', (port, buffer) => {
const eventName = `${port}-buffer`;
if (!this.eventRegistry.hasKey(eventName)) {
return;
}
const event = this.eventRegistry.getItem(eventName);
event(buffer);
});
socket.on('serial.stringEvent', (port, str) => {
const eventName = `${port}-string`;
if (!this.eventRegistry.hasKey(eventName)) {
return;
}
const event = this.eventRegistry.getItem(eventName);
event(str);
});
socket.on('serial.errorEvent', (port, error) => {
const eventName = `${port}-error`;
if (!this.eventRegistry.hasKey(eventName)) {
return;
}
const event = this.eventRegistry.getItem(eventName);
event(error);
});
socket.on('serial.openEvent', (port) => {
const eventName = `${port}-open`;
if (!this.eventRegistry.hasKey(eventName)) {
return;
}
const event = this.eventRegistry.getItem(eventName);
event();
});
socket.on('serial.closeEvent', (port, code) => {
const eventName = `${port}-close`;
if (!this.eventRegistry.hasKey(eventName)) {
return;
}
const event = this.eventRegistry.getItem(eventName);
event(code);
});
}
this.getSocket = function () {
return this.socket;
}
this.getEventRegistry = function () {
return this.eventRegistry;
}
}
constructor(port) {
super(port);
this.#addEventsListener_();
const socket = WebSocketSerial.getSocket();
socket.emit('serial.create', port);
}
#addEventsListener_() {
const port = this.getPortName();
const eventRegistry = WebSocketSerial.getEventRegistry();
eventRegistry.register(`${port}-buffer`, (buffer) => {
this.onBuffer(buffer);
});
eventRegistry.register(`${port}-string`, (str) => {
this.onString(str);
});
eventRegistry.register(`${port}-error`, (error) => {
this.onError(String(error));
this.onClose(1);
});
eventRegistry.register(`${port}-open`, () => {
this.onOpen();
});
eventRegistry.register(`${port}-close`, (code) => {
this.onClose(code);
});
}
async open(baud) {
return new Promise((resolve, reject) => {
const portsName = Serial.getCurrentPortsName();
const currentPort = this.getPortName();
if (!portsName.includes(currentPort)) {
reject('无可用串口');
return;
}
if (this.isOpened()) {
resolve();
return;
}
baud = baud ?? this.getBaudRate();
const socket = WebSocketSerial.getSocket();
socket.emit('serial.open', this.getPortName(), baud, (response) => {
const [error, result] = response;
if (error) {
this.onError(error);
reject(error);
} else {
super.open(baud);
this.setBaudRate(baud);
resolve(result);
}
});
});
}
async close() {
return new Promise((resolve, reject) => {
if (!this.isOpened()) {
resolve();
return;
}
super.close();
const socket = WebSocketSerial.getSocket();
socket.emit('serial.close', this.getPortName(), (response) => {
const [error, result] = response;
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
async setBaudRate(baud) {
return new Promise((resolve, reject) => {
if (!this.isOpened()
|| this.getBaudRate() === baud
|| !this.baudRateIsLegal(baud)) {
resolve();
return;
}
const socket = WebSocketSerial.getSocket();
socket.emit('serial.setBaudRate', this.getPortName(), baud, (response) => {
const [error,] = response;
if (error) {
reject(error);
} else {
super.setBaudRate(baud);
this.setDTRAndRTS(this.getDTR(), this.getRTS()).finally(resolve);
}
});
});
}
async send(data) {
return new Promise((resolve, reject) => {
if (!this.isOpened()) {
resolve();
return;
}
const socket = WebSocketSerial.getSocket();
socket.emit('serial.send', this.getPortName(), data, (response) => {
const [error, result] = response;
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
async sendString(str) {
return this.send(str);
}
async sendBuffer(buffer) {
return this.send(buffer);
}
async setDTRAndRTS(dtr, rts) {
return new Promise((resolve, reject) => {
if (!this.isOpened()) {
resolve();
return;
}
const socket = WebSocketSerial.getSocket();
socket.emit('serial.setDTRAndRTS', this.getPortName(), dtr, rts, (response) => {
const [error, result] = response;
if (error) {
reject(error);
} else {
super.setDTRAndRTS(dtr, rts);
resolve(result);
}
});
});
}
async setDTR(dtr) {
return this.setDTRAndRTS(dtr, this.getRTS());
}
async setRTS(rts) {
return this.setDTRAndRTS(this.getDTR(), rts);
}
onBuffer(buffer) {
super.onBuffer(buffer);
for (let i = 0; i < buffer.length; i++) {
super.onByte(buffer[i]);
}
const string = this.decodeBuffer(buffer);
if (!string) {
return;
}
for (let char of string) {
super.onChar(char);
}
}
async dispose() {
return new Promise((resolve, reject) => {
const port = this.getPortName();
const eventRegistry = WebSocketSerial.getEventRegistry();
eventRegistry.unregister(`${port}-buffer`);
eventRegistry.unregister(`${port}-string`);
eventRegistry.unregister(`${port}-error`);
eventRegistry.unregister(`${port}-open`);
eventRegistry.unregister(`${port}-close`);
super.dispose()
.then(() => {
const socket = WebSocketSerial.getSocket();
socket.emit('serial.dispose', port, ([error, result]) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
})
.catch(reject);
})
}
}
WebSocket.Serial = WebSocketSerial;
});

View File

@@ -1,294 +1,25 @@
goog.loadJs('web', () => {
goog.require('path');
goog.require('Mixly.Env');
goog.require('Mixly.Config');
goog.require('Mixly.Boards');
goog.require('Mixly.Command');
goog.require('Mixly.MJSON');
goog.require('Mixly.MArray');
goog.require('Mixly.LayerExt');
goog.require('io');
goog.require('Mixly.WebSocket');
goog.require('Mixly.WebSocket.Serial');
goog.require('Mixly.WebSocket.ArduShell');
goog.provide('Mixly.WebSocket.Socket');
const {
Env,
Config,
Boards,
Command,
MJSON,
MArray,
LayerExt
} = Mixly;
const { WebSocket } = Mixly;
const { Socket, Serial, ArduShell } = WebSocket;
const { BOARD, SELECTED_BOARD, SOFTWARE } = Config;
const { Socket } = Mixly.WebSocket;
Socket.obj = null;
Socket.url = 'ws://127.0.0.1/socket';
Socket.jsonArr = [];
Socket.connected = false;
Socket.initFunc = null;
Socket.debug = SOFTWARE.debug;
BOARD.server = { ...SOFTWARE.webSocket };
let { hostname, protocol, port } = window.location;
if (protocol === 'http:') {
Socket.protocol = 'ws:';
} else {
Socket.protocol = 'wss:';
}
if (port) {
port = ':' + port;
}
Socket.url = Socket.protocol + '//' + hostname + port + '/socket';
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); //这里设置重连间隔(ms)
}
//心跳检测
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;
let WS = Socket;
this.timeoutObj = setInterval(() => {
if (count < 3) {
if (WS.obj.readyState === 1) {
WS.obj.send('HeartBeat');
console.info(`HeartBeat第${count + 1}`);
}
count++;
} else {
clearInterval(this.timeoutObj);
count = 0;
if (WS.obj.readyState === 0 && WS.obj.readyState === 1) {
WS.obj.close();
}
}
}, 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);
let WS = Socket;
WS.obj = new WebSocket(WS.url);
WS.obj.onopen = () => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
console.log('已连接' + WS.url);
mainStatusBarTabs.show();
mainStatusBarTabs.changeTo('output');
statusBarTerminal.setValue(WS.url + '连接成功\n');
WS.connected = true;
Socket.toggleUIToolbar(true);
Socket.initFunc = doFunc;
reconectNum = 0;
timeoutFlag = false;
clearTimeout(timeoutSet);
heartCheck.reset().start();
onopenFunc(WS);
};
WS.obj.onmessage = (event) => {
heartCheck.reset().start();
let command = Command.parse(event.data);
command = MJSON.decode(command);
if (Socket.debug)
console.log('receive -> ', event.data);
/*if (command && command.obj && command.function) {
if (command.type === 1) {
let args = command.args ?? [];
try {
if (window[command.obj][command.function])
window[command.obj][command.function](...args);
} catch (e) {
console.log(e);
}
}
}*/
Command.run(command);
};
WS.obj.onerror = (event) => {
console.log('WebSocket error: ', event);
reconnect(); //重连
};
WS.obj.onclose = (event) => {
const { mainStatusBarTabs } = Mixly;
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
WS.connected = false;
console.log('已断开' + WS.url);
mainStatusBarTabs.show();
mainStatusBarTabs.changeTo('output');
statusBarTerminal.setValue(WS.url + '连接断开,请在设置中重新连接\n');
let ports = [ ...mainStatusBarTabs.statusBarIndexToIds ];
MArray.remove(ports, 'output');
for (let i = 0; i < ports.length; i++) {
const statusBarSerial = mainStatusBarTabs.getStatusBarById(ports[i]);
statusBarSerial.close(ports[i]);
}
Socket.toggleUIToolbar(false);
layer.closeAll();
Mixly.WebSocket.BU.burning = false;
Mixly.WebSocket.BU.uploading = false;
Mixly.WebSocket.ArduShell.compiling = false;
Mixly.WebSocket.ArduShell.uploading = false;
console.info(`关闭`, event.code);
if (event.code !== 1000) {
timeoutFlag = false;
clearTimeout(timeoutSet);
reconnect();
} else {
clearInterval(heartCheck.timeoutObj);
clearTimeout(heartCheck.serverTimeoutObj);
}
}
}
Socket.sendCommand = (command) => {
let WS = Mixly.WebSocket.Socket;
if (!WS.connected) {
layer.msg('未连接' + WS.url, {time: 1000});
return;
}
let commandStr = '';
try {
commandStr = JSON.stringify(MJSON.encode(command));
if (Socket.debug)
console.log('send -> ', commandStr);
} catch (e) {
console.log(e);
return;
}
WS.obj.send(commandStr);
}
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.init = function () {
const socket = io('wss://127.0.0.1:4000', {
path: '/mixly-socket/',
reconnectionDelayMax: 10000,
transports: ['websocket'],
protocols: ['my-protocol-v1']
});
}
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.close();
});
}
Socket.toggleUIToolbar = (connected) => {
try {
if (connected) {
$('#socket-connect-btn').html(Blockly.Msg.MSG['disconnect']);
$('#socket-connect-btn').removeClass('icon-link').addClass('icon-unlink');
} else {
$('#socket-connect-btn').html(Blockly.Msg.MSG['connect']);
$('#socket-connect-btn').removeClass('icon-unlink').addClass('icon-link');
}
} catch (e) {
console.log(e);
}
}
Socket.updateSelectedBoardConfig = (info) => {
Env.currentPlatform = info.currentPlatform;
info.clientPath = info.clientPath.replaceAll('\\', '/');
Env.clientPath = info.clientPath;
info.appPath = info.appPath.replaceAll('\\', '/');
Env.srcDirPath = info.appPath;
Env.indexDirPath = path.join(Env.srcDirPath, 'boards');
Env.boardDirPath = path.join(Env.srcDirPath, BOARD.boardIndex, '../');
Env.python3Path = info.python3Path;
const boardType = Boards.getSelectedBoardName();
Boards.changeTo(boardType);
Serial.init(socket);
ArduShell.init(socket);
}
});