Skip to content

Commit 767b09d

Browse files
authored
Fix upload and serial (#661)
* get serial connection status from BE * handle serial connect in the BE * allow breakpoints on vscode (windows) * Timeout on config change to prevent serial busy * serial-service tests
1 parent 8839793 commit 767b09d

19 files changed

+574
-754
lines changed

Diff for: .vscode/launch.json

-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
99
"windows": {
1010
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
11-
"env": {
12-
"NODE_ENV": "development",
13-
"NODE_PRESERVE_SYMLINKS": "1"
14-
}
1511
},
1612
"cwd": "${workspaceFolder}/electron-app",
1713
"protocol": "inspector",

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@
1919
"test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\""
2020
},
2121
"dependencies": {
22-
"arduino-serial-plotter-webapp": "0.0.15",
2322
"@grpc/grpc-js": "^1.3.7",
2423
"@theia/application-package": "1.19.0",
2524
"@theia/core": "1.19.0",
2625
"@theia/editor": "1.19.0",
27-
"@theia/editor-preview": "1.19.0",
26+
"@theia/editor-preview": "1.19.0",
2827
"@theia/filesystem": "1.19.0",
2928
"@theia/git": "1.19.0",
3029
"@theia/keymaps": "1.19.0",
@@ -53,10 +52,10 @@
5352
"@types/ps-tree": "^1.1.0",
5453
"@types/react-select": "^3.0.0",
5554
"@types/react-tabs": "^2.3.2",
56-
"@types/sinon": "^7.5.2",
5755
"@types/temp": "^0.8.34",
5856
"@types/which": "^1.3.1",
5957
"ajv": "^6.5.3",
58+
"arduino-serial-plotter-webapp": "0.0.15",
6059
"async-mutex": "^0.3.0",
6160
"atob": "^2.1.2",
6261
"auth0-js": "^9.14.0",
@@ -97,6 +96,8 @@
9796
"@types/chai-string": "^1.4.2",
9897
"@types/mocha": "^5.2.7",
9998
"@types/react-window": "^1.8.5",
99+
"@types/sinon": "^10.0.6",
100+
"@types/sinon-chai": "^3.2.6",
100101
"chai": "^4.2.0",
101102
"chai-string": "^1.5.0",
102103
"decompress": "^4.2.0",
@@ -109,7 +110,8 @@
109110
"moment": "^2.24.0",
110111
"protoc": "^1.0.4",
111112
"shelljs": "^0.8.3",
112-
"sinon": "^9.0.1",
113+
"sinon": "^12.0.1",
114+
"sinon-chai": "^3.7.0",
113115
"typemoq": "^2.1.0",
114116
"uuid": "^3.2.1",
115117
"yargs": "^11.1.0"

Diff for: arduino-ide-extension/src/browser/contributions/burn-bootloader.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export class BurnBootloader extends SketchContribution {
4848
}
4949

5050
async burnBootloader(): Promise<void> {
51-
await this.serialConnection.disconnect();
5251
try {
5352
const { boardsConfig } = this.boardsServiceClientImpl;
5453
const port = boardsConfig.selectedPort;
@@ -87,9 +86,7 @@ export class BurnBootloader extends SketchContribution {
8786
}
8887
this.messageService.error(errorMessage);
8988
} finally {
90-
if (this.serialConnection.isSerialOpen()) {
91-
await this.serialConnection.connect();
92-
}
89+
await this.serialConnection.reconnectAfterUpload();
9390
}
9491
}
9592
}

Diff for: arduino-ide-extension/src/browser/contributions/upload-sketch.ts

+2-22
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ export class UploadSketch extends SketchContribution {
210210
if (!sketch) {
211211
return;
212212
}
213-
await this.serialConnection.disconnect();
213+
214214
try {
215215
const { boardsConfig } = this.boardsServiceClientImpl;
216216
const [fqbn, { selectedProgrammer }, verify, verbose, sourceOverride] =
@@ -288,27 +288,7 @@ export class UploadSketch extends SketchContribution {
288288
this.uploadInProgress = false;
289289
this.onDidChangeEmitter.fire();
290290

291-
if (
292-
this.serialConnection.isSerialOpen() &&
293-
this.serialConnection.serialConfig
294-
) {
295-
const { board, port } = this.serialConnection.serialConfig;
296-
try {
297-
await this.boardsServiceClientImpl.waitUntilAvailable(
298-
Object.assign(board, { port }),
299-
10_000
300-
);
301-
await this.serialConnection.connect();
302-
} catch (waitError) {
303-
this.messageService.error(
304-
nls.localize(
305-
'arduino/sketch/couldNotConnectToSerial',
306-
'Could not reconnect to serial port. {0}',
307-
waitError.toString()
308-
)
309-
);
310-
}
311-
}
291+
setTimeout(() => this.serialConnection.reconnectAfterUpload(), 5000);
312292
}
313293
}
314294
}

