@mega-yfue/eufy-sdk 0.5.0-beta.54 → 0.5.0-beta.56

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
@@ -1605,6 +1605,8 @@ var MegaHttpClient = class {
1605
1605
  /** True while a 2FA code is outstanding: `auth_` holds only the limited pre-verify token, so the
1606
1606
  * restored-session short-circuit must NOT treat it as a usable session. Cleared on Ok/reset. */
1607
1607
  pending2fa = false;
1608
+ /** An autonomous re-login answered captcha/2FA; see {@link canReauthenticate}. */
1609
+ reloginChallenged = false;
1608
1610
  tokenExpiresAt = 0;
1609
1611
  /**
1610
1612
  * Stable per-install device id: `openudid` as configured, as restored from the session store, or as
@@ -1656,6 +1658,7 @@ var MegaHttpClient = class {
1656
1658
  *
1657
1659
  * Read at construction, and again when a rejection is being recovered from — a store SHARED with another
1658
1660
  * client may already hold the session that client obtained, which is cheaper to adopt than to compete with.
1661
+ * An adopted session is a complete one, so it ends any 2FA or challenged re-login this client was left with.
1659
1662
  *
1660
1663
  * Note: the device identity (openudid + phone model + media UA) is NOT restored here — it is resolved once
1661
1664
  * in the constructor, where an explicit config wins over the stored value, and must not be re-derived from a
@@ -1674,6 +1677,8 @@ var MegaHttpClient = class {
1674
1677
  geoKey: saved.geoKey
1675
1678
  };
1676
1679
  this.tokenExpiresAt = saved.tokenExpiresAt;
1680
+ this.pending2fa = false;
1681
+ this.reloginChallenged = false;
1677
1682
  this.sessionKey = {
1678
1683
  keyIdent: saved.keyIdent,
1679
1684
  shareKey: saved.shareKey,
@@ -2358,11 +2363,13 @@ ${this.auth_?.authToken ?? ""}`;
2358
2363
  * Structural rather than a list of paths: a login round trip is itself an authenticated call while a limited
2359
2364
  * token is held, so re-logging in from inside one would recurse — and a path list would have to be
2360
2365
  * maintained alongside every request the login flow makes. A 2FA code already outstanding is a login a human
2361
- * is part-way through, and restarting it silently would discard it. No credentials means nothing to try,
2366
+ * is part-way through, and restarting it silently would discard it. A re-login that already came back needing
2367
+ * a captcha or a 2FA code would need the same again, and each attempt sends the account another code, so
2368
+ * none is tried until a login completes or a stored session is adopted. No credentials means nothing to try,
2362
2369
  * so the rejection surfaces instead.
2363
2370
  */
2364
2371
  canReauthenticate() {
2365
- return !!this.cfg.email && !!this.cfg.password && !this.loggingIn && !this.pending2fa;
2372
+ return !!this.cfg.email && !!this.cfg.password && !this.loggingIn && !this.pending2fa && !this.reloginChallenged;
2366
2373
  }
2367
2374
  /**
2368
2375
  * Replace a rejected token by running the login state machine again, at most once at a time.
@@ -2379,8 +2386,10 @@ ${this.auth_?.authToken ?? ""}`;
2379
2386
  this.reauthAttempt ??= this.login().then((result) => {
2380
2387
  if (result.status === LoginStatus.Ok)
2381
2388
  this.logger.debug("[mega] token was rejected \u2014 logged in again");
2382
- else
2389
+ else {
2390
+ this.reloginChallenged = true;
2383
2391
  this.logger.warn(`[mega] token was rejected and the re-login needs ${result.status} \u2014 cannot recover`);
2392
+ }
2384
2393
  return result.status === LoginStatus.Ok;
2385
2394
  }).catch((e) => {
2386
2395
  this.logger.warn(`[mega] re-login failed: ${e instanceof Error ? e.message : String(e)}`);
@@ -2457,6 +2466,7 @@ ${this.auth_?.authToken ?? ""}`;
2457
2466
  }
2458
2467
  this.pendingCaptchaId = void 0;
2459
2468
  this.pending2fa = false;
2469
+ this.reloginChallenged = false;
2460
2470
  this.auth_ = { userId, accountUserId, authToken, geoKey };
2461
2471
  this.tokenExpiresAt = reply.tokenExpiresAt;
2462
2472
  this.sessionKey = void 0;
@@ -2963,6 +2973,8 @@ var KNOWN_VALUE_KINDS = [
2963
2973
  "dbm",
2964
2974
  "seconds",
2965
2975
  "hours",
2976
+ "minutes",
2977
+ "millimetres",
2966
2978
  "megabytes",
2967
2979
  "degrees",
2968
2980
  "scalar",
@@ -10663,6 +10675,221 @@ var SUCTION = {
10663
10675
  }
10664
10676
  };
10665
10677
 
10678
+ // dist/model/capabilities/mower.js
10679
+ var MOWER_DP = {
10680
+ BATTERY: 8,
10681
+ VOLUME: 26,
10682
+ CHILD_LOCK: 47,
10683
+ RAIN_AUTO_RETURN: 101,
10684
+ WIFI_SIGNAL: 109,
10685
+ MOW_HEIGHT: 110,
10686
+ SAVE_MAP_PROGRESS: 118,
10687
+ STATION_USED_TIME: 125,
10688
+ BLADE_USED_TIME: 126,
10689
+ EDGE_TRIM: 128,
10690
+ WORK_ANGLE_ENABLED: 130,
10691
+ WORK_ANGLE: 131,
10692
+ SMART_NO_GO_ZONES: 132,
10693
+ BIRD_VIEW_CAPTURE: 133,
10694
+ NETWORK: 134,
10695
+ CELLULAR_ENABLED: 137,
10696
+ EDGE_DISTANCE: 139,
10697
+ GPS_ANTI_THEFT: 140,
10698
+ SPARSE_LAWN_OPTIMIZATION: 141
10699
+ };
10700
+ var MOWER_NETWORKS = ["None", "Wifi", "Cellular"];
10701
+ var MOWER_MEMBERS = {
10702
+ /** Charge percentage (DP 8, `battery_percentage`). */
10703
+ battery: {
10704
+ param: MOWER_DP.BATTERY,
10705
+ type: "number",
10706
+ unit: "%",
10707
+ kind: "percent",
10708
+ provenance: "mega",
10709
+ description: "Battery level 0-100 (DP 8, battery_percentage). Read-only."
10710
+ },
10711
+ /** Speaker volume (DP 26, `volume_set`). */
10712
+ volume: {
10713
+ param: MOWER_DP.VOLUME,
10714
+ type: "number",
10715
+ unit: "%",
10716
+ kind: "percent",
10717
+ provenance: "mega",
10718
+ description: "Speaker volume 0-100 (DP 26, volume_set). Read-only."
10719
+ },
10720
+ /** Whether the child lock is on (DP 47, `child_lock`). */
10721
+ childLock: {
10722
+ param: MOWER_DP.CHILD_LOCK,
10723
+ type: "bool",
10724
+ kind: "boolean",
10725
+ provenance: "mega",
10726
+ description: "Child lock on (DP 47, child_lock). Read-only."
10727
+ },
10728
+ /** Whether the mower returns to its station when it detects rain (DP 101, `rain_auto_return`). */
10729
+ rainAutoReturn: {
10730
+ param: MOWER_DP.RAIN_AUTO_RETURN,
10731
+ type: "bool",
10732
+ kind: "boolean",
10733
+ provenance: "mega",
10734
+ description: "Return to the station when rain is detected (DP 101, rain_auto_return). Read-only."
10735
+ },
10736
+ /** Wi-Fi signal strength as a percentage (DP 109, `wifi_signal_strength`), not a dBm reading. */
10737
+ wifiSignal: {
10738
+ param: MOWER_DP.WIFI_SIGNAL,
10739
+ type: "number",
10740
+ unit: "%",
10741
+ kind: "percent",
10742
+ provenance: "mega",
10743
+ description: "Wi-Fi signal strength 0-100 % (DP 109, wifi_signal_strength). Read-only."
10744
+ },
10745
+ /** Cutting height in millimetres (DP 110, `mow_height`), 25-75. */
10746
+ cutHeight: {
10747
+ param: MOWER_DP.MOW_HEIGHT,
10748
+ type: "number",
10749
+ unit: "mm",
10750
+ kind: "millimetres",
10751
+ min: 25,
10752
+ max: 75,
10753
+ provenance: "mega",
10754
+ description: "Cutting height 25-75 mm (DP 110, mow_height). Read-only."
10755
+ },
10756
+ /** Progress of saving the map (DP 118, `save_map_process`). */
10757
+ mapSaveProgress: {
10758
+ param: MOWER_DP.SAVE_MAP_PROGRESS,
10759
+ type: "number",
10760
+ unit: "%",
10761
+ kind: "percent",
10762
+ provenance: "mega",
10763
+ description: "Map-save progress 0-100 % (DP 118, save_map_process). Read-only."
10764
+ },
10765
+ /** Total base-station use in minutes (DP 125, `base_station_used_time`). */
10766
+ stationUsedTime: {
10767
+ param: MOWER_DP.STATION_USED_TIME,
10768
+ type: "number",
10769
+ unit: "min",
10770
+ kind: "minutes",
10771
+ provenance: "mega",
10772
+ description: "Base-station use in minutes (DP 125, base_station_used_time). Read-only."
10773
+ },
10774
+ /** Total cutting-blade use in minutes (DP 126, `mow_blade_used_time`). */
10775
+ bladeUsedTime: {
10776
+ param: MOWER_DP.BLADE_USED_TIME,
10777
+ type: "number",
10778
+ unit: "min",
10779
+ kind: "minutes",
10780
+ provenance: "mega",
10781
+ description: "Cutting-blade use in minutes (DP 126, mow_blade_used_time). Read-only."
10782
+ },
10783
+ /** Whether edge trimming is on (DP 128, `edge_trim`). */
10784
+ edgeTrim: {
10785
+ param: MOWER_DP.EDGE_TRIM,
10786
+ type: "bool",
10787
+ kind: "boolean",
10788
+ provenance: "mega",
10789
+ description: "Edge trimming on (DP 128, edge_trim). Read-only."
10790
+ },
10791
+ /** Whether a fixed mowing angle is in use (DP 130, `enable_work_angle`); the angle is `workAngle`. */
10792
+ workAngleEnabled: {
10793
+ param: MOWER_DP.WORK_ANGLE_ENABLED,
10794
+ type: "bool",
10795
+ kind: "boolean",
10796
+ provenance: "mega",
10797
+ description: "Fixed mowing angle in use (DP 130, enable_work_angle). Read-only."
10798
+ },
10799
+ /** The mowing angle in degrees, -90 to 90 (DP 131, `work_angle`). */
10800
+ workAngle: {
10801
+ param: MOWER_DP.WORK_ANGLE,
10802
+ type: "number",
10803
+ unit: "\xB0",
10804
+ kind: "degrees",
10805
+ min: -90,
10806
+ max: 90,
10807
+ provenance: "mega",
10808
+ description: "Mowing angle -90 to 90 degrees (DP 131, work_angle). Read-only."
10809
+ },
10810
+ /** Whether smart no-go zones are on (DP 132, `enable_smart_forbid_zone`). */
10811
+ smartNoGoZones: {
10812
+ param: MOWER_DP.SMART_NO_GO_ZONES,
10813
+ type: "bool",
10814
+ kind: "boolean",
10815
+ provenance: "mega",
10816
+ description: "Smart no-go zones on (DP 132, enable_smart_forbid_zone). Read-only."
10817
+ },
10818
+ /** Whether bird's-eye-view capture is on (DP 133, `enable_bird_view_capture`). */
10819
+ birdViewCapture: {
10820
+ param: MOWER_DP.BIRD_VIEW_CAPTURE,
10821
+ type: "bool",
10822
+ kind: "boolean",
10823
+ provenance: "mega",
10824
+ description: "Bird's-eye-view capture on (DP 133, enable_bird_view_capture). Read-only."
10825
+ },
10826
+ /**
10827
+ * The network link in use (DP 134, `net_media_type`). Answers `undefined` for a value outside the
10828
+ * schema's range.
10829
+ */
10830
+ network: {
10831
+ param: MOWER_DP.NETWORK,
10832
+ type: "string",
10833
+ provenance: "mega",
10834
+ decode: (raw) => typeof raw === "string" && MOWER_NETWORKS.includes(raw) ? raw : void 0,
10835
+ decodedKind: "enum",
10836
+ decodedValues: MOWER_NETWORKS,
10837
+ description: "Network link: None, Wifi or Cellular (DP 134, net_media_type). Read-only."
10838
+ },
10839
+ /** Whether the cellular link is enabled (DP 137, `enable_cellular`). */
10840
+ cellularEnabled: {
10841
+ param: MOWER_DP.CELLULAR_ENABLED,
10842
+ type: "bool",
10843
+ kind: "boolean",
10844
+ provenance: "mega",
10845
+ description: "Cellular link enabled (DP 137, enable_cellular). Read-only."
10846
+ },
10847
+ /** Edge-following distance in millimetres (DP 139, `follow_edge_distance`), signed. */
10848
+ edgeDistance: {
10849
+ param: MOWER_DP.EDGE_DISTANCE,
10850
+ type: "number",
10851
+ unit: "mm",
10852
+ kind: "millimetres",
10853
+ min: -1e4,
10854
+ max: 1e4,
10855
+ provenance: "mega",
10856
+ description: "Edge-following distance in mm, signed (DP 139, follow_edge_distance). Read-only."
10857
+ },
10858
+ /** Whether GPS anti-theft is on (DP 140, `gps_location_check`). */
10859
+ gpsAntiTheft: {
10860
+ param: MOWER_DP.GPS_ANTI_THEFT,
10861
+ type: "bool",
10862
+ kind: "boolean",
10863
+ provenance: "mega",
10864
+ description: "GPS anti-theft on (DP 140, gps_location_check). Read-only."
10865
+ },
10866
+ /** Whether sparse-lawn optimisation is on (DP 141, `sparse_lawn_optimization`). */
10867
+ sparseLawnOptimization: {
10868
+ param: MOWER_DP.SPARSE_LAWN_OPTIMIZATION,
10869
+ type: "bool",
10870
+ kind: "boolean",
10871
+ provenance: "mega",
10872
+ description: "Sparse-lawn optimisation on (DP 141, sparse_lawn_optimization). Read-only."
10873
+ }
10874
+ };
10875
+ var MOWER_DP_IDS = Object.values(MOWER_DP);
10876
+ var MOWER = {
10877
+ capability: "mower",
10878
+ line: "clean",
10879
+ description: "Robot-mower state: battery, cutting height, settings and wear timers (read-only).",
10880
+ members: MOWER_MEMBERS,
10881
+ properties: propertiesOf(MOWER_MEMBERS),
10882
+ /**
10883
+ * The T2880 (E15) only: its Tuya product schema and a live report are the evidence for every member.
10884
+ * The E18 and C15 share the `mower` codec but neither has a schema or a report in hand.
10885
+ */
10886
+ detection: { detect: (record, codec) => codec === "mower" && record.model === "T2880" },
10887
+ decodeState(signal) {
10888
+ const params = pickDpParams(signal.source === "mqtt" ? signal.dpParams : void 0, MOWER_DP_IDS);
10889
+ return params ? { params } : null;
10890
+ }
10891
+ };
10892
+
10666
10893
  // dist/model/capabilities/dp-catalog.js
