# esptool-js
**Repository Path**: duzc2/esptool-js
## Basic Information
- **Project Name**: esptool-js
- **Description**: No description available
- **Primary Language**: JavaScript
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-04-26
- **Last Updated**: 2026-04-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Javascript implementation of esptool
This repository contains a Javascript implementation of [esptool](https://github.com/espressif/esptool), a serial flasher utility for Espressif chips. `esptool-js` is based on [Web Serial API](https://wicg.github.io/serial/) and works in Google Chrome and Microsoft Edge [version 89 or later](https://developer.mozilla.org/en-US/docs/Web/API/Serial#browser_compatibility) browsers and Google Chrome on Android [version 61 or later](https://developer.mozilla.org/en-US/docs/Web/API/USB#browser_compatibility) via the [web-serial-polyfill](https://github.com/google/web-serial-polyfill) compatibility layer.
**NOTE:** Unlike the Python-based esptool, `esptool-js` doesn't implement generation of binary images out of ELF files, and doesn't include companion tools similar to [espefuse.py](https://github.com/espressif/esptool/wiki/espefuse) and [espsecure.py](https://github.com/espressif/esptool/wiki/espsecure).
**📚 [API Documentation](https://espressif.github.io/esptool-js/docs/)** - Complete API reference with detailed class and method documentation.
## Installation
**CDN**
`https://unpkg.com/esptool-js/lib/index.js` or `https://unpkg.com/esptool-js/bundle.js` to use the single bundle JavaScript file.
**NPM**
```bash
npm install --save esptool-js
```
**Yarn**
```bash
yarn add --save esptool-js
```
**Nightly builds** for ESPTOOL-JS
## How to Use
### Basic Setup
First, import the necessary classes and types:
```typescript
import {
ESPLoader,
Transport,
LoaderOptions,
FlashOptions,
FlashModeValues,
FlashFreqValues,
FlashSizeValues,
IEspLoaderTerminal,
} from "esptool-js";
```
### 1. Request Serial Port Access
Request access to a serial port using the Web Serial API:
```typescript
// Request port access (user will be prompted to select a device)
const port = await navigator.serial.requestPort();
// Optionally, filter by USB vendor/product IDs
const portFilters = [
{ usbVendorId: 0x10c4, usbProductId: 0xea60 } // Example: Silicon Labs CP210x
];
const port = await navigator.serial.requestPort({ filters: portFilters });
```
### 2. Create Transport and ESPLoader
Create a `Transport` instance and configure the `ESPLoader`:
```typescript
// Create transport instance
const transport = new Transport(port, true);
// Optional: Create a terminal interface for logging
const terminal: IEspLoaderTerminal = {
clean() {
console.clear();
},
writeLine(data: string) {
console.log(data);
},
write(data: string) {
console.log(data);
},
};
// Configure loader options
const loaderOptions: LoaderOptions = {
transport: transport,
baudrate: 115200, // Communication baud rate
terminal: terminal, // Optional terminal for logging
debugLogging: false, // Optional debug logging
};
// Create ESPLoader instance
const esploader = new ESPLoader(loaderOptions);
```
### 3. Connect to Device
Connect to the ESP device and detect the chip:
```typescript
try {
// Connect and detect chip (this will reset the device)
const chipName = await esploader.main();
console.log(`Connected to: ${chipName}`);
} catch (error) {
console.error("Failed to connect:", error);
}
```
### 4. Flash Firmware
Flash firmware images to the device:
```typescript
// Read your firmware file (e.g., from a File input or fetch)
const firmwareData = new Uint8Array(/* your firmware binary data */);
const firmwareAddress = 0x1000; // Starting address in flash
// Configure flash options
const flashOptions: FlashOptions = {
fileArray: [
{ data: firmwareData, address: firmwareAddress }
],
flashMode: "dio" as FlashModeValues, // Flash mode: "qio", "qout", "dio", "dout"
flashFreq: "40m" as FlashFreqValues, // Flash frequency: "80m", "40m", "26m", "20m", etc.
flashSize: "4MB" as FlashSizeValues, // Flash size: "256KB", "512KB", "1MB", "2MB", "4MB", etc.
eraseAll: false, // Set to true to erase entire flash before writing
compress: true, // Compress data during transfer
reportProgress: (fileIndex, written, total) => {
const percent = (written / total) * 100;
console.log(`Progress: ${percent.toFixed(1)}%`);
},
// Optional: MD5 hash calculation for verification
calculateMD5Hash: (image: Uint8Array) => {
// Implement your MD5 calculation here
return "your-md5-hash";
},
};
// Flash the firmware
await esploader.writeFlash(flashOptions);
// Reset the device after flashing (optional)
await esploader.after("hard_reset");
```
### 5. Read Flash Memory
Read data from flash memory:
```typescript
const startAddress = 0x1000;
const size = 4096; // Read 4KB
const data = await esploader.readFlash(
startAddress,
size,
(packet, progress, totalSize) => {
// Optional progress callback
console.log(`Read: ${progress}/${totalSize} bytes`);
}
);
console.log("Read data:", data);
```
### 6. Erase Flash
Erase flash memory:
```typescript
// Erase entire flash
await esploader.eraseFlash();
// Or erase a specific region (if supported)
// await esploader.eraseRegion(startAddress, size);
```
### 7. Reset Strategies (OPTIONAL and advanced)
**Note:** This is an advanced feature. For most use cases, the default reset strategies provided by `esptool-js` will work correctly. You only need to implement custom reset strategies if:
- You're using custom hardware that requires specific DTR/RTS sequences
- The default reset methods don't work with your particular board or adapter
- You need fine-grained control over the reset timing and sequence
- You're working with non-standard ESP development boards
By default, `ESPLoader` uses built-in reset strategies that work with most ESP32/ESP8266 boards. However, if you need to implement your own reset sequence, you can provide custom reset constructors.
#### Understanding Reset Commands
Reset strategies use a sequence of commands to control the DTR (Data Terminal Ready) and RTS (Request To Send) signals on the serial port:
- **D**: `setDTR` - Set DTR signal (0=False, 1=True)
- **R**: `setRTS` - Set RTS signal (0=False, 1=True)
- **W**: Wait - Delay in milliseconds (positive integer)
Commands are separated by `|` (pipe). For example, `"D0|R1|W100|D1|R0|W50|D0"` represents:
1. Set DTR to false
2. Set RTS to true
3. Wait 100ms
4. Set DTR to true
5. Set RTS to false
6. Wait 50ms
7. Set DTR to false
#### Implementing Custom Reset Strategies
```typescript
import {
ClassicReset,
HardReset,
UsbJtagSerialReset,
CustomReset,
ResetConstructors,
validateCustomResetStringSequence,
} from "esptool-js";
// Option 1: Use built-in reset strategies with custom parameters
const resetConstructors: ResetConstructors = {
classicReset: (transport, resetDelay) => new ClassicReset(transport, resetDelay),
hardReset: (transport, usingUsbOtg) => new HardReset(transport, usingUsbOtg),
usbJTAGSerialReset: (transport) => new UsbJtagSerialReset(transport),
};
// Option 2: Implement a completely custom reset sequence
const customResetSequence = "D0|R1|W100|D1|R0|W50|D0";
// Validate the sequence before using it
if (validateCustomResetStringSequence(customResetSequence)) {
resetConstructors.customReset = (transport, sequenceString) =>
new CustomReset(transport, customResetSequence);
} else {
console.error("Invalid reset sequence");
}
// Apply custom reset strategies to loader options
const loaderOptions: LoaderOptions = {
transport: transport,
baudrate: 115200,
resetConstructors: resetConstructors,
};
const esploader = new ESPLoader(loaderOptions);
// Use specific reset mode when connecting
await esploader.main("default_reset"); // Uses classicReset
// await esploader.main("hard_reset"); // Uses hardReset
// await esploader.main("no_reset"); // Skips reset
```
#### Example: Custom Reset for Special Hardware
If your board requires a specific reset sequence:
```typescript
// Custom sequence for a board that needs longer reset pulse
const customSequence = "D0|R0|W50|D1|R1|W200|D0|R0|W100";
if (validateCustomResetStringSequence(customSequence)) {
const resetConstructors: ResetConstructors = {
customReset: (transport, _) => new CustomReset(transport, customSequence),
};
const esploader = new ESPLoader({
transport,
baudrate: 115200,
resetConstructors,
});
await esploader.main("default_reset");
}
```
### 8. Complete Example
Here's a complete example that demonstrates the full workflow:
```typescript
import {
ESPLoader,
Transport,
LoaderOptions,
FlashOptions,
FlashModeValues,
FlashFreqValues,
FlashSizeValues,
} from "esptool-js";
async function flashFirmware() {
try {
// 1. Request serial port
const port = await navigator.serial.requestPort();
// 2. Create transport and loader
const transport = new Transport(port, true);
const esploader = new ESPLoader({
transport,
baudrate: 115200,
terminal: {
clean: () => console.clear(),
writeLine: (data) => console.log(data),
write: (data) => console.log(data),
},
});
// 3. Connect to device
const chipName = await esploader.main();
console.log(`Connected to: ${chipName}`);
// 4. Load firmware (example: from a file input)
const fileInput = document.getElementById("firmwareFile") as HTMLInputElement;
const file = fileInput.files[0];
const firmwareData = new Uint8Array(await file.arrayBuffer());
// 5. Flash firmware
const flashOptions: FlashOptions = {
fileArray: [{ data: firmwareData, address: 0x1000 }],
flashMode: "dio" as FlashModeValues,
flashFreq: "40m" as FlashFreqValues,
flashSize: "4MB" as FlashSizeValues,
eraseAll: false,
compress: true,
reportProgress: (fileIndex, written, total) => {
console.log(`Progress: ${((written / total) * 100).toFixed(1)}%`);
},
};
await esploader.writeFlash(flashOptions);
console.log("Firmware flashed successfully!");
// 6. Reset device
await esploader.after("hard_reset");
// 7. Disconnect
await transport.disconnect();
} catch (error) {
console.error("Error:", error);
}
}
```
### Terminal Interface
You can use any JavaScript-compatible terminal by implementing the `IEspLoaderTerminal` interface:
```typescript
import { IEspLoaderTerminal } from "esptool-js";
const terminal: IEspLoaderTerminal = {
clean() {
// Clear terminal output
},
writeLine(data: string) {
// Write a line with newline
},
write(data: string) {
// Write data without newline
},
};
```
Check the [example project](https://github.com/espressif/esptool-js/tree/main/examples/typescript) for a complete working implementation.
## Live demo
Visit https://espressif.github.io/esptool-js/ to see this tool in action.
## Testing it locally
```sh
npm install
npm run build
cd examples/typescript
npm install
npm run dev # Run local sever with example code
```
Then open `http://localhost:1234` in a Chrome browser. The `npm run build` step builds the `lib` used in the example `examples/typescript/index.html`. Update this reference as described in the [Installation](#installation) section.
## Test from Pull Request artifact
If you are testing the main branch or any Pull Request (PR) artifact you can follow these steps:
1. Get the `esptool-js-.tgz` where `` is the current version and download it.
2. Add the following line to your project's package.json dependencies
```json
"dependencies": {
"esptool-js": "file:../path/to/esptool-js-.tgz"
}
```
3. Use the package like `import "esptool-js/lib/index.js"` when added in package.json as shown before.
## License
The code in this repository is Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. It is licensed under Apache 2.0 license, as described in [LICENSE](https://github.com/espressif/esptool-js/blob/main/LICENSE) file.