ota-hub-reactjs 0.1.2 → 0.1.4
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.
|
@@ -36,7 +36,7 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
36
36
|
let inSlipFrame = false; // are we inside a SLIP frame?
|
|
37
37
|
let escapeNext = false;
|
|
38
38
|
const reader = transport.rawRead();
|
|
39
|
-
base.updateConnection(uuid, (c) => ({ ...c
|
|
39
|
+
base.updateConnection(uuid, (c) => ({ ...c }));
|
|
40
40
|
try {
|
|
41
41
|
while (true) {
|
|
42
42
|
const conn = base.getConnection(uuid);
|
|
@@ -44,6 +44,8 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
44
44
|
console.log("Kack!");
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
+
if (conn.isFlashing || !conn.isConnected)
|
|
48
|
+
break;
|
|
47
49
|
const { value, done } = await reader.next();
|
|
48
50
|
if (done || !value)
|
|
49
51
|
break;
|
|
@@ -114,6 +116,7 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
}
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, 100)); // Little breather before attempt any disconnects
|
|
117
120
|
}
|
|
118
121
|
catch (e) {
|
|
119
122
|
base.appendLog(uuid, {
|
|
@@ -122,13 +125,11 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
122
125
|
});
|
|
123
126
|
}
|
|
124
127
|
finally {
|
|
125
|
-
|
|
126
|
-
base.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
});
|
|
131
|
-
await disconnect(uuid);
|
|
128
|
+
base.updateConnection(uuid, (c) => ({ ...c }));
|
|
129
|
+
const conn = base.getConnection(uuid);
|
|
130
|
+
if (conn?.isConnected) {
|
|
131
|
+
await disconnect(uuid);
|
|
132
|
+
}
|
|
132
133
|
}
|
|
133
134
|
};
|
|
134
135
|
const restartDevice = async (uuid, default_transport) => {
|
|
@@ -155,21 +156,6 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
155
156
|
});
|
|
156
157
|
base.updateConnection(uuid, (c) => ({ ...c, port }));
|
|
157
158
|
}
|
|
158
|
-
else {
|
|
159
|
-
try {
|
|
160
|
-
const oldInfo = port.getInfo();
|
|
161
|
-
const authorizedPorts = await navigator.serial.getPorts();
|
|
162
|
-
const freshPort = authorizedPorts.find((p) => p.getInfo().usbVendorId === oldInfo.usbVendorId &&
|
|
163
|
-
p.getInfo().usbProductId === oldInfo.usbProductId);
|
|
164
|
-
if (freshPort) {
|
|
165
|
-
port = freshPort; // Swap out the dead pointer
|
|
166
|
-
base.updateConnection(uuid, (c) => ({ ...c, port }));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
catch (e) {
|
|
170
|
-
console.warn(`[${uuid}] Failed to silently heal port reference:`, e);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
159
|
base.updateConnection(uuid, (c) => ({ ...c, isConnecting: true }));
|
|
174
160
|
const use_baudrate = baudrate ?? conn.baudrate ?? 115200;
|
|
175
161
|
const transport = new Transport(port, false, false);
|
|
@@ -177,7 +163,7 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
177
163
|
const esploader = new ESPLoader({
|
|
178
164
|
transport,
|
|
179
165
|
baudrate: use_baudrate,
|
|
180
|
-
enableTracing:
|
|
166
|
+
enableTracing: !!conn.debugLogging,
|
|
181
167
|
debugLogging: !!conn.debugLogging,
|
|
182
168
|
});
|
|
183
169
|
try {
|
|
@@ -230,29 +216,9 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
230
216
|
};
|
|
231
217
|
const disconnect = async (uuid, timeout = 2000) => {
|
|
232
218
|
const conn = base.getConnection(uuid);
|
|
233
|
-
// 1. Politely kill our high-level generator
|
|
234
|
-
if (conn?.reader && typeof conn.reader.return === "function") {
|
|
235
|
-
try {
|
|
236
|
-
// @ts-ignore
|
|
237
|
-
await conn.reader.return();
|
|
238
|
-
}
|
|
239
|
-
catch (e) {
|
|
240
|
-
console.warn(`[${uuid}] Error returning generator lock:`, e);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
219
|
if (conn?.transport) {
|
|
244
220
|
try {
|
|
245
|
-
//
|
|
246
|
-
// Dig into esptool-js's internal state and force the native reader to release.
|
|
247
|
-
// If we don't do this, transport.disconnect() will hang and fail to close the port.
|
|
248
|
-
const internalReader = conn.transport.reader;
|
|
249
|
-
if (internalReader) {
|
|
250
|
-
await internalReader.cancel().catch(() => { });
|
|
251
|
-
if (typeof internalReader.releaseLock === "function") {
|
|
252
|
-
internalReader.releaseLock();
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// 3. Now that locks are cleared, attempt standard disconnect
|
|
221
|
+
// Attempt disconnect, but don’t hang if the port is crashed
|
|
256
222
|
await Promise.race([
|
|
257
223
|
conn.transport.disconnect(),
|
|
258
224
|
new Promise((resolve) => setTimeout(resolve, timeout)),
|
|
@@ -262,32 +228,20 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
262
228
|
console.warn(`[${uuid}] Serial Disconnect error:`, e);
|
|
263
229
|
}
|
|
264
230
|
}
|
|
265
|
-
//
|
|
266
|
-
// Guarantee the port is closed natively just in case the transport failed
|
|
267
|
-
if (conn?.port) {
|
|
268
|
-
try {
|
|
269
|
-
if (conn.port.readable?.locked) {
|
|
270
|
-
await conn.port.readable.cancel().catch(() => { });
|
|
271
|
-
}
|
|
272
|
-
if (conn.port.writable?.locked) {
|
|
273
|
-
await conn.port.writable.abort().catch(() => { });
|
|
274
|
-
}
|
|
275
|
-
await conn.port.close().catch(() => { });
|
|
276
|
-
}
|
|
277
|
-
catch (e) {
|
|
278
|
-
// It will throw if already closed, which is perfectly fine.
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// 5. Always clear the transport and reset connection state
|
|
231
|
+
// Always clear the transport and reset connection state
|
|
282
232
|
base.updateConnection(uuid, (c) => ({
|
|
283
233
|
...c,
|
|
284
|
-
port: releasePortByDefault ?
|
|
285
|
-
transport: releasePortByDefault ?
|
|
286
|
-
|
|
234
|
+
port: releasePortByDefault ? null : c.port,
|
|
235
|
+
transport: releasePortByDefault ? null : c.transport,
|
|
236
|
+
esp: releasePortByDefault ? null : c.transport,
|
|
287
237
|
isConnected: false,
|
|
288
238
|
isConnecting: false,
|
|
289
239
|
autoConnect: false,
|
|
290
240
|
}));
|
|
241
|
+
base.appendLog(uuid, {
|
|
242
|
+
level: 0,
|
|
243
|
+
message: "[!] Serial disconnected",
|
|
244
|
+
});
|
|
291
245
|
await conn?.onDisconnect?.();
|
|
292
246
|
};
|
|
293
247
|
const addConnection = async ({ uuid, propCreator, }) => {
|
|
@@ -362,27 +316,25 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
362
316
|
// 1. Bail if we don't have the required state
|
|
363
317
|
if (!conn || !conn.port || assetsToFlash.length === 0)
|
|
364
318
|
return;
|
|
365
|
-
|
|
366
|
-
await disconnect(uuid);
|
|
367
|
-
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
319
|
+
const prevAutoConnect = conn.autoConnect;
|
|
368
320
|
base.updateConnection(uuid, (c) => ({
|
|
369
321
|
...c,
|
|
370
|
-
port: conn.port, // Restore the port into state in case disconnect wiped it
|
|
371
322
|
isFlashing: true,
|
|
372
323
|
flashProgress: 0,
|
|
373
324
|
flashError: undefined,
|
|
325
|
+
autoConnect: false,
|
|
374
326
|
}));
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
327
|
+
if (conn.isConnected)
|
|
328
|
+
await disconnect(uuid);
|
|
329
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
378
330
|
try {
|
|
379
331
|
// --- Connect ONCE ---
|
|
380
|
-
transport = new Transport(conn.port, true);
|
|
381
|
-
esploader = new ESPLoader({
|
|
332
|
+
const transport = new Transport(conn.port, true);
|
|
333
|
+
const esploader = new ESPLoader({
|
|
382
334
|
transport,
|
|
383
335
|
baudrate: 921600,
|
|
384
|
-
enableTracing:
|
|
385
|
-
|
|
336
|
+
enableTracing: !!conn.debugLogging,
|
|
337
|
+
debugLogging: !!conn.debugLogging,
|
|
386
338
|
});
|
|
387
339
|
// This may fail, that'll bubble the failure up to the upper try/catch
|
|
388
340
|
await esploader.main();
|
|
@@ -436,9 +388,8 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
436
388
|
...c,
|
|
437
389
|
isFlashing: false,
|
|
438
390
|
flashProgress: 100,
|
|
391
|
+
autoConnect: prevAutoConnect,
|
|
439
392
|
}));
|
|
440
|
-
// --- Reconnect the standard monitor ---
|
|
441
|
-
await connect(uuid);
|
|
442
393
|
}
|
|
443
394
|
catch (e) {
|
|
444
395
|
console.error(`[${uuid}] Flashing failed:`, e);
|
|
@@ -448,6 +399,8 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
448
399
|
flashError: e?.message ?? "Unknown error",
|
|
449
400
|
}));
|
|
450
401
|
// Attempt recovery
|
|
402
|
+
}
|
|
403
|
+
finally {
|
|
451
404
|
await connect(uuid);
|
|
452
405
|
}
|
|
453
406
|
};
|
package/package.json
CHANGED