ota-hub-reactjs 0.0.15 → 0.0.16
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/base/device-whisperer.d.ts +1 -2
- package/dist/base/device-whisperer.js +23 -22
- package/dist/message_layers/protobuf-wrapper.d.ts +0 -1
- package/dist/transport_layers/esp32-device-whisperer.d.ts +4 -3
- package/dist/transport_layers/esp32-device-whisperer.js +26 -40
- package/dist/transport_layers/mqtt-device-whisperer.d.ts +0 -1
- package/dist/transport_layers/mqtt-device-whisperer.js +8 -6
- package/dist/transport_layers/serial-device-whisperer.d.ts +5 -4
- package/dist/transport_layers/serial-device-whisperer.js +22 -5
- package/dist/transport_layers/websocket-device-whisperer.d.ts +1 -2
- package/dist/transport_layers/websocket-device-whisperer.js +9 -7
- package/package.json +1 -2
|
@@ -2,7 +2,7 @@ export type LogMessage = string | number | boolean | Record<string, any> | any[]
|
|
|
2
2
|
export type LogLine = {
|
|
3
3
|
level: number;
|
|
4
4
|
message: LogMessage;
|
|
5
|
-
timestamp?:
|
|
5
|
+
timestamp?: Date;
|
|
6
6
|
};
|
|
7
7
|
type PropCreatorProps<T> = (uuid: string) => Partial<T> | undefined;
|
|
8
8
|
export interface AddConnectionProps<T> {
|
|
@@ -30,7 +30,6 @@ export type DeviceWhispererProps<T extends DeviceConnectionState> = {
|
|
|
30
30
|
};
|
|
31
31
|
export declare function MultiDeviceWhisperer<T extends DeviceConnectionState>({ createInitialConnectionState, }?: DeviceWhispererProps<T>): {
|
|
32
32
|
connections: T[];
|
|
33
|
-
connectionsRef: import("react").RefObject<T[]>;
|
|
34
33
|
addConnection: ({ uuid, propCreator }: AddConnectionProps<T>) => Promise<string>;
|
|
35
34
|
removeConnection: (uuid: string) => void;
|
|
36
35
|
connect: (_uuid: string) => void;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
|
-
import { uniqueNamesGenerator, animals } from "unique-names-generator";
|
|
4
3
|
;
|
|
5
4
|
// Initial, generic state for the generic device
|
|
6
5
|
export function createDefaultInitialDeviceState(uuid, props) {
|
|
@@ -20,53 +19,55 @@ export function createDefaultInitialDeviceState(uuid, props) {
|
|
|
20
19
|
*/
|
|
21
20
|
export function MultiDeviceWhisperer({ createInitialConnectionState = createDefaultInitialDeviceState, } = {}) {
|
|
22
21
|
const [connections, setConnections] = useState([]);
|
|
23
|
-
const connectionsRef = useRef(
|
|
22
|
+
const connectionsRef = useRef(new Map());
|
|
24
23
|
const [isReady, setIsReady] = useState(false);
|
|
25
|
-
|
|
24
|
+
// ---------- GET ----------
|
|
25
|
+
const getConnection = (uuid) => connectionsRef.current.get(uuid);
|
|
26
|
+
// ---------- UPDATE ----------
|
|
26
27
|
const updateConnection = (uuid, updater) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const current = connectionsRef.current.get(uuid);
|
|
29
|
+
if (!current)
|
|
30
|
+
return;
|
|
31
|
+
const next = updater(current);
|
|
32
|
+
connectionsRef.current.set(uuid, next);
|
|
33
|
+
setConnections(Array.from(connectionsRef.current.values()));
|
|
32
34
|
};
|
|
33
35
|
const updateConnectionName = (uuid, name) => {
|
|
34
|
-
|
|
36
|
+
updateConnection(uuid, (c) => ({ ...c, name }));
|
|
35
37
|
};
|
|
36
38
|
const appendLog = (uuid, log) => {
|
|
37
|
-
if (!log.timestamp)
|
|
39
|
+
if (!log.timestamp)
|
|
38
40
|
log.timestamp = new Date();
|
|
39
|
-
}
|
|
40
41
|
updateConnection(uuid, (c) => ({
|
|
41
42
|
...c,
|
|
42
43
|
logs: [...c.logs.slice(-199), log],
|
|
43
44
|
}));
|
|
44
45
|
};
|
|
46
|
+
// ---------- ADD ----------
|
|
45
47
|
const addConnection = async ({ uuid, propCreator }) => {
|
|
46
|
-
uuid = uuid ??
|
|
48
|
+
uuid = uuid ?? `unnamed_device_${connectionsRef.current.size}`;
|
|
47
49
|
const props = propCreator?.(uuid);
|
|
48
50
|
const newConnection = {
|
|
49
51
|
...createDefaultInitialDeviceState(uuid),
|
|
50
52
|
...createInitialConnectionState(uuid),
|
|
51
53
|
...props
|
|
52
54
|
};
|
|
53
|
-
connectionsRef.current
|
|
54
|
-
setConnections(
|
|
55
|
-
const anyUpdatedConnection = getConnection(uuid);
|
|
56
|
-
if (!anyUpdatedConnection) {
|
|
57
|
-
return "";
|
|
58
|
-
}
|
|
55
|
+
connectionsRef.current.set(uuid, newConnection);
|
|
56
|
+
setConnections(Array.from(connectionsRef.current.values()));
|
|
59
57
|
return uuid;
|
|
60
58
|
};
|
|
59
|
+
// ---------- REMOVE ----------
|
|
61
60
|
const removeConnection = (uuid) => {
|
|
62
|
-
|
|
61
|
+
connectionsRef.current.delete(uuid);
|
|
62
|
+
setConnections(Array.from(connectionsRef.current.values()));
|
|
63
63
|
};
|
|
64
|
+
// ---------- EFFECT ----------
|
|
64
65
|
useEffect(() => {
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// initial snapshot
|
|
67
|
+
setConnections(Array.from(connectionsRef.current.values()));
|
|
68
|
+
}, []);
|
|
67
69
|
return {
|
|
68
70
|
connections,
|
|
69
|
-
connectionsRef,
|
|
70
71
|
addConnection,
|
|
71
72
|
removeConnection,
|
|
72
73
|
connect: (_uuid) => { },
|
|
@@ -20,7 +20,6 @@ export declare function ProtobufMultiDeviceWhisperer<AppLayer extends DeviceConn
|
|
|
20
20
|
sendProtobuf: (uuid: string, message: MessageTX) => void;
|
|
21
21
|
protoBufOnReceiveHandler: (uuid: string, data: string | Uint8Array) => void;
|
|
22
22
|
connections: AppLayer[];
|
|
23
|
-
connectionsRef: import("react").RefObject<AppLayer[]>;
|
|
24
23
|
removeConnection: (uuid: string) => void;
|
|
25
24
|
connect: (_uuid: string) => void;
|
|
26
25
|
disconnect: (_uuid: string) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ESPLoader, FlashOptions, Transport } from "esptool-js";
|
|
2
|
-
import { AddConnectionProps, DeviceConnectionState } from "../base/device-whisperer.js";
|
|
2
|
+
import { AddConnectionProps, DeviceConnectionState, DeviceWhispererProps } from "../base/device-whisperer.js";
|
|
3
3
|
export type ESP32ConnectionState = DeviceConnectionState & {
|
|
4
4
|
port?: SerialPort;
|
|
5
5
|
baudrate?: number;
|
|
@@ -15,7 +15,9 @@ export type FlashFirmwareProps = {
|
|
|
15
15
|
firmwareBlob?: Blob;
|
|
16
16
|
fileArray?: FlashOptions["fileArray"];
|
|
17
17
|
};
|
|
18
|
-
export declare function ESP32MultiDeviceWhisperer<AppOrMessageLayer extends ESP32ConnectionState>({ ...props }?: {
|
|
18
|
+
export declare function ESP32MultiDeviceWhisperer<AppOrMessageLayer extends ESP32ConnectionState>({ releasePortByDefault, ...props }?: {
|
|
19
|
+
releasePortByDefault: boolean;
|
|
20
|
+
} & DeviceWhispererProps<AppOrMessageLayer>): {
|
|
19
21
|
addConnection: ({ uuid, propCreator }: AddConnectionProps<AppOrMessageLayer>) => Promise<string>;
|
|
20
22
|
removeConnection: (uuid: string) => Promise<void>;
|
|
21
23
|
connect: (uuid: string, baudrate?: number, restart_on_connect?: boolean) => Promise<void>;
|
|
@@ -26,7 +28,6 @@ export declare function ESP32MultiDeviceWhisperer<AppOrMessageLayer extends ESP3
|
|
|
26
28
|
address: number;
|
|
27
29
|
}[]) => Promise<void>;
|
|
28
30
|
connections: AppOrMessageLayer[];
|
|
29
|
-
connectionsRef: import("react").RefObject<AppOrMessageLayer[]>;
|
|
30
31
|
updateConnection: (uuid: string, updater: (c: AppOrMessageLayer) => AppOrMessageLayer) => void;
|
|
31
32
|
updateConnectionName: (uuid: string, name: string) => void;
|
|
32
33
|
getConnection: (uuid: string) => AppOrMessageLayer | undefined;
|
|
@@ -1,39 +1,19 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import { ESPLoader, Transport } from "esptool-js";
|
|
3
3
|
import { MultiDeviceWhisperer } from "../base/device-whisperer.js";
|
|
4
|
-
export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
4
|
+
export function ESP32MultiDeviceWhisperer({ releasePortByDefault, ...props } = { releasePortByDefault: true }) {
|
|
5
5
|
const base = MultiDeviceWhisperer(props);
|
|
6
6
|
const defaultOnReceive = (uuid, data) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const text = typeof data === "string"
|
|
8
|
+
? data
|
|
9
|
+
: new TextDecoder().decode(data);
|
|
10
|
+
const trimmed = text.trim();
|
|
11
|
+
if (!trimmed)
|
|
9
12
|
return;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
else if (data instanceof ArrayBuffer) {
|
|
16
|
-
bytes = new Uint8Array(data);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
bytes = data;
|
|
20
|
-
}
|
|
21
|
-
const asText = decoder.decode(bytes);
|
|
22
|
-
const combined = conn.readBufferLeftover + asText;
|
|
23
|
-
const lines = combined.split("\r\n");
|
|
24
|
-
base.updateConnection(uuid, (c) => ({
|
|
25
|
-
...c,
|
|
26
|
-
readBufferLeftover: lines.pop() || ""
|
|
27
|
-
}));
|
|
28
|
-
for (const line of lines) {
|
|
29
|
-
const trimmed = line.trim();
|
|
30
|
-
if (trimmed) {
|
|
31
|
-
base.appendLog(uuid, {
|
|
32
|
-
level: 2,
|
|
33
|
-
message: trimmed,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
}
|
|
13
|
+
base.appendLog(uuid, {
|
|
14
|
+
level: 2,
|
|
15
|
+
message: trimmed,
|
|
16
|
+
});
|
|
37
17
|
};
|
|
38
18
|
const defaultSend = async (uuid, data) => {
|
|
39
19
|
const conn = base.getConnection(uuid);
|
|
@@ -52,9 +32,7 @@ export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
|
52
32
|
return;
|
|
53
33
|
};
|
|
54
34
|
const readLoop = async (uuid, transport) => {
|
|
55
|
-
const
|
|
56
|
-
if (!conn)
|
|
57
|
-
return;
|
|
35
|
+
const textDecoder = new TextDecoder();
|
|
58
36
|
let readBuffer = ""; // accumulate ASCII/lines
|
|
59
37
|
let slipBuffer = []; // accumulate SLIP frames
|
|
60
38
|
let inSlipFrame = false; // are we inside a SLIP frame?
|
|
@@ -62,6 +40,12 @@ export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
|
62
40
|
try {
|
|
63
41
|
const reader = transport.rawRead();
|
|
64
42
|
while (true) {
|
|
43
|
+
const conn = base.getConnection(uuid);
|
|
44
|
+
if (!conn) {
|
|
45
|
+
console.log("Kack!");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
;
|
|
65
49
|
const { value, done } = await reader.next();
|
|
66
50
|
if (done || !value)
|
|
67
51
|
break;
|
|
@@ -117,9 +101,8 @@ export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
|
117
101
|
escapeNext = false;
|
|
118
102
|
continue;
|
|
119
103
|
}
|
|
120
|
-
// treat as normal
|
|
121
|
-
|
|
122
|
-
readBuffer += char;
|
|
104
|
+
// treat as normal text (correctly)
|
|
105
|
+
readBuffer += textDecoder.decode(new Uint8Array([b]), { stream: true });
|
|
123
106
|
// check for newline
|
|
124
107
|
let newlineIndex;
|
|
125
108
|
while ((newlineIndex = readBuffer.indexOf("\n")) >= 0) {
|
|
@@ -244,8 +227,8 @@ export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
|
244
227
|
// Always clear the transport and reset connection state
|
|
245
228
|
base.updateConnection(uuid, (c) => ({
|
|
246
229
|
...c,
|
|
247
|
-
port: null,
|
|
248
|
-
transport: null,
|
|
230
|
+
port: releasePortByDefault ? null : c.port,
|
|
231
|
+
transport: releasePortByDefault ? null : c.transport,
|
|
249
232
|
isConnected: false,
|
|
250
233
|
isConnecting: false,
|
|
251
234
|
autoConnect: false,
|
|
@@ -285,8 +268,11 @@ export function ESP32MultiDeviceWhisperer({ ...props } = {}) {
|
|
|
285
268
|
base.removeConnection(uuid);
|
|
286
269
|
};
|
|
287
270
|
const reconnectAll = async (...connectionProps) => {
|
|
288
|
-
const
|
|
289
|
-
await Promise.all(
|
|
271
|
+
const connectionIds = base.connections.map(c => c.uuid);
|
|
272
|
+
await Promise.all(connectionIds.map(async (id) => {
|
|
273
|
+
const c = base.getConnection(id);
|
|
274
|
+
if (!c)
|
|
275
|
+
return;
|
|
290
276
|
await disconnect(c.uuid);
|
|
291
277
|
await new Promise((res) => setTimeout(res, 250));
|
|
292
278
|
return connect(c.uuid, ...connectionProps);
|
|
@@ -22,7 +22,6 @@ export declare function MQTTMultiDeviceWhisperer<AppOrMessageLayer extends MQTTC
|
|
|
22
22
|
reconnectAll: () => Promise<void>;
|
|
23
23
|
connectToMQTTServer: () => (() => void) | undefined;
|
|
24
24
|
connections: AppOrMessageLayer[];
|
|
25
|
-
connectionsRef: import("react").RefObject<AppOrMessageLayer[]>;
|
|
26
25
|
updateConnection: (uuid: string, updater: (c: AppOrMessageLayer) => AppOrMessageLayer) => void;
|
|
27
26
|
updateConnectionName: (uuid: string, name: string) => void;
|
|
28
27
|
getConnection: (uuid: string) => AppOrMessageLayer | undefined;
|
|
@@ -189,7 +189,7 @@ export function MQTTMultiDeviceWhisperer({ serverUrl, uuidFromMessage, subTopicF
|
|
|
189
189
|
Error("In MQTT you MUST define a UUID otherwise we don't know what device we're connecting to!");
|
|
190
190
|
return;
|
|
191
191
|
}
|
|
192
|
-
if (base.
|
|
192
|
+
if (base.connections.some(c => c.uuid === uuid) || addingConnections.current.has(uuid)) {
|
|
193
193
|
return;
|
|
194
194
|
}
|
|
195
195
|
await base.addConnection({
|
|
@@ -221,13 +221,15 @@ export function MQTTMultiDeviceWhisperer({ serverUrl, uuidFromMessage, subTopicF
|
|
|
221
221
|
base.removeConnection(uuid);
|
|
222
222
|
};
|
|
223
223
|
const reconnectAll = async () => {
|
|
224
|
-
|
|
224
|
+
const connectionIds = base.connections.map(c => c.uuid);
|
|
225
|
+
await Promise.all(connectionIds.map(async (id) => {
|
|
226
|
+
const c = base.getConnection(id);
|
|
227
|
+
if (!c)
|
|
228
|
+
return;
|
|
225
229
|
await disconnect(c.uuid);
|
|
226
230
|
await new Promise((res) => setTimeout(res, 250));
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
await connect(c.uuid);
|
|
230
|
-
}
|
|
231
|
+
return connect(c.uuid);
|
|
232
|
+
}));
|
|
231
233
|
};
|
|
232
234
|
useEffect(() => {
|
|
233
235
|
if (!(serverAutoConnect || serverConnectOn))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeviceConnectionState, AddConnectionProps } from "../base/device-whisperer.js";
|
|
1
|
+
import { DeviceConnectionState, AddConnectionProps, DeviceWhispererProps } from "../base/device-whisperer.js";
|
|
2
2
|
export declare class UsbTransport {
|
|
3
3
|
device: USBDevice;
|
|
4
4
|
controlInterface: number;
|
|
@@ -38,14 +38,15 @@ export type SerialConnectionState = DeviceConnectionState & {
|
|
|
38
38
|
baudrate?: number;
|
|
39
39
|
slipReadWrite?: boolean;
|
|
40
40
|
};
|
|
41
|
-
export declare function SerialMultiDeviceWhisperer<AppOrMessageLayer extends SerialConnectionState>({ ...props }?:
|
|
41
|
+
export declare function SerialMultiDeviceWhisperer<AppOrMessageLayer extends SerialConnectionState>({ ...props }?: DeviceWhispererProps<AppOrMessageLayer>): {
|
|
42
42
|
addConnection: ({ uuid, propCreator }: AddConnectionProps<AppOrMessageLayer>) => Promise<string | undefined>;
|
|
43
43
|
removeConnection: (uuid: string) => Promise<void>;
|
|
44
44
|
connect: (uuid: string, baudrate?: number) => Promise<void>;
|
|
45
45
|
disconnect: (uuid: string) => Promise<void>;
|
|
46
|
-
reconnectAll: () => Promise<void>;
|
|
46
|
+
reconnectAll: (...connectionProps: any) => Promise<void>;
|
|
47
|
+
releasePortByDefault: boolean;
|
|
48
|
+
setReleasePortByDefault: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
47
49
|
connections: AppOrMessageLayer[];
|
|
48
|
-
connectionsRef: import("react").RefObject<AppOrMessageLayer[]>;
|
|
49
50
|
updateConnection: (uuid: string, updater: (c: AppOrMessageLayer) => AppOrMessageLayer) => void;
|
|
50
51
|
updateConnectionName: (uuid: string, name: string) => void;
|
|
51
52
|
getConnection: (uuid: string) => AppOrMessageLayer | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultiDeviceWhisperer } from "../base/device-whisperer.js";
|
|
2
|
-
import { useEffect } from "react";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
/*
|
|
4
4
|
┌────────────────────────────────┐
|
|
5
5
|
│ Device Whisperer (Generic) │ (connect/disconnect, state mgmt) - "Abstraction Layer"
|
|
@@ -150,6 +150,11 @@ UsbTransport.SET_LINE_CODING = 0x20;
|
|
|
150
150
|
UsbTransport.SET_CONTROL_LINE_STATE = 0x22;
|
|
151
151
|
export function SerialMultiDeviceWhisperer({ ...props } = {}) {
|
|
152
152
|
const base = MultiDeviceWhisperer(props);
|
|
153
|
+
const releasePortByDefaultRef = useRef(false);
|
|
154
|
+
const [releasePortByDefaultState, setReleasePortByDefaultState] = useState(false);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
releasePortByDefaultRef.current = releasePortByDefaultState;
|
|
157
|
+
}, [releasePortByDefaultState]);
|
|
153
158
|
// --- Message Processing (Identical logic, just copied over) ---
|
|
154
159
|
const defaultOnReceive = (uuid, data) => {
|
|
155
160
|
const conn = base.getConnection(uuid);
|
|
@@ -165,7 +170,7 @@ export function SerialMultiDeviceWhisperer({ ...props } = {}) {
|
|
|
165
170
|
bytes = data;
|
|
166
171
|
const asText = decoder.decode(bytes);
|
|
167
172
|
const combined = conn.readBufferLeftover + asText;
|
|
168
|
-
const lines = combined.split("\
|
|
173
|
+
const lines = combined.split("\n");
|
|
169
174
|
base.updateConnection(uuid, (c) => ({ ...c, readBufferLeftover: lines.pop() || "" }));
|
|
170
175
|
for (const line of lines) {
|
|
171
176
|
if (line.trim()) {
|
|
@@ -306,7 +311,7 @@ export function SerialMultiDeviceWhisperer({ ...props } = {}) {
|
|
|
306
311
|
}
|
|
307
312
|
base.updateConnection(uuid, c => ({
|
|
308
313
|
...c,
|
|
309
|
-
transport: null,
|
|
314
|
+
transport: releasePortByDefaultRef.current ? null : c.transport,
|
|
310
315
|
isConnected: false,
|
|
311
316
|
isConnecting: false
|
|
312
317
|
}));
|
|
@@ -346,7 +351,17 @@ export function SerialMultiDeviceWhisperer({ ...props } = {}) {
|
|
|
346
351
|
await disconnect(uuid);
|
|
347
352
|
base.removeConnection(uuid);
|
|
348
353
|
};
|
|
349
|
-
const reconnectAll = async () => {
|
|
354
|
+
const reconnectAll = async (...connectionProps) => {
|
|
355
|
+
const connectionIds = base.connections.map(c => c.uuid);
|
|
356
|
+
await Promise.all(connectionIds.map(async (id) => {
|
|
357
|
+
const c = base.getConnection(id);
|
|
358
|
+
if (!c)
|
|
359
|
+
return;
|
|
360
|
+
await disconnect(c.uuid);
|
|
361
|
+
await new Promise((res) => setTimeout(res, 250));
|
|
362
|
+
return connect(c.uuid, ...connectionProps);
|
|
363
|
+
}));
|
|
364
|
+
};
|
|
350
365
|
useEffect(() => { base.setIsReady(true); }, []);
|
|
351
366
|
return {
|
|
352
367
|
...base,
|
|
@@ -354,6 +369,8 @@ export function SerialMultiDeviceWhisperer({ ...props } = {}) {
|
|
|
354
369
|
removeConnection,
|
|
355
370
|
connect,
|
|
356
371
|
disconnect,
|
|
357
|
-
reconnectAll
|
|
372
|
+
reconnectAll,
|
|
373
|
+
releasePortByDefault: releasePortByDefaultState,
|
|
374
|
+
setReleasePortByDefault: setReleasePortByDefaultState
|
|
358
375
|
};
|
|
359
376
|
}
|
|
@@ -18,9 +18,8 @@ export declare function WebsocketMultiDeviceWhisperer<AppOrMessageLayer extends
|
|
|
18
18
|
connect: (uuid: string, attempt?: number) => Promise<void>;
|
|
19
19
|
disconnect: (uuid: string) => Promise<void>;
|
|
20
20
|
checkForNewDevices: () => Promise<DeviceObjectResponse[]>;
|
|
21
|
-
reconnectAll: () => Promise<void>;
|
|
21
|
+
reconnectAll: (...connectionProps: any) => Promise<void>;
|
|
22
22
|
connections: AppOrMessageLayer[];
|
|
23
|
-
connectionsRef: import("react").RefObject<AppOrMessageLayer[]>;
|
|
24
23
|
updateConnection: (uuid: string, updater: (c: AppOrMessageLayer) => AppOrMessageLayer) => void;
|
|
25
24
|
updateConnectionName: (uuid: string, name: string) => void;
|
|
26
25
|
getConnection: (uuid: string) => AppOrMessageLayer | undefined;
|
|
@@ -19,7 +19,7 @@ export function WebsocketMultiDeviceWhisperer({ server_url, server_port, ...prop
|
|
|
19
19
|
}
|
|
20
20
|
const asText = decoder.decode(bytes);
|
|
21
21
|
const combined = conn.readBufferLeftover + asText;
|
|
22
|
-
const lines = combined.split(
|
|
22
|
+
const lines = combined.split(/\r?\n/);
|
|
23
23
|
base.updateConnection(uuid, (c) => ({
|
|
24
24
|
...c,
|
|
25
25
|
readBufferLeftover: lines.pop() || ""
|
|
@@ -173,14 +173,16 @@ export function WebsocketMultiDeviceWhisperer({ server_url, server_port, ...prop
|
|
|
173
173
|
return [];
|
|
174
174
|
}
|
|
175
175
|
};
|
|
176
|
-
const reconnectAll = async () => {
|
|
177
|
-
|
|
176
|
+
const reconnectAll = async (...connectionProps) => {
|
|
177
|
+
const connectionIds = base.connections.map(c => c.uuid);
|
|
178
|
+
await Promise.all(connectionIds.map(async (id) => {
|
|
179
|
+
const c = base.getConnection(id);
|
|
180
|
+
if (!c)
|
|
181
|
+
return;
|
|
178
182
|
await disconnect(c.uuid);
|
|
179
183
|
await new Promise((res) => setTimeout(res, 250));
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
await connect(c.uuid);
|
|
183
|
-
}
|
|
184
|
+
return connect(c.uuid, ...connectionProps);
|
|
185
|
+
}));
|
|
184
186
|
};
|
|
185
187
|
useEffect(() => {
|
|
186
188
|
base.setIsReady(true); // Ready on page load by default
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ota-hub-reactjs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "ReactJS tools for building web apps to flash MCU devices such as esp32, brought to you by OTA Hub.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"esptool-js": "^0.5.5",
|
|
35
35
|
"mqtt": "^5.14.1",
|
|
36
|
-
"unique-names-generator": "^4.7.1",
|
|
37
36
|
"uuid": "^11.1.0"
|
|
38
37
|
},
|
|
39
38
|
"peerDependencies": {
|