simplified monitor connection API.

we have one connenction per editor anyways.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta
2019-12-03 17:19:32 +01:00
parent 80549db289
commit a4e5e65286
6 changed files with 195 additions and 208 deletions

View File

@@ -2,7 +2,7 @@ import { injectable, inject, postConstruct } from 'inversify';
import { Emitter, Event } from '@theia/core/lib/common/event';
// import { ConnectionStatusService } from '@theia/core/lib/browser/connection-status-service';
import { MessageService } from '@theia/core/lib/common/message-service';
import { MonitorService, MonitorConfig, MonitorError } from '../../common/protocol/monitor-service';
import { MonitorService, MonitorConfig, MonitorError, Status } from '../../common/protocol/monitor-service';
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
import { Port, Board } from '../../common/protocol/boards-service';
import { MonitorServiceClientImpl } from './monitor-service-client-impl';
@@ -26,82 +26,81 @@ export class MonitorConnection {
// protected readonly connectionStatusService: ConnectionStatusService;
protected state: MonitorConnection.State | undefined;
protected readonly onConnectionChangedEmitter = new Emitter<string | undefined>();
protected readonly onConnectionChangedEmitter = new Emitter<boolean>();
readonly onConnectionChanged: Event<string | undefined> = this.onConnectionChangedEmitter.event;
readonly onConnectionChanged: Event<boolean> = this.onConnectionChangedEmitter.event;
@postConstruct()
protected init(): void {
this.monitorServiceClient.onError(async error => {
let shouldReconnect = false;
if (this.state) {
const { code, connectionId, config } = error;
if (this.state.connectionId === connectionId) {
switch (code) {
case MonitorError.ErrorCodes.CLIENT_CANCEL: {
console.debug(`Connection was canceled by client: ${MonitorConnection.State.toString(this.state)}.`);
break;
}
case MonitorError.ErrorCodes.DEVICE_BUSY: {
const { port } = config;
this.messageService.warn(`Connection failed. Serial port is busy: ${Port.toString(port)}.`);
break;
}
case MonitorError.ErrorCodes.DEVICE_NOT_CONFIGURED: {
const { port } = config;
this.messageService.info(`Disconnected from ${Port.toString(port)}.`);
break;
}
case MonitorError.ErrorCodes.interrupted_system_call: {
const { board, port } = config;
this.messageService.warn(`Unexpectedly interrupted by backend. Reconnecting ${Board.toString(board)} on port ${Port.toString(port)}.`);
shouldReconnect = true;
}
const { code, config } = error;
switch (code) {
case MonitorError.ErrorCodes.CLIENT_CANCEL: {
console.debug(`Connection was canceled by client: ${MonitorConnection.State.toString(this.state)}.`);
break;
}
const oldState = this.state;
this.state = undefined;
if (shouldReconnect) {
await this.connect(oldState.config);
case MonitorError.ErrorCodes.DEVICE_BUSY: {
const { port } = config;
this.messageService.warn(`Connection failed. Serial port is busy: ${Port.toString(port)}.`);
break;
}
} else {
console.warn(`Received an error from unexpected connection: ${MonitorConnection.State.toString({ connectionId, config })}.`);
case MonitorError.ErrorCodes.DEVICE_NOT_CONFIGURED: {
const { port } = config;
this.messageService.info(`Disconnected from ${Port.toString(port)}.`);
break;
}
case undefined: {
const { board, port } = config;
this.messageService.error(`Unexpected error. Reconnecting ${Board.toString(board)} on port ${Port.toString(port)}.`);
console.error(JSON.stringify(error));
shouldReconnect = true;
}
}
const oldState = this.state;
this.state = undefined;
if (shouldReconnect) {
await this.connect(oldState.config);
}
}
});
}
get connectionId(): string | undefined {
return this.state ? this.state.connectionId : undefined;
get connected(): boolean {
return !!this.state;
}
get connectionConfig(): MonitorConfig | undefined {
return this.state ? this.state.config : undefined;
}
async connect(config: MonitorConfig): Promise<string | undefined> {
async connect(config: MonitorConfig): Promise<Status> {
if (this.state) {
throw new Error(`Already connected to ${MonitorConnection.State.toString(this.state)}.`);
}
const { connectionId } = await this.monitorService.connect(config);
this.state = { connectionId, config };
this.onConnectionChangedEmitter.fire(connectionId);
return connectionId;
const status = await this.monitorService.connect(config);
if (Status.isOK(status)) {
this.state = { config };
this.onConnectionChangedEmitter.fire(true);
}
return Status.isOK(status);
}
async disconnect(): Promise<boolean> {
async disconnect(): Promise<Status> {
if (!this.state) {
throw new Error('Not connected. Nothing to disconnect.');
}
console.log('>>> Disposing existing monitor connection before establishing a new one...');
const result = await this.monitorService.disconnect(this.state.connectionId);
if (result) {
const status = await this.monitorService.disconnect();
if (Status.isOK(status)) {
console.log(`<<< Disposed connection. Was: ${MonitorConnection.State.toString(this.state)}`);
} else {
console.warn(`<<< Could not dispose connection. Activate connection: ${MonitorConnection.State.toString(this.state)}`);
}
this.state = undefined;
this.onConnectionChangedEmitter.fire(undefined);
return result;
this.onConnectionChangedEmitter.fire(false);
return status;
}
}
@@ -109,15 +108,14 @@ export class MonitorConnection {
export namespace MonitorConnection {
export interface State {
readonly connectionId: string;
readonly config: MonitorConfig;
}
export namespace State {
export function toString(state: State): string {
const { connectionId, config } = state;
const { config } = state;
const { board, port } = config;
return `${Board.toString(board)} ${Port.toString(port)} [ID: ${connectionId}]`;
return `${Board.toString(board)} ${Port.toString(port)}`;
}
}

View File

@@ -12,8 +12,8 @@ export class MonitorServiceClientImpl implements MonitorServiceClient {
notifyRead(event: MonitorReadEvent): void {
this.onReadEmitter.fire(event);
const { connectionId, data } = event;
console.debug(`Received data from ${connectionId}: ${data}`);
const { data } = event;
console.debug(`Received data: ${data}`);
}
notifyError(error: MonitorError): void {

View File

@@ -202,7 +202,7 @@ export class MonitorWidget extends ReactWidget {
protected onBeforeDetach(msg: Message): void {
super.onBeforeDetach(msg);
if (this.connection.connectionId) {
if (this.connection.connected) {
this.connection.disconnect();
}
}
@@ -294,9 +294,8 @@ export class MonitorWidget extends ReactWidget {
protected readonly onSend = (value: string) => this.doSend(value);
protected async doSend(value: string) {
const { connectionId } = this.connection;
if (connectionId) {
this.monitorService.send(connectionId, value + this.model.lineEnding);
if (this.connection.connected) {
this.monitorService.send(value + this.model.lineEnding);
}
}