@mega-yfue/eufy-sdk 0.5.0-beta.14 → 0.5.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.
|
@@ -92,6 +92,8 @@ export declare class DeviceRegistry {
|
|
|
92
92
|
private overlayRefusalReported;
|
|
93
93
|
/** Per-serial capability cache for {@link capabilitiesForDevice}; `null` = negative hit. */
|
|
94
94
|
private readonly deviceCapsCache;
|
|
95
|
+
/** Per-serial cloud data points of an AIoT robot, joined beneath the params in {@link record} — see {@link loadCloudDps}. */
|
|
96
|
+
private readonly cloudDps;
|
|
95
97
|
/** Per-serial realtime state, keyed by param id in the device's own namespace (see {@link DeviceRecord.dpParams}). */
|
|
96
98
|
private readonly dpParams;
|
|
97
99
|
/** Callers blocked in {@link awaitRealtimeState}, released by the device's first report. */
|
|
@@ -181,9 +183,26 @@ export declare class DeviceRegistry {
|
|
|
181
183
|
* transport stacks own the claim predicate over the record.
|
|
182
184
|
*/
|
|
183
185
|
require(sn: string): EufyDevice;
|
|
186
|
+
/**
|
|
187
|
+
* Hold an AIoT robot's cloud data points: the cloud's last-known value of each one it has reported,
|
|
188
|
+
* from `getDeviceRelationList`'s per-device `dps`.
|
|
189
|
+
*
|
|
190
|
+
* The device list carries only some of a robot's data points, so a point the robot publishes on change
|
|
191
|
+
* alone (its scene list, its schedules, its consumables) has no value until it next reports. The
|
|
192
|
+
* relation list holds every one, for an account the robot is shared with as well as its owner.
|
|
193
|
+
*
|
|
194
|
+
* Kept apart from the device list's params rather than merged into them: those are what a poll diffs,
|
|
195
|
+
* and a diff retires the realtime report for that id, so a cloud value lagging the robot's last report
|
|
196
|
+
* would replace it. {@link record} joins this beneath both halves. A failure keeps what was held.
|
|
197
|
+
*
|
|
198
|
+
* Limited to {@link CLOUD_DPS_MODELS}, the models whose relation-list `dps` are checked to carry the
|
|
199
|
+
* DP numbers their realtime reports use.
|
|
200
|
+
*/
|
|
201
|
+
private loadCloudDps;
|
|
184
202
|
/**
|
|
185
203
|
* Resolve a serial to a {@link DeviceRecord} with current params: starts from the device-list params, then
|
|
186
|
-
* overlays a fresh `get_device_param_list` when that call is available to this account.
|
|
204
|
+
* overlays a fresh `get_device_param_list` when that call is available to this account. An AIoT robot's
|
|
205
|
+
* cloud data points ({@link loadCloudDps}) sit beneath both, filling only ids neither carries.
|
|
187
206
|
*
|
|
188
207
|
* The overlay is **owner-gated** — a shared or member account is refused it for every device, permanently,
|
|
189
208
|
* which {@link OWNER_ONLY_CODE} identifies — so when it is unavailable the device list is the source
|
package/dist/index.js
CHANGED
|
@@ -1996,6 +1996,17 @@ ${this.auth_?.authToken ?? ""}`;
|
|
|
1996
1996
|
device_sns: [deviceSn]
|
|
1997
1997
|
});
|
|
1998
1998
|
}
|
|
1999
|
+
/**
|
|
2000
|
+
* Fetch the account's devices as the `devicerelation` service lists them, `{attribute: 7, house_id: ""}`.
|
|
2001
|
+
*
|
|
2002
|
+
* Each entry is `{device: {device_sn, dps, …}}`, and `dps` is the cloud's last-known value of every
|
|
2003
|
+
* data point that device has reported, keyed by DP number. Answered for an account a device is shared
|
|
2004
|
+
* with as well as for its owner. Sent with `category: eufy_home`, without which the service answers
|
|
2005
|
+
* `10000`.
|
|
2006
|
+
*/
|
|
2007
|
+
getDeviceRelationList() {
|
|
2008
|
+
return this.post("devicerelation", "/app/devicerelation/get_device_list", { attribute: 7, house_id: "" }, { category: "eufy_home" });
|
|
2009
|
+
}
|
|
1999
2010
|
/**
|
|
2000
2011
|
* Fetch one page of a device's **cleaning history** from the mega `clean` service.
|
|
2001
2012
|
*
|
|
@@ -26331,6 +26342,7 @@ function deviceClassOf(codec, realtime) {
|
|
|
26331
26342
|
return cls === "camera" && realtime !== "p2p" ? "other" : cls;
|
|
26332
26343
|
}
|
|
26333
26344
|
var LIST_REUSE_MS = 5e3;
|
|
26345
|
+
var CLOUD_DPS_MODELS = /* @__PURE__ */ new Set(["T2351"]);
|
|
26334
26346
|
var DeviceRegistry = class {
|
|
26335
26347
|
mega;
|
|
26336
26348
|
onError;
|
|
@@ -26355,6 +26367,8 @@ var DeviceRegistry = class {
|
|
|
26355
26367
|
overlayRefusalReported = false;
|
|
26356
26368
|
/** Per-serial capability cache for {@link capabilitiesForDevice}; `null` = negative hit. */
|
|
26357
26369
|
deviceCapsCache = /* @__PURE__ */ new Map();
|
|
26370
|
+
/** Per-serial cloud data points of an AIoT robot, joined beneath the params in {@link record} — see {@link loadCloudDps}. */
|
|
26371
|
+
cloudDps = /* @__PURE__ */ new Map();
|
|
26358
26372
|
/** Per-serial realtime state, keyed by param id in the device's own namespace (see {@link DeviceRecord.dpParams}). */
|
|
26359
26373
|
dpParams = /* @__PURE__ */ new Map();
|
|
26360
26374
|
/** Callers blocked in {@link awaitRealtimeState}, released by the device's first report. */
|
|
@@ -26464,6 +26478,7 @@ var DeviceRegistry = class {
|
|
|
26464
26478
|
});
|
|
26465
26479
|
}
|
|
26466
26480
|
}
|
|
26481
|
+
await this.loadCloudDps(seen);
|
|
26467
26482
|
this.lastRefreshPartial = partial;
|
|
26468
26483
|
if (partial) {
|
|
26469
26484
|
for (const prev of this.devices)
|
|
@@ -26554,9 +26569,46 @@ var DeviceRegistry = class {
|
|
|
26554
26569
|
}
|
|
26555
26570
|
return dev;
|
|
26556
26571
|
}
|
|
26572
|
+
/**
|
|
26573
|
+
* Hold an AIoT robot's cloud data points: the cloud's last-known value of each one it has reported,
|
|
26574
|
+
* from `getDeviceRelationList`'s per-device `dps`.
|
|
26575
|
+
*
|
|
26576
|
+
* The device list carries only some of a robot's data points, so a point the robot publishes on change
|
|
26577
|
+
* alone (its scene list, its schedules, its consumables) has no value until it next reports. The
|
|
26578
|
+
* relation list holds every one, for an account the robot is shared with as well as its owner.
|
|
26579
|
+
*
|
|
26580
|
+
* Kept apart from the device list's params rather than merged into them: those are what a poll diffs,
|
|
26581
|
+
* and a diff retires the realtime report for that id, so a cloud value lagging the robot's last report
|
|
26582
|
+
* would replace it. {@link record} joins this beneath both halves. A failure keeps what was held.
|
|
26583
|
+
*
|
|
26584
|
+
* Limited to {@link CLOUD_DPS_MODELS}, the models whose relation-list `dps` are checked to carry the
|
|
26585
|
+
* DP numbers their realtime reports use.
|
|
26586
|
+
*/
|
|
26587
|
+
async loadCloudDps(seen) {
|
|
26588
|
+
const robots = [...seen.values()].filter((d) => CLOUD_DPS_MODELS.has(d.model ?? ""));
|
|
26589
|
+
if (!robots.length)
|
|
26590
|
+
return;
|
|
26591
|
+
let res;
|
|
26592
|
+
try {
|
|
26593
|
+
res = await this.mega.getDeviceRelationList();
|
|
26594
|
+
} catch (e) {
|
|
26595
|
+
if (e instanceof SessionExpiredError)
|
|
26596
|
+
throw e;
|
|
26597
|
+
this.logger.debug(`[registry] device relation list unavailable: ${e?.message ?? e}`);
|
|
26598
|
+
return;
|
|
26599
|
+
}
|
|
26600
|
+
const wanted = new Set(robots.map((d) => d.sn));
|
|
26601
|
+
for (const entry of res.devices ?? []) {
|
|
26602
|
+
const sn = entry?.device?.device_sn;
|
|
26603
|
+
const dps = parseAiotDpReport({ payload: entry?.device?.dps });
|
|
26604
|
+
if (sn && wanted.has(sn) && dps)
|
|
26605
|
+
this.cloudDps.set(sn, dps);
|
|
26606
|
+
}
|
|
26607
|
+
}
|
|
26557
26608
|
/**
|
|
26558
26609
|
* Resolve a serial to a {@link DeviceRecord} with current params: starts from the device-list params, then
|
|
26559
|
-
* overlays a fresh `get_device_param_list` when that call is available to this account.
|
|
26610
|
+
* overlays a fresh `get_device_param_list` when that call is available to this account. An AIoT robot's
|
|
26611
|
+
* cloud data points ({@link loadCloudDps}) sit beneath both, filling only ids neither carries.
|
|
26560
26612
|
*
|
|
26561
26613
|
* The overlay is **owner-gated** — a shared or member account is refused it for every device, permanently,
|
|
26562
26614
|
* which {@link OWNER_ONLY_CODE} identifies — so when it is unavailable the device list is the source
|
|
@@ -26585,7 +26637,7 @@ var DeviceRegistry = class {
|
|
|
26585
26637
|
let dev = this.devices.find((d) => d.sn === sn);
|
|
26586
26638
|
if (!dev)
|
|
26587
26639
|
throw new Error(`device ${sn} not found (have: ${this.devices.map((d) => d.sn).join(", ")})`);
|
|
26588
|
-
const params = { ...dev.params ?? {} };
|
|
26640
|
+
const params = { ...this.cloudDps.get(sn), ...dev.params ?? {} };
|
|
26589
26641
|
const paramUpdatedAt = { ...dev.paramUpdatedAt ?? {} };
|
|
26590
26642
|
if (!this.overlayRefused.has(sn)) {
|
|
26591
26643
|
try {
|