@mega-yfue/eufy-sdk 0.6.0-beta.34 → 0.6.0-beta.36
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/core/contracts.d.ts +12 -5
- package/dist/index.js +74 -17
- package/dist/index.js.map +2 -2
- package/dist/model/capabilities/camera.d.ts +1 -0
- package/dist/model/device-family.d.ts +2 -0
- package/dist/transport/p2p/recording-download.d.ts +11 -2
- package/dist/transport/rtc/command-router.d.ts +4 -3
- package/dist/transport/rtc/live.d.ts +4 -1
- package/dist/transport/rtc/session.d.ts +16 -1
- package/package.json +1 -1
|
@@ -575,6 +575,7 @@ export declare const CAMERA_MEMBERS: {
|
|
|
575
575
|
readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
|
|
576
576
|
};
|
|
577
577
|
readonly views: import("./members.js").ProvidedMember<"media", (() => readonly number[]) | undefined>;
|
|
578
|
+
readonly outputResolutions: import("./members.js").ProvidedMember<"media", (() => readonly "1080p"[]) | undefined>;
|
|
578
579
|
/**
|
|
579
580
|
* Media is not a property: it returns DATA rather than moving state, its options are richer than a
|
|
580
581
|
* value, and it exists only on a device bound to a provider. Each is declared once, with its
|
|
@@ -56,6 +56,8 @@ export declare const isNvrT8N00: (ctx: FamilyContext) => boolean;
|
|
|
56
56
|
export declare const isNvrMediaCamera: (ctx: FamilyContext) => boolean;
|
|
57
57
|
/** PoE S4 camera with independently streamed fixed and movable optical views. */
|
|
58
58
|
export declare const isNvrDualLensCamera: (ctx: FamilyContext) => boolean;
|
|
59
|
+
/** NVR cameras verified to support an explicit 1080p live output. */
|
|
60
|
+
export declare const isNvrFullHdCamera: (ctx: FamilyContext) => boolean;
|
|
59
61
|
/** Video Doorbell C31 (T8223) or C30 (T8224), streamed by the app over the portal `call` route. */
|
|
60
62
|
export declare const isCallDoorbell: (ctx: FamilyContext) => boolean;
|
|
61
63
|
/** Wired doorbell (DeviceType.DOORBELL). */
|
|
@@ -68,6 +68,11 @@ export interface RecordingStation {
|
|
|
68
68
|
* ({@link AccessUnitAssembler}).
|
|
69
69
|
*/
|
|
70
70
|
readonly chunkBytes: number;
|
|
71
|
+
/**
|
|
72
|
+
* The result code that opens the station's `CMD_DOWNLOAD_VIDEO` reply on the camera's channel when it holds no
|
|
73
|
+
* recording at the path, after which it sends nothing. Absent on a station whose reply is unconfirmed.
|
|
74
|
+
*/
|
|
75
|
+
readonly missingCode?: number;
|
|
71
76
|
}
|
|
72
77
|
/**
|
|
73
78
|
* The path a HomeBase 2 stores a camera's recording under: its {@link cameraFolder}, then the recording's name
|
|
@@ -91,7 +96,8 @@ export declare function homeBase3RecordingPath(channel: number, recording: strin
|
|
|
91
96
|
* with channel 0, split pictures filled to {@link STATION_CHUNK_BYTES}.
|
|
92
97
|
*
|
|
93
98
|
* `T8030`, HomeBase 3: `/zx/emmcdata/CameraNN/<yyyyMM>/<name>/<name>.zxvideo`, in the clear, finish tagged
|
|
94
|
-
* with {@link STATION_CHANNEL}, a keyframe over 400000 bytes split at exactly 400000
|
|
99
|
+
* with {@link STATION_CHANNEL}, a keyframe over 400000 bytes split at exactly 400000, a missing recording
|
|
100
|
+
* answered with -111.
|
|
95
101
|
*/
|
|
96
102
|
export declare const RECORDING_STATIONS: ReadonlyMap<string, RecordingStation>;
|
|
97
103
|
/** One recording transfer on a station session. */
|
|
@@ -107,7 +113,9 @@ export interface RecordingTransfer {
|
|
|
107
113
|
* station is never mixed in. The finish frame is taken on the camera's channel or on `finishChannel`
|
|
108
114
|
* ({@link RecordingStation.finishChannel}).
|
|
109
115
|
*
|
|
110
|
-
* `frames` rejects with {@link RecordingDownloadError}: `no-data` when
|
|
116
|
+
* `frames` rejects with {@link RecordingDownloadError}: `no-data` when the station's reply on the camera's
|
|
117
|
+
* channel carries `missingCode` ({@link RecordingStation.missingCode}) before any of the recording's frames, which
|
|
118
|
+
* also ends the transfer, or when nothing arrives within
|
|
111
119
|
* {@link FIRST_FRAME_WAIT_MS}, and `incomplete` when the transfer ends without its finish frame, on a
|
|
112
120
|
* {@link IDLE_END_MS} silence, on `timeoutMs` or on {@link MAX_TRANSFER_BYTES}. An abort rejects it at once
|
|
113
121
|
* with the signal's reason. After a time bound, the byte ceiling or an abort, the transfer stops collecting
|
|
@@ -118,6 +126,7 @@ export declare function receiveRecording(session: P2PSession, request: {
|
|
|
118
126
|
accountId: string;
|
|
119
127
|
channel: number;
|
|
120
128
|
finishChannel: number;
|
|
129
|
+
missingCode?: number;
|
|
121
130
|
timeoutMs?: number;
|
|
122
131
|
signal?: AbortSignal;
|
|
123
132
|
}): RecordingTransfer;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* through one shared live source per station: the station serves one camera at a time, so a second
|
|
24
24
|
* camera is refused until the first one's view ends.
|
|
25
25
|
*/
|
|
26
|
-
import { type Command, type MediaProvider } from "../../core/contracts.js";
|
|
26
|
+
import { type Command, type MediaOutputResolution, type MediaProvider } from "../../core/contracts.js";
|
|
27
27
|
import type { Logger } from "../../core/logger.js";
|
|
28
28
|
import { RtcSession, type RtcSessionOptions } from "./session.js";
|
|
29
29
|
export interface RtcIdentity {
|
|
@@ -133,7 +133,7 @@ export declare class RtcCommandRouter {
|
|
|
133
133
|
*/
|
|
134
134
|
trackMediaProviderFor(route: RtcRoute): MediaProvider;
|
|
135
135
|
/** NVR media uses a dedicated call per camera, independent of station commands. */
|
|
136
|
-
nvrMediaProviderFor(route: RtcLiveRoute, views: readonly number[]): MediaProvider;
|
|
136
|
+
nvrMediaProviderFor(route: RtcLiveRoute, views: readonly number[], outputResolutions?: readonly MediaOutputResolution[]): MediaProvider;
|
|
137
137
|
/**
|
|
138
138
|
* Share a dedicated-call source and its consumer operations under one route key.
|
|
139
139
|
*
|
|
@@ -194,7 +194,8 @@ export declare class RtcCommandRouter {
|
|
|
194
194
|
/**
|
|
195
195
|
* One bounded bring-up: the session is up when its command channel opens, and it fails, with the
|
|
196
196
|
* session closed and every listener gone, when `connect()` throws, the session closes first (rejecting
|
|
197
|
-
* with the failure that closed it, when it carries one), or {@link CONNECT_TIMEOUT_MS} passes
|
|
197
|
+
* with the failure that closed it, when it carries one), or {@link CONNECT_TIMEOUT_MS} passes, naming the
|
|
198
|
+
* stage the session reached and its peer's last state. A single
|
|
198
199
|
* promise, so an early failure cannot leave a second one rejecting unheard.
|
|
199
200
|
*/
|
|
200
201
|
private bringUp;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - Start is inner `cmd 1003` in a `1350` SET_PAYLOAD on the station channel `255`. The header byte the
|
|
7
7
|
* codec names `isResponse` carries the portal's `streamId`, `1` for a live view, and `chn_list` is an
|
|
8
8
|
* array of `{index, chn, sensor, isUps, isClicked}` objects. Stop is inner `cmd 1004`, the same way.
|
|
9
|
+
* - The NVR start may carry `stitch_resolution: {width, height}` to set output geometry; omission keeps the NVR default.
|
|
9
10
|
* - Video arrives on the live link as portal packets `1300` on channel `100 + play id`; a single-camera
|
|
10
11
|
* view is play id `1`, whatever the camera's own channel. Each body is a fixed 22-byte media header,
|
|
11
12
|
* then the Annex B video it declares. See {@link parseMediaBody}.
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
* shared live source's.
|
|
18
19
|
*/
|
|
19
20
|
import { EventEmitter } from "node:events";
|
|
20
|
-
import type { LiveStreamHandle } from "../../core/contracts.js";
|
|
21
|
+
import type { LiveStreamHandle, MediaOutputResolution } from "../../core/contracts.js";
|
|
21
22
|
import type { Logger } from "../../core/logger.js";
|
|
22
23
|
import type { RtcSession } from "./session.js";
|
|
23
24
|
import { type SegmentCounter } from "./portal-packet.js";
|
|
@@ -46,6 +47,8 @@ export interface RtcLiveOptions {
|
|
|
46
47
|
nvr?: boolean;
|
|
47
48
|
/** Optical view carried by the NVR start request; defaults to 0. */
|
|
48
49
|
view?: number;
|
|
50
|
+
/** NVR live-start output geometry; absence sends no size override. */
|
|
51
|
+
outputResolution?: MediaOutputResolution;
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* One camera's live pull. `start()` sends the start; a non-zero start ACK or a closed session ends it with
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
* nominally up. A dropped signalling socket closes the peer with it: a hub that still sees the peer
|
|
19
19
|
* answers every later `scall` with 486 until that peer's ICE gives up. A peer that cannot be built when
|
|
20
20
|
* the hub grants the relay ends the session there: the failure is emitted as `error` and `close` fires
|
|
21
|
-
* carrying it.
|
|
21
|
+
* carrying it. Before the command channel opens, a peer that fails or closes also ends the session, and so
|
|
22
|
+
* does a hub `hangup` on a `scall` session, the exchange above; {@link RtcSession.stage} names how far
|
|
23
|
+
* the bring-up got. A `call` session's pre-open hangup is not evidenced as terminal and stays logged only.
|
|
22
24
|
*
|
|
23
25
|
* A session whose peer is a {@link RtcPeerOptions.mediaTrack} peer has no command channel: `close` fires
|
|
24
26
|
* when the peer fails or closes, and the video track's packets are emitted as `rtp`.
|
|
@@ -47,6 +49,11 @@ export interface RtcSessionEvents {
|
|
|
47
49
|
/** One packet of the video track, in a {@link RtcPeerOptions.mediaTrack} session. */
|
|
48
50
|
rtp: [packet: Buffer];
|
|
49
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* How far a session's bring-up got, in order: the sign fetch, the signalling socket, its auth, the placed
|
|
54
|
+
* call, the hub's relay grant, our answer to its offer, and the open command channel.
|
|
55
|
+
*/
|
|
56
|
+
type RtcBringUpStage = "signing" | "connecting" | "authenticating" | "calling" | "relay-granted" | "answered" | "connected";
|
|
50
57
|
export declare class RtcSession extends EventEmitter<RtcSessionEvents> {
|
|
51
58
|
private readonly opts;
|
|
52
59
|
private readonly signaling;
|
|
@@ -60,8 +67,15 @@ export declare class RtcSession extends EventEmitter<RtcSessionEvents> {
|
|
|
60
67
|
private closeAnnounced;
|
|
61
68
|
private sdpHandled;
|
|
62
69
|
private chain;
|
|
70
|
+
private stageReached;
|
|
71
|
+
private lastPeerState?;
|
|
63
72
|
constructor(opts: RtcSessionOptions);
|
|
73
|
+
private get mediaTrack();
|
|
64
74
|
get isConnected(): boolean;
|
|
75
|
+
/** The last bring-up stage this session reached. */
|
|
76
|
+
get stage(): RtcBringUpStage;
|
|
77
|
+
/** The peer connection's last reported state; `undefined` before it reports one. */
|
|
78
|
+
get peerState(): string | undefined;
|
|
65
79
|
/**
|
|
66
80
|
* Start the sequence; resolves once the call is sent. `connected` fires when the channel opens. A session
|
|
67
81
|
* closed by the time the sign fetch or the auth completes rejects instead of opening the socket or
|
|
@@ -99,3 +113,4 @@ export declare class RtcSession extends EventEmitter<RtcSessionEvents> {
|
|
|
99
113
|
*/
|
|
100
114
|
private onInfo;
|
|
101
115
|
}
|
|
116
|
+
export {};
|
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.36",
|
|
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",
|