@riddix/hamh 2.1.0-alpha.830 → 2.1.0-alpha.832
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/backend/cli.js
CHANGED
|
@@ -130689,7 +130689,14 @@ var init_controller_compat = __esm({
|
|
|
130689
130689
|
google: "no",
|
|
130690
130690
|
alexa: "unknown",
|
|
130691
130691
|
aqara: "unknown",
|
|
130692
|
-
note: "
|
|
130692
|
+
note: "SolarPower is only rendered standalone by SmartThings today."
|
|
130693
|
+
},
|
|
130694
|
+
1300: {
|
|
130695
|
+
apple: "no",
|
|
130696
|
+
google: "yes",
|
|
130697
|
+
alexa: "no",
|
|
130698
|
+
aqara: "unknown",
|
|
130699
|
+
note: "ElectricalMeter shows in Google Home and SmartThings; Apple and Alexa do not surface standalone power/energy."
|
|
130693
130700
|
},
|
|
130694
130701
|
24: {
|
|
130695
130702
|
apple: "no",
|
|
@@ -131529,6 +131536,12 @@ var init_bridge_config_schema = __esm({
|
|
|
131529
131536
|
description: "When a controller drops all subscriptions, clean up the dead session and re-announce after 5 seconds instead of 60. Opt-in for Google Home users whose devices go offline after a cancelled subscription (#386). It shortens the offline window but cannot stop the controller from rejecting the subscription. Default off.",
|
|
131530
131537
|
type: "boolean",
|
|
131531
131538
|
default: false
|
|
131539
|
+
},
|
|
131540
|
+
stableIdentity: {
|
|
131541
|
+
title: "Stable Device Identity",
|
|
131542
|
+
description: "Anchor each device to its Home Assistant entity registry id instead of the entity id, so renaming an entity no longer re-adds it in your controller (Alexa, Google Home, Apple Home) and keeps groups and automations. Records are seeded from the start, so enabling this later is safe and never re-adds existing devices. Default off.",
|
|
131543
|
+
type: "boolean",
|
|
131544
|
+
default: false
|
|
131532
131545
|
}
|
|
131533
131546
|
}
|
|
131534
131547
|
};
|
|
@@ -132293,6 +132306,12 @@ var init_home_assistant_entity_behavior = __esm({
|
|
|
132293
132306
|
customName;
|
|
132294
132307
|
/** Entity mapping configuration (optional, used for advanced features like filter life sensor) */
|
|
132295
132308
|
mapping;
|
|
132309
|
+
/**
|
|
132310
|
+
* Stable identity anchor for uniqueId/serialNumber. Set to the entity_id the
|
|
132311
|
+
* identity was first seeded under, so those stay frozen across HA renames.
|
|
132312
|
+
* Undefined falls back to the live entity_id (legacy behaviour).
|
|
132313
|
+
*/
|
|
132314
|
+
identityAnchor;
|
|
132296
132315
|
}
|
|
132297
132316
|
HomeAssistantEntityBehavior2.State = State;
|
|
132298
132317
|
class Events2 extends EventEmitter {
|
|
@@ -132616,6 +132635,10 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
132616
132635
|
lockPinMaxLength: config11.lockPinMaxLength,
|
|
132617
132636
|
powerEntity: config11.powerEntity,
|
|
132618
132637
|
energyEntity: config11.energyEntity,
|
|
132638
|
+
voltageEntity: config11.voltageEntity,
|
|
132639
|
+
currentEntity: config11.currentEntity,
|
|
132640
|
+
batteryPowerEntity: config11.batteryPowerEntity,
|
|
132641
|
+
batteryEnergyEntity: config11.batteryEnergyEntity,
|
|
132619
132642
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
132620
132643
|
mopIntensityEntity: config11.mopIntensityEntity,
|
|
132621
132644
|
valetudoIdentifier: config11.valetudoIdentifier,
|
|
@@ -132773,6 +132796,10 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
132773
132796
|
lockPinMaxLength: config11.lockPinMaxLength,
|
|
132774
132797
|
powerEntity: config11.powerEntity,
|
|
132775
132798
|
energyEntity: config11.energyEntity,
|
|
132799
|
+
voltageEntity: config11.voltageEntity,
|
|
132800
|
+
currentEntity: config11.currentEntity,
|
|
132801
|
+
batteryPowerEntity: config11.batteryPowerEntity,
|
|
132802
|
+
batteryEnergyEntity: config11.batteryEnergyEntity,
|
|
132776
132803
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
132777
132804
|
mopIntensityEntity: config11.mopIntensityEntity,
|
|
132778
132805
|
temperatureEntity: config11.temperatureEntity,
|
|
@@ -133576,7 +133603,7 @@ function diagnosticApi(bridgeService, haClient, haRegistry, version2, startTime)
|
|
|
133576
133603
|
|
|
133577
133604
|
// src/api/entity-mapping-api.ts
|
|
133578
133605
|
import express7 from "express";
|
|
133579
|
-
function entityMappingApi(mappingStorage) {
|
|
133606
|
+
function entityMappingApi(mappingStorage, identityStorage) {
|
|
133580
133607
|
const router = express7.Router();
|
|
133581
133608
|
router.get("/:bridgeId", (req, res) => {
|
|
133582
133609
|
const { bridgeId } = req.params;
|
|
@@ -133621,6 +133648,10 @@ function entityMappingApi(mappingStorage) {
|
|
|
133621
133648
|
lockPinMaxLength: body.lockPinMaxLength,
|
|
133622
133649
|
powerEntity: body.powerEntity,
|
|
133623
133650
|
energyEntity: body.energyEntity,
|
|
133651
|
+
voltageEntity: body.voltageEntity,
|
|
133652
|
+
currentEntity: body.currentEntity,
|
|
133653
|
+
batteryPowerEntity: body.batteryPowerEntity,
|
|
133654
|
+
batteryEnergyEntity: body.batteryEnergyEntity,
|
|
133624
133655
|
suctionLevelEntity: body.suctionLevelEntity,
|
|
133625
133656
|
mopIntensityEntity: body.mopIntensityEntity,
|
|
133626
133657
|
customServiceAreas: body.customServiceAreas,
|
|
@@ -133657,6 +133688,7 @@ function entityMappingApi(mappingStorage) {
|
|
|
133657
133688
|
router.delete("/:bridgeId", async (req, res) => {
|
|
133658
133689
|
const { bridgeId } = req.params;
|
|
133659
133690
|
await mappingStorage.deleteBridgeMappings(bridgeId);
|
|
133691
|
+
await identityStorage.deleteBridgeIdentities(bridgeId);
|
|
133660
133692
|
res.status(204).send();
|
|
133661
133693
|
});
|
|
133662
133694
|
return router;
|
|
@@ -134117,6 +134149,10 @@ function configToProfileEntry(config11) {
|
|
|
134117
134149
|
lockPinMaxLength: config11.lockPinMaxLength,
|
|
134118
134150
|
powerEntity: config11.powerEntity,
|
|
134119
134151
|
energyEntity: config11.energyEntity,
|
|
134152
|
+
voltageEntity: config11.voltageEntity,
|
|
134153
|
+
currentEntity: config11.currentEntity,
|
|
134154
|
+
batteryPowerEntity: config11.batteryPowerEntity,
|
|
134155
|
+
batteryEnergyEntity: config11.batteryEnergyEntity,
|
|
134120
134156
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
134121
134157
|
mopIntensityEntity: config11.mopIntensityEntity,
|
|
134122
134158
|
customServiceAreas: config11.customServiceAreas,
|
|
@@ -134252,6 +134288,10 @@ function mappingProfileApi(mappingStorage) {
|
|
|
134252
134288
|
lockPinMaxLength: entry.lockPinMaxLength,
|
|
134253
134289
|
powerEntity: entry.powerEntity,
|
|
134254
134290
|
energyEntity: entry.energyEntity,
|
|
134291
|
+
voltageEntity: entry.voltageEntity,
|
|
134292
|
+
currentEntity: entry.currentEntity,
|
|
134293
|
+
batteryPowerEntity: entry.batteryPowerEntity,
|
|
134294
|
+
batteryEnergyEntity: entry.batteryEnergyEntity,
|
|
134255
134295
|
suctionLevelEntity: entry.suctionLevelEntity,
|
|
134256
134296
|
mopIntensityEntity: entry.mopIntensityEntity,
|
|
134257
134297
|
customServiceAreas: entry.customServiceAreas,
|
|
@@ -134523,7 +134563,7 @@ function endpointToJson(endpoint, parentId) {
|
|
|
134523
134563
|
|
|
134524
134564
|
// src/api/matter-api.ts
|
|
134525
134565
|
var ajv = new Ajv();
|
|
134526
|
-
function matterApi(bridgeService, haRegistry) {
|
|
134566
|
+
function matterApi(bridgeService, haRegistry, identityStorage) {
|
|
134527
134567
|
const router = express11.Router();
|
|
134528
134568
|
router.get("/", (_, res) => {
|
|
134529
134569
|
res.status(200).json({});
|
|
@@ -134600,6 +134640,7 @@ function matterApi(bridgeService, haRegistry) {
|
|
|
134600
134640
|
const bridgeId = req.params.bridgeId;
|
|
134601
134641
|
try {
|
|
134602
134642
|
await bridgeService.delete(bridgeId);
|
|
134643
|
+
await identityStorage?.deleteBridgeIdentities(bridgeId);
|
|
134603
134644
|
res.status(204).send();
|
|
134604
134645
|
} catch (e) {
|
|
134605
134646
|
res.status(500).json({
|
|
@@ -134615,6 +134656,7 @@ function matterApi(bridgeService, haRegistry) {
|
|
|
134615
134656
|
return;
|
|
134616
134657
|
}
|
|
134617
134658
|
try {
|
|
134659
|
+
await identityStorage?.deleteBridgeIdentities(bridgeId);
|
|
134618
134660
|
await bridge.factoryReset();
|
|
134619
134661
|
await bridge.start();
|
|
134620
134662
|
res.status(200).json(bridge.data);
|
|
@@ -136597,13 +136639,14 @@ var WebSocketApi = class {
|
|
|
136597
136639
|
|
|
136598
136640
|
// src/api/web-api.ts
|
|
136599
136641
|
var WebApi = class extends Service {
|
|
136600
|
-
constructor(logger245, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, lockCredentialStorage, settingsStorage, backupService, props) {
|
|
136642
|
+
constructor(logger245, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, identityStorage, lockCredentialStorage, settingsStorage, backupService, props) {
|
|
136601
136643
|
super("WebApi");
|
|
136602
136644
|
this.bridgeService = bridgeService;
|
|
136603
136645
|
this.haClient = haClient;
|
|
136604
136646
|
this.haRegistry = haRegistry;
|
|
136605
136647
|
this.bridgeStorage = bridgeStorage;
|
|
136606
136648
|
this.mappingStorage = mappingStorage;
|
|
136649
|
+
this.identityStorage = identityStorage;
|
|
136607
136650
|
this.lockCredentialStorage = lockCredentialStorage;
|
|
136608
136651
|
this.settingsStorage = settingsStorage;
|
|
136609
136652
|
this.backupService = backupService;
|
|
@@ -136623,6 +136666,7 @@ var WebApi = class extends Service {
|
|
|
136623
136666
|
haRegistry;
|
|
136624
136667
|
bridgeStorage;
|
|
136625
136668
|
mappingStorage;
|
|
136669
|
+
identityStorage;
|
|
136626
136670
|
lockCredentialStorage;
|
|
136627
136671
|
settingsStorage;
|
|
136628
136672
|
backupService;
|
|
@@ -136639,7 +136683,10 @@ var WebApi = class extends Service {
|
|
|
136639
136683
|
}
|
|
136640
136684
|
async initialize() {
|
|
136641
136685
|
const api = express17.Router();
|
|
136642
|
-
api.use(express17.json()).use(nocache()).use(
|
|
136686
|
+
api.use(express17.json()).use(nocache()).use(
|
|
136687
|
+
"/matter",
|
|
136688
|
+
matterApi(this.bridgeService, this.haRegistry, this.identityStorage)
|
|
136689
|
+
).use(
|
|
136643
136690
|
"/health",
|
|
136644
136691
|
healthApi(
|
|
136645
136692
|
this.bridgeService,
|
|
@@ -136650,7 +136697,10 @@ var WebApi = class extends Service {
|
|
|
136650
136697
|
).use("/bridges", bridgeExportApi(this.bridgeStorage)).use("/bridge-icons", bridgeIconApi(this.props.storageLocation)).use(
|
|
136651
136698
|
"/device-images",
|
|
136652
136699
|
deviceImageApi(this.props.storageLocation, this.haRegistry)
|
|
136653
|
-
).use(
|
|
136700
|
+
).use(
|
|
136701
|
+
"/entity-mappings",
|
|
136702
|
+
entityMappingApi(this.mappingStorage, this.identityStorage)
|
|
136703
|
+
).use("/mapping-profiles", mappingProfileApi(this.mappingStorage)).use("/lock-credentials", lockCredentialApi(this.lockCredentialStorage)).use(
|
|
136654
136704
|
"/settings",
|
|
136655
136705
|
settingsApi(this.settingsStorage, this.bridgeService, this.props.auth)
|
|
136656
136706
|
).use(
|
|
@@ -138355,9 +138405,112 @@ var BridgeStorage = class extends Service {
|
|
|
138355
138405
|
}
|
|
138356
138406
|
};
|
|
138357
138407
|
|
|
138358
|
-
// src/services/storage/entity-
|
|
138408
|
+
// src/services/storage/entity-identity-storage.ts
|
|
138359
138409
|
init_service();
|
|
138360
138410
|
var CURRENT_VERSION = 1;
|
|
138411
|
+
var PERSIST_DEBOUNCE_MS = 500;
|
|
138412
|
+
var EntityIdentityStorage = class extends Service {
|
|
138413
|
+
constructor(appStorage) {
|
|
138414
|
+
super("EntityIdentityStorage");
|
|
138415
|
+
this.appStorage = appStorage;
|
|
138416
|
+
}
|
|
138417
|
+
appStorage;
|
|
138418
|
+
storage;
|
|
138419
|
+
identities = /* @__PURE__ */ new Map();
|
|
138420
|
+
persistTimer = null;
|
|
138421
|
+
async initialize() {
|
|
138422
|
+
this.storage = this.appStorage.createContext("entity-identities");
|
|
138423
|
+
await this.load();
|
|
138424
|
+
}
|
|
138425
|
+
async dispose() {
|
|
138426
|
+
await this.flush();
|
|
138427
|
+
}
|
|
138428
|
+
async load() {
|
|
138429
|
+
const stored = await this.storage.get("data", {
|
|
138430
|
+
version: CURRENT_VERSION,
|
|
138431
|
+
identities: {}
|
|
138432
|
+
});
|
|
138433
|
+
if (!stored || Object.keys(stored).length === 0) {
|
|
138434
|
+
return;
|
|
138435
|
+
}
|
|
138436
|
+
const data = stored;
|
|
138437
|
+
if (data.version !== CURRENT_VERSION) {
|
|
138438
|
+
await this.migrate(data);
|
|
138439
|
+
return;
|
|
138440
|
+
}
|
|
138441
|
+
for (const [bridgeId, records] of Object.entries(data.identities)) {
|
|
138442
|
+
const bridgeMap = /* @__PURE__ */ new Map();
|
|
138443
|
+
for (const [key, record] of Object.entries(records)) {
|
|
138444
|
+
bridgeMap.set(key, record);
|
|
138445
|
+
}
|
|
138446
|
+
this.identities.set(bridgeId, bridgeMap);
|
|
138447
|
+
}
|
|
138448
|
+
}
|
|
138449
|
+
async migrate(data) {
|
|
138450
|
+
if (data.version < CURRENT_VERSION) {
|
|
138451
|
+
for (const [bridgeId, records] of Object.entries(data.identities)) {
|
|
138452
|
+
const bridgeMap = /* @__PURE__ */ new Map();
|
|
138453
|
+
for (const [key, record] of Object.entries(records)) {
|
|
138454
|
+
bridgeMap.set(key, record);
|
|
138455
|
+
}
|
|
138456
|
+
this.identities.set(bridgeId, bridgeMap);
|
|
138457
|
+
}
|
|
138458
|
+
await this.persist();
|
|
138459
|
+
}
|
|
138460
|
+
}
|
|
138461
|
+
async persist() {
|
|
138462
|
+
const data = {
|
|
138463
|
+
version: CURRENT_VERSION,
|
|
138464
|
+
identities: {}
|
|
138465
|
+
};
|
|
138466
|
+
for (const [bridgeId, bridgeMap] of this.identities) {
|
|
138467
|
+
const records = {};
|
|
138468
|
+
for (const [key, record] of bridgeMap) {
|
|
138469
|
+
records[key] = record;
|
|
138470
|
+
}
|
|
138471
|
+
data.identities[bridgeId] = records;
|
|
138472
|
+
}
|
|
138473
|
+
await this.storage.set("data", data);
|
|
138474
|
+
}
|
|
138475
|
+
schedulePersist() {
|
|
138476
|
+
if (this.persistTimer) return;
|
|
138477
|
+
this.persistTimer = setTimeout(() => {
|
|
138478
|
+
this.persistTimer = null;
|
|
138479
|
+
void this.persist();
|
|
138480
|
+
}, PERSIST_DEBOUNCE_MS);
|
|
138481
|
+
}
|
|
138482
|
+
// Flush any pending debounced write, used on dispose and by tests.
|
|
138483
|
+
async flush() {
|
|
138484
|
+
if (this.persistTimer) {
|
|
138485
|
+
clearTimeout(this.persistTimer);
|
|
138486
|
+
this.persistTimer = null;
|
|
138487
|
+
}
|
|
138488
|
+
await this.persist();
|
|
138489
|
+
}
|
|
138490
|
+
getIdentity(bridgeId, key) {
|
|
138491
|
+
return this.identities.get(bridgeId)?.get(key);
|
|
138492
|
+
}
|
|
138493
|
+
getBridgeIdentities(bridgeId) {
|
|
138494
|
+
return this.identities.get(bridgeId) ?? /* @__PURE__ */ new Map();
|
|
138495
|
+
}
|
|
138496
|
+
setIdentity(bridgeId, key, record) {
|
|
138497
|
+
let bridgeMap = this.identities.get(bridgeId);
|
|
138498
|
+
if (!bridgeMap) {
|
|
138499
|
+
bridgeMap = /* @__PURE__ */ new Map();
|
|
138500
|
+
this.identities.set(bridgeId, bridgeMap);
|
|
138501
|
+
}
|
|
138502
|
+
bridgeMap.set(key, record);
|
|
138503
|
+
this.schedulePersist();
|
|
138504
|
+
}
|
|
138505
|
+
async deleteBridgeIdentities(bridgeId) {
|
|
138506
|
+
this.identities.delete(bridgeId);
|
|
138507
|
+
await this.flush();
|
|
138508
|
+
}
|
|
138509
|
+
};
|
|
138510
|
+
|
|
138511
|
+
// src/services/storage/entity-mapping-storage.ts
|
|
138512
|
+
init_service();
|
|
138513
|
+
var CURRENT_VERSION2 = 1;
|
|
138361
138514
|
var EntityMappingStorage = class extends Service {
|
|
138362
138515
|
constructor(appStorage) {
|
|
138363
138516
|
super("EntityMappingStorage");
|
|
@@ -138372,14 +138525,14 @@ var EntityMappingStorage = class extends Service {
|
|
|
138372
138525
|
}
|
|
138373
138526
|
async load() {
|
|
138374
138527
|
const stored = await this.storage.get("data", {
|
|
138375
|
-
version:
|
|
138528
|
+
version: CURRENT_VERSION2,
|
|
138376
138529
|
mappings: {}
|
|
138377
138530
|
});
|
|
138378
138531
|
if (!stored || Object.keys(stored).length === 0) {
|
|
138379
138532
|
return;
|
|
138380
138533
|
}
|
|
138381
138534
|
const data = stored;
|
|
138382
|
-
if (data.version !==
|
|
138535
|
+
if (data.version !== CURRENT_VERSION2) {
|
|
138383
138536
|
await this.migrate(data);
|
|
138384
138537
|
return;
|
|
138385
138538
|
}
|
|
@@ -138392,7 +138545,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
138392
138545
|
}
|
|
138393
138546
|
}
|
|
138394
138547
|
async migrate(data) {
|
|
138395
|
-
if (data.version <
|
|
138548
|
+
if (data.version < CURRENT_VERSION2) {
|
|
138396
138549
|
for (const [bridgeId, configs] of Object.entries(data.mappings)) {
|
|
138397
138550
|
const bridgeMap = /* @__PURE__ */ new Map();
|
|
138398
138551
|
for (const config11 of configs) {
|
|
@@ -138405,7 +138558,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
138405
138558
|
}
|
|
138406
138559
|
async persist() {
|
|
138407
138560
|
const data = {
|
|
138408
|
-
version:
|
|
138561
|
+
version: CURRENT_VERSION2,
|
|
138409
138562
|
mappings: {}
|
|
138410
138563
|
};
|
|
138411
138564
|
for (const [bridgeId, bridgeMap] of this.mappings) {
|
|
@@ -138455,6 +138608,10 @@ var EntityMappingStorage = class extends Service {
|
|
|
138455
138608
|
lockPinMaxLength: pinLengths.max,
|
|
138456
138609
|
powerEntity: request.powerEntity?.trim() || void 0,
|
|
138457
138610
|
energyEntity: request.energyEntity?.trim() || void 0,
|
|
138611
|
+
voltageEntity: request.voltageEntity?.trim() || void 0,
|
|
138612
|
+
currentEntity: request.currentEntity?.trim() || void 0,
|
|
138613
|
+
batteryPowerEntity: request.batteryPowerEntity?.trim() || void 0,
|
|
138614
|
+
batteryEnergyEntity: request.batteryEnergyEntity?.trim() || void 0,
|
|
138458
138615
|
pressureEntity: request.pressureEntity?.trim() || void 0,
|
|
138459
138616
|
suctionLevelEntity: request.suctionLevelEntity?.trim() || void 0,
|
|
138460
138617
|
mopIntensityEntity: request.mopIntensityEntity?.trim() || void 0,
|
|
@@ -138483,7 +138640,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
138483
138640
|
composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0,
|
|
138484
138641
|
disableMomentaryFlip: request.disableMomentaryFlip || void 0
|
|
138485
138642
|
};
|
|
138486
|
-
if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.disableBatteryMapping && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.lockUsercodeService && config11.lockUsercodeSlot === void 0 && config11.lockPinMinLength === void 0 && config11.lockPinMaxLength === void 0 && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0) && !config11.disableMomentaryFlip) {
|
|
138643
|
+
if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.disableBatteryMapping && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.lockUsercodeService && config11.lockUsercodeSlot === void 0 && config11.lockPinMinLength === void 0 && config11.lockPinMaxLength === void 0 && !config11.powerEntity && !config11.energyEntity && !config11.voltageEntity && !config11.currentEntity && !config11.batteryPowerEntity && !config11.batteryEnergyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0) && !config11.disableMomentaryFlip) {
|
|
138487
138644
|
bridgeMap.delete(request.entityId);
|
|
138488
138645
|
} else {
|
|
138489
138646
|
bridgeMap.set(request.entityId, config11);
|
|
@@ -138565,7 +138722,7 @@ function sanitizeThrottleMs(value) {
|
|
|
138565
138722
|
// src/services/storage/lock-credential-storage.ts
|
|
138566
138723
|
init_service();
|
|
138567
138724
|
import { pbkdf2Sync, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
138568
|
-
var
|
|
138725
|
+
var CURRENT_VERSION3 = 2;
|
|
138569
138726
|
var HASH_ITERATIONS = 1e5;
|
|
138570
138727
|
var HASH_KEY_LENGTH = 64;
|
|
138571
138728
|
var HASH_ALGORITHM = "sha512";
|
|
@@ -138584,14 +138741,14 @@ var LockCredentialStorage = class extends Service {
|
|
|
138584
138741
|
}
|
|
138585
138742
|
async load() {
|
|
138586
138743
|
const stored = await this.storage.get("data", {
|
|
138587
|
-
version:
|
|
138744
|
+
version: CURRENT_VERSION3,
|
|
138588
138745
|
credentials: []
|
|
138589
138746
|
});
|
|
138590
138747
|
if (!stored || Object.keys(stored).length === 0) {
|
|
138591
138748
|
return;
|
|
138592
138749
|
}
|
|
138593
138750
|
const data = stored;
|
|
138594
|
-
if (data.version !==
|
|
138751
|
+
if (data.version !== CURRENT_VERSION3) {
|
|
138595
138752
|
await this.migrate(data);
|
|
138596
138753
|
return;
|
|
138597
138754
|
}
|
|
@@ -138620,7 +138777,7 @@ var LockCredentialStorage = class extends Service {
|
|
|
138620
138777
|
}
|
|
138621
138778
|
async persist() {
|
|
138622
138779
|
const data = {
|
|
138623
|
-
version:
|
|
138780
|
+
version: CURRENT_VERSION3,
|
|
138624
138781
|
credentials: Array.from(this.credentials.values())
|
|
138625
138782
|
};
|
|
138626
138783
|
await this.storage.set("data", data);
|
|
@@ -148297,6 +148454,7 @@ var ElectricalMeterDeviceDefinition = MutableEndpoint({
|
|
|
148297
148454
|
behaviors: SupportedBehaviors()
|
|
148298
148455
|
});
|
|
148299
148456
|
Object.freeze(ElectricalMeterDeviceDefinition);
|
|
148457
|
+
var ElectricalMeterDevice = ElectricalMeterDeviceDefinition;
|
|
148300
148458
|
|
|
148301
148459
|
// ../../node_modules/.pnpm/@matter+types@0.17.5/node_modules/@matter/types/dist/esm/clusters/meter-identification.js
|
|
148302
148460
|
init_ClusterType();
|
|
@@ -156975,8 +157133,8 @@ var AggregatorEndpoint2 = class extends Endpoint {
|
|
|
156975
157133
|
// src/matter/endpoints/entity-endpoint.ts
|
|
156976
157134
|
init_esm7();
|
|
156977
157135
|
var EntityEndpoint = class extends Endpoint {
|
|
156978
|
-
constructor(type, entityId, customName, mappedEntityIds) {
|
|
156979
|
-
super(type, { id: createEndpointId(entityId, customName) });
|
|
157136
|
+
constructor(type, entityId, customName, mappedEntityIds, endpointId) {
|
|
157137
|
+
super(type, { id: endpointId ?? createEndpointId(entityId, customName) });
|
|
156980
157138
|
this.entityId = entityId;
|
|
156981
157139
|
this.mappedEntityIds = mappedEntityIds ?? [];
|
|
156982
157140
|
}
|
|
@@ -157018,6 +157176,10 @@ function getMappedEntityIds(mapping) {
|
|
|
157018
157176
|
if (mapping.filterLifeEntity) ids.push(mapping.filterLifeEntity);
|
|
157019
157177
|
if (mapping.powerEntity) ids.push(mapping.powerEntity);
|
|
157020
157178
|
if (mapping.energyEntity) ids.push(mapping.energyEntity);
|
|
157179
|
+
if (mapping.voltageEntity) ids.push(mapping.voltageEntity);
|
|
157180
|
+
if (mapping.currentEntity) ids.push(mapping.currentEntity);
|
|
157181
|
+
if (mapping.batteryPowerEntity) ids.push(mapping.batteryPowerEntity);
|
|
157182
|
+
if (mapping.batteryEnergyEntity) ids.push(mapping.batteryEnergyEntity);
|
|
157021
157183
|
if (mapping.currentRoomEntity) ids.push(mapping.currentRoomEntity);
|
|
157022
157184
|
if (mapping.cleanedAreaEntity) ids.push(mapping.cleanedAreaEntity);
|
|
157023
157185
|
if (mapping.composedEntities) {
|
|
@@ -157262,13 +157424,14 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
|
|
|
157262
157424
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
157263
157425
|
const device = entity.deviceRegistry;
|
|
157264
157426
|
const mapping = homeAssistant.state.mapping;
|
|
157427
|
+
const anchor = homeAssistant.state.identityAnchor ?? entity.entity_id;
|
|
157265
157428
|
const registryName = featureFlags?.preferEntityRegistryName ? entity.registry?.name ?? entity.registry?.original_name : void 0;
|
|
157266
157429
|
const nodeLabel = ellipse(32, homeAssistant.state.customName) ?? ellipse(32, registryName) ?? ellipse(32, entity.state?.attributes?.friendly_name) ?? ellipse(32, entity.entity_id);
|
|
157267
157430
|
const productNameFromNodeLabel = featureFlags?.productNameFromNodeLabel === true ? ellipse(32, sanitizeMatterString(nodeLabel ?? "")) ?? void 0 : void 0;
|
|
157268
157431
|
const serialNumberSuffix = this.env.get(BridgeDataProvider).serialNumberSuffix;
|
|
157269
157432
|
const maxRawLen = 32 - (serialNumberSuffix?.length ?? 0);
|
|
157270
157433
|
const registrySerial = featureFlags?.useHaRegistrySerial ? ellipse(maxRawLen, device?.serial_number) : void 0;
|
|
157271
|
-
const rawSerial = ellipse(maxRawLen, mapping?.customSerialNumber) ?? registrySerial ?? hash(maxRawLen,
|
|
157434
|
+
const rawSerial = ellipse(maxRawLen, mapping?.customSerialNumber) ?? registrySerial ?? hash(maxRawLen, anchor);
|
|
157272
157435
|
const serialNumber = rawSerial && serialNumberSuffix ? `${rawSerial}${serialNumberSuffix}` : rawSerial;
|
|
157273
157436
|
const customVendorId = mapping?.customVendorId;
|
|
157274
157437
|
const vendorId3 = isValidVendorId(customVendorId) ? customVendorId : basicInformation.vendorId;
|
|
@@ -157288,18 +157451,18 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
|
|
|
157288
157451
|
// multiple fabric connections. Using MD5 hash of entity_id for stability.
|
|
157289
157452
|
// uniqueIdSuffix mints a fresh identity so stale controller cloud
|
|
157290
157453
|
// records keyed on it can be shed (#385).
|
|
157291
|
-
uniqueId: this.frozenUniqueId(
|
|
157454
|
+
uniqueId: this.frozenUniqueId(anchor)
|
|
157292
157455
|
});
|
|
157293
157456
|
logger201.debug(
|
|
157294
157457
|
`[${entity.entity_id}] basicInfo vendor=${this.state.vendorName} product=${this.state.productName} label=${this.state.productLabel} serial=${this.state.serialNumber} node=${this.state.nodeLabel} uniqueId=${this.state.uniqueId}`
|
|
157295
157458
|
);
|
|
157296
157459
|
}
|
|
157297
|
-
frozenUniqueId(
|
|
157460
|
+
frozenUniqueId(anchor) {
|
|
157298
157461
|
const provider = this.env.get(BridgeDataProvider);
|
|
157299
|
-
const key = `${provider.id}:${
|
|
157462
|
+
const key = `${provider.id}:${anchor}`;
|
|
157300
157463
|
let uniqueId = appliedUniqueIds.get(key);
|
|
157301
157464
|
if (uniqueId == null) {
|
|
157302
|
-
uniqueId = crypto6.createHash("md5").update(
|
|
157465
|
+
uniqueId = crypto6.createHash("md5").update(anchor + (provider.uniqueIdSuffix ?? "")).digest("hex").substring(0, 32);
|
|
157303
157466
|
appliedUniqueIds.set(key, uniqueId);
|
|
157304
157467
|
}
|
|
157305
157468
|
return uniqueId;
|
|
@@ -157459,7 +157622,8 @@ var HaElectricalEnergyMeasurementServer = ElectricalEnergyMeasurementServerBase.
|
|
|
157459
157622
|
init_esm();
|
|
157460
157623
|
init_home_assistant_entity_behavior();
|
|
157461
157624
|
var logger203 = Logger.get("ElectricalPowerMeasurementServer");
|
|
157462
|
-
var
|
|
157625
|
+
var FeaturedBase2 = ElectricalPowerMeasurementServer.with("AlternatingCurrent");
|
|
157626
|
+
var ElectricalPowerMeasurementServerBase = class extends FeaturedBase2 {
|
|
157463
157627
|
async initialize() {
|
|
157464
157628
|
await super.initialize();
|
|
157465
157629
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
@@ -157475,23 +157639,38 @@ var ElectricalPowerMeasurementServerBase = class extends ElectricalPowerMeasurem
|
|
|
157475
157639
|
}
|
|
157476
157640
|
update() {
|
|
157477
157641
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
157478
|
-
const
|
|
157479
|
-
|
|
157642
|
+
const mapping = homeAssistant.state.mapping;
|
|
157643
|
+
const powerEntity = mapping?.powerEntity;
|
|
157644
|
+
const voltageEntity = mapping?.voltageEntity;
|
|
157645
|
+
const currentEntity = mapping?.currentEntity;
|
|
157646
|
+
if (!powerEntity && !voltageEntity && !currentEntity) return;
|
|
157480
157647
|
const stateProvider = this.agent.env.get(EntityStateProvider);
|
|
157481
|
-
const
|
|
157482
|
-
if (
|
|
157483
|
-
|
|
157484
|
-
|
|
157648
|
+
const patch = {};
|
|
157649
|
+
if (powerEntity) {
|
|
157650
|
+
const powerWatts = stateProvider.getNumericState(powerEntity);
|
|
157651
|
+
if (powerWatts != null) patch.activePower = Math.round(powerWatts * 1e3);
|
|
157652
|
+
}
|
|
157653
|
+
if (voltageEntity) {
|
|
157654
|
+
const volts = stateProvider.getNumericState(voltageEntity);
|
|
157655
|
+
if (volts != null) patch.voltage = Math.round(volts * 1e3);
|
|
157656
|
+
}
|
|
157657
|
+
if (currentEntity) {
|
|
157658
|
+
const amps = stateProvider.getNumericState(currentEntity);
|
|
157659
|
+
if (amps != null) patch.activeCurrent = Math.round(amps * 1e3);
|
|
157660
|
+
}
|
|
157661
|
+
if (Object.keys(patch).length > 0) applyPatchState(this.state, patch);
|
|
157485
157662
|
}
|
|
157486
157663
|
};
|
|
157487
157664
|
((ElectricalPowerMeasurementServerBase2) => {
|
|
157488
|
-
class State extends
|
|
157665
|
+
class State extends FeaturedBase2.State {
|
|
157489
157666
|
}
|
|
157490
157667
|
ElectricalPowerMeasurementServerBase2.State = State;
|
|
157491
157668
|
})(ElectricalPowerMeasurementServerBase || (ElectricalPowerMeasurementServerBase = {}));
|
|
157492
157669
|
var HaElectricalPowerMeasurementServer = ElectricalPowerMeasurementServerBase.set({
|
|
157493
157670
|
powerMode: ElectricalPowerMeasurement3.PowerMode.Ac,
|
|
157494
|
-
|
|
157671
|
+
// Voltage and current are folded onto this endpoint when mapped, so the
|
|
157672
|
+
// accuracy list carries an entry for each reported measurement type.
|
|
157673
|
+
numberOfMeasurementTypes: 3,
|
|
157495
157674
|
accuracy: [
|
|
157496
157675
|
{
|
|
157497
157676
|
measurementType: ElectricalPowerMeasurement3.MeasurementType.ActivePower,
|
|
@@ -157508,6 +157687,37 @@ var HaElectricalPowerMeasurementServer = ElectricalPowerMeasurementServerBase.se
|
|
|
157508
157687
|
// 1W accuracy
|
|
157509
157688
|
}
|
|
157510
157689
|
]
|
|
157690
|
+
},
|
|
157691
|
+
{
|
|
157692
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.Voltage,
|
|
157693
|
+
measured: true,
|
|
157694
|
+
minMeasuredValue: 0,
|
|
157695
|
+
maxMeasuredValue: 1e6,
|
|
157696
|
+
// 1000V in mV
|
|
157697
|
+
accuracyRanges: [
|
|
157698
|
+
{
|
|
157699
|
+
rangeMin: 0,
|
|
157700
|
+
rangeMax: 1e6,
|
|
157701
|
+
fixedMax: 1e3
|
|
157702
|
+
// 1V accuracy
|
|
157703
|
+
}
|
|
157704
|
+
]
|
|
157705
|
+
},
|
|
157706
|
+
{
|
|
157707
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.ActiveCurrent,
|
|
157708
|
+
measured: true,
|
|
157709
|
+
minMeasuredValue: -1e6,
|
|
157710
|
+
// -1000A in mA
|
|
157711
|
+
maxMeasuredValue: 1e6,
|
|
157712
|
+
// 1000A in mA
|
|
157713
|
+
accuracyRanges: [
|
|
157714
|
+
{
|
|
157715
|
+
rangeMin: -1e6,
|
|
157716
|
+
rangeMax: 1e6,
|
|
157717
|
+
fixedMax: 1e3
|
|
157718
|
+
// 1A accuracy
|
|
157719
|
+
}
|
|
157720
|
+
]
|
|
157511
157721
|
}
|
|
157512
157722
|
]
|
|
157513
157723
|
});
|
|
@@ -157603,8 +157813,8 @@ function HumidityMeasurementServer(config11) {
|
|
|
157603
157813
|
init_esm();
|
|
157604
157814
|
init_home_assistant_entity_behavior();
|
|
157605
157815
|
var logger205 = Logger.get("PowerSourceServer");
|
|
157606
|
-
var
|
|
157607
|
-
var PowerSourceServerBase = class extends
|
|
157816
|
+
var FeaturedBase3 = PowerSourceServer.with("Battery", "Rechargeable");
|
|
157817
|
+
var PowerSourceServerBase = class extends FeaturedBase3 {
|
|
157608
157818
|
async initialize() {
|
|
157609
157819
|
await super.initialize();
|
|
157610
157820
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
@@ -157682,7 +157892,7 @@ var PowerSourceServerBase = class extends FeaturedBase2 {
|
|
|
157682
157892
|
}
|
|
157683
157893
|
};
|
|
157684
157894
|
((PowerSourceServerBase2) => {
|
|
157685
|
-
class State extends
|
|
157895
|
+
class State extends FeaturedBase3.State {
|
|
157686
157896
|
config;
|
|
157687
157897
|
}
|
|
157688
157898
|
PowerSourceServerBase2.State = State;
|
|
@@ -157763,8 +157973,8 @@ function TemperatureMeasurementServer2(config11) {
|
|
|
157763
157973
|
|
|
157764
157974
|
// src/matter/behaviors/hepa-filter-monitoring-server.ts
|
|
157765
157975
|
init_home_assistant_entity_behavior();
|
|
157766
|
-
var
|
|
157767
|
-
var HepaFilterMonitoringServerBase = class extends
|
|
157976
|
+
var FeaturedBase4 = HepaFilterMonitoringServer.with("Condition", "Warning");
|
|
157977
|
+
var HepaFilterMonitoringServerBase = class extends FeaturedBase4 {
|
|
157768
157978
|
async initialize() {
|
|
157769
157979
|
this.state.condition = 100;
|
|
157770
157980
|
this.state.degradationDirection = ResourceMonitoring3.DegradationDirection.Down;
|
|
@@ -157801,7 +158011,7 @@ var HepaFilterMonitoringServerBase = class extends FeaturedBase3 {
|
|
|
157801
158011
|
}
|
|
157802
158012
|
};
|
|
157803
158013
|
((HepaFilterMonitoringServerBase2) => {
|
|
157804
|
-
class State extends
|
|
158014
|
+
class State extends FeaturedBase4.State {
|
|
157805
158015
|
config;
|
|
157806
158016
|
}
|
|
157807
158017
|
HepaFilterMonitoringServerBase2.State = State;
|
|
@@ -158059,8 +158269,8 @@ function notifyLightTurnedOn(entityId) {
|
|
|
158059
158269
|
lastTurnOnTimestamps.set(entityId, now);
|
|
158060
158270
|
}
|
|
158061
158271
|
var logger206 = Logger.get("LevelControlServer");
|
|
158062
|
-
var
|
|
158063
|
-
var LevelControlServerBase = class extends
|
|
158272
|
+
var FeaturedBase5 = LevelControlServer.with("OnOff", "Lighting");
|
|
158273
|
+
var LevelControlServerBase = class extends FeaturedBase5 {
|
|
158064
158274
|
pendingTransitionTime;
|
|
158065
158275
|
async initialize() {
|
|
158066
158276
|
if (this.state.currentLevel == null) {
|
|
@@ -158217,7 +158427,7 @@ var LevelControlServerBase = class extends FeaturedBase4 {
|
|
|
158217
158427
|
}
|
|
158218
158428
|
};
|
|
158219
158429
|
((LevelControlServerBase2) => {
|
|
158220
|
-
class State extends
|
|
158430
|
+
class State extends FeaturedBase5.State {
|
|
158221
158431
|
config;
|
|
158222
158432
|
}
|
|
158223
158433
|
LevelControlServerBase2.State = State;
|
|
@@ -158359,7 +158569,7 @@ var logger208 = Logger.get("FanControlServer");
|
|
|
158359
158569
|
var defaultStepSize = 33.33;
|
|
158360
158570
|
var minSpeedMax = 3;
|
|
158361
158571
|
var maxSpeedMax = 100;
|
|
158362
|
-
var
|
|
158572
|
+
var FeaturedBase6 = FanControlServer.with(
|
|
158363
158573
|
"Step",
|
|
158364
158574
|
"MultiSpeed",
|
|
158365
158575
|
"AirflowDirection",
|
|
@@ -158369,7 +158579,7 @@ var FeaturedBase5 = FanControlServer.with(
|
|
|
158369
158579
|
).set({
|
|
158370
158580
|
windSupport: { naturalWind: true, sleepWind: true }
|
|
158371
158581
|
});
|
|
158372
|
-
var FanControlServerBase = class extends
|
|
158582
|
+
var FanControlServerBase = class extends FeaturedBase6 {
|
|
158373
158583
|
// Fallback last-speed tracking for endpoints without FanSpeedMemoryBehavior
|
|
158374
158584
|
// (climate companion, humidifier). matter.js builds behavior instances per
|
|
158375
158585
|
// transaction, so these fields only live within one interaction; fans use
|
|
@@ -158822,7 +159032,7 @@ var FanControlServerBase = class extends FeaturedBase5 {
|
|
|
158822
159032
|
}
|
|
158823
159033
|
};
|
|
158824
159034
|
((FanControlServerBase2) => {
|
|
158825
|
-
class State extends
|
|
159035
|
+
class State extends FeaturedBase6.State {
|
|
158826
159036
|
config;
|
|
158827
159037
|
}
|
|
158828
159038
|
FanControlServerBase2.State = State;
|
|
@@ -159071,7 +159281,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
159071
159281
|
})
|
|
159072
159282
|
);
|
|
159073
159283
|
}
|
|
159074
|
-
const endpointId = createEndpointId2(primaryEntityId, config11.customName);
|
|
159284
|
+
const endpointId = config11.endpointId ?? createEndpointId2(primaryEntityId, config11.customName);
|
|
159075
159285
|
const parts = [];
|
|
159076
159286
|
const airPurifierSub = new Endpoint(
|
|
159077
159287
|
airPurifierSubType.set({
|
|
@@ -159116,7 +159326,8 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
159116
159326
|
homeAssistantEntity: {
|
|
159117
159327
|
entity: primaryPayload,
|
|
159118
159328
|
customName: config11.customName,
|
|
159119
|
-
mapping: parentMapping
|
|
159329
|
+
mapping: parentMapping,
|
|
159330
|
+
identityAnchor: config11.identityAnchor
|
|
159120
159331
|
}
|
|
159121
159332
|
});
|
|
159122
159333
|
const mappedIds = [];
|
|
@@ -160574,7 +160785,7 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
|
|
|
160574
160785
|
const { registry: registry2, primaryEntityId } = config11;
|
|
160575
160786
|
const payload = buildEntityPayload2(registry2, primaryEntityId);
|
|
160576
160787
|
if (!payload) return void 0;
|
|
160577
|
-
const endpointId = createEndpointId3(primaryEntityId, config11.customName);
|
|
160788
|
+
const endpointId = config11.endpointId ?? createEndpointId3(primaryEntityId, config11.customName);
|
|
160578
160789
|
const mapping = config11.mapping ?? {
|
|
160579
160790
|
entityId: primaryEntityId
|
|
160580
160791
|
};
|
|
@@ -160618,7 +160829,8 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
|
|
|
160618
160829
|
homeAssistantEntity: {
|
|
160619
160830
|
entity: payload,
|
|
160620
160831
|
customName: config11.customName,
|
|
160621
|
-
mapping
|
|
160832
|
+
mapping,
|
|
160833
|
+
identityAnchor: config11.identityAnchor
|
|
160622
160834
|
}
|
|
160623
160835
|
});
|
|
160624
160836
|
const endpoint = new _ComposedClimateFanEndpoint(
|
|
@@ -160882,7 +161094,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
160882
161094
|
})
|
|
160883
161095
|
);
|
|
160884
161096
|
}
|
|
160885
|
-
const endpointId = createEndpointId4(primaryEntityId, config11.customName);
|
|
161097
|
+
const endpointId = config11.endpointId ?? createEndpointId4(primaryEntityId, config11.customName);
|
|
160886
161098
|
const parts = [];
|
|
160887
161099
|
const tempSub = new Endpoint(
|
|
160888
161100
|
TemperatureSubType2.set({
|
|
@@ -160924,7 +161136,8 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
160924
161136
|
homeAssistantEntity: {
|
|
160925
161137
|
entity: primaryPayload,
|
|
160926
161138
|
customName: config11.customName,
|
|
160927
|
-
mapping
|
|
161139
|
+
mapping,
|
|
161140
|
+
identityAnchor: config11.identityAnchor
|
|
160928
161141
|
}
|
|
160929
161142
|
});
|
|
160930
161143
|
const mappedIds = [];
|
|
@@ -161821,7 +162034,7 @@ init_home_assistant_actions();
|
|
|
161821
162034
|
init_home_assistant_entity_behavior();
|
|
161822
162035
|
var logger216 = Logger.get("WindowCoveringServer");
|
|
161823
162036
|
var MovementStatus = WindowCovering3.MovementStatus;
|
|
161824
|
-
var
|
|
162037
|
+
var FeaturedBase7 = WindowCoveringServer.with(
|
|
161825
162038
|
"Lift",
|
|
161826
162039
|
"PositionAwareLift",
|
|
161827
162040
|
"Tilt",
|
|
@@ -161857,7 +162070,7 @@ function clearPendingTilt(st) {
|
|
|
161857
162070
|
}
|
|
161858
162071
|
st.pendingTilt = null;
|
|
161859
162072
|
}
|
|
161860
|
-
var WindowCoveringServerBase = class _WindowCoveringServerBase extends
|
|
162073
|
+
var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedBase7 {
|
|
161861
162074
|
// Written and read within one synchronous command (upOrOpen fires lift then
|
|
161862
162075
|
// tilt on the same instance), so these stay as instance fields (#246).
|
|
161863
162076
|
lastLiftMovementMs = 0;
|
|
@@ -162166,7 +162379,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
162166
162379
|
}
|
|
162167
162380
|
};
|
|
162168
162381
|
((WindowCoveringServerBase2) => {
|
|
162169
|
-
class State extends
|
|
162382
|
+
class State extends FeaturedBase7.State {
|
|
162170
162383
|
config;
|
|
162171
162384
|
}
|
|
162172
162385
|
WindowCoveringServerBase2.State = State;
|
|
@@ -163878,8 +164091,8 @@ function consumePendingColorStaging(entityId) {
|
|
|
163878
164091
|
pendingColorStaging.delete(entityId);
|
|
163879
164092
|
return data;
|
|
163880
164093
|
}
|
|
163881
|
-
var
|
|
163882
|
-
var ColorControlServerBase = class extends
|
|
164094
|
+
var FeaturedBase8 = ColorControlServer.with("ColorTemperature", "HueSaturation", "Xy");
|
|
164095
|
+
var ColorControlServerBase = class extends FeaturedBase8 {
|
|
163883
164096
|
pendingTransitionTime;
|
|
163884
164097
|
async [Symbol.asyncDispose]() {
|
|
163885
164098
|
const entityId = this.agent.get(HomeAssistantEntityBehavior).entityId;
|
|
@@ -164224,7 +164437,7 @@ var ColorControlServerBase = class extends FeaturedBase7 {
|
|
|
164224
164437
|
}
|
|
164225
164438
|
};
|
|
164226
164439
|
((ColorControlServerBase2) => {
|
|
164227
|
-
class State extends
|
|
164440
|
+
class State extends FeaturedBase8.State {
|
|
164228
164441
|
config;
|
|
164229
164442
|
}
|
|
164230
164443
|
ColorControlServerBase2.State = State;
|
|
@@ -164441,11 +164654,12 @@ function LightDevice(homeAssistantEntity) {
|
|
|
164441
164654
|
) : supportsBrightness ? hasBattery ? DimmableLightWithBatteryType : DimmableLightType : hasBattery ? OnOffLightWithBatteryType : OnOffLightType;
|
|
164442
164655
|
const hasPowerEntity = !!homeAssistantEntity.mapping?.powerEntity;
|
|
164443
164656
|
const hasEnergyEntity = !!homeAssistantEntity.mapping?.energyEntity;
|
|
164657
|
+
const hasElectricalPower = hasPowerEntity || !!homeAssistantEntity.mapping?.voltageEntity || !!homeAssistantEntity.mapping?.currentEntity;
|
|
164444
164658
|
let device = deviceType;
|
|
164445
|
-
if (
|
|
164659
|
+
if (hasElectricalPower || hasEnergyEntity) {
|
|
164446
164660
|
device = device.with(HaPowerTopologyServer);
|
|
164447
164661
|
}
|
|
164448
|
-
if (
|
|
164662
|
+
if (hasElectricalPower) {
|
|
164449
164663
|
device = device.with(HaElectricalPowerMeasurementServer);
|
|
164450
164664
|
}
|
|
164451
164665
|
if (hasEnergyEntity) {
|
|
@@ -165477,8 +165691,8 @@ function sweepOptimisticLevel2(now) {
|
|
|
165477
165691
|
}
|
|
165478
165692
|
}
|
|
165479
165693
|
}
|
|
165480
|
-
var
|
|
165481
|
-
var SpeakerLevelControlServerBase = class extends
|
|
165694
|
+
var FeaturedBase9 = LevelControlServer.with("OnOff");
|
|
165695
|
+
var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
|
|
165482
165696
|
async initialize() {
|
|
165483
165697
|
if (this.state.currentLevel == null) {
|
|
165484
165698
|
this.state.currentLevel = 0;
|
|
@@ -165580,7 +165794,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase8 {
|
|
|
165580
165794
|
}
|
|
165581
165795
|
};
|
|
165582
165796
|
((SpeakerLevelControlServerBase2) => {
|
|
165583
|
-
class State extends
|
|
165797
|
+
class State extends FeaturedBase9.State {
|
|
165584
165798
|
config;
|
|
165585
165799
|
}
|
|
165586
165800
|
SpeakerLevelControlServerBase2.State = State;
|
|
@@ -166014,6 +166228,126 @@ var BatterySensorType = BatteryStorageDevice.with(
|
|
|
166014
166228
|
})
|
|
166015
166229
|
);
|
|
166016
166230
|
|
|
166231
|
+
// src/matter/endpoints/legacy/sensor/devices/battery-storage-ess.ts
|
|
166232
|
+
init_home_assistant_entity_behavior();
|
|
166233
|
+
var PowerFeaturedBase = ElectricalPowerMeasurementServer.with("DirectCurrent");
|
|
166234
|
+
var EssPowerServer = class extends PowerFeaturedBase {
|
|
166235
|
+
async initialize() {
|
|
166236
|
+
await super.initialize();
|
|
166237
|
+
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
166238
|
+
this.update();
|
|
166239
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
166240
|
+
}
|
|
166241
|
+
update() {
|
|
166242
|
+
const mapping = this.agent.get(HomeAssistantEntityBehavior).state.mapping;
|
|
166243
|
+
const powerEntity = mapping?.batteryPowerEntity;
|
|
166244
|
+
if (!powerEntity) return;
|
|
166245
|
+
const stateProvider = this.agent.env.get(EntityStateProvider);
|
|
166246
|
+
const watts = stateProvider.getNumericState(powerEntity);
|
|
166247
|
+
if (watts == null) return;
|
|
166248
|
+
applyPatchState(this.state, { activePower: Math.round(watts * -1e3) });
|
|
166249
|
+
}
|
|
166250
|
+
};
|
|
166251
|
+
((EssPowerServer2) => {
|
|
166252
|
+
class State extends PowerFeaturedBase.State {
|
|
166253
|
+
}
|
|
166254
|
+
EssPowerServer2.State = State;
|
|
166255
|
+
})(EssPowerServer || (EssPowerServer = {}));
|
|
166256
|
+
var EssPower = EssPowerServer.set({
|
|
166257
|
+
powerMode: ElectricalPowerMeasurement3.PowerMode.Dc,
|
|
166258
|
+
numberOfMeasurementTypes: 1,
|
|
166259
|
+
// Seed 0 so the cluster reports a value before the first update (SmartThings).
|
|
166260
|
+
activePower: 0,
|
|
166261
|
+
accuracy: [
|
|
166262
|
+
{
|
|
166263
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.ActivePower,
|
|
166264
|
+
measured: true,
|
|
166265
|
+
// Wide symmetric range: batteries both charge (negative) and discharge.
|
|
166266
|
+
minMeasuredValue: -1e8,
|
|
166267
|
+
maxMeasuredValue: 1e8,
|
|
166268
|
+
accuracyRanges: [
|
|
166269
|
+
{
|
|
166270
|
+
rangeMin: -1e8,
|
|
166271
|
+
rangeMax: 1e8,
|
|
166272
|
+
fixedMax: 1e3
|
|
166273
|
+
}
|
|
166274
|
+
]
|
|
166275
|
+
}
|
|
166276
|
+
]
|
|
166277
|
+
});
|
|
166278
|
+
var EnergyFeaturedBase = ElectricalEnergyMeasurementServer.with(
|
|
166279
|
+
"CumulativeEnergy",
|
|
166280
|
+
"ImportedEnergy"
|
|
166281
|
+
);
|
|
166282
|
+
var EssEnergyServer = class extends EnergyFeaturedBase {
|
|
166283
|
+
async initialize() {
|
|
166284
|
+
await super.initialize();
|
|
166285
|
+
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
166286
|
+
this.update();
|
|
166287
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
166288
|
+
}
|
|
166289
|
+
update() {
|
|
166290
|
+
const mapping = this.agent.get(HomeAssistantEntityBehavior).state.mapping;
|
|
166291
|
+
const energyEntity = mapping?.batteryEnergyEntity;
|
|
166292
|
+
if (!energyEntity) return;
|
|
166293
|
+
const stateProvider = this.agent.env.get(EntityStateProvider);
|
|
166294
|
+
const kwh = stateProvider.getNumericState(energyEntity);
|
|
166295
|
+
if (kwh == null) return;
|
|
166296
|
+
const energyImported = { energy: Math.round(kwh * 1e6) };
|
|
166297
|
+
const changed = applyPatchState(this.state, {
|
|
166298
|
+
cumulativeEnergyImported: energyImported
|
|
166299
|
+
});
|
|
166300
|
+
if ("cumulativeEnergyImported" in changed) {
|
|
166301
|
+
this.events.cumulativeEnergyMeasured?.emit(
|
|
166302
|
+
{ energyImported, energyExported: void 0 },
|
|
166303
|
+
this.context
|
|
166304
|
+
);
|
|
166305
|
+
}
|
|
166306
|
+
}
|
|
166307
|
+
};
|
|
166308
|
+
((EssEnergyServer2) => {
|
|
166309
|
+
class State extends EnergyFeaturedBase.State {
|
|
166310
|
+
}
|
|
166311
|
+
EssEnergyServer2.State = State;
|
|
166312
|
+
})(EssEnergyServer || (EssEnergyServer = {}));
|
|
166313
|
+
var EssEnergy = EssEnergyServer.set({
|
|
166314
|
+
cumulativeEnergyImported: { energy: 0 },
|
|
166315
|
+
accuracy: {
|
|
166316
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.ElectricalEnergy,
|
|
166317
|
+
measured: true,
|
|
166318
|
+
minMeasuredValue: -1e6,
|
|
166319
|
+
maxMeasuredValue: 1e11,
|
|
166320
|
+
accuracyRanges: [
|
|
166321
|
+
{
|
|
166322
|
+
rangeMin: -1e6,
|
|
166323
|
+
rangeMax: 1e11,
|
|
166324
|
+
fixedMax: 1e3
|
|
166325
|
+
}
|
|
166326
|
+
]
|
|
166327
|
+
}
|
|
166328
|
+
});
|
|
166329
|
+
var BatteryStorageEssBase = BatteryStorageDevice.with(
|
|
166330
|
+
BasicInformationServer2,
|
|
166331
|
+
IdentifyServer2,
|
|
166332
|
+
HomeAssistantEntityBehavior,
|
|
166333
|
+
HaPowerTopologyServer,
|
|
166334
|
+
PowerSourceServer2({
|
|
166335
|
+
getBatteryPercent(entity) {
|
|
166336
|
+
const state = entity.state;
|
|
166337
|
+
if (state == null || Number.isNaN(+state)) {
|
|
166338
|
+
return null;
|
|
166339
|
+
}
|
|
166340
|
+
return +state;
|
|
166341
|
+
}
|
|
166342
|
+
})
|
|
166343
|
+
);
|
|
166344
|
+
function batteryStorageEssType(mapping) {
|
|
166345
|
+
let device = BatteryStorageEssBase;
|
|
166346
|
+
if (mapping?.batteryPowerEntity) device = device.with(EssPower);
|
|
166347
|
+
if (mapping?.batteryEnergyEntity) device = device.with(EssEnergy);
|
|
166348
|
+
return device;
|
|
166349
|
+
}
|
|
166350
|
+
|
|
166017
166351
|
// src/matter/behaviors/carbon-monoxide-concentration-measurement-server.ts
|
|
166018
166352
|
init_home_assistant_entity_behavior();
|
|
166019
166353
|
var CarbonMonoxideConcentrationMeasurementServerBase = CarbonMonoxideConcentrationMeasurementServer.with(
|
|
@@ -166105,10 +166439,14 @@ var CarbonMonoxideSensorType = AirQualitySensorDevice.with(
|
|
|
166105
166439
|
CarbonMonoxideConcentrationMeasurementServer2
|
|
166106
166440
|
);
|
|
166107
166441
|
|
|
166442
|
+
// src/matter/endpoints/legacy/sensor/devices/electrical-meter.ts
|
|
166443
|
+
init_home_assistant_entity_behavior();
|
|
166444
|
+
|
|
166108
166445
|
// src/matter/endpoints/legacy/sensor/devices/electrical-sensor.ts
|
|
166109
166446
|
init_dist();
|
|
166110
166447
|
init_home_assistant_entity_behavior();
|
|
166111
|
-
var
|
|
166448
|
+
var PowerFeaturedBase2 = ElectricalPowerMeasurementServer.with("AlternatingCurrent");
|
|
166449
|
+
var StandalonePowerServer = class extends PowerFeaturedBase2 {
|
|
166112
166450
|
async initialize() {
|
|
166113
166451
|
await super.initialize();
|
|
166114
166452
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
@@ -166116,36 +166454,48 @@ var StandalonePowerServer = class extends ElectricalPowerMeasurementServer {
|
|
|
166116
166454
|
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
166117
166455
|
}
|
|
166118
166456
|
update(entity) {
|
|
166119
|
-
|
|
166120
|
-
|
|
166121
|
-
|
|
166122
|
-
const
|
|
166123
|
-
if (
|
|
166124
|
-
|
|
166125
|
-
|
|
166126
|
-
|
|
166127
|
-
|
|
166128
|
-
|
|
166129
|
-
|
|
166130
|
-
|
|
166131
|
-
|
|
166132
|
-
|
|
166133
|
-
|
|
166134
|
-
|
|
166135
|
-
|
|
166136
|
-
|
|
166137
|
-
|
|
166457
|
+
const patch = {};
|
|
166458
|
+
const attrs = entity.state?.attributes;
|
|
166459
|
+
const dc = attrs?.device_class;
|
|
166460
|
+
const primary = entity.state?.state;
|
|
166461
|
+
if (primary != null && !Number.isNaN(+primary)) {
|
|
166462
|
+
if (dc === SensorDeviceClass.power) {
|
|
166463
|
+
patch.activePower = Math.round(+primary * 1e3);
|
|
166464
|
+
} else if (dc === SensorDeviceClass.voltage) {
|
|
166465
|
+
patch.voltage = Math.round(+primary * 1e3);
|
|
166466
|
+
} else if (dc === SensorDeviceClass.current) {
|
|
166467
|
+
patch.activeCurrent = Math.round(+primary * 1e3);
|
|
166468
|
+
}
|
|
166469
|
+
}
|
|
166470
|
+
const mapping = this.agent.get(HomeAssistantEntityBehavior).state.mapping;
|
|
166471
|
+
if (mapping?.powerEntity || mapping?.voltageEntity || mapping?.currentEntity) {
|
|
166472
|
+
const stateProvider = this.agent.env.get(EntityStateProvider);
|
|
166473
|
+
if (mapping.powerEntity) {
|
|
166474
|
+
const w = stateProvider.getNumericState(mapping.powerEntity);
|
|
166475
|
+
if (w != null) patch.activePower = Math.round(w * 1e3);
|
|
166476
|
+
}
|
|
166477
|
+
if (mapping.voltageEntity) {
|
|
166478
|
+
const v = stateProvider.getNumericState(mapping.voltageEntity);
|
|
166479
|
+
if (v != null) patch.voltage = Math.round(v * 1e3);
|
|
166480
|
+
}
|
|
166481
|
+
if (mapping.currentEntity) {
|
|
166482
|
+
const a = stateProvider.getNumericState(mapping.currentEntity);
|
|
166483
|
+
if (a != null) patch.activeCurrent = Math.round(a * 1e3);
|
|
166484
|
+
}
|
|
166138
166485
|
}
|
|
166486
|
+
if (Object.keys(patch).length > 0) applyPatchState(this.state, patch);
|
|
166139
166487
|
}
|
|
166140
166488
|
};
|
|
166141
166489
|
((StandalonePowerServer2) => {
|
|
166142
|
-
class State extends
|
|
166490
|
+
class State extends PowerFeaturedBase2.State {
|
|
166143
166491
|
}
|
|
166144
166492
|
StandalonePowerServer2.State = State;
|
|
166145
166493
|
})(StandalonePowerServer || (StandalonePowerServer = {}));
|
|
166146
166494
|
var PowerServer = StandalonePowerServer.set({
|
|
166147
166495
|
powerMode: ElectricalPowerMeasurement3.PowerMode.Ac,
|
|
166148
|
-
|
|
166496
|
+
// Power, voltage and current can all be folded onto this endpoint, so the
|
|
166497
|
+
// accuracy list carries an entry for each reported measurement type.
|
|
166498
|
+
numberOfMeasurementTypes: 3,
|
|
166149
166499
|
// SmartThings keeps the endpoint in a "device not yet updated" state
|
|
166150
166500
|
// when activePower stays null. Seed 0 so the cluster reports a value
|
|
166151
166501
|
// for energy/voltage/current-only sensors that never feed activePower.
|
|
@@ -166163,14 +166513,43 @@ var PowerServer = StandalonePowerServer.set({
|
|
|
166163
166513
|
fixedMax: 1e3
|
|
166164
166514
|
}
|
|
166165
166515
|
]
|
|
166516
|
+
},
|
|
166517
|
+
{
|
|
166518
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.Voltage,
|
|
166519
|
+
measured: true,
|
|
166520
|
+
minMeasuredValue: 0,
|
|
166521
|
+
maxMeasuredValue: 1e6,
|
|
166522
|
+
// 1000V in mV
|
|
166523
|
+
accuracyRanges: [
|
|
166524
|
+
{
|
|
166525
|
+
rangeMin: 0,
|
|
166526
|
+
rangeMax: 1e6,
|
|
166527
|
+
fixedMax: 1e3
|
|
166528
|
+
}
|
|
166529
|
+
]
|
|
166530
|
+
},
|
|
166531
|
+
{
|
|
166532
|
+
measurementType: ElectricalPowerMeasurement3.MeasurementType.ActiveCurrent,
|
|
166533
|
+
measured: true,
|
|
166534
|
+
minMeasuredValue: -1e6,
|
|
166535
|
+
// -1000A in mA
|
|
166536
|
+
maxMeasuredValue: 1e6,
|
|
166537
|
+
// 1000A in mA
|
|
166538
|
+
accuracyRanges: [
|
|
166539
|
+
{
|
|
166540
|
+
rangeMin: -1e6,
|
|
166541
|
+
rangeMax: 1e6,
|
|
166542
|
+
fixedMax: 1e3
|
|
166543
|
+
}
|
|
166544
|
+
]
|
|
166166
166545
|
}
|
|
166167
166546
|
]
|
|
166168
166547
|
});
|
|
166169
|
-
var
|
|
166548
|
+
var EnergyFeaturedBase2 = ElectricalEnergyMeasurementServer.with(
|
|
166170
166549
|
"CumulativeEnergy",
|
|
166171
166550
|
"ImportedEnergy"
|
|
166172
166551
|
);
|
|
166173
|
-
var StandaloneEnergyServer = class extends
|
|
166552
|
+
var StandaloneEnergyServer = class extends EnergyFeaturedBase2 {
|
|
166174
166553
|
async initialize() {
|
|
166175
166554
|
await super.initialize();
|
|
166176
166555
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
@@ -166178,32 +166557,39 @@ var StandaloneEnergyServer = class extends EnergyFeaturedBase {
|
|
|
166178
166557
|
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
166179
166558
|
}
|
|
166180
166559
|
update(entity) {
|
|
166181
|
-
|
|
166182
|
-
|
|
166560
|
+
let energyKwh = null;
|
|
166561
|
+
const attrs = entity.state?.attributes;
|
|
166562
|
+
if (attrs?.device_class === SensorDeviceClass.energy) {
|
|
166563
|
+
const state = entity.state?.state;
|
|
166564
|
+
if (state != null && !Number.isNaN(+state)) energyKwh = +state;
|
|
166565
|
+
}
|
|
166566
|
+
const mapping = this.agent.get(HomeAssistantEntityBehavior).state.mapping;
|
|
166567
|
+
if (mapping?.energyEntity) {
|
|
166568
|
+
const stateProvider = this.agent.env.get(EntityStateProvider);
|
|
166569
|
+
const mapped = stateProvider.getNumericState(mapping.energyEntity);
|
|
166570
|
+
if (mapped != null) energyKwh = mapped;
|
|
166183
166571
|
}
|
|
166184
|
-
|
|
166185
|
-
|
|
166186
|
-
const
|
|
166187
|
-
if (state == null || Number.isNaN(+state)) return;
|
|
166188
|
-
const energyMwh = Math.round(+state * 1e6);
|
|
166189
|
-
const energyImported = { energy: energyMwh };
|
|
166190
|
-
applyPatchState(this.state, {
|
|
166572
|
+
if (energyKwh == null) return;
|
|
166573
|
+
const energyImported = { energy: Math.round(energyKwh * 1e6) };
|
|
166574
|
+
const changed = applyPatchState(this.state, {
|
|
166191
166575
|
cumulativeEnergyImported: energyImported
|
|
166192
166576
|
});
|
|
166193
|
-
|
|
166194
|
-
|
|
166195
|
-
|
|
166196
|
-
|
|
166577
|
+
if ("cumulativeEnergyImported" in changed) {
|
|
166578
|
+
this.events.cumulativeEnergyMeasured?.emit(
|
|
166579
|
+
{ energyImported, energyExported: void 0 },
|
|
166580
|
+
this.context
|
|
166581
|
+
);
|
|
166582
|
+
}
|
|
166197
166583
|
}
|
|
166198
166584
|
};
|
|
166199
166585
|
((StandaloneEnergyServer2) => {
|
|
166200
|
-
class State extends
|
|
166586
|
+
class State extends EnergyFeaturedBase2.State {
|
|
166201
166587
|
}
|
|
166202
166588
|
StandaloneEnergyServer2.State = State;
|
|
166203
166589
|
})(StandaloneEnergyServer || (StandaloneEnergyServer = {}));
|
|
166204
166590
|
var EnergyServer = StandaloneEnergyServer.set({
|
|
166205
166591
|
// Match the activePower=0 default so SmartThings doesn't show "- kWh"
|
|
166206
|
-
// on
|
|
166592
|
+
// on an endpoint whose mapped entity only carries power data.
|
|
166207
166593
|
cumulativeEnergyImported: { energy: 0 },
|
|
166208
166594
|
accuracy: {
|
|
166209
166595
|
measurementType: ElectricalPowerMeasurement3.MeasurementType.ElectricalEnergy,
|
|
@@ -166228,6 +166614,15 @@ var ElectricalSensorType = SolarPowerDevice.with(
|
|
|
166228
166614
|
EnergyServer
|
|
166229
166615
|
);
|
|
166230
166616
|
|
|
166617
|
+
// src/matter/endpoints/legacy/sensor/devices/electrical-meter.ts
|
|
166618
|
+
var ElectricalMeterType = ElectricalMeterDevice.with(
|
|
166619
|
+
BasicInformationServer2,
|
|
166620
|
+
IdentifyServer2,
|
|
166621
|
+
HomeAssistantEntityBehavior,
|
|
166622
|
+
PowerServer,
|
|
166623
|
+
EnergyServer
|
|
166624
|
+
);
|
|
166625
|
+
|
|
166231
166626
|
// src/matter/behaviors/flow-measurement-server.ts
|
|
166232
166627
|
init_home_assistant_entity_behavior();
|
|
166233
166628
|
var FlowMeasurementServerBase = class extends FlowMeasurementServer {
|
|
@@ -167595,9 +167990,12 @@ function SensorDevice(homeAssistantEntity) {
|
|
|
167595
167990
|
return RadonSensorType.set({ homeAssistantEntity });
|
|
167596
167991
|
}
|
|
167597
167992
|
if (deviceClass === SensorDeviceClass.power || deviceClass === SensorDeviceClass.energy || deviceClass === SensorDeviceClass.voltage || deviceClass === SensorDeviceClass.current) {
|
|
167598
|
-
return
|
|
167993
|
+
return ElectricalMeterType.set({ homeAssistantEntity });
|
|
167599
167994
|
}
|
|
167600
167995
|
if (deviceClass === SensorDeviceClass.battery) {
|
|
167996
|
+
if (mapping?.batteryPowerEntity || mapping?.batteryEnergyEntity) {
|
|
167997
|
+
return batteryStorageEssType(mapping).set({ homeAssistantEntity });
|
|
167998
|
+
}
|
|
167601
167999
|
return BatterySensorType.set({ homeAssistantEntity });
|
|
167602
168000
|
}
|
|
167603
168001
|
if (deviceClass) {
|
|
@@ -167671,11 +168069,12 @@ function SwitchDevice(homeAssistantEntity) {
|
|
|
167671
168069
|
const hasBatteryEntity = !!homeAssistantEntity.mapping?.batteryEntity;
|
|
167672
168070
|
const hasPowerEntity = !!homeAssistantEntity.mapping?.powerEntity;
|
|
167673
168071
|
const hasEnergyEntity = !!homeAssistantEntity.mapping?.energyEntity;
|
|
168072
|
+
const hasElectricalPower = hasPowerEntity || !!homeAssistantEntity.mapping?.voltageEntity || !!homeAssistantEntity.mapping?.currentEntity;
|
|
167674
168073
|
let device = hasBatteryAttr || hasBatteryEntity ? SwitchWithBatteryEndpointType : SwitchEndpointType;
|
|
167675
|
-
if (
|
|
168074
|
+
if (hasElectricalPower || hasEnergyEntity) {
|
|
167676
168075
|
device = device.with(HaPowerTopologyServer);
|
|
167677
168076
|
}
|
|
167678
|
-
if (
|
|
168077
|
+
if (hasElectricalPower) {
|
|
167679
168078
|
device = device.with(HaElectricalPowerMeasurementServer);
|
|
167680
168079
|
}
|
|
167681
168080
|
if (hasEnergyEntity) {
|
|
@@ -169960,7 +170359,7 @@ function WeatherDevice(homeAssistant) {
|
|
|
169960
170359
|
|
|
169961
170360
|
// src/matter/endpoints/legacy/create-legacy-endpoint-type.ts
|
|
169962
170361
|
var legacyLogger = Logger.get("LegacyEndpointType");
|
|
169963
|
-
function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
170362
|
+
function createLegacyEndpointType(entity, mapping, areaName, options, identityAnchor) {
|
|
169964
170363
|
if (mapping?.disableBatteryMapping) {
|
|
169965
170364
|
entity = {
|
|
169966
170365
|
...entity,
|
|
@@ -169973,11 +170372,12 @@ function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
|
169973
170372
|
}
|
|
169974
170373
|
const domain = entity.entity_id.split(".")[0];
|
|
169975
170374
|
const customName = mapping?.customName;
|
|
170375
|
+
const ha = { entity, customName, mapping, identityAnchor };
|
|
169976
170376
|
let type;
|
|
169977
170377
|
if (mapping?.matterDeviceType) {
|
|
169978
170378
|
const overrideFactory = matterDeviceTypeFactories[mapping.matterDeviceType];
|
|
169979
170379
|
if (overrideFactory) {
|
|
169980
|
-
type = overrideFactory(
|
|
170380
|
+
type = overrideFactory(ha);
|
|
169981
170381
|
if (type && mapping.batteryEntity && !hasPowerSource(type)) {
|
|
169982
170382
|
type = addPowerSource(type);
|
|
169983
170383
|
}
|
|
@@ -169986,14 +170386,14 @@ function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
|
169986
170386
|
if (!type) {
|
|
169987
170387
|
if (domain === "vacuum") {
|
|
169988
170388
|
type = VacuumDevice(
|
|
169989
|
-
|
|
170389
|
+
ha,
|
|
169990
170390
|
options?.vacuumOnOff,
|
|
169991
170391
|
options?.cleaningModeOptions
|
|
169992
170392
|
);
|
|
169993
170393
|
} else {
|
|
169994
170394
|
const factory = deviceCtrs[domain];
|
|
169995
170395
|
if (factory) {
|
|
169996
|
-
type = factory(
|
|
170396
|
+
type = factory(ha);
|
|
169997
170397
|
} else if (options?.pluginDomainMappings?.has(domain)) {
|
|
169998
170398
|
const mappedType = options.pluginDomainMappings.get(domain);
|
|
169999
170399
|
const mappedFactory = matterDeviceTypeFactories[mappedType];
|
|
@@ -170001,7 +170401,7 @@ function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
|
170001
170401
|
legacyLogger.info(
|
|
170002
170402
|
`Using plugin domain mapping for "${domain}" \u2192 "${mappedType}"`
|
|
170003
170403
|
);
|
|
170004
|
-
type = mappedFactory(
|
|
170404
|
+
type = mappedFactory(ha);
|
|
170005
170405
|
}
|
|
170006
170406
|
} else {
|
|
170007
170407
|
return void 0;
|
|
@@ -170112,7 +170512,12 @@ var matterDeviceTypeFactories = {
|
|
|
170112
170512
|
light_sensor: (ha) => IlluminanceSensorType.set({ homeAssistantEntity: ha }),
|
|
170113
170513
|
flow_sensor: (ha) => FlowSensorType.set({ homeAssistantEntity: ha }),
|
|
170114
170514
|
air_quality_sensor: (ha) => AirQualitySensorType.set({ homeAssistantEntity: ha }),
|
|
170115
|
-
battery_storage: (ha) =>
|
|
170515
|
+
battery_storage: (ha) => {
|
|
170516
|
+
if (ha.mapping?.batteryPowerEntity || ha.mapping?.batteryEnergyEntity) {
|
|
170517
|
+
return batteryStorageEssType(ha.mapping).set({ homeAssistantEntity: ha });
|
|
170518
|
+
}
|
|
170519
|
+
return BatterySensorType.set({ homeAssistantEntity: ha });
|
|
170520
|
+
},
|
|
170116
170521
|
tvoc_sensor: (ha) => TvocSensorType.set({ homeAssistantEntity: ha }),
|
|
170117
170522
|
carbon_monoxide_sensor: (ha) => CarbonMonoxideSensorType.set({ homeAssistantEntity: ha }),
|
|
170118
170523
|
nitrogen_dioxide_sensor: (ha) => NitrogenDioxideSensorType.set({ homeAssistantEntity: ha }),
|
|
@@ -170120,7 +170525,10 @@ var matterDeviceTypeFactories = {
|
|
|
170120
170525
|
formaldehyde_sensor: (ha) => FormaldehydeSensorType.set({ homeAssistantEntity: ha }),
|
|
170121
170526
|
radon_sensor: (ha) => RadonSensorType.set({ homeAssistantEntity: ha }),
|
|
170122
170527
|
pm1_sensor: (ha) => Pm1SensorType.set({ homeAssistantEntity: ha }),
|
|
170528
|
+
electrical_meter: (ha) => ElectricalMeterType.set({ homeAssistantEntity: ha }),
|
|
170529
|
+
// Legacy SolarPower alias, kept for existing mappings.
|
|
170123
170530
|
electrical_sensor: (ha) => ElectricalSensorType.set({ homeAssistantEntity: ha }),
|
|
170531
|
+
solar_power: (ha) => ElectricalSensorType.set({ homeAssistantEntity: ha }),
|
|
170124
170532
|
contact_sensor: (ha) => ContactSensorType.set({ homeAssistantEntity: ha }),
|
|
170125
170533
|
motion_sensor: (ha) => MotionSensorType.set({ homeAssistantEntity: ha }),
|
|
170126
170534
|
occupancy_sensor: (ha) => OccupancySensorType.set({ homeAssistantEntity: ha }),
|
|
@@ -170186,7 +170594,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
|
170186
170594
|
if (hasParentBattery) {
|
|
170187
170595
|
parentType = parentType.with(DefaultPowerSourceServer);
|
|
170188
170596
|
}
|
|
170189
|
-
const endpointId = createEndpointId5(primaryEntityId, config11.customName);
|
|
170597
|
+
const endpointId = config11.endpointId ?? createEndpointId5(primaryEntityId, config11.customName);
|
|
170190
170598
|
const parts = [];
|
|
170191
170599
|
const subEndpointMap = /* @__PURE__ */ new Map();
|
|
170192
170600
|
const mappedIds = [];
|
|
@@ -170264,7 +170672,8 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
|
170264
170672
|
homeAssistantEntity: {
|
|
170265
170673
|
entity: primaryPayload,
|
|
170266
170674
|
customName: config11.customName,
|
|
170267
|
-
mapping: config11.mapping
|
|
170675
|
+
mapping: config11.mapping,
|
|
170676
|
+
identityAnchor: config11.identityAnchor
|
|
170268
170677
|
}
|
|
170269
170678
|
});
|
|
170270
170679
|
const endpoint = new _UserComposedEndpoint(
|
|
@@ -170386,7 +170795,7 @@ function asStandaloneEndpointType(type) {
|
|
|
170386
170795
|
// src/matter/endpoints/legacy/legacy-endpoint.ts
|
|
170387
170796
|
var logger240 = Logger.get("LegacyEndpoint");
|
|
170388
170797
|
var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
170389
|
-
static async create(registry2, entityId, mapping, pluginDomainMappings, standalone = false) {
|
|
170798
|
+
static async create(registry2, entityId, mapping, pluginDomainMappings, standalone = false, endpointId, identityAnchor) {
|
|
170390
170799
|
const deviceRegistry = registry2.deviceOf(entityId);
|
|
170391
170800
|
let state = registry2.initialState(entityId);
|
|
170392
170801
|
const entity = registry2.entity(entityId);
|
|
@@ -170639,7 +171048,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170639
171048
|
mapping: effectiveMapping,
|
|
170640
171049
|
composedEntities: effectiveMapping.composedEntities,
|
|
170641
171050
|
customName: effectiveMapping?.customName,
|
|
170642
|
-
areaName: composedAreaName
|
|
171051
|
+
areaName: composedAreaName,
|
|
171052
|
+
endpointId,
|
|
171053
|
+
identityAnchor
|
|
170643
171054
|
});
|
|
170644
171055
|
if (composed) {
|
|
170645
171056
|
return composed;
|
|
@@ -170661,7 +171072,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170661
171072
|
powerEntityId: effectiveMapping?.powerEntity,
|
|
170662
171073
|
energyEntityId: effectiveMapping?.energyEntity,
|
|
170663
171074
|
customName: effectiveMapping?.customName,
|
|
170664
|
-
areaName: composedAreaName
|
|
171075
|
+
areaName: composedAreaName,
|
|
171076
|
+
endpointId,
|
|
171077
|
+
identityAnchor
|
|
170665
171078
|
});
|
|
170666
171079
|
return composed;
|
|
170667
171080
|
}
|
|
@@ -170681,7 +171094,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170681
171094
|
energyEntityId: effectiveMapping?.energyEntity,
|
|
170682
171095
|
mapping: effectiveMapping,
|
|
170683
171096
|
customName: effectiveMapping?.customName,
|
|
170684
|
-
areaName: composedAreaName
|
|
171097
|
+
areaName: composedAreaName,
|
|
171098
|
+
endpointId,
|
|
171099
|
+
identityAnchor
|
|
170685
171100
|
});
|
|
170686
171101
|
if (composed) {
|
|
170687
171102
|
return composed;
|
|
@@ -170698,7 +171113,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170698
171113
|
primaryEntityId: entityId,
|
|
170699
171114
|
mapping: effectiveMapping,
|
|
170700
171115
|
customName: effectiveMapping?.customName,
|
|
170701
|
-
areaName: composedAreaName
|
|
171116
|
+
areaName: composedAreaName,
|
|
171117
|
+
endpointId,
|
|
171118
|
+
identityAnchor
|
|
170702
171119
|
});
|
|
170703
171120
|
if (composed) {
|
|
170704
171121
|
return composed;
|
|
@@ -170732,11 +171149,17 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170732
171149
|
}
|
|
170733
171150
|
}
|
|
170734
171151
|
const areaName = registry2.getAreaName(entityId);
|
|
170735
|
-
let type = createLegacyEndpointType(
|
|
170736
|
-
|
|
170737
|
-
|
|
170738
|
-
|
|
170739
|
-
|
|
171152
|
+
let type = createLegacyEndpointType(
|
|
171153
|
+
payload,
|
|
171154
|
+
effectiveMapping,
|
|
171155
|
+
areaName,
|
|
171156
|
+
{
|
|
171157
|
+
vacuumOnOff: registry2.isVacuumOnOffEnabled(),
|
|
171158
|
+
cleaningModeOptions,
|
|
171159
|
+
pluginDomainMappings
|
|
171160
|
+
},
|
|
171161
|
+
identityAnchor
|
|
171162
|
+
);
|
|
170740
171163
|
if (!type) {
|
|
170741
171164
|
return;
|
|
170742
171165
|
}
|
|
@@ -170750,11 +171173,12 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170750
171173
|
entityId,
|
|
170751
171174
|
customName,
|
|
170752
171175
|
mappedIds,
|
|
170753
|
-
effectiveMapping?.updateThrottleMs
|
|
171176
|
+
effectiveMapping?.updateThrottleMs,
|
|
171177
|
+
endpointId
|
|
170754
171178
|
);
|
|
170755
171179
|
}
|
|
170756
|
-
constructor(type, entityId, customName, mappedEntityIds, throttleMs) {
|
|
170757
|
-
super(type, entityId, customName, mappedEntityIds);
|
|
171180
|
+
constructor(type, entityId, customName, mappedEntityIds, throttleMs, endpointId) {
|
|
171181
|
+
super(type, entityId, customName, mappedEntityIds, endpointId);
|
|
170758
171182
|
this.flushUpdate = throttleMs && throttleMs > 50 ? throttleLatest(this.flushPendingUpdate.bind(this), throttleMs) : debounce6(this.flushPendingUpdate.bind(this), 50);
|
|
170759
171183
|
}
|
|
170760
171184
|
lastState;
|
|
@@ -171601,11 +172025,124 @@ var EntityIsolationServiceImpl = class {
|
|
|
171601
172025
|
};
|
|
171602
172026
|
var EntityIsolationService = new EntityIsolationServiceImpl();
|
|
171603
172027
|
|
|
172028
|
+
// src/services/bridges/identity-resolver.ts
|
|
172029
|
+
var SEP = "\0";
|
|
172030
|
+
function identityKey(entity) {
|
|
172031
|
+
const uniqueId = entity.registry?.unique_id;
|
|
172032
|
+
const platform = entity.registry?.platform;
|
|
172033
|
+
if (!uniqueId || !platform) {
|
|
172034
|
+
return null;
|
|
172035
|
+
}
|
|
172036
|
+
const domain = entity.entity_id.split(".")[0];
|
|
172037
|
+
return platform + SEP + domain + SEP + uniqueId;
|
|
172038
|
+
}
|
|
172039
|
+
var IdentityResolver = class {
|
|
172040
|
+
constructor(identityStorage, mappingStorage) {
|
|
172041
|
+
this.identityStorage = identityStorage;
|
|
172042
|
+
this.mappingStorage = mappingStorage;
|
|
172043
|
+
}
|
|
172044
|
+
identityStorage;
|
|
172045
|
+
mappingStorage;
|
|
172046
|
+
async resolveIdentity(bridgeId, entity, mapping, opts) {
|
|
172047
|
+
const entityId = entity.entity_id;
|
|
172048
|
+
const key = identityKey(entity);
|
|
172049
|
+
if (key == null) {
|
|
172050
|
+
return {
|
|
172051
|
+
endpointId: createEndpointId(entityId, mapping?.customName),
|
|
172052
|
+
anchorEntityId: entityId,
|
|
172053
|
+
protected: false
|
|
172054
|
+
};
|
|
172055
|
+
}
|
|
172056
|
+
const existing = this.identityStorage.getIdentity(bridgeId, key);
|
|
172057
|
+
if (existing) {
|
|
172058
|
+
const renamedFrom = existing.lastEntityId !== entityId ? existing.lastEntityId ?? existing.anchorEntityId : void 0;
|
|
172059
|
+
if (opts.stableIdentity) {
|
|
172060
|
+
if (renamedFrom) {
|
|
172061
|
+
this.identityStorage.setIdentity(bridgeId, key, {
|
|
172062
|
+
...existing,
|
|
172063
|
+
lastEntityId: entityId
|
|
172064
|
+
});
|
|
172065
|
+
await this.rekeyMapping(bridgeId, renamedFrom, entityId);
|
|
172066
|
+
}
|
|
172067
|
+
return {
|
|
172068
|
+
endpointId: existing.endpointId,
|
|
172069
|
+
anchorEntityId: existing.anchorEntityId,
|
|
172070
|
+
protected: true,
|
|
172071
|
+
renamedFrom
|
|
172072
|
+
};
|
|
172073
|
+
}
|
|
172074
|
+
const liveEndpointId = createEndpointId(entityId, mapping?.customName);
|
|
172075
|
+
if (existing.endpointId !== liveEndpointId || existing.anchorEntityId !== entityId || existing.lastEntityId !== entityId) {
|
|
172076
|
+
this.identityStorage.setIdentity(bridgeId, key, {
|
|
172077
|
+
...existing,
|
|
172078
|
+
endpointId: liveEndpointId,
|
|
172079
|
+
anchorEntityId: entityId,
|
|
172080
|
+
lastEntityId: entityId
|
|
172081
|
+
});
|
|
172082
|
+
}
|
|
172083
|
+
return {
|
|
172084
|
+
endpointId: liveEndpointId,
|
|
172085
|
+
anchorEntityId: entityId,
|
|
172086
|
+
protected: false,
|
|
172087
|
+
renamedFrom
|
|
172088
|
+
};
|
|
172089
|
+
}
|
|
172090
|
+
const desired = createEndpointId(entityId, mapping?.customName);
|
|
172091
|
+
let endpointId = desired;
|
|
172092
|
+
if (opts.stableIdentity) {
|
|
172093
|
+
let n = 2;
|
|
172094
|
+
while (opts.isEndpointIdTaken(endpointId, key)) {
|
|
172095
|
+
endpointId = `${desired}_${n++}`;
|
|
172096
|
+
}
|
|
172097
|
+
}
|
|
172098
|
+
const record = {
|
|
172099
|
+
endpointId,
|
|
172100
|
+
anchorEntityId: entityId,
|
|
172101
|
+
lastEntityId: entityId,
|
|
172102
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
172103
|
+
};
|
|
172104
|
+
this.identityStorage.setIdentity(bridgeId, key, record);
|
|
172105
|
+
if (opts.stableIdentity) {
|
|
172106
|
+
return {
|
|
172107
|
+
endpointId: record.endpointId,
|
|
172108
|
+
anchorEntityId: record.anchorEntityId,
|
|
172109
|
+
protected: true
|
|
172110
|
+
};
|
|
172111
|
+
}
|
|
172112
|
+
return {
|
|
172113
|
+
endpointId: desired,
|
|
172114
|
+
anchorEntityId: entityId,
|
|
172115
|
+
protected: false
|
|
172116
|
+
};
|
|
172117
|
+
}
|
|
172118
|
+
// Carry a mapping from the old entity_id to the new one on rename. anchorEntityId
|
|
172119
|
+
// never changes, only the mapping key. Skips when no old mapping exists or a new
|
|
172120
|
+
// one already does, so a manual mapping under the new id is never clobbered.
|
|
172121
|
+
async rekeyMapping(bridgeId, oldEntityId, newEntityId) {
|
|
172122
|
+
if (oldEntityId === newEntityId) {
|
|
172123
|
+
return;
|
|
172124
|
+
}
|
|
172125
|
+
const old = this.mappingStorage.getMapping(bridgeId, oldEntityId);
|
|
172126
|
+
if (!old) {
|
|
172127
|
+
return;
|
|
172128
|
+
}
|
|
172129
|
+
if (this.mappingStorage.getMapping(bridgeId, newEntityId)) {
|
|
172130
|
+
return;
|
|
172131
|
+
}
|
|
172132
|
+
await this.mappingStorage.setMapping({
|
|
172133
|
+
...old,
|
|
172134
|
+
bridgeId,
|
|
172135
|
+
entityId: newEntityId
|
|
172136
|
+
});
|
|
172137
|
+
await this.mappingStorage.deleteMapping(bridgeId, oldEntityId);
|
|
172138
|
+
}
|
|
172139
|
+
};
|
|
172140
|
+
|
|
171604
172141
|
// src/services/bridges/bridge-endpoint-manager.ts
|
|
171605
172142
|
var MAX_ENTITY_ID_LENGTH = 150;
|
|
171606
172143
|
var ENDPOINT_REMOVAL_GRACE_MS = 6e4;
|
|
171607
172144
|
var BridgeEndpointManager = class extends Service {
|
|
171608
|
-
constructor(client, registry2, mappingStorage, bridgeId, log, pluginManager, pluginRegistry, pluginInstaller) {
|
|
172145
|
+
constructor(client, registry2, mappingStorage, identityStorage, bridgeId, log, pluginManager, pluginRegistry, pluginInstaller) {
|
|
171609
172146
|
super("BridgeEndpointManager");
|
|
171610
172147
|
this.client = client;
|
|
171611
172148
|
this.registry = registry2;
|
|
@@ -171616,6 +172153,10 @@ var BridgeEndpointManager = class extends Service {
|
|
|
171616
172153
|
this.pluginRegistry = pluginRegistry;
|
|
171617
172154
|
this.pluginInstaller = pluginInstaller;
|
|
171618
172155
|
this.root = new AggregatorEndpoint2("aggregator");
|
|
172156
|
+
this.identityResolver = new IdentityResolver(
|
|
172157
|
+
identityStorage,
|
|
172158
|
+
mappingStorage
|
|
172159
|
+
);
|
|
171619
172160
|
EntityIsolationService.registerIsolationCallback(
|
|
171620
172161
|
bridgeId,
|
|
171621
172162
|
this.isolateEntity.bind(this)
|
|
@@ -171654,6 +172195,7 @@ var BridgeEndpointManager = class extends Service {
|
|
|
171654
172195
|
failedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
171655
172196
|
});
|
|
171656
172197
|
}
|
|
172198
|
+
identityResolver;
|
|
171657
172199
|
wirePluginCallbacks() {
|
|
171658
172200
|
if (!this.pluginManager) return;
|
|
171659
172201
|
this.pluginManager.onDeviceRegistered = async (pluginName, device) => {
|
|
@@ -171993,10 +172535,57 @@ var BridgeEndpointManager = class extends Service {
|
|
|
171993
172535
|
if (humId) this.registry.markComposedSubEntityUsed(humId);
|
|
171994
172536
|
}
|
|
171995
172537
|
}
|
|
172538
|
+
const stableIdentity = this.registry.isStableIdentityEnabled();
|
|
172539
|
+
const resolvedByEntity = /* @__PURE__ */ new Map();
|
|
172540
|
+
const endpointIdToEntity = /* @__PURE__ */ new Map();
|
|
172541
|
+
const claimedEndpointIds = /* @__PURE__ */ new Map();
|
|
172542
|
+
for (const entityId of this.entityIds) {
|
|
172543
|
+
const entityInfo = {
|
|
172544
|
+
entity_id: entityId,
|
|
172545
|
+
registry: this.registry.entity(entityId)
|
|
172546
|
+
};
|
|
172547
|
+
const resolved = await this.identityResolver.resolveIdentity(
|
|
172548
|
+
this.bridgeId,
|
|
172549
|
+
entityInfo,
|
|
172550
|
+
this.getEntityMapping(entityId),
|
|
172551
|
+
{
|
|
172552
|
+
stableIdentity,
|
|
172553
|
+
isEndpointIdTaken: (id, key) => claimedEndpointIds.has(id) && claimedEndpointIds.get(id) !== key
|
|
172554
|
+
}
|
|
172555
|
+
);
|
|
172556
|
+
resolvedByEntity.set(entityId, resolved);
|
|
172557
|
+
claimedEndpointIds.set(
|
|
172558
|
+
resolved.endpointId,
|
|
172559
|
+
identityKey(entityInfo) ?? `\0e:${entityId}`
|
|
172560
|
+
);
|
|
172561
|
+
endpointIdToEntity.set(resolved.endpointId, entityId);
|
|
172562
|
+
if (resolved.renamedFrom && this.mappingFingerprints.has(resolved.renamedFrom)) {
|
|
172563
|
+
const fp = this.mappingFingerprints.get(resolved.renamedFrom);
|
|
172564
|
+
this.mappingFingerprints.delete(resolved.renamedFrom);
|
|
172565
|
+
this.mappingFingerprints.set(entityId, fp);
|
|
172566
|
+
}
|
|
172567
|
+
}
|
|
171996
172568
|
const existingEndpoints = [];
|
|
171997
172569
|
const now = Date.now();
|
|
171998
172570
|
for (const endpoint of endpoints) {
|
|
171999
172571
|
const present = this.entityIds.includes(endpoint.entityId);
|
|
172572
|
+
const claimant = endpointIdToEntity.get(endpoint.id);
|
|
172573
|
+
if (!present && claimant != null && claimant !== endpoint.entityId) {
|
|
172574
|
+
this.log.info(
|
|
172575
|
+
`Entity renamed ${endpoint.entityId} -> ${claimant}, keeping endpoint ${endpoint.id}`
|
|
172576
|
+
);
|
|
172577
|
+
try {
|
|
172578
|
+
await endpoint.close();
|
|
172579
|
+
} catch (e) {
|
|
172580
|
+
this.log.warn(
|
|
172581
|
+
`Failed to close renamed endpoint ${endpoint.entityId}:`,
|
|
172582
|
+
e
|
|
172583
|
+
);
|
|
172584
|
+
}
|
|
172585
|
+
this.pendingRemovals.delete(endpoint.entityId);
|
|
172586
|
+
this.mappingFingerprints.delete(endpoint.entityId);
|
|
172587
|
+
continue;
|
|
172588
|
+
}
|
|
172000
172589
|
if (present) {
|
|
172001
172590
|
this.pendingRemovals.delete(endpoint.entityId);
|
|
172002
172591
|
}
|
|
@@ -172039,7 +172628,8 @@ var BridgeEndpointManager = class extends Service {
|
|
|
172039
172628
|
this.log.info(
|
|
172040
172629
|
`Mapping changed for ${endpoint.entityId}, recreating endpoint`
|
|
172041
172630
|
);
|
|
172042
|
-
const
|
|
172631
|
+
const resolvedId = resolvedByEntity.get(endpoint.entityId)?.endpointId ?? createEndpointId(endpoint.entityId, currentMapping?.customName);
|
|
172632
|
+
const sameId = resolvedId === endpoint.id;
|
|
172043
172633
|
try {
|
|
172044
172634
|
if (sameId) {
|
|
172045
172635
|
await endpoint.close();
|
|
@@ -172097,11 +172687,15 @@ var BridgeEndpointManager = class extends Service {
|
|
|
172097
172687
|
if (!endpoint) {
|
|
172098
172688
|
try {
|
|
172099
172689
|
const domainMappings = this.getPluginDomainMappings();
|
|
172690
|
+
const resolved = resolvedByEntity.get(entityId);
|
|
172100
172691
|
endpoint = await LegacyEndpoint.create(
|
|
172101
172692
|
this.registry,
|
|
172102
172693
|
entityId,
|
|
172103
172694
|
mapping,
|
|
172104
|
-
domainMappings
|
|
172695
|
+
domainMappings,
|
|
172696
|
+
false,
|
|
172697
|
+
resolved?.endpointId,
|
|
172698
|
+
resolved?.anchorEntityId
|
|
172105
172699
|
);
|
|
172106
172700
|
} catch (e) {
|
|
172107
172701
|
const reason = this.extractErrorReason(e);
|
|
@@ -172513,6 +173107,11 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
172513
173107
|
isVacuumOnOffEnabled() {
|
|
172514
173108
|
return this.dataProvider.featureFlags?.vacuumOnOff === true;
|
|
172515
173109
|
}
|
|
173110
|
+
// Consume frozen device identities (#404). Seeding always runs; only
|
|
173111
|
+
// consumption of the stored endpoint id/anchor is gated on this flag.
|
|
173112
|
+
isStableIdentityEnabled() {
|
|
173113
|
+
return this.dataProvider.featureFlags?.stableIdentity === true;
|
|
173114
|
+
}
|
|
172516
173115
|
/**
|
|
172517
173116
|
* Check if the vacuum OnOff cluster should be included for server-mode vacuums.
|
|
172518
173117
|
* Defaults to OFF. OnOff is NOT part of the RoboticVacuumCleaner (0x74) device
|
|
@@ -173942,7 +174541,7 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
|
|
|
173942
174541
|
// src/matter/endpoints/server-mode-vacuum-endpoint.ts
|
|
173943
174542
|
var logger243 = Logger.get("ServerModeVacuumEndpoint");
|
|
173944
174543
|
var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEndpoint {
|
|
173945
|
-
static async create(registry2, entityId, mapping) {
|
|
174544
|
+
static async create(registry2, entityId, mapping, endpointId) {
|
|
173946
174545
|
const deviceRegistry = registry2.deviceOf(entityId);
|
|
173947
174546
|
let state = registry2.initialState(entityId);
|
|
173948
174547
|
const entity = registry2.entity(entityId);
|
|
@@ -174123,14 +174722,15 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
174123
174722
|
endpointType,
|
|
174124
174723
|
entityId,
|
|
174125
174724
|
customName,
|
|
174126
|
-
mappedIds
|
|
174725
|
+
mappedIds,
|
|
174726
|
+
endpointId
|
|
174127
174727
|
);
|
|
174128
174728
|
}
|
|
174129
174729
|
lastState;
|
|
174130
174730
|
pendingMappedChange = false;
|
|
174131
174731
|
flushUpdate;
|
|
174132
|
-
constructor(type, entityId, customName, mappedEntityIds) {
|
|
174133
|
-
super(type, entityId, customName, mappedEntityIds);
|
|
174732
|
+
constructor(type, entityId, customName, mappedEntityIds, endpointId) {
|
|
174733
|
+
super(type, entityId, customName, mappedEntityIds, endpointId);
|
|
174134
174734
|
this.flushUpdate = debounce7(this.flushPendingUpdate.bind(this), 50);
|
|
174135
174735
|
}
|
|
174136
174736
|
clearTimers() {
|
|
@@ -174197,7 +174797,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
174197
174797
|
// src/services/bridges/server-mode-endpoint-manager.ts
|
|
174198
174798
|
var MAX_SERVER_MODE_DEVICES = 10;
|
|
174199
174799
|
var ServerModeEndpointManager = class extends Service {
|
|
174200
|
-
constructor(serverNode, client, registry2, mappingStorage, dataProvider, log) {
|
|
174800
|
+
constructor(serverNode, client, registry2, mappingStorage, identityStorage, dataProvider, log) {
|
|
174201
174801
|
super("ServerModeEndpointManager");
|
|
174202
174802
|
this.serverNode = serverNode;
|
|
174203
174803
|
this.client = client;
|
|
@@ -174205,6 +174805,10 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174205
174805
|
this.mappingStorage = mappingStorage;
|
|
174206
174806
|
this.dataProvider = dataProvider;
|
|
174207
174807
|
this.log = log;
|
|
174808
|
+
this.identityResolver = new IdentityResolver(
|
|
174809
|
+
identityStorage,
|
|
174810
|
+
mappingStorage
|
|
174811
|
+
);
|
|
174208
174812
|
}
|
|
174209
174813
|
serverNode;
|
|
174210
174814
|
client;
|
|
@@ -174223,6 +174827,7 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174223
174827
|
get devices() {
|
|
174224
174828
|
return [...this.endpoints.values()].map((entry) => entry.endpoint);
|
|
174225
174829
|
}
|
|
174830
|
+
identityResolver;
|
|
174226
174831
|
getEntityMapping(entityId) {
|
|
174227
174832
|
return this.mappingStorage.getMapping(this.dataProvider.id, entityId);
|
|
174228
174833
|
}
|
|
@@ -174291,6 +174896,19 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174291
174896
|
this.endpoints.delete(entityId);
|
|
174292
174897
|
}
|
|
174293
174898
|
}
|
|
174899
|
+
// Like removeEndpoints but close() keeps the persisted number pre-allocated,
|
|
174900
|
+
// so a same-id recreate reuses it. Used on rename and same-id recreates (#404).
|
|
174901
|
+
async closeEndpoint(entityId) {
|
|
174902
|
+
const entry = this.endpoints.get(entityId);
|
|
174903
|
+
if (!entry) return;
|
|
174904
|
+
try {
|
|
174905
|
+
await entry.endpoint.close();
|
|
174906
|
+
} catch (e) {
|
|
174907
|
+
this.log.warn(`Failed to close endpoint ${entityId}:`, e);
|
|
174908
|
+
}
|
|
174909
|
+
this.serverNode.forgetDevice(entry.endpoint);
|
|
174910
|
+
this.endpoints.delete(entityId);
|
|
174911
|
+
}
|
|
174294
174912
|
async refreshDevices() {
|
|
174295
174913
|
this.registry.refresh();
|
|
174296
174914
|
this._failedEntities = [];
|
|
@@ -174318,10 +174936,45 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174318
174936
|
`Server mode node is capped at ${MAX_SERVER_MODE_DEVICES} devices, ${surplus.length} entities skipped`
|
|
174319
174937
|
);
|
|
174320
174938
|
}
|
|
174939
|
+
const stableIdentity = this.dataProvider.featureFlags?.stableIdentity === true;
|
|
174940
|
+
const resolvedByEntity = /* @__PURE__ */ new Map();
|
|
174941
|
+
const endpointIdToEntity = /* @__PURE__ */ new Map();
|
|
174942
|
+
const claimedEndpointIds = /* @__PURE__ */ new Map();
|
|
174943
|
+
for (const entityId of orderedIds) {
|
|
174944
|
+
const entityInfo = {
|
|
174945
|
+
entity_id: entityId,
|
|
174946
|
+
registry: this.registry.entity(entityId)
|
|
174947
|
+
};
|
|
174948
|
+
const resolved = await this.identityResolver.resolveIdentity(
|
|
174949
|
+
this.dataProvider.id,
|
|
174950
|
+
entityInfo,
|
|
174951
|
+
this.getEntityMapping(entityId),
|
|
174952
|
+
{
|
|
174953
|
+
stableIdentity,
|
|
174954
|
+
isEndpointIdTaken: (id, key) => claimedEndpointIds.has(id) && claimedEndpointIds.get(id) !== key
|
|
174955
|
+
}
|
|
174956
|
+
);
|
|
174957
|
+
resolvedByEntity.set(entityId, resolved);
|
|
174958
|
+
claimedEndpointIds.set(
|
|
174959
|
+
resolved.endpointId,
|
|
174960
|
+
identityKey(entityInfo) ?? `\0e:${entityId}`
|
|
174961
|
+
);
|
|
174962
|
+
endpointIdToEntity.set(resolved.endpointId, entityId);
|
|
174963
|
+
}
|
|
174321
174964
|
const keep = new Set(orderedIds);
|
|
174322
174965
|
const removed = [...this.endpoints.keys()].filter((id) => !keep.has(id));
|
|
174323
174966
|
let structureChanged = removed.length > 0;
|
|
174324
|
-
|
|
174967
|
+
const genuinelyRemoved = [];
|
|
174968
|
+
for (const oldId of removed) {
|
|
174969
|
+
const entry = this.endpoints.get(oldId);
|
|
174970
|
+
const claimant = entry ? endpointIdToEntity.get(entry.endpoint.id) : void 0;
|
|
174971
|
+
if (entry && claimant != null && claimant !== oldId) {
|
|
174972
|
+
await this.closeEndpoint(oldId);
|
|
174973
|
+
} else {
|
|
174974
|
+
genuinelyRemoved.push(oldId);
|
|
174975
|
+
}
|
|
174976
|
+
}
|
|
174977
|
+
await this.removeEndpoints(genuinelyRemoved);
|
|
174325
174978
|
for (const entityId of orderedIds) {
|
|
174326
174979
|
const mapping = this.getEntityMapping(entityId);
|
|
174327
174980
|
if (mapping?.disabled) {
|
|
@@ -174344,9 +174997,14 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174344
174997
|
this.log.debug(`Device endpoint already exists for ${entityId}`);
|
|
174345
174998
|
continue;
|
|
174346
174999
|
}
|
|
175000
|
+
const resolved = resolvedByEntity.get(entityId);
|
|
174347
175001
|
if (existing) {
|
|
174348
175002
|
this.log.info(`Mapping changed for ${entityId}, recreating endpoint`);
|
|
174349
|
-
|
|
175003
|
+
if (resolved && existing.endpoint.id === resolved.endpointId) {
|
|
175004
|
+
await this.closeEndpoint(entityId);
|
|
175005
|
+
} else {
|
|
175006
|
+
await this.removeEndpoints([entityId]);
|
|
175007
|
+
}
|
|
174350
175008
|
structureChanged = true;
|
|
174351
175009
|
}
|
|
174352
175010
|
const claimedBy = [...this.endpoints.entries()].find(
|
|
@@ -174359,7 +175017,7 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174359
175017
|
});
|
|
174360
175018
|
continue;
|
|
174361
175019
|
}
|
|
174362
|
-
const endpointId = createEndpointId(entityId, mapping?.customName);
|
|
175020
|
+
const endpointId = resolved?.endpointId ?? createEndpointId(entityId, mapping?.customName);
|
|
174363
175021
|
const collision = [...this.endpoints.entries()].find(
|
|
174364
175022
|
([, entry]) => entry.endpoint.id === endpointId
|
|
174365
175023
|
);
|
|
@@ -174382,12 +175040,18 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174382
175040
|
}
|
|
174383
175041
|
try {
|
|
174384
175042
|
const domain = entityId.split(".")[0];
|
|
174385
|
-
const endpoint = domain === "vacuum" ? await this.createServerModeVacuumEndpoint(
|
|
175043
|
+
const endpoint = domain === "vacuum" ? await this.createServerModeVacuumEndpoint(
|
|
175044
|
+
entityId,
|
|
175045
|
+
mapping,
|
|
175046
|
+
resolved?.endpointId
|
|
175047
|
+
) : await LegacyEndpoint.create(
|
|
174386
175048
|
this.registry,
|
|
174387
175049
|
entityId,
|
|
174388
175050
|
mapping,
|
|
174389
175051
|
void 0,
|
|
174390
|
-
true
|
|
175052
|
+
true,
|
|
175053
|
+
resolved?.endpointId,
|
|
175054
|
+
resolved?.anchorEntityId
|
|
174391
175055
|
);
|
|
174392
175056
|
if (!endpoint) {
|
|
174393
175057
|
this._failedEntities.push({
|
|
@@ -174455,8 +175119,13 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
174455
175119
|
* This makes the vacuum appear as a standalone Matter device, which is required
|
|
174456
175120
|
* for Apple Home Siri voice commands and Alexa discovery.
|
|
174457
175121
|
*/
|
|
174458
|
-
async createServerModeVacuumEndpoint(entityId, mapping) {
|
|
174459
|
-
return ServerModeVacuumEndpoint.create(
|
|
175122
|
+
async createServerModeVacuumEndpoint(entityId, mapping, endpointId) {
|
|
175123
|
+
return ServerModeVacuumEndpoint.create(
|
|
175124
|
+
this.registry,
|
|
175125
|
+
entityId,
|
|
175126
|
+
mapping,
|
|
175127
|
+
endpointId
|
|
175128
|
+
);
|
|
174460
175129
|
}
|
|
174461
175130
|
};
|
|
174462
175131
|
|
|
@@ -174540,6 +175209,7 @@ var BridgeEnvironment = class _BridgeEnvironment extends EnvironmentBase {
|
|
|
174540
175209
|
await this.load(HomeAssistantClient),
|
|
174541
175210
|
this.get(BridgeRegistry),
|
|
174542
175211
|
await this.load(EntityMappingStorage),
|
|
175212
|
+
await this.load(EntityIdentityStorage),
|
|
174543
175213
|
bridgeId,
|
|
174544
175214
|
this.endpointManagerLogger,
|
|
174545
175215
|
pluginManager,
|
|
@@ -174625,6 +175295,7 @@ var BridgeEnvironmentFactory = class extends BridgeFactory {
|
|
|
174625
175295
|
await env.load(HomeAssistantClient),
|
|
174626
175296
|
env.get(BridgeRegistry),
|
|
174627
175297
|
await env.load(EntityMappingStorage),
|
|
175298
|
+
await env.load(EntityIdentityStorage),
|
|
174628
175299
|
dataProvider,
|
|
174629
175300
|
loggerService.get("ServerModeEndpointManager")
|
|
174630
175301
|
);
|
|
@@ -174676,6 +175347,10 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
174676
175347
|
EntityMappingStorage,
|
|
174677
175348
|
new EntityMappingStorage(await this.load(AppStorage))
|
|
174678
175349
|
);
|
|
175350
|
+
this.set(
|
|
175351
|
+
EntityIdentityStorage,
|
|
175352
|
+
new EntityIdentityStorage(await this.load(AppStorage))
|
|
175353
|
+
);
|
|
174679
175354
|
this.set(
|
|
174680
175355
|
LockCredentialStorage,
|
|
174681
175356
|
new LockCredentialStorage(await this.load(AppStorage))
|
|
@@ -174736,6 +175411,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
174736
175411
|
await this.load(HomeAssistantRegistry),
|
|
174737
175412
|
await this.load(BridgeStorage),
|
|
174738
175413
|
await this.load(EntityMappingStorage),
|
|
175414
|
+
await this.load(EntityIdentityStorage),
|
|
174739
175415
|
await this.load(LockCredentialStorage),
|
|
174740
175416
|
await this.load(AppSettingsStorage),
|
|
174741
175417
|
await this.load(BackupService),
|