diff --git a/CHANGELOG.md b/CHANGELOG.md index 344c52e0..858ce039 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change Log All notable changes to this project will be documented in this file. +## Version 0.3.4 + +- Release date: November 22, 2020 + +### Changed +- Add DTR and RTS signals on serial open and buad rate change +- Improves c_cpp_properties.json autogeneration for intelliSense + ## Version 0.3.3 - Release date: October 29, 2020 diff --git a/package-lock.json b/package-lock.json index d72659ed..74bb9c6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-arduino", - "version": "0.3.3", + "version": "0.3.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -214,8 +214,7 @@ "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, "@types/compare-versions": { "version": "3.3.0", @@ -480,15 +479,15 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "json-schema-traverse": "^0.3.0" } }, "ajv-errors": { @@ -541,7 +540,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, "requires": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" @@ -551,7 +549,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -559,8 +556,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -1556,6 +1552,38 @@ "semver": "^5.4.1" } }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "cocopa": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/cocopa/-/cocopa-0.0.13.tgz", + "integrity": "sha512-MKWdCbaC9MpT+CMNXRP2rufpIndIaCKY1KD3XXwg6I2jNI1uFjEKNGXObL1mJ+7X53FTzKaZydJbPinCG+WJTQ==", + "requires": { + "chalk": "^3.0.0", + "commander": "^4.1.1", + "shlex": "^2.0.1" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + } + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -2424,6 +2452,18 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -2439,6 +2479,12 @@ "ms": "^2.1.1" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -2454,6 +2500,12 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2939,9 +2991,9 @@ } }, "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -5467,9 +5519,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -7642,6 +7694,11 @@ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "shlex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/shlex/-/shlex-2.0.2.tgz", + "integrity": "sha512-i4p9nNXgBTILspHwZlBCNsZzwuVWW8SFx5dyIONrjL0R+AbMOPbg7ndqgGfjYivkYRTtZMKqIT8HT+QyOhPQWA==" + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -8095,7 +8152,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, "requires": { "has-flag": "^4.0.0" }, @@ -8103,8 +8159,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" } } }, @@ -8130,6 +8185,18 @@ "string-width": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -8142,12 +8209,24 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -8538,9 +8617,9 @@ } }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "unc-path-regex": { diff --git a/package.json b/package.json index 6bec2da4..5c028b01 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-arduino", "displayName": "Arduino", "description": "Arduino for Visual Studio Code", - "version": "0.3.3", + "version": "0.3.4", "publisher": "vsciot-vscode", "aiKey": "83dd2c27-6594-41d3-85a9-bdb22070eb42", "preview": true, @@ -93,6 +93,10 @@ "light": "images/ArduinoUpload_16.svg" } }, + { + "command": "arduino.cliUpload", + "title": "Arduino CLI: Upload" + }, { "command": "arduino.uploadUsingProgrammer", "title": "Arduino: Upload Using Programmer" @@ -101,6 +105,10 @@ "command": "arduino.rebuildIntelliSenseConfig", "title": "Arduino: Rebuild IntelliSense Configuration" }, + { + "command": "arduino.cliUploadUsingProgrammer", + "title": "Arduino CLI: Upload Using Programmer" + }, { "command": "arduino.selectProgrammer", "title": "Arduino: Select Programmer" @@ -451,6 +459,11 @@ "type": "object", "title": "Arduino configuration", "properties": { + "arduino.useArduinoCli": { + "type": "boolean", + "default": false, + "markdownDescription": "Use Arduino CLI installed instead of Arduino IDE. `#arduino.path#` must be set, as there is no default path for 'arduino-cli'. (Requires a restart after change)" + }, "arduino.path": { "type": "string", "default": "", diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts index 732643fb..62a6d0a2 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -36,7 +36,9 @@ export enum BuildMode { Verify = "Verifying", Analyze = "Analyzing", Upload = "Uploading", + CliUpload = "Uploading latest binaries", UploadProgrammer = "Uploading (programmer)", + CliUploadProgrammer = "Uploading latest binaries (programmer)", }; /** @@ -219,9 +221,14 @@ export class ArduinoApp { } } - /** - * Install arduino board package based on package name and platform hardware architecture. - */ + /** + * Installs arduino board package. + * (If using the aduino CLI this installs the corrosponding core.) + * @param {string} packageName - board vendor + * @param {string} arch - board architecture + * @param {string} version - version of board package or core to download + * @param {boolean} [showOutput=true] - show raw output from command + */ public async installBoard(packageName: string, arch: string = "", version: string = "", showOutput: boolean = true) { arduinoChannel.show(); const updatingIndex = packageName === "dummy" && !arch && !version; @@ -229,24 +236,29 @@ export class ArduinoApp { arduinoChannel.start(`Update package index files...`); } else { try { - const packagePath = path.join(this._settings.packagePath, "packages", packageName); + const packagePath = path.join(this._settings.packagePath, "packages", packageName, arch); if (util.directoryExistsSync(packagePath)) { util.rmdirRecursivelySync(packagePath); } arduinoChannel.start(`Install package - ${packageName}...`); } catch (error) { arduinoChannel.start(`Install package - ${packageName} failed under directory : ${error.path}${os.EOL} -Please make sure the folder is not occupied by other procedures .`); + Please make sure the folder is not occupied by other procedures .`); arduinoChannel.error(`Error message - ${error.message}${os.EOL}`); arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`); return; } } + arduinoChannel.info(`${packageName}${arch && ":" + arch}${version && ":" + version}`); try { - await util.spawn(this._settings.commandPath, - ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`], - undefined, - { channel: showOutput ? arduinoChannel.channel : null }); + this._settings.useArduinoCli ? + await util.spawn(this._settings.commandPath, + ["core", "install", `${packageName}${arch && ":" + arch}${version && "@" + version}`], undefined, + { channel: showOutput ? arduinoChannel.channel : null }) : + await util.spawn(this._settings.commandPath, + ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`], undefined, + { channel: showOutput ? arduinoChannel.channel : null }); + if (updatingIndex) { arduinoChannel.end("Updated package index files."); } else { @@ -272,6 +284,13 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.end(`Uninstalled board package - ${boardName}${os.EOL}`); } + /** + * Downloads or updates a library + * @param {string} libName - name of the library to download + * @param {string} version - version of library to download + * @param {boolean} [showOutput=true] - show raw output from command + */ + public async installLibrary(libName: string, version: string = "", showOutput: boolean = true) { arduinoChannel.show(); const updatingIndex = (libName === "dummy" && !version); @@ -281,6 +300,11 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.start(`Install library - ${libName}`); } try { + this.useArduinoCli() ? + await util.spawn(this._settings.commandPath, + ["lib", "install", `${libName}${version && "@" + version}`], + undefined, + { channel: showOutput ? arduinoChannel.channel : undefined }) : await util.spawn(this._settings.commandPath, ["--install-library", `${libName}${version && ":" + version}`], undefined, @@ -450,8 +474,25 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.error(`Running ${what}-build command failed: ${os.EOL}${msg}`); return false; } + return true; + } + } + + /** + * Checks if the arduino cli is being used + * @returns {bool} - true if arduino cli is being use + */ + private useArduinoCli() { + return this._settings.useArduinoCli; + // return VscodeSettings.getInstance().useArduinoCli; + } + + private getProgrammerString(): string { + const selectProgrammer = this.programmerManager.currentProgrammer; + if (!selectProgrammer) { + logger.notifyUserError("getProgrammerString", new Error(constants.messages.NO_PROGRAMMMER_SELECTED)); + return; } - return true; } /** @@ -475,7 +516,7 @@ Please make sure the folder is not occupied by other procedures .`); } const boardDescriptor = this.boardManager.currentBoard.getBuildConfig(); - args.push("--board", boardDescriptor); + this._settings.useArduinoCli ? args.push("-b", boardDescriptor) : args.push("--board", boardDescriptor); if (!ArduinoWorkspace.rootPath) { vscode.window.showWarningMessage("Workspace doesn't seem to have a folder added to it yet."); @@ -507,7 +548,26 @@ Please make sure the folder is not occupied by other procedures .`); await selectSerial(); return false; } - args.push("--upload"); + + this._settings.useArduinoCli ? args.push("compile", "--upload") : args.push("--upload"); + + if (dc.port) { + args.push("--port", dc.port); + } + + } else if (mode === BuildMode.CliUpload) { + if ((!dc.configuration || !/upload_method=[^=,]*st[^,]*link/i.test(dc.configuration)) && !dc.port) { + await selectSerial(); + return false; + } + + if (!this._settings.useArduinoCli) { + arduinoChannel.error("This command is only avaialble while using the Arduino CLI"); + return false; + } + + args.push("upload"); + if (dc.port) { args.push("--port", dc.port); } @@ -521,15 +581,43 @@ Please make sure the folder is not occupied by other procedures .`); await selectSerial(); return false; } - args.push("--upload", - "--port", dc.port, - "--useprogrammer", - "--pref", `programmer=${programmer}`); + this._settings.useArduinoCli ? + args.push("compile", + "--upload", + "--porgrammer", programmer) : + args.push("--upload", + "--useprogrammer", + "--pref", `programmer=${programmer}`); + + args.push("--port", dc.port); + + } else if (mode === BuildMode.CliUploadProgrammer) { + const programmer = this.programmerManager.currentProgrammer; + if (!programmer) { + logger.notifyUserError("getProgrammerString", new Error(constants.messages.NO_PROGRAMMMER_SELECTED)); + return false; + } + if (!dc.port) { + await selectSerial(); + return false; + } + + if (!this._settings.useArduinoCli) { + arduinoChannel.error("This command is only avaialble while using the Arduino CLI"); + return false; + } + + args.push("compile", + "--upload", + "--porgrammer", programmer, + "--port", dc.port); + } else { - args.push("--verify"); + this._settings.useArduinoCli ? args.unshift("compile") : args.push("--verify"); } - if (dc.buildPreferences) { + // TODO: Option to add prefrences when using the CLI + if (dc.buildPreferences && !this._settings.useArduinoCli) { for (const pref of dc.buildPreferences) { // Note: BuildPrefSetting makes sure that each preference // value consists of exactly two items (key and value). @@ -538,9 +626,11 @@ Please make sure the folder is not occupied by other procedures .`); } // We always build verbosely but filter the output based on the settings - args.push("--verbose-build"); + + this._settings.useArduinoCli ? args.push("--verbose") : args.push("--verbose-build"); + if (verbose) { - args.push("--verbose-upload"); + this._settings.useArduinoCli ? args.push ("--verbose") : args.push("--verbose-upload"); } await vscode.workspace.saveAll(false); @@ -559,7 +649,7 @@ Please make sure the folder is not occupied by other procedures .`); logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + buildDir)); return false; } - args.push("--pref", `build.path=${buildDir}`); + this._settings.useArduinoCli ? args.push ("--build-path", buildDir) : args.push("--pref", `build.path=${buildDir}`); arduinoChannel.info(`Please see the build logs in output path: ${buildDir}`); } else { const msg = "Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README."; @@ -584,13 +674,16 @@ Please make sure the folder is not occupied by other procedures .`); // TODO EW: What should we do with pre-/post build commands when running // analysis? Some could use it to generate/manipulate code which could // be a prerequisite for a successful build - if (!await this.runPrePostBuildCommand(dc, env, "pre")) { + if (dc.prebuild && !await this.runPrePostBuildCommand(dc, env, "pre")) { return false; } // stop serial monitor when everything is prepared and good // what makes restoring of its previous state easier - if (mode === BuildMode.Upload || mode === BuildMode.UploadProgrammer) { + if (mode === BuildMode.Upload || + mode === BuildMode.UploadProgrammer || + mode === BuildMode.CliUpload || + mode === BuildMode.CliUploadProgrammer) { restoreSerialMonitor = await SerialMonitor.getInstance().closeSerialMonitor(dc.port); UsbDetector.getInstance().pauseListening(); } @@ -653,7 +746,7 @@ Please make sure the folder is not occupied by other procedures .`); this._settings.commandPath, args, undefined, - { stdout: stdoutcb, stderr: stderrcb }, + { /*channel: arduinoChannel.channel,*/ stdout: stdoutcb, stderr: stderrcb }, ).then(async () => { const ret = await cleanup("ok"); if (ret) { diff --git a/src/arduino/arduinoSettings.ts b/src/arduino/arduinoSettings.ts index 58419519..8d994d81 100644 --- a/src/arduino/arduinoSettings.ts +++ b/src/arduino/arduinoSettings.ts @@ -22,6 +22,7 @@ export interface IArduinoSettings { preferencePath: string; defaultBaudRate: number; preferences: Map; + useArduinoCli: boolean; reloadPreferences(): void; } @@ -38,18 +39,21 @@ export class ArduinoSettings implements IArduinoSettings { private _preferences: Map; + private _useArduinoCli: boolean; + public constructor() { } public async initialize() { const platform = os.platform(); this._commandPath = VscodeSettings.getInstance().commandPath; + this._useArduinoCli = VscodeSettings.getInstance().useArduinoCli; await this.tryResolveArduinoPath(); await this.tryGetDefaultBaudRate(); if (platform === "win32") { await this.updateWindowsPath(); if (this._commandPath === "") { - this._commandPath = "arduino_debug.exe"; + this._useArduinoCli ? this._commandPath = "arduino-cli.exe" : this._commandPath = "arduino_debug.exe"; } } else if (platform === "linux") { if (util.directoryExistsSync(path.join(this._arduinoPath, "portable"))) { @@ -150,6 +154,10 @@ export class ArduinoSettings implements IArduinoSettings { return this._preferences; } + public get useArduinoCli() { + return this._useArduinoCli; + } + public get defaultBaudRate() { return this._defaultBaudRate; } diff --git a/src/arduino/programmerManager.ts b/src/arduino/programmerManager.ts index a060f211..7a7e2991 100644 --- a/src/arduino/programmerManager.ts +++ b/src/arduino/programmerManager.ts @@ -4,103 +4,78 @@ import { DeviceContext } from "../deviceContext"; import { ArduinoApp } from "./arduino"; import { IArduinoSettings } from "./arduinoSettings"; -export enum ProgrammerList { - "AVR ISP", - "AVRISP mkII", - "USBtinyISP", - "ArduinoISP", - "ArduinoISP.org", - "USBasp", - "Parallel Programmer", - "Arduino as ISP", - "Arduino Gemma", - "BusPirate as ISP", - "Atmel STK500 development board", - "Atmel JTAGICE3 (ISP mode)", - "Atmel JTAGICE3 (JTAG mode)", - "Atmel-ICE (AVR)", -} - export class ProgrammerManager { - - private static _programmerManager: ProgrammerManager = null; - - private _currentprogrammer: ProgrammerList; - private _programmervalue: string; private _programmerStatusBar: vscode.StatusBarItem; + // Static list of 'available' programmers. This should be repopulated by the currently selected board type. + private _availableProgrammers = { + avrisp: "AVR ISP", + avrispmkii: "AVRISP mkII", + usbtinyisp: "USBtinyISP", + arduinoisp: "ArduinoISP", + usbasp: "USBasp", + parallel: "Parallel Programmer", + arduinoasisp: "Arduino as ISP", + usbGemma: "Arduino Gemma", + buspirate: "BusPirate as ISP", + stk500: "Atmel STK500 development board", + jtag3isp: "Atmel JTAGICE3 (ISP mode)", + jtag3: "Atmel JTAGICE3 (JTAG mode)", + atmel_ice: "Atmel-ICE (AVR)", + }; + constructor(private _settings: IArduinoSettings, private _arduinoApp: ArduinoApp) { - this._programmerStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, constants.statusBarPriority.PROGRAMMER); + this._programmerStatusBar = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + constants.statusBarPriority.PROGRAMMER, + ); this._programmerStatusBar.command = "arduino.selectProgrammer"; this._programmerStatusBar.tooltip = "Select Programmer"; - this._programmerStatusBar.text = ""; + } + + private getFriendlyName(programmer: string): string { + const friendlyName = this._availableProgrammers[programmer]; + return friendlyName ? friendlyName : programmer; } } diff --git a/src/arduino/vscodeSettings.ts b/src/arduino/vscodeSettings.ts index 9192a656..8bfd9425 100644 --- a/src/arduino/vscodeSettings.ts +++ b/src/arduino/vscodeSettings.ts @@ -16,6 +16,7 @@ const configKeys = { SKIP_HEADER_PROVIDER: "arduino.skipHeaderProvider", DEFAULT_BAUD_RATE: "arduino.defaultBaudRate", DISABLE_INTELLISENSE_AUTO_GEN: "arduino.disableIntelliSenseAutoGen", + USE_ARDUINO_CLI: "arduino.useArduinoCli", }; export interface IVscodeSettings { @@ -30,6 +31,7 @@ export interface IVscodeSettings { skipHeaderProvider: boolean; defaultBaudRate: number; disableIntelliSenseAutoGen: boolean; + useArduinoCli: boolean; updateAdditionalUrls(urls: string | string[]): void; } @@ -85,6 +87,10 @@ export class VscodeSettings implements IVscodeSettings { return this.getConfigValue(configKeys.DEFAULT_BAUD_RATE); } + public get useArduinoCli(): boolean { + return this.getConfigValue(configKeys.USE_ARDUINO_CLI); + } + public get skipHeaderProvider(): boolean { return this.getConfigValue(configKeys.SKIP_HEADER_PROVIDER); } diff --git a/src/common/platform.ts b/src/common/platform.ts index aa17cadf..1675c8b0 100644 --- a/src/common/platform.ts +++ b/src/common/platform.ts @@ -14,8 +14,8 @@ export function resolveArduinoPath(): string { return internalSysLib.resolveArduinoPath(); } -export function validateArduinoPath(arduinoPath: string): boolean { - return internalSysLib.validateArduinoPath(arduinoPath); +export function validateArduinoPath(arduinoPath: string, useArduinoCli = false): boolean { + return internalSysLib.validateArduinoPath(arduinoPath, useArduinoCli); } export function findFile(fileName: string, cwd: string): string { diff --git a/src/common/sys/darwin.ts b/src/common/sys/darwin.ts index 235aaf38..4d5c7e98 100644 --- a/src/common/sys/darwin.ts +++ b/src/common/sys/darwin.ts @@ -18,8 +18,9 @@ export function resolveArduinoPath(): string { return result || ""; } -export function validateArduinoPath(arduinoPath: string): boolean { - return fileExistsSync(path.join(resolveMacArduinoAppPath(arduinoPath), "/Contents/MacOS/Arduino")); +export function validateArduinoPath(arduinoPath: string, useArduinoCli = false): boolean { + return fileExistsSync(path.join(resolveMacArduinoAppPath(arduinoPath), useArduinoCli ? "arduino-cli" : "/Contents/MacOS/Arduino")); + } export function findFile(fileName: string, cwd: string): string { diff --git a/src/common/sys/linux.ts b/src/common/sys/linux.ts index 6c9189d7..fbb904b4 100644 --- a/src/common/sys/linux.ts +++ b/src/common/sys/linux.ts @@ -20,8 +20,8 @@ export function resolveArduinoPath(): string { return pathString || ""; } -export function validateArduinoPath(arduinoPath: string): boolean { - return fileExistsSync(path.join(arduinoPath, "arduino")); +export function validateArduinoPath(arduinoPath: string, useArduinoCli = false): boolean { + return fileExistsSync(path.join(arduinoPath, useArduinoCli ? "arduino-cli" : "arduino")); } export function findFile(fileName: string, cwd: string): string { diff --git a/src/common/sys/win32.ts b/src/common/sys/win32.ts index dbbbaaac..ad237e27 100644 --- a/src/common/sys/win32.ts +++ b/src/common/sys/win32.ts @@ -27,8 +27,9 @@ export async function resolveArduinoPath() { return pathString; } -export function validateArduinoPath(arduinoPath: string): boolean { - return fileExistsSync(path.join(arduinoPath, "arduino_debug.exe")); +export function validateArduinoPath(arduinoPath: string, useArduinoCli = false): boolean { + return fileExistsSync(path.join(arduinoPath, useArduinoCli ? "arduino-cli.exe" : "arduino_debug.exe")); + } export function findFile(fileName: string, cwd: string): string { diff --git a/src/extension.ts b/src/extension.ts index 218bd3a7..0ae03769 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -90,7 +90,9 @@ export async function activate(context: vscode.ExtensionContext) { const arduinoPath = arduinoContextModule.default.arduinoApp.settings.arduinoPath; const commandPath = arduinoContextModule.default.arduinoApp.settings.commandPath; - if (!arduinoPath || !validateArduinoPath(arduinoPath)) { // Pop up vscode User Settings page when cannot resolve arduino path. + const useArduinoCli = arduinoContextModule.default.arduinoApp.settings.useArduinoCli; + // Pop up vscode User Settings page when cannot resolve arduino path. + if (!arduinoPath || !validateArduinoPath(arduinoPath, useArduinoCli)) { Logger.notifyUserError("InvalidArduinoPath", new Error(constants.messages.INVALID_ARDUINO_PATH)); vscode.commands.executeCommand("workbench.action.openGlobalSettings"); } else if (!commandPath || !util.fileExistsSync(commandPath)) { @@ -141,6 +143,19 @@ export async function activate(context: vscode.ExtensionContext) { return { board: arduinoContextModule.default.boardManager.currentBoard.name }; }); + registerArduinoCommand("arduino.cliUpload", async () => { + if (!arduinoContextModule.default.arduinoApp.building) { + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Window, + title: "Arduino: Uploading...", + }, async () => { + await arduinoContextModule.default.arduinoApp.build(BuildMode.Upload); + }); + } + }, () => { + return { board: arduinoContextModule.default.boardManager.currentBoard.name }; + }); + registerArduinoCommand("arduino.setSketchFile", async () => { const sketchFileName = deviceContext.sketch; const newSketchFileName = await vscode.window.showInputBox({ @@ -175,6 +190,19 @@ export async function activate(context: vscode.ExtensionContext) { return { board: arduinoContextModule.default.boardManager.currentBoard.name }; }); + registerArduinoCommand("arduino.cliUploadUsingProgrammer", async () => { + if (!arduinoContextModule.default.arduinoApp.building) { + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Window, + title: "Arduino: Uploading (programmer)...", + }, async () => { + await arduinoContextModule.default.arduinoApp.build(BuildMode.UploadProgrammer); + }); + } + }, () => { + return { board: arduinoContextModule.default.boardManager.currentBoard.name }; + }); + registerArduinoCommand("arduino.rebuildIntelliSenseConfig", async () => { if (!arduinoContextModule.default.arduinoApp.building) { await vscode.window.withProgress({ diff --git a/src/serialmonitor/serialMonitor.ts b/src/serialmonitor/serialMonitor.ts index 2d3dd75b..622d1855 100644 --- a/src/serialmonitor/serialMonitor.ts +++ b/src/serialmonitor/serialMonitor.ts @@ -22,7 +22,7 @@ export class SerialMonitor implements vscode.Disposable { public static DEFAULT_BAUD_RATE: number = 115200; public static listBaudRates(): number[] { - return [300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 250000]; + return [300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 250000, 500000, 1000000, 2000000]; } public static getInstance(): SerialMonitor { diff --git a/src/serialmonitor/serialportctrl.ts b/src/serialmonitor/serialportctrl.ts index c09e1e78..27204eb6 100644 --- a/src/serialmonitor/serialportctrl.ts +++ b/src/serialmonitor/serialportctrl.ts @@ -79,6 +79,11 @@ export class SerialPortCtrl { reject(err); } else { this._outputChannel.appendLine(`[Info] Opened the serial port - ${this._currentPort}`); + this._currentSerialPort.set(["dtr=true", "rts=true"], (err) => { + if (err) { + reject(err); + } + }); resolve(); } }); @@ -164,7 +169,13 @@ export class SerialPortCtrl { if (err) { reject(err); } else { - resolve(); + this._currentSerialPort.set(["dtr=true", "rts=true"], (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); } }); }); diff --git a/test/extension.test.ts b/test/extension.test.ts index 0b3db851..fb746313 100644 --- a/test/extension.test.ts +++ b/test/extension.test.ts @@ -55,6 +55,8 @@ suite("Arduino: Extension Tests", () => { "arduino.loadPackages", "arduino.installBoard", "arduino.setSketchFile", + "arduino.cliUpload", + "arduino.cliUploadUsingProgrammer", ]; const foundArduinoCommands = commands.filter((value) => { diff --git a/test/librarymanager.test.ts b/test/librarymanager.test.ts index 7e43af26..5ff5cc84 100644 --- a/test/librarymanager.test.ts +++ b/test/librarymanager.test.ts @@ -79,7 +79,7 @@ suite("Arduino: Library Manager.", () => { if (util.directoryExistsSync(libPath)) { done(); } else { - done(new Error("AzureIoTHub library install failure, can't find library path :" + libPath)); + done(new Error("AzureIoTHub library install failure, can't find library path: " + libPath)); } });