feat: 添加对web compiler的支持
This commit is contained in:
@@ -16,7 +16,7 @@ module.exports = {
|
||||
"no-else-return": 2, // 如果if语句里面有return,后面不能跟else语句
|
||||
"no-empty": 2, // 块语句中的内容不能为空
|
||||
"no-var": 0, // 不能使用 var 定义变量
|
||||
"indent": [2, 4], // 缩进风格
|
||||
"indent": [2, 4, { SwitchCase: 1 }], // 缩进风格
|
||||
"strict": 2,
|
||||
"use-isnan": 2,
|
||||
"no-redeclare": 2, // 禁止重复声明变量
|
||||
|
||||
43
package-lock.json
generated
43
package-lock.json
generated
@@ -7,9 +7,10 @@
|
||||
"": {
|
||||
"name": "mixly3-server",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"await-to-js": "^3.0.0",
|
||||
"better-sse": "^0.14.1",
|
||||
"commander": "^12.1.0",
|
||||
"express": "^4.21.1",
|
||||
"fs-extra": "^11.2.0",
|
||||
@@ -20,7 +21,7 @@
|
||||
"mustache": "^4.2.0",
|
||||
"serialport": "^12.0.0",
|
||||
"shelljs": "^0.8.5",
|
||||
"shortid": "^2.2.16",
|
||||
"shortid": "^2.2.17",
|
||||
"simple-git": "^3.27.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"usb": "^2.14.0"
|
||||
@@ -1003,6 +1004,15 @@
|
||||
"node": "^4.5.0 || >= 5.9"
|
||||
}
|
||||
},
|
||||
"node_modules/better-sse": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmmirror.com/better-sse/-/better-sse-0.14.1.tgz",
|
||||
"integrity": "sha512-htQOrymWPKD/LDkRRlgmqS5+xX3p9/BetUQTRshqtwuSk+aQ63RluzHx0CJpY1AYUadCvUex8J+B6XwkGLkZxw==",
|
||||
"engines": {
|
||||
"node": ">=20",
|
||||
"pnpm": ">=9"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
@@ -3300,9 +3310,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "2.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-2.1.11.tgz",
|
||||
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
@@ -4520,12 +4543,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/shortid": {
|
||||
"version": "2.2.16",
|
||||
"resolved": "https://registry.npmmirror.com/shortid/-/shortid-2.2.16.tgz",
|
||||
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"version": "2.2.17",
|
||||
"resolved": "https://registry.npmmirror.com/shortid/-/shortid-2.2.17.tgz",
|
||||
"integrity": "sha512-GpbM3gLF1UUXZvQw6MCyulHkWbRseNO4cyBEZresZRorwl1+SLu1ZdqgVtuwqz8mB6RpwPkm541mYSqrKyJSaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^2.1.0"
|
||||
"nanoid": "^3.3.8"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
"url": "https://gitee.com/bnu_mixly/mixly3-server.git"
|
||||
},
|
||||
"author": "Mixly Team",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"await-to-js": "^3.0.0",
|
||||
"better-sse": "^0.14.1",
|
||||
"commander": "^12.1.0",
|
||||
"express": "^4.21.1",
|
||||
"fs-extra": "^11.2.0",
|
||||
@@ -28,7 +29,7 @@
|
||||
"mustache": "^4.2.0",
|
||||
"serialport": "^12.0.0",
|
||||
"shelljs": "^0.8.5",
|
||||
"shortid": "^2.2.16",
|
||||
"shortid": "^2.2.17",
|
||||
"simple-git": "^3.27.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"usb": "^2.14.0"
|
||||
|
||||
200
src/common/boards.js
Normal file
200
src/common/boards.js
Normal file
@@ -0,0 +1,200 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import MString from './mstring';
|
||||
import { ARDUINO } from './config';
|
||||
|
||||
|
||||
const Boards = {};
|
||||
|
||||
Boards.TYPE = {
|
||||
AVR: [
|
||||
"arduino:avr:uno",
|
||||
"arduino:avr:nano",
|
||||
"arduino:avr:pro",
|
||||
"arduino:avr:mega",
|
||||
"arduino:avr:leonardo"
|
||||
],
|
||||
ESP8266: [
|
||||
"esp8266:esp8266:generic",
|
||||
"esp8266:esp8266:nodemcu",
|
||||
"esp8266:esp8266:nodemcuv2",
|
||||
"esp8266:esp8266:d1"
|
||||
],
|
||||
ESP32: [
|
||||
"esp32:esp32:esp32",
|
||||
"esp32:esp32:pico32",
|
||||
"esp32:esp32:node32s",
|
||||
"esp32:esp32:nodemcu-32s",
|
||||
"esp32:esp32:m5stack-fire",
|
||||
"esp32:esp32:mPython",
|
||||
"esp32:esp32:esp32cam",
|
||||
"esp32:esp32:bpi-bit"
|
||||
],
|
||||
ESP32S2: [
|
||||
"esp32:esp32:esp32s2"
|
||||
],
|
||||
ESP32S3: [
|
||||
"esp32:esp32:esp32s3"
|
||||
],
|
||||
ESP32C3: [
|
||||
"esp32:esp32:esp32c3"
|
||||
]
|
||||
};
|
||||
|
||||
Boards.FIRMWARE_PATH = {
|
||||
AVR: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.hex'
|
||||
}
|
||||
],
|
||||
ESP8266: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.bin',
|
||||
offset: '0x0'
|
||||
}
|
||||
],
|
||||
ESP32: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.bootloader.bin',
|
||||
offset: '0x1000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.partitions.bin',
|
||||
offset: '0x8000'
|
||||
}, {
|
||||
path: '{shellPath}/Arduino15/packages/esp32/hardware/esp32/2.0.15/tools/partitions/boot_app0.bin',
|
||||
offset: '0xe000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.bin',
|
||||
offset: '0x10000'
|
||||
}
|
||||
],
|
||||
ESP32S2: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.bootloader.bin',
|
||||
offset: '0x1000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.partitions.bin',
|
||||
offset: '0x8000'
|
||||
}, {
|
||||
path: '{shellPath}/Arduino15/packages/esp32/hardware/esp32/2.0.5/tools/partitions/boot_app0.bin',
|
||||
offset: '0xe000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.bin',
|
||||
offset: '0x10000'
|
||||
}
|
||||
],
|
||||
ESP32S3: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.bootloader.bin',
|
||||
offset: '0x1000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.partitions.bin',
|
||||
offset: '0x8000'
|
||||
}, {
|
||||
path: '{shellPath}/Arduino15/packages/esp32/hardware/esp32/2.0.5/tools/partitions/boot_app0.bin',
|
||||
offset: '0xe000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.bin',
|
||||
offset: '0x10000'
|
||||
}
|
||||
],
|
||||
ESP32C3: [
|
||||
{
|
||||
path: '{buildPath}/testArduino.ino.bootloader.bin',
|
||||
offset: '0x0'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.partitions.bin',
|
||||
offset: '0x8000'
|
||||
}, {
|
||||
path: '{shellPath}/Arduino15/packages/esp32/hardware/esp32/2.0.5/tools/partitions/boot_app0.bin',
|
||||
offset: '0xe000'
|
||||
}, {
|
||||
path: '{buildPath}/testArduino.ino.bin',
|
||||
offset: '0x10000'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Boards.getBoardType = (board) => {
|
||||
if (typeof board !== 'string') {
|
||||
return null;
|
||||
}
|
||||
const boardParam = board.split(':');
|
||||
if (boardParam.length < 3) {
|
||||
return null;
|
||||
}
|
||||
let boardType;
|
||||
const inBoardType = boardParam[0] + ':' + boardParam[1];
|
||||
switch (inBoardType) {
|
||||
case 'arduino:avr':
|
||||
boardType = 'AVR';
|
||||
break;
|
||||
case 'esp8266:esp8266':
|
||||
boardType = 'ESP8266';
|
||||
break;
|
||||
case 'esp32:esp32':
|
||||
boardType = 'ESP32';
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
if (boardType !== 'ESP32') {
|
||||
return boardType;
|
||||
}
|
||||
switch (boardParam[2]) {
|
||||
case 'esp32c3':
|
||||
boardType = 'ESP32C3';
|
||||
break;
|
||||
case 'esp32s2':
|
||||
boardType = 'ESP32S2';
|
||||
break;
|
||||
case 'esp32s3':
|
||||
boardType = 'ESP32S3';
|
||||
break;
|
||||
default:
|
||||
boardType = 'ESP32';
|
||||
}
|
||||
return boardType;
|
||||
}
|
||||
|
||||
Boards.getBoardKey = (board) => {
|
||||
const idxs = [];
|
||||
for (let i = 0; i < board.length; i++) {
|
||||
if (board[i] === ':') idxs.push(i);
|
||||
if (idxs.length === 3) break;
|
||||
}
|
||||
return idxs.length === 3 ? board.slice(0, idxs[2]) : board;
|
||||
}
|
||||
|
||||
Boards.exist = (board) => {
|
||||
const boardType = Boards.getBoardType(board);
|
||||
if (!boardType) {
|
||||
return false;
|
||||
}
|
||||
const boardParam = board.split(':');
|
||||
const inBoardType = boardParam[0] + ':' + boardParam[1];
|
||||
board = inBoardType + ':' + boardParam[2];
|
||||
if (Boards.TYPE[boardType] && Boards.TYPE[boardType].includes(board)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Boards.getFiles = async (board, buildPath) => {
|
||||
const type = Boards.getBoardType(board);
|
||||
const output = [];
|
||||
const files = Boards.FIRMWARE_PATH[type];
|
||||
for (let file of files) {
|
||||
const filePath = MString.tpl(file.path, {
|
||||
buildPath,
|
||||
shellPath: ARDUINO.path.folder
|
||||
});
|
||||
const data = await fs.promises.readFile(filePath, {
|
||||
encoding: path.extname(filePath) === '.hex' ? 'utf8' : 'hex'
|
||||
});
|
||||
output.push({ ...file, data });
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
export default Boards;
|
||||
@@ -7,6 +7,5 @@ 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 = CONFIG.webSocketTempPath;
|
||||
export const WEB_COMPILER_TEMP_PATH = CONFIG.webSocketTempPath;
|
||||
export const TEMP_PATH = CONFIG.tempPath;
|
||||
export const CLIENT_PATH = CONFIG.clientPath;
|
||||
@@ -29,7 +29,7 @@ export default class EventsBase {
|
||||
return this.#events_.reset();
|
||||
}
|
||||
|
||||
disposeEvent() {
|
||||
dispose() {
|
||||
this.resetEvent();
|
||||
this.#events_ = null;
|
||||
}
|
||||
|
||||
20
src/common/id-generator.js
Normal file
20
src/common/id-generator.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import shortid from 'shortid';
|
||||
|
||||
|
||||
const IdGenerator = {};
|
||||
|
||||
IdGenerator.generate = function (input) {
|
||||
let output = {};
|
||||
if (input instanceof Array) {
|
||||
for (let i of input) {
|
||||
if (typeof i !== 'string') {
|
||||
continue;
|
||||
}
|
||||
output[i] = shortid.generate();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
return shortid.generate();
|
||||
}
|
||||
|
||||
export default IdGenerator;
|
||||
@@ -82,7 +82,10 @@ export default class Shell extends EventsBase {
|
||||
}
|
||||
|
||||
async kill() {
|
||||
if (this.#killed_) {
|
||||
if (this.#killed_ || !this.#shell_) {
|
||||
return;
|
||||
}
|
||||
if (this.#shell_.exitCode !== null) {
|
||||
return;
|
||||
}
|
||||
this.#shell_.stdin.end();
|
||||
@@ -92,9 +95,15 @@ export default class Shell extends EventsBase {
|
||||
} else {
|
||||
this.#shell_.kill('SIGTERM')
|
||||
}
|
||||
this.#shell_ = null;
|
||||
}
|
||||
|
||||
getShell() {
|
||||
return this.#shell_;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.#shell_ = null;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
408
src/common/socket.js
Normal file
408
src/common/socket.js
Normal file
@@ -0,0 +1,408 @@
|
||||
import { Server } from 'socket.io';
|
||||
import to from 'await-to-js';
|
||||
import { usb } from 'usb';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import Serial from './serial';
|
||||
import Debug from './debug';
|
||||
import Registry from './registry';
|
||||
import ShellArduino from './shell-arduino';
|
||||
import ShellMicroPython from './shell-micropython';
|
||||
import ShellAmpy from './shell-ampy';
|
||||
import MString from './mstring';
|
||||
import Boards from './boards';
|
||||
import { TEMP_PATH, CLIENT_PATH } from './config';
|
||||
|
||||
|
||||
export default class Socket {
|
||||
#io_ = null;
|
||||
#namespaceAll_ = null;
|
||||
#namespaceCompile_ = null;
|
||||
#serialRegistry_ = new Registry();
|
||||
#shellMicroPython_ = new Registry();
|
||||
#shellArduino_ = new Registry();
|
||||
#shellAmpy_ = new Registry();
|
||||
|
||||
constructor(httpsServer, options) {
|
||||
this.#io_ = new Server(httpsServer, options);
|
||||
this.#namespaceAll_ = this.#io_.of('/all');
|
||||
this.#namespaceCompile_ = this.#io_.of('/compile');
|
||||
this.#namespaceCompile_.on('connection', (socket) => {
|
||||
this.#shellArduino_.register(socket.id, new ShellArduino());
|
||||
this.#addEventsListenerForMode1_(socket);
|
||||
});
|
||||
this.#namespaceAll_.on('connection', (socket) => {
|
||||
this.#shellMicroPython_.register(socket.id, new ShellMicroPython());
|
||||
this.#shellArduino_.register(socket.id, new ShellArduino());
|
||||
this.#shellAmpy_.register(socket.id, new ShellAmpy());
|
||||
this.#addEventsListenerForMode2_(socket);
|
||||
});
|
||||
usb.on('attach', (device) => {
|
||||
this.#namespaceAll_.emit('serial.attachEvent', device);
|
||||
});
|
||||
usb.on('detach', (device) => {
|
||||
this.#namespaceAll_.emit('serial.detachEvent', device);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForMode1_(socket) {
|
||||
socket.on('disconnect', () => {
|
||||
const folderPath = path.resolve(TEMP_PATH, socket.id);
|
||||
fsExtra.remove(folderPath).catch(Debug.error);
|
||||
const shellArduino = this.#shellArduino_.getItem(socket.id);
|
||||
shellArduino.dispose();
|
||||
this.#shellArduino_.unregister(socket.id);
|
||||
});
|
||||
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
shell.bind('data', (data) => {
|
||||
socket.emit('arduino.dataEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('error', (data) => {
|
||||
socket.emit('arduino.errorEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('close', (code, time) => {
|
||||
socket.emit('arduino.closeEvent', code, time);
|
||||
});
|
||||
|
||||
socket.on('arduino.compile', async (config, callback) => {
|
||||
if (!Boards.exist(config.key)) {
|
||||
callback(['illegal board name', {}]);
|
||||
return;
|
||||
}
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path = config?.path ?? {};
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
config.path.code = path.resolve(TEMP_PATH, socket.id, '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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(shell.compile(config));
|
||||
if (error) {
|
||||
Debug.error(error);
|
||||
callback([error, result]);
|
||||
return;
|
||||
}
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.upload', async (config, callback) => {
|
||||
if (!Boards.exist(config.key)) {
|
||||
callback(['illegal board name', {}]);
|
||||
return;
|
||||
}
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path = config?.path ?? {};
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
config.path.code = path.resolve(TEMP_PATH, socket.id, '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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(shell.compile(config));
|
||||
if (error) {
|
||||
Debug.error(error);
|
||||
callback([error, result]);
|
||||
return;
|
||||
}
|
||||
if (result.code === 0) {
|
||||
const buildPath = config.path.build;
|
||||
result.files = await Boards.getFiles(config.key, buildPath);
|
||||
}
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.kill', async (callback) => {
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.kill());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForMode2_(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);
|
||||
}
|
||||
const folderPath = path.resolve(TEMP_PATH, socket.id);
|
||||
fsExtra.remove(folderPath).catch(Debug.error);
|
||||
const shellMicropython = this.#shellMicroPython_.getItem(socket.id);
|
||||
shellMicropython.dispose();
|
||||
this.#shellMicroPython_.unregister(socket.id);
|
||||
const shellArduino = this.#shellArduino_.getItem(socket.id);
|
||||
shellArduino.dispose();
|
||||
this.#shellArduino_.unregister(socket.id);
|
||||
const shellAmpy = this.#shellAmpy_.getItem(socket.id);
|
||||
shellAmpy.dispose();
|
||||
this.#shellAmpy_.unregister(socket.id);
|
||||
});
|
||||
|
||||
this.#addEventsListenerForMode2MicroPython_(socket);
|
||||
this.#addEventsListenerForMode2Arduino_(socket);
|
||||
this.#addEventsListenerForMode2Ampy_(socket);
|
||||
this.#addEventsListenerForMode2Serial_(socket);
|
||||
}
|
||||
|
||||
#addEventsListenerForMode2MicroPython_(socket) {
|
||||
const shell = this.#shellMicroPython_.getItem(socket.id);
|
||||
shell.bind('data', (data) => {
|
||||
socket.emit('arduino.dataEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('error', (data) => {
|
||||
socket.emit('arduino.errorEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('close', (code, time) => {
|
||||
socket.emit('arduino.closeEvent', code, time);
|
||||
});
|
||||
|
||||
socket.on('micropython.burn', async (config, callback) => {
|
||||
const shell = this.#shellMicroPython_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.burn(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('micropython.upload', async (config, callback) => {
|
||||
const shell = this.#shellMicroPython_.getItem(socket.id);
|
||||
let { filePath = '', libraries = {} } = config;
|
||||
filePath = MString.tpl(filePath, {
|
||||
indexPath: path.resolve(CLIENT_PATH, config.boardDirPath)
|
||||
});
|
||||
const dirname = path.dirname(filePath);
|
||||
await to(fsExtra.ensureDir(dirname));
|
||||
await to(fsExtra.emptyDir(dirname));
|
||||
await to(fsExtra.outputFile(filePath, config.code));
|
||||
if (libraries && libraries instanceof Object) {
|
||||
for (let key in libraries) {
|
||||
await to(fsExtra.outputFile(path.resolve(dirname, key), libraries[key]));
|
||||
}
|
||||
}
|
||||
const [error, result] = await to(shell.upload(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('micropython.kill', async (callback) => {
|
||||
const shell = this.#shellMicroPython_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.kill());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForMode2Arduino_(socket) {
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
shell.bind('data', (data) => {
|
||||
socket.emit('arduino.dataEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('error', (data) => {
|
||||
socket.emit('arduino.errorEvent', data);
|
||||
});
|
||||
|
||||
shell.bind('close', (code, time) => {
|
||||
socket.emit('arduino.closeEvent', code, time);
|
||||
});
|
||||
|
||||
socket.on('arduino.compile', async (config, callback) => {
|
||||
console.log(config)
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path = config?.path ?? {};
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
config.path.code = path.resolve(TEMP_PATH, socket.id, '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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(shell.compile(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.upload', async (config, callback) => {
|
||||
config.path = config?.path ?? {};
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
config.path.build = path.resolve(TEMP_PATH, socket.id, 'build');
|
||||
config.path.code = path.resolve(TEMP_PATH, socket.id, '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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(shell.upload(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.kill', async (callback) => {
|
||||
const shell = this.#shellArduino_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.kill());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForMode2Ampy_(socket) {
|
||||
socket.on('ampy.ls', async (port, baud, folderPath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.ls(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.get', async (port, baud, filePath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.get(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.mkdir', async (port, baud, folderPath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.mkdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.mkfile', async (port, baud, filePath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.mkfile(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.isdir', async (port, baud, folderPath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.isdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.isfile', async (port, baud, filePath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.isfile(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.put', async (port, baud, filePath, data, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const startPath = path.join(TEMP_PATH, socket.id, 'ampy/temp').replaceAll('\\', '/');
|
||||
const endPath = filePath;
|
||||
await to(fsExtra.outputFile(startPath, data));
|
||||
const [error, result] = await to(shell.put(port, baud, startPath, endPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rm', async (port, baud, filePath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.rm(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rmdir', async (port, baud, folderPath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.rmdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rename', async (port, baud, oldPath, newPath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.rm(port, baud, oldPath, newPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.run', async (port, baud, filePath, callback) => {
|
||||
const shell = this.#shellAmpy_.getItem(socket.id);
|
||||
const [error, result] = await to(shell.rm(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForMode2Serial_(socket) {
|
||||
socket.on('serial.getPorts', async (callback) => {
|
||||
const [error, result] = await to(Serial.getPorts());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.create', (port) => {
|
||||
const serial = new Serial(port);
|
||||
this.#serialRegistry_.register(port, serial);
|
||||
serial.bind('buffer', (buffer) => {
|
||||
socket.emit('serial.bufferEvent', port, buffer);
|
||||
});
|
||||
serial.bind('string', (str) => {
|
||||
socket.emit('serial.stringEvent', port, str);
|
||||
});
|
||||
serial.bind('error', (error) => {
|
||||
socket.emit('serial.errorEvent', port, error);
|
||||
});
|
||||
serial.bind('open', () => {
|
||||
socket.emit('serial.openEvent', port);
|
||||
});
|
||||
serial.bind('close', (code) => {
|
||||
socket.emit('serial.closeEvent', port, code);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('serial.dispose', async (port, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.dispose());
|
||||
error && Debug.error(error);
|
||||
this.#serialRegistry_.unregister(port);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.open', async (port, baud, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.open(baud));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.close', async (port, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.close());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.setBaudRate', async (port, baud, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.setBaudRate(baud));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.send', async (port, data, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.send(data));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.setDTRAndRTS', async (port, dtr, rts, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.setDTRAndRTS(dtr, rts));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
getIO() {
|
||||
return this.#io_;
|
||||
}
|
||||
}
|
||||
26
src/index.js
26
src/index.js
@@ -2,10 +2,10 @@ import express from 'express';
|
||||
import path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { createServer } from 'https';
|
||||
import Socket from './web-socket/socket';
|
||||
|
||||
import { createServer } from 'node:https';
|
||||
import Socket from './common/socket';
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
const __dirname = path.dirname(url.fileURLToPath(new URL(import.meta.url)));
|
||||
const app = express();
|
||||
const httpsServer = createServer({
|
||||
@@ -13,8 +13,9 @@ const httpsServer = createServer({
|
||||
cert: readFileSync(path.resolve(__dirname, '../certs/server.crt'))
|
||||
}, app);
|
||||
|
||||
new Socket(httpsServer, {
|
||||
const socket = new Socket(httpsServer, {
|
||||
path: '/mixly-socket/',
|
||||
maxHttpBufferSize: 1e8,
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ['GET', 'POST'],
|
||||
@@ -23,4 +24,21 @@ new Socket(httpsServer, {
|
||||
}
|
||||
});
|
||||
|
||||
const io = socket.getIO();
|
||||
|
||||
function close() {
|
||||
io.close(() => {
|
||||
console.log('Socket服务已关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
close();
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
close();
|
||||
});
|
||||
|
||||
httpsServer.listen(4000);
|
||||
@@ -2,27 +2,26 @@
|
||||
"debug": true,
|
||||
"arduino": {
|
||||
"path": {
|
||||
"folder": "D:/gitee/mixly/arduino-cli",
|
||||
"cli": "D:/gitee/mixly/arduino-cli/arduino-cli.exe",
|
||||
"folder": "D:/gitee/arduino-cli-win32/arduino-cli",
|
||||
"cli": "D:/gitee/arduino-cli-win32/arduino-cli/arduino-cli.exe",
|
||||
"libraries": [
|
||||
"D:/gitee/mixly/arduino-cli/libraries"
|
||||
"D:/gitee/arduino-cli-win32/arduino-cli/libraries"
|
||||
],
|
||||
"cache": "D:/gitee/mixly/arduino-cli/cache",
|
||||
"config": "D:/gitee/mixly/arduino-cli/arduino-cli.json"
|
||||
"cache": "D:/gitee/arduino-cli-win32/arduino-cli/cache",
|
||||
"config": "D:/gitee/arduino-cli-win32/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"
|
||||
"ampy": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/ampy_main.py",
|
||||
"esptool": "D:/gitee/mixly3.0-win32-x64/resources/app/src/tools/python/esptool_main.py"
|
||||
}
|
||||
},
|
||||
"python": {
|
||||
"path": {
|
||||
"cli": "D:/gitee/mixly3-resource/mixly3.0-win32-x64/mixpyBuild/win_python3/python3.exe"
|
||||
"cli": "D:/gitee/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"
|
||||
"tempPath": "D:/gitee/mixly3-server/temp",
|
||||
"clientPath": "D:/gitee/mixly3.0-win32-x64/resources/app/src"
|
||||
}
|
||||
@@ -1,287 +0,0 @@
|
||||
import { Server } from 'socket.io';
|
||||
import to from 'await-to-js';
|
||||
import { usb } from 'usb';
|
||||
import path from 'node:path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import Serial from '../common/serial';
|
||||
import Debug from '../common/debug';
|
||||
import Registry from '../common/registry';
|
||||
import ShellArduino from '../common/shell-arduino';
|
||||
import ShellMicroPython from '../common/shell-micropython';
|
||||
import ShellAmpy from '../common/shell-ampy';
|
||||
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();
|
||||
#shellAmpy_ = new ShellAmpy();
|
||||
|
||||
constructor(httpsServer, options) {
|
||||
this.#io_ = new Server(httpsServer, options);
|
||||
this.#io_.on('connection', (socket) => {
|
||||
this.#addEventsListener_(socket);
|
||||
});
|
||||
usb.on('attach', (device) => {
|
||||
this.#io_.emit('serial.attachEvent', device);
|
||||
});
|
||||
usb.on('detach', (device) => {
|
||||
this.#io_.emit('serial.detachEvent', device);
|
||||
});
|
||||
}
|
||||
|
||||
#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.#addEventsListenerForAmpy_(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 = '', libraries = {} } = config;
|
||||
filePath = MString.tpl(filePath, {
|
||||
indexPath: path.resolve(CLIENT_PATH, config.boardDirPath)
|
||||
});
|
||||
const dirname = path.dirname(filePath);
|
||||
await to(fsExtra.ensureDir(dirname));
|
||||
await to(fsExtra.emptyDir(dirname));
|
||||
await to(fsExtra.outputFile(filePath, config.code));
|
||||
if (libraries && libraries instanceof Object) {
|
||||
for (let key in libraries) {
|
||||
await to(fsExtra.outputFile(path.resolve(dirname, key), libraries[key]));
|
||||
}
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
this.#shellArduino_.bind('error', (data) => {
|
||||
socket.emit('arduino.errorEvent', data);
|
||||
});
|
||||
|
||||
this.#shellArduino_.bind('close', (code, time) => {
|
||||
socket.emit('arduino.closeEvent', code, time);
|
||||
});
|
||||
|
||||
socket.on('arduino.compile', async (config, callback) => {
|
||||
config.path = config?.path ?? {};
|
||||
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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(this.#shellArduino_.compile(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.upload', async (config, callback) => {
|
||||
config.path = config?.path ?? {};
|
||||
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));
|
||||
error2 && Debug.error(error2);
|
||||
const [error, result] = await to(this.#shellArduino_.upload(config));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('arduino.kill', async (callback) => {
|
||||
const [error, result] = await to(this.#shellArduino_.kill());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForAmpy_(socket) {
|
||||
socket.on('ampy.ls', async (port, baud, folderPath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.ls(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.get', async (port, baud, filePath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.get(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.mkdir', async (port, baud, folderPath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.mkdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.mkfile', async (port, baud, filePath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.mkfile(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.isdir', async (port, baud, folderPath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.isdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.isfile', async (port, baud, filePath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.isfile(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.put', async (port, baud, filePath, data, callback) => {
|
||||
const startPath = path.join(WEB_SOCKT_TEMP_PATH, 'ampy/temp').replaceAll('\\', '/');
|
||||
const endPath = filePath;
|
||||
await to(fsExtra.outputFile(startPath, data));
|
||||
const [error, result] = await to(this.#shellAmpy_.put(port, baud, startPath, endPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rm', async (port, baud, filePath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.rm(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rmdir', async (port, baud, folderPath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.rmdir(port, baud, folderPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.rename', async (port, baud, oldPath, newPath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.rm(port, baud, oldPath, newPath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('ampy.run', async (port, baud, filePath, callback) => {
|
||||
const [error, result] = await to(this.#shellAmpy_.rm(port, baud, filePath));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForSerial_(socket) {
|
||||
socket.on('serial.getPorts', async (callback) => {
|
||||
const [error, result] = await to(Serial.getPorts());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.create', (port) => {
|
||||
const serial = new Serial(port);
|
||||
this.#serialRegistry_.register(port, serial);
|
||||
serial.bind('buffer', (buffer) => {
|
||||
socket.emit('serial.bufferEvent', port, buffer);
|
||||
});
|
||||
serial.bind('string', (str) => {
|
||||
socket.emit('serial.stringEvent', port, str);
|
||||
});
|
||||
serial.bind('error', (error) => {
|
||||
socket.emit('serial.errorEvent', port, error);
|
||||
});
|
||||
serial.bind('open', () => {
|
||||
socket.emit('serial.openEvent', port);
|
||||
});
|
||||
serial.bind('close', (code) => {
|
||||
socket.emit('serial.closeEvent', port, code);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('serial.dispose', async (port, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.dispose());
|
||||
error && Debug.error(error);
|
||||
this.#serialRegistry_.unregister(port);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.open', async (port, baud, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.open(baud));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.close', async (port, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.close());
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.setBaudRate', async (port, baud, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.setBaudRate(baud));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.send', async (port, data, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.send(data));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
|
||||
socket.on('serial.setDTRAndRTS', async (port, dtr, rts, callback) => {
|
||||
const serial = this.#serialRegistry_.getItem(port);
|
||||
const [error, result] = await to(serial.setDTRAndRTS(dtr, rts));
|
||||
error && Debug.error(error);
|
||||
callback([error, result]);
|
||||
});
|
||||
}
|
||||
|
||||
getIO() {
|
||||
return this.#io_;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user