@camstack/addon-provider-dreame 0.1.19 → 0.1.20
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/addon.js +97 -55
- package/dist/addon.mjs +97 -55
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -76387,6 +76387,93 @@ function catalogProps() {
|
|
|
76387
76387
|
return props;
|
|
76388
76388
|
}
|
|
76389
76389
|
//#endregion
|
|
76390
|
+
//#region src/dreame-gateway.ts
|
|
76391
|
+
/**
|
|
76392
|
+
* Per-broker registry that device classes use to reach the live
|
|
76393
|
+
* {@link Nodreame} facade (and its discovered device handles) for a given
|
|
76394
|
+
* Dreamehome account.
|
|
76395
|
+
*
|
|
76396
|
+
* The kernel constructs device classes with only a `DeviceContext` — it cannot
|
|
76397
|
+
* thread the facade in as a constructor arg. Like the Homematic addon's
|
|
76398
|
+
* `homematicFacades`, we keep it simple and in-process: the registry owns one
|
|
76399
|
+
* `Nodreame` facade per registered account and publishes it here; device
|
|
76400
|
+
* classes resolve their live `BaseDevice` handle by `(brokerId, deviceId)`.
|
|
76401
|
+
*/
|
|
76402
|
+
var DreameFacadeResolver = class {
|
|
76403
|
+
#facades = /* @__PURE__ */ new Map();
|
|
76404
|
+
/**
|
|
76405
|
+
* Per-(broker, device) `stateChanged` fan-out. Accessory children subscribe
|
|
76406
|
+
* here instead of attaching directly to their device handle's EventEmitter —
|
|
76407
|
+
* a robot container with dozens of children would otherwise trip Node's
|
|
76408
|
+
* default MaxListeners cap (one listener per child on a single emitter). The
|
|
76409
|
+
* integration manager pumps this bus from its single facade subscription
|
|
76410
|
+
* (the facade re-emits every handle's `stateChanged` tagged with the
|
|
76411
|
+
* deviceId); a plain `Set` of callbacks has no listener limit.
|
|
76412
|
+
*/
|
|
76413
|
+
#stateSubs = /* @__PURE__ */ new Map();
|
|
76414
|
+
/** Publish or remove the facade for a broker id. `null` removes the entry. */
|
|
76415
|
+
set(brokerId, facade) {
|
|
76416
|
+
if (facade === null) {
|
|
76417
|
+
this.#facades.delete(brokerId);
|
|
76418
|
+
return;
|
|
76419
|
+
}
|
|
76420
|
+
this.#facades.set(brokerId, facade);
|
|
76421
|
+
}
|
|
76422
|
+
/** Subscribe a child to its device's state pushes. Returns an unsubscribe fn. */
|
|
76423
|
+
onStateChanged(brokerId, dreameDeviceId, cb) {
|
|
76424
|
+
let byDevice = this.#stateSubs.get(brokerId);
|
|
76425
|
+
if (!byDevice) {
|
|
76426
|
+
byDevice = /* @__PURE__ */ new Map();
|
|
76427
|
+
this.#stateSubs.set(brokerId, byDevice);
|
|
76428
|
+
}
|
|
76429
|
+
let set = byDevice.get(dreameDeviceId);
|
|
76430
|
+
if (!set) {
|
|
76431
|
+
set = /* @__PURE__ */ new Set();
|
|
76432
|
+
byDevice.set(dreameDeviceId, set);
|
|
76433
|
+
}
|
|
76434
|
+
set.add(cb);
|
|
76435
|
+
return () => {
|
|
76436
|
+
const devices = this.#stateSubs.get(brokerId);
|
|
76437
|
+
const current = devices?.get(dreameDeviceId);
|
|
76438
|
+
current?.delete(cb);
|
|
76439
|
+
if (devices && current && current.size === 0) {
|
|
76440
|
+
devices.delete(dreameDeviceId);
|
|
76441
|
+
if (devices.size === 0) this.#stateSubs.delete(brokerId);
|
|
76442
|
+
}
|
|
76443
|
+
};
|
|
76444
|
+
}
|
|
76445
|
+
/** Fan one device's state push out to every subscribed child. */
|
|
76446
|
+
emitStateChanged(brokerId, dreameDeviceId) {
|
|
76447
|
+
const set = this.#stateSubs.get(brokerId)?.get(dreameDeviceId);
|
|
76448
|
+
if (!set) return;
|
|
76449
|
+
for (const cb of set) try {
|
|
76450
|
+
cb();
|
|
76451
|
+
} catch {}
|
|
76452
|
+
}
|
|
76453
|
+
/** The live facade for a broker id, or null when unknown / disconnected. */
|
|
76454
|
+
get(brokerId) {
|
|
76455
|
+
return this.#facades.get(brokerId) ?? null;
|
|
76456
|
+
}
|
|
76457
|
+
/**
|
|
76458
|
+
* Resolve the live {@link DreameBaseDevice} handle for a `(brokerId,
|
|
76459
|
+
* dreameDeviceId)` pair, or null when the broker is unknown or the device is
|
|
76460
|
+
* no longer present in the facade's discovered set.
|
|
76461
|
+
*/
|
|
76462
|
+
getDevice(brokerId, dreameDeviceId) {
|
|
76463
|
+
const facade = this.#facades.get(brokerId);
|
|
76464
|
+
if (!facade) return null;
|
|
76465
|
+
return facade.devices.find((d) => d.deviceId === dreameDeviceId) ?? null;
|
|
76466
|
+
}
|
|
76467
|
+
/** Remove all registered facades + subscriptions (called on full shutdown). */
|
|
76468
|
+
clear() {
|
|
76469
|
+
this.#facades.clear();
|
|
76470
|
+
this.#stateSubs.clear();
|
|
76471
|
+
}
|
|
76472
|
+
};
|
|
76473
|
+
/** The single in-process per-broker facade resolver shared between the registry
|
|
76474
|
+
* and device instances. */
|
|
76475
|
+
var dreameFacades = new DreameFacadeResolver();
|
|
76476
|
+
//#endregion
|
|
76390
76477
|
//#region src/dreame-integration-manager.ts
|
|
76391
76478
|
/**
|
|
76392
76479
|
* Wraps exactly one `@apocaliss92/nodedreame` facade (= one Dreamehome account)
|
|
@@ -76465,6 +76552,9 @@ var DreameIntegrationManager = class {
|
|
|
76465
76552
|
meta: { error: errMsg(err) }
|
|
76466
76553
|
});
|
|
76467
76554
|
});
|
|
76555
|
+
facade.on("stateChanged", (push) => {
|
|
76556
|
+
dreameFacades.emitStateChanged(this.#id, push.deviceId);
|
|
76557
|
+
});
|
|
76468
76558
|
try {
|
|
76469
76559
|
await facade.login();
|
|
76470
76560
|
const devices = await facade.discoverDevices();
|
|
@@ -76538,51 +76628,6 @@ function sameConnection(a, b) {
|
|
|
76538
76628
|
return a.username === b.username && a.password === b.password && a.region === b.region && a.pollIntervalMs === b.pollIntervalMs;
|
|
76539
76629
|
}
|
|
76540
76630
|
//#endregion
|
|
76541
|
-
//#region src/dreame-gateway.ts
|
|
76542
|
-
/**
|
|
76543
|
-
* Per-broker registry that device classes use to reach the live
|
|
76544
|
-
* {@link Nodreame} facade (and its discovered device handles) for a given
|
|
76545
|
-
* Dreamehome account.
|
|
76546
|
-
*
|
|
76547
|
-
* The kernel constructs device classes with only a `DeviceContext` — it cannot
|
|
76548
|
-
* thread the facade in as a constructor arg. Like the Homematic addon's
|
|
76549
|
-
* `homematicFacades`, we keep it simple and in-process: the registry owns one
|
|
76550
|
-
* `Nodreame` facade per registered account and publishes it here; device
|
|
76551
|
-
* classes resolve their live `BaseDevice` handle by `(brokerId, deviceId)`.
|
|
76552
|
-
*/
|
|
76553
|
-
var DreameFacadeResolver = class {
|
|
76554
|
-
#facades = /* @__PURE__ */ new Map();
|
|
76555
|
-
/** Publish or remove the facade for a broker id. `null` removes the entry. */
|
|
76556
|
-
set(brokerId, facade) {
|
|
76557
|
-
if (facade === null) {
|
|
76558
|
-
this.#facades.delete(brokerId);
|
|
76559
|
-
return;
|
|
76560
|
-
}
|
|
76561
|
-
this.#facades.set(brokerId, facade);
|
|
76562
|
-
}
|
|
76563
|
-
/** The live facade for a broker id, or null when unknown / disconnected. */
|
|
76564
|
-
get(brokerId) {
|
|
76565
|
-
return this.#facades.get(brokerId) ?? null;
|
|
76566
|
-
}
|
|
76567
|
-
/**
|
|
76568
|
-
* Resolve the live {@link DreameBaseDevice} handle for a `(brokerId,
|
|
76569
|
-
* dreameDeviceId)` pair, or null when the broker is unknown or the device is
|
|
76570
|
-
* no longer present in the facade's discovered set.
|
|
76571
|
-
*/
|
|
76572
|
-
getDevice(brokerId, dreameDeviceId) {
|
|
76573
|
-
const facade = this.#facades.get(brokerId);
|
|
76574
|
-
if (!facade) return null;
|
|
76575
|
-
return facade.devices.find((d) => d.deviceId === dreameDeviceId) ?? null;
|
|
76576
|
-
}
|
|
76577
|
-
/** Remove all registered facades (called on full shutdown). */
|
|
76578
|
-
clear() {
|
|
76579
|
-
this.#facades.clear();
|
|
76580
|
-
}
|
|
76581
|
-
};
|
|
76582
|
-
/** The single in-process per-broker facade resolver shared between the registry
|
|
76583
|
-
* and device instances. */
|
|
76584
|
-
var dreameFacades = new DreameFacadeResolver();
|
|
76585
|
-
//#endregion
|
|
76586
76631
|
//#region src/dreame-client-registry.ts
|
|
76587
76632
|
/**
|
|
76588
76633
|
* Per-integration Dreame connection registry (account mode).
|
|
@@ -77106,13 +77151,13 @@ var DreameChildDevice = class extends BaseDevice$1 {
|
|
|
77106
77151
|
this.stateChangedUnsub = null;
|
|
77107
77152
|
}
|
|
77108
77153
|
}
|
|
77109
|
-
/**
|
|
77154
|
+
/** Subscribe to this device's state pushes (recompute this child's slice).
|
|
77155
|
+
* Uses the resolver's shared fan-out bus rather than the device handle's
|
|
77156
|
+
* EventEmitter directly, so N children on one robot never trip Node's
|
|
77157
|
+
* MaxListeners cap. Works even before the facade exists — `recomputeSlice`
|
|
77158
|
+
* reads through `resolveHandle()` and replays once pushes arrive. */
|
|
77110
77159
|
attachStateListener() {
|
|
77111
|
-
|
|
77112
|
-
if (!handle) {
|
|
77113
|
-
this.ctx.logger.debug("DreameChildDevice: handle not present; no live listener yet", { meta: { dreameDeviceId: this.dreameDeviceId } });
|
|
77114
|
-
return;
|
|
77115
|
-
}
|
|
77160
|
+
this.stateChangedUnsub?.();
|
|
77116
77161
|
const onState = () => {
|
|
77117
77162
|
try {
|
|
77118
77163
|
this.recomputeSlice();
|
|
@@ -77123,10 +77168,7 @@ var DreameChildDevice = class extends BaseDevice$1 {
|
|
|
77123
77168
|
} });
|
|
77124
77169
|
}
|
|
77125
77170
|
};
|
|
77126
|
-
|
|
77127
|
-
this.stateChangedUnsub = () => {
|
|
77128
|
-
handle.off("stateChanged", onState);
|
|
77129
|
-
};
|
|
77171
|
+
this.stateChangedUnsub = dreameFacades.onStateChanged(this.brokerId, this.dreameDeviceId, onState);
|
|
77130
77172
|
}
|
|
77131
77173
|
};
|
|
77132
77174
|
//#endregion
|
package/dist/addon.mjs
CHANGED
|
@@ -76387,6 +76387,93 @@ function catalogProps() {
|
|
|
76387
76387
|
return props;
|
|
76388
76388
|
}
|
|
76389
76389
|
//#endregion
|
|
76390
|
+
//#region src/dreame-gateway.ts
|
|
76391
|
+
/**
|
|
76392
|
+
* Per-broker registry that device classes use to reach the live
|
|
76393
|
+
* {@link Nodreame} facade (and its discovered device handles) for a given
|
|
76394
|
+
* Dreamehome account.
|
|
76395
|
+
*
|
|
76396
|
+
* The kernel constructs device classes with only a `DeviceContext` — it cannot
|
|
76397
|
+
* thread the facade in as a constructor arg. Like the Homematic addon's
|
|
76398
|
+
* `homematicFacades`, we keep it simple and in-process: the registry owns one
|
|
76399
|
+
* `Nodreame` facade per registered account and publishes it here; device
|
|
76400
|
+
* classes resolve their live `BaseDevice` handle by `(brokerId, deviceId)`.
|
|
76401
|
+
*/
|
|
76402
|
+
var DreameFacadeResolver = class {
|
|
76403
|
+
#facades = /* @__PURE__ */ new Map();
|
|
76404
|
+
/**
|
|
76405
|
+
* Per-(broker, device) `stateChanged` fan-out. Accessory children subscribe
|
|
76406
|
+
* here instead of attaching directly to their device handle's EventEmitter —
|
|
76407
|
+
* a robot container with dozens of children would otherwise trip Node's
|
|
76408
|
+
* default MaxListeners cap (one listener per child on a single emitter). The
|
|
76409
|
+
* integration manager pumps this bus from its single facade subscription
|
|
76410
|
+
* (the facade re-emits every handle's `stateChanged` tagged with the
|
|
76411
|
+
* deviceId); a plain `Set` of callbacks has no listener limit.
|
|
76412
|
+
*/
|
|
76413
|
+
#stateSubs = /* @__PURE__ */ new Map();
|
|
76414
|
+
/** Publish or remove the facade for a broker id. `null` removes the entry. */
|
|
76415
|
+
set(brokerId, facade) {
|
|
76416
|
+
if (facade === null) {
|
|
76417
|
+
this.#facades.delete(brokerId);
|
|
76418
|
+
return;
|
|
76419
|
+
}
|
|
76420
|
+
this.#facades.set(brokerId, facade);
|
|
76421
|
+
}
|
|
76422
|
+
/** Subscribe a child to its device's state pushes. Returns an unsubscribe fn. */
|
|
76423
|
+
onStateChanged(brokerId, dreameDeviceId, cb) {
|
|
76424
|
+
let byDevice = this.#stateSubs.get(brokerId);
|
|
76425
|
+
if (!byDevice) {
|
|
76426
|
+
byDevice = /* @__PURE__ */ new Map();
|
|
76427
|
+
this.#stateSubs.set(brokerId, byDevice);
|
|
76428
|
+
}
|
|
76429
|
+
let set = byDevice.get(dreameDeviceId);
|
|
76430
|
+
if (!set) {
|
|
76431
|
+
set = /* @__PURE__ */ new Set();
|
|
76432
|
+
byDevice.set(dreameDeviceId, set);
|
|
76433
|
+
}
|
|
76434
|
+
set.add(cb);
|
|
76435
|
+
return () => {
|
|
76436
|
+
const devices = this.#stateSubs.get(brokerId);
|
|
76437
|
+
const current = devices?.get(dreameDeviceId);
|
|
76438
|
+
current?.delete(cb);
|
|
76439
|
+
if (devices && current && current.size === 0) {
|
|
76440
|
+
devices.delete(dreameDeviceId);
|
|
76441
|
+
if (devices.size === 0) this.#stateSubs.delete(brokerId);
|
|
76442
|
+
}
|
|
76443
|
+
};
|
|
76444
|
+
}
|
|
76445
|
+
/** Fan one device's state push out to every subscribed child. */
|
|
76446
|
+
emitStateChanged(brokerId, dreameDeviceId) {
|
|
76447
|
+
const set = this.#stateSubs.get(brokerId)?.get(dreameDeviceId);
|
|
76448
|
+
if (!set) return;
|
|
76449
|
+
for (const cb of set) try {
|
|
76450
|
+
cb();
|
|
76451
|
+
} catch {}
|
|
76452
|
+
}
|
|
76453
|
+
/** The live facade for a broker id, or null when unknown / disconnected. */
|
|
76454
|
+
get(brokerId) {
|
|
76455
|
+
return this.#facades.get(brokerId) ?? null;
|
|
76456
|
+
}
|
|
76457
|
+
/**
|
|
76458
|
+
* Resolve the live {@link DreameBaseDevice} handle for a `(brokerId,
|
|
76459
|
+
* dreameDeviceId)` pair, or null when the broker is unknown or the device is
|
|
76460
|
+
* no longer present in the facade's discovered set.
|
|
76461
|
+
*/
|
|
76462
|
+
getDevice(brokerId, dreameDeviceId) {
|
|
76463
|
+
const facade = this.#facades.get(brokerId);
|
|
76464
|
+
if (!facade) return null;
|
|
76465
|
+
return facade.devices.find((d) => d.deviceId === dreameDeviceId) ?? null;
|
|
76466
|
+
}
|
|
76467
|
+
/** Remove all registered facades + subscriptions (called on full shutdown). */
|
|
76468
|
+
clear() {
|
|
76469
|
+
this.#facades.clear();
|
|
76470
|
+
this.#stateSubs.clear();
|
|
76471
|
+
}
|
|
76472
|
+
};
|
|
76473
|
+
/** The single in-process per-broker facade resolver shared between the registry
|
|
76474
|
+
* and device instances. */
|
|
76475
|
+
var dreameFacades = new DreameFacadeResolver();
|
|
76476
|
+
//#endregion
|
|
76390
76477
|
//#region src/dreame-integration-manager.ts
|
|
76391
76478
|
/**
|
|
76392
76479
|
* Wraps exactly one `@apocaliss92/nodedreame` facade (= one Dreamehome account)
|
|
@@ -76465,6 +76552,9 @@ var DreameIntegrationManager = class {
|
|
|
76465
76552
|
meta: { error: errMsg(err) }
|
|
76466
76553
|
});
|
|
76467
76554
|
});
|
|
76555
|
+
facade.on("stateChanged", (push) => {
|
|
76556
|
+
dreameFacades.emitStateChanged(this.#id, push.deviceId);
|
|
76557
|
+
});
|
|
76468
76558
|
try {
|
|
76469
76559
|
await facade.login();
|
|
76470
76560
|
const devices = await facade.discoverDevices();
|
|
@@ -76538,51 +76628,6 @@ function sameConnection(a, b) {
|
|
|
76538
76628
|
return a.username === b.username && a.password === b.password && a.region === b.region && a.pollIntervalMs === b.pollIntervalMs;
|
|
76539
76629
|
}
|
|
76540
76630
|
//#endregion
|
|
76541
|
-
//#region src/dreame-gateway.ts
|
|
76542
|
-
/**
|
|
76543
|
-
* Per-broker registry that device classes use to reach the live
|
|
76544
|
-
* {@link Nodreame} facade (and its discovered device handles) for a given
|
|
76545
|
-
* Dreamehome account.
|
|
76546
|
-
*
|
|
76547
|
-
* The kernel constructs device classes with only a `DeviceContext` — it cannot
|
|
76548
|
-
* thread the facade in as a constructor arg. Like the Homematic addon's
|
|
76549
|
-
* `homematicFacades`, we keep it simple and in-process: the registry owns one
|
|
76550
|
-
* `Nodreame` facade per registered account and publishes it here; device
|
|
76551
|
-
* classes resolve their live `BaseDevice` handle by `(brokerId, deviceId)`.
|
|
76552
|
-
*/
|
|
76553
|
-
var DreameFacadeResolver = class {
|
|
76554
|
-
#facades = /* @__PURE__ */ new Map();
|
|
76555
|
-
/** Publish or remove the facade for a broker id. `null` removes the entry. */
|
|
76556
|
-
set(brokerId, facade) {
|
|
76557
|
-
if (facade === null) {
|
|
76558
|
-
this.#facades.delete(brokerId);
|
|
76559
|
-
return;
|
|
76560
|
-
}
|
|
76561
|
-
this.#facades.set(brokerId, facade);
|
|
76562
|
-
}
|
|
76563
|
-
/** The live facade for a broker id, or null when unknown / disconnected. */
|
|
76564
|
-
get(brokerId) {
|
|
76565
|
-
return this.#facades.get(brokerId) ?? null;
|
|
76566
|
-
}
|
|
76567
|
-
/**
|
|
76568
|
-
* Resolve the live {@link DreameBaseDevice} handle for a `(brokerId,
|
|
76569
|
-
* dreameDeviceId)` pair, or null when the broker is unknown or the device is
|
|
76570
|
-
* no longer present in the facade's discovered set.
|
|
76571
|
-
*/
|
|
76572
|
-
getDevice(brokerId, dreameDeviceId) {
|
|
76573
|
-
const facade = this.#facades.get(brokerId);
|
|
76574
|
-
if (!facade) return null;
|
|
76575
|
-
return facade.devices.find((d) => d.deviceId === dreameDeviceId) ?? null;
|
|
76576
|
-
}
|
|
76577
|
-
/** Remove all registered facades (called on full shutdown). */
|
|
76578
|
-
clear() {
|
|
76579
|
-
this.#facades.clear();
|
|
76580
|
-
}
|
|
76581
|
-
};
|
|
76582
|
-
/** The single in-process per-broker facade resolver shared between the registry
|
|
76583
|
-
* and device instances. */
|
|
76584
|
-
var dreameFacades = new DreameFacadeResolver();
|
|
76585
|
-
//#endregion
|
|
76586
76631
|
//#region src/dreame-client-registry.ts
|
|
76587
76632
|
/**
|
|
76588
76633
|
* Per-integration Dreame connection registry (account mode).
|
|
@@ -77106,13 +77151,13 @@ var DreameChildDevice = class extends BaseDevice$1 {
|
|
|
77106
77151
|
this.stateChangedUnsub = null;
|
|
77107
77152
|
}
|
|
77108
77153
|
}
|
|
77109
|
-
/**
|
|
77154
|
+
/** Subscribe to this device's state pushes (recompute this child's slice).
|
|
77155
|
+
* Uses the resolver's shared fan-out bus rather than the device handle's
|
|
77156
|
+
* EventEmitter directly, so N children on one robot never trip Node's
|
|
77157
|
+
* MaxListeners cap. Works even before the facade exists — `recomputeSlice`
|
|
77158
|
+
* reads through `resolveHandle()` and replays once pushes arrive. */
|
|
77110
77159
|
attachStateListener() {
|
|
77111
|
-
|
|
77112
|
-
if (!handle) {
|
|
77113
|
-
this.ctx.logger.debug("DreameChildDevice: handle not present; no live listener yet", { meta: { dreameDeviceId: this.dreameDeviceId } });
|
|
77114
|
-
return;
|
|
77115
|
-
}
|
|
77160
|
+
this.stateChangedUnsub?.();
|
|
77116
77161
|
const onState = () => {
|
|
77117
77162
|
try {
|
|
77118
77163
|
this.recomputeSlice();
|
|
@@ -77123,10 +77168,7 @@ var DreameChildDevice = class extends BaseDevice$1 {
|
|
|
77123
77168
|
} });
|
|
77124
77169
|
}
|
|
77125
77170
|
};
|
|
77126
|
-
|
|
77127
|
-
this.stateChangedUnsub = () => {
|
|
77128
|
-
handle.off("stateChanged", onState);
|
|
77129
|
-
};
|
|
77171
|
+
this.stateChangedUnsub = dreameFacades.onStateChanged(this.brokerId, this.dreameDeviceId, onState);
|
|
77130
77172
|
}
|
|
77131
77173
|
};
|
|
77132
77174
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreame",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|