Add monitor proxy functions for the frontend

This commit is contained in:
Silvano Cerza 2022-03-07 14:45:48 +01:00 committed by Alberto Iannaccone
parent c5695d3a76
commit 61b8bdeec9
4 changed files with 109 additions and 51 deletions

View File

@ -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<MonitorManagerProxyClient> {
//set the monitor settings, which includes address, port and other monitor-specific settings
setMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise<void>;
startMonitor(board: Board, port: Port, settings?: MonitorSettings): Promise<void>;
changeMonitorSettings(board: Board, port: Port, settings: MonitorSettings): Promise<void>;
stopMonitor(board: Board, port: Port): Promise<void>;
getSupportedSettings(protocol: string, fqbn: string): Promise<MonitorSettings>;
}
export const MonitorManagerProxyClient = Symbol('MonitorManagerProxyClient');

View File

@ -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<void> {
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<void> {
// 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<void> {
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<void> {
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<MonitorSettings> {
return this.manager.portMonitorSettings(protocol, fqbn);
}
setClient(client: MonitorManagerProxyClient | undefined): void {
@ -51,7 +81,5 @@ export class MonitorManagerProxyImpl implements MonitorManagerProxy {
return;
}
this.client = client;
}
}

View File

@ -15,16 +15,6 @@ export class MonitorManager extends CoreClientAware {
// be started.
private monitorServices = new Map<MonitorID, MonitorService>();
// 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<Status> {
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<void> {
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<void> {
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<Status> {
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<string, MonitorSetting>) {
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(

View File

@ -57,7 +57,7 @@ export class MonitorService extends CoreClientAware implements Disposable {
});
}
getWebsocketAddress(): number {
getWebsocketAddressPort(): number {
return this.webSocketProvider.getAddress().port;
}