Update: WebSocket下MicroPython板卡支持管理板卡文件
This commit is contained in:
@@ -1,17 +1,34 @@
|
|||||||
goog.loadJs('common', () => {
|
goog.loadJs('common', () => {
|
||||||
|
|
||||||
|
goog.require('Mixly.Env');
|
||||||
goog.require('Mixly.FileTree');
|
goog.require('Mixly.FileTree');
|
||||||
goog.require('Mixly.Electron.AmpyFS');
|
goog.require('Mixly.Electron.AmpyFS');
|
||||||
goog.require('Mixly.Web.AmpyFS');
|
goog.require('Mixly.Web.AmpyFS');
|
||||||
|
goog.require('Mixly.WebSocket.AmpyFS');
|
||||||
goog.provide('Mixly.AmpyFileTree');
|
goog.provide('Mixly.AmpyFileTree');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
Env,
|
||||||
FileTree,
|
FileTree,
|
||||||
Electron = {},
|
Electron = {},
|
||||||
Web = {}
|
Web = {},
|
||||||
|
WebSocket = {}
|
||||||
} = Mixly;
|
} = 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 {
|
class AmpyFileTree extends FileTree {
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
{
|
{
|
||||||
"path": "/common/ampy-file-tree.js",
|
"path": "/common/ampy-file-tree.js",
|
||||||
"require": [
|
"require": [
|
||||||
|
"Mixly.Env",
|
||||||
"Mixly.FileTree",
|
"Mixly.FileTree",
|
||||||
"Mixly.Electron.AmpyFS",
|
"Mixly.Electron.AmpyFS",
|
||||||
"Mixly.Web.AmpyFS"
|
"Mixly.Web.AmpyFS",
|
||||||
|
"Mixly.WebSocket.AmpyFS"
|
||||||
],
|
],
|
||||||
"provide": [
|
"provide": [
|
||||||
"Mixly.AmpyFileTree"
|
"Mixly.AmpyFileTree"
|
||||||
@@ -1718,6 +1720,34 @@
|
|||||||
"Mixly.WebCompiler"
|
"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",
|
"path": "/web-socket/arduino-shell.js",
|
||||||
"require": [
|
"require": [
|
||||||
@@ -1784,7 +1814,8 @@
|
|||||||
"Mixly.WebSocket",
|
"Mixly.WebSocket",
|
||||||
"Mixly.WebSocket.Serial",
|
"Mixly.WebSocket.Serial",
|
||||||
"Mixly.WebSocket.ArduShell",
|
"Mixly.WebSocket.ArduShell",
|
||||||
"Mixly.WebSocket.BU"
|
"Mixly.WebSocket.BU",
|
||||||
|
"Mixly.WebSocket.Ampy"
|
||||||
],
|
],
|
||||||
"provide": [
|
"provide": [
|
||||||
"Mixly.WebSocket.Socket"
|
"Mixly.WebSocket.Socket"
|
||||||
|
|||||||
201
common/modules/mixly-modules/web-socket/ampy-fs.js
Normal file
201
common/modules/mixly-modules/web-socket/ampy-fs.js
Normal 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;
|
||||||
|
|
||||||
|
});
|
||||||
108
common/modules/mixly-modules/web-socket/ampy.js
Normal file
108
common/modules/mixly-modules/web-socket/ampy.js
Normal 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;
|
||||||
|
|
||||||
|
});
|
||||||
@@ -6,6 +6,7 @@ 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.require('Mixly.WebSocket.BU');
|
||||||
|
goog.require('Mixly.WebSocket.Ampy');
|
||||||
goog.provide('Mixly.WebSocket.Socket');
|
goog.provide('Mixly.WebSocket.Socket');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -18,7 +19,8 @@ const {
|
|||||||
Socket,
|
Socket,
|
||||||
Serial,
|
Serial,
|
||||||
ArduShell,
|
ArduShell,
|
||||||
BU
|
BU,
|
||||||
|
Ampy
|
||||||
} = WebSocket;
|
} = WebSocket;
|
||||||
|
|
||||||
|
|
||||||
@@ -76,6 +78,7 @@ Socket.init = function () {
|
|||||||
Serial.init(mixlySocket);
|
Serial.init(mixlySocket);
|
||||||
ArduShell.init(mixlySocket);
|
ArduShell.init(mixlySocket);
|
||||||
BU.init(mixlySocket);
|
BU.init(mixlySocket);
|
||||||
|
Ampy.init(mixlySocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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() {
|
getSocket() {
|
||||||
return this.#socket_;
|
return this.#socket_;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user