@mega-yfue/eufy-sdk 0.5.0-beta.51 → 0.5.0-beta.52

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.
@@ -454,8 +454,9 @@ export declare class EufyMega extends EventEmitter {
454
454
  *
455
455
  * Side-effect: registers `eufy_home_tuya` devices with the Tuya command router so
456
456
  * the command dispatcher can resolve a eufy SN → Tuya devId without a separate lookup.
457
- * The Tuya id is extracted from the device's raw cloud record (`tuya_uuid`, `tuya_virtual_id`,
458
- * `tuya_device_id`, or `virtualId` fields — whichever is non-empty).
457
+ * The Tuya id is the first non-empty `tuya_uuid`, `tuya_virtual_id`, `tuya_device_id` or
458
+ * `virtualId` on the raw cloud record, else the device's serial: the app keys its Tuya device by
459
+ * the eufy device id, and a record that carries none of those fields is read under its serial.
459
460
  *
460
461
  * A partial cloud outage still resolves, with the devices that answered plus the ones already known — but a
461
462
  * session the cloud has rejected REJECTS, with {@link SessionExpiredError}. An empty list would be
@@ -790,6 +791,10 @@ export declare class EufyMega extends EventEmitter {
790
791
  /**
791
792
  * Subscribe the devices on one credential scope; a failing subscribe is reported, not fatal (one
792
793
  * unreachable device must not stop the rest of the roster from coming up).
794
+ *
795
+ * A Tuya clean-line device's DPs are also read from the Tuya cloud, whether or not its subscribe
796
+ * succeeded: the cloud read is a separate plane, and the broker can refuse a subscribe for a device
797
+ * whose DPs the Tuya cloud still serves.
793
798
  */
794
799
  private subscribeMqttDevices;
795
800
  /**
package/dist/index.js CHANGED
@@ -25525,11 +25525,11 @@ function buildPublishDpsAction(devId, gwId, dps) {
25525
25525
  postData: JSON.stringify({ gwId, devId, dps: JSON.stringify(dps) })
25526
25526
  };
25527
25527
  }
25528
- function buildGetDeviceDpsAction(devId, dpCacheType = 1) {
25528
+ function buildGetDeviceDpsAction(devId) {
25529
25529
  return {
25530
- a: "smartlife.m.device.cache.dp.get",
25531
- v: "2.0",
25532
- postData: JSON.stringify({ devId, dpCacheType })
25530
+ a: "smartlife.m.device.dp.get",
25531
+ v: "1.0",
25532
+ postData: JSON.stringify({ devId })
25533
25533
  };
25534
25534
  }
25535
25535
  function buildUsernameTokenGetAction(countryCode, username) {
@@ -25685,11 +25685,12 @@ var TuyaClient = class {
25685
25685
  return { sid: result.sid, uid: result.uid };
25686
25686
  }
25687
25687
  /**
25688
- * READ/dump a device's cached data-points (`smartlife.m.device.cache.dp.get`).
25689
- * Builds the request without needing a working signer; the signer is only exercised on send.
25688
+ * READ a device's current data-points (`smartlife.m.device.dp.get`). The envelope's `result` is a
25689
+ * flat `{ "<dpId>": value }` map. Builds the request without needing a working signer; the signer is
25690
+ * only exercised on send.
25690
25691
  */
25691
- async getDeviceDps(devId, dpCacheType) {
25692
- return this.call(buildGetDeviceDpsAction(devId, dpCacheType));
25692
+ async getDeviceDps(devId) {
25693
+ return this.call(buildGetDeviceDpsAction(devId));
25693
25694
  }
25694
25695
  /**
25695
25696
  * CONTROL: publish data-points to a device (`smartlife.m.device.dp.publish`). `dps` is
@@ -25780,9 +25781,9 @@ var TuyaCommandRouter = class {
25780
25781
  /** Promise that resolves once Tuya login has completed. Reset by {@link bind}. */
25781
25782
  loginOnce = null;
25782
25783
  /**
25783
- * eufy SN → Tuya device ids, populated by the facade via {@link registerDevice}.
25784
- * The facade extracts the Tuya id from the `raw` device record fields (`tuya_uuid`,
25785
- * `tuya_virtual_id`, `tuya_device_id`, `virtualId`) and registers it once the device list loads.
25784
+ * eufy SN → Tuya device ids, populated via {@link registerDevice} once the device list loads.
25785
+ * The Tuya id is the record's first non-empty `tuya_uuid` / `tuya_virtual_id` / `tuya_device_id` /
25786
+ * `virtualId`, or the device's serial when the record carries none of them.
25786
25787
  */
25787
25788
  snMap = /* @__PURE__ */ new Map();
25788
25789
  constructor(config = {}) {
@@ -25804,10 +25805,10 @@ var TuyaCommandRouter = class {
25804
25805
  this.loginOnce = null;
25805
25806
  }
25806
25807
  /**
25807
- * Register a eufy SN → Tuya devId mapping. Called by the facade for each `eufy_home_tuya`
25808
- * device after the cloud device list loads. The facade extracts the Tuya id from the device's
25809
- * raw record (`tuya_uuid` / `tuya_virtual_id` / `tuya_device_id` / `virtualId` fields).
25810
- * `gwId` defaults to `devId` — standalone devices share the two.
25808
+ * Register a eufy SN → Tuya devId mapping for an `eufy_home_tuya` device. `devId` is the record's
25809
+ * first non-empty `tuya_uuid` / `tuya_virtual_id` / `tuya_device_id` / `virtualId`, or the device's
25810
+ * serial when the record carries none of them. `gwId` defaults to `devId` — standalone devices
25811
+ * share the two.
25811
25812
  */
25812
25813
  registerDevice(sn, devId, gwId = devId) {
25813
25814
  this.snMap.set(sn, { devId, gwId });
@@ -25831,13 +25832,9 @@ var TuyaCommandRouter = class {
25831
25832
  return this.loginOnce;
25832
25833
  }
25833
25834
  /**
25834
- * Fetch a device's cached DPs from the Tuya cloud (`smartlife.m.device.cache.dp.get`) and deliver
25835
- * the raw DP map to the caller. Used for initial state hydration after MQTT subscribe — gets the
25836
- * last-known state without waiting for the first realtime push.
25837
- *
25838
- * The response shape from `getDeviceDps` is not yet pinned from a live capture. The defensive
25839
- * extraction tries both `result.dps` (a nested map) and bare `result` (a flat map), and returns
25840
- * `null` when neither yields a non-empty record.
25835
+ * Read a device's current DPs from the Tuya cloud (`smartlife.m.device.dp.get`) and answer the DP
25836
+ * map: the reply's flat `result`, kept to integer DP keys with scalar values. Answers `null` for an
25837
+ * unregistered device, a failed reply, or a reply with no DPs.
25841
25838
  */
25842
25839
  async fetchDps(sn) {
25843
25840
  const ids = this.snMap.get(sn);
@@ -25847,12 +25844,8 @@ var TuyaCommandRouter = class {
25847
25844
  const res = await this.client.getDeviceDps(ids.devId);
25848
25845
  if (!res.success || !res.result)
25849
25846
  return null;
25850
- const nested = res.result.dps;
25851
- if (nested && typeof nested === "object" && !Array.isArray(nested) && Object.keys(nested).length > 0) {
25852
- return nested;
25853
- }
25854
- const flat = parseTuyaDpEvent(res.result);
25855
- return flat ? flat : null;
25847
+ const dps = parseTuyaDpEvent(res.result);
25848
+ return dps ? dps : null;
25856
25849
  }
25857
25850
  /**
25858
25851
  * Route an `aiot-dp` {@link Command} to the Tuya REST API.
@@ -25871,7 +25864,7 @@ var TuyaCommandRouter = class {
25871
25864
  await this.ensureLoggedIn();
25872
25865
  const ids = this.snMap.get(sn);
25873
25866
  if (!ids) {
25874
- throw new Error(`TuyaCommandRouter: no Tuya device id registered for ${sn}. Ensure getDevices() was called and the cloud record includes a tuya_uuid / tuya_virtual_id field.`);
25867
+ throw new Error(`TuyaCommandRouter: no Tuya device id registered for ${sn}. Ensure getDevices() was called; it registers every eufy_home_tuya device under its Tuya id or its serial.`);
25875
25868
  }
25876
25869
  await this.client.publishDps(ids.devId, ids.gwId, { [cmd.dp]: cmd.value }, { allowUnverified: this.allowUnverified });
25877
25870
  }
@@ -28679,8 +28672,9 @@ var EufyMega = class extends EventEmitter13 {
28679
28672
  *
28680
28673
  * Side-effect: registers `eufy_home_tuya` devices with the Tuya command router so
28681
28674
  * the command dispatcher can resolve a eufy SN → Tuya devId without a separate lookup.
28682
- * The Tuya id is extracted from the device's raw cloud record (`tuya_uuid`, `tuya_virtual_id`,
28683
- * `tuya_device_id`, or `virtualId` fields — whichever is non-empty).
28675
+ * The Tuya id is the first non-empty `tuya_uuid`, `tuya_virtual_id`, `tuya_device_id` or
28676
+ * `virtualId` on the raw cloud record, else the device's serial: the app keys its Tuya device by
28677
+ * the eufy device id, and a record that carries none of those fields is read under its serial.
28684
28678
  *
28685
28679
  * A partial cloud outage still resolves, with the devices that answered plus the ones already known — but a
28686
28680
  * session the cloud has rejected REJECTS, with {@link SessionExpiredError}. An empty list would be
@@ -28692,9 +28686,7 @@ var EufyMega = class extends EventEmitter13 {
28692
28686
  if (dev.category !== "eufy_home_tuya")
28693
28687
  continue;
28694
28688
  const raw = dev.raw ?? {};
28695
- const devId = tuyaDevIdFrom(raw);
28696
- if (devId)
28697
- this.tuya.registerDevice(dev.sn, devId);
28689
+ this.tuya.registerDevice(dev.sn, tuyaDevIdFrom(raw) ?? dev.sn);
28698
28690
  }
28699
28691
  return devices;
28700
28692
  }
@@ -29362,21 +29354,25 @@ var EufyMega = class extends EventEmitter13 {
29362
29354
  /**
29363
29355
  * Subscribe the devices on one credential scope; a failing subscribe is reported, not fatal (one
29364
29356
  * unreachable device must not stop the rest of the roster from coming up).
29357
+ *
29358
+ * A Tuya clean-line device's DPs are also read from the Tuya cloud, whether or not its subscribe
29359
+ * succeeded: the cloud read is a separate plane, and the broker can refuse a subscribe for a device
29360
+ * whose DPs the Tuya cloud still serves.
29365
29361
  */
29366
29362
  async subscribeMqttDevices(scope, transport) {
29367
29363
  for (const d of this.getMqttDevices().filter((dev) => mqttScopeFor(dev) === scope)) {
29368
29364
  try {
29369
29365
  await transport.subscribeDevice(d);
29370
29366
  await this.sendRealtimeInit(d.sn);
29371
- if (d.category === "eufy_home_tuya") {
29372
- this.tuya.fetchDps(d.sn).then((dps) => {
29373
- if (dps)
29374
- this.tuyaDpRouter.deliver(d.sn, dps);
29375
- }).catch((e) => this.reportError(e));
29376
- }
29377
29367
  } catch (e) {
29378
29368
  this.reportError(e);
29379
29369
  }
29370
+ if (d.category === "eufy_home_tuya") {
29371
+ this.tuya.fetchDps(d.sn).then((dps) => {
29372
+ if (dps)
29373
+ this.tuyaDpRouter.deliver(d.sn, dps);
29374
+ }).catch((e) => this.reportError(e));
29375
+ }
29380
29376
  }
29381
29377
  }
29382
29378
  /**