@mega-yfue/eufy-sdk 0.2.0-beta.11 → 0.2.0-beta.13
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
|
|
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 = [];
|
|
@@ -10375,6 +10408,11 @@ var MODEL_REGISTRY = {
|
|
|
10375
10408
|
T8210: { codec: "camera", caps: ["doorbell", "battery"], name: "Video Doorbell" },
|
|
10376
10409
|
// Confirmed against a real owned unit (named "Doorbell"): Video Doorbell Dual.
|
|
10377
10410
|
T8214: { codec: "camera", caps: ["doorbell", "battery"], name: "Video Doorbell Dual" },
|
|
10411
|
+
// Confirmed against a real owned unit: the mains-powered Wired Doorbell 2K. No `battery` row
|
|
10412
|
+
// member on purpose — this model is wired, so the codec baseline plus inference is the whole
|
|
10413
|
+
// truth for power. Without this row it classified as a plain camera, so the doorbell capability
|
|
10414
|
+
// never appeared and consumers got no doorbell event entity or ring trigger.
|
|
10415
|
+
T8200: { codec: "camera", caps: ["doorbell"], name: "Wired Doorbell 2K" },
|
|
10378
10416
|
// Cameras observed on real owned hardware (inspect-device sweep). Names from the app's own
|
|
10379
10417
|
// model-family constants (scripts/data/app_model_registry.json); caps mirror what the device
|
|
10380
10418
|
// reports. T8171 has no family entry in that dump, so it keeps the raw T-code.
|
|
@@ -12384,6 +12422,11 @@ var Device = class _Device {
|
|
|
12384
12422
|
* different wire ids across device families still resolves to one named value.
|
|
12385
12423
|
*/
|
|
12386
12424
|
specByParam;
|
|
12425
|
+
/**
|
|
12426
|
+
* Params a resolved capability declares that this device's schema does not carry — withheld by a
|
|
12427
|
+
* member's gate, so not named from the param dictionary either. See {@link Device.applyParams}.
|
|
12428
|
+
*/
|
|
12429
|
+
withheld = /* @__PURE__ */ new Set();
|
|
12387
12430
|
/** Which param namespace this device's ids live in (clean DPs vs security P2P). */
|
|
12388
12431
|
namespace;
|
|
12389
12432
|
/** The record's `device_name` as stated, before the {@link modelName} fallback is applied. */
|
|
@@ -12450,6 +12493,7 @@ var Device = class _Device {
|
|
|
12450
12493
|
byParam.set(a.paramType, { spec: p, invert: a.invert ?? false });
|
|
12451
12494
|
}
|
|
12452
12495
|
this.specByParam = byParam;
|
|
12496
|
+
this.withheld = new Set([...claimedParams(resolved.capabilities)].filter((pt) => !byParam.has(pt)));
|
|
12453
12497
|
this.namespace = namespaceForCodec(resolved.codec);
|
|
12454
12498
|
this.installAccessors();
|
|
12455
12499
|
}
|
|
@@ -12612,6 +12656,16 @@ var Device = class _Device {
|
|
|
12612
12656
|
* Apply a raw param map (cloud record or P2P notification). Known params update their named
|
|
12613
12657
|
* property; unrecognised params are retained as `unknown_<paramType>` so nothing is lost.
|
|
12614
12658
|
*
|
|
12659
|
+
* Naming precedence: this device's own `PropertySpec` (curated), then the param dictionary for its
|
|
12660
|
+
* namespace, then the `unknown_<paramType>` passthrough. The dictionary def is consulted even where a
|
|
12661
|
+
* spec exists, because `encoding` lives there.
|
|
12662
|
+
*
|
|
12663
|
+
* A param a resolved capability's gate WITHHELD takes the passthrough instead of its dictionary name.
|
|
12664
|
+
* The gate decided the read does not describe this device, the dictionary names it what the member
|
|
12665
|
+
* would have, and republishing it there hands a caller a reading indistinguishable from one the device
|
|
12666
|
+
* really answered. A capability that never resolved withholds nothing: a param arriving before its
|
|
12667
|
+
* capability is still the device's own, and keeps its dictionary name.
|
|
12668
|
+
*
|
|
12615
12669
|
* @param params param_type → raw value.
|
|
12616
12670
|
* @param ts observation time (epoch ms); defaults to `Date.now()`.
|
|
12617
12671
|
* @returns the list of property names whose value changed.
|
|
@@ -12624,7 +12678,7 @@ var Device = class _Device {
|
|
|
12624
12678
|
continue;
|
|
12625
12679
|
const hit = this.specByParam.get(pt);
|
|
12626
12680
|
const spec = hit?.spec;
|
|
12627
|
-
const def = paramDef(this.namespace, pt);
|
|
12681
|
+
const def = this.withheld.has(pt) ? void 0 : paramDef(this.namespace, pt);
|
|
12628
12682
|
const name = spec ? spec.name : def ? def.name : `${UNKNOWN_PARAM_PREFIX}${pt}`;
|
|
12629
12683
|
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
12684
|
const prev = this.state.get(name);
|
|
@@ -26700,6 +26754,7 @@ export {
|
|
|
26700
26754
|
buildRealtimeInit,
|
|
26701
26755
|
captureSnapshotFromShared,
|
|
26702
26756
|
cellAtPoint,
|
|
26757
|
+
claimedParams,
|
|
26703
26758
|
clamp,
|
|
26704
26759
|
classify,
|
|
26705
26760
|
classifyDevice,
|