@mega-yfue/eufy-sdk 0.6.0-beta.14 → 0.6.0-beta.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/client/eufy-mega.d.ts +60 -8
- package/dist/client/types.d.ts +3 -3
- package/dist/core/contracts.d.ts +3 -1
- package/dist/core/store.d.ts +12 -1
- package/dist/index.js +704 -259
- package/dist/index.js.map +4 -4
- package/dist/transport/http/mega-client.d.ts +3 -2
- package/dist/transport/p2p/audio-frame.d.ts +13 -0
- package/dist/transport/p2p/codec.d.ts +2 -2
- package/dist/transport/p2p/command-router.d.ts +17 -0
- package/dist/transport/p2p/database-wire.d.ts +30 -0
- package/dist/transport/p2p/live-stream.d.ts +33 -7
- package/dist/transport/p2p/live-trace.d.ts +6 -4
- package/dist/transport/p2p/p2p-session.d.ts +80 -16
- package/dist/transport/p2p/readable-egress.d.ts +3 -1
- package/dist/transport/p2p/recording-download.d.ts +22 -0
- package/dist/transport/p2p/shared-live-source.d.ts +2 -1
- package/dist/transport/p2p/video.d.ts +2 -0
- package/dist/transport/push/store.d.ts +7 -6
- package/dist/transport/rtc/command-router.d.ts +63 -3
- package/dist/transport/rtc/portal-packet.d.ts +3 -13
- package/dist/transport/rtc/session.d.ts +4 -2
- package/dist/transport/stored-image-cache.d.ts +14 -0
- package/package.json +1 -1
|
@@ -20,8 +20,8 @@ import { type P2PSession } from "../transport/p2p/p2p-session.js";
|
|
|
20
20
|
import { type CleanRecordPage } from "../model/clean-records.js";
|
|
21
21
|
import { type AvailabilityObservation, type EufyDevice } from "../core/types.js";
|
|
22
22
|
import { Device, type DeviceInspection } from "../model/index.js";
|
|
23
|
-
import type { EufyMegaOptions, EufyMegaEvent, EufyMegaEventMap, DeviceState, RealtimeReadiness, StationFace,
|
|
24
|
-
export type { EufyMegaOptions, EufyMegaEvent, EufyMegaEventMap, AnyDeviceEvent, DeviceState, RealtimePlaneReadiness, RealtimeReadiness, StationFace,
|
|
23
|
+
import type { EufyMegaOptions, EufyMegaEvent, EufyMegaEventMap, DeviceState, RealtimeReadiness, StationFace, StationReadOptions, WaitForRealtimeOptions } from "./types.js";
|
|
24
|
+
export type { EufyMegaOptions, EufyMegaEvent, EufyMegaEventMap, AnyDeviceEvent, DeviceState, RealtimePlaneReadiness, RealtimeReadiness, StationFace, StationReadOptions, WaitForRealtimeOptions, } from "./types.js";
|
|
25
25
|
export interface EufyMega {
|
|
26
26
|
on<E extends EufyMegaEvent>(event: E, listener: (...args: EufyMegaEventMap[E]) => void): this;
|
|
27
27
|
once<E extends EufyMegaEvent>(event: E, listener: (...args: EufyMegaEventMap[E]) => void): this;
|
|
@@ -54,6 +54,12 @@ export declare class EufyMega extends EventEmitter {
|
|
|
54
54
|
/** Shared in-flight/settled `startMqtt()` promise PER SCOPE — so realtime bring-up and an on-demand
|
|
55
55
|
* publish await the SAME fully-connected transport instead of racing (and never open two). */
|
|
56
56
|
private readonly mqttReady;
|
|
57
|
+
/**
|
|
58
|
+
* Serials {@link subscribeMqttDevices} has subscribed or is subscribing, per transport, so a later pass
|
|
59
|
+
* subscribes only devices that transport has not carried yet. Keyed by transport, so a new connection
|
|
60
|
+
* starts empty.
|
|
61
|
+
*/
|
|
62
|
+
private readonly mqttSubscribed;
|
|
57
63
|
/** Device list/record/capability resolution + the frame→caps cache. */
|
|
58
64
|
private readonly registry;
|
|
59
65
|
private pushClient?;
|
|
@@ -385,7 +391,9 @@ export declare class EufyMega extends EventEmitter {
|
|
|
385
391
|
/**
|
|
386
392
|
* On a successful login, kick off auto-realtime (unless `autoRealtime:false`). Fire-and-forget so
|
|
387
393
|
* `login()` returns as soon as the session is ready — realtime channels come up in the background and
|
|
388
|
-
* surface failures via `error`. Idempotent through the retained generation promise.
|
|
394
|
+
* surface failures via `error`. Idempotent through the retained generation promise. A login for a
|
|
395
|
+
* different account drops every stored image; one for the same account drops only the lifecycle
|
|
396
|
+
* failures recorded against the session it replaces.
|
|
389
397
|
*/
|
|
390
398
|
private afterLogin;
|
|
391
399
|
/**
|
|
@@ -627,6 +635,12 @@ export declare class EufyMega extends EventEmitter {
|
|
|
627
635
|
* device absent from the previous pass is skipped — first sight is discovery, not a transition;
|
|
628
636
|
* {@link deviceState} answers an initial reading.
|
|
629
637
|
*
|
|
638
|
+
* A device with changed params is re-resolved by {@link widenCapabilities} once per pass, however many
|
|
639
|
+
* of its params moved, since each re-resolution is a cloud param-list read.
|
|
640
|
+
*
|
|
641
|
+
* Then brings the secure-MQTT plane up to the roster ({@link syncMqttRoster}): the startup bring-up
|
|
642
|
+
* sized it from the roster at login, which is empty when the cloud was unreachable then.
|
|
643
|
+
*
|
|
630
644
|
* Then re-reads every Tuya clean-line robot from the Tuya cloud ({@link readTuyaDevices}): its state
|
|
631
645
|
* is not in the cloud record this pass diffs and no live channel carries it, so the poll is where it
|
|
632
646
|
* stays fresh. That read runs after the `try`, not inside it, so a cloud error on the list diff does
|
|
@@ -813,11 +827,20 @@ export declare class EufyMega extends EventEmitter {
|
|
|
813
827
|
/**
|
|
814
828
|
* Subscribe the devices on one credential scope; a failing subscribe is reported, not fatal (one
|
|
815
829
|
* unreachable device must not stop the rest of the roster from coming up).
|
|
830
|
+
* A device is recorded in that transport's {@link mqttSubscribed} entry before its subscribe is awaited,
|
|
831
|
+
* whatever the outcome, so a pass running alongside or after skips it: each device is attempted once
|
|
832
|
+
* per transport.
|
|
816
833
|
*
|
|
817
834
|
* A Tuya clean-line device (`eufy_home_tuya`) is not subscribed: its state lives on the Tuya cloud,
|
|
818
835
|
* and the broker refuses its `eufy_home` topics on every credential.
|
|
819
836
|
*/
|
|
820
837
|
private subscribeMqttDevices;
|
|
838
|
+
/**
|
|
839
|
+
* Start every credential scope the roster now needs and has no transport for, and subscribe the
|
|
840
|
+
* devices that joined a scope already up — each scope's failure reported, not thrown. A no-op once
|
|
841
|
+
* the realtime generation is superseded or was never started.
|
|
842
|
+
*/
|
|
843
|
+
private syncMqttRoster;
|
|
821
844
|
/**
|
|
822
845
|
* Send whatever a device's capabilities want sent once its realtime channel is up — for a line whose
|
|
823
846
|
* state is pushed on change with no heartbeat, the request that makes its state readable before the
|
|
@@ -838,19 +861,45 @@ export declare class EufyMega extends EventEmitter {
|
|
|
838
861
|
*/
|
|
839
862
|
getP2pSessions(): Map<string, P2PSession>;
|
|
840
863
|
/**
|
|
841
|
-
* The people enrolled on a station, read from its own `person_basic_info` table
|
|
864
|
+
* The people enrolled on a station, read from its own `person_basic_info` table through
|
|
865
|
+
* {@link readStationTable}.
|
|
842
866
|
*
|
|
843
867
|
* The cloud roster (`api.getFaces()`) answers empty for an account that keeps its faces on the
|
|
844
868
|
* station, because they were never uploaded — the station holds them.
|
|
845
869
|
*
|
|
846
|
-
* Resolves with the rows the station returned
|
|
847
|
-
*
|
|
848
|
-
* reply is `P2PSession.readDatabase`'s; this resolves which station and which account id.
|
|
870
|
+
* Resolves with the rows the station returned that are objects. Rejects as {@link readStationTable}
|
|
871
|
+
* does.
|
|
849
872
|
*
|
|
850
873
|
* `stranger<n>` names are the station's own placeholders for a face nobody has named, and are
|
|
851
874
|
* returned as they arrive; a caller that wants only named people filters them.
|
|
852
875
|
*/
|
|
853
|
-
getStationFaces(stationSn: string, opts?:
|
|
876
|
+
getStationFaces(stationSn: string, opts?: StationReadOptions): Promise<StationFace[]>;
|
|
877
|
+
/**
|
|
878
|
+
* The rows of one of a station's own tables (`history_record_info`, `person_basic_info`, …), read over
|
|
879
|
+
* the transport the station speaks: the control channel of a HomeBase S1 Pro (T9000), P2P for any
|
|
880
|
+
* other station. The query is the table's whole content; the rows are the station's, shaped by it.
|
|
881
|
+
*
|
|
882
|
+
* Resolves with the rows the station returned. Rejects on a serial not in the device list, on a record
|
|
883
|
+
* stating no `admin_user_id`, on a station that cannot be reached, on a query the station refuses, and
|
|
884
|
+
* on the reply not arriving in time. Assembling the reply is the transport's; this resolves which
|
|
885
|
+
* station, which transport and which account id.
|
|
886
|
+
*/
|
|
887
|
+
readStationTable(stationSn: string, table: string, opts?: StationReadOptions): Promise<unknown[]>;
|
|
888
|
+
/**
|
|
889
|
+
* One image stored on a HomeBase S1 Pro (T9000), by the on-station path a table row names
|
|
890
|
+
* (`thumb_path`, …), read over the station's control channel.
|
|
891
|
+
*
|
|
892
|
+
* Resolves with the image bytes as the station holds them. Rejects on a serial not in the device list,
|
|
893
|
+
* on a record stating no `admin_user_id`, on a station other than a T9000, on a station that cannot be
|
|
894
|
+
* reached, and on the reply not arriving in time. Fetching the image is the transport's; this resolves
|
|
895
|
+
* which station and which account id.
|
|
896
|
+
*/
|
|
897
|
+
readStationImage(stationSn: string, filePath: string, opts?: StationReadOptions): Promise<Buffer>;
|
|
898
|
+
/**
|
|
899
|
+
* The station a database read goes to, its `admin_user_id` and, for a T9000, its RTC route. Throws,
|
|
900
|
+
* prefixed with `op`, on a serial the device list does not carry and on a record stating no admin id.
|
|
901
|
+
*/
|
|
902
|
+
private stationReadTarget;
|
|
854
903
|
/** The station's own `admin_user_id`, which its database refuses the query without. */
|
|
855
904
|
private adminUserIdOf;
|
|
856
905
|
/**
|
|
@@ -962,6 +1011,9 @@ export declare class EufyMega extends EventEmitter {
|
|
|
962
1011
|
* Returns the connected client rather than installing it. Registration can outlive a `disconnect()`,
|
|
963
1012
|
* and {@link ensureRealtime} owns the decision of whether a finished bring-up is still the current
|
|
964
1013
|
* one — so this never overwrites a channel a later login already brought up.
|
|
1014
|
+
*
|
|
1015
|
+
* Persisting the seen ids after each push reports a failed `save` through `error` rather than throwing:
|
|
1016
|
+
* the push handler runs inside the MCS socket's `data` callback, where a throw is an uncaught exception.
|
|
965
1017
|
*/
|
|
966
1018
|
private startPush;
|
|
967
1019
|
/**
|
package/dist/client/types.d.ts
CHANGED
|
@@ -240,9 +240,9 @@ export interface StationFace {
|
|
|
240
240
|
group_id?: number | string;
|
|
241
241
|
[column: string]: unknown;
|
|
242
242
|
}
|
|
243
|
-
/** How long to wait for a station's
|
|
244
|
-
export interface
|
|
245
|
-
/** Default 15s. A
|
|
243
|
+
/** How long to wait for a station's reply to a read, and how to give up early. */
|
|
244
|
+
export interface StationReadOptions {
|
|
245
|
+
/** Default 15s. A station that will not answer says nothing. */
|
|
246
246
|
timeoutMs?: number;
|
|
247
247
|
signal?: AbortSignal;
|
|
248
248
|
}
|
package/dist/core/contracts.d.ts
CHANGED
|
@@ -852,7 +852,9 @@ export interface MediaProvider {
|
|
|
852
852
|
* {@link ReceivedVideoFrame} envelopes whose original source-arrival time survives retained replay.
|
|
853
853
|
* Raw mode ignores arrivalTime. Audio is available separately through {@link live} or muxed through
|
|
854
854
|
* {@link recordFragments}; it is never interleaved into raw video. The caller owns the Readable's
|
|
855
|
-
* lifetime, and destroying it releases the shared pull.
|
|
855
|
+
* lifetime, and destroying it releases the shared pull. On a battery-budgeted source the Readable
|
|
856
|
+
* emits a `budget` event with a {@link StreamBudgetNotice}; unless `extend()` is called within its
|
|
857
|
+
* grace, the Readable ends.
|
|
856
858
|
*/
|
|
857
859
|
openReadable?(opts?: {
|
|
858
860
|
objectMode?: boolean;
|
package/dist/core/store.d.ts
CHANGED
|
@@ -48,7 +48,18 @@ export declare class MemorySessionStore<T = PersistedSession> implements Session
|
|
|
48
48
|
save(s: T): void;
|
|
49
49
|
clear(): void;
|
|
50
50
|
}
|
|
51
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* JSON-file store, e.g. new FileSessionStore("./.eufy-session.json").
|
|
53
|
+
*
|
|
54
|
+
* `save` resolves a symlinked path to its real file (the file a dangling symlink names, created with its
|
|
55
|
+
* directory), writes a fresh owner-only (`0o600`) temp file under a random name beside that file and
|
|
56
|
+
* renames it over it, so where the directory allows it the file on disk is always a complete record — the
|
|
57
|
+
* old one until the rename, the new one after — and the symlink itself stays in place. When the directory
|
|
58
|
+
* refuses the temp file or the rename (`EACCES`, `EPERM`, `EBUSY`, `EXDEV`, `EROFS`: a read-only directory
|
|
59
|
+
* around a writable file, a single-file bind mount), `save` rewrites the file in place instead, which is
|
|
60
|
+
* not atomic and keeps an existing file's mode. The atomic path always leaves `0o600`, whatever mode an
|
|
61
|
+
* existing file had. Any other failure removes the temp file and throws.
|
|
62
|
+
*/
|
|
52
63
|
export declare class FileSessionStore<T = PersistedSession> implements SessionStore<T> {
|
|
53
64
|
private readonly path;
|
|
54
65
|
constructor(path: string);
|