@mega-yfue/eufy-sdk 0.5.0-beta.73 → 0.5.0-beta.75

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.
@@ -1,3 +1,4 @@
1
+ import { isCameraCodec } from "./access.js";
1
2
  import { type Surface } from "./members.js";
2
3
  import type { AvailabilityContext, CapabilityModule, CommandContext } from "./types.js";
3
4
  import { type Command, type MediaProvider } from "../../core/contracts.js";
@@ -300,6 +301,7 @@ export declare const CAMERA_MEMBERS: {
300
301
  readonly type: "bool";
301
302
  readonly kind: "boolean";
302
303
  readonly provenance: "verified";
304
+ readonly available: typeof isCameraCodec;
303
305
  readonly invert: true;
304
306
  readonly invertFor: (ctx: AvailabilityContext) => false | undefined;
305
307
  readonly readAliases: readonly [{
@@ -334,6 +336,7 @@ export declare const CAMERA_MEMBERS: {
334
336
  readonly type: "bool";
335
337
  readonly kind: "boolean";
336
338
  readonly provenance: "apk";
339
+ readonly available: typeof isCameraCodec;
337
340
  readonly description: string;
338
341
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
339
342
  };
@@ -353,6 +356,7 @@ export declare const CAMERA_MEMBERS: {
353
356
  readonly 2: "Timestamp + Logo";
354
357
  };
355
358
  readonly provenance: "verified";
359
+ readonly available: typeof isCameraCodec;
356
360
  readonly description: string;
357
361
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
358
362
  };
@@ -366,6 +370,7 @@ export declare const CAMERA_MEMBERS: {
366
370
  readonly type: "bool";
367
371
  readonly kind: "boolean";
368
372
  readonly provenance: "verified";
373
+ readonly available: typeof isCameraCodec;
369
374
  readonly description: string;
370
375
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
371
376
  };
@@ -381,6 +386,7 @@ export declare const CAMERA_MEMBERS: {
381
386
  readonly type: "number";
382
387
  readonly kind: "scalar";
383
388
  readonly provenance: "verified";
389
+ readonly available: typeof isCameraCodec;
384
390
  readonly description: string;
385
391
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
386
392
  };
@@ -398,6 +404,7 @@ export declare const CAMERA_MEMBERS: {
398
404
  readonly 2: "All Sound";
399
405
  };
400
406
  readonly provenance: "verified";
407
+ readonly available: typeof isCameraCodec;
401
408
  readonly description: string;
402
409
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
403
410
  };
@@ -419,6 +426,7 @@ export declare const CAMERA_MEMBERS: {
419
426
  readonly 3: "Text First, Then Thumbnail";
420
427
  };
421
428
  readonly provenance: "verified";
429
+ readonly available: typeof isCameraCodec;
422
430
  readonly description: string;
423
431
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
424
432
  };
@@ -438,6 +446,7 @@ export declare const CAMERA_MEMBERS: {
438
446
  readonly 2: "Full Color";
439
447
  };
440
448
  readonly provenance: "verified";
449
+ readonly available: typeof isCameraCodec;
441
450
  readonly description: string;
442
451
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command | undefined;
443
452
  };
