@mega-yfue/eufy-sdk 0.4.0-beta.13 → 0.4.0-beta.15

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/index.js CHANGED
@@ -14378,6 +14378,11 @@ var ResponseMessageType = {
14378
14378
  LOOKUP_ADDR: Buffer.from([241, 64]),
14379
14379
  LOOKUP_ADDR2: Buffer.from([241, 130]),
14380
14380
  CAM_ID: Buffer.from([241, 66]),
14381
+ /**
14382
+ * The device's own address record, sent in answer to CHECK_CAM ahead of CAM_ID: its 20-byte device id, one
14383
+ * record in `encodeSelfAddress`'s shape naming the address it answers from, then 8 zero bytes (44-byte payload).
14384
+ */
14385
+ CAM_ADDR: Buffer.from([241, 67]),
14381
14386
  TURN_SERVER_CAM_ID: Buffer.from([241, 132]),
14382
14387
  PING: Buffer.from([241, 224]),
14383
14388
  PONG: Buffer.from([241, 225]),
@@ -15737,6 +15742,9 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
15737
15742
  * straddling a level-2 wait on a camera whose failure to deliver video had a separate cause, and did not
15738
15743
  * recur across later probes of it. Correlate an unmodelled type against a WORKING session before reading it
15739
15744
  * as a cause.
15745
+ *
15746
+ * CAM_ADDR is recognised and dropped: it names the address the device is already answering from, and the
15747
+ * CAM_ID that follows it is what completes the connect.
15740
15748
  */
15741
15749
  onMessage(msg, rinfo, socket = this.socket) {
15742
15750
  if (!socket)
@@ -15767,7 +15775,7 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
15767
15775
  } else if (hasHeader(msg, ResponseMessageType.DATA)) {
15768
15776
  if (this.connected)
15769
15777
  this.onData(msg, { host: rinfo.address, port: rinfo.port });
15770
- } else {
15778
+ } else if (!hasHeader(msg, ResponseMessageType.CAM_ADDR)) {
15771
15779
  this.logger.debug(`[p2p] ${this.cfg.stationSn} UNHANDLED payload hex: ${msg.toString("hex")}`);
15772
15780
  }
15773
15781
  }
@@ -24364,6 +24372,7 @@ var MEDIA_FAILURE_REASONS = [
24364
24372
  // dist/transport/stored-image-cache.js
24365
24373
  var MAX_JPEG_BYTES = 10 * 1024 * 1024;
24366
24374
  var MAX_REMEMBERED_URLS = 64;
24375
+ var NOT_YET_PUBLISHED_RETRY_MS = [2e3, 4e3];
24367
24376
  var DIAGNOSTIC_INTERVAL_MS = 6e4;
24368
24377
  var StoredImageCache = class {
24369
24378
  downloader;
@@ -24401,6 +24410,8 @@ var StoredImageCache = class {
24401
24410
  if (state.seenUrls.has(url))
24402
24411
  return;
24403
24412
  state.seenUrls.add(url);
24413
+ clearTimeout(state.retrying);
24414
+ state.retrying = void 0;
24404
24415
  while (state.seenUrls.size > MAX_REMEMBERED_URLS) {
24405
24416
  const oldest = state.seenUrls.values().next();
24406
24417
  if (oldest.done)
@@ -24412,14 +24423,15 @@ var StoredImageCache = class {
24412
24423
  url,
24413
24424
  sequence: ++state.nextSequence,
24414
24425
  observedAt: this.clock(),
24415
- generation: this.generation
24426
+ generation: this.generation,
24427
+ retries: 0
24416
24428
  };
24417
24429
  this.pump();
24418
24430
  }
24419
24431
  /** Return retained bytes without starting or awaiting network work. */
24420
24432
  snapshotStored(deviceKey) {
24421
24433
  const state = this.devices.get(deviceKey);
24422
- const reason = state?.queued || state?.inFlight ? "pending" : state?.reason ?? "not-observed";
24434
+ const reason = state?.queued || state?.inFlight || state?.retrying ? "pending" : state?.reason ?? "not-observed";
24423
24435
  if (reason !== "pending" && state?.lifecycleError)
24424
24436
  return Promise.reject(state.lifecycleError);
24425
24437
  if (state?.retained)
@@ -24453,6 +24465,8 @@ var StoredImageCache = class {
24453
24465
  if (error !== void 0 && this.isLifecycleError(error)) {
24454
24466
  state.lifecycleError = error;
24455
24467
  state.reason = void 0;
24468
+ } else if (image === void 0 && this.retryLater(state, candidate, error)) {
24469
+ state.lifecycleError = void 0;
24456
24470
  } else if (image === void 0) {
24457
24471
  state.lifecycleError = void 0;
24458
24472
  state.reason = "download-failed";
@@ -24469,6 +24483,21 @@ var StoredImageCache = class {
24469
24483
  }
24470
24484
  this.pump();
24471
24485
  }
24486
+ /** Schedule the next attempt after a 404; answers whether one was scheduled. */
24487
+ retryLater(state, candidate, error) {
24488
+ const delay = NOT_YET_PUBLISHED_RETRY_MS[candidate.retries];
24489
+ const tag2 = mediaFailureTag(error);
24490
+ if (delay === void 0 || tag2.cause !== "http-status" || tag2.status !== 404 || state.queued)
24491
+ return false;
24492
+ const timer = setTimeout(() => {
24493
+ state.retrying = void 0;
24494
+ state.queued = { ...candidate, retries: candidate.retries + 1 };
24495
+ this.pump();
24496
+ }, delay);
24497
+ timer.unref?.();
24498
+ state.retrying = timer;
24499
+ return true;
24500
+ }
24472
24501
  isValidJpeg(image) {
24473
24502
  return Buffer.isBuffer(image) && image.length > 0 && image.length <= MAX_JPEG_BYTES && image.length >= 5 && image[0] === 255 && image[1] === 216 && image[2] === 255 && image[image.length - 2] === 255 && image[image.length - 1] === 217;
24474
24503
  }