Update: WebSocket支持MicroPython板卡烧录固件及上传程序
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -10,11 +10,17 @@ export default function addBoardFSItem () {
|
|||||||
menu.add({
|
menu.add({
|
||||||
weight: 2,
|
weight: 2,
|
||||||
type: 'sep1',
|
type: 'sep1',
|
||||||
|
preconditionFn: () => {
|
||||||
|
return goog.isElectron;
|
||||||
|
},
|
||||||
data: '---------'
|
data: '---------'
|
||||||
});
|
});
|
||||||
menu.add({
|
menu.add({
|
||||||
weight: 3,
|
weight: 3,
|
||||||
type: 'filesystem-tool',
|
type: 'filesystem-tool',
|
||||||
|
preconditionFn: () => {
|
||||||
|
return goog.isElectron;
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
isHtmlName: true,
|
isHtmlName: true,
|
||||||
name: ContextMenu.getItem(Msg.BOARD_FS, ''),
|
name: ContextMenu.getItem(Msg.BOARD_FS, ''),
|
||||||
|
|||||||
@@ -10,11 +10,17 @@ export default function addBoardFSItem () {
|
|||||||
menu.add({
|
menu.add({
|
||||||
weight: 2,
|
weight: 2,
|
||||||
type: 'sep1',
|
type: 'sep1',
|
||||||
|
preconditionFn: () => {
|
||||||
|
return goog.isElectron;
|
||||||
|
},
|
||||||
data: '---------'
|
data: '---------'
|
||||||
});
|
});
|
||||||
menu.add({
|
menu.add({
|
||||||
weight: 3,
|
weight: 3,
|
||||||
type: 'filesystem-tool',
|
type: 'filesystem-tool',
|
||||||
|
preconditionFn: () => {
|
||||||
|
return goog.isElectron;
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
isHtmlName: true,
|
isHtmlName: true,
|
||||||
name: ContextMenu.getItem(Msg.BOARD_FS, ''),
|
name: ContextMenu.getItem(Msg.BOARD_FS, ''),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ goog.require('Mixly.Web.Serial');
|
|||||||
goog.require('Mixly.WebSocket.File');
|
goog.require('Mixly.WebSocket.File');
|
||||||
goog.require('Mixly.WebSocket.Serial');
|
goog.require('Mixly.WebSocket.Serial');
|
||||||
goog.require('Mixly.WebSocket.ArduShell');
|
goog.require('Mixly.WebSocket.ArduShell');
|
||||||
|
goog.require('Mixly.WebSocket.BU');
|
||||||
goog.provide('Mixly.App');
|
goog.provide('Mixly.App');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -181,7 +182,7 @@ class App extends Component {
|
|||||||
id: 'arduino-compile-btn',
|
id: 'arduino-compile-btn',
|
||||||
displayText: Msg.Lang['nav.btn.compile'],
|
displayText: Msg.Lang['nav.btn.compile'],
|
||||||
preconditionFn: () => {
|
preconditionFn: () => {
|
||||||
if (!goog.isElectron && !Env.hasSocketServer && !env.hasCompiler) {
|
if (!goog.isElectron && !Env.hasSocketServer && !Env.hasCompiler) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SELECTED_BOARD?.nav?.compile || !SELECTED_BOARD?.nav?.upload) {
|
if (!SELECTED_BOARD?.nav?.compile || !SELECTED_BOARD?.nav?.upload) {
|
||||||
@@ -209,7 +210,7 @@ class App extends Component {
|
|||||||
id: 'arduino-upload-btn',
|
id: 'arduino-upload-btn',
|
||||||
displayText: Msg.Lang['nav.btn.upload'],
|
displayText: Msg.Lang['nav.btn.upload'],
|
||||||
preconditionFn: () => {
|
preconditionFn: () => {
|
||||||
if (!goog.isElectron && !Env.hasSocketServer && !env.hasCompiler) {
|
if (!goog.isElectron && !Env.hasSocketServer && !Env.hasCompiler) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SELECTED_BOARD?.nav?.compile || !SELECTED_BOARD?.nav?.upload) {
|
if (!SELECTED_BOARD?.nav?.compile || !SELECTED_BOARD?.nav?.upload) {
|
||||||
|
|||||||
@@ -244,7 +244,9 @@ Boards.changeTo = (boardName) => {
|
|||||||
outObj.volume = "CIRCUITPY";
|
outObj.volume = "CIRCUITPY";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outObj.filePath = MString.tpl(outObj.filePath, pathObj);
|
if (!Env.hasSocketServer) {
|
||||||
|
outObj.filePath = MString.tpl(outObj.filePath, pathObj);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'command':
|
case 'command':
|
||||||
let pyToolsPath = "{srcPath}/tools/python/";
|
let pyToolsPath = "{srcPath}/tools/python/";
|
||||||
@@ -256,8 +258,10 @@ Boards.changeTo = (boardName) => {
|
|||||||
'stm32bl': 'stm32bl.py',
|
'stm32bl': 'stm32bl.py',
|
||||||
'ampy': 'ampy/cli.py'
|
'ampy': 'ampy/cli.py'
|
||||||
};
|
};
|
||||||
for (let key in pyTools) {
|
if (!Env.hasSocketServer) {
|
||||||
obj[key] = Env.python3Path + "\" \"" + pyToolsPath + pyTools[key];
|
for (let key in pyTools) {
|
||||||
|
obj[key] = Env.python3Path + "\" \"" + pyToolsPath + pyTools[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (outObj.reset) {
|
if (outObj.reset) {
|
||||||
let resetStr = '{}';
|
let resetStr = '{}';
|
||||||
@@ -270,7 +274,9 @@ Boards.changeTo = (boardName) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
outObj.command = MString.tpl(outObj.command, obj);
|
outObj.command = MString.tpl(outObj.command, obj);
|
||||||
outObj.command = MString.tpl(outObj.command, pathObj);
|
if (!Env.hasSocketServer) {
|
||||||
|
outObj.command = MString.tpl(outObj.command, pathObj);
|
||||||
|
}
|
||||||
if (outObj.special && outObj.special instanceof Array) {
|
if (outObj.special && outObj.special instanceof Array) {
|
||||||
for (let key in outObj.special) {
|
for (let key in outObj.special) {
|
||||||
if (!outObj.special[key]?.name
|
if (!outObj.special[key]?.name
|
||||||
@@ -278,23 +284,31 @@ Boards.changeTo = (boardName) => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
outObj.special[key].command = MString.tpl(outObj.special[key].command, obj);
|
outObj.special[key].command = MString.tpl(outObj.special[key].command, obj);
|
||||||
outObj.special[key].command = MString.tpl(outObj.special[key].command, pathObj);
|
if (!Env.hasSocketServer) {
|
||||||
|
outObj.special[key].command = MString.tpl(outObj.special[key].command, pathObj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (value.type === 'upload' && (goog.isElectron || Env.hasSocketServer) && outObj.copyLib) {
|
if (value.type === 'upload' && (goog.isElectron || Env.hasSocketServer) && outObj.copyLib) {
|
||||||
if (outObj.libPath) {
|
if (outObj.libPath) {
|
||||||
let libPath = [];
|
if (!Env.hasSocketServer) {
|
||||||
for (let dirPath of outObj.libPath) {
|
let libPath = [];
|
||||||
libPath.push(MString.tpl(dirPath, pathObj));
|
for (let dirPath of outObj.libPath) {
|
||||||
|
libPath.push(MString.tpl(dirPath, pathObj));
|
||||||
|
}
|
||||||
|
outObj.libPath = libPath;
|
||||||
}
|
}
|
||||||
outObj.libPath = libPath;
|
|
||||||
} else {
|
} else {
|
||||||
outObj.libPath = [ path.join(Env.boardDirPath, 'build/lib/') ];
|
if (Env.hasSocketServer) {
|
||||||
|
outObj.libPath = [ 'build/lib/' ];
|
||||||
|
} else {
|
||||||
|
outObj.libPath = [ path.join(Env.boardDirPath, 'build/lib/') ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.type === 'upload' && (goog.isElectron || Env.hasSocketServer)) {
|
if (value.type === 'upload' && (goog.isElectron && !Env.hasSocketServer)) {
|
||||||
if (outObj.filePath) {
|
if (outObj.filePath) {
|
||||||
outObj.filePath = MString.tpl(outObj.filePath, pathObj);
|
outObj.filePath = MString.tpl(outObj.filePath, pathObj);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -264,7 +264,11 @@ class StatusBarSerial extends PageBase {
|
|||||||
this.stopRead();
|
this.stopRead();
|
||||||
this.#timer_ && clearTimeout(this.#timer_);
|
this.#timer_ && clearTimeout(this.#timer_);
|
||||||
this.#timer_ = null;
|
this.#timer_ = null;
|
||||||
if (this.isDisposed() || !this.isOpened()) {
|
if (this.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.isOpened()) {
|
||||||
|
this.setValue(`${String(error)}\n`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setValue(`${this.getValue() + this.#valueTemp_}\n${String(error)}\n`);
|
this.setValue(`${this.getValue() + this.#valueTemp_}\n${String(error)}\n`);
|
||||||
|
|||||||
@@ -49,7 +49,8 @@
|
|||||||
"Mixly.Web.Serial",
|
"Mixly.Web.Serial",
|
||||||
"Mixly.WebSocket.File",
|
"Mixly.WebSocket.File",
|
||||||
"Mixly.WebSocket.Serial",
|
"Mixly.WebSocket.Serial",
|
||||||
"Mixly.WebSocket.ArduShell"
|
"Mixly.WebSocket.ArduShell",
|
||||||
|
"Mixly.WebSocket.BU"
|
||||||
],
|
],
|
||||||
"provide": [
|
"provide": [
|
||||||
"Mixly.App"
|
"Mixly.App"
|
||||||
@@ -1736,15 +1737,13 @@
|
|||||||
"path": "/web-socket/burn-upload.js",
|
"path": "/web-socket/burn-upload.js",
|
||||||
"require": [
|
"require": [
|
||||||
"layui",
|
"layui",
|
||||||
"Mixly.Config",
|
"dayjs.duration",
|
||||||
|
"Mixly.Debug",
|
||||||
"Mixly.LayerExt",
|
"Mixly.LayerExt",
|
||||||
"Mixly.Env",
|
|
||||||
"Mixly.Boards",
|
|
||||||
"Mixly.MFile",
|
|
||||||
"Mixly.MString",
|
|
||||||
"Mixly.Msg",
|
"Mixly.Msg",
|
||||||
"Mixly.WebSocket.Serial",
|
"Mixly.Config",
|
||||||
"Mixly.WebSocket.Socket"
|
"Mixly.Workspace",
|
||||||
|
"Mixly.WebSocket.Serial"
|
||||||
],
|
],
|
||||||
"provide": [
|
"provide": [
|
||||||
"Mixly.WebSocket.BU"
|
"Mixly.WebSocket.BU"
|
||||||
@@ -1780,7 +1779,8 @@
|
|||||||
"Mixly.StatusBarsManager",
|
"Mixly.StatusBarsManager",
|
||||||
"Mixly.WebSocket",
|
"Mixly.WebSocket",
|
||||||
"Mixly.WebSocket.Serial",
|
"Mixly.WebSocket.Serial",
|
||||||
"Mixly.WebSocket.ArduShell"
|
"Mixly.WebSocket.ArduShell",
|
||||||
|
"Mixly.WebSocket.BU"
|
||||||
],
|
],
|
||||||
"provide": [
|
"provide": [
|
||||||
"Mixly.WebSocket.Socket"
|
"Mixly.WebSocket.Socket"
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ class WebSocketArduShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.initCompile = function () {
|
this.initCompile = function () {
|
||||||
|
if (!this.mixlySocket.isConnected()) {
|
||||||
|
layer.msg('服务端已离线', { time: 1000 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
const { mainStatusBarTabs } = Mixly;
|
const { mainStatusBarTabs } = Mixly;
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
mainStatusBarTabs.changeTo('output');
|
mainStatusBarTabs.changeTo('output');
|
||||||
@@ -71,17 +75,27 @@ class WebSocketArduShell {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Debug.error(error);
|
Debug.error(error);
|
||||||
statusBarTerminal.addValue(`==${Msg.Lang['shell.compileFailed']}==\n`);
|
statusBarTerminal.addValue(`\n==${Msg.Lang['shell.compileFailed']}==\n`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initUpload = function () {
|
this.initUpload = function () {
|
||||||
|
if (!this.mixlySocket.isConnected()) {
|
||||||
|
layer.msg('服务端已离线', { time: 1000 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const port = Serial.getSelectedPortName();
|
||||||
|
if (!port) {
|
||||||
|
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
|
||||||
|
time: 1000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const { mainStatusBarTabs } = Mixly;
|
const { mainStatusBarTabs } = Mixly;
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
mainStatusBarTabs.changeTo('output');
|
mainStatusBarTabs.changeTo('output');
|
||||||
mainStatusBarTabs.show();
|
mainStatusBarTabs.show();
|
||||||
statusBarTerminal.setValue(`${Msg.Lang['shell.uploading']}...\n`);
|
statusBarTerminal.setValue(`${Msg.Lang['shell.uploading']}...\n`);
|
||||||
const port = Serial.getSelectedPortName();
|
|
||||||
const mainWorkspace = Workspace.getMain();
|
const mainWorkspace = Workspace.getMain();
|
||||||
const editor = mainWorkspace.getEditorsManager().getActive();
|
const editor = mainWorkspace.getEditorsManager().getActive();
|
||||||
const code = editor.getCode();
|
const code = editor.getCode();
|
||||||
@@ -98,6 +112,7 @@ class WebSocketArduShell {
|
|||||||
}
|
}
|
||||||
mainStatusBarTabs.add('serial', port);
|
mainStatusBarTabs.add('serial', port);
|
||||||
mainStatusBarTabs.changeTo(port);
|
mainStatusBarTabs.changeTo(port);
|
||||||
|
const statusBarSerial = mainStatusBarTabs.getStatusBarById(port);
|
||||||
statusBarSerial.open()
|
statusBarSerial.open()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const baudRates = code.match(/(?<=Serial.begin[\s]*\([\s]*)[0-9]*(?=[\s]*\))/g);
|
const baudRates = code.match(/(?<=Serial.begin[\s]*\([\s]*)[0-9]*(?=[\s]*\))/g);
|
||||||
@@ -111,7 +126,7 @@ class WebSocketArduShell {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Debug.error(error);
|
Debug.error(error);
|
||||||
statusBarTerminal.addValue(`==${Msg.Lang['shell.uploadFailed']}==\n`);
|
statusBarTerminal.addValue(`\n==${Msg.Lang['shell.uploadFailed']}==\n`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,506 +1,278 @@
|
|||||||
goog.loadJs('web', () => {
|
goog.loadJs('web', () => {
|
||||||
|
|
||||||
goog.require('layui');
|
goog.require('layui');
|
||||||
goog.require('Mixly.Config');
|
goog.require('dayjs.duration');
|
||||||
|
goog.require('Mixly.Debug');
|
||||||
goog.require('Mixly.LayerExt');
|
goog.require('Mixly.LayerExt');
|
||||||
goog.require('Mixly.Env');
|
|
||||||
goog.require('Mixly.Boards');
|
|
||||||
goog.require('Mixly.MFile');
|
|
||||||
goog.require('Mixly.MString');
|
|
||||||
goog.require('Mixly.Msg');
|
goog.require('Mixly.Msg');
|
||||||
|
goog.require('Mixly.Env');
|
||||||
|
goog.require('Mixly.Config');
|
||||||
|
goog.require('Mixly.Workspace');
|
||||||
goog.require('Mixly.WebSocket.Serial');
|
goog.require('Mixly.WebSocket.Serial');
|
||||||
goog.require('Mixly.WebSocket.Socket');
|
|
||||||
goog.provide('Mixly.WebSocket.BU');
|
goog.provide('Mixly.WebSocket.BU');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Config,
|
Debug,
|
||||||
LayerExt,
|
LayerExt,
|
||||||
|
Config,
|
||||||
|
Msg,
|
||||||
Env,
|
Env,
|
||||||
Boards,
|
Workspace,
|
||||||
MFile,
|
WebSocket
|
||||||
MString,
|
|
||||||
Msg
|
|
||||||
} = Mixly;
|
} = Mixly;
|
||||||
|
|
||||||
const { BU, Serial, Socket } = Mixly.WebSocket;
|
const { SELECTED_BOARD } = Config;
|
||||||
const { BOARD, SELECTED_BOARD } = Config;
|
|
||||||
|
|
||||||
const { form } = layui;
|
const { Serial } = WebSocket;
|
||||||
|
|
||||||
BU.uploading = false;
|
|
||||||
|
|
||||||
BU.burning = false;
|
class WebSocketBU {
|
||||||
|
static {
|
||||||
|
this.mixlySocket = null;
|
||||||
|
this.socket = null;
|
||||||
|
this.shell = null;
|
||||||
|
|
||||||
BU.shell = null;
|
this.getSocket = function () {
|
||||||
|
return this.socket;
|
||||||
/**
|
|
||||||
* @function 根据传入的stdout判断磁盘数量并选择对应操作
|
|
||||||
* @param type {string} 值为'burn' | 'upload'
|
|
||||||
* @param stdout {string} 磁盘名称字符串,形如'G:K:F:'
|
|
||||||
* @param startPath {string} 需要拷贝的文件路径
|
|
||||||
* @return {void}
|
|
||||||
**/
|
|
||||||
BU.checkNumOfDisks = function (type, stdout, startPath) {
|
|
||||||
let wmicResult = stdout;
|
|
||||||
wmicResult = wmicResult.replace(/\s+/g, "");
|
|
||||||
wmicResult = wmicResult.replace("DeviceID", "");
|
|
||||||
// wmicResult = 'G:K:F:';
|
|
||||||
let result = wmicResult.split(':');
|
|
||||||
let pathAdd = (Env.currentPlatform === "win32") ? ':' : '';
|
|
||||||
if (stdout.indexOf(":") != stdout.lastIndexOf(":")) {
|
|
||||||
let form = layui.form;
|
|
||||||
let devicesName = $('#mixly-selector-type');
|
|
||||||
let oldDevice = $('#mixly-selector-type option:selected').val();
|
|
||||||
devicesName.empty();
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
|
||||||
if (result[i]) {
|
|
||||||
if (oldDevice == result[i] + pathAdd) {
|
|
||||||
devicesName.append('<option value="' + result[i] + pathAdd + '" selected>' + result[i] + pathAdd + '</option>');
|
|
||||||
} else {
|
|
||||||
devicesName.append('<option value="' + result[i] + pathAdd + '">' + result[i] + pathAdd + '</option>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
form.render();
|
|
||||||
let initBtnClicked = false;
|
|
||||||
const layerNum = layer.open({
|
|
||||||
type: 1,
|
|
||||||
id: "serial-select",
|
|
||||||
title: Msg.Lang['检测到多个同类型设备,请选择:'],
|
|
||||||
area: ['350px', '150px'],
|
|
||||||
content: $('#mixly-selector-div'),
|
|
||||||
shade: LayerExt.SHADE_ALL,
|
|
||||||
resize: false,
|
|
||||||
closeBtn: 0,
|
|
||||||
success: function (layero) {
|
|
||||||
$('#serial-select').css('height', '195px');
|
|
||||||
$(".layui-layer-page").css("z-index","198910151");
|
|
||||||
$("#mixly-selector-btn1").off("click").click(() => {
|
|
||||||
layer.close(layerNum);
|
|
||||||
BU.cancel();
|
|
||||||
});
|
|
||||||
$("#mixly-selector-btn2").off("click").click(() => {
|
|
||||||
layer.close(layerNum);
|
|
||||||
initBtnClicked = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
end: function () {
|
|
||||||
$('#mixly-selector-div').css('display', 'none');
|
|
||||||
$("#layui-layer-shade" + layerNum).remove();
|
|
||||||
if (initBtnClicked) {
|
|
||||||
BU.initWithDropdownBox(type, startPath);
|
|
||||||
}
|
|
||||||
$("#mixly-selector-btn1").off("click");
|
|
||||||
$("#mixly-selector-btn2").off("click");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const layerNum = layer.open({
|
|
||||||
type: 1,
|
|
||||||
title: (type === 'burn'? Msg.Lang['shell.burning'] : Msg.Lang['shell.uploading']) + '...',
|
|
||||||
content: $('#mixly-loader-div'),
|
|
||||||
shade: LayerExt.SHADE_NAV,
|
|
||||||
resize: false,
|
|
||||||
closeBtn: 0,
|
|
||||||
success: function (layero, index) {
|
|
||||||
BU.copyFiles(type, index, startPath, result[0] + pathAdd + '/');
|
|
||||||
$("#mixly-loader-btn").off("click").click(() => {
|
|
||||||
layer.close(index);
|
|
||||||
BU.cancel();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
end: function () {
|
|
||||||
$('#mixly-selector-div').css('display', 'none');
|
|
||||||
$("#layui-layer-shade" + layerNum).remove();
|
|
||||||
$("#mixly-loader-btn").off("click");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BU.copyFiles = (type, layerNum, startPath, desPath) => {
|
this.getMixlySocket = function () {
|
||||||
const code = MFile.getCode();
|
return this.mixlySocket;
|
||||||
const {
|
|
||||||
copyLib = false,
|
|
||||||
libPath = []
|
|
||||||
} = SELECTED_BOARD.upload;
|
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'copyFiles',
|
|
||||||
args: [ type, layerNum, startPath, desPath, code, copyLib, libPath ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BU.operateSuccess = (type, layerNum, port) => {
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
|
||||||
layer.close(layerNum);
|
|
||||||
const message = (type === 'burn'? Msg.Lang['shell.burnSucc'] : Msg.Lang['shell.uploadSucc']);
|
|
||||||
layer.msg(message, {
|
|
||||||
time: 1000
|
|
||||||
});
|
|
||||||
const value = statusBarTerminal.getValue();
|
|
||||||
let prefix = '';
|
|
||||||
if (value.lastIndexOf('\n') !== value.length - 1) {
|
|
||||||
prefix = '\n';
|
|
||||||
}
|
|
||||||
statusBarTerminal.addValue(prefix + `==${message}==\n`);
|
|
||||||
if (type === 'upload' && (Serial.uploadPorts.length === 1 || port)) {
|
|
||||||
Serial.connect(port ?? Serial.uploadPorts[0].name, null);
|
|
||||||
}
|
|
||||||
BU.burning = false;
|
|
||||||
BU.uploading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BU.operateError = (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';
|
|
||||||
}
|
|
||||||
statusBarTerminal.addValue(prefix + error + '\n');
|
|
||||||
console.log(error);
|
|
||||||
BU.burning = false;
|
|
||||||
BU.uploading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BU.noDevice = () => {
|
|
||||||
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
|
|
||||||
time: 1000
|
|
||||||
});
|
|
||||||
BU.burning = false;
|
|
||||||
BU.uploading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 判断当前环境,以开始一个上传过程
|
|
||||||
* @param type {string} 值为'burn' | 'upload'
|
|
||||||
* @param startPath {string} 需要拷贝的文件或文件夹的路径
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
BU.initWithDropdownBox = function (type, startPath) {
|
|
||||||
const layerNum = layer.open({
|
|
||||||
type: 1,
|
|
||||||
title: (type === 'burn'? Msg.Lang['shell.burning'] : 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(() => {
|
|
||||||
layer.close(index);
|
|
||||||
BU.cancel();
|
|
||||||
});
|
|
||||||
const desPath = $('#mixly-selector-type option:selected').val();
|
|
||||||
BU.copyFiles(type, index, startPath, desPath);
|
|
||||||
},
|
|
||||||
end: function () {
|
|
||||||
$('#mixly-loader-div').css('display', 'none');
|
|
||||||
$("#layui-layer-shade" + layerNum).remove();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.init = function (mixlySocket) {
|
||||||
* @function 取消烧录或上传
|
this.mixlySocket = mixlySocket;
|
||||||
* @return {void}
|
this.socket = mixlySocket.getSocket();
|
||||||
*/
|
this.shell = new WebSocketBU();
|
||||||
BU.cancel = function () {
|
const socket = this.socket;
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'cancel',
|
|
||||||
args: []
|
|
||||||
});
|
|
||||||
if (BU.uploading) {
|
|
||||||
BU.uploading = false;
|
|
||||||
layer.msg(Msg.Lang['shell.uploadCanceled'], {
|
|
||||||
time: 1000
|
|
||||||
});
|
|
||||||
} else if (BU.burning) {
|
|
||||||
BU.burning = false;
|
|
||||||
layer.msg(Msg.Lang['shell.burnCanceled'], {
|
|
||||||
time: 1000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
socket.on('micropython.dataEvent', (data) => {
|
||||||
* @function 开始一个烧录过程
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
BU.initBurn = function () {
|
|
||||||
Socket.connect((WS) => {
|
|
||||||
layer.closeAll();
|
|
||||||
}, () => {
|
|
||||||
if (BU.burning) return;
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
|
||||||
const { burn } = SELECTED_BOARD;
|
|
||||||
statusBarTerminal.setValue('');
|
|
||||||
mainStatusBarTabs.changeTo("output");
|
|
||||||
mainStatusBarTabs.show();
|
|
||||||
BU.burning = true;
|
|
||||||
BU.uploading = false;
|
|
||||||
if (burn.type === 'volume') {
|
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'getDisksWithVolumesName',
|
|
||||||
args: [ 'burn', burn.volume, burn.filePath ]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const port = Serial.getSelectedPortName();
|
|
||||||
BU.burnWithPort(port, burn.command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 开始一个上传过程
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
BU.initUpload = function () {
|
|
||||||
Socket.connect((WS) => {
|
|
||||||
layer.closeAll();
|
|
||||||
}, () => {
|
|
||||||
if (BU.uploading) return;
|
|
||||||
const { upload } = SELECTED_BOARD;
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
|
||||||
statusBarTerminal.setValue('');
|
|
||||||
mainStatusBarTabs.changeTo("output");
|
|
||||||
mainStatusBarTabs.show();
|
|
||||||
BU.burning = false;
|
|
||||||
BU.uploading = true;
|
|
||||||
if (upload.type === "volume") {
|
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'getDisksWithVolumesName',
|
|
||||||
args: [ 'upload', upload.volume, upload.filePath ]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const port = Serial.getSelectedPortName();
|
|
||||||
BU.uploadWithPort(port, upload.command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 通过cmd烧录
|
|
||||||
* @param layerNum {number} 烧录或上传加载弹窗的编号,用于关闭此弹窗
|
|
||||||
* @param port {string} 所选择的串口
|
|
||||||
* @param command {string} 需要执行的指令
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
BU.burnByCmd = function (layerNum, port, command) {
|
|
||||||
const newCommand = MString.tpl(command, { com: port });
|
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'burnByCmd',
|
|
||||||
args: [ layerNum, port, newCommand ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 通过cmd上传
|
|
||||||
* @param layerNum {number} 烧录或上传加载弹窗的编号,用于关闭此弹窗
|
|
||||||
* @param port {string} 所选择的串口
|
|
||||||
* @param command {string} 需要执行的指令
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
BU.uploadByCmd = function (layerNum, port, command) {
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
|
||||||
const newCommand = MString.tpl(command, { com: port });
|
|
||||||
const { upload } = SELECTED_BOARD;
|
|
||||||
const {
|
|
||||||
filePath,
|
|
||||||
copyLib = false,
|
|
||||||
libPath = []
|
|
||||||
} = upload;
|
|
||||||
const code = MFile.getCode();
|
|
||||||
statusBarTerminal.addValue(Msg.Lang['shell.uploading'] + '...\n');
|
|
||||||
Socket.sendCommand({
|
|
||||||
obj: 'BU',
|
|
||||||
func: 'uploadByCmd',
|
|
||||||
args: [ layerNum, port, newCommand, code, filePath, copyLib, libPath ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 特殊固件的烧录
|
|
||||||
* @return {void}
|
|
||||||
**/
|
|
||||||
BU.burnWithSpecialBin = () => {
|
|
||||||
const devNames = $('#mixly-selector-type');
|
|
||||||
let oldDevice = $('#mixly-selector-type option:selected').val();
|
|
||||||
devNames.empty();
|
|
||||||
let firmwareList = BOARD.burn.special;
|
|
||||||
let firmwareObj = {};
|
|
||||||
for (let i = 0; i < firmwareList.length; i++)
|
|
||||||
firmwareObj[firmwareList[i].name] = firmwareList[i].command;
|
|
||||||
firmwareList.map(firmware => {
|
|
||||||
if (!firmware?.name && !firmware?.command) return;
|
|
||||||
|
|
||||||
if (`${firmware.name}` == oldDevice) {
|
|
||||||
devNames.append($(`<option value="${firmware.name}" selected>${firmware.name}</option>`));
|
|
||||||
} else {
|
|
||||||
devNames.append($(`<option value="${firmware.name}">${firmware.name}</option>`));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
form.render();
|
|
||||||
|
|
||||||
let initBtnClicked = false;
|
|
||||||
|
|
||||||
const layerNum = layer.open({
|
|
||||||
type: 1,
|
|
||||||
id: "serial-select",
|
|
||||||
title: "请选择固件:",
|
|
||||||
area: ['350px', '150px'],
|
|
||||||
content: $('#mixly-selector-div'),
|
|
||||||
shade: Mixly.LayerExt.SHADE_ALL,
|
|
||||||
resize: false,
|
|
||||||
closeBtn: 0,
|
|
||||||
success: function (layero) {
|
|
||||||
$('#serial-select').css('height', '180px');
|
|
||||||
$('#serial-select').css('overflow', 'inherit');
|
|
||||||
$(".layui-layer-page").css("z-index", "198910151");
|
|
||||||
$("#mixly-selector-btn1").off("click").click(() => {
|
|
||||||
layer.close(layerNum);
|
|
||||||
});
|
|
||||||
$("#mixly-selector-btn2").click(() => {
|
|
||||||
layer.close(layerNum);
|
|
||||||
initBtnClicked = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
end: function () {
|
|
||||||
$("#mixly-selector-btn1").off("click");
|
|
||||||
$("#mixly-selector-btn2").off("click");
|
|
||||||
$('#mixly-selector-div').css('display', 'none');
|
|
||||||
$(".layui-layer-shade").remove();
|
|
||||||
if (initBtnClicked) {
|
|
||||||
let selectedFirmwareName = $('#mixly-selector-type option:selected').val();
|
|
||||||
try {
|
|
||||||
firmwareObj[selectedFirmwareName] = firmwareObj[selectedFirmwareName].replace(/\\/g, "/");
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
let pyToolName = ["esptool", "kflash", "stm32loader", "stm32bl"];
|
|
||||||
let pyToolPath = "{path}/mixpyBuild/win_python3/Lib/site-packages/"
|
|
||||||
if (Env.currentPlatform == "darwin" || Env.currentPlatform == "linux") {
|
|
||||||
pyToolPath = "{path}/tools/python/";
|
|
||||||
}
|
|
||||||
for (let i = 0; i < pyToolName.length; i++) {
|
|
||||||
if (firmwareObj[selectedFirmwareName].indexOf("\"") != -1) {
|
|
||||||
firmwareObj[selectedFirmwareName] = replaceWithReg(firmwareObj[selectedFirmwareName], Env.python3Path + "\" \"" + pyToolPath + pyToolName[i] + ".py", pyToolName[i]);
|
|
||||||
} else {
|
|
||||||
firmwareObj[selectedFirmwareName] = replaceWithReg(firmwareObj[selectedFirmwareName], Env.python3Path + " " + pyToolPath + pyToolName[i] + ".py", pyToolName[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
firmwareObj[selectedFirmwareName] = replaceWithReg(firmwareObj[selectedFirmwareName], Env.clientPath, "path");
|
|
||||||
firmwareObj[selectedFirmwareName] = replaceWithReg(firmwareObj[selectedFirmwareName], Env.boardDirPath, "indexPath");
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
const { mainStatusBarTabs } = Mixly;
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
statusBarTerminal.setValue('');
|
statusBarTerminal.addValue(data);
|
||||||
mainStatusBarTabs.changeTo("output");
|
});
|
||||||
mainStatusBarTabs.show();
|
|
||||||
BU.burning = true;
|
socket.on('micropython.errorEvent', (data) => {
|
||||||
BU.uploading = false;
|
const { mainStatusBarTabs } = Mixly;
|
||||||
const port = Serial.getSelectedPortName();
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
BU.burnWithPort(port, firmwareObj[selectedFirmwareName]);
|
statusBarTerminal.addValue(data);
|
||||||
} else {
|
});
|
||||||
layer.msg(Msg.Lang['shell.burnCanceled'], { time: 1000 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.initBurn = function () {
|
||||||
* @function 通过串口执行命令行烧录或上传操作
|
if (!this.mixlySocket.isConnected()) {
|
||||||
* @param type {string} 值为 'burn' | 'upload'
|
layer.msg('服务端已离线', { time: 1000 });
|
||||||
* @param port {string} 所选择的串口
|
return;
|
||||||
* @param command {string} 需要执行的指令
|
|
||||||
* @return {void}
|
|
||||||
**/
|
|
||||||
BU.operateWithPort = (type, port, command) => {
|
|
||||||
if (!port) {
|
|
||||||
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
|
|
||||||
time: 1000
|
|
||||||
});
|
|
||||||
BU.burning = false;
|
|
||||||
BU.uploading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const title = (type === 'burn' ? Msg.Lang['shell.burning'] : Msg.Lang['shell.uploading']) + '...';
|
|
||||||
const operate = () => {
|
|
||||||
const layerNum = layer.open({
|
|
||||||
type: 1,
|
|
||||||
title,
|
|
||||||
content: $('#mixly-loader-div'),
|
|
||||||
shade: LayerExt.SHADE_NAV,
|
|
||||||
resize: false,
|
|
||||||
closeBtn: 0,
|
|
||||||
success: function (layero, index) {
|
|
||||||
$(".layui-layer-page").css("z-index","198910151");
|
|
||||||
switch (type) {
|
|
||||||
case 'burn':
|
|
||||||
BU.burnByCmd(index, port, command);
|
|
||||||
break;
|
|
||||||
case 'upload':
|
|
||||||
default:
|
|
||||||
BU.uploadByCmd(index, port, command);
|
|
||||||
}
|
|
||||||
$("#mixly-loader-btn").off("click").click(() => {
|
|
||||||
$("#mixly-loader-btn").css('display', 'none');
|
|
||||||
switch (type) {
|
|
||||||
case 'burn':
|
|
||||||
layer.title(Msg.Lang['shell.aborting'] + '...', index);
|
|
||||||
break;
|
|
||||||
case 'upload':
|
|
||||||
default:
|
|
||||||
layer.title(Msg.Lang['shell.aborting'] + '...', index);
|
|
||||||
}
|
|
||||||
BU.cancel(type);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
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 port = Serial.getSelectedPortName();
|
||||||
|
if (!port) {
|
||||||
|
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
|
||||||
|
time: 1000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { mainStatusBarTabs } = Mixly;
|
||||||
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
|
mainStatusBarTabs.changeTo('output');
|
||||||
|
mainStatusBarTabs.show();
|
||||||
|
statusBarTerminal.setValue(`${Msg.Lang['shell.burning']}...\n`);
|
||||||
|
const statusBarSerial = mainStatusBarTabs.getStatusBarById(port);
|
||||||
|
const closePromise = statusBarSerial ? statusBarSerial.close() : Promise.resolve();
|
||||||
|
closePromise
|
||||||
|
.then(() => {
|
||||||
|
return this.shell.burn(port);
|
||||||
|
})
|
||||||
|
.then((info) => {
|
||||||
|
this.endCallback(info.code, info.time);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
Debug.error(error);
|
||||||
|
statusBarTerminal.addValue(`\n==${Msg.Lang['shell.burnFailed']}==\n`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initUpload = function () {
|
||||||
|
if (!this.mixlySocket.isConnected()) {
|
||||||
|
layer.msg('服务端已离线', { time: 1000 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const port = Serial.getSelectedPortName();
|
||||||
|
if (!port) {
|
||||||
|
layer.msg(Msg.Lang['statusbar.serial.noDevice'], {
|
||||||
|
time: 1000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { mainStatusBarTabs } = Mixly;
|
||||||
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
|
mainStatusBarTabs.changeTo('output');
|
||||||
|
mainStatusBarTabs.show();
|
||||||
|
statusBarTerminal.setValue(`${Msg.Lang['shell.uploading']}...\n`);
|
||||||
|
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(() => {
|
||||||
|
return statusBarSerial.setBaudRate(115200);
|
||||||
|
})
|
||||||
|
.catch(Debug.error);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
Debug.error(error);
|
||||||
|
statusBarTerminal.addValue(`\n==${Msg.Lang['shell.uploadFailed']}==\n`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.endCallback = function (code, time) {
|
||||||
|
const { mainStatusBarTabs } = Mixly;
|
||||||
|
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
||||||
|
mainStatusBarTabs.changeTo('output');
|
||||||
|
let message = '';
|
||||||
|
if (code) {
|
||||||
|
message = (this.shell.isBurning() ? Msg.Lang['shell.burnFailed'] : Msg.Lang['shell.uploadFailed']);
|
||||||
|
statusBarTerminal.addValue(`\n==${message}==\n`);
|
||||||
|
} else {
|
||||||
|
message = (this.shell.isBurning() ? Msg.Lang['shell.burnSucc'] : Msg.Lang['shell.uploadSucc']);
|
||||||
|
statusBarTerminal.addValue(`\n==${message}(${Msg.Lang['shell.timeCost']} ${
|
||||||
|
dayjs.duration(time).format('HH:mm:ss.SSS')
|
||||||
|
})==\n`);
|
||||||
|
}
|
||||||
|
layer.msg(message, { time: 1000 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#running_ = false;
|
||||||
|
#upload_ = false;
|
||||||
|
#layerNum_ = null;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
async burn(port) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
this.#running_ = true;
|
||||||
|
this.#upload_ = false;
|
||||||
|
await this.showProgress();
|
||||||
|
const config = {
|
||||||
|
boardDirPath: `.${Env.boardDirPath}`,
|
||||||
|
port,
|
||||||
|
command: SELECTED_BOARD.burn.command
|
||||||
|
};
|
||||||
|
const mixlySocket = WebSocketBU.getMixlySocket();
|
||||||
|
mixlySocket.emit('micropython.burn', config, (response) => {
|
||||||
|
this.hideProgress();
|
||||||
|
if (response.error) {
|
||||||
|
reject(response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [error, result] = response;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
operate();
|
|
||||||
|
async upload(port, code) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
this.#running_ = true;
|
||||||
|
this.#upload_ = true;
|
||||||
|
await this.showProgress();
|
||||||
|
const config = {
|
||||||
|
boardDirPath: `.${Env.boardDirPath}`,
|
||||||
|
command: SELECTED_BOARD.upload.command,
|
||||||
|
libPath: SELECTED_BOARD.upload.libPath,
|
||||||
|
filePath: SELECTED_BOARD.upload.filePath,
|
||||||
|
port, code
|
||||||
|
};
|
||||||
|
const mixlySocket = WebSocketBU.getMixlySocket();
|
||||||
|
mixlySocket.emit('micropython.upload', config, (response) => {
|
||||||
|
this.hideProgress();
|
||||||
|
if (response.error) {
|
||||||
|
reject(response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [error, result] = response;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async kill() {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const mixlySocket = WebSocketBU.getMixlySocket();
|
||||||
|
mixlySocket.emit('micropython.kill', (response) => {
|
||||||
|
if (response.error) {
|
||||||
|
reject(response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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.burning'] : 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_;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBurning() {
|
||||||
|
return this.#running_ && !this.#upload_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
WebSocket.BU = WebSocketBU;
|
||||||
* @function 通过串口执行命令行烧录操作
|
|
||||||
* @param port {string} 所选择的串口
|
|
||||||
* @param command {string} 需要执行的指令
|
|
||||||
* @return {void}
|
|
||||||
**/
|
|
||||||
BU.burnWithPort = (port, command) => {
|
|
||||||
BU.operateWithPort('burn', port, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function 通过串口执行命令行上传操作
|
|
||||||
* @param port {string} 所选择的串口
|
|
||||||
* @param command {string} 需要执行的指令
|
|
||||||
* @return {void}
|
|
||||||
**/
|
|
||||||
BU.uploadWithPort = (port, command) => {
|
|
||||||
BU.operateWithPort('upload', port, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
BU.addValue = function (data) {
|
|
||||||
const { mainStatusBarTabs } = Mixly;
|
|
||||||
const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output');
|
|
||||||
statusBarTerminal.addValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -157,7 +157,7 @@ class WebSocketSerial extends Serial {
|
|||||||
this.onString(str);
|
this.onString(str);
|
||||||
});
|
});
|
||||||
eventRegistry.register(`${port}-error`, (error) => {
|
eventRegistry.register(`${port}-error`, (error) => {
|
||||||
this.onError(String(error));
|
this.onError(error);
|
||||||
this.onClose(1);
|
this.onClose(1);
|
||||||
});
|
});
|
||||||
eventRegistry.register(`${port}-open`, () => {
|
eventRegistry.register(`${port}-open`, () => {
|
||||||
@@ -324,6 +324,24 @@ class WebSocketSerial extends Serial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async #awaitDispose_() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const mixlySocket = WebSocketSerial.getMixlySocket();
|
||||||
|
mixlySocket.emit('serial.dispose', this.getPortName(), (response) => {
|
||||||
|
if (response.error) {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [error, result] = response;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async dispose() {
|
async dispose() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const port = this.getPortName();
|
const port = this.getPortName();
|
||||||
@@ -335,18 +353,7 @@ class WebSocketSerial extends Serial {
|
|||||||
eventRegistry.unregister(`${port}-close`);
|
eventRegistry.unregister(`${port}-close`);
|
||||||
super.dispose()
|
super.dispose()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const mixlySocket = WebSocketSerial.getMixlySocket();
|
return this.#awaitDispose_();
|
||||||
mixlySocket.emit('serial.dispose', port, ([error, result]) => {
|
|
||||||
if (response.error) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ goog.require('Mixly.StatusBarsManager');
|
|||||||
goog.require('Mixly.WebSocket');
|
goog.require('Mixly.WebSocket');
|
||||||
goog.require('Mixly.WebSocket.Serial');
|
goog.require('Mixly.WebSocket.Serial');
|
||||||
goog.require('Mixly.WebSocket.ArduShell');
|
goog.require('Mixly.WebSocket.ArduShell');
|
||||||
|
goog.require('Mixly.WebSocket.BU');
|
||||||
goog.provide('Mixly.WebSocket.Socket');
|
goog.provide('Mixly.WebSocket.Socket');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -16,7 +17,8 @@ const {
|
|||||||
const {
|
const {
|
||||||
Socket,
|
Socket,
|
||||||
Serial,
|
Serial,
|
||||||
ArduShell
|
ArduShell,
|
||||||
|
BU
|
||||||
} = WebSocket;
|
} = WebSocket;
|
||||||
|
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ Socket.init = function () {
|
|||||||
const socket = mixlySocket.getSocket();
|
const socket = mixlySocket.getSocket();
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
|
|
||||||
Serial.getPorts()
|
Serial.getPorts()
|
||||||
.then((ports) => {
|
.then((ports) => {
|
||||||
let portsName = [];
|
let portsName = [];
|
||||||
@@ -72,6 +75,7 @@ Socket.init = function () {
|
|||||||
|
|
||||||
Serial.init(mixlySocket);
|
Serial.init(mixlySocket);
|
||||||
ArduShell.init(mixlySocket);
|
ArduShell.init(mixlySocket);
|
||||||
|
BU.init(mixlySocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,14 +11,42 @@ class WebSocket {
|
|||||||
this.#socket_ = io(path, option);
|
this.#socket_ = io(path, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#detectStatus_(status, callback) {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
if (status.finished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.isConnected()) {
|
||||||
|
this.#detectStatus_(status, callback);
|
||||||
|
} else {
|
||||||
|
callback({
|
||||||
|
error: 'socket is not connected'
|
||||||
|
});
|
||||||
|
status.finished = true;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
emit(eventName, ...args) {
|
emit(eventName, ...args) {
|
||||||
|
const callback = args.pop();
|
||||||
if (this.isConnected()) {
|
if (this.isConnected()) {
|
||||||
return this.#socket_.emit(eventName, ...args);
|
let emitStatus = {
|
||||||
} else {
|
finished: false
|
||||||
const callback = args.pop();
|
};
|
||||||
callback({
|
let status = this.#socket_.emit(eventName, ...args, (...callbackArgs) => {
|
||||||
error: new Error('socket is not connected')
|
if (emitStatus.finished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitStatus.finished = true;
|
||||||
|
callback(...callbackArgs);
|
||||||
});
|
});
|
||||||
|
this.#detectStatus_(emitStatus, callback);
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
callback({
|
||||||
|
error: 'socket is not connected'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ module.exports = {
|
|||||||
'path': 'path',
|
'path': 'path',
|
||||||
'xscrollbar': 'XScrollbar',
|
'xscrollbar': 'XScrollbar',
|
||||||
'jquery': '$',
|
'jquery': '$',
|
||||||
'ace': 'ace'
|
'ace': 'ace',
|
||||||
|
'goog': 'goog'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user