From 745d8de475e6757d33907db77007126cee920e8a Mon Sep 17 00:00:00 2001 From: Ernesto Castellotti Date: Fri, 9 Jun 2023 00:36:09 +0200 Subject: Convert sendImageMtd and XYMini to SerialReadWrite (#230) --- assets/js/rootLantiq.js | 27 +++----------- assets/js/serialUtil.js | 96 +++++++++++++++++++++++-------------------------- assets/js/xymini.js | 14 ++++---- 3 files changed, 57 insertions(+), 80 deletions(-) diff --git a/assets/js/rootLantiq.js b/assets/js/rootLantiq.js index 433b060..a3e60b1 100644 --- a/assets/js/rootLantiq.js +++ b/assets/js/rootLantiq.js @@ -161,35 +161,18 @@ async function changeBaudrate(port, newBaudrate, currBaudrate, outputErrorCallba } async function sendImageMtd(port, data, baudRate, outputErrorCallback, progressCallback) { - let reader,writer, readableStreamClosed, writerStreamClosed; + const serial = new SerialReadWrite(port, baudRate); try { - ({ reader, writer, readableStreamClosed, writerStreamClosed } = await openPortLineBreak(port, baudRate)); - await writer.write(`loady 0x${LOAD_ADDR}\n`); + await serial.writeString(`loady 0x${LOAD_ADDR}\n`); await delay(1000); - await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed); /* XYMini needs reopen the port */ - } catch (err) { - outputErrorCallback(`Error: ${err.message}`); - await closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed); - return false; - } - - try { - await port.open({ baudRate: baudRate }); - reader = port.readable.getReader(); - writer = port.writable.getWriter(); - - await sendXYMini(reader, writer, data, baudRate, progressCallback); - await reader.cancel(); - await writer.close(); - await port.close(); + await sendXYMini(serial, data, progressCallback); return true; } catch (err) { - await reader.cancel(); - await writer.close(); - await port.close(); outputErrorCallback(`Error: ${err.message}`); return false; + } finally { + await serial.closePort(); } } diff --git a/assets/js/serialUtil.js b/assets/js/serialUtil.js index ebef166..779bd4a 100644 --- a/assets/js/serialUtil.js +++ b/assets/js/serialUtil.js @@ -2,23 +2,6 @@ function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } -class LineBreakTransformer { - constructor() { - this.chunks = ""; - } - - transform(chunk, controller) { - this.chunks += chunk; - const lines = this.chunks.split("\n"); - this.chunks = lines.pop(); - lines.forEach((line) => controller.enqueue(line)); - } - - flush(controller) { - controller.enqueue(this.chunks); - } -} - class SerialReadWrite { constructor(port, baudrate) { this.port = port; @@ -36,6 +19,47 @@ class SerialReadWrite { await this.port.close(); } + async readBytes(retryError = 5, errorNum = 0) { + let reader = undefined; + + if (this.isPortOpen === false) { + await this.openPort(); + this.isPortOpen = true; + } + + try { + if (reader === undefined) { + reader = this.port.readable.getReader(); + } + + const promiseResult = await reader.read(); + + if (promiseResult === undefined) { + return undefined; + } + + return promiseResult.value; + } catch (e) { + if (e instanceof DOMException && + (e.name === "BreakError" || e.name === "FramingError" || e.name === "ParityError")) { + console.log(e); + + if (errorNum > retryError) { + throw e; + } + + return await this.readBytes(retryError, errorNum++); + } else { + throw e; + } + } finally { + if (reader) { + reader.releaseLock(); + reader = undefined; + } + } + } + async readLine(readCallback, timeout = undefined) { let reader = undefined; let extraChunk = ""; @@ -90,7 +114,7 @@ class SerialReadWrite { } } - async writeString(str) { + async writeBytes(bytes) { let writer = undefined; if (this.isPortOpen === false) { @@ -103,7 +127,7 @@ class SerialReadWrite { writer = this.port.writable.getWriter(); } - writer.write(this.textEncoder.encode(str)); + writer.write(bytes); } finally { if (writer) { writer.releaseLock(); @@ -111,38 +135,8 @@ class SerialReadWrite { } } } -} - -async function openPortLineBreak(port, baudRate) { - await port.open({ baudRate: baudRate }); - const textDecoder = new TextDecoderStream(); - const readableStreamClosed = port.readable.pipeTo(textDecoder.writable); - const reader = await textDecoder.readable.pipeThrough(new TransformStream(new LineBreakTransformer())).getReader(); - const textEncoderStream = new TextEncoderStream(); - const writerStreamClosed = textEncoderStream.readable.pipeTo(port.writable); - const writer = await textEncoderStream.writable.getWriter(); - - return { reader, writer, readableStreamClosed, writerStreamClosed }; -} - -async function closePortLineBreak(port, reader, writer, readableStreamClosed, writerStreamClosed) { - if (reader) { - reader.cancel(); - } - - if (readableStreamClosed) { - await readableStreamClosed.catch(() => { /* Ignore the error */ }); - } - if (writer) { - writer.close(); - } - - if (writerStreamClosed) { - await writerStreamClosed; - } - - if (port) { - await port.close(); + async writeString(str) { + await this.writeBytes(this.textEncoder.encode(str)); } } diff --git a/assets/js/xymini.js b/assets/js/xymini.js index a1fd1ca..1b1aaec 100644 --- a/assets/js/xymini.js +++ b/assets/js/xymini.js @@ -49,11 +49,11 @@ function crc16(data) { return crc; } -async function detectXYMini(reader) { +async function detectXYMini(serial) { const textDecoder = new TextDecoder(); while (true) { - const { value, done } = await reader.read(); + const value = await serial.readBytes(); if (value[0] == XYMINI_1K_MAGIC) { console.log("XYMini: detected"); @@ -91,14 +91,14 @@ function generateXYMiniBlock(blockId, payload) { return buf; } -async function sendXYMini(portReader, portWriter, data, baudRate = 115200, progressCallback) { +async function sendXYMini(serial, data, progressCallback) { let blockId = 1; let size = data.length; let i = 0; let nakN = 0; let wrongCharN = 0; - await detectXYMini(portReader); + await detectXYMini(serial); while(true) { const payloadSize = Math.min(PAYLOAD_LEN, size); @@ -107,12 +107,12 @@ async function sendXYMini(portReader, portWriter, data, baudRate = 115200, progr const payload = data.slice(i, payloadSize + i); const block = generateXYMiniBlock(blockId, payload); - await portWriter.write(block); + await serial.writeBytes(block); } else { - portWriter.write(new Uint8Array([EOF])); + serial.writeBytes(new Uint8Array([EOF])); } - const { value, done } = await portReader.read(); + const value = await serial.readBytes(); if (value[0] == ACK) { if (!size) { -- cgit v1.2.3