Skip to content

Serial Plotter implementation #597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
401bcf5
spawn new window where to instantiate serial plotter app
Oct 14, 2021
a834e86
initialize serial monito web app
Oct 20, 2021
a145ad9
WIP connect serial plotter app with websocket
Oct 21, 2021
d7c85fb
use npm serial-plotter package
fstasi Oct 25, 2021
f0fdc24
connect serial plotter app with websocket
Oct 21, 2021
3d616c5
refactor monito connection and fix some connection issues
Oct 29, 2021
eead91d
plotter communication
fstasi Nov 3, 2021
6ab7a38
fix clearConsole + refactor monitor connection
Nov 4, 2021
ef1377e
fixed duplicated message issue
fstasi Nov 4, 2021
eed7366
sync EoL and baudRates
fstasi Nov 4, 2021
8f1223c
add serial unit tests
Nov 9, 2021
dbaf244
updated serial plotter webapp
fstasi Nov 10, 2021
df9902d
updated serial plotter webapp to 0.0.6
fstasi Nov 11, 2021
31fde3e
handle interpolate message
Nov 11, 2021
f96a04a
fix reconnecting issues
Nov 11, 2021
5052862
updated plotter to 0.0.8
fstasi Nov 11, 2021
ee607af
bump arduino-serial-plotter-webapp to 0.0.10
Nov 15, 2021
f4938b5
bump arduino-serial-plotter-webapp to 0.0.11
Nov 16, 2021
e17960b
fix upload when serial port is open
Nov 16, 2021
1f0d4bf
remove menu bar on windows/linux
Nov 16, 2021
89e7bab
dispose send message event listener on disconnect
Nov 17, 2021
ad1cb25
update serial plotter app to 0.0.13
fstasi Nov 22, 2021
f333bbd
i18n generation
fstasi Nov 22, 2021
03eb1b3
clear flush message interval when disconnecting
Nov 23, 2021
90f9afe
bump arduino-serial-plotter-webapp to 0.0.15
Nov 23, 2021
e352f5a
refactoring and cleaning code
Nov 23, 2021
118f7f0
update localisation for serial
Nov 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions arduino-ide-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,20 @@ The Core Service is responsible for building your sketches and uploading them to
- compiling a sketch for a selected board type
- uploading a sketch to a connected board

#### Monitor Service
#### Serial Service

The Monitor Service allows getting information back from sketches running on your Arduino boards.
The Serial Service allows getting information back from sketches running on your Arduino boards.

