feat: add baud rate selection for ESP flashing in DeviceFlasher component

This commit is contained in:
Ben Allfree
2026-04-22 20:55:53 -07:00
parent 5caf5966b8
commit e98793c77d
2 changed files with 30 additions and 4 deletions
+24 -2
View File
@@ -16,10 +16,12 @@ import { toast } from "sonner"
import { buildFlashParts } from "../lib/espFlashLayout"
import {
ensureSerialPortClosed,
ESP_FLASH_BAUD_OPTIONS,
ESP_FLASH_WEB_BAUD,
isSerialUserCancelledError,
pulseUsbBootloaderOnPort,
runEspFlash,
type EspFlashBaud,
type FlashPhase,
} from "../lib/espFlashRun"
import { inferTargetFamilyFromBundle, inferTargetFamilyFromEnv } from "../lib/flashTargetFamily"
@@ -84,6 +86,7 @@ export default function DeviceFlasher({
const [busy, setBusy] = useState(false)
const shareDialogRef = useRef<HTMLDialogElement>(null)
const [eraseFlashForFactory, setEraseFlashForFactory] = useState(false)
const [flashBaud, setFlashBaud] = useState<EspFlashBaud>(ESP_FLASH_WEB_BAUD)
const [bundleFamily, setBundleFamily] = useState<FlashTargetFamily>(inferTargetFamilyFromEnv(targetEnv) ?? "esp32")
const [bundleCanErase, setBundleCanErase] = useState(false)
const [flashProgress, setFlashProgress] = useState<FlashProgress | null>(null)
@@ -175,7 +178,7 @@ export default function DeviceFlasher({
await runEspFlash({
port,
parts: plan.parts,
baud: ESP_FLASH_WEB_BAUD,
baud: flashBaud,
eraseAll: eraseFlashForFactory || plan.eraseAll,
onPhase: phase => {
setFlashProgress({ kind: "indeterminate", label: PHASE_LABEL[phase] })
@@ -212,7 +215,7 @@ export default function DeviceFlasher({
setFlashProgress(null)
}
}
}, [eraseFlashForFactory, prepareBundle, canEspFlash, flashBlockedReason, resolvedFamily])
}, [eraseFlashForFactory, flashBaud, prepareBundle, canEspFlash, flashBlockedReason, resolvedFamily])
const shareUrlTrimmed = useMemo(() => sharePageUrl?.trim() ?? "", [sharePageUrl])
const canNativeShare = typeof navigator !== "undefined" && typeof navigator.share === "function"
@@ -299,6 +302,25 @@ export default function DeviceFlasher({
</button>
<span className="text-sm font-medium text-slate-200">Full device reset</span>
</div>
{resolvedFamily === "esp32" ? (
<label className="flex items-center gap-2 text-sm text-slate-200">
<span>Baud</span>
<select
value={flashBaud}
onChange={e => setFlashBaud(Number(e.target.value) as EspFlashBaud)}
disabled={busy || !canEspFlash}
className="h-8 rounded-md border border-slate-600 bg-slate-900/60 px-2 text-sm text-slate-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-500 disabled:cursor-not-allowed disabled:opacity-50"
title="Lower the baud rate if flashing fails on a cheap cable or USB hub."
>
{ESP_FLASH_BAUD_OPTIONS.map(b => (
<option key={b} value={b}>
{b.toLocaleString()}
</option>
))}
</select>
</label>
) : null}
</div>
{!canFullReset ? (
+6 -2
View File
@@ -195,8 +195,12 @@ export async function runEspFlash(options: {
await transport.disconnect()
}
/** Conservative default for `runEspFlash` over Web Serial (fewer cable/hub issues than 921600). */
export const ESP_FLASH_WEB_BAUD = 115200
/** Supported Web Serial baud rates for ESP flashing. First entry is the default. */
export const ESP_FLASH_BAUD_OPTIONS = [921600, 460800, 230400, 115200] as const
export type EspFlashBaud = (typeof ESP_FLASH_BAUD_OPTIONS)[number]
/** Default baud for `runEspFlash` over Web Serial. Matches PlatformIO; lower if cables/hubs are flaky. */
export const ESP_FLASH_WEB_BAUD: EspFlashBaud = ESP_FLASH_BAUD_OPTIONS[0]
/** Match MeshCore `lib/dfu.js` CDC touch timing (1200 baud → close → wait for re-enumeration). */
const CDC_TOUCH_OPEN_MS = 100