Update: 更新 Web USB

This commit is contained in:
王立帮
2024-12-20 18:51:04 +08:00
parent 03211cb1b2
commit 8727b62cb2
17 changed files with 1428 additions and 583 deletions

View File

@@ -8,7 +8,6 @@ goog.require('Mixly.MArray');
goog.require('Mixly.Boards');
goog.require('Mixly.XML');
goog.require('Mixly.LayerExt');
goog.require('Mixly.MicrobitFs');
goog.require('Mixly.Msg');
goog.provide('Mixly.MFile');
@@ -20,7 +19,6 @@ const {
Boards,
XML,
LayerExt,
MicrobitFs,
Msg,
MFile
} = Mixly;
@@ -108,15 +106,6 @@ MFile.getCode = (type) => {
}
}
MFile.getHex = () => {
const code = MFile.getCode();
return MicrobitFs.getHex(code);
}
MFile.loadHex = (hexStr) => {
MicrobitFs.loadHex('main.py', hexStr);
}
MFile.getMix = () => {
const mixDom = $(Blockly.Xml.workspaceToDom(Editor.blockEditor)),
version = SOFTWARE?.version ?? 'Mixly 2.0',

View File

@@ -1,151 +0,0 @@
/**
* Wrapper for microbit-fs and microbit-universal-hex to perform filesystem
* operations into two hex files.
* https://github.com/microbit-foundation/microbit-fs
* https://github.com/microbit-foundation/microbit-universal-hex
*/
goog.loadJs('common', () => {
'use strict';
goog.require('microbitFs');
goog.provide('fsWrapper');
/**
* @returns An object with the fs wrapper.
*/
var uPyFs = null;
var commonFsSize = 20 * 1024;
var passthroughMethods = [
'create',
'exists',
'getStorageRemaining',
'getStorageSize',
'getStorageUsed',
'getUniversalHex',
'ls',
'read',
'readBytes',
'remove',
'size',
'write',
];
/**
* Duplicates some of the methods from the MicropythonFsHex class by
* creating functions with the same name in this object.
*/
function duplicateMethods() {
passthroughMethods.forEach(function(method) {
fsWrapper[method] = function() {
return uPyFs[method].apply(uPyFs, arguments);
};
});
}
/**
* Fetches both MicroPython hexes and sets up the file system with the
* initial main.py
*/
fsWrapper.setupFilesystem = function() {
var uPyV1 = null;
var uPyV2 = null;
var deferred1 = $.get('../common/micropython/microbit-micropython-v1.hex', function(fileStr) {
uPyV1 = fileStr;
}).fail(function() {
console.error('Could not load the MicroPython v1 file.');
});
var deferred2 = $.get('../common/micropython/microbit-micropython-v2.hex', function(fileStr) {
uPyV2 = fileStr;
}).fail(function() {
console.error('Could not load the MicroPython v2 file.');
});
return $.when(deferred1, deferred2).done(function() {
if (!uPyV1 || !uPyV2) {
console.error('There was an issue loading the MicroPython Hex files.');
}
// TODO: We need to use ID 9901 for app compatibility, but can soon be changed to 9900 (as per spec)
uPyFs = new microbitFs.MicropythonFsHex([
{ hex: uPyV1, boardId: 0x9901 },
{ hex: uPyV2, boardId: 0x9903 },
], {
'maxFsSize': commonFsSize,
});
duplicateMethods();
});
};
/**
* @param {string} boardId String with the Board ID for the generation.
* @returns Uint8Array with the data for the given Board ID.
*/
fsWrapper.getBytesForBoardId = function(boardId) {
if (boardId == '9900' || boardId == '9901') {
return uPyFs.getIntelHexBytes(0x9901);
} else if (boardId == '9903' || boardId == '9904') {
return uPyFs.getIntelHexBytes(0x9903);
} else {
throw Error('Could not recognise the Board ID ' + boardId);
}
};
/**
* @param {string} boardId String with the Board ID for the generation.
* @returns ArrayBuffer with the Intel Hex data for the given Board ID.
*/
fsWrapper.getIntelHexForBoardId = function(boardId) {
if (boardId == '9900' || boardId == '9901') {
var hexStr = uPyFs.getIntelHex(0x9901);
} else if (boardId == '9903' || boardId == '9904') {
var hexStr = uPyFs.getIntelHex(0x9903);
} else {
throw Error('Could not recognise the Board ID ' + boardId);
}
// iHex is ASCII so we can do a 1-to-1 conversion from chars to bytes
var hexBuffer = new Uint8Array(hexStr.length);
for (var i = 0, strLen = hexStr.length; i < strLen; i++) {
hexBuffer[i] = hexStr.charCodeAt(i);
}
return hexBuffer.buffer;
};
/**
* Import the files from the provide hex string into the filesystem.
* If the import is successful this deletes all the previous files.
*
* @param {string} hexStr Hex (Intel or Universal) string with files to
* import.
* @return {string[]} Array with the filenames of all files imported.
*/
fsWrapper.importHexFiles = function(hexStr) {
var filesNames = uPyFs.importFilesFromHex(hexStr, {
overwrite: true,
formatFirst: true
});
if (!filesNames.length) {
throw new Error('The filesystem in the hex file was empty');
}
return filesNames;
};
/**
* Import an appended script from the provide hex string into the filesystem.
* If the import is successful this deletes all the previous files.
*
* @param {string} hexStr Hex (Intel or Universal) string with files to
* import.
* @return {string[]} Array with the filenames of all files imported.
*/
fsWrapper.importHexAppended = function(hexStr) {
var code = microbitFs.getIntelHexAppendedScript(hexStr);
if (!code) {
throw new Error('No appended code found in the hex file');
};
uPyFs.ls().forEach(function(fileName) {
uPyFs.remove(fileName);
});
uPyFs.write('main.py', code);
return ['main.py'];
};
});

View File

@@ -1,137 +0,0 @@
goog.loadJs('common', () => {
goog.require('fsWrapper');
goog.require('Mixly.Config');
goog.provide('Mixly.MicrobitFs');
const {
Config,
MicrobitFs
} = Mixly;
const { BOARD } = Config;
const { nav = {} } = BOARD;
MicrobitFs.init = () => {
fsWrapper.setupFilesystem()
.then(() => {
console.log('初始化成功');
})
.fail(() => {
console.log('初始化失败');
});
}
if (!nav.compile && nav.upload && nav.save?.hex)
MicrobitFs.init();
// Reset the filesystem and load the files from this hex file to the fsWrapper and editor
MicrobitFs.loadHex = (filename, hexStr) => {
var importedFiles = [];
// If hexStr is parsed correctly it formats the file system before adding the new files
try {
importedFiles = fsWrapper.importHexFiles(hexStr);
} catch (hexImportError) {
try {
importedFiles = fsWrapper.importHexAppended(hexStr);
} catch (appendedError) {
console.log(hexImportError.message);
}
}
// Check if imported files includes a main.py file
var code = '';
if (importedFiles.indexOf(filename) > -1) {
code = fsWrapper.read(filename);
} else {
alert('no ' + filename);
}
Editor.mainEditor.drag.full('NEGATIVE'); // 完全显示代码编辑器
Editor.codeEditor.setValue(code, -1);
}
// Function for adding file to filesystem
MicrobitFs.loadFileToFilesystem = (filename, fileBytes) => {
// For main.py confirm if the user wants to replace the editor content
if (filename === 'main.py') {
return;
}
try {
if (fsWrapper.exists(filename)) {
fsWrapper.remove(filename);
fsWrapper.create(filename, fileBytes);
} else {
fsWrapper.write(filename, fileBytes);
}
// Check if the filesystem has run out of space
var _ = fsWrapper.getUniversalHex();
} catch (e) {
if (fsWrapper.exists(filename)) {
fsWrapper.remove(filename);
}
return alert(filename + '\n' + e.message);
}
}
MicrobitFs.updateMainPy = (code) => {
try {
// Remove main.py if editor content is empty to download a hex file
// with MicroPython included (also includes the rest of the filesystem)
if (fsWrapper.exists('main.py')) {
fsWrapper.remove('main.py');
}
for (var i = 0; i < py_module.length; i++) {
if (fsWrapper.exists(py_module[i]['filename'])) {
fsWrapper.remove(py_module[i]['filename']);
}
}
if (code) {
fsWrapper.create('main.py', code);
}
var str = code;
var arrayObj = new Array();
str.trim().split("\n").forEach(function (v, i) {
arrayObj.push(v);
});
let moduleName = "";
for (var i = 0; i < arrayObj.length; i++) {
if (arrayObj[i].indexOf("from") == 0) {
moduleName = arrayObj[i].substring(4, arrayObj[i].indexOf("import"));
moduleName = moduleName.replace(/(^\s*)|(\s*$)/g, "");
if (fsWrapper.exists(moduleName + '.py'))
continue;
for (var j = 0; j < py_module.length; j++) {
if (py_module[j]['filename'] == moduleName + ".py") {
MicrobitFs.loadFileToFilesystem(py_module[j]['filename'], py_module[j]['code']);
}
}
} else if (arrayObj[i].indexOf("import") == 0) {
moduleName = arrayObj[i].substring(6);
moduleName = moduleName.replace(/(^\s*)|(\s*$)/g, "");
if (fsWrapper.exists(moduleName + '.py'))
continue;
for (var j = 0; j < py_module.length; j++) {
if (py_module[j]['filename'] == moduleName + ".py") {
MicrobitFs.loadFileToFilesystem(py_module[j]['filename'], py_module[j]['code']);
}
}
}
}
} catch (e) {
// We generate a user readable error here to be caught and displayed
throw new Error(e.message);
}
}
MicrobitFs.getHex = (code) => {
try {
MicrobitFs.updateMainPy(code);
return output = fsWrapper.getUniversalHex();
} catch (e) {
alert(e.message);
return null;
}
}
});

View File

@@ -186,7 +186,8 @@ class StatusBarsManager extends PagesManager {
}
});*/
if (['micropython', 'circuitpython'].includes(BOARD.language.toLowerCase())) {
if (['micropython', 'circuitpython'].includes(BOARD.language.toLowerCase())
&& !['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) {
menu.add({
weight: 2,
type: 'sep1',