ota-hub-reactjs 0.1.2 → 0.1.3
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) => {
|
|
@@ -177,7 +178,7 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
177
178
|
const esploader = new ESPLoader({
|
|
178
179
|
transport,
|
|
179
180
|
baudrate: use_baudrate,
|
|
180
|
-
enableTracing:
|
|
181
|
+
enableTracing: !!conn.debugLogging,
|
|
181
182
|
debugLogging: !!conn.debugLogging,
|
|
182
183
|
});
|
|
183
184
|
try {
|
|
@@ -230,29 +231,9 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
230
231
|
};
|
|
231
232
|
const disconnect = async (uuid, timeout = 2000) => {
|
|
232
233
|
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
234
|
if (conn?.transport) {
|
|
244
235
|
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
|
|
236
|
+
// Attempt disconnect, but don’t hang if the port is crashed
|
|
256
237
|
await Promise.race([
|
|
257
238
|
conn.transport.disconnect(),
|
|
258
239
|
new Promise((resolve) => setTimeout(resolve, timeout)),
|
|
@@ -262,32 +243,20 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
262
243
|
console.warn(`[${uuid}] Serial Disconnect error:`, e);
|
|
263
244
|
}
|
|
264
245
|
}
|
|
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
|
|
246
|
+
// Always clear the transport and reset connection state
|
|
282
247
|
base.updateConnection(uuid, (c) => ({
|
|
283
248
|
...c,
|
|
284
|
-
port: releasePortByDefault ?
|
|
285
|
-
transport: releasePortByDefault ?
|
|
286
|
-
|
|
249
|
+
port: releasePortByDefault ? null : c.port,
|
|
250
|
+
transport: releasePortByDefault ? null : c.transport,
|
|
251
|
+
esp: releasePortByDefault ? null : c.transport,
|
|
287
252
|
isConnected: false,
|
|
288
253
|
isConnecting: false,
|
|
289
254
|
autoConnect: false,
|
|
290
255
|
}));
|
|
256
|
+
base.appendLog(uuid, {
|
|
257
|
+
level: 0,
|
|
258
|
+
message: "[!] Serial disconnected",
|
|
259
|
+
});
|
|
291
260
|
await conn?.onDisconnect?.();
|
|
292
261
|
};
|
|
293
262
|
const addConnection = async ({ uuid, propCreator, }) => {
|
|
@@ -362,27 +331,26 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
362
331
|
// 1. Bail if we don't have the required state
|
|
363
332
|
if (!conn || !conn.port || assetsToFlash.length === 0)
|
|
364
333
|
return;
|
|
365
|
-
|
|
366
|
-
await disconnect(uuid);
|
|
367
|
-
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
334
|
+
const prevAutoConnect = conn.autoConnect;
|
|
368
335
|
base.updateConnection(uuid, (c) => ({
|
|
369
336
|
...c,
|
|
370
337
|
port: conn.port, // Restore the port into state in case disconnect wiped it
|
|
371
338
|
isFlashing: true,
|
|
372
339
|
flashProgress: 0,
|
|
373
340
|
flashError: undefined,
|
|
341
|
+
autoConnect: false,
|
|
374
342
|
}));
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
343
|
+
if (conn.isConnected)
|
|
344
|
+
await disconnect(uuid);
|
|
345
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
378
346
|
try {
|
|
379
347
|
// --- Connect ONCE ---
|
|
380
|
-
transport = new Transport(conn.port, true);
|
|
381
|
-
esploader = new ESPLoader({
|
|
348
|
+
const transport = new Transport(conn.port, true);
|
|
349
|
+
const esploader = new ESPLoader({
|
|
382
350
|
transport,
|
|
383
351
|
baudrate: 921600,
|
|
384
|
-
enableTracing:
|
|
385
|
-
|
|
352
|
+
enableTracing: !!conn.debugLogging,
|
|
353
|
+
debugLogging: !!conn.debugLogging,
|
|
386
354
|
});
|
|
387
355
|
// This may fail, that'll bubble the failure up to the upper try/catch
|
|
388
356
|
await esploader.main();
|
|
@@ -436,9 +404,8 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
436
404
|
...c,
|
|
437
405
|
isFlashing: false,
|
|
438
406
|
flashProgress: 100,
|
|
407
|
+
autoConnect: prevAutoConnect,
|
|
439
408
|
}));
|
|
440
|
-
// --- Reconnect the standard monitor ---
|
|
441
|
-
await connect(uuid);
|
|
442
409
|
}
|
|
443
410
|
catch (e) {
|
|
444
411
|
console.error(`[${uuid}] Flashing failed:`, e);
|
|
@@ -448,6 +415,8 @@ export function useESP32MultiDeviceWhisperer({ releasePortByDefault, ...props }
|
|
|
448
415
|
flashError: e?.message ?? "Unknown error",
|
|
449
416
|
}));
|
|
450
417
|
// Attempt recovery
|
|
418
|
+
}
|
|
419
|
+
finally {
|
|
451
420
|
await connect(uuid);
|
|
452
421
|
}
|
|
453
422
|
};
|
package/package.json
CHANGED