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.
- package/dist/esp_loader.d.ts +7 -1
- package/dist/esp_loader.js +110 -37
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -10
- package/dist/web/index.js +1 -1
- package/js/modules/esptool.js +1 -1
- package/js/script.js +31 -2
- package/js/webusb-serial.js +9 -19
- package/package.json +1 -1
- package/src/esp_loader.ts +128 -40
- package/src/index.ts +40 -13
package/dist/esp_loader.d.ts
CHANGED
|
@@ -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>;
|
package/dist/esp_loader.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
993
|
+
// Strategy: UnixTight reset
|
|
965
994
|
resetStrategies.push({
|
|
966
|
-
name: "
|
|
995
|
+
name: "UnixTight",
|
|
967
996
|
fn: async function () {
|
|
968
|
-
return await self.
|
|
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
|
|
994
|
-
|
|
995
|
-
if (
|
|
996
|
-
//
|
|
997
|
-
this.logger.log(`
|
|
998
|
-
|
|
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
|
-
|
|
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.
|
|
1101
|
+
await this.setRTSWebUSB(true); // EN->LOW
|
|
1050
1102
|
await this.sleep(200);
|
|
1051
|
-
await this.
|
|
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
|
-
|
|
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,
|
|
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
|
-
//
|
|
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
|
|
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 (
|
|
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
|
-
//
|
|
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
|
};
|