@sensebox/flash-tool
v0.1.0
Published
Drop-in React widget for flashing ESP32-based boards (e.g. senseBox MCU-S2) over the Web Serial API.
Readme
@sensebox/flash-tool
A drop-in React widget for flashing ESP32-family boards (senseBox MCU-S2 by default) over the Web Serial API, using esptool-js.
<FlashTool /> renders a small, self-contained status panel: connect a
board, pick a sketch from the built-in dropdown (CircuitPython, senseBox
OTA, Basic, or the standard senseBox sketch), put the board into bootloader
mode, and flash it. Four ready-to-flash firmware images ship with the
package, so it works out of the box - or bring your own binary(ies) if you'd
rather compile them yourself.
Install
npm install @sensebox/flash-toolreact and react-dom (>=17) are peer dependencies.
Usage
import { FlashTool } from "@sensebox/flash-tool";
import "@sensebox/flash-tool/style.css";
// Simplest case: the dropdown lets the user pick a sketch, and each option
// flashes the matching built-in firmware image - nothing else to wire up.
function App() {
return (
<FlashTool
onFlashed={() => console.log("done!")}
onError={(err) => console.error(err)}
/>
);
}Lock the widget to a single sketch (dropdown disabled) by passing
firmwareType:
<FlashTool firmwareType="circuitpy" />Bring your own binary(ies) instead of the bundled ones - either a single
binary for a one-off flash, or a firmwares map so the dropdown flashes
whichever one you supply per type (falling back to the built-in image for
any type you don't override):
<FlashTool
firmwares={{ standard: myCompiledSketch }} // Uint8Array
/>The widget walks through: connect device -> prepare bootloader (1200bps
touch) -> (first time only) grant permission for the re-enumerated
bootloader port -> flash. With autoFlash (default true) it starts
flashing automatically as soon as both a binary and a connected/prepared
device are available. A "?" button next to the dropdown opens a short
how-to modal.
Props
| Prop | Type | Default | Description |
| ----------------------- | ---------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------- |
| binary | Uint8Array | - | Compiled firmware image to flash. Ignored if firmwares is set. |
| firmwares | { circuitpy?, ota?, basic?, standard? } (each Uint8Array) | - | Per-sketch overrides. Any type you don't supply falls back to the bundled image. |
| firmwareType | "circuitpy" \| "ota" \| "basic" \| "standard" | - | Locks the dropdown to this sketch and disables it. |
| defaultFirmwareType | same as above | "circuitpy" | Initial dropdown selection when firmwareType isn't set (stays interactive). |
| firmwareFlashOptions | { [type]: object } | see below | Per-sketch overrides for the esptool flash step (address/eraseAll/etc.), merged over the built-in ones. |
| usbVendorId | number | 0x303a (senseBox/Espressif) | USB vendor id used to filter the device picker. |
| flashOptions | object | see below | Base overrides for the esptool flash step, applied to every sketch type. |
| autoFlash | boolean | true | Start flashing automatically once ready. |
| strings | object | English defaults | Override any UI label for i18n (including sketch names and the help modal text). |
| onConnected | (label: string) => void | - | Fired when a device is selected/connected. |
| onDisconnected | () => void | - | Fired when the device is disconnected. |
| onFlashed | () => void | - | Fired when a flash finishes successfully. |
| onError | (err: Error) => void | - | Fired on any connect/prepare/flash/firmware-load error. |
| onFirmwareTypeChange | (type: string) => void | - | Fired when the dropdown selection changes. |
Sketch types & flash addresses
circuitpy, ota, basic and standard are all pre-merged images
(bootloader + partition table + otadata + app baked into one file via
esptool merge_bin), so they're written starting at 0x0 with the whole
chip erased first. This makes them self-contained: they boot correctly
regardless of whatever partition layout, OTA selection, or filesystem was
previously on the chip. See BUILTIN_FIRMWARE_FLASH_OVERRIDES in
FlashTool.jsx - override any of it per type via firmwareFlashOptions.
flashOptions defaults:
{
address: 0x10000,
baudrate: 115200,
flashMode: "dio",
flashFreq: "80m",
flashSize: "4MB",
eraseAll: false,
usingUsbOtg: true,
}Building a custom UI
If the built-in widget doesn't fit, use the underlying hook directly:
import { useFlashDevice } from "@sensebox/flash-tool";
const {
supported, connected, bootloaderReady, deviceLabel,
status, progress, log, error, needsBootloaderPermission,
selectDevice, prepareBootloader, grantBootloaderPort, flash, disconnect,
} = useFlashDevice({ usbVendorId: 0x303a });Or drop to the raw esptool helpers: touchTo1200bps, waitForBootloaderPort,
flashBinary.
Browser support
Requires a browser with Web Serial support (Chrome/Edge on desktop). The
widget renders a fallback message when navigator.serial is unavailable.
License
MIT
