@mega-yfue/eufy-sdk 0.2.0-beta.7 → 0.2.0-beta.9

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.
@@ -4,11 +4,11 @@
4
4
  * Cloud APIs: the eufy v6 cloud (+ legacy, planned)
5
5
  * Realtime: secure MQTT (appliances) + P2P (cameras/HomeBases)
6
6
  *
7
- * const eufy = new EufyMega({ email, password, region: "eu" });
7
+ * const eufy = new EufyMega({ email, password, region: "eu-pr" });
8
8
  * await eufy.login(); // → LoginResult; on success the SDK auto-starts realtime (push/MQTT/wired P2P)
9
9
  * eufy.on("motion", (e) => console.log(e.deviceSn)); // typed semantic events — flowing already
10
10
  * const dev = await eufy.getDevice((await eufy.getDevices())[0].sn);
11
- * await dev.camera()?.snapshotStored();
11
+ * await dev.camera?.()?.snapshotStored?.();
12
12
  *
13
13
  * Connectivity is SDK-managed: the host calls no `connect*`. P2P to a battery camera is opened only
14
14
  * when a command/stream/doorbell-ring needs it and closed when idle, so the camera can sleep.
@@ -346,8 +346,8 @@ export declare class EufyMega extends EventEmitter {
346
346
  * @example
347
347
  * ```ts
348
348
  * const res = await eufy.login();
349
- * if (res.status === "captcha") await eufy.solveCaptcha(await ask(res.image));
350
- * else if (res.status === "2fa") await eufy.submitVerifyCode(await ask());
349
+ * if (res.status === "captcha") await eufy.solveCaptcha(await promptUser(res.image));
350
+ * else if (res.status === "2fa") await eufy.submitVerifyCode(await promptUser());
351
351
  * ```
352
352
  */
353
353
  login(opts?: {
@@ -493,7 +493,7 @@ export declare class EufyMega extends EventEmitter {
493
493
  * @example
494
494
  * ```ts
495
495
  * const dev = await eufy.getDevice(sn);
496
- * if (dev.has("camera")) await dev.camera()?.snapshotStored();
496
+ * if (dev.has("camera")) await dev.camera?.()?.snapshotStored?.();
497
497
  * console.log(dev.getProperty("battery"));
498
498
  * ```
499
499
  */
@@ -758,9 +758,9 @@ export interface MediaProvider {
758
758
  *
759
759
  * @example
760
760
  * ```ts
761
- * const stream = await cam.live();
762
- * stream.on("video", (frame) => write(frame.data)); // Annex-B
763
- * stream.stop(); // detach this consumer
761
+ * const stream = await cam.live?.();
762
+ * stream?.on("video", (frame) => sink.write(frame.data)); // Annex-B
763
+ * stream?.stop(); // detach this consumer
764
764
  * ```
765
765
  */
766
766
  live(opts?: SharedSourceHints & AbortableCall & Record<string, unknown>): Promise<LiveStreamConsumer>;
@@ -19,7 +19,9 @@ export type LogLevel = "debug" | "info" | "warn" | "error";
19
19
  * ```ts
20
20
  * // A custom sink (or pass a tslog / winston instance directly — they already match this shape):
21
21
  * const eufy = new EufyMega({
22
- * logger: { debug: (m, ...a) => log.debug(m, ...a), info: () => {}, warn: console.warn, error: console.error },
22
+ * email,
23
+ * password,
24
+ * logger: { debug: (m, ...a) => myLog.debug(m, ...a), info: () => {}, warn: console.warn, error: console.error },
23
25
  * });
24
26
  * ```
25
27
  */
@@ -38,8 +40,8 @@ export declare const noopLogger: Logger;
38
40
  *
39
41
  * @example
40
42
  * ```ts
41
- * const eufy = new EufyMega({ logger: new ConsoleLogger() }); // verbose
42
- * const quiet = new EufyMega({ logger: new ConsoleLogger("warn") }); // warn + error only
43
+ * const eufy = new EufyMega({ email, password, logger: new ConsoleLogger() }); // verbose
44
+ * const quiet = new EufyMega({ email, password, logger: new ConsoleLogger("warn") }); // warn + error only
43
45
  * ```
44
46
  */
45
47
  export declare class ConsoleLogger implements Logger {
package/dist/index.js CHANGED
@@ -6916,8 +6916,18 @@ var ArmingMode = {
6916
6916
  away: "away",
6917
6917
  /** Armed for occupancy — reduced/perimeter protection while home (wire value 1). */
6918
6918
  home: "home",
6919
+ /** Scheduled — the station follows the timetable configured in the app (wire value 2). */
6920
+ schedule: "schedule",
6919
6921
  /** Custom 1 — a user-defined posture configured in the app (wire value 3). */
6920
6922
  custom1: "custom1",
6923
+ /** Custom 2 — a user-defined posture configured in the app (wire value 4). */
6924
+ custom2: "custom2",
6925
+ /** Custom 3 — a user-defined posture configured in the app (wire value 5). */
6926
+ custom3: "custom3",
6927
+ /** Off — the station's alarm system is switched off entirely (wire value 6). */
6928
+ off: "off",
6929
+ /** Geofenced — the station follows the app's location-based rules (wire value 47). */
6930
+ geo: "geo",
6921
6931
  /** Disarmed — no alarms; sensors still report state (wire value 63). */
6922
6932
  disarmed: "disarmed"
6923
6933
  };
@@ -6938,10 +6948,10 @@ var ARMING_CMD = {
6938
6948
  *
6939
6949
  * ⚠️ Only 3 of the 9 modes were exercised in that capture — `mode_type` 0 (away), 63 (disarmed), 1
6940
6950
  * (home), all confirmed byte-exact. Re-confirmed live 2026-08-05: each reported its own MODE_SWITCH push
6941
- * within ~5s of the write. `custom1` 3 joined {@link ArmingMode} on a live confirmation rather than a
6942
- * capture, making four settable in total. The remaining five are named by the app but never observed
6943
- * leaving it, so this capability reads them and refuses to send them. See `ARMING_MODE_WIRE` for the
6944
- * per-value breakdown.
6951
+ * within ~5s of the write. The remaining six are live confirmations rather than captures — `custom1` 3
6952
+ * first, then `schedule` 2, `custom2` 4, `custom3` 5, `off` 6 and `geo` 47 — each sent as this exact
6953
+ * frame and each observed to bring MODE_SWITCH back, so all nine are settable. `ARMING_MODE_WIRE` has
6954
+ * the per-value evidence and the dates.
6945
6955
  */
6946
6956
  SET_ARMING: 1224,
6947
6957
  /**
@@ -6975,20 +6985,14 @@ var ARMING_MODE_WIRE = {
6975
6985
  away: 0,
6976
6986
  home: 1,
6977
6987
  schedule: 2,
6978
- // ⚠️ reportable, NOT settable — see the doc comment above
6979
6988
  custom1: 3,
6980
6989
  custom2: 4,
6981
- // ⚠️ reportable, NOT settable — see the doc comment above
6982
6990
  custom3: 5,
6983
- // ⚠️ reportable, NOT settable — see the doc comment above
6984
6991
  off: 6,
6985
- // ⚠️ reportable, NOT settable — see the doc comment above
6986
6992
  geo: 47,
6987
- // ⚠️ reportable, NOT settable — see the doc comment above
6988
6993
  disarmed: 63
6989
6994
  };
6990
6995
  var ARMING_MODE_LABELS = enumLabels(ARMING_MODE_WIRE);
6991
- var SETTABLE_MODES = Object.values(ArmingMode).map((m) => ARMING_MODE_WIRE[m]);
6992
6996
  function armingModeOf(v) {
6993
6997
  const name = String(v);
6994
6998
  if (name in ArmingMode)
@@ -6997,11 +7001,10 @@ function armingModeOf(v) {
6997
7001
  return Object.values(ArmingMode).find((m) => ARMING_MODE_WIRE[m] === wire);
6998
7002
  }
6999
7003
  function armingCommand(mode, ctx) {
7000
- const modeType = ARMING_MODE_WIRE[mode];
7001
7004
  if (!ctx.accountName) {
7002
7005
  throw new Error(`arming: missing account identity (user_name) [${describeDevice(ctx)}]`);
7003
7006
  }
7004
- return setPayload(ARMING_CMD.SET_ARMING, { mode_type: modeType, user_name: ctx.accountName }, ctx, 0);
7007
+ return setPayload(ARMING_CMD.SET_ARMING, { mode_type: ARMING_MODE_WIRE[mode], user_name: ctx.accountName }, ctx, 0);
7005
7008
  }
7006
7009
  function alarmDelayCommand(mode, config, ctx) {
7007
7010
  const data = {
@@ -7018,11 +7021,10 @@ function alarmDelayCommand(mode, config, ctx) {
7018
7021
  }
7019
7022
  var ARMING_MEMBERS = {
7020
7023
  /**
7021
- * The one member whose write domain is NARROWER than its read: `enumValues` names all nine modes a
7022
- * station can report, and the argument's `values` publishes only the four whose write is confirmed. That
7023
- * argument IS the domain the derived setter enforces and the refusal names, so an unconfirmed mode is
7024
- * refused by naming the four that work — nine labels for the read and four for the write, off one
7025
- * declaration.
7024
+ * Read and write are the same nine modes, so `enumValues` is the whole domain: `writeDomain` falls back
7025
+ * to it, and the derived setter, the refusal message and the offered argument all read from that one
7026
+ * declaration. A member states an `args` entry only where the two sides DIFFER. See
7027
+ * {@link ARMING_MODE_WIRE} for the per-value evidence.
7026
7028
  *
7027
7029
  * `armingCommand` may also throw synchronously (missing account identity) and `bindMembers` turns that
7028
7030
  * into a rejection, so the builder stays plain.
@@ -7041,8 +7043,7 @@ var ARMING_MEMBERS = {
7041
7043
  kind: "enum",
7042
7044
  enumValues: ARMING_MODE_LABELS,
7043
7045
  provenance: "verified",
7044
- args: [{ name: "mode", kind: "enum", values: SETTABLE_MODES }],
7045
- description: "Guard mode (verified: param 1224 = GUARD_MODE, read/write mechanism confirmed). Reads all 9 modes the app defines; SETS only the 4 whose write is confirmed (away/home/custom1/disarmed) \u2014 schedule/custom2/custom3/off/geo are named by the app but no capture shows one being sent, so they are refused rather than guessed; see ARMING_MODE_WIRE in arming.ts for the breakdown.",
7046
+ description: "Guard mode (verified: param 1224 = GUARD_MODE, read/write mechanism confirmed). Reads and SETS all 9 modes the app defines \u2014 away/home/schedule/custom1/custom2/custom3/off/geo/disarmed. Three are byte-captured writes and six are live-confirmed (each sent and observed to report its own MODE_SWITCH); see ARMING_MODE_WIRE in arming.ts for the per-value evidence.",
7046
7047
  observation: {
7047
7048
  event: "armingModeChanged",
7048
7049
  reflects: (value) => ({ param: ARMING_CMD.SET_ARMING, expected: ARMING_MODE_WIRE[armingModeOf(value)] }),
@@ -24284,8 +24285,8 @@ var EufyMega = class extends EventEmitter9 {
24284
24285
  * @example
24285
24286
  * ```ts
24286
24287
  * const res = await eufy.login();
24287
- * if (res.status === "captcha") await eufy.solveCaptcha(await ask(res.image));
24288
- * else if (res.status === "2fa") await eufy.submitVerifyCode(await ask());
24288
+ * if (res.status === "captcha") await eufy.solveCaptcha(await promptUser(res.image));
24289
+ * else if (res.status === "2fa") await eufy.submitVerifyCode(await promptUser());
24289
24290
  * ```
24290
24291
  */
24291
24292
  async login(opts = {}) {
@@ -24610,7 +24611,7 @@ var EufyMega = class extends EventEmitter9 {
24610
24611
  * @example
24611
24612
  * ```ts
24612
24613
  * const dev = await eufy.getDevice(sn);
24613
- * if (dev.has("camera")) await dev.camera()?.snapshotStored();
24614
+ * if (dev.has("camera")) await dev.camera?.()?.snapshotStored?.();
24614
24615
  * console.log(dev.getProperty("battery"));
24615
24616
  * ```
24616
24617
  */