From 93091f5cd0567832316171a1a3ec5f69c779c85a Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Sun, 27 Oct 2024 22:13:08 +0100 Subject: [PATCH] fix: detect bootloader in more difficult cases --- .../src/serialport/ZWaveSerialPortBase.ts | 22 ++++++++++++++++--- .../test/driver/bootloaderDetection.test.ts | 7 +++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/serial/src/serialport/ZWaveSerialPortBase.ts b/packages/serial/src/serialport/ZWaveSerialPortBase.ts index 50bf85b7ae8b..2c880173e0f3 100644 --- a/packages/serial/src/serialport/ZWaveSerialPortBase.ts +++ b/packages/serial/src/serialport/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 3d36d73752c3..537768a09b6f 100644 --- a/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts +++ b/packages/zwave-js/src/lib/test/driver/bootloaderDetection.test.ts @@ -6,7 +6,7 @@ integrationTest( "The bootloader is detected when received in smaller chunks", { // Reproduction for issue #7316 - // debug: true, + debug: true, additionalDriverOptions: { allowBootloaderOnly: true, @@ -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