@mega-yfue/eufy-sdk 0.2.0-beta.21 → 0.2.0-beta.22

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
@@ -3230,7 +3230,14 @@ function describeBound(modules, bound, ctx) {
3230
3230
  else
3231
3231
  undescribedActions.push(name);
3232
3232
  }
3233
- out.push({ capability: m.capability, accessor, reads: reads2, actions, undescribedActions, events: emitsOf(m) });
3233
+ out.push({
3234
+ capability: m.capability,
3235
+ accessor,
3236
+ reads: reads2,
3237
+ actions,
3238
+ undescribedActions,
3239
+ events: emitsOf(m, reads2, ctx)
3240
+ });
3234
3241
  }
3235
3242
  return out;
3236
3243
  }
@@ -3249,8 +3256,22 @@ function readDescriptor(name, m, descriptors, ctx) {
3249
3256
  description: m.description
3250
3257
  };
3251
3258
  }
3252
- function emitsOf(m) {
3253
- return [.../* @__PURE__ */ new Set([...(m.events ?? []).map((e) => e.emit), ...m.emits ?? []])];
3259
+ function emitsOf(m, reads2, ctx) {
3260
+ const installed = new Set(reads2.map((r) => r.accessor));
3261
+ const claimed = (m.events ?? []).filter((e) => holds(e.claim, installed, ctx)).map((e) => e.emit);
3262
+ return [.../* @__PURE__ */ new Set([...claimed, ...m.emits ?? []])];
3263
+ }
3264
+ function holds(claim, installed, ctx) {
3265
+ if (!claim)
3266
+ return true;
3267
+ if (claim.codecs && (ctx?.codec === void 0 || !claim.codecs.includes(ctx.codec)))
3268
+ return false;
3269
+ if (claim.reads?.some((name) => !installed.has(name)))
3270
+ return false;
3271
+ if (claim.homeBaseAttached !== void 0 && ctx?.homeBaseAttached !== void 0) {
3272
+ return ctx.homeBaseAttached === claim.homeBaseAttached;
3273
+ }
3274
+ return true;
3254
3275
  }
3255
3276
 
3256
3277
  // dist/model/capabilities/video.js
@@ -3755,6 +3776,9 @@ var AiDetectType = {
3755
3776
  vehicle: 4,
3756
3777
  pet: 8
3757
3778
  };
3779
+ var CAMERA_AI_CLAIM = { codecs: ["camera"] };
3780
+ var VEHICLE_CLAIM = { ...CAMERA_AI_CLAIM, reads: ["aiDetectType"] };
3781
+ var DOG_CLAIM = { ...CAMERA_AI_CLAIM, homeBaseAttached: true };
3758
3782
  var SENSITIVITY_SCALES = [
3759
3783
  /** Standalone PIR sensor: five steps counting DOWN. */
3760
3784
  {
@@ -4146,21 +4170,24 @@ var MOTION = {
4146
4170
  events: [
4147
4171
  { source: "push", match: DoorbellPushEvent.MOTION_DETECTION, emit: "motion" },
4148
4172
  { source: "push", match: CusPushEvent.MOTION_SENSOR_PIR, emit: "motion" },
4149
- { source: "push", match: IndoorPushEvent.CRYING_DETECTION, emit: "cryingDetected" },
4150
- { source: "push", match: IndoorPushEvent.SOUND_DETECTION, emit: "soundDetected" },
4151
- { source: "push", match: DoorbellPushEvent.VEHICLE_DETECTION, emit: "vehicleDetected" },
4152
- { source: "push", match: HB3PairedDevicePushEvent.DOG_DETECTION, emit: "dogDetected" },
4173
+ { source: "push", match: IndoorPushEvent.CRYING_DETECTION, emit: "cryingDetected", claim: CAMERA_AI_CLAIM },
4174
+ { source: "push", match: IndoorPushEvent.SOUND_DETECTION, emit: "soundDetected", claim: CAMERA_AI_CLAIM },
4175
+ { source: "push", match: IndoorPushEvent.PET_DETECTION, emit: "petDetection", claim: CAMERA_AI_CLAIM },
4176
+ { source: "push", match: DoorbellPushEvent.VEHICLE_DETECTION, emit: "vehicleDetected", claim: VEHICLE_CLAIM },
4177
+ { source: "push", match: HB3PairedDevicePushEvent.DOG_DETECTION, emit: "dogDetected", claim: DOG_CLAIM },
4153
4178
  {
4154
4179
  source: "push",
4155
4180
  match: HB3PairedDevicePushEvent.DOG_LICK_DETECTION,
4156
4181
  emit: "dogDetected",
4157
- payload: { kind: "lick" }
4182
+ payload: { kind: "lick" },
4183
+ claim: DOG_CLAIM
4158
4184
  },
4159
4185
  {
4160
4186
  source: "push",
4161
4187
  match: HB3PairedDevicePushEvent.DOG_POOP_DETECTION,
4162
4188
  emit: "dogDetected",
4163
- payload: { kind: "poop" }
4189
+ payload: { kind: "poop" },
4190
+ claim: DOG_CLAIM
4164
4191
  }
4165
4192
  ]
4166
4193
  };
@@ -6830,10 +6857,16 @@ var DOORBELL = {
6830
6857
  properties: propertiesOf(DOORBELL_MEMBERS),
6831
6858
  /** Doorbells self-report no single unambiguous param; the model name is the reliable signal. */
6832
6859
  detection: { modelHints: [/doorbell/i] },
6833
- /** Inbound FCM doorbell events (`DoorbellPushEvent`): ring press, pet, package delivered/taken. */
6860
+ /**
6861
+ * Inbound FCM doorbell events (`DoorbellPushEvent`): ring press and the package trio.
6862
+ *
6863
+ * Pet (3106) is NOT here. The id is declared identically in the doorbell, indoor and HB3-paired
6864
+ * vocabularies, so it belongs to the camera-wide `motion` module that every camera binds; claiming
6865
+ * it here as well would make it a contested id that a doorbell — which has both capabilities —
6866
+ * matches twice, emitting one push as two events.
6867
+ */
6834
6868
  events: [
6835
6869
  { source: "push", match: DoorbellPushEvent.PRESS_DOORBELL, emit: "doorbellPress" },
6836
- { source: "push", match: DoorbellPushEvent.PET_DETECTION, emit: "petDetection" },
6837
6870
  { source: "push", match: DoorbellPushEvent.PACKAGE_DELIVERED, emit: "packageDelivered" },
6838
6871
  { source: "push", match: DoorbellPushEvent.PACKAGE_TAKEN, emit: "packageTaken" },
6839
6872
  { source: "push", match: DoorbellPushEvent.PACKAGE_STRANDED, emit: "packageStranded" }
@@ -8326,6 +8359,25 @@ var CARPET_STRATEGIES = ["autoRaise", "avoid", "ignore"];
8326
8359
  var CARPET_STRATEGY = { 0: "autoRaise", 1: "avoid", 2: "ignore" };
8327
8360
  var CLEAN_EXTENTS = ["normal", "narrow", "quick"];
8328
8361
  var CLEAN_EXTENT = { 0: "normal", 1: "narrow", 2: "quick" };
8362
+ function cleanParamWireValue(names, name) {
8363
+ const found = Object.entries(names).find(([, candidate]) => candidate === name);
8364
+ if (found === void 0)
8365
+ throw new Error(`clean param: ${name} is not a value this setting takes`);
8366
+ return Number(found[0]);
8367
+ }
8368
+ function writeCleanSetting(p, wrapper, inner, value) {
8369
+ p.sub(wrapper, (w) => {
8370
+ if (value !== 0)
8371
+ w.int(inner, value);
8372
+ });
8373
+ }
8374
+ function encodeCleanParam(cleanType, cleanExtent, mopLevel) {
8375
+ return rawDp((w) => w.sub(CLEAN_PARAM_FIELD.CONFIGURED, (p) => {
8376
+ writeCleanSetting(p, CLEAN_PARAM_FIELD.CLEAN_TYPE, CLEAN_PARAM_FIELD.VALUE, cleanParamWireValue(CLEAN_TYPE, cleanType));
8377
+ writeCleanSetting(p, CLEAN_PARAM_FIELD.CLEAN_EXTENT, CLEAN_PARAM_FIELD.VALUE, cleanParamWireValue(CLEAN_EXTENT, cleanExtent));
8378
+ writeCleanSetting(p, CLEAN_PARAM_FIELD.MOP_MODE, CLEAN_PARAM_FIELD.MOP_LEVEL, cleanParamWireValue(MOP_LEVEL, mopLevel));
8379
+ }));
8380
+ }
8329
8381
  function decodeCleanParamValue(raw, codec, field, inner) {
8330
8382
  if (typeof raw !== "string" || !codec)
8331
8383
  return void 0;
@@ -10005,6 +10057,49 @@ var VACUUM_CLEAN_MEMBERS = {
10005
10057
  * WATCHED: run on a T2351, it started the named scene.
10006
10058
  */
10007
10059
  startScene: method(({ sink }) => (sceneId) => sink.dispatch(aiotDp(VACUUM_DP.MODE_CTRL, encodeSceneClean(sceneId))), "Run a saved cleaning scene by its id (ModeCtrlRequest method 24 over DP 152).", isAiotVacuum),
10060
+ /**
10061
+ * State the cleaning settings a run uses — `CleanParamRequest.clean_param` over DP 154.
10062
+ *
10063
+ * The write counterpart of {@link VACUUM_CLEAN_MEMBERS.cleanType},
10064
+ * {@link VACUUM_CLEAN_MEMBERS.cleanExtent} and {@link VACUUM_CLEAN_MEMBERS.mopLevel}: one message
10065
+ * carries all three, so they are set together rather than through three setters that would each send
10066
+ * the same message with the other two silent.
10067
+ *
10068
+ * **The evidence, and its limit.** The frame is field 1 of `CleanParamRequest`, which carries the
10069
+ * very `CleanParam` this module decodes out of field 1 of the reports a live T2351 sends — the
10070
+ * field numbers, the single-field wrappers and the `mop_mode.level` scale are all read off that
10071
+ * capture, and `encodeCleanParam` writes what `decodeCleanParamValue` reads. What is NOT captured is
10072
+ * the write direction itself. It ships as a method rather than an unverified write because the
10073
+ * hazard that rule answers does not arise here: DP 154 is the robot's own settings report, so a frame
10074
+ * it does not accept leaves those three reads unchanged, where a wrong fire-and-forget command would
10075
+ * look exactly like success.
10076
+ *
10077
+ * Suction is not here. It has its own data point and its own capability — a `fan` field exists in
10078
+ * this message and is deliberately not written, for the same reason it is not read.
10079
+ */
10080
+ setCleanParam: {
10081
+ ...method(({ sink }) => (cleanType, cleanExtent, mopLevel) => sink.dispatch(aiotDp(VACUUM_DP.CLEAN_PARAM, encodeCleanParam(cleanType, cleanExtent, mopLevel))), "Set the cleaning type, extent and mop water level together (CleanParamRequest.clean_param over DP 154).", isAiotVacuum),
10082
+ args: [
10083
+ {
10084
+ name: "cleanType",
10085
+ kind: "enum",
10086
+ values: VACUUM_CLEAN_TYPES,
10087
+ description: "What the robot does with a surface."
10088
+ },
10089
+ {
10090
+ name: "cleanExtent",
10091
+ kind: "enum",
10092
+ values: CLEAN_EXTENTS,
10093
+ description: "How far past the mapped edge a job reaches. Wire order, not app order."
10094
+ },
10095
+ {
10096
+ name: "mopLevel",
10097
+ kind: "enum",
10098
+ values: MOP_LEVELS,
10099
+ description: "How much water the mop lays down. Only meaningful for a clean type that mops."
10100
+ }
10101
+ ]
10102
+ },
10008
10103
  /**
10009
10104
  * Clean the named rooms of a named map (ModeCtrlRequest method 1 over DP 152).
10010
10105
  *
@@ -13043,7 +13138,8 @@ var Device = class _Device {
13043
13138
  details: describeCapabilities(this.actionMap, {
13044
13139
  codec: this.codec,
13045
13140
  model: this.model,
13046
- capabilities: new Set(this.capabilities)
13141
+ capabilities: new Set(this.capabilities),
13142
+ homeBaseAttached: this.stationSn !== this.sn
13047
13143
  })
13048
13144
  };
13049
13145
  }