- [src/common/protocol/monitor-service.ts](./src/common/protocol/monitor-service.ts) implements the common classes and interfaces
- [src/node/monitor/monitor-service-impl.ts](./src/node/monitor/monitor-service-impl.ts) implements the service backend:
- [src/common/protocol/serial-service.ts](./src/common/protocol/serial-service.ts) implements the common classes and interfaces
- [src/node/serial/serial-service-impl.ts](./src/node/serial/serial-service-impl.ts) implements the service backend:
- connecting to / disconnecting from a board
- receiving and sending data
- [src/browser/monitor/monitor-widget.tsx](./src/browser/monitor/monitor-widget.tsx) implements the serial monitor front-end:
- [src/browser/serial/serial-connection-manager.ts](./src/browser/serial/serial-connection-manager.ts) handles the serial connection in the frontend
- [src/browser/serial/monitor/monitor-widget.tsx](./src/browser/serial/monitor/monitor-widget.tsx) implements the serial monitor front-end:
- viewing the output from a connected board
- entering data to send to the board
- [src/browser/serial/plotter/plotter-frontend-contribution.ts](./src/browser/serial/plotter/plotter-frontend-contribution.ts) implements the serial plotter front-end:
- opening a new window running the [Serial Plotter Web App](https://github.com/arduino/arduino-serial-plotter-webapp)

#### Config Service

Expand Down
7 changes: 5 additions & 2 deletions arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"description": "An extension for Theia building the Arduino IDE",
"license": "AGPL-3.0-or-later",
"scripts": {
"prepare": "yarn download-cli && yarn download-fwuploader && yarn download-ls && yarn clean && yarn download-examples && yarn build && yarn test",
"prepare": "yarn download-cli && yarn download-fwuploader && yarn download-ls && yarn copy-serial-plotter && yarn clean && yarn download-examples && yarn build && yarn test",
"clean": "rimraf lib",
"download-cli": "node ./scripts/download-cli.js",
"download-fwuploader": "node ./scripts/download-fwuploader.js",
"copy-serial-plotter": "npx ncp ../node_modules/arduino-serial-plotter-webapp ./build/arduino-serial-plotter-webapp",
"download-ls": "node ./scripts/download-ls.js",
"download-examples": "node ./scripts/download-examples.js",
"generate-protocol": "node ./scripts/generate-protocol.js",
Expand All @@ -18,11 +19,12 @@
"test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\""
},
"dependencies": {
"arduino-serial-plotter-webapp": "0.0.15",
"@grpc/grpc-js": "^1.3.7",
"@theia/application-package": "1.18.0",
"@theia/core": "1.18.0",
"@theia/editor": "1.18.0",
"@theia/editor-preview": "1.18.0",
"@theia/editor-preview": "1.18.0",
"@theia/filesystem": "1.18.0",
"@theia/git": "1.18.0",
"@theia/keymaps": "1.18.0",
Expand Down Expand Up @@ -77,6 +79,7 @@
"open": "^8.0.6",
"p-queue": "^5.0.0",
"ps-tree": "^1.2.0",
"query-string": "^7.0.1",
"react-disable": "^0.1.0",
"react-select": "^3.0.4",
"react-tabs": "^3.1.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ import {
MAIN_MENU_BAR,
MenuContribution,
MenuModelRegistry,
SelectionService,
ILogger,
DisposableCollection,
} from '@theia/core';
import {
ContextMenuRenderer,
FrontendApplication,
FrontendApplicationContribution,
LocalStorageService,
OpenerService,
StatusBar,
StatusBarAlignment,
} from '@theia/core/lib/browser';
Expand All @@ -35,7 +32,6 @@ import {
EditorManager,
EditorOpenerOptions,
} from '@theia/editor/lib/browser';
import { FileDialogService } from '@theia/filesystem/lib/browser/file-dialog';
import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution';
import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu';
import { FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution';
Expand All @@ -47,33 +43,25 @@ import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-con
import { inject, injectable, postConstruct } from 'inversify';
import * as React from 'react';
import { remote } from 'electron';
import { MainMenuManager } from '../common/main-menu-manager';
import {
BoardsService,
CoreService,
Port,
SketchesService,
ExecutableService,
Sketch,
} from '../common/protocol';
import { ArduinoDaemon } from '../common/protocol/arduino-daemon';
import { ConfigService } from '../common/protocol/config-service';
import { FileSystemExt } from '../common/protocol/filesystem-ext';
import { ArduinoCommands } from './arduino-commands';
import { BoardsConfig } from './boards/boards-config';
import { BoardsConfigDialog } from './boards/boards-config-dialog';
import { BoardsDataStore } from './boards/boards-data-store';
import { BoardsServiceProvider } from './boards/boards-service-provider';
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
import { EditorMode } from './editor-mode';
import { ArduinoMenus } from './menu/arduino-menus';
import { MonitorConnection } from './monitor/monitor-connection';
import { MonitorViewContribution } from './monitor/monitor-view-contribution';
import { WorkspaceService } from './theia/workspace/workspace-service';
import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution';
import { ArduinoToolbar } from './toolbar/arduino-toolbar';
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { FileService } from '@theia/filesystem/lib/browser/file-service';
import { ResponseService } from '../common/protocol/response-service';
import { ArduinoPreferences } from './arduino-preferences';
import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl';
import { SaveAsSketch } from './contributions/save-as-sketch';
Expand Down Expand Up @@ -101,24 +89,12 @@ export class ArduinoFrontendContribution
@inject(BoardsService)
protected readonly boardsService: BoardsService;

@inject(CoreService)
protected readonly coreService: CoreService;

@inject(BoardsServiceProvider)
protected readonly boardsServiceClientImpl: BoardsServiceProvider;

@inject(SelectionService)
protected readonly selectionService: SelectionService;

@inject(EditorManager)
protected readonly editorManager: EditorManager;

@inject(ContextMenuRenderer)
protected readonly contextMenuRenderer: ContextMenuRenderer;

@inject(FileDialogService)
protected readonly fileDialogService: FileDialogService;

@inject(FileService)
protected readonly fileService: FileService;

Expand All @@ -128,21 +104,12 @@ export class ArduinoFrontendContribution
@inject(BoardsConfigDialog)
protected readonly boardsConfigDialog: BoardsConfigDialog;

@inject(MenuModelRegistry)
protected readonly menuRegistry: MenuModelRegistry;

@inject(CommandRegistry)
protected readonly commandRegistry: CommandRegistry;

@inject(StatusBar)
protected readonly statusBar: StatusBar;

@inject(WorkspaceService)
protected readonly workspaceService: WorkspaceService;

@inject(MonitorConnection)
protected readonly monitorConnection: MonitorConnection;

@inject(FileNavigatorContribution)
protected readonly fileNavigatorContributions: FileNavigatorContribution;

Expand All @@ -167,40 +134,21 @@ export class ArduinoFrontendContribution
@inject(EditorMode)
protected readonly editorMode: EditorMode;

@inject(ArduinoDaemon)
protected readonly daemon: ArduinoDaemon;

@inject(OpenerService)
protected readonly openerService: OpenerService;

@inject(ConfigService)
protected readonly configService: ConfigService;

@inject(BoardsDataStore)
protected readonly boardsDataStore: BoardsDataStore;

@inject(MainMenuManager)
protected readonly mainMenuManager: MainMenuManager;

@inject(FileSystemExt)
protected readonly fileSystemExt: FileSystemExt;

@inject(HostedPluginSupport)
protected hostedPluginSupport: HostedPluginSupport;

@inject(ExecutableService)
protected executableService: ExecutableService;

@inject(ResponseService)
protected readonly responseService: ResponseService;

@inject(ArduinoPreferences)
protected readonly arduinoPreferences: ArduinoPreferences;

@inject(SketchesServiceClientImpl)
protected readonly sketchServiceClient: SketchesServiceClientImpl;

@inject(FrontendApplicationStateService)
protected readonly appStateService: FrontendApplicationStateService;

@inject(LocalStorageService)
Expand Down
39 changes: 21 additions & 18 deletions arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,20 @@ import { ScmContribution } from './theia/scm/scm-contribution';
import { SearchInWorkspaceFrontendContribution as TheiaSearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution';
import { SearchInWorkspaceFrontendContribution } from './theia/search-in-workspace/search-in-workspace-frontend-contribution';
import { LibraryListWidgetFrontendContribution } from './library/library-widget-frontend-contribution';
import { MonitorServiceClientImpl } from './monitor/monitor-service-client-impl';
import { SerialServiceClientImpl } from './serial/serial-service-client-impl';
import {
MonitorServicePath,
MonitorService,
MonitorServiceClient,
} from '../common/protocol/monitor-service';
SerialServicePath,
SerialService,
SerialServiceClient,
} from '../common/protocol/serial-service';
import {
ConfigService,
ConfigServicePath,
} from '../common/protocol/config-service';
import { MonitorWidget } from './monitor/monitor-widget';
import { MonitorViewContribution } from './monitor/monitor-view-contribution';
import { MonitorConnection } from './monitor/monitor-connection';
import { MonitorModel } from './monitor/monitor-model';
import { MonitorWidget } from './serial/monitor/monitor-widget';
import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution';
import { SerialConnectionManager } from './serial/serial-connection-manager';
import { SerialModel } from './serial/serial-model';
import { TabBarDecoratorService as TheiaTabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator';
import { TabBarDecoratorService } from './theia/core/tab-bar-decorator';
import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser';
Expand Down Expand Up @@ -253,6 +253,7 @@ import {
UploadCertificateDialogProps,
UploadCertificateDialogWidget,
} from './dialogs/certificate-uploader/certificate-uploader-dialog';
import { PlotterFrontendContribution } from './serial/plotter/plotter-frontend-contribution';
import { nls } from '@theia/core/lib/browser/nls';

const ElementQueries = require('css-element-queries/src/ElementQueries');
Expand Down Expand Up @@ -386,27 +387,28 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
.inSingletonScope();

// Serial monitor
bind(MonitorModel).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(MonitorModel);
bind(SerialModel).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(SerialModel);
bind(MonitorWidget).toSelf();
bindViewContribution(bind, MonitorViewContribution);
bind(TabBarToolbarContribution).toService(MonitorViewContribution);
bind(WidgetFactory).toDynamicValue((context) => ({
id: MonitorWidget.ID,
createWidget: () => context.container.get(MonitorWidget),
}));
// Frontend binding for the serial monitor service
bind(MonitorService)
// Frontend binding for the serial service
bind(SerialService)
.toDynamicValue((context) => {
const connection = context.container.get(WebSocketConnectionProvider);
const client =
context.container.get<MonitorServiceClient>(MonitorServiceClient);
return connection.createProxy(MonitorServicePath, client);
context.container.get<SerialServiceClient>(SerialServiceClient);
return connection.createProxy(SerialServicePath, client);
})
.inSingletonScope();
bind(MonitorConnection).toSelf().inSingletonScope();
// Serial monitor service client to receive and delegate notifications from the backend.
bind(MonitorServiceClient).to(MonitorServiceClientImpl).inSingletonScope();
bind(SerialConnectionManager).toSelf().inSingletonScope();

// Serial service client to receive and delegate notifications from the backend.
bind(SerialServiceClient).to(SerialServiceClientImpl).inSingletonScope();

bind(WorkspaceService).toSelf().inSingletonScope();
rebind(TheiaWorkspaceService).toService(WorkspaceService);
Expand Down Expand Up @@ -597,6 +599,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
Contribution.configure(bind, AddFile);
Contribution.configure(bind, ArchiveSketch);
Contribution.configure(bind, AddZipLibrary);
Contribution.configure(bind, PlotterFrontendContribution);

bind(ResponseServiceImpl)
.toSelf()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
* This even also fires, when the boards package was not available for the currently selected board,
* and the user installs the board package. Note: installing a board package will set the `fqbn` of the
* currently selected board.\
* This even also emitted when the board package for the currently selected board was uninstalled.
* This event is also emitted when the board package for the currently selected board was uninstalled.
*/
readonly onBoardsConfigChanged = this.onBoardsConfigChangedEmitter.event;
readonly onAvailableBoardsChanged =
Expand Down
24 changes: 17 additions & 7 deletions arduino-ide-extension/src/browser/contributions/board-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ PID: ${PID}`;
// The board specific items, and the rest, have order with `z`. We needed something between `0` and `z` with natural-order.
this.menuModelRegistry.registerSubmenu(
boardsSubmenuPath,
nls.localize('arduino/board/board', 'Board{0}', !!boardsSubmenuLabel ? `: "${boardsSubmenuLabel}"` : ''),
nls.localize(
'arduino/board/board',
'Board{0}',
!!boardsSubmenuLabel ? `: "${boardsSubmenuLabel}"` : ''
),
{ order: '100' }
);
this.toDisposeBeforeMenuRebuild.push(
Expand All @@ -155,7 +159,11 @@ PID: ${PID}`;
const portsSubmenuLabel = config.selectedPort?.address;
this.menuModelRegistry.registerSubmenu(
portsSubmenuPath,
nls.localize('arduino/board/port', 'Port{0}', portsSubmenuLabel ? `: "${portsSubmenuLabel}"` : ''),
nls.localize(
'arduino/board/port',
'Port{0}',
portsSubmenuLabel ? `: "${portsSubmenuLabel}"` : ''
),
{ order: '101' }
);
this.toDisposeBeforeMenuRebuild.push(
Expand Down Expand Up @@ -193,9 +201,10 @@ PID: ${PID}`;

const packageLabel =
packageName +
`${manuallyInstalled
? nls.localize('arduino/board/inSketchbook', ' (in Sketchbook)')
: ''
`${
manuallyInstalled
? nls.localize('arduino/board/inSketchbook', ' (in Sketchbook)')
: ''
}`;
// Platform submenu
const platformMenuPath = [...boardsPackagesGroup, packageId];
Expand Down Expand Up @@ -268,8 +277,9 @@ PID: ${PID}`;
});
}
for (const { name, fqbn } of boards) {
const id = `arduino-select-port--${address}${fqbn ? `--${fqbn}` : ''
}`;
const id = `arduino-select-port--${address}${
fqbn ? `--${fqbn}` : ''
}`;
const command = { id };
const handler = {
execute: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
import { CoreService } from '../../common/protocol';
import { ArduinoMenus } from '../menu/arduino-menus';
import { BoardsDataStore } from '../boards/boards-data-store';
import { MonitorConnection } from '../monitor/monitor-connection';
import { SerialConnectionManager } from '../serial/serial-connection-manager';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import {
SketchContribution,
Expand All @@ -18,8 +18,8 @@ export class BurnBootloader extends SketchContribution {
@inject(CoreService)
protected readonly coreService: CoreService;

@inject(MonitorConnection)
protected readonly monitorConnection: MonitorConnection;
@inject(SerialConnectionManager)
protected readonly serialConnection: SerialConnectionManager;

@inject(BoardsDataStore)
protected readonly boardsDataStore: BoardsDataStore;
Expand Down Expand Up @@ -48,10 +48,7 @@ export class BurnBootloader extends SketchContribution {
}

async burnBootloader(): Promise<void> {
const monitorConfig = this.monitorConnection.monitorConfig;
if (monitorConfig) {
await this.monitorConnection.disconnect();
}
await this.serialConnection.disconnect();
try {
const { boardsConfig } = this.boardsServiceClientImpl;
const port = boardsConfig.selectedPort;
Expand Down Expand Up @@ -84,8 +81,8 @@ export class BurnBootloader extends SketchContribution {
} catch (e) {
this.messageService.error(e.toString());
} finally {
if (monitorConfig) {
await this.monitorConnection.connect(monitorConfig);
if (this.serialConnection.isSerialOpen()) {
await this.serialConnection.connect();
}
}
}
Expand Down
Loading