Skip to content

Commit 9efcbcf

Browse files
author
Akos Kitta
committed
[rewrite-me]: initial serial monitor changes
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent d22c0b9 commit 9efcbcf

File tree

13 files changed

+469
-305
lines changed

13 files changed

+469
-305
lines changed

arduino-ide-extension/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@
2323
"@theia/terminal": "next",
2424
"@theia/workspace": "next",
2525
"@types/google-protobuf": "^3.7.1",
26+
"@types/dateformat": "^3.0.1",
27+
"@types/chance": "1.0.7",
2628
"@types/ps-tree": "^1.1.0",
2729
"@types/react-select": "^3.0.0",
2830
"@types/which": "^1.3.1",
31+
"chance": "^1.1.3",
2932
"css-element-queries": "^1.2.0",
33+
"dateformat": "^3.0.3",
34+
"google-protobuf": "^3.11.0",
3035
"p-queue": "^5.0.0",
3136
"ps-tree": "^1.2.0",
3237
"react-select": "^3.0.4",

arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import { MaybePromise } from '@theia/core/lib/common/types';
4141
import { BoardsConfigDialog } from './boards/boards-config-dialog';
4242
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
4343
import { BoardsConfig } from './boards/boards-config';
44-
import { MonitorService } from '../common/protocol/monitor-service';
4544
import { ConfigService } from '../common/protocol/config-service';
4645
import { MonitorConnection } from './monitor/monitor-connection';
4746
import { MonitorViewContribution } from './monitor/monitor-view-contribution';
@@ -79,9 +78,6 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
7978
@inject(CoreService)
8079
protected readonly coreService: CoreService;
8180

82-
@inject(MonitorService)
83-
protected readonly monitorService: MonitorService;
84-
8581
@inject(WorkspaceServiceExt)
8682
protected readonly workspaceServiceExt: WorkspaceServiceExt;
8783

@@ -336,7 +332,9 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
336332
}
337333

338334
const connectionConfig = this.monitorConnection.connectionConfig;
339-
await this.monitorConnection.disconnect();
335+
if (connectionConfig) {
336+
await this.monitorConnection.disconnect();
337+
}
340338

