From 66c4f83887c3e441875c4567313478c193c868ce Mon Sep 17 00:00:00 2001 From: Christella Cidolit Date: Thu, 15 Aug 2019 16:42:48 -0700 Subject: [PATCH 1/3] Adding a setting for the user to pick the port and passing it to the python process --- locales/en/out/constants.i18n.json | 3 +- locales/en/package.i18n.json | 5 +- package.json | 11 +- package.nls.json | 5 +- src/adafruit_circuitplayground/constants.py | 3 +- src/constants.ts | 26 +++-- src/debug_user_code.py | 17 ++- src/debuggerCommunicationServer.ts | 21 +++- src/extension.ts | 114 ++++++++++++++------ src/extension_utils/utils.ts | 89 ++++++++++----- src/python_constants.py | 2 + src/simulatorDebugConfigurationProvider.ts | 29 ++--- 12 files changed, 228 insertions(+), 97 deletions(-) diff --git a/locales/en/out/constants.i18n.json b/locales/en/out/constants.i18n.json index 4d587e2df..d438b129e 100644 --- a/locales/en/out/constants.i18n.json +++ b/locales/en/out/constants.i18n.json @@ -7,6 +7,7 @@ "dialogResponses.help": "I need help", "dialogResponses.installPython": "Install from python.org", "dialogResponses.tutorials": "Tutorials on Adafruit", + "error.debuggerServerInitFailed": "Warning : The Debugger Server cannot be opened. Please try to free the port {0} if it's already in use or select another one in your Settings 'Pacifica: Debugger Server Port' and start another debug session.\n You can still debug your code but you won't be able to use the Simulator.", "error.debuggingSessionInProgress": "[ERROR] A debugging session is currently in progress, please stop it before running your code. \n", "error.incorrectFileNameForDevice": "[ERROR] Can\\'t deploy to your Circuit Playground Express device, please rename your file to \"code.py\" or \"main.py\". \n", "error.incorrectFileNameForDevicePopup": "Seems like you have a different file name than what the CPX requires, please rename it to \"code.py\" or \"main.py\".", @@ -33,4 +34,4 @@ "label.webviewPanel": "Adafruit CPX", "name": "Pacifica Simulator", "warning.agreeAndRun": "By selecting ‘Agree and Run’, you understand the extension executes Python code on your local computer, which may be a potential security risk." -} \ No newline at end of file +} diff --git a/locales/en/package.i18n.json b/locales/en/package.i18n.json index 5280a0c1b..88e726942 100644 --- a/locales/en/package.i18n.json +++ b/locales/en/package.i18n.json @@ -11,5 +11,6 @@ "pacificaExtension.configuration.title": "Pacfica configuration", "pacificaExtension.configuration.properties.open": "Whether to show 'Open Simulator' icon in editor title menu.", "pacificaExtension.configuration.properties.device": "Whether to show 'Run Device' icon in editor title menu.", - "pacificaExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu." -} \ No newline at end of file + "pacificaExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu.", + "pacificaExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger." +} diff --git a/package.json b/package.json index 98ab18e9a..d74793f42 100644 --- a/package.json +++ b/package.json @@ -144,6 +144,12 @@ "default": true, "description": "%pacificaExtension.configuration.properties.device%", "scope": "resource" + }, + "pacifica.debuggerServerPort": { + "type": "number", + "default": 5678, + "description": "%pacificaExtension.configuration.properties.debuggerPort%", + "scope": "resource" } } }, @@ -180,7 +186,8 @@ "description": "Command line arguments passed to the program.", "default": [], "items": { - "type": "string" + "filePath": "string", + "serverPort": "string" } }, "rules": { @@ -298,4 +305,4 @@ "extensionDependencies": [ "ms-python.python" ] -} \ No newline at end of file +} diff --git a/package.nls.json b/package.nls.json index 5280a0c1b..88e726942 100644 --- a/package.nls.json +++ b/package.nls.json @@ -11,5 +11,6 @@ "pacificaExtension.configuration.title": "Pacfica configuration", "pacificaExtension.configuration.properties.open": "Whether to show 'Open Simulator' icon in editor title menu.", "pacificaExtension.configuration.properties.device": "Whether to show 'Run Device' icon in editor title menu.", - "pacificaExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu." -} \ No newline at end of file + "pacificaExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu.", + "pacificaExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger." +} diff --git a/src/adafruit_circuitplayground/constants.py b/src/adafruit_circuitplayground/constants.py index c044e2e02..acb1226ec 100644 --- a/src/adafruit_circuitplayground/constants.py +++ b/src/adafruit_circuitplayground/constants.py @@ -19,7 +19,8 @@ TIME_DELAY = 0.03 -DEFAULT_PORT = 5678 +DEFAULT_PORT = "5678" + EVENTS_BUTTON_PRESS = ['button_a', 'button_b', 'switch'] EVENTS_SENSOR_CHANGED = ['temperature', 'light', 'motion_x', 'motion_y', 'motion_z'] diff --git a/src/constants.ts b/src/constants.ts index 351bfd1f9..05df319a5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,7 +5,12 @@ import * as nls from "vscode-nls"; import * as path from "path"; import { MessageItem } from "vscode"; -export const DEFAULT_SERVER_PORT: number = 5678; +// Debugger Server +export const SERVER_INFO = { + DEFAULT_SERVER_PORT: 5678, + ERROR_CODE_INIT_SERVER: "ERROR_INIT_SERVER", + SERVER_PORT_CONFIGURATION: "pacifica.debuggerServerPort" +}; const localize: nls.LocalizeFunc = nls.config({ messageFormat: nls.MessageFormat.file @@ -19,11 +24,18 @@ export const CONSTANTS = { PYTHON_LAUNCHER: "py -3" }, ERROR: { - COMPORT_UNKNOWN_ERROR: "Writing to COM port (GetOverlappedResult): Unknown error code 121", + COMPORT_UNKNOWN_ERROR: + "Writing to COM port (GetOverlappedResult): Unknown error code 121", CPX_FILE_ERROR: localize( "error.cpxFileFormat", "The cpx.json file format is not correct." ), + DEBUGGER_SERVER_INIT_FAILED: (port: number) => { + return localize( + "error.debuggerServerInitFailed", + `Warning : The Debugger Server cannot be opened. Please try to free the port ${port} if it's already in use or select another one in your Settings 'Pacifica: Debugger Server Port' and start another debug session.\n You can still debug your code but you won't be able to use the Simulator.` + ); + }, DEBUGGING_SESSION_IN_PROGESS: localize( "error.debuggingSessionInProgress", "[ERROR] A debugging session is currently in progress, please stop it before running your code. \n" @@ -32,13 +44,13 @@ export const CONSTANTS = { return localize( "error.failedToOpenSerialPort", `[ERROR] Failed to open serial port ${port}.` - ) + ); }, FAILED_TO_OPEN_SERIAL_PORT_DUE_TO: (port: string, error: any) => { return localize( "error.failedToOpenSerialPortDueTo", `[ERROR] Failed to open serial port ${port} due to error: ${error}. \n` - ) + ); }, INCORRECT_FILE_NAME_FOR_DEVICE: localize( "error.incorrectFileNameForDevice", @@ -146,7 +158,7 @@ export const CONSTANTS = { RUNNING_CODE: localize("info.runningCode", "Running user code"), THIRD_PARTY_WEBSITE: localize( "info.thirdPartyWebsite", - "By clicking \"Agree and Proceed\" you will be redirected to adafruit.com, a third party website not managed by Microsoft. Please note that your activity on adafruit.com is subject to Adafruit's privacy policy", + 'By clicking "Agree and Proceed" you will be redirected to adafruit.com, a third party website not managed by Microsoft. Please note that your activity on adafruit.com is subject to Adafruit\'s privacy policy' ), WELCOME_OUTPUT_TAB: localize( "info.welcomeOutputTab", @@ -198,7 +210,7 @@ export const CONSTANTS = { return localize( "warning.serialMonitorAlreadyOpened", `Serial monitor is already opened for ${port} \n` - ) + ); }, SERIAL_MONITOR_NOT_STARTED: localize( "warning.serialMonitorNotStarted", @@ -308,7 +320,7 @@ export const USER_CODE_NAMES = { export const STATUS_BAR_PRIORITY = { PORT: 20, OPEN_PORT: 30, - BAUD_RATE: 40, + BAUD_RATE: 40 }; export default CONSTANTS; diff --git a/src/debug_user_code.py b/src/debug_user_code.py index 75523d27e..68bdb4d70 100644 --- a/src/debug_user_code.py +++ b/src/debug_user_code.py @@ -10,22 +10,31 @@ from adafruit_circuitplayground import debugger_communication_client -# Init Communication -debugger_communication_client.init_connection() - # Insert absolute path to Adafruit library into sys.path abs_path_to_parent_dir = os.path.dirname(os.path.abspath(__file__)) abs_path_to_lib = os.path.join(abs_path_to_parent_dir, CONSTANTS.LIBRARY_NAME) sys.path.insert(0, abs_path_to_lib) -# Execute User Code +## Execute User Code ## + + +# Get user's code path abs_path_to_code_file = '' if len(sys.argv) > 1 and sys.argv[1]: abs_path_to_code_file = sys.argv[1] else: raise FileNotFoundError(CONSTANTS.ERROR_NO_FILE) +# Get Debugger Server Port +server_port = CONSTANTS.DEFAULT_PORT +if len(sys.argv) > 2: + server_port = sys.argv[2] + +# Init Communication +debugger_communication_client.init_connection(server_port) + +# Init API variables cpx._Express__abs_path_to_code_file = abs_path_to_code_file cpx._Express__debug_mode = True cpx.pixels._Pixel__set_debug_mode(True) diff --git a/src/debuggerCommunicationServer.ts b/src/debuggerCommunicationServer.ts index e0c517c94..7cd2d45bc 100644 --- a/src/debuggerCommunicationServer.ts +++ b/src/debuggerCommunicationServer.ts @@ -1,27 +1,33 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import * as http from "http"; import * as socketio from "socket.io"; import { WebviewPanel } from "vscode"; -import { DEFAULT_SERVER_PORT } from "./constants"; +import { SERVER_INFO } from "./constants"; export class DebuggerCommunicationServer { - // TODO: Port as a constants + user setting private port: number; + private serverHttp: http.Server; private serverIo: socketio.Server; private simulatorWebview: WebviewPanel | undefined; constructor( webviewPanel: WebviewPanel | undefined, - port = DEFAULT_SERVER_PORT + port = SERVER_INFO.DEFAULT_SERVER_PORT ) { this.port = port; - this.serverIo = socketio(this.port); + this.serverHttp = new http.Server(); + this.initHttpServer(); + + this.serverIo = socketio(this.serverHttp); this.simulatorWebview = webviewPanel; this.initEventsHandlers(); + console.info(`Server running on port ${this.port}`); } public closeConnection(): void { + this.serverHttp.close(); this.serverIo.close(); } @@ -41,6 +47,13 @@ export class DebuggerCommunicationServer { this.serverIo.emit("sensor_changed", newState); } + private initHttpServer(): void { + this.serverHttp.listen(this.port); + if (!this.serverHttp.listening) { + throw new Error(SERVER_INFO.ERROR_CODE_INIT_SERVER); + } + } + private initEventsHandlers(): void { this.serverIo.on("connection", (socket: any) => { console.log("Connection received"); diff --git a/src/extension.ts b/src/extension.ts index 50673951c..6e3ccd120 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -12,7 +12,8 @@ import { CPX_CONFIG_FILE, DialogResponses, TelemetryEventName, - WebviewMessages + WebviewMessages, + SERVER_INFO } from "./constants"; import { CPXWorkspace } from "./cpxWorkspace"; import { SimulatorDebugConfigurationProvider } from "./simulatorDebugConfigurationProvider"; @@ -62,12 +63,18 @@ export async function activate(context: vscode.ExtensionContext) { if (outChannel === undefined) { outChannel = vscode.window.createOutputChannel(CONSTANTS.NAME); - utils.logToOutputChannel(outChannel, CONSTANTS.INFO.WELCOME_OUTPUT_TAB, true); + utils.logToOutputChannel( + outChannel, + CONSTANTS.INFO.WELCOME_OUTPUT_TAB, + true + ); } - vscode.workspace.onDidSaveTextDocument(async (document: vscode.TextDocument) => { - await updateCurrentFileIfPython(document); - }); + vscode.workspace.onDidSaveTextDocument( + async (document: vscode.TextDocument) => { + await updateCurrentFileIfPython(document); + } + ); const openWebview = () => { if (currentPanel) { @@ -106,7 +113,7 @@ export async function activate(context: vscode.ExtensionContext) { // Send input to the Python process handleButtonPressTelemetry(message.text); console.log(`About to write ${messageJson} \n`); - if (inDebugMode) { + if (inDebugMode && debuggerCommunicationHandler) { debuggerCommunicationHandler.emitButtonPress(messageJson); } else if (childProcess) { childProcess.stdin.write(messageJson + "\n"); @@ -115,7 +122,9 @@ export async function activate(context: vscode.ExtensionContext) { case WebviewMessages.PLAY_SIMULATOR: console.log(`Play button ${messageJson} \n`); if (message.text as boolean) { - telemetryAI.trackFeatureUsage(TelemetryEventName.COMMAND_RUN_SIMULATOR_BUTTON); + telemetryAI.trackFeatureUsage( + TelemetryEventName.COMMAND_RUN_SIMULATOR_BUTTON + ); runSimulatorCommand(); } else { killProcessIfRunning(); @@ -123,7 +132,7 @@ export async function activate(context: vscode.ExtensionContext) { break; case WebviewMessages.SENSOR_CHANGED: console.log(`Sensor changed ${messageJson} \n`); - if (inDebugMode) { + if (inDebugMode && debuggerCommunicationHandler) { debuggerCommunicationHandler.emitSensorChanged(messageJson); } else if (childProcess) { childProcess.stdin.write(messageJson + "\n"); @@ -295,7 +304,11 @@ export async function activate(context: vscode.ExtensionContext) { await updateCurrentFileIfPython(vscode.window.activeTextEditor!.document); if (currentFileAbsPath === "") { - utils.logToOutputChannel(outChannel, CONSTANTS.ERROR.NO_FILE_TO_RUN, true); + utils.logToOutputChannel( + outChannel, + CONSTANTS.ERROR.NO_FILE_TO_RUN, + true + ); } else { // Save on run await currentTextDocument.save(); @@ -364,7 +377,7 @@ export async function activate(context: vscode.ExtensionContext) { case "print": console.log( `Process print statement output = ${ - messageToWebview.data + messageToWebview.data }` ); utils.logToOutputChannel( @@ -391,7 +404,11 @@ export async function activate(context: vscode.ExtensionContext) { childProcess.stderr.on("data", data => { console.error(`Error from the Python process through stderr: ${data}`); telemetryAI.trackFeatureUsage(TelemetryEventName.ERROR_PYTHON_PROCESS); - utils.logToOutputChannel(outChannel, CONSTANTS.ERROR.STDERR(data), true); + utils.logToOutputChannel( + outChannel, + CONSTANTS.ERROR.STDERR(data), + true + ); if (currentPanel) { console.log("Sending clearing state command"); currentPanel.webview.postMessage({ command: "reset-state" }); @@ -405,11 +422,13 @@ export async function activate(context: vscode.ExtensionContext) { } }; - const runSimulatorEditorButton: vscode.Disposable = vscode.commands.registerCommand("pacifica.runSimulatorEditorButton", + const runSimulatorEditorButton: vscode.Disposable = vscode.commands.registerCommand( + "pacifica.runSimulatorEditorButton", () => { telemetryAI.trackFeatureUsage(TelemetryEventName.COMMAND_RUN_EDITOR_ICON); runSimulatorCommand(); - }); + } + ); // Send message to the webview const runSimulator: vscode.Disposable = vscode.commands.registerCommand( @@ -428,7 +447,11 @@ export async function activate(context: vscode.ExtensionContext) { await updateCurrentFileIfPython(vscode.window.activeTextEditor!.document); if (currentFileAbsPath === "") { - utils.logToOutputChannel(outChannel, CONSTANTS.ERROR.NO_FILE_TO_RUN, true); + utils.logToOutputChannel( + outChannel, + CONSTANTS.ERROR.NO_FILE_TO_RUN, + true + ); } else if (!utils.validCodeFileName(currentFileAbsPath)) { // Save on run await currentTextDocument.save(); @@ -468,7 +491,10 @@ export async function activate(context: vscode.ExtensionContext) { telemetryAI.trackFeatureUsage( TelemetryEventName.SUCCESS_COMMAND_DEPLOY_DEVICE ); - utils.logToOutputChannel(outChannel, CONSTANTS.INFO.DEPLOY_SUCCESS); + utils.logToOutputChannel( + outChannel, + CONSTANTS.INFO.DEPLOY_SUCCESS + ); break; case "no-device": @@ -570,13 +596,16 @@ export async function activate(context: vscode.ExtensionContext) { UsbDetector.getInstance().initialize(context.extensionPath); UsbDetector.getInstance().startListening(); - if (CPXWorkspace.rootPath && - (utils.fileExistsSync(path.join(CPXWorkspace.rootPath, CPX_CONFIG_FILE)) || vscode.window.activeTextEditor)) { - (() => { - if (!SerialMonitor.getInstance().initialized) { - SerialMonitor.getInstance().initialize(); - } - })(); + if ( + CPXWorkspace.rootPath && + (utils.fileExistsSync(path.join(CPXWorkspace.rootPath, CPX_CONFIG_FILE)) || + vscode.window.activeTextEditor) + ) { + (() => { + if (!SerialMonitor.getInstance().initialized) { + SerialMonitor.getInstance().initialize(); + } + })(); } // Debugger configuration @@ -586,17 +615,33 @@ export async function activate(context: vscode.ExtensionContext) { // On Debug Session Start: Init comunication const debugSessionsStarted = vscode.debug.onDidStartDebugSession(() => { - // Set up the webview + // Reinitialize process killProcessIfRunning(); - openWebview(); - if (currentPanel) { - currentPanel.webview.postMessage({ command: "activate-play" }); - } console.log("Debug Started"); inDebugMode = true; - debuggerCommunicationHandler = new DebuggerCommunicationServer( - currentPanel - ); + + try { + debuggerCommunicationHandler = new DebuggerCommunicationServer( + currentPanel, + utils.getServerPortConfig() + ); + openWebview(); + if (currentPanel) { + debuggerCommunicationHandler.setWebview(currentPanel); + currentPanel.webview.postMessage({ command: "activate-play" }); + } + } catch (err) { + if (err.message === SERVER_INFO.ERROR_CODE_INIT_SERVER) { + console.error( + `Error trying to init the server on port ${utils.getServerPortConfig()}` + ); + vscode.window.showErrorMessage( + CONSTANTS.ERROR.DEBUGGER_SERVER_INIT_FAILED( + utils.getServerPortConfig() + ) + ); + } + } }); // On Debug Session Stop: Stop communiation @@ -636,7 +681,7 @@ const getActivePythonFile = () => { editor => editor.document.languageId === "python" ); if (activeEditor) { - currentTextDocument = activeEditor.document + currentTextDocument = activeEditor.document; } return activeEditor ? activeEditor.document.fileName : ""; }; @@ -670,7 +715,10 @@ const updateCurrentFileIfPython = async ( getActivePythonFile() || (await getFileFromFilePicker()) || ""; } if (currentFileAbsPath) { - await vscode.window.showTextDocument(currentTextDocument, vscode.ViewColumn.One); + await vscode.window.showTextDocument( + currentTextDocument, + vscode.ViewColumn.One + ); } }; @@ -725,6 +773,6 @@ function getWebviewContent(context: vscode.ExtensionContext) { export async function deactivate() { const monitor: SerialMonitor = SerialMonitor.getInstance(); - await monitor.closeSerialMonitor(null, false); + await monitor.closeSerialMonitor(null, false); UsbDetector.getInstance().stopListening(); } diff --git a/src/extension_utils/utils.ts b/src/extension_utils/utils.ts index 9df7a6434..ed78e33cb 100644 --- a/src/extension_utils/utils.ts +++ b/src/extension_utils/utils.ts @@ -5,8 +5,21 @@ import * as fs from "fs"; import * as path from "path"; import { DependencyChecker } from "./dependencyChecker"; import { DeviceContext } from "../deviceContext"; -import { ExtensionContext, MessageItem, OutputChannel, Uri, window } from "vscode"; -import { CONSTANTS, CPX_CONFIG_FILE, DialogResponses, USER_CODE_NAMES } from "../constants"; +import { + ExtensionContext, + MessageItem, + OutputChannel, + Uri, + window, + workspace +} from "vscode"; +import { + CONSTANTS, + CPX_CONFIG_FILE, + DialogResponses, + USER_CODE_NAMES, + SERVER_INFO +} from "../constants"; // tslint:disable-next-line: export-name export const getPathToScript = ( @@ -29,11 +42,12 @@ export const validCodeFileName = (filePath: string) => { }; export const showPrivacyModal = (okAction: () => void) => { - window.showInformationMessage( - `${CONSTANTS.INFO.THIRD_PARTY_WEBSITE}: ${CONSTANTS.LINKS.PRIVACY}`, - DialogResponses.AGREE_AND_PROCEED, - DialogResponses.CANCEL, - ) + window + .showInformationMessage( + `${CONSTANTS.INFO.THIRD_PARTY_WEBSITE}: ${CONSTANTS.LINKS.PRIVACY}`, + DialogResponses.AGREE_AND_PROCEED, + DialogResponses.CANCEL + ) .then((privacySelection: MessageItem | undefined) => { if (privacySelection === DialogResponses.AGREE_AND_PROCEED) { okAction(); @@ -41,7 +55,7 @@ export const showPrivacyModal = (okAction: () => void) => { // do nothing } }); -} +}; export const logToOutputChannel = ( outChannel: OutputChannel | undefined, @@ -60,9 +74,9 @@ export function tryParseJSON(jsonString: string): any | boolean { try { const jsonObj = JSON.parse(jsonString); if (jsonObj && typeof jsonObj === "object") { - return jsonObj; + return jsonObj; } - } catch (exception) { } + } catch (exception) {} return false; } @@ -103,25 +117,29 @@ export function directoryExistsSync(dirPath: string): boolean { * so that the resulting string reaches the given length. * The padding is applied from the start (left) of the current string. */ -export function padStart(sourceString: string, targetLength: number, padString?: string): string { +export function padStart( + sourceString: string, + targetLength: number, + padString?: string +): string { if (!sourceString) { - return sourceString; + return sourceString; } if (!(String.prototype as any).padStart) { - // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js - padString = String(padString || " "); - if (sourceString.length > targetLength) { - return sourceString; - } else { - targetLength = targetLength - sourceString.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed - } - return padString.slice(0, targetLength) + sourceString; + // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js + padString = String(padString || " "); + if (sourceString.length > targetLength) { + return sourceString; + } else { + targetLength = targetLength - sourceString.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed } + return padString.slice(0, targetLength) + sourceString; + } } else { - return (sourceString as any).padStart(targetLength, padString); + return (sourceString as any).padStart(targetLength, padString); } } @@ -140,9 +158,11 @@ export function generateCPXConfig(): void { } export const checkPythonDependency = async () => { const dependencyChecker: DependencyChecker = new DependencyChecker(); - const result = await dependencyChecker.checkDependency(CONSTANTS.DEPENDENCY_CHECKER.PYTHON); + const result = await dependencyChecker.checkDependency( + CONSTANTS.DEPENDENCY_CHECKER.PYTHON + ); return result.payload; -} +}; export const setPythonExectuableName = async () => { // Find our what command is the PATH for python @@ -151,8 +171,11 @@ export const setPythonExectuableName = async () => { if (dependencyCheck.installed) { executableName = dependencyCheck.dependency; } else { - window.showErrorMessage(CONSTANTS.ERROR.NO_PYTHON_PATH, - DialogResponses.INSTALL_PYTHON) + window + .showErrorMessage( + CONSTANTS.ERROR.NO_PYTHON_PATH, + DialogResponses.INSTALL_PYTHON + ) .then((selection: MessageItem | undefined) => { if (selection === DialogResponses.INSTALL_PYTHON) { const okAction = () => { @@ -164,4 +187,14 @@ export const setPythonExectuableName = async () => { } return executableName; -} +}; + +export const getServerPortConfig = (): number => { + // tslint:disable: no-backbone-get-set-outside-model prefer-type-cast + if (workspace.getConfiguration().has(SERVER_INFO.SERVER_PORT_CONFIGURATION)) { + return workspace + .getConfiguration() + .get(SERVER_INFO.SERVER_PORT_CONFIGURATION) as number; + } + return SERVER_INFO.DEFAULT_SERVER_PORT; +}; diff --git a/src/python_constants.py b/src/python_constants.py index 8b131e786..65944d9a6 100644 --- a/src/python_constants.py +++ b/src/python_constants.py @@ -35,3 +35,5 @@ UTF_FORMAT = "utf-8" WINDOWS_OS = "win32" + +DEFAULT_PORT = "5678" diff --git a/src/simulatorDebugConfigurationProvider.ts b/src/simulatorDebugConfigurationProvider.ts index 0e948f089..15d87c117 100644 --- a/src/simulatorDebugConfigurationProvider.ts +++ b/src/simulatorDebugConfigurationProvider.ts @@ -2,14 +2,17 @@ // Licensed under the MIT license. import * as vscode from "vscode"; -import { validCodeFileName } from "./extension_utils/utils"; +import { + validCodeFileName, + getServerPortConfig +} from "./extension_utils/utils"; import { CONSTANTS, DialogResponses } from "./constants"; let shouldShowInvalidFileNamePopup: boolean = true; export class SimulatorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { - constructor(private pathToScript: string) { } + constructor(private pathToScript: string) {} /** * Modify the debug configuration just before a debug session is being launched. @@ -26,21 +29,21 @@ export class SimulatorDebugConfigurationProvider const currentFilePath = activeTextEditor.document.fileName; // Check file type and name - if ( - !(activeTextEditor.document.languageId === "python") - ) { + if (!(activeTextEditor.document.languageId === "python")) { return vscode.window .showErrorMessage(CONSTANTS.ERROR.INVALID_FILE_EXTENSION_DEBUG) .then(() => { return undefined; // Abort launch }); - } else if (!validCodeFileName(currentFilePath) && shouldShowInvalidFileNamePopup) { + } else if ( + !validCodeFileName(currentFilePath) && + shouldShowInvalidFileNamePopup + ) { vscode.window - .showInformationMessage(CONSTANTS.INFO.INVALID_FILE_NAME_DEBUG, - ...[ - DialogResponses.DONT_SHOW, - DialogResponses.MESSAGE_UNDERSTOOD - ]) + .showInformationMessage( + CONSTANTS.INFO.INVALID_FILE_NAME_DEBUG, + ...[DialogResponses.DONT_SHOW, DialogResponses.MESSAGE_UNDERSTOOD] + ) .then((selection: vscode.MessageItem | undefined) => { if (selection === DialogResponses.DONT_SHOW) { shouldShowInvalidFileNamePopup = false; @@ -49,8 +52,8 @@ export class SimulatorDebugConfigurationProvider } // Set process_user_code path as program config.program = this.pathToScript; - // Set user's code path as args - config.args = [currentFilePath]; + // Set user's code path and server's port as args + config.args = [currentFilePath, getServerPortConfig().toString()]; // Set rules config.rules = [ { path: this.pathToScript, include: false }, From 231e5f07288e283d59a01e8f95f2303858232c60 Mon Sep 17 00:00:00 2001 From: Christella Cidolit Date: Thu, 15 Aug 2019 17:01:45 -0700 Subject: [PATCH 2/3] Updating doc to help users if the port is not available --- docs/how-to-use.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/how-to-use.md b/docs/how-to-use.md index a8da859c8..3619f2a72 100644 --- a/docs/how-to-use.md +++ b/docs/how-to-use.md @@ -58,8 +58,9 @@ Commands are accessible through : - To open the output panel again after closing it go to VS Code menu : `View->Output`. - If you have pylint enabled, it might underline the import of the adafruit_circuitplayground library, but it will work correctly. - If you try to deploy to the device while it's plugged in but you still get an error saying it cannot find the board, make sure your Circuit Playground Express is formatted correctly and that its name matches `CIRCUITPY`. +- If you can't get the Simulator communication working while debugging, try to open you `Settings` and check the port used under `'Pacifica: Debugger Server Port'`. You can either change it (usually ports above 5000 could work) or try to free it, then start debugging again. ### Note \* Sensors currently not supported by the official adafruit_circuit_playground Express library (v2.1.2). -\** The regular communication is using the stdout and stdin of the Pyhton process. But when you debug your code, it will use a communication over sockets on the port 5678. +\*\* The regular communication is using the stdout and stdin of the Pyhton process. But when you debug your code, it will use a communication over sockets on the port 5678. This is the default port that you can change in your `Settings` : `'Pacifica: Debugger Server Port'`. From 9e2ba4d31365e70a719a15df1bd1089ebdb91a81 Mon Sep 17 00:00:00 2001 From: Christella Cidolit Date: Thu, 15 Aug 2019 17:22:30 -0700 Subject: [PATCH 3/3] Changing default port to not conflict with pyhton remote debugging --- docs/how-to-use.md | 2 +- package.json | 2 +- src/adafruit_circuitplayground/constants.py | 2 +- src/constants.ts | 2 +- src/python_constants.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/how-to-use.md b/docs/how-to-use.md index 3619f2a72..18ab71545 100644 --- a/docs/how-to-use.md +++ b/docs/how-to-use.md @@ -63,4 +63,4 @@ Commands are accessible through : ### Note \* Sensors currently not supported by the official adafruit_circuit_playground Express library (v2.1.2). -\*\* The regular communication is using the stdout and stdin of the Pyhton process. But when you debug your code, it will use a communication over sockets on the port 5678. This is the default port that you can change in your `Settings` : `'Pacifica: Debugger Server Port'`. +\*\* The regular communication is using the stdout and stdin of the Pyhton process. But when you debug your code, it will use a communication over sockets on the port 5577. This is the default port that you can change in your `Settings` : `'Pacifica: Debugger Server Port'`. diff --git a/package.json b/package.json index d74793f42..4b06904a5 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ }, "pacifica.debuggerServerPort": { "type": "number", - "default": 5678, + "default": 5577, "description": "%pacificaExtension.configuration.properties.debuggerPort%", "scope": "resource" } diff --git a/src/adafruit_circuitplayground/constants.py b/src/adafruit_circuitplayground/constants.py index acb1226ec..109b237b9 100644 --- a/src/adafruit_circuitplayground/constants.py +++ b/src/adafruit_circuitplayground/constants.py @@ -19,7 +19,7 @@ TIME_DELAY = 0.03 -DEFAULT_PORT = "5678" +DEFAULT_PORT = "5577" EVENTS_BUTTON_PRESS = ['button_a', 'button_b', 'switch'] EVENTS_SENSOR_CHANGED = ['temperature', diff --git a/src/constants.ts b/src/constants.ts index 05df319a5..d74e64ba4 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -7,7 +7,7 @@ import { MessageItem } from "vscode"; // Debugger Server export const SERVER_INFO = { - DEFAULT_SERVER_PORT: 5678, + DEFAULT_SERVER_PORT: 5577, ERROR_CODE_INIT_SERVER: "ERROR_INIT_SERVER", SERVER_PORT_CONFIGURATION: "pacifica.debuggerServerPort" }; diff --git a/src/python_constants.py b/src/python_constants.py index 65944d9a6..cfbf17730 100644 --- a/src/python_constants.py +++ b/src/python_constants.py @@ -36,4 +36,4 @@ WINDOWS_OS = "win32" -DEFAULT_PORT = "5678" +DEFAULT_PORT = "5577"