diff --git a/src/common/config.js b/src/common/config.js index d9a44d8..f5cddc8 100644 --- a/src/common/config.js +++ b/src/common/config.js @@ -1,20 +1,12 @@ import os from 'node:os'; +import CONFIG from '../user/config.json'; -export const DEBUG = true; -export const ARDUINO = { - path: { - folder: 'D:/gitee/arduino-cli-win32/arduino-cli', - cli: 'D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.exe', - libraries: ['D:/gitee/arduino-cli-win32/arduino-cli/libraries'], - cache: 'D:/gitee/arduino-cli-win32/arduino-cli/cache', - config: 'D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.json', - build: 'D:/gitee/mixly3-server/temp/web-socket', - code: '' - }, - key: '', - port: '', - code: '' -}; + +export const DEBUG = CONFIG.debug; +export const ARDUINO = CONFIG.arduino; +export const MICROPYTHON = CONFIG.micropython; +export const PYTHON = CONFIG.python; export const CURRENT_PLANTFORM = os.platform(); -export const WEB_SOCKT_TEMP_PATH = ''; -export const WEB_COMPILER_TEMP_PATH = ''; \ No newline at end of file +export const WEB_SOCKT_TEMP_PATH = CONFIG.webSocketTempPath; +export const WEB_COMPILER_TEMP_PATH = CONFIG.webSocketTempPath; +export const CLIENT_PATH = CONFIG.clientPath; \ No newline at end of file diff --git a/src/common/mstring.js b/src/common/mstring.js new file mode 100644 index 0000000..2547eb9 --- /dev/null +++ b/src/common/mstring.js @@ -0,0 +1,26 @@ +const MString = {}; + + +/** + * @function 使用传入值替换字符串中{xxx} + * @param str {string} 传入字符串 + * @param obj {object} + * obj = { + * xxx: value1, + * xxx: value2 + * } + * 使用value替换{xxx} + * @return {string} 返回处理后的字符串 + **/ +MString.tpl = (str, obj) => { + if (!(typeof str === 'string' && obj instanceof Object)) { + return str; + } + for (let key in obj) { + let re = new RegExp(`{*${key}*}`, 'gim'); + str = str.replace(re, obj[key]); + } + return str; +} + +export default MString; \ No newline at end of file diff --git a/src/common/serial.js b/src/common/serial.js index b46eccc..c26ba61 100644 --- a/src/common/serial.js +++ b/src/common/serial.js @@ -79,7 +79,7 @@ export default class Serial extends EventsBase { }); this.#serialport_.on('error', (error) => { - this.runEvent('error', error); + this.runEvent('error', error.toString()); }); this.#serialport_.on('open', () => { @@ -121,7 +121,7 @@ export default class Serial extends EventsBase { this.#addEventsListener_(); this.#serialport_.open((error) => { if (error) { - reject(error); + reject(error.toString()); } else { resolve(); } @@ -137,7 +137,7 @@ export default class Serial extends EventsBase { } this.#serialport_.close((error) => { if (error) { - reject(error); + reject(error.toString()); } else { resolve(); } @@ -153,7 +153,7 @@ export default class Serial extends EventsBase { } this.#serialport_.update({ baudRate: baud }, (error) => { if (error) { - reject(error); + reject(error.toString()); } else { resolve(); } @@ -169,7 +169,7 @@ export default class Serial extends EventsBase { } this.#serialport_.write(data, (error) => { if (error) { - reject(error); + reject(error.toString()); } else { resolve(); } @@ -185,7 +185,7 @@ export default class Serial extends EventsBase { } this.#serialport_.set({ dtr, rts }, (error) => { if (error) { - reject(error); + reject(error.toString()); } else { resolve(); } diff --git a/src/common/shell-micropython.js b/src/common/shell-micropython.js index e69de29..a0d7de8 100644 --- a/src/common/shell-micropython.js +++ b/src/common/shell-micropython.js @@ -0,0 +1,31 @@ +import path from 'node:path'; +import Shell from './shell'; +import MString from './mstring'; +import { MICROPYTHON, PYTHON, CLIENT_PATH } from './config'; + + +export default class ShellMicroPython extends Shell { + constructor() { + super(); + } + + async burn(config) { + const info = { + indexPath: path.resolve(CLIENT_PATH, config.boardDirPath), + esptool: `${PYTHON.path.cli}" "${MICROPYTHON.path.esptool}`, + com: config.port + }; + const command = MString.tpl(config.command, info); + return this.exec(command); + } + + async upload(config) { + const info = { + indexPath: path.resolve(CLIENT_PATH, config.boardDirPath), + ampy: `${PYTHON.path.cli}" "${MICROPYTHON.path.ampy}`, + com: config.port + }; + const command = MString.tpl(config.command, info); + return this.exec(command); + } +} \ No newline at end of file diff --git a/src/common/shell.js b/src/common/shell.js index b20b21e..c596368 100644 --- a/src/common/shell.js +++ b/src/common/shell.js @@ -1,6 +1,5 @@ import { execFile, exec } from 'node:child_process'; import * as iconv_lite from 'iconv-lite'; -// import duration from 'dayjs/plugin/duration'; import Debug from './debug'; import EventsBase from './events-base'; import { CURRENT_PLANTFORM } from './config'; @@ -52,7 +51,7 @@ export default class Shell extends EventsBase { lines[i] = iconv_lite.decode(Buffer.from(lines[i], 'binary'), encoding); } data = lines.join('\n'); - data = this.#decode_(data); + // data = this.#decode_(data); this.runEvent('error', data); }); } diff --git a/src/user/config.json b/src/user/config.json index e69de29..b9dc8d3 100644 --- a/src/user/config.json +++ b/src/user/config.json @@ -0,0 +1,28 @@ +{ + "debug": true, + "arduino": { + "path": { + "folder": "D:/gitee/mixly/arduino-cli", + "cli": "D:/gitee/mixly/arduino-cli/arduino-cli.exe", + "libraries": [ + "D:/gitee/mixly/arduino-cli/libraries" + ], + "cache": "D:/gitee/mixly/arduino-cli/cache", + "config": "D:/gitee/mixly/arduino-cli/arduino-cli.json" + } + }, + "micropython": { + "path": { + "ampy": "D:/gitee/mixly3-resource/mixly3.0-win32-x64/resources/app/src/tools/python/ampy/cli.py", + "esptool": "D:/gitee/mixly3-resource/mixly3.0-win32-x64/resources/app/src/tools/python/esptool/__init__.py" + } + }, + "python": { + "path": { + "cli": "D:/gitee/mixly3-resource/mixly3.0-win32-x64/mixpyBuild/win_python3/python3.exe" + } + }, + "webSocketTempPath": "D:/gitee/mixly3-resource/mixly3-server/temp/web-socket", + "webCompilerTempPath": "D:/gitee/mixly3-resource/mixly3-server/temp/web-compiler", + "clientPath": "D:/gitee/mixly3-resource/mixly3.0-win32-x64/resources/app/src" +} \ No newline at end of file diff --git a/src/web-socket/socket.js b/src/web-socket/socket.js index 7d24ae5..a71cbde 100644 --- a/src/web-socket/socket.js +++ b/src/web-socket/socket.js @@ -3,17 +3,19 @@ import to from 'await-to-js'; import { usb } from 'usb'; import path from 'node:path'; import fsExtra from 'fs-extra'; -import fsPlus from 'fs-plus'; import Serial from '../common/serial'; import Debug from '../common/debug'; import Registry from '../common/registry'; import ShellArduino from '../common/shell-arduino'; -import { ARDUINO } from '../common/config'; +import ShellMicroPython from '../common/shell-micropython'; +import MString from '../common/mstring'; +import { WEB_SOCKT_TEMP_PATH, CLIENT_PATH } from '../common/config'; export default class Socket { #io_ = null; #serialRegistry_ = new Registry(); + #shellMicroPython_ = new ShellMicroPython(); #shellArduino_ = new ShellArduino(); constructor(httpsServer, options) { @@ -29,6 +31,60 @@ export default class Socket { }); } + #addEventsListener_(socket) { + socket.on('disconnect', () => { + for (let key of this.#serialRegistry_.keys()) { + const serial = this.#serialRegistry_.getItem(key); + serial.dispose().catch(Debug.error); + this.#serialRegistry_.unregister(key); + } + }); + + this.#addEventsListenerForMicroPython_(socket); + this.#addEventsListenerForArduino_(socket); + this.#addEventsListenerForSerial_(socket); + } + + #addEventsListenerForMicroPython_(socket) { + this.#shellMicroPython_.bind('data', (data) => { + socket.emit('arduino.dataEvent', data); + }); + + this.#shellMicroPython_.bind('error', (data) => { + socket.emit('arduino.errorEvent', data); + }); + + this.#shellMicroPython_.bind('close', (code, time) => { + socket.emit('arduino.closeEvent', code, time); + }); + + socket.on('micropython.burn', async (config, callback) => { + const [error, result] = await to(this.#shellMicroPython_.burn(config)); + error && Debug.error(error); + callback([error, result]); + }); + + socket.on('micropython.upload', async (config, callback) => { + let { filePath = '' } = config; + filePath = MString.tpl(filePath, { + indexPath: path.resolve(CLIENT_PATH, config.boardDirPath) + }); + let [error1,] = await to(fsExtra.ensureDir(path.dirname(filePath))); + error1 && Debug.error(error1); + let [error2,] = await to(fsExtra.outputFile(filePath, config.code)); + error2 && Debug.error(error2); + const [error, result] = await to(this.#shellMicroPython_.upload(config)); + error && Debug.error(error); + callback([error, result]); + }); + + socket.on('micropython.kill', async (callback) => { + const [error, result] = await to(this.#shellMicroPython_.kill()); + error && Debug.error(error); + callback([error, result]); + }); + } + #addEventsListenerForArduino_(socket) { this.#shellArduino_.bind('data', (data) => { socket.emit('arduino.dataEvent', data); @@ -43,11 +99,9 @@ export default class Socket { }); socket.on('arduino.compile', async (config, callback) => { - let { build } = ARDUINO.path; - let user = path.resolve(build, socket.id); config.path = config?.path ?? {}; - config.path.build = path.resolve(user, 'build'); - config.path.code = path.resolve(user, 'testArduino/testArduino.ino'); + config.path.build = path.resolve(WEB_SOCKT_TEMP_PATH, 'build'); + config.path.code = path.resolve(WEB_SOCKT_TEMP_PATH, 'testArduino/testArduino.ino'); let [error1,] = await to(fsExtra.ensureDir(config.path.build)); error1 && Debug.error(error1); let [error2,] = await to(fsExtra.outputFile(config.path.code, config.code)); @@ -58,11 +112,9 @@ export default class Socket { }); socket.on('arduino.upload', async (config, callback) => { - let { build } = ARDUINO.path; - let user = path.resolve(build, socket.id); config.path = config?.path ?? {}; - config.path.build = path.resolve(user, 'build'); - config.path.code = path.resolve(user, 'testArduino/testArduino.ino'); + config.path.build = path.resolve(WEB_SOCKT_TEMP_PATH, 'build'); + config.path.code = path.resolve(WEB_SOCKT_TEMP_PATH, 'testArduino/testArduino.ino'); let [error1,] = await to(fsExtra.ensureDir(config.path.build)); error1 && Debug.error(error1); let [error2,] = await to(fsExtra.outputFile(config.path.code, config.code)); @@ -150,24 +202,6 @@ export default class Socket { }); } - #addEventsListener_(socket) { - socket.on('disconnect', () => { - let { build } = ARDUINO.path; - let user = path.resolve(build, socket.id); - if (fsPlus.isDirectorySync(user)) { - fsExtra.remove(user); - } - for (let key of this.#serialRegistry_.keys()) { - const serial = this.#serialRegistry_.getItem(key); - serial.dispose().catch(Debug.error); - this.#serialRegistry_.unregister(key); - } - }); - - this.#addEventsListenerForArduino_(socket); - this.#addEventsListenerForSerial_(socket); - } - getIO() { return this.#io_; }