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..a7a49f3d 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": { diff --git a/package.json b/package.json index f30bc901..20cf48a1 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,10 +93,18 @@ "light": "images/ArduinoUpload_16.svg" } }, + { + "command": "arduino.cliUpload", + "title": "Arduino CLI: Upload" + }, { "command": "arduino.uploadUsingProgrammer", "title": "Arduino: Upload Using Programmer" }, + { + "command": "arduino.cliUploadUsingProgrammer", + "title": "Arduino CLI: Upload Using Programmer" + }, { "command": "arduino.selectProgrammer", "title": "Arduino: Select Programmer" @@ -442,6 +450,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 73619a7b..a4b9b1aa 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -93,13 +93,23 @@ export class ArduinoApp { } } - public async upload() { + /** + * Upload code to selected board + * @param {bool} [compile=true] - Indicates whether to compile the code when using the CLI to upload + * @param {bool} [useProgrammer=false] - Indicate whether a specific programmer should be used + */ + public async upload(compile: boolean = true, useProgrammer: boolean = false) { const dc = DeviceContext.getInstance(); const boardDescriptor = this.getBoardBuildString(); if (!boardDescriptor) { return; } + const selectProgrammer = useProgrammer ? this.getProgrammerString() : null; + if (useProgrammer && !selectProgrammer) { + return; + } + if (!ArduinoWorkspace.rootPath) { vscode.window.showWarningMessage("Cannot find the sketch file."); return; @@ -140,8 +150,25 @@ export class ArduinoApp { } } + if (!compile && !this.useArduinoCli()) { + arduinoChannel.error("This command is only availble when using the Arduino CLI"); + return; + } + const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--upload", "--board", boardDescriptor]; + // TODO: add the --clean argument to the cli args when v 0.14 is released (this will clean up the build folder after uploading) + const args = (!compile && this.useArduinoCli()) ? ["upload", "-b", boardDescriptor] : + this.useArduinoCli() ? ["compile", "--upload", "-b", boardDescriptor] : + ["--upload", "--board", boardDescriptor]; + + if (useProgrammer) { + if (this.useArduinoCli()) { + args.push("--programmer", selectProgrammer) + } else { + args.push("--useprogrammer", "--pref", "programmer=arduino:" + selectProgrammer) + } + } + if (dc.port) { args.push("--port", dc.port); } @@ -149,7 +176,7 @@ export class ArduinoApp { if (VscodeSettings.getInstance().logLevel === "verbose") { args.push("--verbose"); } - if (dc.output) { + if (dc.output && compile) { const outputPath = path.resolve(ArduinoWorkspace.rootPath, dc.output); const dirPath = path.dirname(outputPath); if (!util.directoryExistsSync(dirPath)) { @@ -157,77 +184,13 @@ export class ArduinoApp { return; } - args.push("--pref", `build.path=${outputPath}`); - arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); - } else { - const msg = "Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README."; - arduinoChannel.warning(msg); - } - await util.spawn(this._settings.commandPath, arduinoChannel.channel, args).then(async () => { - UsbDetector.getInstance().resumeListening(); - if (needRestore) { - await serialMonitor.openSerialMonitor(); - } - arduinoChannel.end(`Uploaded the sketch: ${dc.sketch}${os.EOL}`); - }, (reason) => { - arduinoChannel.error(`Exit with code=${reason.code}${os.EOL}`); - }); - } - - public async uploadUsingProgrammer() { - const dc = DeviceContext.getInstance(); - const boardDescriptor = this.getBoardBuildString(); - if (!boardDescriptor) { - return; - } + if (this.useArduinoCli()) { + args.push("--build-path", outputPath); - const selectProgrammer = this.getProgrammerString(); - if (!selectProgrammer) { - return; - } - - if (!ArduinoWorkspace.rootPath) { - vscode.window.showWarningMessage("Cannot find the sketch file."); - return; - } - - if (!dc.sketch || !util.fileExistsSync(path.join(ArduinoWorkspace.rootPath, dc.sketch))) { - await this.getMainSketch(dc); - } - if (!dc.port) { - const choice = await vscode.window.showInformationMessage( - "Serial port is not specified. Do you want to select a serial port for uploading?", - "Yes", "No"); - if (choice === "Yes") { - vscode.commands.executeCommand("arduino.selectSerialPort"); - } - return; - } - - arduinoChannel.show(); - arduinoChannel.start(`Upload sketch - ${dc.sketch}`); - - const serialMonitor = SerialMonitor.getInstance(); - - const needRestore = await serialMonitor.closeSerialMonitor(dc.port); - UsbDetector.getInstance().pauseListening(); - await vscode.workspace.saveAll(false); - - const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--upload", "--board", boardDescriptor, "--port", dc.port, "--useprogrammer", - "--pref", "programmer=" + selectProgrammer, appPath]; - if (VscodeSettings.getInstance().logLevel === "verbose") { - args.push("--verbose"); - } - if (dc.output) { - const outputPath = path.resolve(ArduinoWorkspace.rootPath, dc.output); - const dirPath = path.dirname(outputPath); - if (!util.directoryExistsSync(dirPath)) { - Logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + outputPath)); - return; + } else { + args.push("--pref", `build.path=${outputPath}`); } - args.push("--pref", `build.path=${outputPath}`); arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); } else { const msg = "Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README."; @@ -277,7 +240,7 @@ export class ArduinoApp { } const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--verify", "--board", boardDescriptor, appPath]; + const args = this.useArduinoCli() ? ["compile", "-b", boardDescriptor, appPath] : ["--verify", "--board", boardDescriptor, appPath]; if (VscodeSettings.getInstance().logLevel === "verbose") { args.push("--verbose"); } @@ -289,7 +252,13 @@ export class ArduinoApp { return; } - args.push("--pref", `build.path=${outputPath}`); + if (this.useArduinoCli()) { + args.push("--build-path", outputPath); + + } else { + args.push("--pref", `build.path=${outputPath}`); + } + arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); } else { const msg = "Output path is not specified. Unable to reuse previously compiled files. Verify could be slow. See README."; @@ -320,15 +289,21 @@ export class ArduinoApp { return; } const cppConfigFile = fs.readFileSync(configFilePath, "utf8"); - const cppConfig = JSON.parse(cppConfigFile) as { configurations: Array<{ includePath: string[], forcedInclude: string[] }> }; + const cppConfig = JSON.parse(cppConfigFile) as { configurations: Array<{ + includePath: string[], + forcedInclude: string[], + defines: string[], + }> }; const libPaths = this.getDefaultPackageLibPaths(); const defaultForcedInclude = this.getDefaultForcedIncludeFiles(); + const defines = this.getDefaultDefines(); const configuration = cppConfig.configurations[0]; let cppConfigFileUpdated = false; - // cpp exntension changes \\ to \\\\ in paths in JSON string, revert them first + // cpp extension changes \\ to \\\\ in paths in JSON string, revert them first configuration.includePath = configuration.includePath.map((path) => path.replace(/\\\\/g, "\\")); configuration.forcedInclude = configuration.forcedInclude.map((path) => path.replace(/\\\\/g, "\\")); + configuration.defines = configuration.defines.map((path) => path.replace(/\\\\/g, "\\")); for (const libPath of libPaths) { if (configuration.includePath.indexOf(libPath) === -1) { @@ -343,6 +318,12 @@ export class ArduinoApp { } } + for (const define of defines) { + if (configuration.defines.indexOf(define) === -1) { + cppConfigFileUpdated = true; + configuration.defines.push(define); + } + } // remove all unexisting paths // concern mistake removal, comment temporary // for (let pathIndex = 0; pathIndex < configuration.includePath.length; pathIndex++) { @@ -386,6 +367,7 @@ export class ArduinoApp { } const defaultForcedInclude = this.getDefaultForcedIncludeFiles(); + const defaultDefines = this.getDefaultDefines(); if (!ArduinoWorkspace.rootPath) { return; @@ -444,6 +426,10 @@ export class ArduinoApp { configSection.forcedInclude = defaultForcedInclude.concat(configSection.forcedInclude); } + if (!configSection.defines) { + configSection.defines = defaultDefines; + } + fs.writeFileSync(configFilePath, JSON.stringify(deviceContext, null, 4)); } @@ -478,9 +464,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; @@ -488,23 +479,28 @@ 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, - showOutput ? arduinoChannel.channel : null, - ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`]); + this.useArduinoCli() ? + await util.spawn(this._settings.commandPath, + showOutput ? arduinoChannel.channel : null, + ["core", "install", `${packageName}${arch && ":" + arch}${version && "@" + version}`]) : + await util.spawn(this._settings.commandPath, + showOutput ? arduinoChannel.channel : null, + ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`]); if (updatingIndex) { arduinoChannel.end("Updated package index files."); @@ -531,6 +527,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); @@ -540,6 +543,10 @@ 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, + showOutput ? arduinoChannel.channel : null, + ["lib", "install", `${libName}${version && "@" + version}`]) : await util.spawn(this._settings.commandPath, showOutput ? arduinoChannel.channel : null, ["--install-library", `${libName}${version && ":" + version}`]); @@ -577,6 +584,16 @@ Please make sure the folder is not occupied by other procedures .`); } const toolsPath = boardDescriptor.platform.rootBoardPath; result.push(path.normalize(path.join(toolsPath, "**"))); + const hardwareToolPath = path.join(toolsPath, "..", "..", "tools"); + if (fs.existsSync(hardwareToolPath)) { + result.push(path.normalize(path.join(hardwareToolPath, "**"))); + } + + // Add default libraries to include path + result.push(path.normalize(path.join(this._settings.defaultLibPath, "**"))); + + const userLibsPath = (path.join(this._settings.sketchbookPath, "libraries", "**")); + result.push(userLibsPath); // if (util.directoryExistsSync(path.join(toolsPath, "cores"))) { // const coreLibs = fs.readdirSync(path.join(toolsPath, "cores")); // if (coreLibs && coreLibs.length > 0) { @@ -608,6 +625,13 @@ Please make sure the folder is not occupied by other procedures .`); return result; } + public getDefaultDefines(): string[] { + const result = []; + // USBCON is required in order for Serial to be recognized by intellisense + result.push("USBCON"); + return result; + } + public openExample(example) { function tmpName(name) { let counter = 0; @@ -735,6 +759,15 @@ Please make sure the folder is not occupied by other procedures .`); this._programmerManager = value; } + /** + * 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) { 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..08d3a425 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 f66e268b..14726cd8 100644 --- a/src/arduino/vscodeSettings.ts +++ b/src/arduino/vscodeSettings.ts @@ -15,6 +15,7 @@ const configKeys = { IGNORE_BOARDS: "arduino.ignoreBoards", SKIP_HEADER_PROVIDER: "arduino.skipHeaderProvider", DEFAULT_BAUD_RATE: "arduino.defaultBaudRate", + USE_ARDUINO_CLI: "arduino.useArduinoCli", }; export interface IVscodeSettings { @@ -28,6 +29,7 @@ export interface IVscodeSettings { ignoreBoards: string[]; skipHeaderProvider: boolean; defaultBaudRate: number; + useArduinoCli: boolean; updateAdditionalUrls(urls: string | string[]): void; } @@ -83,6 +85,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/common/util.ts b/src/common/util.ts index 2af4b83b..696c99ea 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -200,6 +200,13 @@ export function isArduinoFile(filePath): boolean { return fileExistsSync(filePath) && (path.extname(filePath) === ".ino" || path.extname(filePath) === ".pde"); } +/** + * Send a command to arduino + * @param {string} command - base command path (either Arduino IDE or CLI) + * @param {vscode.OutputChannel} outputChannel - output display channel + * @param {string[]} [args=[]] - arguments to pass to the command + * @param {any} [options={}] - options and flags for the arguments + */ export function spawn(command: string, outputChannel: vscode.OutputChannel, args: string[] = [], options: any = {}): Thenable { return new Promise((resolve, reject) => { const stdout = ""; diff --git a/src/deviceContext.ts b/src/deviceContext.ts index 2e7f18e3..5e24aea1 100644 --- a/src/deviceContext.ts +++ b/src/deviceContext.ts @@ -151,9 +151,9 @@ export class DeviceContext implements IDeviceContext, vscode.Disposable { this._configuration = deviceConfigJson.configuration; this._output = deviceConfigJson.output; this._debugger = deviceConfigJson["debugger"]; - this._onDidChange.fire(); this._prebuild = deviceConfigJson.prebuild; this._programmer = deviceConfigJson.programmer; + this._onDidChange.fire(); } else { Logger.notifyUserError("arduinoFileError", new Error(constants.messages.ARDUINO_FILE_ERROR)); } @@ -164,9 +164,9 @@ export class DeviceContext implements IDeviceContext, vscode.Disposable { this._configuration = null; this._output = null; this._debugger = null; - this._onDidChange.fire(); this._prebuild = null; this._programmer = null; + this._onDidChange.fire(); } return this; }, (reason) => { @@ -182,9 +182,9 @@ export class DeviceContext implements IDeviceContext, vscode.Disposable { this._configuration = null; this._output = null; this._debugger = null; - this._onDidChange.fire(); this._prebuild = null; this._programmer = null; + this._onDidChange.fire(); return this; }); diff --git a/src/extension.ts b/src/extension.ts index c4112bd7..b6cf7a78 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -91,7 +91,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)) { @@ -152,6 +154,24 @@ export async function activate(context: vscode.ExtensionContext) { return { board: arduinoContextModule.default.boardManager.currentBoard.name }; }); + registerArduinoCommand("arduino.cliUpload", async () => { + if (!status.compile) { + status.compile = "cliUpload"; + try { + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Window, + title: "Arduino: Using CLI to upload...", + }, async () => { + await arduinoContextModule.default.arduinoApp.upload(false); + }); + } catch (ex) { + } + delete status.compile; + } + }, () => { + return { board: arduinoContextModule.default.boardManager.currentBoard.name }; + }); + registerArduinoCommand("arduino.setSketchFile", async () => { const sketchFileName = deviceContext.sketch; const newSketchFileName = await vscode.window.showInputBox({ @@ -177,7 +197,20 @@ export async function activate(context: vscode.ExtensionContext) { if (!status.compile) { status.compile = "upload"; try { - await arduinoContextModule.default.arduinoApp.uploadUsingProgrammer(); + await arduinoContextModule.default.arduinoApp.upload(true, true); + } catch (ex) { + } + delete status.compile; + } + }, () => { + return { board: arduinoContextModule.default.boardManager.currentBoard.name }; + }); + + registerArduinoCommand("arduino.cliUploadUsingProgrammer", async () => { + if (!status.compile) { + status.compile = "cliUpload"; + try { + await arduinoContextModule.default.arduinoApp.upload(false, true); } catch (ex) { } delete status.compile; diff --git a/src/serialmonitor/serialMonitor.ts b/src/serialmonitor/serialMonitor.ts index 5153972c..812801d5 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 e1a8de12..9c56fc41 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)); } });