diff --git a/src/lib/serial/device.ts b/src/lib/serial/device.ts index 2783fe2f..d22bbd8b 100644 --- a/src/lib/serial/device.ts +++ b/src/lib/serial/device.ts @@ -477,10 +477,14 @@ export class CharaDevice { return Number(await this.send(1, ["RAM"]).then(([bytes]) => bytes)); } - async updateFirmware(file: File | Blob): Promise { + async updateFirmware( + file: ArrayBuffer, + progress: (transferred: number, total: number) => void, + ): Promise { while (this.lock) { await this.lock; } + let resolveLock: (result: true) => void; this.lock = new Promise((resolve) => { resolveLock = resolve; @@ -510,46 +514,46 @@ export class CharaDevice { }); return it; }); - } finally { - writer.releaseLock(); - } - // Wait for the device to be ready - const signal = await this.reader.read(); - serialLog.update((it) => { - it.push({ - type: "output", - value: signal.value!.trim(), + // Wait for the device to be ready + const signal = await this.reader.read(); + serialLog.update((it) => { + it.push({ + type: "output", + value: signal.value!.trim(), + }); + return it; }); - return it; - }); - await file.stream().pipeTo(this.port.writable!); + const chunkSize = 128; + for (let i = 0; i < file.byteLength; i += chunkSize) { + const chunk = file.slice(i, i + chunkSize); + await writer.write(new Uint8Array(chunk)); + progress(i + chunk.byteLength, file.byteLength); + } - serialLog.update((it) => { - it.push({ - type: "input", - value: `...${file.size} bytes`, + serialLog.update((it) => { + it.push({ + type: "input", + value: `...${file.byteLength} bytes`, + }); + return it; }); - return it; - }); - const result = (await this.reader.read()).value!.trim(); - serialLog.update((it) => { - it.push({ - type: "output", - value: result!, + const result = (await this.reader.read()).value!.trim(); + serialLog.update((it) => { + it.push({ + type: "output", + value: result!, + }); + return it; }); - return it; - }); - if (result !== "OTA OK") { - throw new Error(result); - } + if (result !== "OTA OK") { + throw new Error(result); + } - const writer2 = this.port.writable!.getWriter(); - try { - await writer2.write(new TextEncoder().encode(`RST RESTART\r\n`)); + await writer.write(new TextEncoder().encode(`RST RESTART\r\n`)); serialLog.update((it) => { it.push({ type: "input", @@ -558,7 +562,7 @@ export class CharaDevice { return it; }); } finally { - writer2.releaseLock(); + writer.releaseLock(); } await this.suspend(); diff --git a/src/lib/setting.ts b/src/lib/setting.ts index 9a753b56..998fab60 100644 --- a/src/lib/setting.ts +++ b/src/lib/setting.ts @@ -49,6 +49,8 @@ export const setting: Action< if (isNumeric) { value = Number(node.value); if (Number.isNaN(value)) return; + if (min !== undefined) value = Math.max(min, value); + if (max !== undefined) value = Math.min(max, value); value = Math.floor( inverse !== undefined ? inverse / value @@ -56,8 +58,6 @@ export const setting: Action< ? value / scale : value, ); - if (min !== undefined) value = Math.max(min, value); - if (max !== undefined) value = Math.min(max, value); } else { value = node.checked ? 1 : 0; } diff --git a/src/routes/(app)/ccos/[device]/[version]/+page.svelte b/src/routes/(app)/ccos/[device]/[version]/+page.svelte index cd265dd0..018f46b2 100644 --- a/src/routes/(app)/ccos/[device]/[version]/+page.svelte +++ b/src/routes/(app)/ccos/[device]/[version]/+page.svelte @@ -13,6 +13,7 @@ let unsafeUpdate = $state(false); let terminalOutput = $state(""); + let progress = $state(0); let step = $state(0); let eraseAll = $state(false); @@ -28,9 +29,11 @@ try { const file = await fetch( `${data.meta.path}/${data.meta.update.ota}`, - ).then((it) => it.blob()); + ).then((it) => it.arrayBuffer()); - await port.updateFirmware(file); + await port.updateFirmware(file, (transferred, total) => { + progress = transferred / total; + }); success = true; } catch (e) { @@ -194,7 +197,9 @@