10667
10894
  var EMPTY_DP_CATALOG = {
10668
10895
  enumRanges: /* @__PURE__ */ new Map()
@@ -10918,6 +11145,7 @@ var MODULES = [
10918
11145
  VACUUM_CLEAN,
10919
11146
  VACUUM_DOCK,
10920
11147
  SUCTION,
11148
+ MOWER,
10921
11149
  LOCATE,
10922
11150
  DISPLAY,
10923
11151
  INFO
@@ -13131,6 +13359,103 @@ var DISPLAY_PARAMS = {
13131
13359
  provenance: "mega"
13132
13360
  }
13133
13361
  };
13362
+ var MOWER_PARAMS = {
13363
+ 8: {
13364
+ name: "battery",
13365
+ type: "number",
13366
+ provenance: "mega"
13367
+ },
13368
+ 26: {
13369
+ name: "volume",
13370
+ type: "number",
13371
+ provenance: "mega"
13372
+ },
13373
+ 47: {
13374
+ name: "childLock",
13375
+ type: "bool",
13376
+ provenance: "mega"
13377
+ },
13378
+ 101: {
13379
+ name: "rainAutoReturn",
13380
+ type: "bool",
13381
+ provenance: "mega"
13382
+ },
13383
+ 109: {
13384
+ name: "wifiSignal",
13385
+ type: "number",
13386
+ provenance: "mega"
13387
+ },
13388
+ 110: {
13389
+ name: "cutHeight",
13390
+ type: "number",
13391
+ provenance: "mega"
13392
+ },
13393
+ 118: {
13394
+ name: "mapSaveProgress",
13395
+ type: "number",
13396
+ provenance: "mega"
13397
+ },
13398
+ 125: {
13399
+ name: "stationUsedTime",
13400
+ type: "number",
13401
+ provenance: "mega"
13402
+ },
13403
+ 126: {
13404
+ name: "bladeUsedTime",
13405
+ type: "number",
13406
+ provenance: "mega"
13407
+ },
13408
+ 128: {
13409
+ name: "edgeTrim",
13410
+ type: "bool",
13411
+ provenance: "mega"
13412
+ },
13413
+ 130: {
13414
+ name: "workAngleEnabled",
13415
+ type: "bool",
13416
+ provenance: "mega"
13417
+ },
13418
+ 131: {
13419
+ name: "workAngle",
13420
+ type: "number",
13421
+ provenance: "mega"
13422
+ },
13423
+ 132: {
13424
+ name: "smartNoGoZones",
13425
+ type: "bool",
13426
+ provenance: "mega"
13427
+ },
13428
+ 133: {
13429
+ name: "birdViewCapture",
13430
+ type: "bool",
13431
+ provenance: "mega"
13432
+ },
13433
+ 134: {
13434
+ name: "network",
13435
+ type: "string",
13436
+ provenance: "mega"
13437
+ },
13438
+ 137: {
13439
+ name: "cellularEnabled",
13440
+ type: "bool",
13441
+ provenance: "mega"
13442
+ },
13443
+ 139: {
13444
+ name: "edgeDistance",
13445
+ type: "number",
13446
+ provenance: "mega"
13447
+ },
13448
+ 140: {
13449
+ name: "gpsAntiTheft",
13450
+ type: "bool",
13451
+ provenance: "mega"
13452
+ },
13453
+ 141: {
13454
+ name: "sparseLawnOptimization",
13455
+ type: "bool",
13456
+ provenance: "mega"
13457
+ }
13458
+ };
13134
13459
 
13135
13460
  // dist/model/life-params.js
13136
13461
  var LIFE_PARAMS = {
@@ -13154,6 +13479,8 @@ var LIFE_PARAMS = {
13154
13479
  var TABLES = {
13155
13480
  security: SECURITY_PARAMS,
13156
13481
  clean: CLEAN_PARAMS,
13482
+ // Robot mowers — their own Tuya DP space, so an id stays unnamed rather than reading as a vacuum's.
13483
+ mower: MOWER_PARAMS,
13157
13484
  life: LIFE_PARAMS,
13158
13485
  // 3D-printer (ankermake) id space — empty until a live capture confirms the param↔semantic map
13159
13486
  // (printer-support plan Stage 3). Present so the printer codec resolves to its OWN namespace rather
@@ -13173,7 +13500,7 @@ var NAMESPACE_BY_CODEC = {
13173
13500
  lock: "security",
13174
13501
  keypad: "security",
13175
13502
  vacuum: "clean",
13176
- mower: "clean",
13503
+ mower: "mower",
13177
13504
  light: "life",
13178
13505
  printer: "print",
13179
13506
  display: "display"
@@ -30902,6 +31229,7 @@ export {
30902
31229
  MODEL_REGISTRY,
30903
31230
  MOP_LEVELS,
30904
31231
  MOTION_MEMBERS,
31232
+ MOWER_MEMBERS,
30905
31233
  McsParser,
30906
31234
  MegaApiError,
30907
31235
  MegaHttpClient,