import { ArduinoFirmwareUploader, FirmwareInfo, } from '../common/protocol/arduino-firmware-uploader'; import { injectable, inject, named } from 'inversify'; import { ExecutableService } from '../common/protocol'; import { getExecPath, spawnCommand } from './exec-util'; import { ILogger } from '@theia/core/lib/common/logger'; @injectable() export class ArduinoFirmwareUploaderImpl implements ArduinoFirmwareUploader { @inject(ExecutableService) protected executableService: ExecutableService; protected _execPath: string | undefined; @inject(ILogger) @named('fwuploader') protected readonly logger: ILogger; protected onError(error: any): void { this.logger.error(error); } async getExecPath(): Promise { if (this._execPath) { return this._execPath; } this._execPath = await getExecPath('arduino-fwuploader'); return this._execPath; } async runCommand(args: string[]): Promise { const execPath = await this.getExecPath(); return await spawnCommand(`"${execPath}"`, args, this.onError.bind(this)); } async uploadCertificates(command: string): Promise { return await this.runCommand(['certificates', 'flash', command]); } async list(fqbn?: string): Promise { const fqbnFlag = fqbn ? ['--fqbn', fqbn] : []; const firmwares: FirmwareInfo[] = JSON.parse( await this.runCommand([ 'firmware', 'list', ...fqbnFlag, '--format', 'json', ]) ) || []; return firmwares.reverse(); } async updatableBoards(): Promise { return (await this.list()).reduce( (a, b) => (a.includes(b.board_fqbn) ? a : [...a, b.board_fqbn]), [] as string[] ); } async availableFirmwares(fqbn: string): Promise { return await this.list(fqbn); } async flash(firmware: FirmwareInfo, port: string): Promise { return await this.runCommand([ 'firmware', 'flash', '--fqbn', firmware.board_fqbn, '--address', port, '--module', `${firmware.module}@${firmware.firmware_version}`, ]); } }