From f128bb06f9a5fb285d5bfe22a1bad1a9b5d24659 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Fri, 30 Aug 2024 11:05:59 +0100 Subject: [PATCH] Fixed auto-connect delay and upgraded to pico-mpy-com v1.0.1 to fix filesystem errors Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package-lock.json | 8 +-- package.json | 2 +- src/activator.mts | 137 ++++++++++++++------------------------------- src/filesystem.mts | 9 ++- 4 files changed, 50 insertions(+), 106 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4c2d9b..ea4b739 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "linux" ], "dependencies": { - "@paulober/pico-mpy-com": "^1.0.0", + "@paulober/pico-mpy-com": "^1.0.1", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.5", "fs-extra": "^11.2.0", @@ -331,9 +331,9 @@ } }, "node_modules/@paulober/pico-mpy-com": { - "version": "1.0.0", - "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.0/90fbe781f900dab9e9418e1df4ec7d9f2ac348cd", - "integrity": "sha512-np8mENLNP5x/PbSmC98ikELUePt74wbOuttsRkxYSonmh8jUEz9oITZMTUFd4WDuSuBi+N8rT84orKShMzn+Dg==", + "version": "1.0.1", + "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.1/80242a15979202a6c543bf56779a1d0be781d635", + "integrity": "sha512-K7dMxuCOksVxdOtBnI1ZALp/pqnKs3t/YctViHZQOmC7hjfFwvb+kPxYqdHREUN5SjO8zw2pgwhazhKMgLWFkQ==", "cpu": [ "x64", "arm64" diff --git a/package.json b/package.json index 8576b25..c6b5218 100644 --- a/package.json +++ b/package.json @@ -611,7 +611,7 @@ "typescript-eslint": "^8.3.0" }, "dependencies": { - "@paulober/pico-mpy-com": "^1.0.0", + "@paulober/pico-mpy-com": "^1.0.1", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.5", "fs-extra": "^11.2.0", diff --git a/src/activator.mts b/src/activator.mts index 1ace5b0..f07a33c 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -22,7 +22,7 @@ import Stubs, { import Settings, { SettingsKey } from "./settings.mjs"; import Logger from "./logger.mjs"; import { basename, dirname, join } from "path"; -import { PicoWFs } from "./filesystem.mjs"; +import { PicoRemoteFileSystem } from "./filesystem.mjs"; import { Terminal } from "./terminal.mjs"; import { fileURLToPath } from "url"; import { ContextKeys } from "./models/contextKeys.mjs"; @@ -47,7 +47,7 @@ export default class Activator { private logger: Logger; private ui?: UI; private stubs?: Stubs; - private picoFs?: PicoWFs; + private picoFs?: PicoRemoteFileSystem; private terminal?: Terminal; private pythonPath?: string; @@ -74,8 +74,10 @@ export default class Activator { } ) ); - // get currently selected environment - this.pythonPath = pythonApi.environments.getActiveEnvironmentPath()?.path; + setImmediate(() => { + // get currently selected environment + this.pythonPath = pythonApi.environments.getActiveEnvironmentPath()?.path; + }); // execute async not await void vscode.commands.executeCommand( @@ -267,7 +269,7 @@ export default class Activator { ); // register fs provider as early as possible - this.picoFs = new PicoWFs(); + this.picoFs = new PicoRemoteFileSystem(); context.subscriptions.push( vscode.workspace.registerFileSystemProvider("pico", this.picoFs, { isCaseSensitive: true, @@ -1311,7 +1313,7 @@ export default class Activator { PicoMpyCom.getInstance().on( PicoSerialEvents.portError, - this.boardOnExit.bind(this) + this.boardOnError.bind(this) ); PicoMpyCom.getInstance().on( PicoSerialEvents.portClosed, @@ -1324,10 +1326,15 @@ export default class Activator { this.logger.debug( "Connected to a board. Now executing *OnConnect stuff..." ); + this.logger.info("Connection to board successfully established"); this.terminal?.cls(); this.terminal?.open(undefined); + void vscode.window.showInformationMessage( + "Connection to MicoPython board established." + ); + const scriptToExecute = settings.getString(SettingsKey.executeOnConnect); if (scriptToExecute !== undefined && scriptToExecute.trim() !== "") { void vscode.commands.executeCommand( @@ -1420,103 +1427,41 @@ export default class Activator { }); }; + // required because setInterval would call it first after 1500ms + onAutoConnect(); + // setup interval this.autoConnectTimer = setInterval(onAutoConnect, 1500); - - // TODO: implement auto connect based on event emitter of PicoMpyCom - /*this.autoConnectTimer = setInterval( - // TODO (important): this should not take longer than 2500ms because - // then the there would b a hell of a concurrency problem - () => - void (async () => { - // this could let the PyboardRunner let recognize that it lost connection to - // the pyboard wrapper and mark the Pico as disconnected - // O(1) - if (PicoMpyCom.getInstance().) { - // ensure that the script is only executed once - if (this.ui?.getState() === false) { - const scriptToExecute = settings.getString( - SettingsKey.executeOnConnect - ); - if ( - scriptToExecute !== undefined && - scriptToExecute.trim() !== "" - ) { - void vscode.commands.executeCommand( - commandPrefix + "remote.run", - scriptToExecute - ); - } - - const moduleToImport = settings.getString( - SettingsKey.importOnConnect - ); - if ( - moduleToImport !== undefined && - moduleToImport.trim() !== "" - ) { - await this.pyb?.executeCommand(`import ${moduleToImport}`); - } - } - this.ui?.refreshState(true); - - return; - } - this.ui?.refreshState(false); - settings.reload(); - const autoPort = settings.getBoolean(SettingsKey.autoConnect); - - const ports = await PyboardRunner.getPorts(); - if (ports.ports.length === 0) { - return; - } - - // try to connect to previously connected device first - if (this.comDevice && ports.ports.includes(this.comDevice)) { - // try to reconnect - this.pyb?.switchDevice(this.comDevice); - await new Promise(resolve => setTimeout(resolve, 1000)); - if (this.pyb?.isPipeConnected()) { - return; - } - } - - if (autoPort) { - const port = ports.ports[0]; - this.comDevice = port; - this.pyb?.switchDevice(port); - } - })(), - 2500 - );*/ } private showNoActivePythonError(): void { - // TODO: add details button taking them to the python extension docs - void vscode.window.showWarningMessage( - "Python path not found. Please check your Python environment.\n" + - "See the Python extension for instructions on how to select " + - "a Python interpreter." - ); + vscode.window + .showWarningMessage( + "Python path not found. Please check your Python environment.\n" + + "See the Python extension for instructions on how to select " + + "a Python interpreter.", + "Open Documentation" + ) + .then(selection => { + if (selection?.toLocaleLowerCase().startsWith("open")) { + vscode.env.openExternal( + vscode.Uri.parse( + // eslint-disable-next-line max-len + "https://code.visualstudio.com/docs/languages/python#_environments" + ) + ); + } + }); } - private pyboardOnError(data: Buffer | undefined): void { - if ( - data === undefined && - this.comDevice !== undefined && - this.comDevice !== "" && - this.comDevice !== "default" - ) { - //this.ui?.refreshState(true); - this.logger.info("Connection to wrapper successfully established"); - void vscode.window.showInformationMessage( - "Connection to board established." + private boardOnError(error?: Error): void { + if (error) { + void vscode.window.showErrorMessage( + error instanceof Error + ? error.message + : typeof error === "string" + ? error + : "Unknown error" ); - - return; - } else { - if (data) { - void vscode.window.showErrorMessage(data.toString("utf-8")); - } } } diff --git a/src/filesystem.mts b/src/filesystem.mts index 05b99d0..6b46e6f 100644 --- a/src/filesystem.mts +++ b/src/filesystem.mts @@ -30,7 +30,7 @@ const forbiddenFolders = [".vscode", ".git"]; // disabled because the Python and Pylance extensions don't currently support virtual workspaces const picoWFsVscodeConfiguration = false; -export class PicoWFs implements FileSystemProvider { +export class PicoRemoteFileSystem implements FileSystemProvider { private logger: Logger; //private cache: Map = new Map(); @@ -43,7 +43,7 @@ export class PicoWFs implements FileSystemProvider { public onDidChangeFile: Event = this._emitter.event; constructor() { - this.logger = new Logger("PicoWFs"); + this.logger = new Logger("PicoRemoteFileSystem"); if (picoWFsVscodeConfiguration) { void getTypeshedPicoWStubPath().then(path => { @@ -112,7 +112,7 @@ export class PicoWFs implements FileSystemProvider { const result = await PicoMpyCom.getInstance().getItemStat(uri.path); if (result.type !== OperationResultType.getItemStat) { - this.logger.error("stat: unexpected result type"); + this.logger.error("stat: unexpected result type for " + uri.path); throw FileSystemError.Unavailable(uri); } @@ -211,8 +211,7 @@ export class PicoWFs implements FileSystemProvider { ); if (result.type === OperationResultType.commandResult) { - const status = result.result; - if (!status) { + if (!result.result) { this.logger.error("readFile: File not found"); throw FileSystemError.FileNotFound(uri); } else {