From 4c53bbd9cf16d5e853cfe093114c548384d9a720 Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Mon, 28 Oct 2024 09:21:38 +0100 Subject: [PATCH] fix: detect bootloader in more difficult cases This is a backport from #7325 --- packages/serial/src/ZWaveSerialPortBase.ts | 22 ++++++++++++++++--- .../test/driver/bootloaderDetection.test.ts | 5 +++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/serial/src/ZWaveSerialPortBase.ts b/packages/serial/src/ZWaveSerialPortBase.ts index 0f445df97f77..73e4b4f85057 100644 --- a/packages/serial/src/ZWaveSerialPortBase.ts +++ b/packages/serial/src/ZWaveSerialPortBase.ts @@ -161,9 +161,25 @@ export class ZWaveSerialPortBase extends PassThrough { const str = (data as Buffer).toString("ascii") // like .trim(), but including null bytes .replaceAll(/^[\s\0]+|[\s\0]+$/g, ""); - this.mode = str.startsWith(bootloaderMenuPreamble) - ? ZWaveSerialMode.Bootloader - : ZWaveSerialMode.SerialAPI; + + if (str.startsWith(bootloaderMenuPreamble)) { + // We're sure we're in bootloader mode + this.mode = ZWaveSerialMode.Bootloader; + } else if ( + (data as Buffer).every((b) => + b === 0x00 + || b === 0x0a + || b === 0x0d + || (b >= 0x20 && b <= 0x7e) + ) && (data as Buffer).some((b) => b >= 0x20 && b <= 0x7e) + ) { + // Only printable line breaks, null bytes and at least one printable ASCII character + // --> We're pretty sure we're in bootloader mode + this.mode = ZWaveSerialMode.Bootloader; + } else { + // We're in Serial API mode + this.mode = ZWaveSerialMode.SerialAPI; + } } // On Windows, writing to the parsers immediately seems to lag the event loop diff --git a/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts b/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts index 0f0e02934987..a41f06468f8a 100644 --- a/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts +++ b/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts @@ -19,12 +19,13 @@ integrationTest( // ctrl.length === 1 // && (ctrl[0] === MessageHeaders.NAK || ctrl[0] === 0x32) // ) { + // I've seen logs with as few as 5 bytes in the first chunk self.serial.emitData( - Buffer.from("\0\r\nGecko Bootloa", "ascii"), + Buffer.from("\0\r\nGeck", "ascii"), ); await wait(20); self.serial.emitData(Buffer.from( - `der v2.05.01 + `o Bootloader v2.05.01 1. upload gbl 2. run 3. ebl info