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

@@ -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) => {
result.on('data', (cr: CompileResp) => {
this.toolOutputService.publishNewOutput("compile", new Buffer(cr.getOutStream_asU8()).toString());
console.error(cr.getErrStream().toString());
try {
await new Promise<void>((resolve, reject) => {
result.on('data', (cr: CompileResp) => {
this.toolOutputService.publishNewOutput("compile", new Buffer(cr.getOutStream_asU8()).toString());
this.toolOutputService.publishNewOutput("compile error", new Buffer(cr.getErrStream_asU8()).toString());
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
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,18 +94,27 @@ 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) => {
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());
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());
});
result.on('error', error => reject(error));
result.on('end', () => resolve());
});
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));
}