@mega-yfue/eufy-sdk 0.2.0-beta.11 → 0.2.0-beta.12

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
@@ -3972,12 +3972,32 @@ function decodePowerSource(raw) {
3972
3972
  function recordSetting(param, value, ctx) {
3973
3973
  return setStationScalar(param, value, ctx.channel);
3974
3974
  }
3975
- var MAINS_CAMERA_MODELS = ["T8425", "T8419"];
3975
+ var MAINS_CAMERA_MODELS = ["T8425", "T8419", "T8410"];
3976
3976
  var notMainsCamera = (ctx) => {
3977
3977
  const model = (ctx.model ?? "").toUpperCase();
3978
3978
  return !MAINS_CAMERA_MODELS.some((prefix) => model.startsWith(prefix));
3979
3979
  };
3980
- var BATTERY_MEMBERS = {
3980
+ var CELL_PARAMS = [
3981
+ BATTERY_PARAM.BATTERY,
3982
+ BATTERY_PARAM.BATTERY_STATUS,
3983
+ BATTERY_PARAM.BATTERY_TEMP,
3984
+ BATTERY_PARAM.BATTERY_HEALTH,
3985
+ BATTERY_PARAM.SOLAR_INTENSITY,
3986
+ BATTERY_PARAM.SOLAR_CONNECT_24H,
3987
+ BATTERY_PARAM.BATTERY_POWER_DATAS
3988
+ ];
3989
+ function cellGated(members) {
3990
+ const gated = Object.entries(members).map(([name, m]) => {
3991
+ const param = m.param;
3992
+ if (typeof param !== "number" || !CELL_PARAMS.includes(param))
3993
+ return [name, m];
3994
+ const own = m.available;
3995
+ const available = own ? (ctx) => notMainsCamera(ctx) && own(ctx) : notMainsCamera;
3996
+ return [name, { ...m, available }];
3997
+ });
3998
+ return Object.fromEntries(gated);
3999
+ }
4000
+ var BATTERY_MEMBERS = cellGated({
3981
4001
  /**
3982
4002
  * The headline percentage, and this capability's detection evidence: reporting 1101 is what proves a
3983
4003
  * device is battery-powered, which is also the fact `MediaProvider` reads to decide a stream needs a
@@ -3990,7 +4010,6 @@ var BATTERY_MEMBERS = {
3990
4010
  unit: "%",
3991
4011
  kind: "percent",
3992
4012
  provenance: "verified",
3993
- available: notMainsCamera,
3994
4013
  description: "Battery level 0-100 (verified: param 1101)."
3995
4014
  },
3996
4015
  /**
@@ -4003,7 +4022,6 @@ var BATTERY_MEMBERS = {
4003
4022
  type: "bool",
4004
4023
  kind: "boolean",
4005
4024
  provenance: "apk",
4006
- available: notMainsCamera,
4007
4025
  coerce: (v) => {
4008
4026
  const n = Number(v);
4009
4027
  return n !== 0 && n !== 2;
@@ -4174,6 +4192,11 @@ var BATTERY_MEMBERS = {
4174
4192
  * Reported, so it stays in the schema and answers through `getProperty` — but given no typed getter:
4175
4193
  * the payload's fields have never been decoded, and a getter would hand back an opaque blob typed as
4176
4194
  * though it meant something.
4195
+ *
4196
+ * `unexposed` is NOT a substitute for the cell gate. It suppresses the fluent GETTER; `propertiesOf`
4197
+ * filters `writeOnly` and `available` and deliberately not `unexposed`, because a schema entry
4198
+ * reachable through `getProperty` is the whole point of the mark. So a cell param needs
4199
+ * {@link CELL_PARAMS} either way, or a mains camera publishes "battery power history" and answers it.
4177
4200
  */
4178
4201
  batteryPowerStats: {
4179
4202
  param: BATTERY_PARAM.BATTERY_POWER_DATAS,
@@ -4199,7 +4222,7 @@ var BATTERY_MEMBERS = {
4199
4222
  unexposed: true,
4200
4223
  description: "Raw GET_CAMERA_INFO value (1103), meaning unevidenced \u2014 read live as the constant 5 on a T8170 at 92% and a T8171 at 27%, so it is NOT a low-battery flag."
4201
4224
  }
4202
- };
4225
+ });
4203
4226
  var BATTERY = {
4204
4227
  capability: "battery",
4205
4228
  description: "Battery level, charging, health, temperature, and solar input.",
@@ -10093,6 +10116,16 @@ function getCapabilityModule(cap) {
10093
10116
  return BY_CAP.get(cap);
10094
10117
  }
10095
10118
  var CAPABILITY_MODULES = Object.fromEntries(MODULES.map((m) => [m.capability, m]));
10119
+ function claimedParams(caps) {
10120
+ const claimed = /* @__PURE__ */ new Set();
10121
+ for (const cap of caps)
10122
+ for (const spec of getCapabilityModule(cap)?.properties ?? []) {
10123
+ claimed.add(spec.paramType);
10124
+ for (const alias of spec.readAliases ?? [])
10125
+ claimed.add(alias.paramType);
10126
+ }
10127
+ return claimed;
10128
+ }
10096
10129
  function mergeProperties(caps, ctx) {
10097
10130
  const seen = /* @__PURE__ */ new Set();
10098
10131
  const merged = [];
@@ -12384,6 +12417,11 @@ var Device = class _Device {
12384
12417
  * different wire ids across device families still resolves to one named value.
12385
12418
  */
12386
12419
  specByParam;
12420
+ /**
12421
+ * Params a resolved capability declares that this device's schema does not carry — withheld by a
12422
+ * member's gate, so not named from the param dictionary either. See {@link Device.applyParams}.
12423
+ */
12424
+ withheld = /* @__PURE__ */ new Set();
12387
12425
  /** Which param namespace this device's ids live in (clean DPs vs security P2P). */
12388
12426
  namespace;
12389
12427
  /** The record's `device_name` as stated, before the {@link modelName} fallback is applied. */
@@ -12450,6 +12488,7 @@ var Device = class _Device {
12450
12488
  byParam.set(a.paramType, { spec: p, invert: a.invert ?? false });
12451
12489
  }
12452
12490
  this.specByParam = byParam;
12491
+ this.withheld = new Set([...claimedParams(resolved.capabilities)].filter((pt) => !byParam.has(pt)));
12453
12492
  this.namespace = namespaceForCodec(resolved.codec);
12454
12493
  this.installAccessors();
12455
12494
  }
@@ -12612,6 +12651,16 @@ var Device = class _Device {
12612
12651
  * Apply a raw param map (cloud record or P2P notification). Known params update their named
12613
12652
  * property; unrecognised params are retained as `unknown_<paramType>` so nothing is lost.
12614
12653
  *
12654
+ * Naming precedence: this device's own `PropertySpec` (curated), then the param dictionary for its
12655
+ * namespace, then the `unknown_<paramType>` passthrough. The dictionary def is consulted even where a
12656
+ * spec exists, because `encoding` lives there.
12657
+ *
12658
+ * A param a resolved capability's gate WITHHELD takes the passthrough instead of its dictionary name.
12659
+ * The gate decided the read does not describe this device, the dictionary names it what the member
12660
+ * would have, and republishing it there hands a caller a reading indistinguishable from one the device
12661
+ * really answered. A capability that never resolved withholds nothing: a param arriving before its
12662
+ * capability is still the device's own, and keeps its dictionary name.
12663
+ *
12615
12664
  * @param params param_type → raw value.
12616
12665
  * @param ts observation time (epoch ms); defaults to `Date.now()`.
12617
12666
  * @returns the list of property names whose value changed.
@@ -12624,7 +12673,7 @@ var Device = class _Device {
12624
12673
  continue;
12625
12674
  const hit = this.specByParam.get(pt);
12626
12675
  const spec = hit?.spec;
12627
- const def = paramDef(this.namespace, pt);
12676
+ const def = this.withheld.has(pt) ? void 0 : paramDef(this.namespace, pt);
12628
12677
  const name = spec ? spec.name : def ? def.name : `${UNKNOWN_PARAM_PREFIX}${pt}`;
12629
12678
  const value = def?.encoding ? decodeEncoded(rawVal, def.encoding) : spec ? coerce(spec, rawVal, hit.invert, this.logger) : def ? coerceByType(def.type, rawVal, def.name, this.logger) : String(rawVal);
12630
12679
  const prev = this.state.get(name);
@@ -26700,6 +26749,7 @@ export {
26700
26749
  buildRealtimeInit,
26701
26750
  captureSnapshotFromShared,
26702
26751
  cellAtPoint,
26752
+ claimedParams,
26703
26753
  clamp,
26704
26754
  classify,
26705
26755
  classifyDevice,