@mega-yfue/eufy-sdk 0.5.0-beta.93 → 0.5.0-beta.94
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.
|
@@ -8,7 +8,12 @@ export declare const MAGIC_WORD = "XZYH";
|
|
|
8
8
|
export declare const RequestMessageType: {
|
|
9
9
|
readonly LOCAL_LOOKUP: Buffer<ArrayBuffer>;
|
|
10
10
|
readonly LOOKUP_WITH_KEY: Buffer<ArrayBuffer>;
|
|
11
|
+
/** `ListReq_DSK`: the same body as a variant-2 lookup, answered with {@link ResponseMessageType.LIST_REQ_ACK}. */
|
|
11
12
|
readonly LOOKUP_WITH_KEY2: Buffer<ArrayBuffer>;
|
|
13
|
+
readonly RLY_HELLO: Buffer<ArrayBuffer>;
|
|
14
|
+
readonly RLY_PORT: Buffer<ArrayBuffer>;
|
|
15
|
+
readonly RLY_REQ: Buffer<ArrayBuffer>;
|
|
16
|
+
readonly RLY_PKT: Buffer<ArrayBuffer>;
|
|
12
17
|
readonly CHECK_CAM: Buffer<ArrayBuffer>;
|
|
13
18
|
readonly CHECK_CAM2: Buffer<ArrayBuffer>;
|
|
14
19
|
readonly PING: Buffer<ArrayBuffer>;
|
|
@@ -20,14 +25,24 @@ export declare const RequestMessageType: {
|
|
|
20
25
|
export declare const ResponseMessageType: {
|
|
21
26
|
readonly LOCAL_LOOKUP_RESP: Buffer<ArrayBuffer>;
|
|
22
27
|
readonly LOOKUP_ADDR: Buffer<ArrayBuffer>;
|
|
23
|
-
|
|
28
|
+
/** The relay servers a cloud lookup server names: `[count:1][pad:3]` then `count` address records. */
|
|
29
|
+
readonly LIST_REQ_ACK: Buffer<ArrayBuffer>;
|
|
30
|
+
readonly RLY_HELLO_ACK: Buffer<ArrayBuffer>;
|
|
31
|
+
/** A relay's answer to RLY_PORT: `[mark:4 BE][port:2 BE][pad:2]`, the port being the one it relays on. */
|
|
32
|
+
readonly RLY_PORT_ACK: Buffer<ArrayBuffer>;
|
|
33
|
+
readonly RLY_REQ_ACK: Buffer<ArrayBuffer>;
|
|
34
|
+
/** A relay endpoint to register with: one address record, then `[handle:4 BE]`. */
|
|
35
|
+
readonly RLY_TO: Buffer<ArrayBuffer>;
|
|
24
36
|
readonly CAM_ID: Buffer<ArrayBuffer>;
|
|
37
|
+
/** A lookup server's answer to a P2P request: `[result:1]` first, 0 when the request is accepted. */
|
|
38
|
+
readonly P2P_REQ_ACK: Buffer<ArrayBuffer>;
|
|
25
39
|
/**
|
|
26
40
|
* The device's own address record, sent in answer to CHECK_CAM ahead of CAM_ID: its 20-byte device id, one
|
|
27
|
-
* record in `
|
|
41
|
+
* record in `encodeAddress`'s shape naming the address it answers from, then 8 zero bytes (44-byte payload).
|
|
28
42
|
*/
|
|
29
43
|
readonly CAM_ADDR: Buffer<ArrayBuffer>;
|
|
30
|
-
|
|
44
|
+
/** A relay reporting the path to the device ready: the device's 20-byte id, sent from the relay endpoint. */
|
|
45
|
+
readonly RLY_RDY: Buffer<ArrayBuffer>;
|
|
31
46
|
readonly PING: Buffer<ArrayBuffer>;
|
|
32
47
|
readonly PONG: Buffer<ArrayBuffer>;
|
|
33
48
|
readonly DATA: Buffer<ArrayBuffer>;
|
|
@@ -160,6 +175,10 @@ export declare function buildLookupWithKeyPayload2(p2pDid: string, dskKey: strin
|
|
|
160
175
|
* its exact semantics (and whether it's validated) are unconfirmed.
|
|
161
176
|
*/
|
|
162
177
|
export declare function buildLookupWithKeyPayload(p2pDid: string, selfHost: string, selfPort: number, dskKey: string): Buffer;
|
|
178
|
+
/** RLY_REQ payload: `[p2pDid:20][relay address record:16][mark:4 BE]`, naming the relay port and mark a RLY_PORT_ACK gave. */
|
|
179
|
+
export declare function buildRelayRequestPayload(p2pDid: string, relay: Address, mark: number): Buffer;
|
|
180
|
+
/** RLY_PKT payload: `[handle:4 BE][p2pDid:20][role:1][pad:3]`; a connecting client's role byte is 0. */
|
|
181
|
+
export declare function buildRelayPacketPayload(handle: number, p2pDid: string): Buffer;
|
|
163
182
|
/** CHECK_CAM hole-punch payload: `[p2pDid:20][0x000000]`. */
|
|
164
183
|
export declare function buildCheckCamPayload(p2pDid: string): Buffer;
|
|
165
184
|
/** 10-byte command header: `[dataTypeHeader:2][seq:2 BE]["XZYH"][cmd:2 LE]`. */
|
|
@@ -205,7 +224,19 @@ export declare function buildRawCommandPayload(data: Buffer, channel?: number, s
|
|
|
205
224
|
export declare function buildAckPayload(dataTypeHeader: Buffer, seqNo: number): Buffer;
|
|
206
225
|
/** Parse the 16-byte data-frame header that follows the "XZYH" magic. */
|
|
207
226
|
export declare function parseDataFrameHeader(frame: Buffer): P2PDataFrameHeader;
|
|
208
|
-
/** Parse a LOOKUP_ADDR
|
|
227
|
+
/** Parse a LOOKUP_ADDR or RLY_TO message's leading address record. */
|
|
209
228
|
export declare function parseLookupAddr(msg: Buffer): Address;
|
|
229
|
+
/** The relay servers a LIST_REQ_ACK names, in the order listed, without the unspecified address; records past the message's end are dropped. */
|
|
230
|
+
export declare function parseRelayList(msg: Buffer): Address[];
|
|
231
|
+
/** A RLY_PORT_ACK's mark and relay port, or `undefined` for a message too short to carry them. */
|
|
232
|
+
export declare function parseRelayPortAck(msg: Buffer): {
|
|
233
|
+
mark: number;
|
|
234
|
+
port: number;
|
|
235
|
+
} | undefined;
|
|
236
|
+
/** A RLY_TO's relay endpoint and handle, or `undefined` for a message too short to carry them. */
|
|
237
|
+
export declare function parseRelayTo(msg: Buffer): {
|
|
238
|
+
address: Address;
|
|
239
|
+
handle: number;
|
|
240
|
+
} | undefined;
|
|
210
241
|
/** Read a NUL-terminated UTF-8 string (CMD_NOTIFY_PAYLOAD carries JSON this way). */
|
|
211
242
|
export declare function readNullTerminatedString(data: Buffer, encoding?: BufferEncoding): string;
|
|
@@ -22,7 +22,7 @@ import { FragmentRecording } from "./fragment-recording.js";
|
|
|
22
22
|
* negotiation is re-prompted once.
|
|
23
23
|
*/
|
|
24
24
|
export declare const P2P_STATION_WAITS: {
|
|
25
|
-
readonly connect:
|
|
25
|
+
readonly connect: 45000;
|
|
26
26
|
readonly level2Grace: 25000;
|
|
27
27
|
readonly level2Settle: 8000;
|
|
28
28
|
};
|
|
@@ -218,6 +218,15 @@ export declare class P2PCommandRouter {
|
|
|
218
218
|
* carry the start is not a connected session, so this refuses rather than returning one.
|
|
219
219
|
*/
|
|
220
220
|
private openMediaSession;
|
|
221
|
+
/**
|
|
222
|
+
* Wait for `session` to connect, for up to the session's own connect deadline, and throw
|
|
223
|
+
* {@link StationUnreachableError} when it does not.
|
|
224
|
+
*
|
|
225
|
+
* `connect()` resolves once the lookups are under way, not once a path answers, so a session handed back by
|
|
226
|
+
* {@link openSession} may still be connecting: a relay connect lands about 25 s in. A level-2 grace counted
|
|
227
|
+
* before this would be spent on the connect rather than on the key.
|
|
228
|
+
*/
|
|
229
|
+
private awaitConnected;
|
|
221
230
|
/** Open (or reuse) the session filed under `key`, dialling `parentSn`'s endpoint. */
|
|
222
231
|
private openSession;
|
|
223
232
|
/**
|
|
@@ -23,8 +23,13 @@ import { type Logger } from "../../core/logger.js";
|
|
|
23
23
|
* a connection that reaches this closes itself, so nothing addressed to that station can succeed afterwards.
|
|
24
24
|
* Published because it bounds every wait on a session connecting — a second number for the same deadline
|
|
25
25
|
* elsewhere would outlive the connection it waits on and charge the difference to every failure.
|
|
26
|
+
*
|
|
27
|
+
* The relay handshake starts once the lookup server has acknowledged the P2P request for 24 lookup rounds, so
|
|
28
|
+
* about 25 s in. The vendor app's own remote connect has a 30 s budget, which leaves the handshake 3–6 s.
|
|
29
|
+
* Forty-five seconds keeps the vendor's threshold and gives the handshake about 20 s to complete. A station that
|
|
30
|
+
* never acknowledges the request, as an offline one does, takes this long to fail.
|
|
26
31
|
*/
|
|
27
|
-
export declare const CONNECT_TIMEOUT_MS =
|
|
32
|
+
export declare const CONNECT_TIMEOUT_MS = 45000;
|
|
28
33
|
/**
|
|
29
34
|
* The channel a command addresses the station itself on, rather than one of its cameras, and the value a
|
|
30
35
|
* session's channel-taking methods resolve an omitted channel to.
|
|
@@ -140,6 +145,17 @@ export declare class P2PSession extends EventEmitter {
|
|
|
140
145
|
private probeSockets;
|
|
141
146
|
/** Cloud lookup inputs resolved once for a connection. */
|
|
142
147
|
private cloudLookup?;
|
|
148
|
+
/**
|
|
149
|
+
* Lookup rounds since the lookup server acknowledged this connect's P2P request, or `undefined` while it
|
|
150
|
+
* has not; see {@link RELAY_AFTER_ACKED_ROUNDS}.
|
|
151
|
+
*/
|
|
152
|
+
private ackedRounds?;
|
|
153
|
+
/**
|
|
154
|
+
* The relay handshake of a connect that has fallen back to one, by the step it waits on: the relay list
|
|
155
|
+
* (`list`, answering ListReq_DSK), a relay's hello acknowledgement (`hello`), that relay's port (`port`),
|
|
156
|
+
* then the relay-ready the device's registration produces (`request`, re-sending RLY_REQ meanwhile).
|
|
157
|
+
*/
|
|
158
|
+
private relay?;
|
|
143
159
|
/** Local outbound IPv4 reported inside LOOKUP_WITH_KEY requests. */
|
|
144
160
|
private selfHost?;
|
|
145
161
|
/**
|
|
@@ -341,21 +357,42 @@ export declare class P2PSession extends EventEmitter {
|
|
|
341
357
|
*/
|
|
342
358
|
private static detectLocalIp;
|
|
343
359
|
private sendLookups;
|
|
360
|
+
/** Step {@link ackedRounds} for one lookup round, and start the relay handshake once it passes its threshold. */
|
|
361
|
+
private countAckedRound;
|
|
362
|
+
/**
|
|
363
|
+
* How far this connect got towards a relay: the handshake step it was waiting on (`list` meaning no lookup
|
|
364
|
+
* server named a relay), `not started` where it had not fallen back yet, or `no cloud lookup` where it could
|
|
365
|
+
* not.
|
|
366
|
+
*/
|
|
367
|
+
private relayProgress;
|
|
368
|
+
/**
|
|
369
|
+
* Send the relay handshake's message for the step it waits on, from the session's own socket.
|
|
370
|
+
*
|
|
371
|
+
* The order is the vendor client's: ListReq_DSK to the cloud lookup servers, RLY_HELLO to every relay they
|
|
372
|
+
* list, RLY_PORT to the first of those relays that acknowledges, then RLY_REQ to the lookup servers naming
|
|
373
|
+
* that relay's port and mark. The lookup server has the device register with the relay, and the relay
|
|
374
|
+
* answers RLY_RDY.
|
|
375
|
+
*/
|
|
376
|
+
private sendRelay;
|
|
377
|
+
/** Advance the relay handshake on one of its answers, arriving on the session's own socket. */
|
|
378
|
+
private onRelayMessage;
|
|
344
379
|
/** Register a bound socket's own port with each configured cloud lookup address. */
|
|
345
380
|
private sendCloudLookup;
|
|
346
381
|
/**
|
|
347
382
|
* Route one inbound UDP datagram by its message type, tracing every non-DATA one and any type this session
|
|
348
383
|
* does not model.
|
|
349
384
|
*
|
|
350
|
-
* An unmodelled type is not by itself evidence about a session that is failing.
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
* as a cause.
|
|
385
|
+
* An unmodelled type is not by itself evidence about a session that is failing. Correlate one against a
|
|
386
|
+
* WORKING session before reading it as a cause.
|
|
387
|
+
*
|
|
388
|
+
* P2P_REQ_ACK is the lookup server acknowledging this connect's P2P request; the first one carrying result 0
|
|
389
|
+
* starts the round count {@link RELAY_AFTER_ACKED_ROUNDS} measures.
|
|
356
390
|
*
|
|
357
391
|
* CAM_ADDR is recognised and dropped: it names the address the device is already answering from, and the
|
|
358
|
-
* CAM_ID that follows it is what completes the connect.
|
|
392
|
+
* CAM_ID that follows it is what completes the connect. RLY_TO is a relay endpoint, never the device: it is
|
|
393
|
+
* answered with {@link RELAY_PACKET_COPIES} RLY_PKTs carrying its handle, and the RLY_RDY naming this
|
|
394
|
+
* session's device completes the connect with the relay as the peer. The other relay answers advance the
|
|
395
|
+
* handshake {@link sendRelay} drives, and are dropped outside it.
|
|
359
396
|
*/
|
|
360
397
|
private onMessage;
|
|
361
398
|
private beginCheckCam;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mega-yfue/eufy-sdk",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.94",
|
|
4
4
|
"description": "One typed TypeScript client for the Anker eufy v6 cloud — capability-driven devices, realtime events over P2P/MQTT/push, and live media",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "mega-yfue",
|