Skip to content

Commit df8658e

Browse files
Alberto Iannacconefstasisilvanocerzamsujewdavegarthsimpson
authored
Pluggable monitor (#982)
* backend structure WIP * Scaffold interfaces and classes for pluggable monitors * Implement MonitorService to handle pluggable monitor lifetime * Rename WebSocketService to WebSocketProvider and uninjected it * Moved some interfaces * Changed upload settings * Enhance MonitorManager APIs * Fixed WebSocketChange event signature * Add monitor proxy functions for the frontend * Moved settings to MonitorService * Remove several unnecessary serial monitor classes * Changed how connection is handled on upload * Proxied more monitor methods to frontend * WebSocketProvider is not injectable anymore * Add generic monitor settings storaging * More serial classes removal * Remove unused file * Changed plotter contribution to use new manager proxy * Changed MonitorWidget and children to use new monitor proxy * Updated MonitorWidget to use new monitor proxy * Fix backend logger bindings * Delete unnecessary Symbol * coreClientProvider is now set when constructing MonitorService * Add missing binding * Fix `MonitorManagerProxy` DI issue * fix monitor connection * delete duplex when connection is closed * update arduino-cli to 0.22.0 * fix upload when monitor is open * add MonitorSettingsProvider interface * monitor settings provider stub * updated pseudo code * refactor monitor settings interfaces * monitor service provider singleton * add unit tests * change MonitorService providers to injectable deps * fix monitor settings client communication * refactor monitor commands protocol * use monitor settings provider properly * add settings to monitor model * add settings to monitor model * reset serial monitor when port changes * fix serial plotter opening * refine monitor connection settings * fix hanging web socket connections * add serial plotter reset command * send port to web socket clients * monitor service wait for success serial port open * fix reset loop * update serial plotter version * update arduino-cli version to 0.23.0-rc1 and regenerate grpc protocol * remove useless plotter protocol file * localize web socket errors * clean-up code * update translation file * Fix duplicated editor tabs (#1012) * Save dialog for closing temporary sketch and unsaved files (#893) * Use normal `OnWillStop` event * Align `CLOSE` command to rest of app * Fixed FS path vs encoded URL comparision when handling stop request. Ref: eclipse-theia/theia#11226 Signed-off-by: Akos Kitta <[email protected]> * Fixed the translations. Signed-off-by: Akos Kitta <[email protected]> * Fixed the translations again. Removed `electron` from the `nls-extract`. It does not contain app code. Signed-off-by: Akos Kitta <[email protected]> * Aligned the stop handler code to Theia. Signed-off-by: Akos Kitta <[email protected]> Co-authored-by: Akos Kitta <[email protected]> * fix serial monitor send line ending * refactor monitor-service poll for test/readability * localize web socket errors * update translation file * Fix duplicated editor tabs (#1012) * i18n:check rerun * Speed up IDE startup time. Signed-off-by: Akos Kitta <[email protected]> * override coreClientProvider in monitor-service * cleanup merged code Co-authored-by: Francesco Stasi <[email protected]> Co-authored-by: Silvano Cerza <[email protected]> Co-authored-by: Mark Sujew <[email protected]> Co-authored-by: David Simpson <[email protected]> Co-authored-by: Akos Kitta <[email protected]>
1 parent 4c55807 commit df8658e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2328
-1566
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"@types/temp": "^0.8.34",
5858
"@types/which": "^1.3.1",
5959
"ajv": "^6.5.3",
60-
"arduino-serial-plotter-webapp": "0.0.17",
60+
"arduino-serial-plotter-webapp": "0.1.0",
6161
"async-mutex": "^0.3.0",
6262
"atob": "^2.1.2",
6363
"auth0-js": "^9.14.0",

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

+54-39
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,12 @@ import { ScmContribution } from './theia/scm/scm-contribution';
6868
import { SearchInWorkspaceFrontendContribution as TheiaSearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution';
6969
import { SearchInWorkspaceFrontendContribution } from './theia/search-in-workspace/search-in-workspace-frontend-contribution';
7070
import { LibraryListWidgetFrontendContribution } from './library/library-widget-frontend-contribution';
71-
import { SerialServiceClientImpl } from './serial/serial-service-client-impl';
72-
import {
73-
SerialServicePath,
74-
SerialService,
75-
SerialServiceClient,
76-
} from '../common/protocol/serial-service';
7771
import {
7872
ConfigService,
7973
ConfigServicePath,
8074
} from '../common/protocol/config-service';
8175
import { MonitorWidget } from './serial/monitor/monitor-widget';
8276
import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution';
83-
import { SerialConnectionManager } from './serial/serial-connection-manager';
84-
import { SerialModel } from './serial/serial-model';
8577
import { TabBarDecoratorService as TheiaTabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator';
8678
import { TabBarDecoratorService } from './theia/core/tab-bar-decorator';
8779
import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser';
@@ -158,7 +150,14 @@ import {
158150
OutputChannelRegistryMainImpl as TheiaOutputChannelRegistryMainImpl,
159151
OutputChannelRegistryMainImpl,
160152
} from './theia/plugin-ext/output-channel-registry-main';
161-
import { ExecutableService, ExecutableServicePath } from '../common/protocol';
153+
import {
154+
ExecutableService,
155+
ExecutableServicePath,
156+
MonitorManagerProxy,
157+
MonitorManagerProxyClient,
158+
MonitorManagerProxyFactory,
159+
MonitorManagerProxyPath,
160+
} from '../common/protocol';
162161
import { MonacoTextModelService as TheiaMonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
163162
import { MonacoTextModelService } from './theia/monaco/monaco-text-model-service';
164163
import { ResponseServiceImpl } from './response-service-impl';
@@ -273,6 +272,8 @@ import {
273272
IDEUpdaterDialogWidget,
274273
} from './dialogs/ide-updater/ide-updater-dialog';
275274
import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider';
275+
import { MonitorModel } from './monitor-model';
276+
import { MonitorManagerProxyClientImpl } from './monitor-manager-proxy-client-impl';
276277
import { EditorManager as TheiaEditorManager } from '@theia/editor/lib/browser/editor-manager';
277278
import { EditorManager } from './theia/editor/editor-manager';
278279
import { HostedPluginEvents } from './hosted-plugin-events';
@@ -424,29 +425,44 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
424425
.inSingletonScope();
425426

426427
// Serial monitor
427-
bind(SerialModel).toSelf().inSingletonScope();
428-
bind(FrontendApplicationContribution).toService(SerialModel);
429428
bind(MonitorWidget).toSelf();
429+
bind(FrontendApplicationContribution).toService(MonitorModel);
430+
bind(MonitorModel).toSelf().inSingletonScope();
430431
bindViewContribution(bind, MonitorViewContribution);
431432
bind(TabBarToolbarContribution).toService(MonitorViewContribution);
432433
bind(WidgetFactory).toDynamicValue((context) => ({
433434
id: MonitorWidget.ID,
434-
createWidget: () => context.container.get(MonitorWidget),
435-
}));
436-
// Frontend binding for the serial service
437-
bind(SerialService)
438-
.toDynamicValue((context) => {
439-
const connection = context.container.get(WebSocketConnectionProvider);
440-
const client = context.container.get<SerialServiceClient>(
441-
SerialServiceClient
435+
createWidget: () => {
436+
return new MonitorWidget(
437+
context.container.get<MonitorModel>(MonitorModel),
438+
context.container.get<MonitorManagerProxyClient>(
439+
MonitorManagerProxyClient
440+
),
441+
context.container.get<BoardsServiceProvider>(BoardsServiceProvider)
442442
);
443-
return connection.createProxy(SerialServicePath, client);
444-
})
443+
},
444+
}));
445+
446+
bind(MonitorManagerProxyFactory).toFactory(
447+
(context) => () =>
448+
context.container.get<MonitorManagerProxy>(MonitorManagerProxy)
449+
);
450+
451+
bind(MonitorManagerProxy)
452+
.toDynamicValue((context) =>
453+
WebSocketConnectionProvider.createProxy(
454+
context.container,
455+
MonitorManagerProxyPath,
456+
context.container.get(MonitorManagerProxyClient)
457+
)
458+
)
445459
.inSingletonScope();
446-
bind(SerialConnectionManager).toSelf().inSingletonScope();
447460

448-
// Serial service client to receive and delegate notifications from the backend.
449-
bind(SerialServiceClient).to(SerialServiceClientImpl).inSingletonScope();
461+
// Monitor manager proxy client to receive and delegate pluggable monitors
462+
// notifications from the backend
463+
bind(MonitorManagerProxyClient)
464+
.to(MonitorManagerProxyClientImpl)
465+
.inSingletonScope();
450466

451467
bind(WorkspaceService).toSelf().inSingletonScope();
452468
rebind(TheiaWorkspaceService).toService(WorkspaceService);
@@ -502,11 +518,12 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
502518
.inSingletonScope();
503519
rebind(TheiaEditorWidgetFactory).to(EditorWidgetFactory).inSingletonScope();
504520
rebind(TabBarToolbarFactory).toFactory(
505-
({ container: parentContainer }) => () => {
506-
const container = parentContainer.createChild();
507-
container.bind(TabBarToolbar).toSelf().inSingletonScope();
508-
return container.get(TabBarToolbar);
509-
}
521+
({ container: parentContainer }) =>
522+
() => {
523+
const container = parentContainer.createChild();
524+
container.bind(TabBarToolbar).toSelf().inSingletonScope();
525+
return container.get(TabBarToolbar);
526+
}
510527
);
511528
bind(OutputWidget).toSelf().inSingletonScope();
512529
rebind(TheiaOutputWidget).toService(OutputWidget);
@@ -523,7 +540,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
523540

524541
bind(SearchInWorkspaceWidget).toSelf();
525542
rebind(TheiaSearchInWorkspaceWidget).toService(SearchInWorkspaceWidget);
526-
543+
527544
rebind(TheiaEditorManager).to(EditorManager);
528545

529546
// replace search icon
@@ -560,9 +577,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
560577
bind(ProblemManager).toSelf().inSingletonScope();
561578
rebind(TheiaProblemManager).toService(ProblemManager);
562579

563-
// Customized layout restorer that can restore the state in async way: https://github.com/eclipse-theia/theia/issues/6579
564-
bind(ShellLayoutRestorer).toSelf().inSingletonScope();
565-
rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer);
580+
// Customized layout restorer that can restore the state in async way: https://github.com/eclipse-theia/theia/issues/6579
581+
bind(ShellLayoutRestorer).toSelf().inSingletonScope();
582+
rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer);
566583

567584
// No dropdown for the _Output_ view.
568585
bind(OutputToolbarContribution).toSelf().inSingletonScope();
@@ -687,15 +704,13 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
687704

688705
// Enable the dirty indicator on uncloseable widgets.
689706
rebind(TabBarRendererFactory).toFactory((context) => () => {
690-
const contextMenuRenderer = context.container.get<ContextMenuRenderer>(
691-
ContextMenuRenderer
692-
);
707+
const contextMenuRenderer =
708+
context.container.get<ContextMenuRenderer>(ContextMenuRenderer);
693709
const decoratorService = context.container.get<TabBarDecoratorService>(
694710
TabBarDecoratorService
695711
);
696-
const iconThemeService = context.container.get<IconThemeService>(
697-
IconThemeService
698-
);
712+
const iconThemeService =
713+
context.container.get<IconThemeService>(IconThemeService);
699714
return new TabBarRenderer(
700715
contextMenuRenderer,
701716
decoratorService,

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

+7-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { OutputChannelManager } from '@theia/output/lib/browser/output-channel';
33
import { CoreService } from '../../common/protocol';
44
import { ArduinoMenus } from '../menu/arduino-menus';
55
import { BoardsDataStore } from '../boards/boards-data-store';
6-
import { SerialConnectionManager } from '../serial/serial-connection-manager';
76
import { BoardsServiceProvider } from '../boards/boards-service-provider';
87
import {
98
SketchContribution,
@@ -18,8 +17,6 @@ export class BurnBootloader extends SketchContribution {
1817
@inject(CoreService)
1918
protected readonly coreService: CoreService;
2019

21-
@inject(SerialConnectionManager)
22-
protected readonly serialConnection: SerialConnectionManager;
2320

2421
@inject(BoardsDataStore)
2522
protected readonly boardsDataStore: BoardsDataStore;
@@ -60,9 +57,15 @@ export class BurnBootloader extends SketchContribution {
6057
this.preferences.get('arduino.upload.verify'),
6158
this.preferences.get('arduino.upload.verbose'),
6259
]);
60+
61+
const board = {
62+
...boardsConfig.selectedBoard,
63+
name: boardsConfig.selectedBoard?.name || '',
64+
fqbn,
65+
}
6366
this.outputChannelManager.getChannel('Arduino').clear();
6467
await this.coreService.burnBootloader({
65-
fqbn,
68+
board,
6669
programmer,
6770
port,
6871
verify,
@@ -85,8 +88,6 @@ export class BurnBootloader extends SketchContribution {
8588
errorMessage = e.toString();
8689
}
8790
this.messageService.error(errorMessage);
88-
} finally {
89-
await this.serialConnection.reconnectAfterUpload();
9091
}
9192
}
9293
}

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

+7-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { BoardUserField, CoreService } from '../../common/protocol';
44
import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus';
55
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
66
import { BoardsDataStore } from '../boards/boards-data-store';
7-
import { SerialConnectionManager } from '../serial/serial-connection-manager';
87
import { BoardsServiceProvider } from '../boards/boards-service-provider';
98
import {
109
SketchContribution,
@@ -23,9 +22,6 @@ export class UploadSketch extends SketchContribution {
2322
@inject(CoreService)
2423
protected readonly coreService: CoreService;
2524

26-
@inject(SerialConnectionManager)
27-
protected readonly serialConnection: SerialConnectionManager;
28-
2925
@inject(MenuModelRegistry)
3026
protected readonly menuRegistry: MenuModelRegistry;
3127

@@ -227,6 +223,11 @@ export class UploadSketch extends SketchContribution {
227223
this.sourceOverride(),
228224
]);
229225

226+
const board = {
227+
...boardsConfig.selectedBoard,
228+
name: boardsConfig.selectedBoard?.name || '',
229+
fqbn,
230+
}
230231
let options: CoreService.Upload.Options | undefined = undefined;
231232
const sketchUri = sketch.uri;
232233
const optimizeForDebug = this.editorMode.compileForDebug;
@@ -248,7 +249,7 @@ export class UploadSketch extends SketchContribution {
248249
const programmer = selectedProgrammer;
249250
options = {
250251
sketchUri,
251-
fqbn,
252+
board,
252253
optimizeForDebug,
253254
programmer,
254255
port,
@@ -260,7 +261,7 @@ export class UploadSketch extends SketchContribution {
260261
} else {
261262
options = {
262263
sketchUri,
263-
fqbn,
264+
board,
264265
optimizeForDebug,
265266
port,
266267
verbose,
@@ -290,8 +291,6 @@ export class UploadSketch extends SketchContribution {
290291
} finally {
291292
this.uploadInProgress = false;
292293
this.onDidChangeEmitter.fire();
293-
294-
setTimeout(() => this.serialConnection.reconnectAfterUpload(), 5000);
295294
}
296295
}
297296
}

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,17 @@ export class VerifySketch extends SketchContribution {
111111
),
112112
this.sourceOverride(),
113113
]);
114+
const board = {
115+
...boardsConfig.selectedBoard,
116+
name: boardsConfig.selectedBoard?.name || '',
117+
fqbn,
118+
}
114119
const verbose = this.preferences.get('arduino.compile.verbose');
115120
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
116121
this.outputChannelManager.getChannel('Arduino').clear();
117122
await this.coreService.compile({
118123
sketchUri: sketch.uri,
119-
fqbn,
124+
board,
120125
optimizeForDebug: this.editorMode.compileForDebug,
121126
verbose,
122127
exportBinaries,

Diff for: arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-component.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { nls } from '@theia/core/lib/common';
22
import * as React from '@theia/core/shared/react';
3+
import { Port } from '../../../common/protocol';
34
import {
45
ArduinoFirmwareUploader,
56
FirmwareInfo,
@@ -20,7 +21,7 @@ export const FirmwareUploaderComponent = ({
2021
availableBoards: AvailableBoard[];
2122
firmwareUploader: ArduinoFirmwareUploader;
2223
updatableFqbns: string[];
23-
flashFirmware: (firmware: FirmwareInfo, port: string) => Promise<any>;
24+
flashFirmware: (firmware: FirmwareInfo, port: Port) => Promise<any>;
2425
isOpen: any;
2526
}): React.ReactElement => {
2627
// boolean states for buttons
@@ -81,7 +82,7 @@ export const FirmwareUploaderComponent = ({
8182
const installStatus =
8283
!!firmwareToFlash &&
8384
!!selectedBoard?.port &&
84-
(await flashFirmware(firmwareToFlash, selectedBoard?.port.address));
85+
(await flashFirmware(firmwareToFlash, selectedBoard?.port));
8586

8687
setInstallFeedback((installStatus && 'ok') || 'fail');
8788
} catch {

Diff for: arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import * as React from '@theia/core/shared/react';
2-
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
2+
import {
3+
inject,
4+
injectable,
5+
postConstruct,
6+
} from '@theia/core/shared/inversify';
37
import { DialogProps } from '@theia/core/lib/browser/dialogs';
48
import { AbstractDialog } from '../../theia/dialogs/dialogs';
59
import { Widget } from '@theia/core/shared/@phosphor/widgets';
@@ -15,6 +19,7 @@ import {
1519
} from '../../../common/protocol/arduino-firmware-uploader';
1620
import { FirmwareUploaderComponent } from './firmware-uploader-component';
1721
import { UploadFirmware } from '../../contributions/upload-firmware';
22+
import { Port } from '../../../common/protocol';
1823
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
1924

2025
@injectable()
@@ -54,7 +59,7 @@ export class UploadFirmwareDialogWidget extends ReactWidget {
5459
});
5560
}
5661

57-
protected flashFirmware(firmware: FirmwareInfo, port: string): Promise<any> {
62+
protected flashFirmware(firmware: FirmwareInfo, port: Port): Promise<any> {
5863
this.busyCallback(true);
5964
return this.arduinoFirmwareUploader
6065
.flash(firmware, port)

0 commit comments

Comments
 (0)