Update: WebSocket下MicroPython板卡支持管理板卡文件

This commit is contained in:
王立帮
2024-12-03 19:00:17 +08:00
parent 6dff4d2a98
commit c3212fecb1
6 changed files with 392 additions and 5 deletions

View File

@@ -1,17 +1,34 @@
goog.loadJs('common', () => {
goog.require('Mixly.Env');
goog.require('Mixly.FileTree');
goog.require('Mixly.Electron.AmpyFS');
goog.require('Mixly.Web.AmpyFS');
goog.require('Mixly.WebSocket.AmpyFS');
goog.provide('Mixly.AmpyFileTree');
const {
Env,
FileTree,
Electron = {},
Web = {}
Web = {},
WebSocket = {}
} = Mixly;
const { AmpyFS } = goog.isElectron? Electron : Web;
let currentObj = null;
if (goog.isElectron) {
currentObj = Electron;
} else {
if (Env.hasSocketServer) {
currentObj = WebSocket;
} else {
currentObj = Web;
}
}
const { AmpyFS } = currentObj;
class AmpyFileTree extends FileTree {

View File

@@ -2,9 +2,11 @@
{
"path": "/common/ampy-file-tree.js",
"require": [
"Mixly.Env",
"Mixly.FileTree",
"Mixly.Electron.AmpyFS",
"Mixly.Web.AmpyFS"
"Mixly.Web.AmpyFS",
"Mixly.WebSocket.AmpyFS"
],
"provide": [
"Mixly.AmpyFileTree"
@@ -1718,6 +1720,34 @@
"Mixly.WebCompiler"
]
},
{
"path": "/web-socket/ampy-fs.js",
"require": [
"path",
"Mixly.Env",
"Mixly.FS",
"Mixly.Debug",
"Mixly.MJSON",
"Mixly.WebSocket.Ampy"
],
"provide": [
"Mixly.WebSocket.AmpyFS"
]
},
{
"path": "/web-socket/ampy.js",
"require": [
"path",
"Mustache",
"Mixly.Ampy",
"Mixly.Env",
"Mixly.Serial",
"Mixly.WebSocket"
],
"provide": [
"Mixly.WebSocket.Ampy"
]
},
{
"path": "/web-socket/arduino-shell.js",
"require": [
@@ -1784,7 +1814,8 @@
"Mixly.WebSocket",
"Mixly.WebSocket.Serial",
"Mixly.WebSocket.ArduShell",
"Mixly.WebSocket.BU"
"Mixly.WebSocket.BU",
"Mixly.WebSocket.Ampy"
],
"provide": [
"Mixly.WebSocket.Socket"

View File

@@ -0,0 +1,201 @@
goog.loadJs('web', () => {
goog.require('path');
goog.require('Mixly.Env');
goog.require('Mixly.FS');
goog.require('Mixly.Debug');
goog.require('Mixly.MJSON');
goog.require('Mixly.WebSocket.Ampy');
goog.provide('Mixly.WebSocket.AmpyFS');
const {
Env,
FS,
Debug,
MJSON,
WebSocket
} = Mixly;
const { Ampy } = WebSocket;
class AmpyFS extends FS {
#ampy_ = null;
#port_ = '';
#baud_ = 115200;
#decoder_ = new TextDecoder('utf8');
constructor() {
super();
this.#ampy_ = new Ampy();
}
async rename(oldPath, newPath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.rename(this.#port_, this.#baud_, oldPath, newPath);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async createFile(filePath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.mkfile(this.#port_, this.#baud_, filePath);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async readFile(filePath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.get(this.#port_, this.#baud_, filePath);
stdout = this.#decoder_.decode(this.#ampy_.unhexlify(stdout));
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async writeFile(filePath, data) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.put(this.#port_, this.#baud_, filePath, data);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async isFile(filePath) {
/*const [error, stdout] = await this.readDirectory(filePath);
if (error) {
return true;
}
return false;*/
let error = null;
if (path.extname(filePath)) {
return [error, true];
} else {
return [error, false];
}
}
async renameFile(oldFilePath, newFilePath) {
return this.rename(oldFilePath, newFilePath);
}
// async moveFile(oldFilePath, newFilePath) {}
// async copyFile(oldFilePath, newFilePath) {}
async deleteFile(filePath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.rm(this.#port_, this.#baud_, filePath);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async createDirectory(folderPath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.mkdir(this.#port_, this.#baud_, folderPath);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async readDirectory(folderPath) {
let stdout = [], error = null;
try {
const output = await this.#ampy_.ls(this.#port_, this.#baud_, folderPath);
const dirs = Array.from(new Set(output.split('\r\n')));
for (let i in dirs) {
if (!dirs[i]) {
continue;
}
stdout.push(MJSON.parse(dirs[i].replaceAll('\'', '"')));
}
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
async isDirectory(folderPath) {
/*const [error, stdout] = await this.readDirectory(folderPath);
if (error) {
return false;
}
return true;*/
let error = null;
if (path.extname(folderPath)) {
return [error, false];
} else {
return [error, true];
}
}
async isDirectoryEmpty(folderPath) {
/*const [error, stdout] = await this.readDirectory(folderPath);
let isEmpty = false;
if (error || !stdout.length) {
isEmpty = true;
}*/
return [null, false];
}
async renameDirectory(oldFolderPath, newFolderPath) {
return this.rename(oldFolderPath, newFolderPath);
}
// async moveDirectory(oldFolderPath, newFolderPath) {}
// async copyDirectory(oldFolderPath, newFolderPath) {}
async deleteDirectory(folderPath) {
let stdout = '', error = null;
try {
stdout = await this.#ampy_.rmdir(this.#port_, this.#baud_, folderPath);
} catch (e) {
error = e;
Debug.error(error);
}
return [error, stdout];
}
setPortName(port) {
this.#port_ = port;
}
getPortName() {
return this.#port_;
}
setBaudRate(baud) {
this.#baud_ = baud;
}
getBaudRate() {
return this.#baud_;
}
}
WebSocket.AmpyFS = AmpyFS;
});

View File

@@ -0,0 +1,108 @@
goog.loadJs('web', () => {
goog.require('path');
goog.require('Mustache');
goog.require('Mixly.Ampy');
goog.require('Mixly.Env');
goog.require('Mixly.Serial');
goog.require('Mixly.WebSocket');
goog.provide('Mixly.WebSocket.Ampy');
const {
Ampy,
Env,
Serial,
WebSocket
} = Mixly;
class AmpyExt extends Ampy {
static {
this.mixlySocket = null;
this.socket = null;
this.getSocket = function () {
return this.socket;
}
this.getMixlySocket = function () {
return this.mixlySocket;
}
this.init = function (mixlySocket) {
this.mixlySocket = mixlySocket;
this.socket = mixlySocket.getSocket();
}
}
constructor() {
super();
}
async ls(port, baud, folderPath) {
return this.exec('ampy.ls', port, baud, folderPath);
}
async get(port, baud, filePath) {
return this.exec('ampy.get', port, baud, filePath);
}
async mkdir(port, baud, folderPath) {
return this.exec('ampy.mkdir', port, baud, folderPath);
}
async mkfile(port, baud, filePath) {
return this.exec('ampy.mkfile', port, baud, filePath);
}
async isdir(port, baud, folderPath) {
return this.exec('ampy.isdir', port, baud, folderPath);
}
async isfile(port, baud, filePath) {
return this.exec('ampy.isfile', port, baud, filePath);
}
async put(port, baud, filePath, data) {
return this.exec('ampy.put', port, baud, filePath, data);
}
async rm(port, baud, filePath) {
return this.exec('ampy.rm', port, baud, filePath);
}
async rmdir(port, baud, folderPath) {
return this.exec('ampy.rmdir', port, baud, folderPath);
}
async rename(port, baud, oldPath, newPath) {
return this.exec('ampy.rename', port, baud, oldPath, newPath);
}
async run(port, baud, filePath) {
return this.exec('ampy.run', port, baud, filePath);
}
async exec(eventType, port, ...args) {
const portsName = Serial.getCurrentPortsName();
if (!portsName.includes(port)) {
throw new Error('无可用串口');
return;
}
const { mainStatusBarTabs } = Mixly;
const statusBarSerial = mainStatusBarTabs.getStatusBarById(port);
if (statusBarSerial) {
await statusBarSerial.close();
}
const mixlySocket = AmpyExt.getMixlySocket();
const output = await mixlySocket.emitAsync(eventType, port, ...args);
if (output[0]) {
throw new Error(output[0]);
}
return output[1];
}
}
WebSocket.Ampy = AmpyExt;
});

View File

@@ -6,6 +6,7 @@ goog.require('Mixly.WebSocket');
goog.require('Mixly.WebSocket.Serial');
goog.require('Mixly.WebSocket.ArduShell');
goog.require('Mixly.WebSocket.BU');
goog.require('Mixly.WebSocket.Ampy');
goog.provide('Mixly.WebSocket.Socket');
const {
@@ -18,7 +19,8 @@ const {
Socket,
Serial,
ArduShell,
BU
BU,
Ampy
} = WebSocket;
@@ -76,6 +78,7 @@ Socket.init = function () {
Serial.init(mixlySocket);
ArduShell.init(mixlySocket);
BU.init(mixlySocket);
Ampy.init(mixlySocket);
}
});

View File

@@ -50,6 +50,33 @@ class WebSocket {
}
}
async emitAsync(eventName, ...args) {
return new Promise((resolve, reject) => {
if (this.isConnected()) {
const callback = (...callbackArgs) => {
if (callbackArgs[0].error) {
reject(callbackArgs[0].error);
return;
}
resolve(...callbackArgs);
}
let emitStatus = {
finished: false
};
let status = this.#socket_.emit(eventName, ...args, (...callbackArgs) => {
if (emitStatus.finished) {
return;
}
emitStatus.finished = true;
callback(...callbackArgs);
});
this.#detectStatus_(emitStatus, callback);
} else {
reject('socket is not connected');
}
})
}
getSocket() {
return this.#socket_;
}