tasmota-webserial-esptool 9.1.8 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,6 +97,7 @@ export declare class ESPLoader extends EventTarget {
97
97
  state_RTS: boolean;
98
98
  setRTS(state: boolean): Promise<void>;
99
99
  setDTR(state: boolean): Promise<void>;
100
+ setDTRandRTS(dtr: boolean, rts: boolean): Promise<void>;
100
101
  /**
101
102
  * @name hardResetUSBJTAGSerial
102
103
  * USB-JTAG/Serial reset for Web Serial (Desktop)
@@ -104,9 +105,14 @@ export declare class ESPLoader extends EventTarget {
104
105
  hardResetUSBJTAGSerial(): Promise<void>;
105
106
  /**
106
107
  * @name hardResetClassic
107
- * Classic reset for Web Serial (Desktop)
108
+ * Classic reset for Web Serial (Desktop) DTR = IO0, RTS = EN
108
109
  */
109
110
  hardResetClassic(): Promise<void>;
111
+ /**
112
+ * @name hardResetUnixTight
113
+ * Unix Tight reset for Web Serial (Desktop) - sets DTR and RTS simultaneously
114
+ */
115
+ hardResetUnixTight(): Promise<void>;
110
116
  setRTSWebUSB(state: boolean): Promise<void>;
111
117
  setDTRWebUSB(state: boolean): Promise<void>;
112
118
  setDTRandRTSWebUSB(dtr: boolean, rts: boolean): Promise<void>;
@@ -25,8 +25,7 @@ export class ESPLoader extends EventTarget {
25
25
  this.__commandLock = Promise.resolve([0, []]);
26
26
  this.__isReconfiguring = false;
27
27
  this.__abandonCurrentOperation = false;
28
- // Adaptive speed adjustment for flash read operations - DISABLED
29
- // Using fixed conservative values that work reliably
28
+ // Adaptive speed adjustment for flash read operations
30
29
  this.__adaptiveBlockMultiplier = 1;
31
30
  this.__adaptiveMaxInFlightMultiplier = 1;
32
31
  this.__consecutiveSuccessfulChunks = 0;
@@ -37,6 +36,7 @@ export class ESPLoader extends EventTarget {
37
36
  this.__writeChain = Promise.resolve();
38
37
  }
39
38
  // Chip properties with parent delegation
39
+ // chipFamily accessed before initialization as designed
40
40
  get chipFamily() {
41
41
  return this._parent ? this._parent.chipFamily : this.__chipFamily;
42
42
  }
@@ -82,7 +82,13 @@ export class ESPLoader extends EventTarget {
82
82
  }
83
83
  }
84
84
  get _inputBuffer() {
85
- return this._parent ? this._parent._inputBuffer : this.__inputBuffer;
85
+ if (this._parent) {
86
+ return this._parent._inputBuffer;
87
+ }
88
+ if (this.__inputBuffer === undefined) {
89
+ throw new Error("_inputBuffer accessed before initialization");
90
+ }
91
+ return this.__inputBuffer;
86
92
  }
87
93
  get _inputBufferReadIndex() {
88
94
  return this._parent
@@ -517,6 +523,14 @@ export class ESPLoader extends EventTarget {
517
523
  this.state_DTR = state;
518
524
  await this.port.setSignals({ dataTerminalReady: state });
519
525
  }
526
+ async setDTRandRTS(dtr, rts) {
527
+ this.state_DTR = dtr;
528
+ this.state_RTS = rts;
529
+ await this.port.setSignals({
530
+ dataTerminalReady: dtr,
531
+ requestToSend: rts,
532
+ });
533
+ }
520
534
  /**
521
535
  * @name hardResetUSBJTAGSerial
522
536
  * USB-JTAG/Serial reset for Web Serial (Desktop)
@@ -538,7 +552,7 @@ export class ESPLoader extends EventTarget {
538
552
  }
539
553
  /**
540
554
  * @name hardResetClassic
541
- * Classic reset for Web Serial (Desktop)
555
+ * Classic reset for Web Serial (Desktop) DTR = IO0, RTS = EN
542
556
  */
543
557
  async hardResetClassic() {
544
558
  await this.setDTR(false); // IO0=HIGH
@@ -550,6 +564,21 @@ export class ESPLoader extends EventTarget {
550
564
  await this.setDTR(false); // IO0=HIGH, done
551
565
  await this.sleep(200);
552
566
  }
567
+ /**
568
+ * @name hardResetUnixTight
569
+ * Unix Tight reset for Web Serial (Desktop) - sets DTR and RTS simultaneously
570
+ */
571
+ async hardResetUnixTight() {
572
+ await this.setDTRandRTS(true, true);
573
+ await this.setDTRandRTS(false, false);
574
+ await this.setDTRandRTS(false, true); // IO0=HIGH & EN=LOW, chip in reset
575
+ await this.sleep(100);
576
+ await this.setDTRandRTS(true, false); // IO0=LOW & EN=HIGH, chip out of reset
577
+ await this.sleep(50);
578
+ await this.setDTRandRTS(false, false); // IO0=HIGH, done
579
+ await this.setDTR(false); // Needed in some environments to ensure IO0=HIGH
580
+ await this.sleep(200);
581
+ }
553
582
  // ============================================================================
554
583
  // WebUSB (Android) - DTR/RTS Signal Handling & Reset Strategies
555
584
  // ============================================================================
@@ -739,10 +768,11 @@ export class ESPLoader extends EventTarget {
739
768
  const resetStrategies = [];
740
769
  // eslint-disable-next-line @typescript-eslint/no-this-alias
741
770
  const self = this;
771
+ // Detect if this is a USB-Serial chip (needs different sync approach)
772
+ const isUSBSerialChip = !isUSBJTAGSerial && !isEspressifUSB;
742
773
  // WebUSB (Android) uses different reset methods than Web Serial (Desktop)
743
774
  if (this.isWebUSB()) {
744
775
  // For USB-Serial chips (CP2102, CH340, etc.), try inverted strategies first
745
- const isUSBSerialChip = !isUSBJTAGSerial && !isEspressifUSB;
746
776
  // Detect specific chip types once
747
777
  const isCP2102 = portInfo.usbVendorId === 0x10c4;
748
778
  const isCH34x = portInfo.usbVendorId === 0x1a86;
@@ -756,28 +786,28 @@ export class ESPLoader extends EventTarget {
756
786
  // Strategy 1: USB-JTAG/Serial (works in CDC mode on Desktop)
757
787
  resetStrategies.push({
758
788
  name: "USB-JTAG/Serial (WebUSB) - ESP32-S2",
759
- fn: async function () {
789
+ fn: async () => {
760
790
  return await self.hardResetUSBJTAGSerialWebUSB();
761
791
  },
762
792
  });
763
793
  // Strategy 2: USB-JTAG/Serial Inverted DTR (works in JTAG mode)
764
794
  resetStrategies.push({
765
795
  name: "USB-JTAG/Serial Inverted DTR (WebUSB) - ESP32-S2",
766
- fn: async function () {
796
+ fn: async () => {
767
797
  return await self.hardResetUSBJTAGSerialInvertedDTRWebUSB();
768
798
  },
769
799
  });
770
800
  // Strategy 3: UnixTight (CDC fallback)
771
801
  resetStrategies.push({
772
802
  name: "UnixTight (WebUSB) - ESP32-S2 CDC",
773
- fn: async function () {
803
+ fn: async () => {
774
804
  return await self.hardResetUnixTightWebUSB();
775
805
  },
776
806
  });
777
807
  // Strategy 4: Classic reset (CDC fallback)
778
808
  resetStrategies.push({
779
809
  name: "Classic (WebUSB) - ESP32-S2 CDC",
780
- fn: async function () {
810
+ fn: async () => {
781
811
  return await self.hardResetClassicWebUSB();
782
812
  },
783
813
  });
@@ -786,19 +816,19 @@ export class ESPLoader extends EventTarget {
786
816
  // Other USB-JTAG chips: Try Inverted DTR first - works best for ESP32-H2 and other JTAG chips
787
817
  resetStrategies.push({
788
818
  name: "USB-JTAG/Serial Inverted DTR (WebUSB)",
789
- fn: async function () {
819
+ fn: async () => {
790
820
  return await self.hardResetUSBJTAGSerialInvertedDTRWebUSB();
791
821
  },
792
822
  });
793
823
  resetStrategies.push({
794
824
  name: "USB-JTAG/Serial (WebUSB)",
795
- fn: async function () {
825
+ fn: async () => {
796
826
  return await self.hardResetUSBJTAGSerialWebUSB();
797
827
  },
798
828
  });
799
829
  resetStrategies.push({
800
830
  name: "Inverted DTR Classic (WebUSB)",
801
- fn: async function () {
831
+ fn: async () => {
802
832
  return await self.hardResetInvertedDTRWebUSB();
803
833
  },
804
834
  });
@@ -810,31 +840,31 @@ export class ESPLoader extends EventTarget {
810
840
  // CH340/CH343: UnixTight works best (like CP2102)
811
841
  resetStrategies.push({
812
842
  name: "UnixTight (WebUSB) - CH34x",
813
- fn: async function () {
843
+ fn: async () => {
814
844
  return await self.hardResetUnixTightWebUSB();
815
845
  },
816
846
  });
817
847
  resetStrategies.push({
818
848
  name: "Classic (WebUSB) - CH34x",
819
- fn: async function () {
849
+ fn: async () => {
820
850
  return await self.hardResetClassicWebUSB();
821
851
  },
822
852
  });
823
853
  resetStrategies.push({
824
854
  name: "Inverted Both (WebUSB) - CH34x",
825
- fn: async function () {
855
+ fn: async () => {
826
856
  return await self.hardResetInvertedWebUSB();
827
857
  },
828
858
  });
829
859
  resetStrategies.push({
830
860
  name: "Inverted RTS (WebUSB) - CH34x",
831
- fn: async function () {
861
+ fn: async () => {
832
862
  return await self.hardResetInvertedRTSWebUSB();
833
863
  },
834
864
  });
835
865
  resetStrategies.push({
836
866
  name: "Inverted DTR (WebUSB) - CH34x",
837
- fn: async function () {
867
+ fn: async () => {
838
868
  return await self.hardResetInvertedDTRWebUSB();
839
869
  },
840
870
  });
@@ -844,31 +874,31 @@ export class ESPLoader extends EventTarget {
844
874
  // Try it first, then fallback to other strategies
845
875
  resetStrategies.push({
846
876
  name: "UnixTight (WebUSB) - CP2102",
847
- fn: async function () {
877
+ fn: async () => {
848
878
  return await self.hardResetUnixTightWebUSB();
849
879
  },
850
880
  });
851
881
  resetStrategies.push({
852
882
  name: "Classic (WebUSB) - CP2102",
853
- fn: async function () {
883
+ fn: async () => {
854
884
  return await self.hardResetClassicWebUSB();
855
885
  },
856
886
  });
857
887
  resetStrategies.push({
858
888
  name: "Inverted Both (WebUSB) - CP2102",
859
- fn: async function () {
889
+ fn: async () => {
860
890
  return await self.hardResetInvertedWebUSB();
861
891
  },
862
892
  });
863
893
  resetStrategies.push({
864
894
  name: "Inverted RTS (WebUSB) - CP2102",
865
- fn: async function () {
895
+ fn: async () => {
866
896
  return await self.hardResetInvertedRTSWebUSB();
867
897
  },
868
898
  });
869
899
  resetStrategies.push({
870
900
  name: "Inverted DTR (WebUSB) - CP2102",
871
- fn: async function () {
901
+ fn: async () => {
872
902
  return await self.hardResetInvertedDTRWebUSB();
873
903
  },
874
904
  });
@@ -877,7 +907,7 @@ export class ESPLoader extends EventTarget {
877
907
  // For other USB-Serial chips, try UnixTight first, then multiple strategies
878
908
  resetStrategies.push({
879
909
  name: "UnixTight (WebUSB)",
880
- fn: async function () {
910
+ fn: async () => {
881
911
  return await self.hardResetUnixTightWebUSB();
882
912
  },
883
913
  });
@@ -951,7 +981,6 @@ export class ESPLoader extends EventTarget {
951
981
  }
952
982
  }
953
983
  else {
954
- // Web Serial (Desktop) strategies
955
984
  // Strategy: USB-JTAG/Serial reset
956
985
  if (isUSBJTAGSerial || isEspressifUSB) {
957
986
  resetStrategies.push({
@@ -961,11 +990,11 @@ export class ESPLoader extends EventTarget {
961
990
  },
962
991
  });
963
992
  }
964
- // Strategy: Classic reset
993
+ // Strategy: UnixTight reset
965
994
  resetStrategies.push({
966
- name: "Classic",
995
+ name: "UnixTight",
967
996
  fn: async function () {
968
- return await self.hardResetClassic();
997
+ return await self.hardResetUnixTight();
969
998
  },
970
999
  });
971
1000
  // Strategy: USB-JTAG/Serial fallback
@@ -990,15 +1019,38 @@ export class ESPLoader extends EventTarget {
990
1019
  // Clear abandon flag before starting new strategy
991
1020
  this._abandonCurrentOperation = false;
992
1021
  await strategy.fn();
993
- // Try to sync after reset with internally time-bounded sync (3 seconds per strategy)
994
- const syncSuccess = await this.syncWithTimeout(3000);
995
- if (syncSuccess) {
996
- // Sync succeeded
997
- this.logger.log(`Connected successfully with ${strategy.name} reset.`);
998
- return;
1022
+ // Try to sync after reset
1023
+ // USB-Serial / native USB chips needs different sync approaches
1024
+ if (isUSBSerialChip) {
1025
+ // USB-Serial chips: Use timeout strategy (2 seconds)
1026
+ // this.logger.log(`USB-Serial chip detected, using sync with timeout.`);
1027
+ const syncSuccess = await this.syncWithTimeout(2000);
1028
+ if (syncSuccess) {
1029
+ // Sync succeeded
1030
+ this.logger.log(`Connected USB Serial successfully with ${strategy.name} reset.`);
1031
+ return;
1032
+ }
1033
+ else {
1034
+ throw new Error("Sync timeout or abandoned");
1035
+ }
999
1036
  }
1000
1037
  else {
1001
- throw new Error("Sync timeout or abandoned");
1038
+ // Native USB chips
1039
+ // Note: We use Promise.race with sync() directly instead of syncWithTimeout()
1040
+ // because syncWithTimeout causes CDC/JTAG devices to hang for unknown reasons.
1041
+ // The abandon flag in readPacket() prevents overlapping I/O.
1042
+ // this.logger.log(`Native USB chip detected, using CDC/JTAG sync.`);
1043
+ const syncPromise = this.sync();
1044
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Sync timeout")), 1000));
1045
+ try {
1046
+ await Promise.race([syncPromise, timeoutPromise]);
1047
+ // Sync succeeded
1048
+ this.logger.log(`Connected CDC/JTAG successfully with ${strategy.name} reset.`);
1049
+ return;
1050
+ }
1051
+ catch (error) {
1052
+ throw new Error("Sync timeout or abandoned");
1053
+ }
1002
1054
  }
1003
1055
  }
1004
1056
  catch (error) {
@@ -1046,9 +1098,9 @@ export class ESPLoader extends EventTarget {
1046
1098
  // just reset (no bootloader mode)
1047
1099
  if (this.isWebUSB()) {
1048
1100
  // WebUSB: Use longer delays for better compatibility
1049
- await this.setRTS(true); // EN->LOW
1101
+ await this.setRTSWebUSB(true); // EN->LOW
1050
1102
  await this.sleep(200);
1051
- await this.setRTS(false);
1103
+ await this.setRTSWebUSB(false);
1052
1104
  await this.sleep(200);
1053
1105
  this.logger.log("Hard reset (WebUSB).");
1054
1106
  }
@@ -2171,7 +2223,15 @@ export class ESPLoader extends EventTarget {
2171
2223
  resolve(undefined);
2172
2224
  return;
2173
2225
  }
2174
- this.addEventListener("disconnect", resolve, { once: true });
2226
+ // Set a timeout to prevent hanging (important for node-usb)
2227
+ const timeout = setTimeout(() => {
2228
+ this.logger.debug("Disconnect timeout - forcing resolution");
2229
+ resolve(undefined);
2230
+ }, 1000);
2231
+ this.addEventListener("disconnect", () => {
2232
+ clearTimeout(timeout);
2233
+ resolve(undefined);
2234
+ }, { once: true });
2175
2235
  // Only cancel if reader is still active
2176
2236
  try {
2177
2237
  this._reader.cancel();
@@ -2179,10 +2239,19 @@ export class ESPLoader extends EventTarget {
2179
2239
  catch (err) {
2180
2240
  this.logger.debug(`Reader cancel error: ${err}`);
2181
2241
  // Reader already released, resolve immediately
2242
+ clearTimeout(timeout);
2182
2243
  resolve(undefined);
2183
2244
  }
2184
2245
  });
2185
2246
  this.connected = false;
2247
+ // Close the port (important for node-usb adapter)
2248
+ try {
2249
+ await this.port.close();
2250
+ this.logger.debug("Port closed successfully");
2251
+ }
2252
+ catch (err) {
2253
+ this.logger.debug(`Port close error: ${err}`);
2254
+ }
2186
2255
  }
2187
2256
  /**
2188
2257
  * @name reconnectAndResume
@@ -2701,6 +2770,10 @@ class EspStubLoader extends ESPLoader {
2701
2770
  if (size > maxValue) {
2702
2771
  throw new Error(`Size ${size} exceeds maximum value ${maxValue}`);
2703
2772
  }
2773
+ // Check for wrap-around
2774
+ if (offset + size > maxValue) {
2775
+ throw new Error(`Region end (offset + size = ${offset + size}) exceeds maximum addressable range ${maxValue}`);
2776
+ }
2704
2777
  const timeout = timeoutPerMb(ERASE_REGION_TIMEOUT_PER_MB, size);
2705
2778
  const buffer = pack("<II", offset, size);
2706
2779
  await this.checkCommand(ESP_ERASE_REGION, buffer, 0, timeout);
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ import { Logger } from "./const";
2
2
  import { ESPLoader } from "./esp_loader";
3
3
  export type { Logger } from "./const";
4
4
  export { ESPLoader } from "./esp_loader";
5
- export { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP8266, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31, } from "./const";
5
+ export { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP8266, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31, ESP_FLASH_BEGIN, ESP_FLASH_DATA, ESP_FLASH_END, ESP_MEM_BEGIN, ESP_MEM_END, ESP_MEM_DATA, ESP_SYNC, ESP_WRITE_REG, ESP_READ_REG, ESP_ERASE_FLASH, ESP_ERASE_REGION, ESP_READ_FLASH, ESP_SPI_SET_PARAMS, ESP_SPI_ATTACH, ESP_CHANGE_BAUDRATE, ESP_SPI_FLASH_MD5, ESP_GET_SECURITY_INFO, ESP_CHECKSUM_MAGIC, ESP_FLASH_DEFL_BEGIN, ESP_FLASH_DEFL_DATA, ESP_FLASH_DEFL_END, ROM_INVALID_RECV_MSG, USB_RAM_BLOCK, ESP_RAM_BLOCK, DEFAULT_TIMEOUT, CHIP_ERASE_TIMEOUT, MAX_TIMEOUT, SYNC_TIMEOUT, ERASE_REGION_TIMEOUT_PER_MB, MEM_END_ROM_TIMEOUT, FLASH_READ_TIMEOUT, } from "./const";
6
6
  export declare const connect: (logger: Logger) => Promise<ESPLoader>;
7
7
  export declare const connectWithPort: (port: SerialPort, logger: Logger) => Promise<ESPLoader>;
package/dist/index.js CHANGED
@@ -2,30 +2,34 @@
2
2
  import { ESP_ROM_BAUD } from "./const";
3
3
  import { ESPLoader } from "./esp_loader";
4
4
  export { ESPLoader } from "./esp_loader";
5
- export { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP8266, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31, } from "./const";
5
+ export { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMILY_ESP8266, CHIP_FAMILY_ESP32C2, CHIP_FAMILY_ESP32C3, CHIP_FAMILY_ESP32C5, CHIP_FAMILY_ESP32C6, CHIP_FAMILY_ESP32C61, CHIP_FAMILY_ESP32H2, CHIP_FAMILY_ESP32H4, CHIP_FAMILY_ESP32H21, CHIP_FAMILY_ESP32P4, CHIP_FAMILY_ESP32S31,
6
+ // Command constants
7
+ ESP_FLASH_BEGIN, ESP_FLASH_DATA, ESP_FLASH_END, ESP_MEM_BEGIN, ESP_MEM_END, ESP_MEM_DATA, ESP_SYNC, ESP_WRITE_REG, ESP_READ_REG, ESP_ERASE_FLASH, ESP_ERASE_REGION, ESP_READ_FLASH, ESP_SPI_SET_PARAMS, ESP_SPI_ATTACH, ESP_CHANGE_BAUDRATE, ESP_SPI_FLASH_MD5, ESP_GET_SECURITY_INFO, ESP_CHECKSUM_MAGIC, ESP_FLASH_DEFL_BEGIN, ESP_FLASH_DEFL_DATA, ESP_FLASH_DEFL_END, ROM_INVALID_RECV_MSG,
8
+ // Block size constants
9
+ USB_RAM_BLOCK, ESP_RAM_BLOCK,
10
+ // Timeout constants
11
+ DEFAULT_TIMEOUT, CHIP_ERASE_TIMEOUT, MAX_TIMEOUT, SYNC_TIMEOUT, ERASE_REGION_TIMEOUT_PER_MB, MEM_END_ROM_TIMEOUT, FLASH_READ_TIMEOUT, } from "./const";
6
12
  export const connect = async (logger) => {
13
+ // - Request a port and open a connection.
14
+ // Try to use requestSerialPort if available (supports WebUSB for Android)
7
15
  let port;
8
- // Check if a custom requestSerialPort function is available (e.g., from WebUSB wrapper)
9
16
  const customRequestPort = globalThis.requestSerialPort;
10
17
  if (typeof customRequestPort === "function") {
11
- // Use custom port request function (handles Android/WebUSB automatically)
12
- logger.log("Using custom port request function");
13
18
  port = await customRequestPort();
14
19
  }
15
20
  else {
16
- // Fallback to standard Web Serial API
21
+ // Check if Web Serial API is available
17
22
  if (!navigator.serial) {
18
23
  throw new Error("Web Serial API is not supported in this browser. " +
19
- "Please use Chrome 89+, Edge 89+, or Opera on desktop, or Chrome 61+ on Android with USB OTG. " +
24
+ "Please use Chrome, Edge, or Opera on desktop, or Chrome on Android. " +
20
25
  "Note: The page must be served over HTTPS or localhost.");
21
26
  }
22
27
  port = await navigator.serial.requestPort();
23
28
  }
24
- // Only open if not already open (WebUSB may return an opened port)
29
+ // Only open if not already open (requestSerialPort may return an opened port)
25
30
  if (!port.readable || !port.writable) {
26
31
  await port.open({ baudRate: ESP_ROM_BAUD });
27
32
  }
28
- logger.log("Connected successfully.");
29
33
  return new ESPLoader(port, logger);
30
34
  };
31
35
  export const connectWithPort = async (port, logger) => {
@@ -33,10 +37,9 @@ export const connectWithPort = async (port, logger) => {
33
37
  if (!port) {
34
38
  throw new Error("Port is required");
35
39
  }
36
- // Only open if not already open
40
+ // Check if port is already open, if not open it
37
41
  if (!port.readable || !port.writable) {
38
42
  await port.open({ baudRate: ESP_ROM_BAUD });
39
43
  }
40
- logger.log("Connected successfully.");
41
44
  return new ESPLoader(port, logger);
42
45
  };