Diff for: arduino-ide-extension/src/browser/serial/monitor/monitor-widget.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { SerialConfig } from '../../../common/protocol/serial-service';
1313
import { ArduinoSelect } from '../../widgets/arduino-select';
1414
import { SerialModel } from '../serial-model';
15-
import { Serial, SerialConnectionManager } from '../serial-connection-manager';
15+
import { SerialConnectionManager } from '../serial-connection-manager';
1616
import { SerialMonitorSendInput } from './serial-monitor-send-input';
1717
import { SerialMonitorOutput } from './serial-monitor-send-output';
1818
import { BoardsServiceProvider } from '../../boards/boards-service-provider';
@@ -57,9 +57,7 @@ export class MonitorWidget extends ReactWidget {
5757
this.scrollOptions = undefined;
5858
this.toDispose.push(this.clearOutputEmitter);
5959
this.toDispose.push(
60-
Disposable.create(() =>
61-
this.serialConnection.closeSerial(Serial.Type.Monitor)
62-
)
60+
Disposable.create(() => this.serialConnection.closeWStoBE())
6361
);
6462
}
6563

@@ -83,7 +81,7 @@ export class MonitorWidget extends ReactWidget {
8381

8482
protected onAfterAttach(msg: Message): void {
8583
super.onAfterAttach(msg);
86-
this.serialConnection.openSerial(Serial.Type.Monitor);
84+
this.serialConnection.openWSToBE();
8785
}
8886

8987
onCloseRequest(msg: Message): void {
@@ -171,7 +169,7 @@ export class MonitorWidget extends ReactWidget {
171169
<div className="head">
172170
<div className="send">
173171
<SerialMonitorSendInput
174-
serialConfig={this.serialConnection.serialConfig}
172+
serialConnection={this.serialConnection}
175173
resolveFocus={this.onFocusResolved}
176174
onSend={this.onSend}
177175
/>

Diff for: arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx

+40-11
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,66 @@
11
import * as React from 'react';
22
import { Key, KeyCode } from '@theia/core/lib/browser/keys';
33
import { Board, Port } from '../../../common/protocol/boards-service';
4-
import { SerialConfig } from '../../../common/protocol/serial-service';
54
import { isOSX } from '@theia/core/lib/common/os';
6-
import { nls } from '@theia/core/lib/common';
5+
import { DisposableCollection, nls } from '@theia/core/lib/common';
6+
import { SerialConnectionManager } from '../serial-connection-manager';
7+
import { SerialPlotter } from '../plotter/protocol';
78

89
export namespace SerialMonitorSendInput {
910
export interface Props {
10-
readonly serialConfig?: SerialConfig;
11+
readonly serialConnection: SerialConnectionManager;
1112
readonly onSend: (text: string) => void;
1213
readonly resolveFocus: (element: HTMLElement | undefined) => void;
1314
}
1415
export interface State {
1516
text: string;
17+
connected: boolean;
1618
}
1719
}
1820

1921
export class SerialMonitorSendInput extends React.Component<
2022
SerialMonitorSendInput.Props,
2123
SerialMonitorSendInput.State
2224
> {
25+
protected toDisposeBeforeUnmount = new DisposableCollection();
26+
2327
constructor(props: Readonly<SerialMonitorSendInput.Props>) {
2428
super(props);
25-
this.state = { text: '' };
29+
this.state = { text: '', connected: false };
2630
this.onChange = this.onChange.bind(this);
2731
this.onSend = this.onSend.bind(this);
2832
this.onKeyDown = this.onKeyDown.bind(this);
2933
}
3034

35+
componentDidMount(): void {
36+
this.props.serialConnection.isBESerialConnected().then((connected) => {
37+
this.setState({ connected });
38+
});
39+
40+
this.toDisposeBeforeUnmount.pushAll([
41+
this.props.serialConnection.onRead(({ messages }) => {
42+
if (
43+
messages.command ===
44+
SerialPlotter.Protocol.Command.MIDDLEWARE_CONFIG_CHANGED &&
45+
'connected' in messages.data
46+
) {
47+
this.setState({ connected: messages.data.connected });
48+
}
49+
}),
50+
]);
51+
}
52+
53+
componentWillUnmount(): void {
54+
// TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout?
55+
this.toDisposeBeforeUnmount.dispose();
56+
}
57+
3158
render(): React.ReactNode {
3259
return (
3360
<input
3461
ref={this.setRef}
3562
type="text"
36-
className={`theia-input ${this.props.serialConfig ? '' : 'warning'}`}
63+
className={`theia-input ${this.state.connected ? '' : 'warning'}`}
3764
placeholder={this.placeholder}
3865
value={this.state.text}
3966
onChange={this.onChange}
@@ -43,8 +70,8 @@ export class SerialMonitorSendInput extends React.Component<
4370
}
4471

4572
protected get placeholder(): string {
46-
const { serialConfig } = this.props;
47-
if (!serialConfig) {
73+
const serialConfig = this.props.serialConnection.getConfig();
74+
if (!this.state.connected || !serialConfig) {
4875
return nls.localize(
4976
'arduino/serial/notConnected',
5077
'Not connected. Select a board and a port to connect automatically.'
@@ -55,10 +82,12 @@ export class SerialMonitorSendInput extends React.Component<
5582
'arduino/serial/message',
5683
"Message ({0} + Enter to send message to '{1}' on '{2}'",
5784
isOSX ? '⌘' : nls.localize('vscode/keybindingLabels/ctrlKey', 'Ctrl'),
58-
Board.toString(board, {
59-
useFqbn: false,
60-
}),
61-
Port.toString(port)
85+
board
86+
? Board.toString(board, {
87+
useFqbn: false,
88+
})
89+
: 'unknown',
90+
port ? Port.toString(port) : 'unknown'
6291
);
6392
}
6493

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

+5-9
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import { ArduinoMenus } from '../../menu/arduino-menus';
1111
import { Contribution } from '../../contributions/contribution';
1212
import { Endpoint, FrontendApplication } from '@theia/core/lib/browser';
1313
import { ipcRenderer } from '@theia/core/shared/electron';
14-
import { SerialConfig, Status } from '../../../common/protocol';
15-
import { Serial, SerialConnectionManager } from '../serial-connection-manager';
14+
import { SerialConfig } from '../../../common/protocol';
15+
import { SerialConnectionManager } from '../serial-connection-manager';
1616
import { SerialPlotter } from './protocol';
1717
import { BoardsServiceProvider } from '../../boards/boards-service-provider';
1818
const queryString = require('query-string');
@@ -51,10 +51,8 @@ export class PlotterFrontendContribution extends Contribution {
5151
ipcRenderer.on('CLOSE_CHILD_WINDOW', async () => {
5252
if (!!this.window) {
5353
this.window = null;
54-
await this.serialConnection.closeSerial(Serial.Type.Plotter);
5554
}
5655
});
57-
5856
return super.onStart(app);
5957
}
6058

@@ -77,25 +75,23 @@ export class PlotterFrontendContribution extends Contribution {
7775
this.window.focus();
7876
return;
7977
}
80-
const status = await this.serialConnection.openSerial(Serial.Type.Plotter);
8178
const wsPort = this.serialConnection.getWsPort();
82-
if (Status.isOK(status) && wsPort) {
79+
if (wsPort) {
8380
this.open(wsPort);
8481
} else {
85-
this.serialConnection.closeSerial(Serial.Type.Plotter);
8682
this.messageService.error(`Couldn't open serial plotter`);
8783
}
8884
}
8985

90-
protected open(wsPort: number): void {
86+
protected async open(wsPort: number): Promise<void> {
9187
const initConfig: Partial<SerialPlotter.Config> = {
9288
baudrates: SerialConfig.BaudRates.map((b) => b),
9389
currentBaudrate: this.model.baudRate,
9490
currentLineEnding: this.model.lineEnding,
9591
darkTheme: this.themeService.getCurrentTheme().type === 'dark',
9692
wsPort,
9793
interpolate: this.model.interpolate,
98-
connected: this.serialConnection.connected,
94+
connected: await this.serialConnection.isBESerialConnected(),
9995
serialPort: this.boardsServiceProvider.boardsConfig.selectedPort?.address,
10096
};
10197
const urlWithParams = queryString.stringifyUrl(

0 commit comments

Comments
 (0)