Skip to content

Commit 8a6b954

Browse files
committed
plotter communication
1 parent 8c60ed9 commit 8a6b954

File tree

9 files changed

+95
-33
lines changed

9 files changed

+95
-33
lines changed

Diff for: arduino-ide-extension/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\""
2020
},
2121
"dependencies": {
22-
"arduino-serial-plotter-webapp": "0.0.2",
22+
"arduino-serial-plotter-webapp": "0.0.3",
2323
"@grpc/grpc-js": "^1.3.7",
2424
"@theia/application-package": "1.18.0",
2525
"@theia/core": "1.18.0",

Diff for: arduino-ide-extension/src/browser/monitor/monitor-connection.ts

+23-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { BoardsConfig } from '../boards/boards-config';
2121
import { MonitorModel } from './monitor-model';
2222
import { NotificationCenter } from '../notification-center';
23+
import { ThemeService } from '@theia/core/lib/browser/theming';
2324

2425
export enum SerialType {
2526
Monitor = 'Monitor',
@@ -55,6 +56,9 @@ export class MonitorConnection {
5556
@inject(MonitorModel)
5657
protected readonly model: MonitorModel;
5758

59+
@inject(ThemeService)
60+
protected readonly themeService: ThemeService;
61+
5862
protected _state: MonitorConnection.State = [];
5963
protected _connected: boolean;
6064

@@ -89,21 +93,27 @@ export class MonitorConnection {
8993
protected init(): void {
9094
this.monitorServiceClient.onWebSocketChanged(
9195
this.handleWebSocketChanged.bind(this)
92-
),
93-
this.monitorServiceClient.onError(this.handleError.bind(this)),
94-
this.boardsServiceProvider.onBoardsConfigChanged(
95-
this.handleBoardConfigChange.bind(this)
96-
),
97-
this.notificationCenter.onAttachedBoardsChanged(
98-
this.handleAttachedBoardsChanged.bind(this)
99-
);
96+
);
97+
this.monitorServiceClient.onError(this.handleError.bind(this));
98+
this.boardsServiceProvider.onBoardsConfigChanged(
99+
this.handleBoardConfigChange.bind(this)
100+
);
101+
this.notificationCenter.onAttachedBoardsChanged(
102+
this.handleAttachedBoardsChanged.bind(this)
103+
);
100104
// Handles the `baudRate` changes by reconnecting if required.
101105
this.monitorModel.onChange(({ property }) => {
102106
if (property === 'baudRate' && this.connected) {
103107
const { boardsConfig } = this.boardsServiceProvider;
104108
this.handleBoardConfigChange(boardsConfig);
105109
}
106110
});
111+
112+
this.themeService.onDidColorThemeChange((theme) => {
113+
this.monitorService.updateWsConfigParam({
114+
darkTheme: theme.newTheme.type === 'dark',
115+
});
116+
});
107117
}
108118

109119
protected setConfig(newConfig: Partial<MonitorConfig>): void {
@@ -392,7 +402,7 @@ export class MonitorConnection {
392402
}
393403
return new Promise<Status>((resolve) => {
394404
this.monitorService
395-
.send(data + this.monitorModel.lineEnding)
405+
.sendMessageToSerial(data + this.monitorModel.lineEnding)
396406
.then(() => resolve(Status.OK));
397407
});
398408
}
@@ -419,6 +429,10 @@ export class MonitorConnection {
419429
if (ports.some((port) => Port.equals(port, boardsConfig.selectedPort))) {
420430
const { selectedBoard: board, selectedPort: port } = boardsConfig;
421431
const { baudRate } = this.monitorModel;
432+
// update the baudrate on the config
433+
this.monitorService.updateWsConfigParam({
434+
currentBaudrate: baudRate,
435+
});
422436
const newConfig: MonitorConfig = { board, port, baudRate };
423437
this.setConfig(newConfig);
424438
}

Diff for: arduino-ide-extension/src/browser/plotter/plotter-frontend-contribution.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ThemeService } from '@theia/core/lib/browser/theming';
12
import { injectable, inject } from 'inversify';
23
import {
34
Command,
@@ -37,6 +38,9 @@ export class PlotterFrontendContribution extends Contribution {
3738
@inject(MonitorModel)
3839
protected readonly model: MonitorModel;
3940

41+
@inject(ThemeService)
42+
protected readonly themeService: ThemeService;
43+
4044
@inject(MonitorConnection)
4145
protected readonly monitorConnection: MonitorConnection;
4246

@@ -90,7 +94,8 @@ export class PlotterFrontendContribution extends Contribution {
9094
const initConfig: SerialPlotter.Config = {
9195
baudrates: MonitorConfig.BaudRates.map((b) => b),
9296
currentBaudrate: this.model.baudRate,
93-
darkTheme: true,
97+
currentLineEnding: this.model.lineEnding,
98+
darkTheme: this.themeService.getCurrentTheme().type === 'dark',
9499
wsPort,
95100
};
96101
const urlWithParams = queryString.stringifyUrl(

Diff for: arduino-ide-extension/src/browser/plotter/protocol.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@ export namespace SerialPlotter {
22
export type Config = {
33
currentBaudrate: number;
44
baudrates: number[];
5+
currentLineEnding: string;
56
darkTheme: boolean;
67
wsPort: number;
78
generate?: boolean;
89
};
910
export namespace Protocol {
1011
export enum Command {
11-
PLOTTER_REQUEST_CONFIG = 'PLOTTER_REQUEST_CONFIG',
12-
PLOTTER_READY = 'PLOTTER_READY',
1312
PLOTTER_SET_BAUDRATE = 'PLOTTER_SET_BAUDRATE',
1413
PLOTTER_SET_LINE_ENDING = 'PLOTTER_SET_LINE_ENDING',
1514
PLOTTER_SEND_MESSAGE = 'PLOTTER_SEND_MESSAGE',
16-
PARENT_SET_CONFIG = 'PARENT_SET_CONFIG',
15+
MIDDLEWARE_CONFIG_CHANGED = 'MIDDLEWARE_CONFIG_CHANGED',
1716
}
1817
export type Message = {
1918
command: SerialPlotter.Protocol.Command;

Diff for: arduino-ide-extension/src/common/protocol/monitor-service.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory';
22
import { Board, Port } from './boards-service';
33
import { Event } from '@theia/core/lib/common/event';
4+
import { SerialPlotter } from '../../browser/plotter/protocol';
45

56
export interface Status {}
67
export type OK = Status;
@@ -23,7 +24,8 @@ export const MonitorService = Symbol('MonitorService');
2324
export interface MonitorService extends JsonRpcServer<MonitorServiceClient> {
2425
connect(config: MonitorConfig): Promise<Status>;
2526
disconnect(): Promise<Status>;
26-
send(message: string): Promise<Status>;
27+
sendMessageToSerial(message: string): Promise<Status>;
28+
updateWsConfigParam(config: Partial<SerialPlotter.Config>): Promise<void>;
2729
}
2830

2931
export interface MonitorConfig {

Diff for: arduino-ide-extension/src/node/monitor/monitor-service-impl.ts

+46-14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import { MonitorClientProvider } from './monitor-client-provider';
2020
import { Board, Port } from '../../common/protocol/boards-service';
2121
import { WebSocketService } from '../web-socket/web-socket-service';
22+
import { SerialPlotter } from '../../browser/plotter/protocol';
2223

2324
interface ErrorWithCode extends Error {
2425
readonly code: number;
@@ -71,7 +72,7 @@ export class MonitorServiceImpl implements MonitorService {
7172
protected readonly webSocketService: WebSocketService;
7273

7374
protected client?: MonitorServiceClient;
74-
protected connection?: {
75+
protected serialConnection?: {
7576
duplex: ClientDuplexStream<StreamingOpenRequest, StreamingOpenResponse>;
7677
config: MonitorConfig;
7778
};
@@ -84,20 +85,30 @@ export class MonitorServiceImpl implements MonitorService {
8485

8586
dispose(): void {
8687
this.logger.info('>>> Disposing monitor service...');
87-
if (this.connection) {
88+
if (this.serialConnection) {
8889
this.disconnect();
8990
}
9091
this.logger.info('<<< Disposed monitor service.');
9192
this.client = undefined;
9293
}
9394

95+
async updateWsConfigParam(
96+
config: Partial<SerialPlotter.Config>
97+
): Promise<void> {
98+
const msg: SerialPlotter.Protocol.Message = {
99+
command: SerialPlotter.Protocol.Command.MIDDLEWARE_CONFIG_CHANGED,
100+
data: config,
101+
};
102+
this.webSocketService.sendMessage(JSON.stringify(msg));
103+
}
104+
94105
async connect(config: MonitorConfig): Promise<Status> {
95106
this.logger.info(
96107
`>>> Creating serial monitor connection for ${Board.toString(
97108
config.board
98109
)} on port ${Port.toString(config.port)}...`
99110
);
100-
if (this.connection) {
111+
if (this.serialConnection) {
101112
return Status.ALREADY_CONNECTED;
102113
}
103114
const client = await this.monitorClientProvider.client();
@@ -108,7 +119,7 @@ export class MonitorServiceImpl implements MonitorService {
108119
return { message: client.message };
109120
}
110121
const duplex = client.streamingOpen();
111-
this.connection = { duplex, config };
122+
this.serialConnection = { duplex, config };
112123

113124
duplex.on(
114125
'error',
@@ -137,6 +148,27 @@ export class MonitorServiceImpl implements MonitorService {
137148
}
138149
};
139150

151+
this.webSocketService.onMessageReceived((msg: string) => {
152+
try {
153+
const message: SerialPlotter.Protocol.Message = JSON.parse(msg);
154+
155+
switch (message.command) {
156+
case SerialPlotter.Protocol.Command.PLOTTER_SEND_MESSAGE:
157+
this.sendMessageToSerial(message.data);
158+
break;
159+
160+
case SerialPlotter.Protocol.Command.PLOTTER_SET_BAUDRATE:
161+
break;
162+
163+
case SerialPlotter.Protocol.Command.PLOTTER_SET_LINE_ENDING:
164+
break;
165+
166+
default:
167+
break;
168+
}
169+
} catch (error) {}
170+
});
171+
140172
// empty the queue every 16ms (~60fps)
141173
setInterval(flushMessagesToFrontend, 32);
142174

@@ -187,8 +219,8 @@ export class MonitorServiceImpl implements MonitorService {
187219
req.setConfig(monitorConfig);
188220

189221
return new Promise<Status>((resolve) => {
190-
if (this.connection) {
191-
this.connection.duplex.write(req, () => {
222+
if (this.serialConnection) {
223+
this.serialConnection.duplex.write(req, () => {
192224
this.logger.info(
193225
`<<< Serial monitor connection created for ${Board.toString(
194226
config.board,
@@ -206,40 +238,40 @@ export class MonitorServiceImpl implements MonitorService {
206238
async disconnect(reason?: MonitorError): Promise<Status> {
207239
try {
208240
if (
209-
!this.connection &&
241+
!this.serialConnection &&
210242
reason &&
211243
reason.code === MonitorError.ErrorCodes.CLIENT_CANCEL
212244
) {
213245
return Status.OK;
214246
}
215247
this.logger.info('>>> Disposing monitor connection...');
216-
if (!this.connection) {
248+
if (!this.serialConnection) {
217249
this.logger.warn('<<< Not connected. Nothing to dispose.');
218250
return Status.NOT_CONNECTED;
219251
}
220-
const { duplex, config } = this.connection;
252+
const { duplex, config } = this.serialConnection;
221253
duplex.cancel();
222254
this.logger.info(
223255
`<<< Disposed monitor connection for ${Board.toString(config.board, {
224256
useFqbn: false,
225257
})} on port ${Port.toString(config.port)}.`
226258
);
227-
this.connection = undefined;
259+
this.serialConnection = undefined;
228260
return Status.OK;
229261
} finally {
230262
this.messages.length = 0;
231263
}
232264
}
233265

234-
async send(message: string): Promise<Status> {
235-
if (!this.connection) {
266+
async sendMessageToSerial(message: string): Promise<Status> {
267+
if (!this.serialConnection) {
236268
return Status.NOT_CONNECTED;
237269
}
238270
const req = new StreamingOpenRequest();
239271
req.setData(new TextEncoder().encode(message));
240272
return new Promise<Status>((resolve) => {
241-
if (this.connection) {
242-
this.connection.duplex.write(req, () => {
273+
if (this.serialConnection) {
274+
this.serialConnection.duplex.write(req, () => {
243275
resolve(Status.OK);
244276
});
245277
return;

Diff for: arduino-ide-extension/src/node/web-socket/web-socket-service-impl.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Emitter } from '@theia/core';
12
import { injectable } from 'inversify';
23
import * as WebSocket from 'ws';
34
import { WebSocketService } from './web-socket-service';
@@ -7,6 +8,9 @@ export default class WebSocketServiceImpl implements WebSocketService {
78
protected wsClients: WebSocket[];
89
protected server: WebSocket.Server;
910

11+
protected readonly onMessage = new Emitter<string>();
12+
public readonly onMessageReceived = this.onMessage.event;
13+
1014
constructor() {
1115
this.server = new WebSocket.Server({ port: 0 });
1216
this.server.on('connection', this.addClient.bind(this));
@@ -18,6 +22,10 @@ export default class WebSocketServiceImpl implements WebSocketService {
1822
ws.onclose = () => {
1923
this.wsClients.splice(this.wsClients.indexOf(ws), 1);
2024
};
25+
26+
ws.onmessage = (res) => {
27+
this.onMessage.fire(res.data.toString());
28+
};
2129
}
2230

2331
getAddress(): WebSocket.AddressInfo {
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { Event } from '@theia/core/lib/common/event';
12
import * as WebSocket from 'ws';
23

34
export const WebSocketService = Symbol('WebSocketService');
45
export interface WebSocketService {
56
getAddress(): WebSocket.AddressInfo;
67
sendMessage(message: string): void;
8+
onMessageReceived: Event<string>;
79
}

Diff for: yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -4012,10 +4012,10 @@ archive-type@^4.0.0:
40124012
dependencies:
40134013
file-type "^4.2.0"
40144014

4015-
4016-
version "0.0.2"
4017-
resolved "https://registry.yarnpkg.com/arduino-serial-plotter-webapp/-/arduino-serial-plotter-webapp-0.0.2.tgz#491950c30b5d29c0169e2b90047c9dcd6f90c5b3"
4018-
integrity sha512-nP1G8F+i2WeGzoNlkuEZiQnFvPfHfK1z5y5lEfa3rTXH18OGrpejmfK2SPBiBMuSirNOni9/FmTxGHIyxaxzDA==
4015+
4016+
version "0.0.3"
4017+
resolved "https://registry.yarnpkg.com/arduino-serial-plotter-webapp/-/arduino-serial-plotter-webapp-0.0.3.tgz#ff7136676fa1cf23950751ea6a675372b3d1eb25"
4018+
integrity sha512-qGxok+UQsuOVk5aOPxGjcXorQYHBNPA5fUgwMt/EbusqOnwphMHDeC3wJ3K82bNwcjg1Yf2xNJI4bRLRv+tNxw==
40194019

40204020
are-we-there-yet@~1.1.2:
40214021
version "1.1.5"

0 commit comments

Comments
 (0)