Can list HW, build for it and upload

This commit is contained in:
Christian Weichel 2019-05-07 12:43:07 +02:00
parent 95ed43c9c4
commit b2d16ff9a4
7 changed files with 119 additions and 38 deletions

View File

@ -75,10 +75,11 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
registry.registerCommand(ArduinoCommands.UPLOAD, {
isVisible: widget => this.isArduinoEditor(widget),
isEnabled: widget => this.isArduinoEditor(widget),
execute: widget => {
execute: async widget => {
const uri = this.toUri(widget);
if (uri) {
this.messageService.info(`Uploading ${uri.toString()}`);
const result = await this.coreService.upload({ uri: uri.toString() });
console.log('upload result', result);
}
}
});

View File

@ -4,40 +4,60 @@ import * as React from 'react';
import { BoardsService, AttachedBoard } from '../../common/protocol/boards-service';
export class ConnectedBoards extends React.Component<ConnectedBoards.Props, ConnectedBoards.State> {
static TOOLBAR_ID: 'connected-boards-toolbar';
constructor(props: ConnectedBoards.Props) {
super(props);
this.state = { boardsLoading: false };
}
render(): React.ReactNode {
let label = "no board available";
if (this.state.boardsLoading) {
label = "Loading ...";
} else if (!!this.state.current) {
label = this.state.current.name;
}
let content = [];
if (!!this.state.boards) {
content = this.state.boards.map((b, i) => <option value={i} key={i}>{b.name}</option>);
} else {
content = [ <option key="loading" value="0">{label}</option> ];
}
return <div className={ConnectedBoards.Styles.CONNECTED_BOARDS_CLASS}>
{this.select(this.state ? this.state.boards : undefined, this.state ? this.state.current : undefined)}
<select disabled={!this.state.boards} onChange={this.onBoardSelect.bind(this)}>
{ content }
</select>
</div>;
}
componentDidMount(): void {
this.props.boardsService.attachedBoards().then(result => {
const { boards } = result;
this.setState({ boards });
});
this.reloadBoards();
}
private select(boards: AttachedBoard[] | undefined, current: AttachedBoard | undefined): React.ReactNode {
// Initial pessimistic.
const options = [<option>Loading...</option>];
protected async reloadBoards() {
this.setState({ boardsLoading: true, boards: undefined, current: undefined });
const { boards } = await this.props.boardsService.getAttachedBoards()
this.setState({ boards, boardsLoading: false });
if (boards) {
options.length = 0;
options.push(...boards.map(b => b.name).map(name => <option value={name} key={name}>{name}</option>));
this.selectBoard(boards[0]);
}
const onChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const current = (boards || []).find(board => board.name === event.target.value);
this.setState({ current });
};
return <select
onChange={onChange}
value={current ? current.name : 'Loading...'}
name={current ? current.name : 'Loading...'}
>
{options}
</select>
}
protected async onBoardSelect(evt: React.ChangeEvent<HTMLSelectElement>) {
const selectedBoard = (this.state.boards || [])[parseInt(evt.target.value, 10)];
if (!selectedBoard) {
return;
}
this.selectBoard(selectedBoard);
}
protected async selectBoard(board: AttachedBoard) {
await this.props.boardsService.selectBoard(board);
this.setState({ current: board });
}
}
@ -49,6 +69,7 @@ export namespace ConnectedBoards {
}
export interface State {
boardsLoading: boolean;
boards?: AttachedBoard[];
current?: AttachedBoard;
}

View File

@ -3,7 +3,10 @@ import { ArduinoComponent } from "./arduino-component";
export const BoardsServicePath = '/services/boards-service';
export const BoardsService = Symbol('BoardsService');
export interface BoardsService {
attachedBoards(): Promise<{ boards: AttachedBoard[] }>;
getAttachedBoards(): Promise<{ boards: AttachedBoard[] }>;
selectBoard(board: AttachedBoard): Promise<void>;
getSelectBoard(): Promise<AttachedBoard | undefined>;
search(options: { query?: string }): Promise<{ items: Board[] }>;
install(board: Board): Promise<void>;
}

View File

@ -2,10 +2,17 @@ export const CoreServicePath = '/services/core-service';
export const CoreService = Symbol('CoreService');
export interface CoreService {
compile(options: CoreService.Compile.Options): Promise<void>;
upload(): Promise<void>;
upload(options: CoreService.Upload.Options): Promise<void>;
}
export namespace CoreService {
export namespace Upload {
export interface Options {
readonly uri: string;
}
}
export namespace Compile {
export interface Options {
readonly uri: string;

View File

@ -33,13 +33,13 @@ export class ArduinoDaemon implements BackendApplicationContribution {
});
if (daemon.stdout) {
daemon.stdout.on('data', data => {
this.toolOutputService.publishNewOutput("daeomn", data.toString());
this.toolOutputService.publishNewOutput("daemon", data.toString());
DaemonLog.log(this.logger, data.toString());
});
}
if (daemon.stderr) {
daemon.stderr.on('data', data => {
this.toolOutputService.publishNewOutput("daeomn error", data.toString());
this.toolOutputService.publishNewOutput("daemon error", data.toString());
DaemonLog.log(this.logger, data.toString());
});
}

View File

@ -10,7 +10,9 @@ export class BoardsServiceImpl implements BoardsService {
@inject(CoreClientProvider)
protected readonly coreClientProvider: CoreClientProvider;
public async attachedBoards(): Promise<{ boards: AttachedBoard[] }> {
protected selectedBoard: AttachedBoard | undefined;
public async getAttachedBoards(): Promise<{ boards: AttachedBoard[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const req = new BoardListReq();
@ -36,6 +38,14 @@ export class BoardsServiceImpl implements BoardsService {
return { boards: serialBoards.concat(networkBoards) };
}
async selectBoard(board: AttachedBoard): Promise<void> {
this.selectedBoard = board;
}
async getSelectBoard(): Promise<AttachedBoard | undefined> {
return this.selectedBoard;
}
async search(options: { query?: string }): Promise<{ items: Board[] }> {
const { client, instance } = await this.coreClientProvider.getClient();

View File

@ -2,10 +2,11 @@ import { inject, injectable } from 'inversify';
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
import { CoreService } from '../common/protocol/core-service';
import { CompileReq, CompileResp } from './cli-protocol/compile_pb';
import { BoardsService } from '../common/protocol/boards-service';
import { BoardsService, AttachedSerialBoard } from '../common/protocol/boards-service';
import { CoreClientProvider } from './core-client-provider';
import * as path from 'path';
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
import { UploadReq, UploadResp } from './cli-protocol/upload_pb';
@injectable()
export class CoreServiceImpl implements CoreService {
@ -32,16 +33,19 @@ export class CoreServiceImpl implements CoreService {
const sketchpath = path.dirname(sketchFilePath);
const { client, instance } = await this.coreClientProvider.getClient(uri);
// const boards = await this.boardsService.connectedBoards();
// if (!boards.current) {
// throw new Error(`No selected board. The connected boards were: ${boards.boards}.`);
// }
// https://github.com/cmaglie/arduino-cli/blob/bd5e78701e7546787649d3cca6b21c5d22d0e438/cli/compile/compile.go#L78-L88
const currentBoard = await this.boardsService.getSelectBoard();
if (!currentBoard) {
throw new Error("no board selected");
}
if (!currentBoard.fqbn) {
throw new Error(`selected board (${currentBoard.name}) has no FQBN`);
}
const compilerReq = new CompileReq();
compilerReq.setInstance(instance);
compilerReq.setSketchpath(sketchpath);
compilerReq.setFqbn('arduino:avr:uno'/*boards.current.name*/);
compilerReq.setFqbn(currentBoard.fqbn!);
compilerReq.setPreprocess(false);
compilerReq.setVerbose(true);
compilerReq.setQuiet(false);
@ -57,8 +61,43 @@ export class CoreServiceImpl implements CoreService {
});
}
upload(): Promise<void> {
throw new Error("Method not implemented.");
async upload(options: CoreService.Upload.Options): Promise<void> {
console.log('upload', options);
const { uri } = options;
const sketchFilePath = await this.fileSystem.getFsPath(options.uri);
if (!sketchFilePath) {
throw new Error(`Cannot resolve filesystem path for URI: ${uri}.`);
}
const sketchpath = path.dirname(sketchFilePath);
const currentBoard = await this.boardsService.getSelectBoard();
if (!currentBoard) {
throw new Error("no board selected");
}
if (!currentBoard.fqbn) {
throw new Error(`selected board (${currentBoard.name}) has no FQBN`);
}
const { client, instance } = await this.coreClientProvider.getClient(uri);
const req = new UploadReq();
req.setInstance(instance);
req.setSketchPath(sketchpath);
req.setFqbn(currentBoard.fqbn);
if (AttachedSerialBoard.is(currentBoard)) {
req.setPort(currentBoard.port);
} else {
throw new Error("can only upload to serial boards");
}
const result = client.upload(req);
return new Promise<void>((resolve, reject) => {
result.on('data', (cr: UploadResp) => {
this.toolOutputService.publishNewOutput("upload", new Buffer(cr.getOutStream_asU8()).toString());
this.toolOutputService.publishNewOutput("upload error", new Buffer(cr.getErrStream_asU8()).toString());
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
}
}