From cb10194d0c7ec20f22b46c97cf0259e091a34d30 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 26 Sep 2025 22:21:03 -0700 Subject: update flash page --- src/routes/(app)/pos/+page.server.ts | 7 +- src/routes/(app)/pos/+page.svelte | 216 +++++++++++++++++++++++++++-------- 2 files changed, 173 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/routes/(app)/pos/+page.server.ts b/src/routes/(app)/pos/+page.server.ts index 59f2d923..1df1bb33 100644 --- a/src/routes/(app)/pos/+page.server.ts +++ b/src/routes/(app)/pos/+page.server.ts @@ -3,7 +3,12 @@ import { auth, fd, get } from "$lib/utils"; import { hex } from "@scure/base"; export async function load({ cookies }) { - const token = await get("/ro", auth(cookies)); + let token; + + try { + token = await get("/ro", auth(cookies)); + } catch (e) {} + return { token }; } diff --git a/src/routes/(app)/pos/+page.svelte b/src/routes/(app)/pos/+page.svelte index be9a9719..6f3c5d24 100644 --- a/src/routes/(app)/pos/+page.svelte +++ b/src/routes/(app)/pos/+page.svelte @@ -3,102 +3,220 @@ import { ESPLoader, Transport } from "esptool-js"; import { hex } from "@scure/base"; + // Convert Uint8Array → JS "binary string" in safe chunks function bs(uint8Array) { let binaryString = ""; - const chunkSize = 0x8000; // 32,768 bytes (safe limit) - + const chunkSize = 0x8000; for (let i = 0; i < uint8Array.length; i += chunkSize) { const chunk = uint8Array.subarray(i, i + chunkSize); binaryString += String.fromCharCode(...chunk); } - return binaryString; } let { data, form } = $props(); let { token } = $state(data); - const address = 0x3d0000; - const baudrate = 921600; + // --- Defaults --- + const LITTLEFS_ADDRESS_DEFAULT = 0x3d0000; // your existing LittleFS offset + const FW_ADDRESS_DEFAULT = 0x10000; // typical app offset on ESP32-C3 + const CONNECT_BAUD = 115200; // initial + const WORK_BAUD = 921600; // fast flashing - let file = $state(); - let ssid = $state(); - let key = $state(); + // --- Shared state --- let esploader = $state(); + let chip, transport; + let connected = $state(false); + let portInfo = $state(""); + + // --- Existing config path (generated server-side to hex in form.bytes) --- let bytes = $derived(form ? hex.decode(form.bytes) : undefined); + let littlefsAddress = $state(LITTLEFS_ADDRESS_DEFAULT); + let configProgress = $state(0); + let configDone = $state(false); + + // --- New firmware flashing path --- + let fwFile = $state(null); + let fwBytes = $state(); // Uint8Array + let fwAddress = $state(FW_ADDRESS_DEFAULT); + let fwEraseAll = $state(false); + let fwProgress = $state(0); + let fwDone = $state(false); + let fwError = $state(""); + + // Simple tab toggle + let tab = $state("config"); // "config" | "firmware" - let chip, transport; let connect = async () => { try { - let device = await navigator.serial.requestPort({}); + const device = await navigator.serial.requestPort({}); transport = new Transport(device, true); - esploader = new ESPLoader({ transport, - baudrate, + baudrate: CONNECT_BAUD, }); chip = await esploader.main(); + + connected = true; + portInfo = (await device.getInfo?.()) ? JSON.stringify(await device.getInfo()) : "Connected"; } catch (e) { console.log(e); + connected = false; } }; - let progress = $state(); - let flash = async () => { - let fileArray = [{ data: bs(bytes), address }]; + let flashConfig = async () => { + if (!esploader || !bytes) return; + configDone = false; + configProgress = 0; - const flashOptions = { + const fileArray = [{ data: bs(bytes), address: Number(littlefsAddress) }]; + + await esploader.writeFlash({ fileArray, flashSize: "keep", eraseAll: false, compress: true, - reportProgress: (fileIndex, written, total) => { - progress = parseInt((written / total) * 100); + reportProgress: (_fileIndex, written, total) => { + configProgress = Math.floor((written / total) * 100); }, + }); + + configDone = true; + }; + + function onPickFw(e) { + fwError = ""; + fwDone = false; + const f = e.target.files?.[0]; + fwFile = f || null; + if (!fwFile) { + fwBytes = undefined; + return; + } + const reader = new FileReader(); + reader.onload = () => { + const buf = new Uint8Array(reader.result); + fwBytes = buf; + }; + reader.onerror = () => { + fwError = "Failed to read file."; + fwBytes = undefined; }; + reader.readAsArrayBuffer(fwFile); + } + + let flashFirmware = async () => { + if (!esploader) { + fwError = "Not connected."; + return; + } + if (!fwBytes?.length) { + fwError = "No firmware selected."; + return; + } + fwError = ""; + fwDone = false; + fwProgress = 0; - await esploader.writeFlash(flashOptions); + try { + const fileArray = [{ data: bs(fwBytes), address: Number(fwAddress) }]; + + await esploader.writeFlash({ + fileArray, + flashSize: "keep", + eraseAll: Boolean(fwEraseAll), + compress: true, + reportProgress: (_fileIndex, written, total) => { + fwProgress = Math.floor((written / total) * 100); + }, + }); + + fwDone = true; + } catch (e) { + console.error(e); + fwError = e?.message || "Flash failed."; + } };

- Flash config + ESP32-C3 Flasher

- {#if esploader} - {#if bytes} - {#if progress} -
Done!
+ {#if !connected} +
+ +
{portInfo}
+
+{/if} + + {#if connected} + +
+ + +
+ + {#if tab === "config"} + + {#if bytes} + {#if configDone} +
Config written ✔
+ {:else} +
Generated config file ({bytes.length} bytes)
+ + (littlefsAddress = Number(e.target.value))} /> +
+ +
+ {#if configProgress > 0}
Progress: {configProgress}%
{/if} + {/if} {:else} -
Generated config file ({bytes.length * 2} bytes)
- +
+ + + + +
{/if} {:else} -
- - - - -
+ +
+ + + + + (fwAddress = Number(e.target.value))} /> + + + +
+ +
+ + {#if fwProgress > 0 && !fwDone} +
Progress: {fwProgress}%
+ {/if} + {#if fwDone} +
Firmware written ✔
+ {/if} + {#if fwError} +
{fwError}
+ {/if} +
{/if} - {:else} - {/if}
+ + -- cgit v1.2.3