Spaces:
Running
Running
File size: 3,322 Bytes
130ae50 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
/**
* Helper to find the USB port associated with your MotorsBus.
*
* Example:
* ```
* npx lerobot find-port
* ```
*/
import { SerialPort } from "serialport";
import { createInterface } from "readline";
import { platform } from "os";
import { readdir } from "fs/promises";
import { join } from "path";
/**
* Find all available serial ports on the system
* Mirrors Python's find_available_ports() function
*/
async function findAvailablePorts(): Promise<string[]> {
if (platform() === "win32") {
// List COM ports using serialport library (equivalent to pyserial)
const ports = await SerialPort.list();
return ports.map((port) => port.path);
} else {
// List /dev/tty* ports for Unix-based systems (Linux/macOS)
try {
const devFiles = await readdir("/dev");
const ttyPorts = devFiles
.filter((file) => file.startsWith("tty"))
.map((file) => join("/dev", file));
return ttyPorts;
} catch (error) {
// Fallback to serialport library if /dev reading fails
const ports = await SerialPort.list();
return ports.map((port) => port.path);
}
}
}
/**
* Create readline interface for user input
* Equivalent to Python's input() function
*/
function createReadlineInterface() {
return createInterface({
input: process.stdin,
output: process.stdout,
});
}
/**
* Prompt user for input and wait for response
* Equivalent to Python's input() function
*/
function waitForInput(prompt: string = ""): Promise<string> {
const rl = createReadlineInterface();
return new Promise((resolve) => {
if (prompt) {
process.stdout.write(prompt);
}
rl.on("line", (answer) => {
rl.close();
resolve(answer);
});
});
}
/**
* Sleep for specified milliseconds
* Equivalent to Python's time.sleep()
*/
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Main find port function - direct port of Python find_port()
* Maintains identical UX and messaging
*/
export async function findPort(): Promise<void> {
console.log("Finding all available ports for the MotorsBus.");
const portsBefore = await findAvailablePorts();
console.log("Ports before disconnecting:", portsBefore);
console.log(
"Remove the USB cable from your MotorsBus and press Enter when done."
);
await waitForInput();
// Allow some time for port to be released (equivalent to Python's time.sleep(0.5))
await sleep(500);
const portsAfter = await findAvailablePorts();
const portsDiff = portsBefore.filter((port) => !portsAfter.includes(port));
if (portsDiff.length === 1) {
const port = portsDiff[0];
console.log(`The port of this MotorsBus is '${port}'`);
console.log("Reconnect the USB cable.");
} else if (portsDiff.length === 0) {
throw new Error(
`Could not detect the port. No difference was found (${JSON.stringify(
portsDiff
)}).`
);
} else {
throw new Error(
`Could not detect the port. More than one port was found (${JSON.stringify(
portsDiff
)}).`
);
}
}
/**
* CLI entry point when called directly
*/
if (import.meta.url === `file://${process.argv[1]}`) {
findPort().catch((error) => {
console.error(error.message);
process.exit(1);
});
}
|