tasmota-webserial-esptool 7.1.0 → 7.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/README.md +1 -1
- package/css/style.css +95 -0
- package/dist/const.js +0 -24
- package/dist/esp_loader.d.ts +2 -0
- package/dist/esp_loader.js +37 -46
- package/dist/web/index.js +1 -1
- package/index.html +12 -1
- package/js/modules/esptool.js +1 -1
- package/js/script.js +64 -1
- package/package.json +7 -7
- package/src/const.ts +0 -24
- package/src/esp_loader.ts +46 -58
- package/.prettierignore +0 -1
- package/rollup.config.js +0 -27
- package/tsconfig.json +0 -20
package/README.md
CHANGED
package/css/style.css
CHANGED
|
@@ -70,6 +70,24 @@
|
|
|
70
70
|
color: #000;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
.header button.highlight {
|
|
74
|
+
background-color: #ff6b00;
|
|
75
|
+
border-color: #ff6b00;
|
|
76
|
+
color: #fff;
|
|
77
|
+
animation: pulse 1.5s infinite;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@keyframes pulse {
|
|
81
|
+
0%, 100% {
|
|
82
|
+
transform: scale(1);
|
|
83
|
+
box-shadow: 0 0 0 0 rgba(255, 107, 0, 0.7);
|
|
84
|
+
}
|
|
85
|
+
50% {
|
|
86
|
+
transform: scale(1.05);
|
|
87
|
+
box-shadow: 0 0 0 10px rgba(255, 107, 0, 0);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
.header select {
|
|
74
92
|
height: 30px;
|
|
75
93
|
}
|
|
@@ -550,3 +568,80 @@ div.clear {
|
|
|
550
568
|
.center {
|
|
551
569
|
text-align: center;
|
|
552
570
|
}
|
|
571
|
+
|
|
572
|
+
/* ESP32-S2 Reconnect Modal */
|
|
573
|
+
.modal {
|
|
574
|
+
display: flex;
|
|
575
|
+
position: fixed;
|
|
576
|
+
z-index: 9999;
|
|
577
|
+
left: 0;
|
|
578
|
+
top: 0;
|
|
579
|
+
width: 100%;
|
|
580
|
+
height: 100%;
|
|
581
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
582
|
+
align-items: center;
|
|
583
|
+
justify-content: center;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.modal.hidden {
|
|
587
|
+
display: none;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.modal-content {
|
|
591
|
+
background-color: #fff;
|
|
592
|
+
padding: 40px;
|
|
593
|
+
border-radius: 15px;
|
|
594
|
+
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.3);
|
|
595
|
+
text-align: center;
|
|
596
|
+
max-width: 500px;
|
|
597
|
+
animation: modalSlideIn 0.3s ease-out;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
@keyframes modalSlideIn {
|
|
601
|
+
from {
|
|
602
|
+
transform: translateY(-50px);
|
|
603
|
+
opacity: 0;
|
|
604
|
+
}
|
|
605
|
+
to {
|
|
606
|
+
transform: translateY(0);
|
|
607
|
+
opacity: 1;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.modal-content h2 {
|
|
612
|
+
color: #4a4a4a;
|
|
613
|
+
margin-top: 0;
|
|
614
|
+
font-size: 24px;
|
|
615
|
+
margin-bottom: 20px;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.modal-content p {
|
|
619
|
+
font-size: 16px;
|
|
620
|
+
line-height: 1.6;
|
|
621
|
+
margin: 15px 0;
|
|
622
|
+
color: #333;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.modal-button {
|
|
626
|
+
background-color: #fff;
|
|
627
|
+
color: #6b6b6b;
|
|
628
|
+
border: 2px solid #6b6b6b;
|
|
629
|
+
padding: 12px 40px;
|
|
630
|
+
font-size: 18px;
|
|
631
|
+
font-weight: 600;
|
|
632
|
+
border-radius: 25px;
|
|
633
|
+
cursor: pointer;
|
|
634
|
+
margin-top: 20px;
|
|
635
|
+
transition: background-color 0.2s, color 0.2s, border-color 0.2s;
|
|
636
|
+
display: inline-flex;
|
|
637
|
+
align-items: center;
|
|
638
|
+
justify-content: center;
|
|
639
|
+
line-height: normal;
|
|
640
|
+
text-align: center;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.modal-button:hover {
|
|
644
|
+
background-color: #71ae1e;
|
|
645
|
+
color: #fff;
|
|
646
|
+
border-color: #71ae1e;
|
|
647
|
+
}
|
package/dist/const.js
CHANGED
|
@@ -244,30 +244,6 @@ export const CHIP_DETECT_MAGIC_VALUES = {
|
|
|
244
244
|
0xfff0c101: { name: "ESP8266", family: CHIP_FAMILY_ESP8266 },
|
|
245
245
|
0x00f01d83: { name: "ESP32", family: CHIP_FAMILY_ESP32 },
|
|
246
246
|
0x000007c6: { name: "ESP32-S2", family: CHIP_FAMILY_ESP32S2 },
|
|
247
|
-
0x9: { name: "ESP32-S3", family: CHIP_FAMILY_ESP32S3 },
|
|
248
|
-
0x0c21e06f: { name: "ESP32-C2", family: CHIP_FAMILY_ESP32C2 },
|
|
249
|
-
0x6f51306f: { name: "ESP32-C2", family: CHIP_FAMILY_ESP32C2 },
|
|
250
|
-
0x7c41a06f: { name: "ESP32-C2", family: CHIP_FAMILY_ESP32C2 },
|
|
251
|
-
0x1b31506f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
|
252
|
-
0x4361606f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
|
253
|
-
0x4881606f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
|
254
|
-
0x6921506f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
|
255
|
-
0x1101406f: { name: "ESP32-C5", family: CHIP_FAMILY_ESP32C5 },
|
|
256
|
-
0x5fd1406f: { name: "ESP32-C5", family: CHIP_FAMILY_ESP32C5 },
|
|
257
|
-
0x5c501458: { name: "ESP32-C5", family: CHIP_FAMILY_ESP32C5 },
|
|
258
|
-
0x63e1406f: { name: "ESP32-C5", family: CHIP_FAMILY_ESP32C5 },
|
|
259
|
-
0x2ce0806f: { name: "ESP32-C6", family: CHIP_FAMILY_ESP32C6 },
|
|
260
|
-
0x2421606f: { name: "ESP32-C61", family: CHIP_FAMILY_ESP32C61 },
|
|
261
|
-
0x33f0206f: { name: "ESP32-C61", family: CHIP_FAMILY_ESP32C61 },
|
|
262
|
-
0x4f81606f: { name: "ESP32-C61", family: CHIP_FAMILY_ESP32C61 },
|
|
263
|
-
0x7211606f: { name: "ESP32-C61", family: CHIP_FAMILY_ESP32C61 },
|
|
264
|
-
0x97e30068: { name: "ESP32-H2", family: CHIP_FAMILY_ESP32H2 },
|
|
265
|
-
0xd7b73e80: { name: "ESP32-H2", family: CHIP_FAMILY_ESP32H2 },
|
|
266
|
-
// ESP32-P4 old revisions (< Rev. 300) - use magic value detection
|
|
267
|
-
// Rev. 300+ uses IMAGE_CHIP_ID detection instead
|
|
268
|
-
0x0: { name: "ESP32-P4", family: CHIP_FAMILY_ESP32P4 },
|
|
269
|
-
0x7039ad9: { name: "ESP32-P4", family: CHIP_FAMILY_ESP32P4 },
|
|
270
|
-
0x0addbad0: { name: "ESP32-P4", family: CHIP_FAMILY_ESP32P4 },
|
|
271
247
|
};
|
|
272
248
|
// Commands supported by ESP8266 ROM bootloader
|
|
273
249
|
export const ESP_FLASH_BEGIN = 0x02;
|
package/dist/esp_loader.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare class ESPLoader extends EventTarget {
|
|
|
18
18
|
private _currentBaudRate;
|
|
19
19
|
private _maxUSBSerialBaudrate?;
|
|
20
20
|
private _reader?;
|
|
21
|
+
private _isESP32S2NativeUSB;
|
|
22
|
+
private _initializationSucceeded;
|
|
21
23
|
constructor(port: SerialPort, logger: Logger, _parent?: ESPLoader | undefined);
|
|
22
24
|
private get _inputBuffer();
|
|
23
25
|
private get _totalBytesRead();
|
package/dist/esp_loader.js
CHANGED
|
@@ -21,6 +21,8 @@ export class ESPLoader extends EventTarget {
|
|
|
21
21
|
this.connected = true;
|
|
22
22
|
this.flashSize = null;
|
|
23
23
|
this._currentBaudRate = ESP_ROM_BAUD;
|
|
24
|
+
this._isESP32S2NativeUSB = false;
|
|
25
|
+
this._initializationSucceeded = false;
|
|
24
26
|
this.state_DTR = false;
|
|
25
27
|
}
|
|
26
28
|
get _inputBuffer() {
|
|
@@ -44,8 +46,13 @@ export class ESPLoader extends EventTarget {
|
|
|
44
46
|
const chips = {
|
|
45
47
|
0x1a86: {
|
|
46
48
|
// QinHeng Electronics
|
|
49
|
+
0x7522: { name: "CH340", maxBaudrate: 460800 },
|
|
47
50
|
0x7523: { name: "CH340", maxBaudrate: 460800 },
|
|
51
|
+
0x7584: { name: "CH340", maxBaudrate: 460800 },
|
|
52
|
+
0x5523: { name: "CH341", maxBaudrate: 2000000 },
|
|
53
|
+
0x55d3: { name: "CH343", maxBaudrate: 6000000 },
|
|
48
54
|
0x55d4: { name: "CH9102", maxBaudrate: 6000000 },
|
|
55
|
+
0x55d8: { name: "CH9101", maxBaudrate: 3000000 },
|
|
49
56
|
},
|
|
50
57
|
0x10c4: {
|
|
51
58
|
// Silicon Labs
|
|
@@ -92,6 +99,10 @@ export class ESPLoader extends EventTarget {
|
|
|
92
99
|
this._maxUSBSerialBaudrate = chipInfo.maxBaudrate;
|
|
93
100
|
this.logger.log(`Max baudrate: ${chipInfo.maxBaudrate}`);
|
|
94
101
|
}
|
|
102
|
+
// Detect ESP32-S2 Native USB
|
|
103
|
+
if (portInfo.usbVendorId === 0x303a && portInfo.usbProductId === 0x2) {
|
|
104
|
+
this._isESP32S2NativeUSB = true;
|
|
105
|
+
}
|
|
95
106
|
}
|
|
96
107
|
// Don't await this promise so it doesn't block rest of method.
|
|
97
108
|
this.readLoop();
|
|
@@ -109,6 +120,8 @@ export class ESPLoader extends EventTarget {
|
|
|
109
120
|
}
|
|
110
121
|
this.logger.log(`Chip type ${this.chipName}`);
|
|
111
122
|
this.logger.debug(`Bootloader flash offset: 0x${FlAddr.flashOffs.toString(16)}`);
|
|
123
|
+
// Mark initialization as successful
|
|
124
|
+
this._initializationSucceeded = true;
|
|
112
125
|
}
|
|
113
126
|
/**
|
|
114
127
|
* Detect chip type using GET_SECURITY_INFO (for newer chips) or magic value (for older chips)
|
|
@@ -154,7 +167,7 @@ export class ESPLoader extends EventTarget {
|
|
|
154
167
|
this.logger.debug(`Re-sync after GET_SECURITY_INFO failure: ${syncErr}`);
|
|
155
168
|
}
|
|
156
169
|
}
|
|
157
|
-
// Fallback: Use magic value detection for ESP8266, ESP32, ESP32-S2
|
|
170
|
+
// Fallback: Use magic value detection for ESP8266, ESP32, ESP32-S2
|
|
158
171
|
const chipMagicValue = await this.readRegister(CHIP_DETECT_MAGIC_REG_ADDR);
|
|
159
172
|
const chip = CHIP_DETECT_MAGIC_VALUES[chipMagicValue >>> 0];
|
|
160
173
|
if (chip === undefined) {
|
|
@@ -162,7 +175,6 @@ export class ESPLoader extends EventTarget {
|
|
|
162
175
|
}
|
|
163
176
|
this.chipName = chip.name;
|
|
164
177
|
this.chipFamily = chip.family;
|
|
165
|
-
// For ESP32-P4 detected via magic value (old revisions), set variant
|
|
166
178
|
if (this.chipFamily === CHIP_FAMILY_ESP32P4) {
|
|
167
179
|
this.chipRevision = await this.getChipRevision();
|
|
168
180
|
this.logger.debug(`ESP32-P4 revision: ${this.chipRevision}`);
|
|
@@ -256,6 +268,14 @@ export class ESPLoader extends EventTarget {
|
|
|
256
268
|
}
|
|
257
269
|
// Disconnected!
|
|
258
270
|
this.connected = false;
|
|
271
|
+
// Check if this is ESP32-S2 Native USB that needs port reselection
|
|
272
|
+
// Only trigger reconnect if initialization did NOT succeed (wrong port)
|
|
273
|
+
if (this._isESP32S2NativeUSB && !this._initializationSucceeded) {
|
|
274
|
+
this.logger.log("ESP32-S2 Native USB detected - requesting port reselection");
|
|
275
|
+
this.dispatchEvent(new CustomEvent("esp32s2-usb-reconnect", {
|
|
276
|
+
detail: { message: "ESP32-S2 Native USB requires port reselection" },
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
259
279
|
this.dispatchEvent(new Event("disconnect"));
|
|
260
280
|
this.logger.debug("Finished read loop");
|
|
261
281
|
}
|
|
@@ -907,7 +927,7 @@ export class ESPLoader extends EventTarget {
|
|
|
907
927
|
}
|
|
908
928
|
async setDataLengths(spiAddresses, mosiBits, misoBits) {
|
|
909
929
|
if (spiAddresses.mosiDlenOffs != -1) {
|
|
910
|
-
//
|
|
930
|
+
// Actual MCUs have a more sophisticated way to set up "user" commands
|
|
911
931
|
const SPI_MOSI_DLEN_REG = spiAddresses.regBase + spiAddresses.mosiDlenOffs;
|
|
912
932
|
const SPI_MISO_DLEN_REG = spiAddresses.regBase + spiAddresses.misoDlenOffs;
|
|
913
933
|
if (mosiBits > 0) {
|
|
@@ -948,7 +968,7 @@ export class ESPLoader extends EventTarget {
|
|
|
948
968
|
const SPI_USR_COMMAND = 1 << 31;
|
|
949
969
|
const SPI_USR_MISO = 1 << 28;
|
|
950
970
|
const SPI_USR_MOSI = 1 << 27;
|
|
951
|
-
// SPI registers, base address differs
|
|
971
|
+
// SPI registers, base address differs
|
|
952
972
|
const spiAddresses = getSpiFlashAddresses(this.getChipFamily());
|
|
953
973
|
const base = spiAddresses.regBase;
|
|
954
974
|
const SPI_CMD_REG = base;
|
|
@@ -1100,6 +1120,10 @@ export class ESPLoader extends EventTarget {
|
|
|
1100
1120
|
return espStubLoader;
|
|
1101
1121
|
}
|
|
1102
1122
|
async writeToStream(data) {
|
|
1123
|
+
if (!this.port.writable) {
|
|
1124
|
+
this.logger.debug("Port writable stream not available, skipping write");
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1103
1127
|
const writer = this.port.writable.getWriter();
|
|
1104
1128
|
await writer.write(new Uint8Array(data));
|
|
1105
1129
|
try {
|
|
@@ -1114,6 +1138,10 @@ export class ESPLoader extends EventTarget {
|
|
|
1114
1138
|
await this._parent.disconnect();
|
|
1115
1139
|
return;
|
|
1116
1140
|
}
|
|
1141
|
+
if (!this.port.writable) {
|
|
1142
|
+
this.logger.debug("Port already closed, skipping disconnect");
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1117
1145
|
await this.port.writable.getWriter().close();
|
|
1118
1146
|
await new Promise((resolve) => {
|
|
1119
1147
|
if (!this._reader) {
|
|
@@ -1146,7 +1174,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1146
1174
|
}
|
|
1147
1175
|
this._reader = undefined;
|
|
1148
1176
|
}
|
|
1149
|
-
await sleep(SYNC_TIMEOUT);
|
|
1150
1177
|
// Close port
|
|
1151
1178
|
try {
|
|
1152
1179
|
await this.port.close();
|
|
@@ -1155,8 +1182,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1155
1182
|
catch (err) {
|
|
1156
1183
|
this.logger.debug(`Port close error: ${err}`);
|
|
1157
1184
|
}
|
|
1158
|
-
// Wait for port to fully close
|
|
1159
|
-
await sleep(SYNC_TIMEOUT);
|
|
1160
1185
|
// Open the port
|
|
1161
1186
|
this.logger.debug("Opening port...");
|
|
1162
1187
|
try {
|
|
@@ -1166,8 +1191,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1166
1191
|
catch (err) {
|
|
1167
1192
|
throw new Error(`Failed to open port: ${err}`);
|
|
1168
1193
|
}
|
|
1169
|
-
// Wait for port to be fully ready
|
|
1170
|
-
await sleep(SYNC_TIMEOUT);
|
|
1171
1194
|
// Verify port streams are available
|
|
1172
1195
|
if (!this.port.readable || !this.port.writable) {
|
|
1173
1196
|
throw new Error(`Port streams not available after open (readable: ${!!this.port.readable}, writable: ${!!this.port.writable})`);
|
|
@@ -1178,7 +1201,7 @@ export class ESPLoader extends EventTarget {
|
|
|
1178
1201
|
const savedChipRevision = this.chipRevision;
|
|
1179
1202
|
const savedChipVariant = this.chipVariant;
|
|
1180
1203
|
const savedFlashSize = this.flashSize;
|
|
1181
|
-
// Reinitialize
|
|
1204
|
+
// Reinitialize
|
|
1182
1205
|
await this.hardReset(true);
|
|
1183
1206
|
if (!this._parent) {
|
|
1184
1207
|
this.__inputBuffer = [];
|
|
@@ -1187,7 +1210,7 @@ export class ESPLoader extends EventTarget {
|
|
|
1187
1210
|
}
|
|
1188
1211
|
await this.flushSerialBuffers();
|
|
1189
1212
|
await this.sync();
|
|
1190
|
-
// Restore chip info
|
|
1213
|
+
// Restore chip info
|
|
1191
1214
|
this.chipFamily = savedChipFamily;
|
|
1192
1215
|
this.chipName = savedChipName;
|
|
1193
1216
|
this.chipRevision = savedChipRevision;
|
|
@@ -1198,14 +1221,12 @@ export class ESPLoader extends EventTarget {
|
|
|
1198
1221
|
if (!this.port.writable || !this.port.readable) {
|
|
1199
1222
|
throw new Error("Port not ready after reconnect");
|
|
1200
1223
|
}
|
|
1201
|
-
// Load stub
|
|
1224
|
+
// Load stub
|
|
1202
1225
|
const stubLoader = await this.runStub(true);
|
|
1203
1226
|
this.logger.debug("Stub loaded");
|
|
1204
1227
|
// Restore baudrate if it was changed
|
|
1205
1228
|
if (this._currentBaudRate !== ESP_ROM_BAUD) {
|
|
1206
1229
|
await stubLoader.setBaudrate(this._currentBaudRate);
|
|
1207
|
-
// Wait for port to be ready after baudrate change
|
|
1208
|
-
await sleep(SYNC_TIMEOUT);
|
|
1209
1230
|
// Verify port is still ready after baudrate change
|
|
1210
1231
|
if (!this.port.writable || !this.port.readable) {
|
|
1211
1232
|
throw new Error(`Port not ready after baudrate change (readable: ${!!this.port.readable}, writable: ${!!this.port.writable})`);
|
|
@@ -1223,18 +1244,12 @@ export class ESPLoader extends EventTarget {
|
|
|
1223
1244
|
* This clears both the application RX buffer and waits for hardware buffers to drain
|
|
1224
1245
|
*/
|
|
1225
1246
|
async flushSerialBuffers() {
|
|
1226
|
-
// Clear application
|
|
1247
|
+
// Clear application buffer
|
|
1227
1248
|
if (!this._parent) {
|
|
1228
1249
|
this.__inputBuffer = [];
|
|
1229
1250
|
}
|
|
1230
|
-
// Wait for any pending
|
|
1251
|
+
// Wait for any pending data
|
|
1231
1252
|
await sleep(SYNC_TIMEOUT);
|
|
1232
|
-
// Clear RX buffer again
|
|
1233
|
-
if (!this._parent) {
|
|
1234
|
-
this.__inputBuffer = [];
|
|
1235
|
-
}
|
|
1236
|
-
// Wait longer to ensure all stale data has been received and discarded
|
|
1237
|
-
await sleep(SYNC_TIMEOUT * 2);
|
|
1238
1253
|
// Final clear
|
|
1239
1254
|
if (!this._parent) {
|
|
1240
1255
|
this.__inputBuffer = [];
|
|
@@ -1253,20 +1268,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1253
1268
|
if (!this.IS_STUB) {
|
|
1254
1269
|
throw new Error("Reading flash is only supported in stub mode. Please run runStub() first.");
|
|
1255
1270
|
}
|
|
1256
|
-
// Check if we should reconnect BEFORE starting the read
|
|
1257
|
-
// Reconnect if total bytes read >= 4MB to ensure clean state
|
|
1258
|
-
if (this._totalBytesRead >= 4 * 1024 * 1024) {
|
|
1259
|
-
this.logger.log(
|
|
1260
|
-
// `Total bytes read: ${this._totalBytesRead}. Reconnecting before new read...`,
|
|
1261
|
-
`Reconnecting before new read...`);
|
|
1262
|
-
try {
|
|
1263
|
-
await this.reconnect();
|
|
1264
|
-
}
|
|
1265
|
-
catch (err) {
|
|
1266
|
-
// If reconnect fails, throw error - don't continue with potentially broken state
|
|
1267
|
-
throw new Error(`Reconnect failed: ${err}`);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
1271
|
// Flush serial buffers before flash read operation
|
|
1271
1272
|
await this.flushSerialBuffers();
|
|
1272
1273
|
this.logger.log(`Reading ${size} bytes from flash at address 0x${addr.toString(16)}...`);
|
|
@@ -1275,16 +1276,6 @@ export class ESPLoader extends EventTarget {
|
|
|
1275
1276
|
let currentAddr = addr;
|
|
1276
1277
|
let remainingSize = size;
|
|
1277
1278
|
while (remainingSize > 0) {
|
|
1278
|
-
// Reconnect every 4MB to prevent browser buffer issues
|
|
1279
|
-
if (allData.length > 0 && allData.length % (4 * 1024 * 1024) === 0) {
|
|
1280
|
-
this.logger.debug(`Read ${allData.length} bytes. Reconnecting to clear buffers...`);
|
|
1281
|
-
try {
|
|
1282
|
-
await this.reconnect();
|
|
1283
|
-
}
|
|
1284
|
-
catch (err) {
|
|
1285
|
-
throw new Error(`Reconnect failed during read: ${err}`);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
1279
|
const chunkSize = Math.min(CHUNK_SIZE, remainingSize);
|
|
1289
1280
|
let chunkSuccess = false;
|
|
1290
1281
|
let retryCount = 0;
|