diff --git a/arduino-ide-extension/src/common/protocol/monitor-service.ts b/arduino-ide-extension/src/common/protocol/monitor-service.ts index 0847068c..11217ca5 100644 --- a/arduino-ide-extension/src/common/protocol/monitor-service.ts +++ b/arduino-ide-extension/src/common/protocol/monitor-service.ts @@ -4,8 +4,10 @@ import { Board, Port } from './boards-service'; export const MonitorManagerProxyPath = '/services/monitor-manager-proxy'; export const MonitorManagerProxy = Symbol('MonitorManagerProxy'); export interface MonitorManagerProxy extends JsonRpcServer { - //set the monitor settings, which includes address, port and other monitor-specific settings - setMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise; + startMonitor(board: Board, port: Port, settings?: MonitorSettings): Promise; + changeMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise; + stopMonitor(board: Board, port: Port): Promise; + getSupportedSettings(protocol: string, fqbn: string): Promise; } export const MonitorManagerProxyClient = Symbol('MonitorManagerProxyClient'); diff --git a/arduino-ide-extension/src/node/monitor-manager-proxy-impl.ts b/arduino-ide-extension/src/node/monitor-manager-proxy-impl.ts index d582ea09..2291228e 100644 --- a/arduino-ide-extension/src/node/monitor-manager-proxy-impl.ts +++ b/arduino-ide-extension/src/node/monitor-manager-proxy-impl.ts @@ -1,6 +1,5 @@ -import { Emitter, ILogger } from "@theia/core"; +import { ILogger } from "@theia/core"; import { inject, injectable, named } from "@theia/core/shared/inversify"; -import { Disposable } from "@theia/core/shared/vscode-languageserver-protocol"; import { MonitorManagerProxy, MonitorManagerProxyClient, MonitorSettings, Status } from "../common/protocol"; import { Board, Port } from "../common/protocol"; import { MonitorManager } from "./monitor-manager"; @@ -9,9 +8,6 @@ import { MonitorManager } from "./monitor-manager"; export class MonitorManagerProxyImpl implements MonitorManagerProxy { protected client: MonitorManagerProxyClient; - protected selectedBoard: Board | null; - protected selectedPort: Port | null; - constructor( @inject(ILogger) @named("monitor-manager-proxy") @@ -26,24 +22,58 @@ export class MonitorManagerProxyImpl implements MonitorManagerProxy { // NOOP } + /** + * Start a pluggable monitor and/or change its settings. + * If settings are defined they'll be set before starting the monitor, + * otherwise default ones will be used by the monitor. + * @param board board connected to port + * @param port port to monitor + * @param settings map of supported configuration by the monitor + */ + async startMonitor(board: Board, port: Port, settings?: MonitorSettings): Promise { + if (settings) { + await this.changeMonitorSettings(board, port, settings); + } + const status = await this.manager.startMonitor(board, port); + if (status === Status.ALREADY_CONNECTED || status === Status.OK) { + this.client.notifyWebSocketChanged(this.manager.getWebsocketAddressPort(board, port)); + } + } - // setMonitorConfig is called by the FE when trying to establish a monitor connection to a board or when changing some - // settings (such as the baudrate, when available) - async setMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise { - - // check if it's a different connection or a change in the settings - if (board === this.selectedBoard && port === this.selectedPort) { - - // TODO: update the settings + /** + * Changes the settings of a running pluggable monitor, if that monitor is not + * started this function is a noop. + * @param board board connected to port + * @param port port monitored + * @param settings map of supported configuration by the monitor + */ + async changeMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise { + if (!this.manager.isStarted(board, port)) { + // Monitor is not running, no need to change settings return; } + return this.manager.changeMonitorSettings(board, port, settings); + } - const startStatus: Status = await this.manager.startMonitor(board, port); - - if (startStatus === Status.ALREADY_CONNECTED || startStatus === Status.OK) { - this.client.notifyWebSocketChanged(this.manager.getWebsocketAddress(board, port)); - } + /** + * Stops a running pluggable monitor. + * @param board board connected to port + * @param port port monitored + */ + async stopMonitor(board: Board, port: Port): Promise { + return this.manager.stopMonitor(board, port); + } + /** + * Returns the settings supported by the pluggable monitor for the specified + * protocol, the fqbn is necessary since it's used to tell different monitors + * using the same protocol. + * @param protocol protocol of a pluggable monitor + * @param fqbn unique ID of a board + * @returns a map of MonitorSetting + */ + async getSupportedSettings(protocol: string, fqbn: string): Promise { + return this.manager.portMonitorSettings(protocol, fqbn); } setClient(client: MonitorManagerProxyClient | undefined): void { @@ -51,7 +81,5 @@ export class MonitorManagerProxyImpl implements MonitorManagerProxy { return; } this.client = client; - } - } \ No newline at end of file diff --git a/arduino-ide-extension/src/node/monitor-manager.ts b/arduino-ide-extension/src/node/monitor-manager.ts index 62434bdc..a1627d3c 100644 --- a/arduino-ide-extension/src/node/monitor-manager.ts +++ b/arduino-ide-extension/src/node/monitor-manager.ts @@ -15,16 +15,6 @@ export class MonitorManager extends CoreClientAware { // be started. private monitorServices = new Map(); - // Used to notify a monitor service that an upload process started - // to the board/port combination it manages - protected readonly onUploadStartedEmitter = new Emitter<{ board: Board, port: Port }>(); - readonly onUploadStarted = this.onUploadStartedEmitter.event; - - // Used to notify a monitor service that an upload process finished - // to the board/port combination it manages - - - constructor( @inject(ILogger) @named('monitor-manager') @@ -55,7 +45,7 @@ export class MonitorManager extends CoreClientAware { } resolve(resp) }) - }) + }); let settings: MonitorSettings = {}; for (const iterator of res.getSettingsList()) { @@ -71,9 +61,28 @@ export class MonitorManager extends CoreClientAware { } /** - * - * @param board - * @param port + * Used to know if a monitor is started + * @param board board connected to port + * @param port port to monitor + * @returns true if the monitor is currently monitoring the board/port + * combination specifed, false in all other cases. + */ + isStarted(board: Board, port: Port): boolean { + const monitorID = this.monitorID(board, port); + const monitor = this.monitorServices.get(monitorID); + if (monitor) { + return monitor.isStarted(); + } + return false; + } + + /** + * Start a pluggable monitor that receives and sends messages + * to the specified board and port combination. + * @param board board connected to port + * @param port port to monitor + * @returns a Status object to know if the process has been + * started or if there have been errors. */ async startMonitor(board: Board, port: Port): Promise { const monitorID = this.monitorID(board, port); @@ -82,12 +91,16 @@ export class MonitorManager extends CoreClientAware { monitor = this.createMonitor(board, port) } return await monitor.start(); - // TODO: I need to return the address here right? } + /** + * Stop a pluggable monitor connected to the specified board/port + * combination. It's a noop if monitor is not running. + * @param board board connected to port + * @param port port monitored + */ async stopMonitor(board: Board, port: Port): Promise { const monitorID = this.monitorID(board, port); - const monitor = this.monitorServices.get(monitorID); if (!monitor) { // There's no monitor to stop, bail @@ -96,14 +109,20 @@ export class MonitorManager extends CoreClientAware { return await monitor.stop(); } - getWebsocketAddress(board: Board, port: Port): number { + /** + * Returns the port of the WebSocket used by the MonitorService + * that is handling the board/port combination + * @param board board connected to port + * @param port port to monitor + * @returns port of the MonitorService's WebSocket + */ + getWebsocketAddressPort(board: Board, port: Port): number { const monitorID = this.monitorID(board, port); - const monitor = this.monitorServices.get(monitorID); if (!monitor) { return -1; } - return monitor.getWebsocketAddress(); + return monitor.getWebsocketAddressPort(); } /** @@ -111,8 +130,8 @@ export class MonitorManager extends CoreClientAware { * that an upload process started on that exact board/port combination. * This must be done so that we can stop the monitor for the time being * until the upload process finished. - * @param board - * @param port + * @param board board connected to port + * @param port port to monitor */ async notifyUploadStarted(board?: Board, port?: Port): Promise { if (!board || !port) { @@ -132,9 +151,10 @@ export class MonitorManager extends CoreClientAware { /** * Notifies the monitor service of that board/port combination * that an upload process started on that exact board/port combination. - * @param board - * @param port - * @returns + * @param board board connected to port + * @param port port to monitor + * @returns a Status object to know if the process has been + * started or if there have been errors. */ async notifyUploadFinished(board?: Board, port?: Port): Promise { if (!board || !port) { @@ -152,10 +172,11 @@ export class MonitorManager extends CoreClientAware { } /** - * - * @param board - * @param port - * @param settings map of monitor settings to change + * Changes the settings of a pluggable monitor even if it's running. + * If monitor is not running they're going to be used as soon as it's started. + * @param board board connected to port + * @param port port to monitor + * @param settings monitor settings to change */ changeMonitorSettings(board: Board, port: Port, settings: Record) { const monitorID = this.monitorID(board, port); @@ -166,6 +187,13 @@ export class MonitorManager extends CoreClientAware { } } + /** + * Creates a MonitorService that handles the lifetime and the + * communication via WebSocket with the frontend. + * @param board board connected to specified port + * @param port port to monitor + * @returns a new instance of MonitorService ready to use. + */ private createMonitor(board: Board, port: Port): MonitorService { const monitorID = this.monitorID(board, port); const monitor = new MonitorService( diff --git a/arduino-ide-extension/src/node/monitor-service.ts b/arduino-ide-extension/src/node/monitor-service.ts index cbb408f0..a5459cf8 100644 --- a/arduino-ide-extension/src/node/monitor-service.ts +++ b/arduino-ide-extension/src/node/monitor-service.ts @@ -57,7 +57,7 @@ export class MonitorService extends CoreClientAware implements Disposable { }); } - getWebsocketAddress(): number { + getWebsocketAddressPort(): number { return this.webSocketProvider.getAddress().port; }