@mega-yfue/eufy-sdk 0.6.0-beta.35 → 0.6.0-beta.37
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
CHANGED
|
@@ -173,10 +173,10 @@ export declare class RecordingDownloadError extends Error {
|
|
|
173
173
|
*
|
|
174
174
|
* `video` is Annex-B H.264 or H.265 in decode order, `audio` AAC-LC 16 kHz mono in ADTS framing (absent
|
|
175
175
|
* when the recording carried none that could be decoded). `codec` is the codec of `video`, read off the parameter
|
|
176
|
-
* sets of its first keyframe that carries them, and is absent when no keyframe does. `frames` counts the
|
|
177
|
-
*
|
|
178
|
-
* usable picture, including at either end. `durationMs`
|
|
179
|
-
* camera's own timestamps; `fps` is derived from those stamps.
|
|
176
|
+
* sets of its first keyframe that carries them, and is absent when no keyframe does. `frames` counts the pictures
|
|
177
|
+
* emitted, numbered by the camera's frame numbers counted on across a change of frame size. `missingFrames` counts
|
|
178
|
+
* gaps in that numbering and numbered frames that yielded no usable picture, including at either end. `durationMs`
|
|
179
|
+
* spans the first to the last emitted picture by the camera's own timestamps; `fps` is derived from those stamps.
|
|
180
180
|
*/
|
|
181
181
|
export interface RecordingDownload {
|
|
182
182
|
video: Buffer;
|
package/dist/index.js
CHANGED
|
@@ -20199,18 +20199,28 @@ function decodeRecording(frames, station, eccPrivateKeyHex) {
|
|
|
20199
20199
|
const receivedNumbers = /* @__PURE__ */ new Set();
|
|
20200
20200
|
let firstStamp;
|
|
20201
20201
|
let lastStamp;
|
|
20202
|
+
let frameSize;
|
|
20203
|
+
let shift = 0;
|
|
20204
|
+
let sequence = 0;
|
|
20202
20205
|
for (const { commandId, raw } of frames) {
|
|
20203
20206
|
if (commandId === CommandType.CMD_VIDEO_FRAME) {
|
|
20204
20207
|
const header = parseVideoFrameHeader(raw);
|
|
20205
20208
|
if (!header)
|
|
20206
20209
|
continue;
|
|
20207
|
-
|
|
20210
|
+
const size = header.width && header.height ? `${header.width}x${header.height}` : void 0;
|
|
20211
|
+
if (header.keyframe && size && frameSize !== void 0 && size !== frameSize) {
|
|
20212
|
+
shift = sequence + 1 - header.sequence & 65535;
|
|
20213
|
+
}
|
|
20214
|
+
if (size)
|
|
20215
|
+
frameSize = size;
|
|
20216
|
+
sequence = header.sequence + shift & 65535;
|
|
20217
|
+
receivedNumbers.add(sequence);
|
|
20208
20218
|
const units = assembler.push(raw, (payload) => decoder && header.keyframe ? decoder.decodeFrame(payload)?.h264 : clearVideoPayload(payload, header));
|
|
20209
20219
|
for (const unit of units) {
|
|
20210
20220
|
video.push(unit.data);
|
|
20211
20221
|
if (unit.keyframe)
|
|
20212
20222
|
codec ??= sniffAnnexbCodec(unit.data);
|
|
20213
|
-
numbers.add(
|
|
20223
|
+
numbers.add(sequence);
|
|
20214
20224
|
const stamp = raw.readUIntLE(14, 6);
|
|
20215
20225
|
firstStamp ??= stamp;
|
|
20216
20226
|
lastStamp = stamp;
|
|
@@ -25545,13 +25555,14 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25545
25555
|
closeAnnounced = false;
|
|
25546
25556
|
sdpHandled = false;
|
|
25547
25557
|
chain = Promise.resolve();
|
|
25558
|
+
stageReached = "signing";
|
|
25559
|
+
lastPeerState;
|
|
25548
25560
|
constructor(opts) {
|
|
25549
25561
|
super();
|
|
25550
25562
|
this.opts = opts;
|
|
25551
25563
|
this.logger = opts.logger ?? noopLogger;
|
|
25552
25564
|
this.signaling = (opts.createSignaling ?? ((o) => new RtcSignalingClient(o)))(opts);
|
|
25553
25565
|
this.peer = (opts.createPeer ?? ((o) => new RtcPeer(o)))({ logger: this.logger, ...opts.peer });
|
|
25554
|
-
const mediaTrack = opts.peer?.mediaTrack === true;
|
|
25555
25566
|
this.signaling.on("message", (inner) => {
|
|
25556
25567
|
this.chain = this.chain.then(() => this.onSignaling(inner)).catch((e) => {
|
|
25557
25568
|
this.emit("error", e instanceof Error ? e : new Error(String(e)));
|
|
@@ -25565,6 +25576,7 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25565
25576
|
if (this.connected)
|
|
25566
25577
|
return;
|
|
25567
25578
|
this.connected = true;
|
|
25579
|
+
this.stageReached = "connected";
|
|
25568
25580
|
this.logger.debug(`[rtc] ${this.opts.stationSn} command channel open`);
|
|
25569
25581
|
this.emit("connected");
|
|
25570
25582
|
});
|
|
@@ -25576,9 +25588,14 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25576
25588
|
this.announceClose();
|
|
25577
25589
|
});
|
|
25578
25590
|
this.peer.on("connectionState", (state) => {
|
|
25579
|
-
|
|
25591
|
+
this.lastPeerState = state;
|
|
25592
|
+
if (state !== "failed" && state !== "closed")
|
|
25593
|
+
return;
|
|
25594
|
+
if (this.connected || this.mediaTrack) {
|
|
25580
25595
|
this.connected = false;
|
|
25581
25596
|
this.announceClose();
|
|
25597
|
+
} else {
|
|
25598
|
+
this.shutdown(new Error(`RTC ${this.opts.stationSn} peer ${state} before the command channel opened`));
|
|
25582
25599
|
}
|
|
25583
25600
|
});
|
|
25584
25601
|
this.peer.on("error", (e) => this.emit("error", e));
|
|
@@ -25591,9 +25608,20 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25591
25608
|
this.emit("commandData", frame, linkType);
|
|
25592
25609
|
});
|
|
25593
25610
|
}
|
|
25611
|
+
get mediaTrack() {
|
|
25612
|
+
return this.opts.peer?.mediaTrack === true;
|
|
25613
|
+
}
|
|
25594
25614
|
get isConnected() {
|
|
25595
25615
|
return this.connected;
|
|
25596
25616
|
}
|
|
25617
|
+
/** The last bring-up stage this session reached. */
|
|
25618
|
+
get stage() {
|
|
25619
|
+
return this.stageReached;
|
|
25620
|
+
}
|
|
25621
|
+
/** The peer connection's last reported state; `undefined` before it reports one. */
|
|
25622
|
+
get peerState() {
|
|
25623
|
+
return this.lastPeerState;
|
|
25624
|
+
}
|
|
25597
25625
|
/**
|
|
25598
25626
|
* Start the sequence; resolves once the call is sent. `connected` fires when the channel opens. A session
|
|
25599
25627
|
* closed by the time the sign fetch or the auth completes rejects instead of opening the socket or
|
|
@@ -25603,11 +25631,14 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25603
25631
|
await this.signaling.fetchSign();
|
|
25604
25632
|
if (this.closed)
|
|
25605
25633
|
throw new Error("RTC session closed before the call was placed");
|
|
25634
|
+
this.stageReached = "connecting";
|
|
25606
25635
|
await this.signaling.connect();
|
|
25636
|
+
this.stageReached = "authenticating";
|
|
25607
25637
|
await this.waitForAuth();
|
|
25608
25638
|
if (this.closed)
|
|
25609
25639
|
throw new Error("RTC session closed before the call was placed");
|
|
25610
25640
|
this.logger.debug(`[rtc] ${this.opts.stationSn} authenticated \u2014 ${this.opts.signalingMode ?? "scall"}`);
|
|
25641
|
+
this.stageReached = "calling";
|
|
25611
25642
|
this.signaling.sendCall();
|
|
25612
25643
|
}
|
|
25613
25644
|
/** Send one portal packet; false when the command channel isn't open. */
|
|
@@ -25703,6 +25734,9 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25703
25734
|
return;
|
|
25704
25735
|
case "hangup":
|
|
25705
25736
|
this.logger.debug(`[rtc] ${this.opts.stationSn} hub hung up`);
|
|
25737
|
+
if (!this.connected && this.opts.signalingMode !== "call") {
|
|
25738
|
+
this.shutdown(new Error(`RTC ${this.opts.stationSn} hub hung up before the command channel opened`));
|
|
25739
|
+
}
|
|
25706
25740
|
return;
|
|
25707
25741
|
default:
|
|
25708
25742
|
return;
|
|
@@ -25715,6 +25749,7 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25715
25749
|
const status = payload.status;
|
|
25716
25750
|
if (status === 100 && payload.turn) {
|
|
25717
25751
|
this.turn = payload.turn;
|
|
25752
|
+
this.stageReached = "relay-granted";
|
|
25718
25753
|
try {
|
|
25719
25754
|
await this.peer.init(payload.turn);
|
|
25720
25755
|
} catch (e) {
|
|
@@ -25770,6 +25805,7 @@ var RtcSession = class extends EventEmitter11 {
|
|
|
25770
25805
|
}
|
|
25771
25806
|
const answer = await this.peer.handleRemoteOffer(offer);
|
|
25772
25807
|
this.signaling.sendInfoSdp(this.opts.signalingMode === "call" ? answer : JSON.stringify(sdpToScallJson(answer)));
|
|
25808
|
+
this.stageReached = "answered";
|
|
25773
25809
|
this.logger.debug(`[rtc] ${this.opts.stationSn} answered the hub's offer`);
|
|
25774
25810
|
}
|
|
25775
25811
|
};
|
|
@@ -26248,7 +26284,8 @@ var RtcCommandRouter = class {
|
|
|
26248
26284
|
/**
|
|
26249
26285
|
* One bounded bring-up: the session is up when its command channel opens, and it fails, with the
|
|
26250
26286
|
* session closed and every listener gone, when `connect()` throws, the session closes first (rejecting
|
|
26251
|
-
* with the failure that closed it, when it carries one), or {@link CONNECT_TIMEOUT_MS} passes
|
|
26287
|
+
* with the failure that closed it, when it carries one), or {@link CONNECT_TIMEOUT_MS} passes, naming the
|
|
26288
|
+
* stage the session reached and its peer's last state. A single
|
|
26252
26289
|
* promise, so an early failure cannot leave a second one rejecting unheard.
|
|
26253
26290
|
*/
|
|
26254
26291
|
bringUp(sn, session) {
|
|
@@ -26274,7 +26311,7 @@ var RtcCommandRouter = class {
|
|
|
26274
26311
|
};
|
|
26275
26312
|
const onConnected = () => finish();
|
|
26276
26313
|
const onClose = (err) => finish(err ?? new Error(`rtc: ${sn} session closed before the command channel opened`));
|
|
26277
|
-
const timer = setTimeout(() => finish(new Error(`rtc: ${sn} did not come up within ${CONNECT_TIMEOUT_MS2}ms`)), CONNECT_TIMEOUT_MS2);
|
|
26314
|
+
const timer = setTimeout(() => finish(new Error(`rtc: ${sn} did not come up within ${CONNECT_TIMEOUT_MS2}ms (stage ${session.stage}, peer ${session.peerState ?? "not started"})`)), CONNECT_TIMEOUT_MS2);
|
|
26278
26315
|
session.once("connected", onConnected);
|
|
26279
26316
|
session.once("close", onClose);
|
|
26280
26317
|
Promise.resolve().then(() => session.connect()).catch((e) => finish(e instanceof Error ? e : new Error(String(e))));
|