341339
try {
342340
const { boardsConfig } = this.boardsServiceClient;
Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,114 @@
1-
import { injectable, inject } from "inversify";
2-
import { MonitorService, ConnectionConfig } from "../../common/protocol/monitor-service";
3-
import { Emitter, Event } from "@theia/core";
1+
import { injectable, inject, postConstruct } from 'inversify';
2+
import { Emitter, Event } from '@theia/core/lib/common/event';
3+
// import { ConnectionStatusService } from '@theia/core/lib/browser/connection-status-service';
4+
import { MessageService } from '@theia/core/lib/common/message-service';
5+
import { MonitorService, MonitorConfig, MonitorError } from '../../common/protocol/monitor-service';
6+
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
7+
import { Port, Board } from '../../common/protocol/boards-service';
8+
import { MonitorServiceClientImpl } from './monitor-service-client-impl';
49

510
@injectable()
611
export class MonitorConnection {
712

813
@inject(MonitorService)
914
protected readonly monitorService: MonitorService;
1015

11-
connectionId: string | undefined;
16+
@inject(MonitorServiceClientImpl)
17+
protected readonly monitorServiceClient: MonitorServiceClientImpl;
1218

13-
protected _connectionConfig: ConnectionConfig | undefined;
19+
@inject(BoardsServiceClientImpl)
20+
protected boardsServiceClient: BoardsServiceClientImpl;
1421

22+
@inject(MessageService)
23+
protected messageService: MessageService;
24+
25+
// @inject(ConnectionStatusService)
26+
// protected readonly connectionStatusService: ConnectionStatusService;
27+
28+
protected state: MonitorConnection.State | undefined;
1529
protected readonly onConnectionChangedEmitter = new Emitter<string | undefined>();
30+
1631
readonly onConnectionChanged: Event<string | undefined> = this.onConnectionChangedEmitter.event;
1732

18-
get connectionConfig(): ConnectionConfig | undefined {
19-
return this._connectionConfig;
33+
@postConstruct()
34+
protected init(): void {
35+
this.monitorServiceClient.onError(error => {
36+
if (this.state) {
37+
const { code, connectionId, config } = error;
38+
if (this.state.connectionId === connectionId) {
39+
switch (code) {
40+
case MonitorError.ErrorCodes.CLIENT_CANCEL: {
41+
console.log(`Connection was canceled by client: ${MonitorConnection.State.toString(this.state)}.`);
42+
break;
43+
}
44+
case MonitorError.ErrorCodes.DEVICE_BUSY: {
45+
const { port } = config;
46+
this.messageService.warn(`Connection failed. Serial port is busy: ${Port.toString(port)}.`);
47+
break;
48+
}
49+
case MonitorError.ErrorCodes.DEVICE_NOT_CONFIGURED: {
50+
const { port } = config;
51+
this.messageService.info(`Disconnected from ${Port.toString(port)}.`);
52+
break;
53+
}
54+
}
55+
this.state = undefined;
56+
} else {
57+
console.warn(`Received an error from unexpected connection: ${MonitorConnection.State.toString({ connectionId, config })}.`);
58+
}
59+
}
60+
});
2061
}
2162

22-
async connect(config: ConnectionConfig): Promise<string | undefined> {
23-
if (this.connectionId) {
24-
await this.disconnect();
25-
}
26-
const { connectionId } = await this.monitorService.connect(config);
27-
this.connectionId = connectionId;
28-
this._connectionConfig = config;
63+
get connectionId(): string | undefined {
64+
return this.state ? this.state.connectionId : undefined;
65+
}
2966

30-
this.onConnectionChangedEmitter.fire(this.connectionId);
67+
get connectionConfig(): MonitorConfig | undefined {
68+
return this.state ? this.state.config : undefined;
69+
}
3170

71+
async connect(config: MonitorConfig): Promise<string | undefined> {
72+
if (this.state) {
73+
throw new Error(`Already connected to ${MonitorConnection.State.toString(this.state)}.`);
74+
}
75+
const { connectionId } = await this.monitorService.connect(config);
76+
this.state = { connectionId, config };
77+
this.onConnectionChangedEmitter.fire(connectionId);
3278
return connectionId;
3379
}
3480

3581
async disconnect(): Promise<boolean> {
36-
let result = true;
37-
const connections = await this.monitorService.getConnectionIds();
38-
if (this.connectionId && connections.findIndex(id => id === this.connectionId) >= 0) {
39-
console.log('>>> Disposing existing monitor connection before establishing a new one...');
40-
result = await this.monitorService.disconnect(this.connectionId);
41-
if (!result) {
42-
// TODO: better!!!
43-
console.error(`Could not close connection: ${this.connectionId}. Check the backend logs.`);
44-
} else {
45-
console.log(`<<< Disposed ${this.connectionId} connection.`);
46-
this.connectionId = undefined;
47-
this._connectionConfig = undefined;
48-
this.onConnectionChangedEmitter.fire(this.connectionId);
49-
}
82+
if (!this.state) {
83+
throw new Error('Not connected. Nothing to disconnect.');
84+
}
85+
console.log('>>> Disposing existing monitor connection before establishing a new one...');
86+
const result = await this.monitorService.disconnect(this.state.connectionId);
87+
if (result) {
88+
console.log(`<<< Disposed connection. Was: ${MonitorConnection.State.toString(this.state)}`);
89+
this.state = undefined;
90+
this.onConnectionChangedEmitter.fire(undefined);
91+
} else {
92+
console.warn(`<<< Could not dispose connection. Activate connection: ${MonitorConnection.State.toString(this.state)}`);
5093
}
5194
return result;
5295
}
53-
}
96+
97+
}
98+
99+
export namespace MonitorConnection {
100+
101+
export interface State {
102+
readonly connectionId: string;
103+
readonly config: MonitorConfig;
104+
}
105+
106+
export namespace State {
107+
export function toString(state: State): string {
108+
const { connectionId, config } = state;
109+
const { board, port } = config;
110+
return `${Board.toString(board)} ${Port.toString(port)} [ID: ${connectionId}]`;
111+
}
112+
}
113+
114+
}
Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,93 @@
1-
import { injectable } from "inversify";
2-
import { Emitter } from "@theia/core";
3-
4-
export namespace MonitorModel {
5-
export interface Data {
6-
autoscroll: boolean,
7-
timestamp: boolean,
8-
baudRate: number,
9-
lineEnding: string
10-
}
11-
}
1+
import { injectable } from 'inversify';
2+
import { Emitter, Event } from '@theia/core/lib/common/event';
3+
import { MonitorConfig } from '../../common/protocol/monitor-service';
124

135
@injectable()
146
export class MonitorModel {
157

16-
protected readonly onChangeEmitter = new Emitter<void>();
8+
protected readonly onChangeEmitter: Emitter<void>;
9+
protected _autoscroll: boolean;
10+
protected _timestamp: boolean;
11+
protected _baudRate: MonitorConfig.BaudRate;
12+
protected _lineEnding: MonitorModel.EOL;
1713

18-
readonly onChange = this.onChangeEmitter.event;
14+
constructor() {
15+
this._autoscroll = true;
16+
this._timestamp = false;
17+
this._baudRate = MonitorConfig.BaudRate.DEFAULT;
18+
this._lineEnding = MonitorModel.EOL.DEFAULT;
19+
this.onChangeEmitter = new Emitter<void>();
20+
}
1921

20-
protected _autoscroll: boolean = true;
21-
protected _timestamp: boolean = false;
22-
baudRate: number;
23-
lineEnding: string = '\n';
22+
get onChange(): Event<void> {
23+
return this.onChangeEmitter.event;
24+
}
2425

2526
get autoscroll(): boolean {
2627
return this._autoscroll;
2728
}
2829

30+
toggleAutoscroll(): void {
31+
this._autoscroll = !this._autoscroll;
32+
}
33+
2934
get timestamp(): boolean {
3035
return this._timestamp;
3136
}
3237

33-
toggleAutoscroll(): void {
34-
this._autoscroll = !this._autoscroll;
38+
toggleTimestamp(): void {
39+
this._timestamp = !this._timestamp;
40+
}
41+
42+
get baudRate(): MonitorConfig.BaudRate {
43+
return this._baudRate;
44+
}
45+
46+
set baudRate(baudRate: MonitorConfig.BaudRate) {
47+
this._baudRate = baudRate;
3548
this.onChangeEmitter.fire(undefined);
3649
}
3750

38-
toggleTimestamp(): void {
39-
this._timestamp = !this._timestamp;
51+
get lineEnding(): MonitorModel.EOL {
52+
return this._lineEnding;
53+
}
54+
55+
set lineEnding(lineEnding: MonitorModel.EOL) {
56+
this._lineEnding = lineEnding;
4057
this.onChangeEmitter.fire(undefined);
4158
}
4259

43-
restore(model: MonitorModel.Data) {
44-
this._autoscroll = model.autoscroll;
45-
this._timestamp = model.timestamp;
46-
this.baudRate = model.baudRate;
47-
this.lineEnding = model.lineEnding;
60+
restore(state: MonitorModel.State) {
61+
this._autoscroll = state.autoscroll;
62+
this._timestamp = state.timestamp;
63+
this._baudRate = state.baudRate;
64+
this._lineEnding = state.lineEnding;
65+
this.onChangeEmitter.fire(undefined);
4866
}
4967

50-
store(): MonitorModel.Data {
68+
store(): MonitorModel.State {
5169
return {
5270
autoscroll: this._autoscroll,
5371
timestamp: this._timestamp,
54-
baudRate: this.baudRate,
55-
lineEnding: this.lineEnding
72+
baudRate: this._baudRate,
73+
lineEnding: this._lineEnding
5674
}
5775
}
58-
}
76+
77+
}
78+
79+
export namespace MonitorModel {
80+
81+
export interface State {
82+
autoscroll: boolean;
83+
timestamp: boolean;
84+
baudRate: MonitorConfig.BaudRate;
85+
lineEnding: EOL;
86+
}
87+
88+
export type EOL = '' | '\n' | '\r' | '\r\n';
89+
export namespace EOL {
90+
export const DEFAULT: EOL = '\n';
91+
}
92+
93+
}

arduino-ide-extension/src/browser/monitor/monitor-service-client-impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class MonitorServiceClientImpl implements MonitorServiceClient {
1313
notifyRead(event: MonitorReadEvent): void {
1414
this.onReadEmitter.fire(event);
1515
const { connectionId, data } = event;
16-
console.log(`Received data from ${connectionId}: ${data}`);
16+
console.debug(`Received data from ${connectionId}: ${data}`);
1717
}
1818

1919
notifyError(error: MonitorError): void {

arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class MonitorViewContribution extends AbstractViewContribution<MonitorWid
8080
isVisible: widget => widget instanceof MonitorWidget,
8181
execute: widget => {
8282
if (widget instanceof MonitorWidget) {
83-
widget.clear();
83+
widget.clearConsole();
8484
}
8585
}
8686
});
@@ -124,4 +124,5 @@ export class MonitorViewContribution extends AbstractViewContribution<MonitorWid
124124
protected async doToggleTimestamp() {
125125
this.model.toggleTimestamp();
126126
}
127-
}
127+
128+
}

0 commit comments

Comments
 (0)