Implemented non-attached boards

This commit is contained in:
Christian Weichel 2019-05-08 11:25:52 +02:00
parent d787de3ed9
commit be20365a6b
14 changed files with 472 additions and 110 deletions

View File

@ -12,6 +12,7 @@ import { ConnectedBoards } from './components/connected-boards';
import { CoreService } from '../common/protocol/core-service';
import { WorkspaceServiceExt } from './workspace-service-ext';
import { ToolOutputServiceClient } from '../common/protocol/tool-output-service';
import { ConfirmDialog } from '@theia/core/lib/browser';
@injectable()
@ -65,6 +66,10 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
isVisible: widget => this.isArduinoEditor(widget),
isEnabled: widget => this.isArduinoEditor(widget),
execute: async widget => {
if (widget instanceof EditorWidget) {
await widget.saveable.save();
}
const uri = this.toUri(widget);
if (uri) {
const result = await this.coreService.compile({ uri: uri.toString() });
@ -76,10 +81,19 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
isVisible: widget => this.isArduinoEditor(widget),
isEnabled: widget => this.isArduinoEditor(widget),
execute: async widget => {
if (widget instanceof EditorWidget) {
await widget.saveable.save();
}
const uri = this.toUri(widget);
if (uri) {
const result = await this.coreService.upload({ uri: uri.toString() });
console.log('upload result', result);
if (!uri) {
return;
}
try {
await this.coreService.upload({ uri: uri.toString() });
} catch (e) {
new ConfirmDialog({ title: "Error during upload", msg: e.toString(), ok: "Ok" }).open();
}
}
});

View File

@ -1,7 +1,6 @@
import * as React from 'react';
// TODO: make this `async`.
// import { Async } from 'react-select/lib/Async';
import { BoardsService, AttachedBoard } from '../../common/protocol/boards-service';
import { BoardsService, Board } from '../../common/protocol/boards-service';
import { SelectBoardDialog } from './select-board-dialog';
export class ConnectedBoards extends React.Component<ConnectedBoards.Props, ConnectedBoards.State> {
static TOOLBAR_ID: 'connected-boards-toolbar';
@ -12,23 +11,28 @@ export class ConnectedBoards extends React.Component<ConnectedBoards.Props, Conn
}
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) {
if (!!this.state.boards && this.state.boards.length > 0) {
content = this.state.boards.map((b, i) => <option value={i} key={i}>{b.name}</option>);
} else {
let label;
if (this.state.boardsLoading) {
label = "Loading ...";
} else {
label = "No board attached";
}
content = [ <option key="loading" value="0">{label}</option> ];
}
return <div className={ConnectedBoards.Styles.CONNECTED_BOARDS_CLASS}>
<select disabled={!this.state.boards} onChange={this.onBoardSelect.bind(this)}>
<select disabled={!this.state.boards} onChange={this.onBoardSelect.bind(this)} value={this.state.selection}>
<optgroup label="Attached boards">
{ content }
</optgroup>
<optgroup label="_________">
{ !!this.state.otherBoard && <option value="selected-other" key="selected-other">{this.state.otherBoard.name} (not attached)</option> }
<option value="select-other" key="select-other">Select other Board</option>
</optgroup>
</select>
</div>;
}
@ -38,26 +42,38 @@ export class ConnectedBoards extends React.Component<ConnectedBoards.Props, Conn
}
protected async reloadBoards() {
this.setState({ boardsLoading: true, boards: undefined, current: undefined });
this.setState({ boardsLoading: true, boards: undefined, selection: undefined });
const { boards } = await this.props.boardsService.getAttachedBoards()
this.setState({ boards, boardsLoading: false });
if (boards) {
this.selectBoard(boards[0]);
this.setState({ selection: "0" });
await this.props.boardsService.selectBoard(boards[0]);
}
}
protected async onBoardSelect(evt: React.ChangeEvent<HTMLSelectElement>) {
const selectedBoard = (this.state.boards || [])[parseInt(evt.target.value, 10)];
const selection = evt.target.value;
if (selection === "select-other" || selection === "selected-other") {
let selectedBoard = this.state.otherBoard;
if (selection === "select-other" || !selectedBoard) {
selectedBoard = await new SelectBoardDialog(this.props.boardsService).open();
}
if (!selectedBoard) {
return;
}
this.selectBoard(selectedBoard);
await this.props.boardsService.selectBoard(selectedBoard);
this.setState({otherBoard: selectedBoard, selection: "selected-other"});
return;
}
protected async selectBoard(board: AttachedBoard) {
await this.props.boardsService.selectBoard(board);
this.setState({ current: board });
const selectedBoard = (this.state.boards || [])[parseInt(selection, 10)];
if (!selectedBoard) {
return;
}
await this.props.boardsService.selectBoard(selectedBoard);
this.setState({selection});
}
}
@ -70,8 +86,9 @@ export namespace ConnectedBoards {
export interface State {
boardsLoading: boolean;
boards?: AttachedBoard[];
current?: AttachedBoard;
boards?: Board[];
otherBoard?: Board;
selection?: string;
}
export namespace Styles {

View File

@ -0,0 +1,103 @@
import { AbstractDialog, ReactRenderer, Message } from "@theia/core/lib/browser";
import { Board, BoardsService } from "../../common/protocol/boards-service";
import * as React from 'react';
interface BoardGroup {
name: string
boards: Board[]
}
class DialogContentRenderer extends ReactRenderer {
protected availableBoards: BoardGroup[] = [ ];
protected searchTerm = "";
constructor(protected readonly boardsService: BoardsService, protected readonly onSelect: (b: Board) => void) {
super();
this.search();
}
doRender(): React.ReactNode {
return <React.Fragment>
<input type="text" placeholder="Search ..." onChange={this.onSearchChange.bind(this)} value={this.searchTerm} />
<select size={10} onChange={this.onChange.bind(this)}>
{ this.availableBoards.map((b, i) => (
<optgroup key={"pkg" + i} label={b.name}>
{ b.boards.map((brd, j) => <option key={j} value={`${i}::${j}`}>{brd.name}</option>) }
</optgroup>
)) }
</select>
</React.Fragment>;
}
protected onChange(evt: React.ChangeEvent<HTMLSelectElement>) {
const [grp, brd] = evt.target.value.split("::");
const grpidx = parseInt(grp, 10);
const brdidx = parseInt(brd, 10);
const board = this.availableBoards[grpidx].boards[brdidx];
this.onSelect(board);
}
protected onSearchChange(evt: React.ChangeEvent<HTMLInputElement>) {
this.searchTerm = evt.target.value;
this.search();
}
protected async search() {
const { items } = await this.boardsService.search({query: this.searchTerm });
this.availableBoards = items.map(pkg => {
const result: BoardGroup = {
name: pkg.name,
boards: pkg.boards.filter(b => b.name.toLocaleLowerCase().includes(this.searchTerm.toLocaleLowerCase()))
}
return result;
}).filter(grp => !!grp.boards).sort((a, b) => {
if (a.name < b.name) return -1;
if (a.name === b.name) return 0;
return 1;
});
this.render();
}
}
export class SelectBoardDialog extends AbstractDialog<Board> {
protected result: Board;
protected readonly contentRenderer: DialogContentRenderer;
constructor(boardsService: BoardsService) {
super({ title: 'Select other board' });
this.contentNode.classList.add(SelectBoardDialog.Styles.DIALOG_CLASS);
this.contentRenderer = new DialogContentRenderer(boardsService, b => this.result = b);
this.contentRenderer.render();
this.contentNode.appendChild(this.contentRenderer.host);
this.appendCloseButton();
this.appendAcceptButton("Select");
}
get value(): Board {
return this.result;
}
onUpdateRequest(msg: Message) {
super.onUpdateRequest(msg);
this.contentRenderer.render();
}
dispose() {
this.contentRenderer.dispose();
super.dispose();
}
}
export namespace SelectBoardDialog {
export namespace Styles {
export const DIALOG_CLASS = "select-board-dialog";
export const SELECTOR_CLASS = "selector";
}
}

View File

@ -1 +1,2 @@
@import './list-widget.css';
@import './select-board-dialog.css';

View File

@ -0,0 +1,13 @@
.select-board-dialog {
width: 600px;
}
.select-board-dialog input {
width: calc(100% - 8px);
margin-bottom: 5px;
}
.select-board-dialog select {
width: 100%;
}

View File

@ -3,24 +3,25 @@ import { ArduinoComponent } from "./arduino-component";
export const BoardsServicePath = '/services/boards-service';
export const BoardsService = Symbol('BoardsService');
export interface BoardsService {
getAttachedBoards(): Promise<{ boards: AttachedBoard[] }>;
selectBoard(board: AttachedBoard): Promise<void>;
getSelectBoard(): Promise<AttachedBoard | undefined>;
getAttachedBoards(): Promise<{ boards: Board[] }>;
selectBoard(board: Board): Promise<void>;
getSelectBoard(): Promise<Board | undefined>;
search(options: { query?: string }): Promise<{ items: Board[] }>;
install(board: Board): Promise<void>;
search(options: { query?: string }): Promise<{ items: BoardPackage[] }>;
install(item: BoardPackage): Promise<void>;
}
export interface Board extends ArduinoComponent {
export interface BoardPackage extends ArduinoComponent {
id: string;
boards: Board[];
}
export interface AttachedBoard {
export interface Board {
name: string
fqbn?: string
}
export interface AttachedSerialBoard extends AttachedBoard {
export interface AttachedSerialBoard extends Board {
port: string;
serialNumber: string;
productID: string;
@ -28,7 +29,7 @@ export interface AttachedSerialBoard extends AttachedBoard {
}
export namespace AttachedSerialBoard {
export function is(b: AttachedBoard): b is AttachedSerialBoard {
export function is(b: Board): b is AttachedSerialBoard {
return 'port' in b
&& 'serialNumber' in b
&& 'productID' in b
@ -36,14 +37,14 @@ export namespace AttachedSerialBoard {
}
}
export interface AttachedNetworkBoard extends AttachedBoard {
export interface AttachedNetworkBoard extends Board {
info: string;
address: string;
port: number;
}
export namespace AttachedNetworkBoard {
export function is(b: AttachedBoard): b is AttachedNetworkBoard {
export function is(b: Board): b is AttachedNetworkBoard {
return 'name' in b
&& 'info' in b
&& 'address' in b

View File

@ -1,5 +1,5 @@
import { injectable, inject } from 'inversify';
import { BoardsService, Board, AttachedBoard, AttachedSerialBoard, AttachedNetworkBoard } from '../common/protocol/boards-service';
import { BoardsService, AttachedSerialBoard, AttachedNetworkBoard, BoardPackage, Board } from '../common/protocol/boards-service';
import { PlatformSearchReq, PlatformSearchResp, PlatformInstallReq, PlatformInstallResp, PlatformListReq, PlatformListResp } from './cli-protocol/core_pb';
import { CoreClientProvider } from './core-client-provider';
import { BoardListReq, BoardListResp } from './cli-protocol/board_pb';
@ -10,16 +10,16 @@ export class BoardsServiceImpl implements BoardsService {
@inject(CoreClientProvider)
protected readonly coreClientProvider: CoreClientProvider;
protected selectedBoard: AttachedBoard | undefined;
protected selectedBoard: Board | undefined;
public async getAttachedBoards(): Promise<{ boards: AttachedBoard[] }> {
public async getAttachedBoards(): Promise<{ boards: Board[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const req = new BoardListReq();
req.setInstance(instance);
const resp = await new Promise<BoardListResp>((resolve, reject) => client.boardList(req, (err, resp) => (!!err ? reject : resolve)(!!err ? err : resp)));
const serialBoards: AttachedBoard[] = resp.getSerialList().map(b => <AttachedSerialBoard>{
const serialBoards: Board[] = resp.getSerialList().map(b => <AttachedSerialBoard>{
name: b.getName() || "unknown",
fqbn: b.getFqbn(),
port: b.getPort(),
@ -27,7 +27,7 @@ export class BoardsServiceImpl implements BoardsService {
productID: b.getProductid(),
vendorID: b.getVendorid()
});
const networkBoards: AttachedBoard[] = resp.getNetworkList().map(b => <AttachedNetworkBoard>{
const networkBoards: Board[] = resp.getNetworkList().map(b => <AttachedNetworkBoard>{
name: b.getName(),
fqbn: b.getFqbn(),
address: b.getAddress(),
@ -38,15 +38,15 @@ export class BoardsServiceImpl implements BoardsService {
return { boards: serialBoards.concat(networkBoards) };
}
async selectBoard(board: AttachedBoard): Promise<void> {
async selectBoard(board: Board): Promise<void> {
this.selectedBoard = board;
}
async getSelectBoard(): Promise<AttachedBoard | undefined> {
async getSelectBoard(): Promise<Board | undefined> {
return this.selectedBoard;
}
async search(options: { query?: string }): Promise<{ items: Board[] }> {
async search(options: { query?: string }): Promise<{ items: BoardPackage[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const installedPlatformsReq = new PlatformListReq();
@ -55,7 +55,6 @@ export class BoardsServiceImpl implements BoardsService {
client.platformList(installedPlatformsReq, (err, resp) => (!!err ? reject : resolve)(!!err ? err : resp))
);
const installedPlatforms = installedPlatformsResp.getInstalledPlatformList();
console.info("Installed platforms", installedPlatforms);
const req = new PlatformSearchReq();
req.setSearchArgs(options.query || "");
@ -69,15 +68,16 @@ export class BoardsServiceImpl implements BoardsService {
installedVersion = matchingPlatform.getInstalled();
}
const result: Board = {
const result: BoardPackage = {
id: item.getId(),
name: item.getName(),
author: item.getAuthor(),
availableVersions: [ item.getVersion() ],
description: item.getParagragh(),
description: item.getBoardsList().map(b => b.getName()).join(", "),
installable: true,
summary: item.getSentence(),
summary: "Boards included in this package:",
installedVersion,
boards: item.getBoardsList().map(b => <Board>{ name: b.getName(), fqbn: b.getFqbn() }),
}
return result;
});
@ -85,18 +85,18 @@ export class BoardsServiceImpl implements BoardsService {
return { items };
}
async install(board: Board): Promise<void> {
async install(pkg: BoardPackage): Promise<void> {
const { client, instance } = await this.coreClientProvider.getClient();
const [ platform, boardName ] = board.id.split(":");
const [ platform, boardName ] = pkg.id.split(":");
const req = new PlatformInstallReq();
req.setInstance(instance);
req.setArchitecture(boardName);
req.setPlatformPackage(platform);
req.setVersion(board.availableVersions[0]);
req.setVersion(pkg.availableVersions[0]);
console.info("Starting board installation", board);
console.info("Starting board installation", pkg);
const resp = client.platformInstall(req);
resp.on('data', (r: PlatformInstallResp) => {
const prog = r.getProgress();
@ -108,7 +108,7 @@ export class BoardsServiceImpl implements BoardsService {
resp.on('end', resolve);
resp.on('error', reject);
});
console.info("Board installation done", board);
console.info("Board installation done", pkg);
}
}

View File

@ -320,11 +320,10 @@ export class SearchOutput extends jspb.Message {
getAuthor(): string;
setAuthor(value: string): void;
getSentence(): string;
setSentence(value: string): void;
getParagragh(): string;
setParagragh(value: string): void;
clearBoardsList(): void;
getBoardsList(): Array<SearchOutputBoard>;
setBoardsList(value: Array<SearchOutputBoard>): void;
addBoards(value?: SearchOutputBoard, index?: number): SearchOutputBoard;
serializeBinary(): Uint8Array;
@ -343,8 +342,32 @@ export namespace SearchOutput {
version: string,
name: string,
author: string,
sentence: string,
paragragh: string,
boardsList: Array<SearchOutputBoard.AsObject>,
}
}
export class SearchOutputBoard extends jspb.Message {
getName(): string;
setName(value: string): void;
getFqbn(): string;
setFqbn(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): SearchOutputBoard.AsObject;
static toObject(includeInstance: boolean, msg: SearchOutputBoard): SearchOutputBoard.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: SearchOutputBoard, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): SearchOutputBoard;
static deserializeBinaryFromReader(message: SearchOutputBoard, reader: jspb.BinaryReader): SearchOutputBoard;
}
export namespace SearchOutputBoard {
export type AsObject = {
name: string,
fqbn: string,
}
}

View File

@ -27,6 +27,7 @@ goog.exportSymbol('proto.arduino.PlatformUninstallResp', null, global);
goog.exportSymbol('proto.arduino.PlatformUpgradeReq', null, global);
goog.exportSymbol('proto.arduino.PlatformUpgradeResp', null, global);
goog.exportSymbol('proto.arduino.SearchOutput', null, global);
goog.exportSymbol('proto.arduino.SearchOutputBoard', null, global);
/**
* Generated by JsPbCodeGenerator.
@ -2050,12 +2051,19 @@ proto.arduino.PlatformSearchResp.prototype.clearSearchOutputList = function() {
* @constructor
*/
proto.arduino.SearchOutput = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
jspb.Message.initialize(this, opt_data, 0, -1, proto.arduino.SearchOutput.repeatedFields_, null);
};
goog.inherits(proto.arduino.SearchOutput, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.arduino.SearchOutput.displayName = 'proto.arduino.SearchOutput';
}
/**
* List of repeated fields within this message type.
* @private {!Array<number>}
* @const
*/
proto.arduino.SearchOutput.repeatedFields_ = [5];
if (jspb.Message.GENERATE_TO_OBJECT) {
@ -2089,8 +2097,8 @@ proto.arduino.SearchOutput.toObject = function(includeInstance, msg) {
version: jspb.Message.getFieldWithDefault(msg, 2, ""),
name: jspb.Message.getFieldWithDefault(msg, 3, ""),
author: jspb.Message.getFieldWithDefault(msg, 4, ""),
sentence: jspb.Message.getFieldWithDefault(msg, 5, ""),
paragragh: jspb.Message.getFieldWithDefault(msg, 6, "")
boardsList: jspb.Message.toObjectList(msg.getBoardsList(),
proto.arduino.SearchOutputBoard.toObject, includeInstance)
};
if (includeInstance) {
@ -2144,12 +2152,9 @@ proto.arduino.SearchOutput.deserializeBinaryFromReader = function(msg, reader) {
msg.setAuthor(value);
break;
case 5:
var value = /** @type {string} */ (reader.readString());
msg.setSentence(value);
break;
case 6:
var value = /** @type {string} */ (reader.readString());
msg.setParagragh(value);
var value = new proto.arduino.SearchOutputBoard;
reader.readMessage(value,proto.arduino.SearchOutputBoard.deserializeBinaryFromReader);
msg.addBoards(value);
break;
default:
reader.skipField();
@ -2208,18 +2213,12 @@ proto.arduino.SearchOutput.serializeBinaryToWriter = function(message, writer) {
f
);
}
f = message.getSentence();
f = message.getBoardsList();
if (f.length > 0) {
writer.writeString(
writer.writeRepeatedMessage(
5,
f
);
}
f = message.getParagragh();
if (f.length > 0) {
writer.writeString(
6,
f
f,
proto.arduino.SearchOutputBoard.serializeBinaryToWriter
);
}
};
@ -2286,32 +2285,202 @@ proto.arduino.SearchOutput.prototype.setAuthor = function(value) {
/**
* optional string Sentence = 5;
* @return {string}
* repeated SearchOutputBoard Boards = 5;
* @return {!Array<!proto.arduino.SearchOutputBoard>}
*/
proto.arduino.SearchOutput.prototype.getSentence = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, ""));
proto.arduino.SearchOutput.prototype.getBoardsList = function() {
return /** @type{!Array<!proto.arduino.SearchOutputBoard>} */ (
jspb.Message.getRepeatedWrapperField(this, proto.arduino.SearchOutputBoard, 5));
};
/** @param {string} value */
proto.arduino.SearchOutput.prototype.setSentence = function(value) {
jspb.Message.setProto3StringField(this, 5, value);
/** @param {!Array<!proto.arduino.SearchOutputBoard>} value */
proto.arduino.SearchOutput.prototype.setBoardsList = function(value) {
jspb.Message.setRepeatedWrapperField(this, 5, value);
};
/**
* optional string Paragragh = 6;
* @param {!proto.arduino.SearchOutputBoard=} opt_value
* @param {number=} opt_index
* @return {!proto.arduino.SearchOutputBoard}
*/
proto.arduino.SearchOutput.prototype.addBoards = function(opt_value, opt_index) {
return jspb.Message.addToRepeatedWrapperField(this, 5, opt_value, proto.arduino.SearchOutputBoard, opt_index);
};
proto.arduino.SearchOutput.prototype.clearBoardsList = function() {
this.setBoardsList([]);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.arduino.SearchOutputBoard = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.arduino.SearchOutputBoard, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.arduino.SearchOutputBoard.displayName = 'proto.arduino.SearchOutputBoard';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.arduino.SearchOutputBoard.prototype.toObject = function(opt_includeInstance) {
return proto.arduino.SearchOutputBoard.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.arduino.SearchOutputBoard} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.arduino.SearchOutputBoard.toObject = function(includeInstance, msg) {
var f, obj = {
name: jspb.Message.getFieldWithDefault(msg, 1, ""),
fqbn: jspb.Message.getFieldWithDefault(msg, 2, "")
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.arduino.SearchOutputBoard}
*/
proto.arduino.SearchOutputBoard.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.arduino.SearchOutputBoard;
return proto.arduino.SearchOutputBoard.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.arduino.SearchOutputBoard} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.arduino.SearchOutputBoard}
*/
proto.arduino.SearchOutputBoard.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setName(value);
break;
case 2:
var value = /** @type {string} */ (reader.readString());
msg.setFqbn(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.arduino.SearchOutputBoard.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.arduino.SearchOutputBoard.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.arduino.SearchOutputBoard} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.arduino.SearchOutputBoard.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getName();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
f = message.getFqbn();
if (f.length > 0) {
writer.writeString(
2,
f
);
}
};
/**
* optional string name = 1;
* @return {string}
*/
proto.arduino.SearchOutput.prototype.getParagragh = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, ""));
proto.arduino.SearchOutputBoard.prototype.getName = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/** @param {string} value */
proto.arduino.SearchOutput.prototype.setParagragh = function(value) {
jspb.Message.setProto3StringField(this, 6, value);
proto.arduino.SearchOutputBoard.prototype.setName = function(value) {
jspb.Message.setProto3StringField(this, 1, value);
};
/**
* optional string fqbn = 2;
* @return {string}
*/
proto.arduino.SearchOutputBoard.prototype.getFqbn = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
};
/** @param {string} value */
proto.arduino.SearchOutputBoard.prototype.setFqbn = function(value) {
jspb.Message.setProto3StringField(this, 2, value);
};

View File

@ -2,7 +2,7 @@ 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, AttachedSerialBoard } from '../common/protocol/boards-service';
import { BoardsService, AttachedSerialBoard, AttachedNetworkBoard } from '../common/protocol/boards-service';
import { CoreClientProvider } from './core-client-provider';
import * as path from 'path';
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
@ -51,17 +51,25 @@ export class CoreServiceImpl implements CoreService {
compilerReq.setQuiet(false);
const result = client.compile(compilerReq);
return new Promise<void>((resolve, reject) => {
try {
await new Promise<void>((resolve, reject) => {
result.on('data', (cr: CompileResp) => {
this.toolOutputService.publishNewOutput("compile", new Buffer(cr.getOutStream_asU8()).toString());
console.error(cr.getErrStream().toString());
this.toolOutputService.publishNewOutput("compile error", new Buffer(cr.getErrStream_asU8()).toString());
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
this.toolOutputService.publishNewOutput("compile", "Compilation complete\n");
} catch (e) {
this.toolOutputService.publishNewOutput("compile error", `Compilation error: ${e}\n`);
throw e;
}
}
async upload(options: CoreService.Upload.Options): Promise<void> {
await this.compile({uri: options.uri});
console.log('upload', options);
const { uri } = options;
const sketchFilePath = await this.fileSystem.getFsPath(options.uri);
@ -86,11 +94,15 @@ export class CoreServiceImpl implements CoreService {
req.setFqbn(currentBoard.fqbn);
if (AttachedSerialBoard.is(currentBoard)) {
req.setPort(currentBoard.port);
} else {
} else if (AttachedNetworkBoard.is(currentBoard)) {
throw new Error("can only upload to serial boards");
} else {
throw new Error("board is not attached");
}
const result = client.upload(req);
return new Promise<void>((resolve, reject) => {
try {
await 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());
@ -98,6 +110,11 @@ export class CoreServiceImpl implements CoreService {
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
this.toolOutputService.publishNewOutput("upload", "Upload complete\n");
} catch (e) {
this.toolOutputService.publishNewOutput("upload error", `Uplaod error: ${e}\n`);
throw e;
}
}
}

View File

@ -6,6 +6,10 @@ export class ToolOutputServiceServerImpl implements ToolOutputServiceServer {
protected clients: ToolOutputServiceClient[] = [];
publishNewOutput(tool: string, chunk: string): void {
if (!chunk) {
return;
}
this.clients.forEach(c => c.onNewOutput(tool, chunk));
}