@mega-yfue/eufy-sdk 0.6.0-beta.17 → 0.6.0-beta.19
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/client/device-registry.d.ts +6 -0
- package/dist/client/eufy-mega.d.ts +20 -2
- package/dist/client/types.d.ts +9 -6
- package/dist/core/types.d.ts +4 -2
- package/dist/index.js +141 -34
- package/dist/index.js.map +3 -3
- package/dist/model/capabilities/vacuum-clean.d.ts +23 -0
- package/dist/transport/mqtt/biz-stream.d.ts +22 -25
- package/dist/transport/p2p/command-router.d.ts +2 -0
- package/dist/transport/p2p/live-stream.d.ts +2 -1
- package/dist/transport/p2p/p2p-session.d.ts +12 -1
- package/package.json +1 -1
|
@@ -280,6 +280,16 @@ export declare function encodeSelectZonesClean(mapId: number, zones: readonly Va
|
|
|
280
280
|
* @internal
|
|
281
281
|
*/
|
|
282
282
|
export declare function encodeSceneClean(sceneId: number): string;
|
|
283
|
+
/**
|
|
284
|
+
* Build one of the two DP 153 writes the vendor app sends when its map view opens: the time in
|
|
285
|
+
* microseconds, and on the second write field 2 set to `1`.
|
|
286
|
+
*
|
|
287
|
+
* Captured from the vendor app on the device's `cmd/…/req` leg, three times with the same layout. The
|
|
288
|
+
* product catalogue lists DP 153 as uplink-only (`WorkStatus`); the vendor app writes this message to it
|
|
289
|
+
* all the same. {@link VACUUM_CLEAN_MEMBERS.requestMap} dispatches both.
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
export declare function encodeMapWatch(nowMs: number, watching: boolean): string;
|
|
283
293
|
/**
|
|
284
294
|
* Build a whole-floor auto clean carrying an `AutoClean` payload of one pass.
|
|
285
295
|
* @internal
|
|
@@ -1986,6 +1996,19 @@ export declare const VACUUM_CLEAN_MEMBERS: {
|
|
|
1986
1996
|
readonly startScene: import("./members.js").MethodMember<(sceneId: number) => Promise<void>> & {
|
|
1987
1997
|
available: (ctx: import("./types.js").CommandContext) => boolean;
|
|
1988
1998
|
};
|
|
1999
|
+
/**
|
|
2000
|
+
* Ask the robot to push its whole map — plane, room outline, room list and restricted zones — on the
|
|
2001
|
+
* map stream, as the vendor app does when its map view opens: two DP 153 writes, the time and then the
|
|
2002
|
+
* time with field 2 set (see {@link encodeMapWatch}).
|
|
2003
|
+
*
|
|
2004
|
+
* A docked robot sends no map of its own accord, so this is how its room ids and names become
|
|
2005
|
+
* readable without a clean. The map arrives on the stream like any other, not as this call's result.
|
|
2006
|
+
*
|
|
2007
|
+
* WATCHED: sent to a docked robot, it pushed its whole map within a second.
|
|
2008
|
+
*/
|
|
2009
|
+
readonly requestMap: import("./members.js").MethodMember<() => Promise<void>> & {
|
|
2010
|
+
available: (ctx: import("./types.js").CommandContext) => boolean;
|
|
2011
|
+
};
|
|
1989
2012
|
/**
|
|
1990
2013
|
* State the cleaning settings a run uses — `CleanParamRequest.clean_param` over DP 154.
|
|
1991
2014
|
*
|
|
@@ -12,44 +12,41 @@ export declare const BIZ_PROTOCOL: {
|
|
|
12
12
|
readonly LIVE_PHOTO: 43;
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
-
* The channels a map frame
|
|
15
|
+
* The channels a map frame arrives on, by id, as a robot's own frames identify them.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* *decodes* a channel's bytes must therefore prefer a device-declared mapping when one has been seen;
|
|
23
|
-
* this table is the default to fall back on, not an authority.
|
|
17
|
+
* Each id is paired with the `stream.proto` message whose field layout its frames carry, which is not
|
|
18
|
+
* the field-number order of `Metadata.ChanIds`: the cell plane (`Map`) arrives on 2, its room outline
|
|
19
|
+
* on 4, the room list on 5, the restricted zones on 6, the robot's pose (`DynamicData`) on 7, the map's
|
|
20
|
+
* `MapDescription` on 60 and a whole `MapBackup` on 68. A `Metadata` frame would declare a device's own numbering; none has been seen,
|
|
21
|
+
* so none is read, and this table is the numbering every frame is read by.
|
|
24
22
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
23
|
+
* Only channels whose message is identified are listed. A channel whose frames carry too little to
|
|
24
|
+
* identify, or that carries a message nothing here reads, is absent.
|
|
25
|
+
*
|
|
26
|
+
* Channel 0 is not in `ChanIds` at all: the app hard-codes it, routing it to a scene-data event rather
|
|
27
|
+
* than a map one, and asks for the scene list on it by number.
|
|
28
28
|
*/
|
|
29
29
|
export declare const BIZ_CHANNEL: {
|
|
30
30
|
/** Scene (room-group) data. Hard-coded in the app, not part of `ChanIds`. */
|
|
31
31
|
readonly SCENES: 0;
|
|
32
|
-
readonly
|
|
33
|
-
readonly
|
|
34
|
-
readonly
|
|
35
|
-
readonly
|
|
36
|
-
readonly
|
|
37
|
-
readonly
|
|
38
|
-
readonly
|
|
39
|
-
readonly OBSTACLE_INFO: 8;
|
|
40
|
-
readonly MAP_DATA: 9;
|
|
41
|
-
readonly CRUISE_DATA: 10;
|
|
32
|
+
readonly MAP_DATA: 2;
|
|
33
|
+
readonly ROOM_OUTLINE: 4;
|
|
34
|
+
readonly ROOM_PARAMS: 5;
|
|
35
|
+
readonly RESTRICTED_ZONE: 6;
|
|
36
|
+
readonly DYNAMIC_DATA: 7;
|
|
37
|
+
readonly MAP_DESCRIPTION: 60;
|
|
38
|
+
readonly MAP_BACKUP: 68;
|
|
42
39
|
};
|
|
43
|
-
/** A channel's name under the
|
|
40
|
+
/** A channel's name under the {@link BIZ_CHANNEL} numbering. */
|
|
44
41
|
export type BizChannel = keyof typeof BIZ_CHANNEL;
|
|
45
42
|
/**
|
|
46
|
-
* Name a channel id under the
|
|
47
|
-
*
|
|
43
|
+
* Name a channel id under the {@link BIZ_CHANNEL} numbering, or `undefined` for an id it does not list.
|
|
44
|
+
* Not a substitute for a device-declared mapping where one exists.
|
|
48
45
|
*/
|
|
49
46
|
export declare function bizChannelName(id: number): BizChannel | undefined;
|
|
50
47
|
/** One frame off the map stream, unwrapped as far as its bytes but not decoded. */
|
|
51
48
|
export interface BizMapFrame {
|
|
52
|
-
/** Which channel the bytes belong to. Compare against {@link BIZ_CHANNEL}
|
|
49
|
+
/** Which channel the bytes belong to. Compare against {@link BIZ_CHANNEL}. */
|
|
53
50
|
readonly channelId: number;
|
|
54
51
|
/**
|
|
55
52
|
* The vendor's `clear_type`. Forwarded, not interpreted: the app passes it straight through to its
|
|
@@ -62,6 +62,8 @@ export interface P2PRouterDeps {
|
|
|
62
62
|
onClose: (stationSn: string) => void;
|
|
63
63
|
onError: (err: Error) => void;
|
|
64
64
|
onLevel2Ready: (stationSn: string, cipherId: number) => void;
|
|
65
|
+
/** The station answered on its own session at `atMs` — a PONG or an ACK from the connected peer. */
|
|
66
|
+
onPeerAnswer?: (stationSn: string, atMs: number) => void;
|
|
65
67
|
/** A raw decoded frame — the client emits the low-level `p2p` event + runs the semantic decode. */
|
|
66
68
|
onFrame: (stationSn: string, frame: P2PFrame) => void;
|
|
67
69
|
/**
|
|
@@ -180,6 +180,7 @@ export declare class LiveStream extends EventEmitter {
|
|
|
180
180
|
stop(): void;
|
|
181
181
|
/** Extract the Annex-B payload from a plaintext 1300 frame (fixed 22-byte header), or undefined. */
|
|
182
182
|
private plaintextAnnexB;
|
|
183
|
+
/** Emit one accepted media frame; an audio frame with no bytes past its header emits nothing. */
|
|
183
184
|
private onFrame;
|
|
184
185
|
/**
|
|
185
186
|
* Whether this stream may take `frame` — the demultiplexer for a station that serves several cameras.
|
|
@@ -226,7 +227,7 @@ export declare class LiveStream extends EventEmitter {
|
|
|
226
227
|
* The payload of an audio frame. On a stream with an ECIES decoder, a sealed frame ({@link isSealedAudio}) is
|
|
227
228
|
* opened under the media key of the latest keyframe, and answers `undefined` when it does not open or arrives
|
|
228
229
|
* before any keyframe gave a media key, since its bytes are ciphertext. Every other frame is the bytes after
|
|
229
|
-
* its header.
|
|
230
|
+
* its header, empty for a frame that carries only its header.
|
|
230
231
|
*/
|
|
231
232
|
private audioPayload;
|
|
232
233
|
/**
|
|
@@ -95,6 +95,12 @@ export interface P2PFrame extends P2PDataFrameHeader {
|
|
|
95
95
|
* the values as device state without any per-capability decoder.
|
|
96
96
|
*/
|
|
97
97
|
params?: Record<number, string>;
|
|
98
|
+
/**
|
|
99
|
+
* A station's camera-info table, one `param_type → param_value` map per channel it names (255 is the
|
|
100
|
+
* station). Set instead of {@link params} when the station answered on {@link STATION_CHANNEL}, so each
|
|
101
|
+
* channel's state can land on the device attached there.
|
|
102
|
+
*/
|
|
103
|
+
channelParams?: Record<number, Record<number, string>>;
|
|
98
104
|
}
|
|
99
105
|
/**
|
|
100
106
|
* A live PPCS session. Internal transport; a host drives cameras through the capability surface.
|
|
@@ -134,7 +140,12 @@ export declare class P2PSession extends EventEmitter {
|
|
|
134
140
|
private audioStalled;
|
|
135
141
|
private audioRetransmitTimer?;
|
|
136
142
|
private lastPongData?;
|
|
137
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* When the selected peer last answered outbound P2P traffic on this connection.
|
|
145
|
+
*
|
|
146
|
+
* Each answer also emits `peerAnswer` with this time: a PONG or an ACK from the connected address is the
|
|
147
|
+
* station replying on this connection now, which a heartbeat draws every {@link HEARTBEAT_MS}.
|
|
148
|
+
*/
|
|
138
149
|
private lastPeerAt?;
|
|
139
150
|
/** Whether the silence has already been stated, so it is traced once per connection rather than per read. */
|
|
140
151
|
private pathStaleTraced;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mega-yfue/eufy-sdk",
|
|
3
|
-
"version": "0.6.0-beta.
|
|
3
|
+
"version": "0.6.0-beta.19",
|
|
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",
|