diff --git a/fix_configs.py b/fix_configs.py deleted file mode 100644 index 7e5f2ddb..00000000 --- a/fix_configs.py +++ /dev/null @@ -1,21 +0,0 @@ -import os -import json - -boards_dir = r"D:\DE-MIXLY\mixly3-server\mixly\boards" - -for root, dirs, files in os.walk(boards_dir): - for file in files: - if file == "config.json": - file_path = os.path.join(root, file) - try: - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - - new_content = content.replace('\\"{esptool}\\"', '{esptool}').replace('\\"{ampy}\\"', '{ampy}') - - if content != new_content: - print(f"Fixing: {file_path}") - with open(file_path, "w", encoding="utf-8") as f: - f.write(new_content) - except Exception as e: - print(f"Error processing {file_path}: {e}") diff --git a/mixly/common/modules/mixly-modules/web-socket/burn-upload.js b/mixly/common/modules/mixly-modules/web-socket/burn-upload.js index ec301439..e7ff32c3 100644 --- a/mixly/common/modules/mixly-modules/web-socket/burn-upload.js +++ b/mixly/common/modules/mixly-modules/web-socket/burn-upload.js @@ -1,350 +1,353 @@ goog.loadJs('web', () => { -goog.require('path'); -goog.require('layui'); -goog.require('dayjs.duration'); -goog.require('Mixly.Debug'); -goog.require('Mixly.LayerExt'); -goog.require('Mixly.Msg'); -goog.require('Mixly.Env'); -goog.require('Mixly.Config'); -goog.require('Mixly.Workspace'); -goog.require('Mixly.MString'); -goog.require('Mixly.LayerProgress'); -goog.require('Mixly.WebSocket.Serial'); -goog.provide('Mixly.WebSocket.BU'); + goog.require('path'); + goog.require('layui'); + goog.require('dayjs.duration'); + goog.require('Mixly.Debug'); + goog.require('Mixly.LayerExt'); + goog.require('Mixly.Msg'); + goog.require('Mixly.Env'); + goog.require('Mixly.Config'); + goog.require('Mixly.Workspace'); + goog.require('Mixly.MString'); + goog.require('Mixly.LayerProgress'); + goog.require('Mixly.WebSocket.Serial'); + goog.provide('Mixly.WebSocket.BU'); -const { - Debug, - LayerExt, - Config, - Msg, - Env, - Workspace, - MString, - LayerProgress, - WebSocket -} = Mixly; + const { + Debug, + LayerExt, + Config, + Msg, + Env, + Workspace, + MString, + LayerProgress, + WebSocket + } = Mixly; -const { SELECTED_BOARD } = Config; + const { SELECTED_BOARD } = Config; -const { Serial } = WebSocket; + const { Serial } = WebSocket; -const { layer } = layui; + const { layer } = layui; -class WebSocketBU { - static { - this.mixlySocket = null; - this.socket = null; - this.shell = null; + class WebSocketBU { + static { + this.mixlySocket = null; + this.socket = null; + this.shell = null; - this.getSocket = function () { - return this.socket; - } + this.getSocket = function () { + return this.socket; + } - this.getMixlySocket = function () { - return this.mixlySocket; - } + this.getMixlySocket = function () { + return this.mixlySocket; + } - this.init = function (mixlySocket) { - this.mixlySocket = mixlySocket; - this.socket = mixlySocket.getSocket(); - this.shell = new WebSocketBU(); - const socket = this.socket; + this.init = function (mixlySocket) { + this.mixlySocket = mixlySocket; + this.socket = mixlySocket.getSocket(); + this.shell = new WebSocketBU(); + const socket = this.socket; - socket.on('micropython.dataEvent', (data) => { + socket.on('micropython.dataEvent', (data) => { + const { mainStatusBarTabs } = Mixly; + const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output'); + statusBarTerminal.addValue(data); + }); + + socket.on('micropython.errorEvent', (data) => { + const { mainStatusBarTabs } = Mixly; + const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output'); + statusBarTerminal.addValue(data); + }); + } + + this.initBurn = function () { + if (!this.mixlySocket.isConnected()) { + layer.msg(Msg.Lang['websocket.offline'], { 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'); - statusBarTerminal.addValue(data); - }); + 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`); + }); + } - socket.on('micropython.errorEvent', (data) => { + this.initUpload = function () { + if (!this.mixlySocket.isConnected()) { + layer.msg(Msg.Lang['websocket.offline'], { 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'); - statusBarTerminal.addValue(data); + 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; + #killing_ = false; + #layer_ = null; + + constructor() { + this.#layer_ = new LayerProgress({ + width: 200, + cancelValue: Msg.Lang['nav.btn.stop'], + skin: 'layui-anim layui-anim-scale', + cancel: () => { + if (this.#killing_) { + return false; + } + this.#layer_.title(`${Msg.Lang['shell.aborting']}...`); + this.#killing_ = true; + this.kill().catch(Debug.error); + return false; + }, + cancelDisplay: false }); } - this.initBurn = function () { - if (!this.mixlySocket.isConnected()) { - layer.msg(Msg.Lang['websocket.offline'], { 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.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(Msg.Lang['websocket.offline'], { 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)) { + async burn(port) { + return new Promise(async (resolve, reject) => { + this.#running_ = true; + this.#upload_ = false; + this.#killing_ = false; + this.showProgress(); + const config = { + boardDirPath: `.${Env.boardDirPath}`, + port, + command: SELECTED_BOARD.burn.command, + baudrate: Boards.getSelectedBoardConfigParam('BurnSpeed'), + reset: SELECTED_BOARD.burn.reset || [] + }; + const mixlySocket = WebSocketBU.getMixlySocket(); + mixlySocket.emit('micropython.burn', config, (response) => { + this.hideProgress(); + if (response.error) { + reject(response.error); 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`); + const [error, result] = response; + if (error) { + reject(error); + } else { + resolve(result); + } }); - } - - 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; - #killing_ = false; - #layer_ = null; - - constructor() { - this.#layer_ = new LayerProgress({ - width: 200, - cancelValue: Msg.Lang['nav.btn.stop'], - skin: 'layui-anim layui-anim-scale', - cancel: () => { - if (this.#killing_) { - return false; - } - this.#layer_.title(`${Msg.Lang['shell.aborting']}...`); - this.#killing_ = true; - this.kill().catch(Debug.error); - return false; - }, - cancelDisplay: false - }); - } - - async burn(port) { - return new Promise(async (resolve, reject) => { - this.#running_ = true; - this.#upload_ = false; - this.#killing_ = false; - 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); - } }); - }); - } + } - async upload(port, code) { - return new Promise(async (resolve, reject) => { - this.#running_ = true; - this.#upload_ = true; - this.#killing_ = false; - this.showProgress(); - const importsMap = this.getImportModules(code); - let libraries = {}; - for (let key in importsMap) { - const filename = importsMap[key]['__name__']; - const data = goog.readFileSync(importsMap[key]['__path__']); - libraries[filename] = data; - } - const config = { - boardDirPath: `.${Env.boardDirPath}`, - command: SELECTED_BOARD.upload.command, - filePath: SELECTED_BOARD.upload.filePath, - port, code, libraries - }; - - 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 upload(port, code) { + return new Promise(async (resolve, reject) => { + this.#running_ = true; + this.#upload_ = true; + this.#killing_ = false; + this.showProgress(); + const importsMap = this.getImportModules(code); + let libraries = {}; + for (let key in importsMap) { + const filename = importsMap[key]['__name__']; + const data = goog.readFileSync(importsMap[key]['__path__']); + libraries[filename] = data; } + const config = { + boardDirPath: `.${Env.boardDirPath}`, + command: SELECTED_BOARD.upload.command, + filePath: SELECTED_BOARD.upload.filePath, + baudrate: Boards.getSelectedBoardConfigParam('BurnSpeed'), + reset: SELECTED_BOARD.upload.reset || [], + port, code, libraries + }; + + 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); + } + }); }); - }); - } - - getImportModulesName(code) { - // 正则表达式: 匹配 import 或 from 导入语句 - const importRegex = /(?:import\s+([a-zA-Z0-9_]+)|from\s+([a-zA-Z0-9_]+)\s+import)/g; - - let imports = []; - let match; - while ((match = importRegex.exec(code)) !== null) { - if (match[1]) { - imports.push(match[1]); // 'import module' - } - if (match[2]) { - imports.push(match[2]); // 'from module import ...' - } - } - return imports; - } - - getImportModules(code) { - let importsMap = {}; - const libPath = SELECTED_BOARD.upload.libPath; - for (let i = libPath.length - 1; i >= 0; i--) { - const dirname = MString.tpl(libPath[i], { indexPath: Env.boardDirPath }); - const map = goog.readJsonSync(path.join(dirname, 'map.json')); - if (!(map && map instanceof Object)) { - continue; - } - for (let key in map) { - importsMap[key] = structuredClone(map[key]); - importsMap[key]['__path__'] = path.join(dirname, map[key]['__name__']); - } } - let usedMap = {}; - let currentImports = this.getImportModulesName(code); - while (currentImports.length) { - let temp = []; - for (let moduleName of currentImports) { - let moduleInfo = importsMap[moduleName]; - if (!moduleInfo) { + getImportModulesName(code) { + // 正则表达式: 匹配 import 或 from 导入语句 + const importRegex = /(?:import\s+([a-zA-Z0-9_]+)|from\s+([a-zA-Z0-9_]+)\s+import)/g; + + let imports = []; + let match; + while ((match = importRegex.exec(code)) !== null) { + if (match[1]) { + imports.push(match[1]); // 'import module' + } + if (match[2]) { + imports.push(match[2]); // 'from module import ...' + } + } + return imports; + } + + getImportModules(code) { + let importsMap = {}; + const libPath = SELECTED_BOARD.upload.libPath; + for (let i = libPath.length - 1; i >= 0; i--) { + const dirname = MString.tpl(libPath[i], { indexPath: Env.boardDirPath }); + const map = goog.readJsonSync(path.join(dirname, 'map.json')); + if (!(map && map instanceof Object)) { continue; } - usedMap[moduleName] = moduleInfo; - const moduleImports = moduleInfo['__require__']; - if (!moduleImports) { - continue; + for (let key in map) { + importsMap[key] = structuredClone(map[key]); + importsMap[key]['__path__'] = path.join(dirname, map[key]['__name__']); } - for (let name of moduleImports) { - if (usedMap[name] || !importsMap[name] || temp.includes(name)) { + } + + let usedMap = {}; + let currentImports = this.getImportModulesName(code); + while (currentImports.length) { + let temp = []; + for (let moduleName of currentImports) { + let moduleInfo = importsMap[moduleName]; + if (!moduleInfo) { continue; } - temp.push(name); + usedMap[moduleName] = moduleInfo; + const moduleImports = moduleInfo['__require__']; + if (!moduleImports) { + continue; + } + for (let name of moduleImports) { + if (usedMap[name] || !importsMap[name] || temp.includes(name)) { + continue; + } + temp.push(name); + } } + currentImports = temp; } - currentImports = temp; + return usedMap; } - return usedMap; - } - 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 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); + } + }); }); - }); + } + + showProgress() { + const message = this.isBurning() ? Msg.Lang['shell.burning'] : Msg.Lang['shell.uploading']; + this.#layer_.title(`${message}...`); + this.#layer_.show(); + } + + hideProgress() { + this.#layer_.hide(); + } + + isUploading() { + return this.#running_ && this.#upload_; + } + + isBurning() { + return this.#running_ && !this.#upload_; + } } - showProgress() { - const message = this.isBurning() ? Msg.Lang['shell.burning'] : Msg.Lang['shell.uploading']; - this.#layer_.title(`${message}...`); - this.#layer_.show(); - } - - hideProgress() { - this.#layer_.hide(); - } - - isUploading() { - return this.#running_ && this.#upload_; - } - - isBurning() { - return this.#running_ && !this.#upload_; - } -} - -WebSocket.BU = WebSocketBU; + WebSocket.BU = WebSocketBU; }); \ No newline at end of file diff --git a/src/common/mstring.js b/src/common/mstring.js index 2547eb97..bbaeeaf1 100755 --- a/src/common/mstring.js +++ b/src/common/mstring.js @@ -17,7 +17,7 @@ MString.tpl = (str, obj) => { return str; } for (let key in obj) { - let re = new RegExp(`{*${key}*}`, 'gim'); + let re = new RegExp(`{${key}}`, 'gm'); str = str.replace(re, obj[key]); } return str; diff --git a/src/common/shell-micropython.js b/src/common/shell-micropython.js index 5ad6c322..009ab313 100755 --- a/src/common/shell-micropython.js +++ b/src/common/shell-micropython.js @@ -14,7 +14,7 @@ export default class ShellMicroPython extends Shell { indexPath: path.resolve(CLIENT_PATH, config.boardDirPath), esptool: `"${PYTHON.path.cli}" "${MICROPYTHON.path.esptool}"`, com: config.port, - baudrate: config.baudRates + baudrate: config.baudrate || "460800" }; // 兼容性处理:移除模板中可能存在的冗余引号 let cmdTemplate = config.command || ""; @@ -29,7 +29,7 @@ export default class ShellMicroPython extends Shell { indexPath: path.resolve(CLIENT_PATH, config.boardDirPath), ampy: `"${PYTHON.path.cli}" "${MICROPYTHON.path.ampy}"`, com: config.port, - reset: config.reset || "" + reset: config.reset || "[]" }; // 兼容性处理:移除模板中可能存在的冗余引号 let cmdTemplate = config.command || "";