mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-01 16:36:33 +00:00
Can list HW, build for it and upload
This commit is contained in:
parent
95ed43c9c4
commit
b2d16ff9a4
@ -75,10 +75,11 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
|
|||||||
registry.registerCommand(ArduinoCommands.UPLOAD, {
|
registry.registerCommand(ArduinoCommands.UPLOAD, {
|
||||||
isVisible: widget => this.isArduinoEditor(widget),
|
isVisible: widget => this.isArduinoEditor(widget),
|
||||||
isEnabled: widget => this.isArduinoEditor(widget),
|
isEnabled: widget => this.isArduinoEditor(widget),
|
||||||
execute: widget => {
|
execute: async widget => {
|
||||||
const uri = this.toUri(widget);
|
const uri = this.toUri(widget);
|
||||||
if (uri) {
|
if (uri) {
|
||||||
this.messageService.info(`Uploading ${uri.toString()}`);
|
const result = await this.coreService.upload({ uri: uri.toString() });
|
||||||
|
console.log('upload result', result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -4,40 +4,60 @@ import * as React from 'react';
|
|||||||
import { BoardsService, AttachedBoard } from '../../common/protocol/boards-service';
|
import { BoardsService, AttachedBoard } from '../../common/protocol/boards-service';
|
||||||
|
|
||||||
export class ConnectedBoards extends React.Component<ConnectedBoards.Props, ConnectedBoards.State> {
|
export class ConnectedBoards extends React.Component<ConnectedBoards.Props, ConnectedBoards.State> {
|
||||||
|
|
||||||
static TOOLBAR_ID: 'connected-boards-toolbar';
|
static TOOLBAR_ID: 'connected-boards-toolbar';
|
||||||
|
|
||||||
|
constructor(props: ConnectedBoards.Props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { boardsLoading: false };
|
||||||
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
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}>
|
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>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
this.props.boardsService.attachedBoards().then(result => {
|
this.reloadBoards();
|
||||||
const { boards } = result;
|
|
||||||
this.setState({ boards });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private select(boards: AttachedBoard[] | undefined, current: AttachedBoard | undefined): React.ReactNode {
|
protected async reloadBoards() {
|
||||||
// Initial pessimistic.
|
this.setState({ boardsLoading: true, boards: undefined, current: undefined });
|
||||||
const options = [<option>Loading...</option>];
|
const { boards } = await this.props.boardsService.getAttachedBoards()
|
||||||
|
this.setState({ boards, boardsLoading: false });
|
||||||
|
|
||||||
if (boards) {
|
if (boards) {
|
||||||
options.length = 0;
|
this.selectBoard(boards[0]);
|
||||||
options.push(...boards.map(b => b.name).map(name => <option value={name} key={name}>{name}</option>));
|
|
||||||
}
|
}
|
||||||
const onChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
}
|
||||||
const current = (boards || []).find(board => board.name === event.target.value);
|
|
||||||
this.setState({ current });
|
protected async onBoardSelect(evt: React.ChangeEvent<HTMLSelectElement>) {
|
||||||
};
|
const selectedBoard = (this.state.boards || [])[parseInt(evt.target.value, 10)];
|
||||||
return <select
|
if (!selectedBoard) {
|
||||||
onChange={onChange}
|
return;
|
||||||
value={current ? current.name : 'Loading...'}
|
}
|
||||||
name={current ? current.name : 'Loading...'}
|
this.selectBoard(selectedBoard);
|
||||||
>
|
}
|
||||||
{options}
|
|
||||||
</select>
|
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 {
|
export interface State {
|
||||||
|
boardsLoading: boolean;
|
||||||
boards?: AttachedBoard[];
|
boards?: AttachedBoard[];
|
||||||
current?: AttachedBoard;
|
current?: AttachedBoard;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ import { ArduinoComponent } from "./arduino-component";
|
|||||||
export const BoardsServicePath = '/services/boards-service';
|
export const BoardsServicePath = '/services/boards-service';
|
||||||
export const BoardsService = Symbol('BoardsService');
|
export const BoardsService = Symbol('BoardsService');
|
||||||
export interface 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[] }>;
|
search(options: { query?: string }): Promise<{ items: Board[] }>;
|
||||||
install(board: Board): Promise<void>;
|
install(board: Board): Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,17 @@ export const CoreServicePath = '/services/core-service';
|
|||||||
export const CoreService = Symbol('CoreService');
|
export const CoreService = Symbol('CoreService');
|
||||||
export interface CoreService {
|
export interface CoreService {
|
||||||
compile(options: CoreService.Compile.Options): Promise<void>;
|
compile(options: CoreService.Compile.Options): Promise<void>;
|
||||||
upload(): Promise<void>;
|
upload(options: CoreService.Upload.Options): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace CoreService {
|
export namespace CoreService {
|
||||||
|
|
||||||
|
export namespace Upload {
|
||||||
|
export interface Options {
|
||||||
|
readonly uri: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export namespace Compile {
|
export namespace Compile {
|
||||||
export interface Options {
|
export interface Options {
|
||||||
readonly uri: string;
|
readonly uri: string;
|
||||||
|
@ -33,13 +33,13 @@ export class ArduinoDaemon implements BackendApplicationContribution {
|
|||||||
});
|
});
|
||||||
if (daemon.stdout) {
|
if (daemon.stdout) {
|
||||||
daemon.stdout.on('data', data => {
|
daemon.stdout.on('data', data => {
|
||||||
this.toolOutputService.publishNewOutput("daeomn", data.toString());
|
this.toolOutputService.publishNewOutput("daemon", data.toString());
|
||||||
DaemonLog.log(this.logger, data.toString());
|
DaemonLog.log(this.logger, data.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (daemon.stderr) {
|
if (daemon.stderr) {
|
||||||
daemon.stderr.on('data', data => {
|
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());
|
DaemonLog.log(this.logger, data.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@ export class BoardsServiceImpl implements BoardsService {
|
|||||||
@inject(CoreClientProvider)
|
@inject(CoreClientProvider)
|
||||||
protected readonly coreClientProvider: 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 { client, instance } = await this.coreClientProvider.getClient();
|
||||||
|
|
||||||
const req = new BoardListReq();
|
const req = new BoardListReq();
|
||||||
@ -36,6 +38,14 @@ export class BoardsServiceImpl implements BoardsService {
|
|||||||
return { boards: serialBoards.concat(networkBoards) };
|
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[] }> {
|
async search(options: { query?: string }): Promise<{ items: Board[] }> {
|
||||||
const { client, instance } = await this.coreClientProvider.getClient();
|
const { client, instance } = await this.coreClientProvider.getClient();
|
||||||
|
|
||||||
|
@ -2,10 +2,11 @@ import { inject, injectable } from 'inversify';
|
|||||||
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
|
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
|
||||||
import { CoreService } from '../common/protocol/core-service';
|
import { CoreService } from '../common/protocol/core-service';
|
||||||
import { CompileReq, CompileResp } from './cli-protocol/compile_pb';
|
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 { CoreClientProvider } from './core-client-provider';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||||
|
import { UploadReq, UploadResp } from './cli-protocol/upload_pb';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class CoreServiceImpl implements CoreService {
|
export class CoreServiceImpl implements CoreService {
|
||||||
@ -32,16 +33,19 @@ export class CoreServiceImpl implements CoreService {
|
|||||||
const sketchpath = path.dirname(sketchFilePath);
|
const sketchpath = path.dirname(sketchFilePath);
|
||||||
|
|
||||||
const { client, instance } = await this.coreClientProvider.getClient(uri);
|
const { client, instance } = await this.coreClientProvider.getClient(uri);
|
||||||
// const boards = await this.boardsService.connectedBoards();
|
|
||||||
// if (!boards.current) {
|
const currentBoard = await this.boardsService.getSelectBoard();
|
||||||
// throw new Error(`No selected board. The connected boards were: ${boards.boards}.`);
|
if (!currentBoard) {
|
||||||
// }
|
throw new Error("no board selected");
|
||||||
// https://github.com/cmaglie/arduino-cli/blob/bd5e78701e7546787649d3cca6b21c5d22d0e438/cli/compile/compile.go#L78-L88
|
}
|
||||||
|
if (!currentBoard.fqbn) {
|
||||||
|
throw new Error(`selected board (${currentBoard.name}) has no FQBN`);
|
||||||
|
}
|
||||||
|
|
||||||
const compilerReq = new CompileReq();
|
const compilerReq = new CompileReq();
|
||||||
compilerReq.setInstance(instance);
|
compilerReq.setInstance(instance);
|
||||||
compilerReq.setSketchpath(sketchpath);
|
compilerReq.setSketchpath(sketchpath);
|
||||||
compilerReq.setFqbn('arduino:avr:uno'/*boards.current.name*/);
|
compilerReq.setFqbn(currentBoard.fqbn!);
|
||||||
compilerReq.setPreprocess(false);
|
compilerReq.setPreprocess(false);
|
||||||
compilerReq.setVerbose(true);
|
compilerReq.setVerbose(true);
|
||||||
compilerReq.setQuiet(false);
|
compilerReq.setQuiet(false);
|
||||||
@ -57,8 +61,43 @@ export class CoreServiceImpl implements CoreService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
upload(): Promise<void> {
|
async upload(options: CoreService.Upload.Options): Promise<void> {
|
||||||
throw new Error("Method not implemented.");
|
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());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user