@mega-yfue/eufy-sdk 0.4.0-beta.31 → 0.4.0-beta.32

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
@@ -3273,7 +3273,7 @@ function propertiesOf(members, ctx) {
3273
3273
  unit: m.unit,
3274
3274
  enumValues: enumValues2,
3275
3275
  provenance: m.provenance,
3276
- invert: promoted?.invert ?? m.invert,
3276
+ invert: promoted?.invert ?? (ctx ? m.invertFor?.(ctx) : void 0) ?? m.invert,
3277
3277
  decode: m.coerce,
3278
3278
  // A member with a getter-side `decode` reads a field out of a structured payload, so the
3279
3279
  // stored value is that payload — see `PropertySpec.raw`.
@@ -5205,8 +5205,10 @@ var AUDIO = {
5205
5205
 
5206
5206
  // dist/model/capabilities/camera.js
5207
5207
  var CAMERA_CMD = {
5208
- /** Camera on/off. switch is inverted: camera ON ⇒ 0, OFF ⇒ 1. */
5208
+ /** Camera on/off. Read and write polarity depend on the family and topology. */
5209
5209
  CAMERA_ENABLE: 1035,
5210
+ /** Wrapped T8410 power switch on HomeBase 3. */
5211
+ PRIVACY_MODE: 6250,
5210
5212
  /**
5211
5213
  * Camera status LED on/off — the "power/recording" indicator. The
5212
5214
  * app JS has a sibling param `1056` (`APP_CMD_LIVEVIEW_LED_SWITCH`) for the SAME UI "Status Light"
@@ -5426,7 +5428,27 @@ var ENABLE_BIT_FLOODLIGHT_TYPES = /* @__PURE__ */ new Set([
5426
5428
  function powerValue(on, ctx) {
5427
5429
  return isEnableBitPolarity(ctx) ? on ? 1 : 0 : on ? 0 : 1;
5428
5430
  }
5431
+ function isT8410HomeBase3(ctx) {
5432
+ return ctx.model === "T8410" && ctx.stationSerial?.startsWith("T8030") === true;
5433
+ }
5434
+ function usesHomeBasePowerPayload(ctx) {
5435
+ if (!isT8410HomeBase3(ctx) || !ctx.firmwareVersion || !/^\d+(?:\.\d+){2,3}$/.test(ctx.firmwareVersion))
5436
+ return false;
5437
+ const version = ctx.firmwareVersion.split(".").map(Number);
5438
+ const minimum = [2, 3, 1, 0];
5439
+ for (let i = 0; i < minimum.length; i++) {
5440
+ const difference = (version[i] ?? 0) - minimum[i];
5441
+ if (difference !== 0)
5442
+ return difference > 0;
5443
+ }
5444
+ return true;
5445
+ }
5446
+ function hasUnreflectedHomeBasePower(ctx) {
5447
+ return usesHomeBasePowerPayload(ctx) && !ctx.paramIds.has(2001);
5448
+ }
5429
5449
  function powerCommand(on, ctx) {
5450
+ if (usesHomeBasePowerPayload(ctx))
5451
+ return setPayload(CAMERA_CMD.PRIVACY_MODE, { switch: on ? 0 : 1 }, ctx, 0);
5430
5452
  return setScalar(CAMERA_CMD.CAMERA_ENABLE, powerValue(on, ctx), ctx, "auto");
5431
5453
  }
5432
5454
  function privacyCommand(enabled, channel) {
@@ -5444,28 +5466,34 @@ function enablementReflection(on, ctx) {
5444
5466
  const alias = CAMERA_MEMBERS.enabled.readAliases[0].paramType;
5445
5467
  if (ctx.paramIds.has(alias))
5446
5468
  return { param: alias, expected: on, observed: on };
5469
+ if (hasUnreflectedHomeBasePower(ctx))
5470
+ return void 0;
5447
5471
  if (ctx.paramIds.has(CAMERA_CMD.CAMERA_ENABLE)) {
5448
- return { param: CAMERA_CMD.CAMERA_ENABLE, expected: powerValue(on, ctx), observed: on };
5472
+ return {
5473
+ param: CAMERA_CMD.CAMERA_ENABLE,
5474
+ expected: powerValue(on, ctx),
5475
+ observed: on
5476
+ };
5449
5477
  }
5450
5478
  return void 0;
5451
5479
  }
5452
5480
  function refuseWhenDisabled(ctx, read) {
5453
- if (read("enabled")?.value === false)
5481
+ if (!hasUnreflectedHomeBasePower(ctx) && read("enabled")?.value === false)
5454
5482
  throw new CameraDisabledError(ctx.name ?? ctx.serial);
5455
5483
  }
5456
5484
  var CAMERA_MEMBERS = {
5457
5485
  /**
5458
- * The READ is the *disable*-bit convention (1035 "0" ⇒ ON, 2001 direct); the WRITE polarity is
5486
+ * The default READ is the *disable*-bit convention (1035 "0" ⇒ ON, 2001 direct); the WRITE polarity is
5459
5487
  * family-dependent — see `powerValue` / `isEnableBitPolarity`. Battery/solo cams report the state under
5460
5488
  * 1035, standalone indoor/outdoor cams under 2001 OPEN_DEVICE with direct polarity, so 2001 is a
5461
5489
  * read-alias. Both verified live, and the write polarity is confirmed against the app's own frames.
5462
5490
  *
5463
- * The read and the setter observe the SAME wire on every family — see `powerCommand` — which is what
5464
- * makes this value track what it is told, and what lets `enablementReflection` confirm a write.
5491
+ * T8410 on HomeBase 3 reports 1035 as an enable bit ("1" ⇒ ON). That reported state does not reliably
5492
+ * reflect the privacy command. `readReflectsWrite` states this distinction.
5465
5493
  *
5466
5494
  * The privacy param (6250) is reported by the outdoor-PT family and by no other camera measured, and both
5467
5495
  * of its polarities are observed. It is deliberately NOT aliased here: it moved in the same step as 1035, so
5468
- * the reading cannot say whether power and privacy are one state or two, and the app drives 1035 — so
5496
+ * the reading cannot say whether power and privacy are one state or two — so
5469
5497
  * aliasing a second param could only fold two possible states into one getter for no gain.
5470
5498
  */
5471
5499
  enabled: {
@@ -5474,8 +5502,10 @@ var CAMERA_MEMBERS = {
5474
5502
  kind: "boolean",
5475
5503
  provenance: "verified",
5476
5504
  invert: true,
5505
+ invertFor: (ctx) => isT8410HomeBase3(ctx) ? false : void 0,
5477
5506
  readAliases: [{ paramType: 2001, invert: false }],
5478
- description: "Camera enabled. Family-dependent wire param: 1035 CMD_DEVS_SWITCH (disable bit, battery/solo cams) or 2001 OPEN_DEVICE (standalone indoor/outdoor). Reliable on/off status source (a live-stream probe is not).",
5507
+ readReflectsWrite: (ctx) => !hasUnreflectedHomeBasePower(ctx),
5508
+ description: "Camera enabled. Family-dependent wire param: 1035 CMD_DEVS_SWITCH (enable bit on T8410/HomeBase 3, disable bit on battery/solo cams) or 2001 OPEN_DEVICE (standalone indoor/outdoor). Reported on/off state; unreflectedMembers identifies commands whose effect this report does not reliably reflect.",
5479
5509
  observation: {
5480
5510
  event: "cameraEnabledChanged",
5481
5511
  reflects: (value, ctx) => enablementReflection(asBool(value), ctx),
@@ -5702,7 +5732,7 @@ var CAMERA_MEMBERS = {
5702
5732
  * value, and it exists only on a device bound to a provider. Each is declared once, with its
5703
5733
  * signature taken FROM {@link MediaProvider} — so a change there is a compile error here, not a drift.
5704
5734
  *
5705
- * Every pull is refused where {@link CAMERA_MEMBERS.enabled} reads false, with {@link CameraDisabledError} —
5735
+ * Every pull is refused where a reliable {@link CAMERA_MEMBERS.enabled} reads false, with {@link CameraDisabledError} —
5706
5736
  * `live`, `snapshotLive`, `record`, `openReadable` and `recordFragments` alike, since each opens media on a
5707
5737
  * camera that serves none. That reading is the on/off source; a live probe is not one, since a disabled
5708
5738
  * camera answers a start with audio and never a video frame.
@@ -11160,7 +11190,8 @@ function resolveProperties(rec, codec, capabilities) {
11160
11190
  model: rec.model,
11161
11191
  category: rec.category,
11162
11192
  capabilities: new Set(capabilities),
11163
- paramIds
11193
+ paramIds,
11194
+ stationSerial: rec.parentSn
11164
11195
  });
11165
11196
  }
11166
11197
 
@@ -13350,7 +13381,8 @@ var Device = class _Device {
13350
13381
  codec: this.codec,
13351
13382
  model: this.model,
13352
13383
  capabilities: new Set(this.capabilities),
13353
- homeBaseAttached: this.stationSn !== this.sn
13384
+ homeBaseAttached: this.stationSn !== this.sn,
13385
+ stationSerial: this.stationSn
13354
13386
  })
13355
13387
  };
13356
13388
  }
@@ -27297,6 +27329,7 @@ var EufyMega = class extends EventEmitter9 {
27297
27329
  model: rec.model,
27298
27330
  category: dev.category,
27299
27331
  serial: sn,
27332
+ stationSerial: rec.parentSn,
27300
27333
  // Identity metadata for `info`, for a host's device-registry surface. `name` = the app-shown
27301
27334
  // device_name (registry's `name`), not the resolved codec/inferred name. firmware/hardware come
27302
27335
  // straight off the device record: `main_sw_version` / `main_hw_version` — the same fields the v6