@@ -461,6 +470,7 @@ export declare const CAMERA_MEMBERS: {
461
470
  readonly kind: "enum";
462
471
  readonly enumValues: Readonly<Record<number, string>>;
463
472
  readonly provenance: "verified";
473
+ readonly available: typeof isCameraCodec;
464
474
  readonly args: readonly [{
465
475
  readonly name: "quality";
466
476
  readonly kind: "enum";
@@ -479,6 +489,7 @@ export declare const CAMERA_MEMBERS: {
479
489
  readonly param: 2731;
480
490
  readonly type: "string";
481
491
  readonly provenance: "verified";
492
+ readonly available: typeof isCameraCodec;
482
493
  readonly decode: (raw: unknown) => number | undefined;
483
494
  readonly decodedKind: "enum";
484
495
  readonly decodedValues: number[];
@@ -500,6 +511,7 @@ export declare const CAMERA_MEMBERS: {
500
511
  readonly type: "bool";
501
512
  readonly kind: "boolean";
502
513
  readonly provenance: "apk";
514
+ readonly available: typeof isCameraCodec;
503
515
  readonly description: string;
504
516
  readonly requires: readonly [1015];
505
517
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
@@ -517,6 +529,7 @@ export declare const CAMERA_MEMBERS: {
517
529
  readonly kind: "boolean";
518
530
  readonly writeOnly: true;
519
531
  readonly provenance: "verified";
532
+ readonly available: typeof isCameraCodec;
520
533
  readonly description: "Privacy mode (PRIVACY_MODE 6250) — the multi-frame burst the sink plays.";
521
534
  readonly write: (v: string | number | boolean, ctx: CommandContext) => Command;
522
535
  };
@@ -530,6 +543,7 @@ export declare const CAMERA_MEMBERS: {
530
543
  readonly type: "bool";
531
544
  readonly kind: "boolean";
532
545
  readonly provenance: "verified";
546
+ readonly available: typeof isCameraCodec;
533
547
  readonly readAvailable: (ctx: AvailabilityContext) => boolean;
534
548
  readonly readAliases: readonly [{
535
549
  readonly paramType: 1716;
@@ -556,21 +570,21 @@ export declare const CAMERA_MEMBERS: {
556
570
  * The refusal REJECTS on the four that answer with a promise, and THROWS on
557
571
  * {@link CAMERA_MEMBERS.recordFragments}, which answers with a handle.
558
572
  */
559
- readonly snapshotStored: import("./members.js").ProvidedMember<"media", (() => Promise<Buffer<ArrayBufferLike>>) | undefined>;
560
- readonly snapshotLive: import("./members.js").ProvidedMember<"media", (opts?: Parameters<MediaProvider["snapshotLive"]>[0]) => Promise<{
573
+ readonly snapshotStored: import("./members.js").ProvidedMember<"media", false | (() => Promise<Buffer<ArrayBufferLike>>) | undefined>;
574
+ readonly snapshotLive: import("./members.js").ProvidedMember<"media", false | ((opts?: Parameters<MediaProvider["snapshotLive"]>[0]) => Promise<{
561
575
  jpeg: Buffer;
562
576
  width: number;
563
577
  height: number;
564
578
  retained?: true;
565
- }>>;
579
+ }>)>;
566
580
  readonly live: import("./members.js").ProvidedMember<"media", (opts?: Parameters<MediaProvider["live"]>[0]) => Promise<import("../../core/contracts.js").LiveStreamConsumer>>;
567
- readonly record: import("./members.js").ProvidedMember<"media", (seconds: number, opts?: {
581
+ readonly record: import("./members.js").ProvidedMember<"media", false | ((seconds: number, opts?: {
568
582
  timeoutMs?: number;
569
583
  skipKeyframes?: number;
570
- } | undefined) => Promise<Buffer<ArrayBufferLike>>>;
571
- readonly openReadable: import("./members.js").ProvidedMember<"media", ((opts?: Parameters<NonNullable<MediaProvider["openReadable"]>>[0]) => Promise<import("node:stream").Readable>) | undefined>;
572
- readonly recordFragments: import("./members.js").ProvidedMember<"media", ((opts?: Parameters<NonNullable<MediaProvider["recordFragments"]>>[0]) => import("../../core/contracts.js").FragmentRecordingHandle) | undefined>;
573
- readonly downloadRecording: import("./members.js").ProvidedMember<"media", ((opts: Parameters<NonNullable<MediaProvider["downloadRecording"]>>[0]) => Promise<import("../../core/contracts.js").RecordingDownload>) | undefined>;
584
+ } | undefined) => Promise<Buffer<ArrayBufferLike>>)>;
585
+ readonly openReadable: import("./members.js").ProvidedMember<"media", false | ((opts?: Parameters<NonNullable<MediaProvider["openReadable"]>>[0]) => Promise<import("node:stream").Readable>) | undefined>;
586
+ readonly recordFragments: import("./members.js").ProvidedMember<"media", false | ((opts?: Parameters<NonNullable<MediaProvider["recordFragments"]>>[0]) => import("../../core/contracts.js").FragmentRecordingHandle) | undefined>;
587
+ readonly downloadRecording: import("./members.js").ProvidedMember<"media", false | ((opts: Parameters<NonNullable<MediaProvider["downloadRecording"]>>[0]) => Promise<import("../../core/contracts.js").RecordingDownload>) | undefined>;
574
588
  /**
575
589
  * Push audio from the host to this camera's speaker. Gated on the **speaker** param specifically —
576
590
  * not the `audio` capability, which resolves on a microphone alone and would advertise a speaker the
@@ -47,6 +47,8 @@ export declare const isHomeBase: (ctx: FamilyContext) => boolean;
47
47
  export declare const isStation9000: (ctx: FamilyContext) => boolean;
48
48
  /** T8N00 NVR, identified by its reported model. */
49
49
  export declare const isNvrT8N00: (ctx: FamilyContext) => boolean;
50
+ /** PoE cameras whose media is served by their NVR's portal call. */
51
+ export declare const isNvrMediaCamera: (ctx: FamilyContext) => boolean;
50
52
  /** Video Doorbell C31 (T8223), identified by its reported model. */
51
53
  export declare const isDoorbellT8223: (ctx: FamilyContext) => boolean;
52
54
  /** Wired doorbell (DeviceType.DOORBELL). */
@@ -0,0 +1,14 @@
1
+ import type { AudioCodec } from "../../core/contracts.js";
2
+ export declare const CMD_AUDIO_FRAME = 1301;
3
+ /** Length of the audio frame header before the payload. */
4
+ export declare const AUDIO_HEADER_LEN = 16;
5
+ /** Byte offset of the codec id between the frame-size and frame-number fields. */
6
+ export declare const AUDIO_TYPE_OFFSET = 5;
7
+ /**
8
+ * Codec ids the station puts at {@link AUDIO_TYPE_OFFSET}, as the v6 app maps them
9
+ * (`AudioReader.AAC_LC = 0`, `G711A = 2`, `AAC_ELD = 7`).
10
+ *
11
+ * The app's `PCM_SILENCE = -1` is absent on purpose: it is not a wire value. The app injects it
12
+ * itself when a stream produces no audio at all, to feed its decoder silence.
13
+ */
14
+ export declare const AUDIO_CODECS: Readonly<Record<number, AudioCodec>>;
@@ -85,6 +85,10 @@ export declare class RtcCommandRouter {
85
85
  * session. Recording has no wire here and is refused.
86
86
  */
87
87
  trackMediaProviderFor(route: RtcRoute): MediaProvider;
88
+ /** NVR media uses a dedicated call per camera, independent of station commands. */
89
+ nvrMediaProviderFor(route: RtcLiveRoute): MediaProvider;
90
+ /** Share a dedicated-call source and its consumer operations under one route key. */
91
+ private callMediaProviderFor;
88
92
  /**
89
93
  * Tear down every station session (logout / shutdown). Each live source is disposed before its session
90
94
  * closes, so its consumers end cleanly and its stop still rides the session.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The live pull of one camera behind a **HomeBase S1 Pro (T9000)**, over the station's control session.
2
+ * A portal camera live pull: T9000 shares its control session, NVR media owns a dedicated call.
3
3
  *
4
4
  * Wire, as the portal sends it on the command data channel:
5
5
  *
@@ -12,8 +12,8 @@
12
12
  * - A raw, unframed keepalive (a 20-byte prefix and a bare `XZYH 1139`) goes out every ~29 s; the hub
13
13
  * echoes it.
14
14
  *
15
- * The station serves one live view at a time on that play slot, so the router builds at most one pull per
16
- * station. This is a {@link LiveStreamHandle}: fan-out, backpressure and the start deadline are the
15
+ * A session serves one live view on that play slot. This is a {@link LiveStreamHandle}:
16
+ * fan-out, backpressure and the start deadline are the
17
17
  * shared live source's.
18
18
  */
19
19
  import { EventEmitter } from "node:events";
@@ -42,15 +42,19 @@ export interface RtcLiveOptions {
42
42
  /** The station's `member.admin_user_id`. */
43
43
  accountId: string;
44
44
  logger?: Logger;
45
+ /** NVR media owns and connects its session; uses the portal default sensor. */
46
+ nvr?: boolean;
45
47
  }
46
48
  /**
47
49
  * One camera's live pull. `start()` sends the start; a non-zero start ACK or a closed session ends it with
48
- * `error`, and `stop()` sends the stop. Frames are `h265` Annex B, keyframes being IDRs.
50
+ * `error`, and `stop()` sends the stop. Video is H.265 Annex B, keyframes being IDRs.
49
51
  */
50
52
  export declare class RtcLiveStream extends EventEmitter implements LiveStreamHandle {
51
53
  private readonly opts;
52
54
  private running;
53
55
  private startSegment;
56
+ private readonly onConnected;
57
+ private readonly onError;
54
58
  private keepalive?;
55
59
  private width;
56
60
  private height;
@@ -60,6 +64,7 @@ export declare class RtcLiveStream extends EventEmitter implements LiveStreamHan
60
64
  constructor(opts: RtcLiveOptions);
61
65
  private get tag();
62
66
  start(): this;
67
+ private sendStart;
63
68
  stop(): void;
64
69
  private teardown;
65
70
  private fail;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mega-yfue/eufy-sdk",
3
- "version": "0.5.0-beta.73",
3
+ "version": "0.5.0-beta.75",
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",