Skip to content

Commit

Permalink
Chip-id in port selection (VSC-1359) (#1195)
Browse files Browse the repository at this point in the history
* added timeout to the spaw util function

* added call to esptoo to identify chips

* changed the way we get list of serial ports from paython to jsvascript

* added use of esptool.py to identify the chip properly

* added check for esptool.py existance

---------

Co-authored-by: Petr Gadorek <petr.gadorek@espressif.com>
  • Loading branch information
Hahihula and Petr Gadorek authored May 24, 2024
1 parent 559116a commit 6e47f31
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 20 deletions.
63 changes: 46 additions & 17 deletions src/espIdf/serial/serialPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
* limitations under the License.
*/

import { join } from "path";
import * as vscode from "vscode";
import * as idfConf from "../../idfConfiguration";
import { Logger } from "../../logger/logger";
import { spawn } from "../../utils";
import { SerialPortDetails } from "./serialPortDetails";
import { OutputChannel } from "../../logger/outputChannel";
import * as SerialPortLib from "serialport";

export class SerialPort {
public static shared(): SerialPort {
Expand All @@ -45,7 +47,7 @@ export class SerialPort {
const chosen = await vscode.window.showQuickPick(
portList.map((l: SerialPortDetails) => {
return {
description: l.manufacturer,
description: l.chipType || l.manufacturer,
label: l.comName,
};
}),
Expand All @@ -58,10 +60,7 @@ export class SerialPort {
const msg = error.message
? error.message
: "Something went wrong while getting the serial port list";
Logger.errorNotify(
msg,
error
);
Logger.errorNotify(msg, error);
OutputChannel.appendLine(msg, "Serial port");
OutputChannel.appendLineAndShow(JSON.stringify(error));
}
Expand All @@ -87,24 +86,54 @@ export class SerialPort {
private list(workspaceFolder: vscode.Uri): Thenable<SerialPortDetails[]> {
return new Promise(async (resolve, reject) => {
try {
const listOfSerialPorts = await SerialPortLib.SerialPort.list();

const choices = listOfSerialPorts.map((item) => {
return new SerialPortDetails(
item.path,
item.manufacturer,
item.vendorId,
item.productId
);
});
const pythonBinPath = idfConf.readParameter(
"idf.pythonBinPath",
workspaceFolder
) as string;
const buff = await spawn(pythonBinPath, ["get_serial_list.py"]);
const regexp = /\'(.*?)\'/g;
const arrayPrint = buff.toString().match(regexp);
const choices: SerialPortDetails[] = Array<SerialPortDetails>();
const idfPath = idfConf.readParameter(
"idf.espIdfPath",
workspaceFolder
);
const esptoolPath = join(
idfPath,
"components",
"esptool_py",
"esptool",
"esptool.py"
);
const stat = await vscode.workspace.fs.stat(vscode.Uri.file(esptoolPath));
if (stat.type !== vscode.FileType.File) { // esptool.py does not exists
throw new Error(`esptool.py does not exists in ${esptoolPath}`);
}
async function processPorts(serialPort: SerialPortDetails) {
try {
const chipIdBuffer = await spawn(
pythonBinPath,
[esptoolPath, "--port", serialPort.comName, "chip_id"],
{},
2000 // success is quick, failing takes too much time
);
const regexp = /Chip is(.*?)[\r]?\n/;
const chipIdString = chipIdBuffer.toString().match(regexp);

if (arrayPrint) {
arrayPrint.forEach((portStr) => {
const portChoice = portStr.replace(/'/g, "").trim();
choices.push(new SerialPortDetails(portChoice));
});
resolve(choices);
} else {
reject(new Error("No serial ports found"));
serialPort.chipType = chipIdString && chipIdString.length > 1 ? chipIdString[1].trim() : undefined;
} catch (error) {
serialPort.chipType = undefined;
}
return serialPort;
}

resolve(await Promise.all(choices.map((item) => processPorts(item))));
} catch (error) {
reject(error);
}
Expand Down
5 changes: 4 additions & 1 deletion src/espIdf/serial/serialPortDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@ export class SerialPortDetails {
public manufacturer: string;
public vendorId: string;
public productId: string;
public chipType: string;

constructor(
comName: string,
manufacturer?: string,
vendorId?: string,
product?: string
product?: string,
chipType?: string
) {
this.comName = comName;
this.manufacturer = manufacturer;
this.vendorId = vendorId;
this.productId = product;
this.chipType = chipType;
}
}
19 changes: 17 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ export class PreCheck {
export function spawn(
command: string,
args: string[] = [],
options: any = {}
options: any = {},
timeout: number = 0
): Promise<Buffer> {
let buff = Buffer.alloc(0);
const sendToOutputChannel = (data: Buffer) => {
Expand All @@ -138,13 +139,27 @@ export function spawn(
return new Promise((resolve, reject) => {
options.cwd = options.cwd || path.resolve(path.join(__dirname, ".."));
const child = childProcess.spawn(command, args, options);
let timeoutHandler = undefined;
if (timeout > 0) {
timeoutHandler = setTimeout(() => {
child.kill();
}, timeout);
}

child.stdout.on("data", sendToOutputChannel);
child.stderr.on("data", sendToOutputChannel);

child.on("error", (error) => reject(error));
child.on("error", (error) => {
if (timeoutHandler) {
clearTimeout(timeoutHandler);
}
reject(error);
});

child.on("exit", (code) => {
if (timeoutHandler) {
clearTimeout(timeoutHandler);
}
if (code === 0) {
resolve(buff);
} else {
Expand Down

0 comments on commit 6e47f31

Please sign in to comment.