@riddix/hamh 2.0.35 → 2.0.36
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/README.md +27 -19
- package/dist/backend/cli.js +902 -399
- package/dist/backend/cli.js.map +4 -4
- package/dist/frontend/assets/index-Ch5MWPnH.js +499 -0
- package/dist/frontend/index.html +1 -1
- package/package.json +4 -4
- package/dist/frontend/assets/index-CpNOwL9y.js +0 -499
package/dist/backend/cli.js
CHANGED
|
@@ -1743,8 +1743,8 @@ var init_Cancelable = __esm({
|
|
|
1743
1743
|
};
|
|
1744
1744
|
return result;
|
|
1745
1745
|
}
|
|
1746
|
-
static set logger(
|
|
1747
|
-
this.#logger =
|
|
1746
|
+
static set logger(logger204) {
|
|
1747
|
+
this.#logger = logger204;
|
|
1748
1748
|
}
|
|
1749
1749
|
static get logger() {
|
|
1750
1750
|
return this.#logger;
|
|
@@ -3422,13 +3422,13 @@ var init_Logger = __esm({
|
|
|
3422
3422
|
*
|
|
3423
3423
|
* @deprecated use {@link destinations}
|
|
3424
3424
|
*/
|
|
3425
|
-
static addLogger(identifier,
|
|
3425
|
+
static addLogger(identifier, logger204, options) {
|
|
3426
3426
|
if (identifier in this.destinations) {
|
|
3427
3427
|
throw new ImplementationError(`Logger "${identifier}" already exists`);
|
|
3428
3428
|
}
|
|
3429
3429
|
const dest = LogDestination({ name: identifier });
|
|
3430
3430
|
const legacy = adaptDestinationToLegacy(dest);
|
|
3431
|
-
legacy.log =
|
|
3431
|
+
legacy.log = logger204;
|
|
3432
3432
|
if (options?.defaultLogLevel !== void 0) {
|
|
3433
3433
|
legacy.defaultLogLevel = options.defaultLogLevel;
|
|
3434
3434
|
}
|
|
@@ -5538,8 +5538,8 @@ function Construction(subject, initializer) {
|
|
|
5538
5538
|
}
|
|
5539
5539
|
}
|
|
5540
5540
|
function unhandledError(...args) {
|
|
5541
|
-
const
|
|
5542
|
-
|
|
5541
|
+
const logger204 = Logger.get(subject.constructor.name);
|
|
5542
|
+
logger204.error(...args);
|
|
5543
5543
|
}
|
|
5544
5544
|
function createErrorHandler(name) {
|
|
5545
5545
|
return (e) => {
|
|
@@ -135998,11 +135998,11 @@ var init_Api = __esm({
|
|
|
135998
135998
|
}
|
|
135999
135999
|
Api2.resourceFor = resourceFor;
|
|
136000
136000
|
function log(level, facility, id, ...message) {
|
|
136001
|
-
let
|
|
136002
|
-
if (!
|
|
136003
|
-
loggers.set(facility,
|
|
136001
|
+
let logger204 = loggers.get(facility);
|
|
136002
|
+
if (!logger204) {
|
|
136003
|
+
loggers.set(facility, logger204 = Logger.get(facility));
|
|
136004
136004
|
}
|
|
136005
|
-
|
|
136005
|
+
logger204[level](Diagnostic.via(id || "(anon)"), message);
|
|
136006
136006
|
}
|
|
136007
136007
|
Api2.log = log;
|
|
136008
136008
|
function logRequest(facility, id, method, target) {
|
|
@@ -147221,10 +147221,10 @@ var init_home_assistant_actions = __esm({
|
|
|
147221
147221
|
circuitBreakerResetMs: 3e4
|
|
147222
147222
|
};
|
|
147223
147223
|
HomeAssistantActions = class extends Service {
|
|
147224
|
-
constructor(
|
|
147224
|
+
constructor(logger204, client, config10) {
|
|
147225
147225
|
super("HomeAssistantActions");
|
|
147226
147226
|
this.client = client;
|
|
147227
|
-
this.log =
|
|
147227
|
+
this.log = logger204.get(this);
|
|
147228
147228
|
this.config = { ...defaultConfig, ...config10 };
|
|
147229
147229
|
this.circuitBreaker = new CircuitBreaker(
|
|
147230
147230
|
this.config.circuitBreakerThreshold,
|
|
@@ -147567,7 +147567,7 @@ var DiagnosticService = class {
|
|
|
147567
147567
|
}
|
|
147568
147568
|
}
|
|
147569
147569
|
}
|
|
147570
|
-
const entities = this.collectEntities(bridge.aggregator);
|
|
147570
|
+
const entities = bridge.aggregator ? this.collectEntities(bridge.aggregator) : [];
|
|
147571
147571
|
return {
|
|
147572
147572
|
bridgeId: data.id,
|
|
147573
147573
|
bridgeName: data.name,
|
|
@@ -147596,10 +147596,10 @@ var DiagnosticService = class {
|
|
|
147596
147596
|
};
|
|
147597
147597
|
|
|
147598
147598
|
// src/api/access-log.ts
|
|
147599
|
-
function accessLogger(
|
|
147599
|
+
function accessLogger(logger204) {
|
|
147600
147600
|
return (req, res, next) => {
|
|
147601
147601
|
res.on("finish", () => {
|
|
147602
|
-
|
|
147602
|
+
logger204.debug(
|
|
147603
147603
|
`${req.method} ${decodeURI(req.originalUrl)} ${res.statusCode} ${res.statusMessage} from ${req.socket.remoteAddress}`
|
|
147604
147604
|
);
|
|
147605
147605
|
});
|
|
@@ -147766,6 +147766,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
147766
147766
|
disabled: config10.disabled,
|
|
147767
147767
|
filterLifeEntity: config10.filterLifeEntity,
|
|
147768
147768
|
cleaningModeEntity: config10.cleaningModeEntity,
|
|
147769
|
+
temperatureEntity: config10.temperatureEntity,
|
|
147769
147770
|
humidityEntity: config10.humidityEntity,
|
|
147770
147771
|
pressureEntity: config10.pressureEntity,
|
|
147771
147772
|
batteryEntity: config10.batteryEntity,
|
|
@@ -147775,7 +147776,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
147775
147776
|
energyEntity: config10.energyEntity,
|
|
147776
147777
|
suctionLevelEntity: config10.suctionLevelEntity,
|
|
147777
147778
|
mopIntensityEntity: config10.mopIntensityEntity,
|
|
147778
|
-
valetudoIdentifier: config10.valetudoIdentifier
|
|
147779
|
+
valetudoIdentifier: config10.valetudoIdentifier,
|
|
147780
|
+
coverSwapOpenClose: config10.coverSwapOpenClose
|
|
147779
147781
|
});
|
|
147780
147782
|
mappingsRestored++;
|
|
147781
147783
|
}
|
|
@@ -148514,6 +148516,15 @@ function logsApi(_logger) {
|
|
|
148514
148516
|
}
|
|
148515
148517
|
|
|
148516
148518
|
// src/api/diagnostic-api.ts
|
|
148519
|
+
function endpointTreeNode(ep) {
|
|
148520
|
+
return {
|
|
148521
|
+
id: ep.id,
|
|
148522
|
+
endpoint: ep.number,
|
|
148523
|
+
deviceType: `0x${ep.type.deviceType.toString(16).padStart(4, "0")}`,
|
|
148524
|
+
deviceTypeName: ep.type.name,
|
|
148525
|
+
parts: [...ep.parts].map((p) => endpointTreeNode(p))
|
|
148526
|
+
};
|
|
148527
|
+
}
|
|
148517
148528
|
function detectEnvironment() {
|
|
148518
148529
|
if (process.env.SUPERVISOR_TOKEN || process.env.HASSIO_TOKEN) {
|
|
148519
148530
|
return "Home Assistant Add-on";
|
|
@@ -148588,7 +148599,14 @@ function diagnosticApi(bridgeService, haClient, haRegistry, version, startTime)
|
|
|
148588
148599
|
failedEntities: failedEntities.map((fe) => ({
|
|
148589
148600
|
entityId: anonymize ? anonymizeEntityId(fe.entityId) : fe.entityId,
|
|
148590
148601
|
reason: fe.reason
|
|
148591
|
-
}))
|
|
148602
|
+
})),
|
|
148603
|
+
endpointTree: (() => {
|
|
148604
|
+
try {
|
|
148605
|
+
return endpointTreeNode(b.server);
|
|
148606
|
+
} catch {
|
|
148607
|
+
return void 0;
|
|
148608
|
+
}
|
|
148609
|
+
})()
|
|
148592
148610
|
};
|
|
148593
148611
|
});
|
|
148594
148612
|
const recentLogs = logBuffer.entries.slice(-logLimit).map((entry) => ({
|
|
@@ -148660,6 +148678,7 @@ function entityMappingApi(mappingStorage) {
|
|
|
148660
148678
|
disabled: body.disabled,
|
|
148661
148679
|
filterLifeEntity: body.filterLifeEntity,
|
|
148662
148680
|
cleaningModeEntity: body.cleaningModeEntity,
|
|
148681
|
+
temperatureEntity: body.temperatureEntity,
|
|
148663
148682
|
humidityEntity: body.humidityEntity,
|
|
148664
148683
|
pressureEntity: body.pressureEntity,
|
|
148665
148684
|
batteryEntity: body.batteryEntity,
|
|
@@ -148671,7 +148690,9 @@ function entityMappingApi(mappingStorage) {
|
|
|
148671
148690
|
mopIntensityEntity: body.mopIntensityEntity,
|
|
148672
148691
|
customServiceAreas: body.customServiceAreas,
|
|
148673
148692
|
customFanSpeedTags: body.customFanSpeedTags,
|
|
148674
|
-
valetudoIdentifier: body.valetudoIdentifier
|
|
148693
|
+
valetudoIdentifier: body.valetudoIdentifier,
|
|
148694
|
+
coverSwapOpenClose: body.coverSwapOpenClose,
|
|
148695
|
+
composedEntities: body.composedEntities
|
|
148675
148696
|
};
|
|
148676
148697
|
const config10 = await mappingStorage.setMapping(request);
|
|
148677
148698
|
res.status(200).json(config10);
|
|
@@ -149121,6 +149142,7 @@ function configToProfileEntry(config10) {
|
|
|
149121
149142
|
disabled: config10.disabled,
|
|
149122
149143
|
filterLifeEntity: config10.filterLifeEntity,
|
|
149123
149144
|
cleaningModeEntity: config10.cleaningModeEntity,
|
|
149145
|
+
temperatureEntity: config10.temperatureEntity,
|
|
149124
149146
|
humidityEntity: config10.humidityEntity,
|
|
149125
149147
|
pressureEntity: config10.pressureEntity,
|
|
149126
149148
|
batteryEntity: config10.batteryEntity,
|
|
@@ -149132,7 +149154,8 @@ function configToProfileEntry(config10) {
|
|
|
149132
149154
|
mopIntensityEntity: config10.mopIntensityEntity,
|
|
149133
149155
|
customServiceAreas: config10.customServiceAreas,
|
|
149134
149156
|
customFanSpeedTags: config10.customFanSpeedTags,
|
|
149135
|
-
valetudoIdentifier: config10.valetudoIdentifier
|
|
149157
|
+
valetudoIdentifier: config10.valetudoIdentifier,
|
|
149158
|
+
coverSwapOpenClose: config10.coverSwapOpenClose
|
|
149136
149159
|
};
|
|
149137
149160
|
}
|
|
149138
149161
|
function mappingProfileApi(mappingStorage) {
|
|
@@ -149240,6 +149263,7 @@ function mappingProfileApi(mappingStorage) {
|
|
|
149240
149263
|
disabled: entry.disabled,
|
|
149241
149264
|
filterLifeEntity: entry.filterLifeEntity,
|
|
149242
149265
|
cleaningModeEntity: entry.cleaningModeEntity,
|
|
149266
|
+
temperatureEntity: entry.temperatureEntity,
|
|
149243
149267
|
humidityEntity: entry.humidityEntity,
|
|
149244
149268
|
pressureEntity: entry.pressureEntity,
|
|
149245
149269
|
batteryEntity: entry.batteryEntity,
|
|
@@ -149251,7 +149275,8 @@ function mappingProfileApi(mappingStorage) {
|
|
|
149251
149275
|
mopIntensityEntity: entry.mopIntensityEntity,
|
|
149252
149276
|
customServiceAreas: entry.customServiceAreas,
|
|
149253
149277
|
customFanSpeedTags: entry.customFanSpeedTags,
|
|
149254
|
-
valetudoIdentifier: entry.valetudoIdentifier
|
|
149278
|
+
valetudoIdentifier: entry.valetudoIdentifier,
|
|
149279
|
+
coverSwapOpenClose: entry.coverSwapOpenClose
|
|
149255
149280
|
});
|
|
149256
149281
|
applied++;
|
|
149257
149282
|
} catch (e) {
|
|
@@ -151087,7 +151112,7 @@ var WebSocketApi = class {
|
|
|
151087
151112
|
|
|
151088
151113
|
// src/api/web-api.ts
|
|
151089
151114
|
var WebApi = class extends Service {
|
|
151090
|
-
constructor(
|
|
151115
|
+
constructor(logger204, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, lockCredentialStorage, settingsStorage, backupService, props) {
|
|
151091
151116
|
super("WebApi");
|
|
151092
151117
|
this.bridgeService = bridgeService;
|
|
151093
151118
|
this.haClient = haClient;
|
|
@@ -151098,8 +151123,8 @@ var WebApi = class extends Service {
|
|
|
151098
151123
|
this.settingsStorage = settingsStorage;
|
|
151099
151124
|
this.backupService = backupService;
|
|
151100
151125
|
this.props = props;
|
|
151101
|
-
this.logger =
|
|
151102
|
-
this.log =
|
|
151126
|
+
this.logger = logger204;
|
|
151127
|
+
this.log = logger204.get(this);
|
|
151103
151128
|
this.accessLogger = accessLogger(this.log.createChild("Access Log"));
|
|
151104
151129
|
this.startTime = Date.now();
|
|
151105
151130
|
this.wsApi = new WebSocketApi(
|
|
@@ -151537,12 +151562,12 @@ var CustomStorage = class extends StorageBackendDisk {
|
|
|
151537
151562
|
|
|
151538
151563
|
// src/core/app/storage.ts
|
|
151539
151564
|
function storage(environment, options) {
|
|
151540
|
-
const
|
|
151565
|
+
const logger204 = environment.get(LoggerService).get("CustomStorage");
|
|
151541
151566
|
const location2 = resolveStorageLocation(options.location);
|
|
151542
151567
|
fs8.mkdirSync(location2, { recursive: true });
|
|
151543
151568
|
const storageService = environment.get(StorageService);
|
|
151544
151569
|
storageService.location = location2;
|
|
151545
|
-
storageService.factory = (ns) => new CustomStorage(
|
|
151570
|
+
storageService.factory = (ns) => new CustomStorage(logger204, path8.resolve(location2, ns));
|
|
151546
151571
|
}
|
|
151547
151572
|
function resolveStorageLocation(storageLocation) {
|
|
151548
151573
|
const homedir = os3.homedir();
|
|
@@ -151568,17 +151593,17 @@ import { createRequire } from "node:module";
|
|
|
151568
151593
|
import os4 from "node:os";
|
|
151569
151594
|
import path9 from "node:path";
|
|
151570
151595
|
function resolveAppVersion() {
|
|
151571
|
-
if (process.env.APP_VERSION) {
|
|
151572
|
-
return process.env.APP_VERSION;
|
|
151573
|
-
}
|
|
151574
151596
|
try {
|
|
151575
151597
|
const require2 = createRequire(import.meta.url);
|
|
151576
151598
|
const pkg = require2("home-assistant-matter-hub/package.json");
|
|
151577
|
-
if (pkg.version) {
|
|
151599
|
+
if (pkg.version && pkg.version !== "0.0.0") {
|
|
151578
151600
|
return pkg.version;
|
|
151579
151601
|
}
|
|
151580
151602
|
} catch {
|
|
151581
151603
|
}
|
|
151604
|
+
if (process.env.APP_VERSION) {
|
|
151605
|
+
return process.env.APP_VERSION;
|
|
151606
|
+
}
|
|
151582
151607
|
return "0.0.0-dev";
|
|
151583
151608
|
}
|
|
151584
151609
|
var Options = class {
|
|
@@ -152092,10 +152117,10 @@ import {
|
|
|
152092
152117
|
getConfig
|
|
152093
152118
|
} from "home-assistant-js-websocket";
|
|
152094
152119
|
var HomeAssistantClient = class extends Service {
|
|
152095
|
-
constructor(
|
|
152120
|
+
constructor(logger204, options) {
|
|
152096
152121
|
super("HomeAssistantClient");
|
|
152097
152122
|
this.options = options;
|
|
152098
|
-
this.log =
|
|
152123
|
+
this.log = logger204.get(this);
|
|
152099
152124
|
}
|
|
152100
152125
|
static Options = /* @__PURE__ */ Symbol.for("HomeAssistantClientProps");
|
|
152101
152126
|
_connection;
|
|
@@ -152673,6 +152698,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
152673
152698
|
disabled: request.disabled,
|
|
152674
152699
|
filterLifeEntity: request.filterLifeEntity?.trim() || void 0,
|
|
152675
152700
|
cleaningModeEntity: request.cleaningModeEntity?.trim() || void 0,
|
|
152701
|
+
temperatureEntity: request.temperatureEntity?.trim() || void 0,
|
|
152676
152702
|
humidityEntity: request.humidityEntity?.trim() || void 0,
|
|
152677
152703
|
batteryEntity: request.batteryEntity?.trim() || void 0,
|
|
152678
152704
|
roomEntities: roomEntities.length > 0 ? roomEntities : void 0,
|
|
@@ -152686,9 +152712,11 @@ var EntityMappingStorage = class extends Service {
|
|
|
152686
152712
|
(a) => a.name?.trim() && a.service?.trim()
|
|
152687
152713
|
) ?? void 0,
|
|
152688
152714
|
customFanSpeedTags: request.customFanSpeedTags && Object.keys(request.customFanSpeedTags).length > 0 ? request.customFanSpeedTags : void 0,
|
|
152689
|
-
valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0
|
|
152715
|
+
valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0,
|
|
152716
|
+
coverSwapOpenClose: request.coverSwapOpenClose || void 0,
|
|
152717
|
+
composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
|
|
152690
152718
|
};
|
|
152691
|
-
if (!config10.matterDeviceType && !config10.customName && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0) && !config10.valetudoIdentifier) {
|
|
152719
|
+
if (!config10.matterDeviceType && !config10.customName && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.temperatureEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0) && !config10.valetudoIdentifier && !config10.coverSwapOpenClose && (!config10.composedEntities || config10.composedEntities.length === 0)) {
|
|
152692
152720
|
bridgeMap.delete(request.entityId);
|
|
152693
152721
|
} else {
|
|
152694
152722
|
bridgeMap.set(request.entityId, config10);
|
|
@@ -166255,6 +166283,7 @@ function validatePluginDevice(device) {
|
|
|
166255
166283
|
}
|
|
166256
166284
|
var PluginManager = class {
|
|
166257
166285
|
instances = /* @__PURE__ */ new Map();
|
|
166286
|
+
domainMappings = /* @__PURE__ */ new Map();
|
|
166258
166287
|
storageDir;
|
|
166259
166288
|
bridgeId;
|
|
166260
166289
|
runner = new SafePluginRunner();
|
|
@@ -166386,6 +166415,21 @@ var PluginManager = class {
|
|
|
166386
166415
|
clusterId3,
|
|
166387
166416
|
attributes7
|
|
166388
166417
|
);
|
|
166418
|
+
},
|
|
166419
|
+
registerDomainMapping: (mapping) => {
|
|
166420
|
+
if (!mapping.domain || typeof mapping.domain !== "string" || !mapping.matterDeviceType || typeof mapping.matterDeviceType !== "string") {
|
|
166421
|
+
pluginLogger.warn("Invalid domain mapping, skipping");
|
|
166422
|
+
return;
|
|
166423
|
+
}
|
|
166424
|
+
if (this.domainMappings.has(mapping.domain)) {
|
|
166425
|
+
pluginLogger.warn(
|
|
166426
|
+
`Domain "${mapping.domain}" already mapped by another plugin, overwriting`
|
|
166427
|
+
);
|
|
166428
|
+
}
|
|
166429
|
+
this.domainMappings.set(mapping.domain, mapping);
|
|
166430
|
+
pluginLogger.info(
|
|
166431
|
+
`Registered domain mapping: ${mapping.domain} \u2192 ${mapping.matterDeviceType}`
|
|
166432
|
+
);
|
|
166389
166433
|
}
|
|
166390
166434
|
};
|
|
166391
166435
|
this.instances.set(plugin.name, {
|
|
@@ -166511,6 +166555,9 @@ var PluginManager = class {
|
|
|
166511
166555
|
if (!instance) return void 0;
|
|
166512
166556
|
return instance.plugin.getConfigSchema?.();
|
|
166513
166557
|
}
|
|
166558
|
+
getDomainMappings() {
|
|
166559
|
+
return new Map(this.domainMappings);
|
|
166560
|
+
}
|
|
166514
166561
|
async updateConfig(pluginName, config10) {
|
|
166515
166562
|
const instance = this.instances.get(pluginName);
|
|
166516
166563
|
if (!instance) return false;
|
|
@@ -166856,11 +166903,12 @@ function ensureCommissioningConfig(server) {
|
|
|
166856
166903
|
|
|
166857
166904
|
// src/services/bridges/bridge.ts
|
|
166858
166905
|
var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
|
|
166906
|
+
var DEAD_SESSION_TIMEOUT_MS = 6e4;
|
|
166859
166907
|
var Bridge = class {
|
|
166860
|
-
constructor(env,
|
|
166908
|
+
constructor(env, logger204, dataProvider, endpointManager) {
|
|
166861
166909
|
this.dataProvider = dataProvider;
|
|
166862
166910
|
this.endpointManager = endpointManager;
|
|
166863
|
-
this.log =
|
|
166911
|
+
this.log = logger204.get(`Bridge / ${dataProvider.id}`);
|
|
166864
166912
|
this.server = new BridgeServerNode(
|
|
166865
166913
|
env,
|
|
166866
166914
|
this.dataProvider,
|
|
@@ -166878,6 +166926,8 @@ var Bridge = class {
|
|
|
166878
166926
|
// (e.g. Stopped → Starting → Running).
|
|
166879
166927
|
onStatusChange;
|
|
166880
166928
|
autoForceSyncTimer = null;
|
|
166929
|
+
deadSessionTimer = null;
|
|
166930
|
+
staleSessionTimers = /* @__PURE__ */ new Map();
|
|
166881
166931
|
// Tracks the last synced state JSON per entity to avoid pushing unchanged states.
|
|
166882
166932
|
// Key: entity_id, Value: JSON.stringify of entity.state
|
|
166883
166933
|
lastSyncedStates = /* @__PURE__ */ new Map();
|
|
@@ -167054,6 +167104,33 @@ ${e?.toString()}`);
|
|
|
167054
167104
|
this.log.warn(
|
|
167055
167105
|
`All subscriptions lost \u2014 ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
|
|
167056
167106
|
);
|
|
167107
|
+
if (!this.deadSessionTimer) {
|
|
167108
|
+
this.deadSessionTimer = setTimeout(() => {
|
|
167109
|
+
this.deadSessionTimer = null;
|
|
167110
|
+
this.closeDeadSessions();
|
|
167111
|
+
}, DEAD_SESSION_TIMEOUT_MS);
|
|
167112
|
+
this.log.info(
|
|
167113
|
+
`Scheduled dead session cleanup in ${DEAD_SESSION_TIMEOUT_MS / 1e3}s`
|
|
167114
|
+
);
|
|
167115
|
+
}
|
|
167116
|
+
} else if (totalSubs > 0 && this.deadSessionTimer) {
|
|
167117
|
+
clearTimeout(this.deadSessionTimer);
|
|
167118
|
+
this.deadSessionTimer = null;
|
|
167119
|
+
this.log.info(
|
|
167120
|
+
"Subscriptions recovered, canceled dead session cleanup"
|
|
167121
|
+
);
|
|
167122
|
+
}
|
|
167123
|
+
if (session.subscriptions.size === 0 && !this.staleSessionTimers.has(session.id)) {
|
|
167124
|
+
this.staleSessionTimers.set(
|
|
167125
|
+
session.id,
|
|
167126
|
+
setTimeout(() => {
|
|
167127
|
+
this.staleSessionTimers.delete(session.id);
|
|
167128
|
+
this.closeStaleSession(session.id);
|
|
167129
|
+
}, DEAD_SESSION_TIMEOUT_MS)
|
|
167130
|
+
);
|
|
167131
|
+
} else if (session.subscriptions.size > 0 && this.staleSessionTimers.has(session.id)) {
|
|
167132
|
+
clearTimeout(this.staleSessionTimers.get(session.id));
|
|
167133
|
+
this.staleSessionTimers.delete(session.id);
|
|
167057
167134
|
}
|
|
167058
167135
|
};
|
|
167059
167136
|
sessionManager.subscriptionsChanged.on(this.sessionDiagHandler);
|
|
@@ -167082,6 +167159,62 @@ ${e?.toString()}`);
|
|
|
167082
167159
|
} catch {
|
|
167083
167160
|
}
|
|
167084
167161
|
}
|
|
167162
|
+
closeStaleSession(sessionId) {
|
|
167163
|
+
try {
|
|
167164
|
+
const sessionManager = this.server.env.get(SessionManager);
|
|
167165
|
+
for (const s of [...sessionManager.sessions]) {
|
|
167166
|
+
if (s.id === sessionId && !s.isClosing && s.subscriptions.size === 0) {
|
|
167167
|
+
this.log.warn(
|
|
167168
|
+
`Closing stale session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS / 1e3}s)`
|
|
167169
|
+
);
|
|
167170
|
+
s.initiateClose().catch(() => {
|
|
167171
|
+
return s.initiateForceClose();
|
|
167172
|
+
}).catch(() => {
|
|
167173
|
+
}).finally(() => this.triggerMdnsReAnnounce());
|
|
167174
|
+
break;
|
|
167175
|
+
}
|
|
167176
|
+
}
|
|
167177
|
+
} catch {
|
|
167178
|
+
}
|
|
167179
|
+
}
|
|
167180
|
+
closeDeadSessions() {
|
|
167181
|
+
try {
|
|
167182
|
+
const sessionManager = this.server.env.get(SessionManager);
|
|
167183
|
+
const sessions = [...sessionManager.sessions];
|
|
167184
|
+
const closes = [];
|
|
167185
|
+
for (const s of sessions) {
|
|
167186
|
+
if (!s.isClosing && s.subscriptions.size === 0) {
|
|
167187
|
+
this.log.warn(
|
|
167188
|
+
`Closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS / 1e3}s)`
|
|
167189
|
+
);
|
|
167190
|
+
closes.push(
|
|
167191
|
+
s.initiateClose().catch(() => {
|
|
167192
|
+
return s.initiateForceClose();
|
|
167193
|
+
})
|
|
167194
|
+
);
|
|
167195
|
+
}
|
|
167196
|
+
}
|
|
167197
|
+
if (closes.length > 0) {
|
|
167198
|
+
Promise.allSettled(closes).then(() => this.triggerMdnsReAnnounce());
|
|
167199
|
+
}
|
|
167200
|
+
} catch {
|
|
167201
|
+
}
|
|
167202
|
+
}
|
|
167203
|
+
/**
|
|
167204
|
+
* Force a fresh mDNS operational advertisement after session cleanup.
|
|
167205
|
+
* matter.js DeviceAdvertiser only re-announces when a subscription is
|
|
167206
|
+
* canceled BY THE PEER. When the server cancels after 3 delivery
|
|
167207
|
+
* timeouts, no re-announcement happens and the controller may not
|
|
167208
|
+
* realize it should reconnect (#266).
|
|
167209
|
+
*/
|
|
167210
|
+
triggerMdnsReAnnounce() {
|
|
167211
|
+
try {
|
|
167212
|
+
const advertiser = this.server.env.get(DeviceAdvertiser);
|
|
167213
|
+
advertiser.restartAdvertisement();
|
|
167214
|
+
this.log.info("Triggered mDNS re-announcement after session cleanup");
|
|
167215
|
+
} catch {
|
|
167216
|
+
}
|
|
167217
|
+
}
|
|
167085
167218
|
unwireSessionDiagnostics() {
|
|
167086
167219
|
try {
|
|
167087
167220
|
const sessionManager = this.server.env.get(SessionManager);
|
|
@@ -167099,6 +167232,14 @@ ${e?.toString()}`);
|
|
|
167099
167232
|
this.sessionDiagHandler = void 0;
|
|
167100
167233
|
this.sessionAddedHandler = void 0;
|
|
167101
167234
|
this.sessionDeletedHandler = void 0;
|
|
167235
|
+
if (this.deadSessionTimer) {
|
|
167236
|
+
clearTimeout(this.deadSessionTimer);
|
|
167237
|
+
this.deadSessionTimer = null;
|
|
167238
|
+
}
|
|
167239
|
+
for (const timer of this.staleSessionTimers.values()) {
|
|
167240
|
+
clearTimeout(timer);
|
|
167241
|
+
}
|
|
167242
|
+
this.staleSessionTimers.clear();
|
|
167102
167243
|
}
|
|
167103
167244
|
stopAutoForceSync() {
|
|
167104
167245
|
if (this.autoForceSyncTimer) {
|
|
@@ -167232,7 +167373,7 @@ var AggregatorEndpoint2 = class extends Endpoint {
|
|
|
167232
167373
|
init_dist();
|
|
167233
167374
|
init_esm();
|
|
167234
167375
|
init_home_assistant_entity_behavior();
|
|
167235
|
-
import
|
|
167376
|
+
import debounce5 from "debounce";
|
|
167236
167377
|
|
|
167237
167378
|
// src/matter/endpoints/entity-endpoint.ts
|
|
167238
167379
|
init_esm7();
|
|
@@ -167266,6 +167407,7 @@ function getMappedEntityIds(mapping) {
|
|
|
167266
167407
|
if (!mapping) return [];
|
|
167267
167408
|
const ids = [];
|
|
167268
167409
|
if (mapping.batteryEntity) ids.push(mapping.batteryEntity);
|
|
167410
|
+
if (mapping.temperatureEntity) ids.push(mapping.temperatureEntity);
|
|
167269
167411
|
if (mapping.humidityEntity) ids.push(mapping.humidityEntity);
|
|
167270
167412
|
if (mapping.pressureEntity) ids.push(mapping.pressureEntity);
|
|
167271
167413
|
if (mapping.cleaningModeEntity) ids.push(mapping.cleaningModeEntity);
|
|
@@ -167274,6 +167416,11 @@ function getMappedEntityIds(mapping) {
|
|
|
167274
167416
|
if (mapping.filterLifeEntity) ids.push(mapping.filterLifeEntity);
|
|
167275
167417
|
if (mapping.powerEntity) ids.push(mapping.powerEntity);
|
|
167276
167418
|
if (mapping.energyEntity) ids.push(mapping.energyEntity);
|
|
167419
|
+
if (mapping.composedEntities) {
|
|
167420
|
+
for (const sub of mapping.composedEntities) {
|
|
167421
|
+
if (sub.entityId) ids.push(sub.entityId);
|
|
167422
|
+
}
|
|
167423
|
+
}
|
|
167277
167424
|
return ids;
|
|
167278
167425
|
}
|
|
167279
167426
|
|
|
@@ -167610,6 +167757,26 @@ function PowerSourceServer2(config10) {
|
|
|
167610
167757
|
order: PowerSource3.Cluster.id
|
|
167611
167758
|
});
|
|
167612
167759
|
}
|
|
167760
|
+
var defaultBatteryConfig = {
|
|
167761
|
+
getBatteryPercent: (entity, agent) => {
|
|
167762
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
167763
|
+
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
167764
|
+
if (batteryEntity) {
|
|
167765
|
+
const stateProvider = agent.env.get(EntityStateProvider);
|
|
167766
|
+
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
167767
|
+
if (battery != null) {
|
|
167768
|
+
return Math.max(0, Math.min(100, battery));
|
|
167769
|
+
}
|
|
167770
|
+
}
|
|
167771
|
+
const attrs = entity.attributes;
|
|
167772
|
+
const level = attrs.battery_level ?? attrs.battery;
|
|
167773
|
+
if (level == null || Number.isNaN(Number(level))) {
|
|
167774
|
+
return null;
|
|
167775
|
+
}
|
|
167776
|
+
return Number(level);
|
|
167777
|
+
}
|
|
167778
|
+
};
|
|
167779
|
+
var DefaultPowerSourceServer = PowerSourceServer2(defaultBatteryConfig);
|
|
167613
167780
|
|
|
167614
167781
|
// src/matter/behaviors/temperature-measurement-server.ts
|
|
167615
167782
|
init_home_assistant_entity_behavior();
|
|
@@ -168028,12 +168195,13 @@ var OnOffServerBase = class extends OnOffServer {
|
|
|
168028
168195
|
return;
|
|
168029
168196
|
}
|
|
168030
168197
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
168031
|
-
const action = turnOn
|
|
168032
|
-
|
|
168033
|
-
|
|
168198
|
+
const action = turnOn ? turnOn(void 0, this.agent) : { action: "homeassistant.turn_on" };
|
|
168199
|
+
applyPatchState(this.state, { onOff: true });
|
|
168200
|
+
if (!action) {
|
|
168201
|
+
return;
|
|
168202
|
+
}
|
|
168034
168203
|
logger167.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
|
|
168035
168204
|
notifyLightTurnedOn(homeAssistant.entityId);
|
|
168036
|
-
applyPatchState(this.state, { onOff: true });
|
|
168037
168205
|
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
168038
168206
|
expectedOnOff: true,
|
|
168039
168207
|
timestamp: Date.now()
|
|
@@ -168050,11 +168218,12 @@ var OnOffServerBase = class extends OnOffServer {
|
|
|
168050
168218
|
return;
|
|
168051
168219
|
}
|
|
168052
168220
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
168053
|
-
const action = turnOff
|
|
168054
|
-
action: "homeassistant.turn_off"
|
|
168055
|
-
};
|
|
168056
|
-
logger167.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
|
|
168221
|
+
const action = turnOff ? turnOff(void 0, this.agent) : { action: "homeassistant.turn_off" };
|
|
168057
168222
|
applyPatchState(this.state, { onOff: false });
|
|
168223
|
+
if (!action) {
|
|
168224
|
+
return;
|
|
168225
|
+
}
|
|
168226
|
+
logger167.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
|
|
168058
168227
|
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
168059
168228
|
expectedOnOff: false,
|
|
168060
168229
|
timestamp: Date.now()
|
|
@@ -168532,35 +168701,25 @@ var FanOnOffServer = OnOffServer2({
|
|
|
168532
168701
|
|
|
168533
168702
|
// src/matter/endpoints/composed/composed-air-purifier-endpoint.ts
|
|
168534
168703
|
var logger169 = Logger.get("ComposedAirPurifierEndpoint");
|
|
168535
|
-
|
|
168536
|
-
|
|
168537
|
-
|
|
168538
|
-
|
|
168539
|
-
|
|
168540
|
-
|
|
168541
|
-
|
|
168542
|
-
|
|
168543
|
-
|
|
168544
|
-
|
|
168545
|
-
|
|
168546
|
-
|
|
168547
|
-
|
|
168548
|
-
|
|
168549
|
-
|
|
168550
|
-
|
|
168551
|
-
|
|
168552
|
-
|
|
168553
|
-
|
|
168554
|
-
getValue(_entity, agent) {
|
|
168555
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
168556
|
-
const humState = stateProvider.getState(humidityEntityId);
|
|
168557
|
-
if (!humState) return null;
|
|
168558
|
-
const humidity = Number.parseFloat(humState.state);
|
|
168559
|
-
if (Number.isNaN(humidity)) return null;
|
|
168560
|
-
return humidity;
|
|
168561
|
-
}
|
|
168562
|
-
};
|
|
168563
|
-
}
|
|
168704
|
+
var temperatureConfig = {
|
|
168705
|
+
getValue(entity, agent) {
|
|
168706
|
+
const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
|
|
168707
|
+
const state = entity.state;
|
|
168708
|
+
const attributes7 = entity.attributes;
|
|
168709
|
+
const temperature3 = state == null || Number.isNaN(+state) ? null : +state;
|
|
168710
|
+
if (temperature3 == null) return void 0;
|
|
168711
|
+
return Temperature.withUnit(
|
|
168712
|
+
temperature3,
|
|
168713
|
+
attributes7.unit_of_measurement ?? fallbackUnit
|
|
168714
|
+
);
|
|
168715
|
+
}
|
|
168716
|
+
};
|
|
168717
|
+
var humidityConfig = {
|
|
168718
|
+
getValue({ state }) {
|
|
168719
|
+
if (state == null || Number.isNaN(+state)) return null;
|
|
168720
|
+
return +state;
|
|
168721
|
+
}
|
|
168722
|
+
};
|
|
168564
168723
|
var batteryConfig = {
|
|
168565
168724
|
getBatteryPercent: (_entity, agent) => {
|
|
168566
168725
|
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
@@ -168573,6 +168732,16 @@ var batteryConfig = {
|
|
|
168573
168732
|
return null;
|
|
168574
168733
|
}
|
|
168575
168734
|
};
|
|
168735
|
+
var TemperatureSubType = TemperatureSensorDevice.with(
|
|
168736
|
+
IdentifyServer2,
|
|
168737
|
+
HomeAssistantEntityBehavior,
|
|
168738
|
+
TemperatureMeasurementServer2(temperatureConfig)
|
|
168739
|
+
);
|
|
168740
|
+
var HumiditySubType = HumiditySensorDevice.with(
|
|
168741
|
+
IdentifyServer2,
|
|
168742
|
+
HomeAssistantEntityBehavior,
|
|
168743
|
+
HumidityMeasurementServer(humidityConfig)
|
|
168744
|
+
);
|
|
168576
168745
|
function createEndpointId2(entityId, customName) {
|
|
168577
168746
|
const baseName = customName || entityId;
|
|
168578
168747
|
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
@@ -168592,9 +168761,9 @@ function buildEntityPayload(registry2, entityId) {
|
|
|
168592
168761
|
var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends Endpoint {
|
|
168593
168762
|
entityId;
|
|
168594
168763
|
mappedEntityIds;
|
|
168595
|
-
|
|
168764
|
+
subEndpoints = /* @__PURE__ */ new Map();
|
|
168596
168765
|
lastStates = /* @__PURE__ */ new Map();
|
|
168597
|
-
|
|
168766
|
+
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
168598
168767
|
static async create(config10) {
|
|
168599
168768
|
const { registry: registry2, primaryEntityId } = config10;
|
|
168600
168769
|
const primaryPayload = buildEntityPayload(registry2, primaryEntityId);
|
|
@@ -168622,8 +168791,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
168622
168791
|
if (hasWindModes) {
|
|
168623
168792
|
features2.add("Wind");
|
|
168624
168793
|
}
|
|
168625
|
-
let
|
|
168626
|
-
BasicInformationServer2,
|
|
168794
|
+
let airPurifierSubType = AirPurifierDevice.with(
|
|
168627
168795
|
IdentifyServer2,
|
|
168628
168796
|
HomeAssistantEntityBehavior,
|
|
168629
168797
|
FanOnOffServer,
|
|
@@ -168631,27 +168799,23 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
168631
168799
|
);
|
|
168632
168800
|
const hasFilterLife = airPurifierAttributes.filter_life != null || airPurifierAttributes.filter_life_remaining != null || airPurifierAttributes.filter_life_level != null || !!config10.mapping?.filterLifeEntity;
|
|
168633
168801
|
if (hasFilterLife) {
|
|
168634
|
-
|
|
168635
|
-
|
|
168636
|
-
if (config10.temperatureEntityId) {
|
|
168637
|
-
parentType = parentType.with(
|
|
168638
|
-
TemperatureMeasurementServer2(
|
|
168639
|
-
createTemperatureConfig(config10.temperatureEntityId)
|
|
168640
|
-
)
|
|
168641
|
-
);
|
|
168642
|
-
}
|
|
168643
|
-
if (config10.humidityEntityId) {
|
|
168644
|
-
parentType = parentType.with(
|
|
168645
|
-
HumidityMeasurementServer(
|
|
168646
|
-
createHumidityConfig(config10.humidityEntityId)
|
|
168647
|
-
)
|
|
168802
|
+
airPurifierSubType = airPurifierSubType.with(
|
|
168803
|
+
AirPurifierHepaFilterMonitoringServer
|
|
168648
168804
|
);
|
|
168649
168805
|
}
|
|
168650
|
-
const
|
|
168806
|
+
const airPurifierMapping = {
|
|
168651
168807
|
entityId: primaryEntityId,
|
|
168652
|
-
...config10.batteryEntityId ? { batteryEntity: config10.batteryEntityId } : {},
|
|
168653
168808
|
...config10.mapping?.filterLifeEntity ? { filterLifeEntity: config10.mapping.filterLifeEntity } : {}
|
|
168654
168809
|
};
|
|
168810
|
+
let parentType = BridgedNodeEndpoint.with(
|
|
168811
|
+
BasicInformationServer2,
|
|
168812
|
+
IdentifyServer2,
|
|
168813
|
+
HomeAssistantEntityBehavior
|
|
168814
|
+
);
|
|
168815
|
+
const parentMapping = {
|
|
168816
|
+
entityId: primaryEntityId,
|
|
168817
|
+
...config10.batteryEntityId ? { batteryEntity: config10.batteryEntityId } : {}
|
|
168818
|
+
};
|
|
168655
168819
|
if (config10.batteryEntityId) {
|
|
168656
168820
|
parentType = parentType.with(PowerSourceServer2(batteryConfig));
|
|
168657
168821
|
}
|
|
@@ -168664,75 +168828,125 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
168664
168828
|
);
|
|
168665
168829
|
}
|
|
168666
168830
|
const endpointId = createEndpointId2(primaryEntityId, config10.customName);
|
|
168831
|
+
const parts = [];
|
|
168832
|
+
const airPurifierSub = new Endpoint(
|
|
168833
|
+
airPurifierSubType.set({
|
|
168834
|
+
homeAssistantEntity: {
|
|
168835
|
+
entity: primaryPayload,
|
|
168836
|
+
mapping: airPurifierMapping
|
|
168837
|
+
}
|
|
168838
|
+
}),
|
|
168839
|
+
{ id: `${endpointId}_air_purifier` }
|
|
168840
|
+
);
|
|
168841
|
+
parts.push(airPurifierSub);
|
|
168842
|
+
let tempSub;
|
|
168843
|
+
if (config10.temperatureEntityId) {
|
|
168844
|
+
const tempPayload = buildEntityPayload(
|
|
168845
|
+
registry2,
|
|
168846
|
+
config10.temperatureEntityId
|
|
168847
|
+
);
|
|
168848
|
+
if (tempPayload) {
|
|
168849
|
+
tempSub = new Endpoint(
|
|
168850
|
+
TemperatureSubType.set({
|
|
168851
|
+
homeAssistantEntity: { entity: tempPayload }
|
|
168852
|
+
}),
|
|
168853
|
+
{ id: `${endpointId}_temp` }
|
|
168854
|
+
);
|
|
168855
|
+
parts.push(tempSub);
|
|
168856
|
+
}
|
|
168857
|
+
}
|
|
168858
|
+
let humSub;
|
|
168859
|
+
if (config10.humidityEntityId) {
|
|
168860
|
+
const humPayload = buildEntityPayload(registry2, config10.humidityEntityId);
|
|
168861
|
+
if (humPayload) {
|
|
168862
|
+
humSub = new Endpoint(
|
|
168863
|
+
HumiditySubType.set({
|
|
168864
|
+
homeAssistantEntity: { entity: humPayload }
|
|
168865
|
+
}),
|
|
168866
|
+
{ id: `${endpointId}_humidity` }
|
|
168867
|
+
);
|
|
168868
|
+
parts.push(humSub);
|
|
168869
|
+
}
|
|
168870
|
+
}
|
|
168667
168871
|
const parentTypeWithState = parentType.set({
|
|
168668
168872
|
homeAssistantEntity: {
|
|
168669
168873
|
entity: primaryPayload,
|
|
168670
168874
|
customName: config10.customName,
|
|
168671
|
-
mapping
|
|
168875
|
+
mapping: parentMapping
|
|
168672
168876
|
}
|
|
168673
168877
|
});
|
|
168674
|
-
const
|
|
168675
|
-
if (config10.temperatureEntityId)
|
|
168676
|
-
|
|
168677
|
-
if (config10.
|
|
168678
|
-
|
|
168878
|
+
const mappedIds = [];
|
|
168879
|
+
if (config10.temperatureEntityId) mappedIds.push(config10.temperatureEntityId);
|
|
168880
|
+
if (config10.humidityEntityId) mappedIds.push(config10.humidityEntityId);
|
|
168881
|
+
if (config10.mapping?.filterLifeEntity)
|
|
168882
|
+
mappedIds.push(config10.mapping.filterLifeEntity);
|
|
168679
168883
|
const endpoint = new _ComposedAirPurifierEndpoint(
|
|
168680
168884
|
parentTypeWithState,
|
|
168681
168885
|
primaryEntityId,
|
|
168682
168886
|
endpointId,
|
|
168683
|
-
|
|
168887
|
+
parts,
|
|
168684
168888
|
mappedIds
|
|
168685
168889
|
);
|
|
168890
|
+
endpoint.subEndpoints.set(primaryEntityId, airPurifierSub);
|
|
168891
|
+
if (config10.temperatureEntityId && tempSub) {
|
|
168892
|
+
endpoint.subEndpoints.set(config10.temperatureEntityId, tempSub);
|
|
168893
|
+
}
|
|
168894
|
+
if (config10.humidityEntityId && humSub) {
|
|
168895
|
+
endpoint.subEndpoints.set(config10.humidityEntityId, humSub);
|
|
168896
|
+
}
|
|
168686
168897
|
const clusterLabels = [
|
|
168687
168898
|
"AirPurifier",
|
|
168688
168899
|
config10.temperatureEntityId ? "+Temp" : "",
|
|
168689
168900
|
config10.humidityEntityId ? "+Hum" : "",
|
|
168690
|
-
config10.batteryEntityId ? "+Bat" : ""
|
|
168901
|
+
config10.batteryEntityId ? "+Bat" : "",
|
|
168902
|
+
hasFilterLife ? "+HEPA" : ""
|
|
168691
168903
|
].filter(Boolean).join("");
|
|
168692
|
-
logger169.info(
|
|
168904
|
+
logger169.info(
|
|
168905
|
+
`Created composed air purifier ${primaryEntityId}: ${clusterLabels}`
|
|
168906
|
+
);
|
|
168693
168907
|
return endpoint;
|
|
168694
168908
|
}
|
|
168695
|
-
constructor(type, entityId, id,
|
|
168696
|
-
super(type, { id });
|
|
168909
|
+
constructor(type, entityId, id, parts, mappedEntityIds) {
|
|
168910
|
+
super(type, { id, parts });
|
|
168697
168911
|
this.entityId = entityId;
|
|
168698
|
-
this.trackedEntityIds = trackedEntityIds;
|
|
168699
168912
|
this.mappedEntityIds = mappedEntityIds;
|
|
168700
168913
|
}
|
|
168701
168914
|
async updateStates(states) {
|
|
168702
|
-
|
|
168703
|
-
for (const entityId of this.
|
|
168704
|
-
|
|
168705
|
-
if (!state) continue;
|
|
168706
|
-
const stateJson = JSON.stringify({
|
|
168707
|
-
s: state.state,
|
|
168708
|
-
a: state.attributes
|
|
168709
|
-
});
|
|
168710
|
-
if (this.lastStates.get(entityId) !== stateJson) {
|
|
168711
|
-
this.lastStates.set(entityId, stateJson);
|
|
168712
|
-
anyChanged = true;
|
|
168713
|
-
}
|
|
168915
|
+
this.scheduleUpdate(this, this.entityId, states);
|
|
168916
|
+
for (const [entityId, sub] of this.subEndpoints) {
|
|
168917
|
+
this.scheduleUpdate(sub, entityId, states);
|
|
168714
168918
|
}
|
|
168715
|
-
|
|
168716
|
-
|
|
168717
|
-
|
|
168718
|
-
if (!
|
|
168719
|
-
|
|
168720
|
-
|
|
168919
|
+
}
|
|
168920
|
+
scheduleUpdate(endpoint, entityId, states) {
|
|
168921
|
+
const state = states[entityId];
|
|
168922
|
+
if (!state) return;
|
|
168923
|
+
const key = endpoint === this ? `_parent_:${entityId}` : entityId;
|
|
168924
|
+
const stateJson = JSON.stringify({
|
|
168925
|
+
s: state.state,
|
|
168926
|
+
a: state.attributes
|
|
168927
|
+
});
|
|
168928
|
+
if (this.lastStates.get(key) === stateJson) return;
|
|
168929
|
+
this.lastStates.set(key, stateJson);
|
|
168930
|
+
let debouncedFn = this.debouncedUpdates.get(key);
|
|
168931
|
+
if (!debouncedFn) {
|
|
168932
|
+
debouncedFn = debounce2(
|
|
168933
|
+
(ep, s) => this.flushUpdate(ep, s),
|
|
168721
168934
|
50
|
|
168722
168935
|
);
|
|
168936
|
+
this.debouncedUpdates.set(key, debouncedFn);
|
|
168723
168937
|
}
|
|
168724
|
-
|
|
168938
|
+
debouncedFn(endpoint, state);
|
|
168725
168939
|
}
|
|
168726
|
-
async flushUpdate(state) {
|
|
168940
|
+
async flushUpdate(endpoint, state) {
|
|
168727
168941
|
try {
|
|
168728
|
-
await
|
|
168942
|
+
await endpoint.construction.ready;
|
|
168729
168943
|
} catch {
|
|
168730
168944
|
return;
|
|
168731
168945
|
}
|
|
168732
168946
|
try {
|
|
168733
|
-
const current =
|
|
168734
|
-
await
|
|
168735
|
-
entity: { ...current, state
|
|
168947
|
+
const current = endpoint.stateOf(HomeAssistantEntityBehavior).entity;
|
|
168948
|
+
await endpoint.setStateOf(HomeAssistantEntityBehavior, {
|
|
168949
|
+
entity: { ...current, state }
|
|
168736
168950
|
});
|
|
168737
168951
|
} catch (error) {
|
|
168738
168952
|
if (error instanceof TransactionDestroyedError || error instanceof DestroyedDependencyError) {
|
|
@@ -168748,7 +168962,9 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
168748
168962
|
}
|
|
168749
168963
|
}
|
|
168750
168964
|
async delete() {
|
|
168751
|
-
this.
|
|
168965
|
+
for (const fn of this.debouncedUpdates.values()) {
|
|
168966
|
+
fn.clear();
|
|
168967
|
+
}
|
|
168752
168968
|
await super.delete();
|
|
168753
168969
|
}
|
|
168754
168970
|
};
|
|
@@ -168833,7 +169049,7 @@ function PressureMeasurementServer2(config10) {
|
|
|
168833
169049
|
|
|
168834
169050
|
// src/matter/endpoints/composed/composed-sensor-endpoint.ts
|
|
168835
169051
|
var logger171 = Logger.get("ComposedSensorEndpoint");
|
|
168836
|
-
var
|
|
169052
|
+
var temperatureConfig2 = {
|
|
168837
169053
|
getValue(entity, agent) {
|
|
168838
169054
|
const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
|
|
168839
169055
|
const state = entity.state;
|
|
@@ -168846,7 +169062,7 @@ var temperatureConfig = {
|
|
|
168846
169062
|
);
|
|
168847
169063
|
}
|
|
168848
169064
|
};
|
|
168849
|
-
var
|
|
169065
|
+
var humidityConfig2 = {
|
|
168850
169066
|
getValue({ state }) {
|
|
168851
169067
|
if (state == null || Number.isNaN(+state)) return null;
|
|
168852
169068
|
return +state;
|
|
@@ -168873,15 +169089,15 @@ var batteryConfig2 = {
|
|
|
168873
169089
|
return null;
|
|
168874
169090
|
}
|
|
168875
169091
|
};
|
|
168876
|
-
var
|
|
169092
|
+
var TemperatureSubType2 = TemperatureSensorDevice.with(
|
|
168877
169093
|
IdentifyServer2,
|
|
168878
169094
|
HomeAssistantEntityBehavior,
|
|
168879
|
-
TemperatureMeasurementServer2(
|
|
169095
|
+
TemperatureMeasurementServer2(temperatureConfig2)
|
|
168880
169096
|
);
|
|
168881
|
-
var
|
|
169097
|
+
var HumiditySubType2 = HumiditySensorDevice.with(
|
|
168882
169098
|
IdentifyServer2,
|
|
168883
169099
|
HomeAssistantEntityBehavior,
|
|
168884
|
-
HumidityMeasurementServer(
|
|
169100
|
+
HumidityMeasurementServer(humidityConfig2)
|
|
168885
169101
|
);
|
|
168886
169102
|
var PressureSubType = PressureSensorDevice.with(
|
|
168887
169103
|
IdentifyServer2,
|
|
@@ -168937,7 +169153,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
168937
169153
|
const endpointId = createEndpointId3(primaryEntityId, config10.customName);
|
|
168938
169154
|
const parts = [];
|
|
168939
169155
|
const tempSub = new Endpoint(
|
|
168940
|
-
|
|
169156
|
+
TemperatureSubType2.set({
|
|
168941
169157
|
homeAssistantEntity: { entity: primaryPayload }
|
|
168942
169158
|
}),
|
|
168943
169159
|
{ id: `${endpointId}_temp` }
|
|
@@ -168948,7 +169164,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
168948
169164
|
const humPayload = buildEntityPayload2(registry2, config10.humidityEntityId);
|
|
168949
169165
|
if (humPayload) {
|
|
168950
169166
|
humSub = new Endpoint(
|
|
168951
|
-
|
|
169167
|
+
HumiditySubType2.set({
|
|
168952
169168
|
homeAssistantEntity: { entity: humPayload }
|
|
168953
169169
|
}),
|
|
168954
169170
|
{ id: `${endpointId}_humidity` }
|
|
@@ -169064,6 +169280,15 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
169064
169280
|
}
|
|
169065
169281
|
};
|
|
169066
169282
|
|
|
169283
|
+
// src/matter/endpoints/composed/user-composed-endpoint.ts
|
|
169284
|
+
init_esm();
|
|
169285
|
+
init_esm7();
|
|
169286
|
+
import debounce4 from "debounce";
|
|
169287
|
+
init_home_assistant_entity_behavior();
|
|
169288
|
+
|
|
169289
|
+
// src/matter/endpoints/legacy/create-legacy-endpoint-type.ts
|
|
169290
|
+
init_esm();
|
|
169291
|
+
|
|
169067
169292
|
// src/matter/endpoints/legacy/air-purifier/index.ts
|
|
169068
169293
|
init_dist();
|
|
169069
169294
|
init_home_assistant_entity_behavior();
|
|
@@ -169857,7 +170082,7 @@ var ClimateFanControlServer = FanControlServer2(config3).with(
|
|
|
169857
170082
|
);
|
|
169858
170083
|
|
|
169859
170084
|
// src/matter/endpoints/legacy/climate/behaviors/climate-humidity-measurement-server.ts
|
|
169860
|
-
var
|
|
170085
|
+
var humidityConfig3 = {
|
|
169861
170086
|
getValue(entity) {
|
|
169862
170087
|
const attributes7 = entity.attributes;
|
|
169863
170088
|
const humidity = attributes7.current_humidity;
|
|
@@ -169867,11 +170092,18 @@ var humidityConfig2 = {
|
|
|
169867
170092
|
return +humidity;
|
|
169868
170093
|
}
|
|
169869
170094
|
};
|
|
169870
|
-
var ClimateHumidityMeasurementServer = HumidityMeasurementServer(
|
|
170095
|
+
var ClimateHumidityMeasurementServer = HumidityMeasurementServer(humidityConfig3);
|
|
169871
170096
|
|
|
169872
170097
|
// src/matter/endpoints/legacy/climate/behaviors/climate-on-off-server.ts
|
|
170098
|
+
init_home_assistant_entity_behavior();
|
|
169873
170099
|
var ClimateOnOffServer = OnOffServer2({
|
|
169874
|
-
turnOn: () =>
|
|
170100
|
+
turnOn: (_value, agent) => {
|
|
170101
|
+
const entity = agent.get(HomeAssistantEntityBehavior).entity;
|
|
170102
|
+
if (entity.state.state !== "off") {
|
|
170103
|
+
return void 0;
|
|
170104
|
+
}
|
|
170105
|
+
return { action: "climate.turn_on" };
|
|
170106
|
+
},
|
|
169875
170107
|
turnOff: () => ({ action: "climate.turn_off" })
|
|
169876
170108
|
}).with("Lighting");
|
|
169877
170109
|
|
|
@@ -170048,7 +170280,8 @@ var ThermostatServerBase = class extends FullFeaturedBase {
|
|
|
170048
170280
|
logger174.debug(
|
|
170049
170281
|
`update: limits heat=[${minHeatLimit}, ${maxHeatLimit}], cool=[${minCoolLimit}, ${maxCoolLimit}], systemMode=${systemMode}, runningMode=${runningMode}`
|
|
170050
170282
|
);
|
|
170051
|
-
|
|
170283
|
+
let controlSequence = config10.getControlSequence(entity.state, this.agent);
|
|
170284
|
+
controlSequence = this.clampControlSequence(controlSequence);
|
|
170052
170285
|
this.internal.controlSequenceOfOperation = controlSequence;
|
|
170053
170286
|
applyPatchState(this.state, {
|
|
170054
170287
|
...this.features.heating ? {
|
|
@@ -170303,6 +170536,26 @@ var ThermostatServerBase = class extends FullFeaturedBase {
|
|
|
170303
170536
|
}
|
|
170304
170537
|
}
|
|
170305
170538
|
}
|
|
170539
|
+
clampControlSequence(value) {
|
|
170540
|
+
const hasHeat = this.features.heating;
|
|
170541
|
+
const hasCool = this.features.cooling;
|
|
170542
|
+
const needsHeat = value === Thermostat3.ControlSequenceOfOperation.HeatingOnly || value === Thermostat3.ControlSequenceOfOperation.HeatingWithReheat;
|
|
170543
|
+
const needsCool = value === Thermostat3.ControlSequenceOfOperation.CoolingOnly || value === Thermostat3.ControlSequenceOfOperation.CoolingWithReheat;
|
|
170544
|
+
const needsBoth = value === Thermostat3.ControlSequenceOfOperation.CoolingAndHeating || value === Thermostat3.ControlSequenceOfOperation.CoolingAndHeatingWithReheat;
|
|
170545
|
+
if (needsHeat && !hasHeat) {
|
|
170546
|
+
return Thermostat3.ControlSequenceOfOperation.CoolingOnly;
|
|
170547
|
+
}
|
|
170548
|
+
if (needsCool && !hasCool) {
|
|
170549
|
+
return Thermostat3.ControlSequenceOfOperation.HeatingOnly;
|
|
170550
|
+
}
|
|
170551
|
+
if (needsBoth && !hasHeat) {
|
|
170552
|
+
return Thermostat3.ControlSequenceOfOperation.CoolingOnly;
|
|
170553
|
+
}
|
|
170554
|
+
if (needsBoth && !hasCool) {
|
|
170555
|
+
return Thermostat3.ControlSequenceOfOperation.HeatingOnly;
|
|
170556
|
+
}
|
|
170557
|
+
return value;
|
|
170558
|
+
}
|
|
170306
170559
|
clampSetpoint(value, min, max, type) {
|
|
170307
170560
|
const effectiveMin = min ?? 0;
|
|
170308
170561
|
const effectiveMax = max ?? 5e3;
|
|
@@ -170551,7 +170804,7 @@ var config4 = {
|
|
|
170551
170804
|
(m) => m === ClimateHvacMode.cool || m === ClimateHvacMode.heat_cool
|
|
170552
170805
|
);
|
|
170553
170806
|
const hasHeating = modes.some(
|
|
170554
|
-
(m) => m === ClimateHvacMode.heat || m === ClimateHvacMode.heat_cool
|
|
170807
|
+
(m) => m === ClimateHvacMode.heat || m === ClimateHvacMode.heat_cool
|
|
170555
170808
|
);
|
|
170556
170809
|
if (hasCooling && hasHeating) {
|
|
170557
170810
|
const hasAutoMode = modes.includes(ClimateHvacMode.heat_cool) && (modes.includes(ClimateHvacMode.heat) || modes.includes(ClimateHvacMode.cool));
|
|
@@ -170611,25 +170864,6 @@ function ClimateThermostatServer(initialState = {}, features2) {
|
|
|
170611
170864
|
}
|
|
170612
170865
|
|
|
170613
170866
|
// src/matter/endpoints/legacy/climate/index.ts
|
|
170614
|
-
var ClimatePowerSourceServer = PowerSourceServer2({
|
|
170615
|
-
getBatteryPercent: (entity, agent) => {
|
|
170616
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
170617
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
170618
|
-
if (batteryEntity) {
|
|
170619
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
170620
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
170621
|
-
if (battery != null) {
|
|
170622
|
-
return Math.max(0, Math.min(100, battery));
|
|
170623
|
-
}
|
|
170624
|
-
}
|
|
170625
|
-
const attrs = entity.attributes;
|
|
170626
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
170627
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
170628
|
-
return null;
|
|
170629
|
-
}
|
|
170630
|
-
return Number(level);
|
|
170631
|
-
}
|
|
170632
|
-
});
|
|
170633
170867
|
var ClimateDeviceType = (supportsOnOff, supportsHumidity, supportsFanMode, hasBattery, features2, initialState = {}) => {
|
|
170634
170868
|
const additionalClusters = [];
|
|
170635
170869
|
if (supportsOnOff) {
|
|
@@ -170639,7 +170873,7 @@ var ClimateDeviceType = (supportsOnOff, supportsHumidity, supportsFanMode, hasBa
|
|
|
170639
170873
|
additionalClusters.push(ClimateHumidityMeasurementServer);
|
|
170640
170874
|
}
|
|
170641
170875
|
if (hasBattery) {
|
|
170642
|
-
additionalClusters.push(
|
|
170876
|
+
additionalClusters.push(DefaultPowerSourceServer);
|
|
170643
170877
|
}
|
|
170644
170878
|
const thermostatServer = ClimateThermostatServer(initialState, features2);
|
|
170645
170879
|
if (supportsFanMode) {
|
|
@@ -170859,6 +171093,22 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
170859
171093
|
);
|
|
170860
171094
|
const currentTilt100ths = currentTilt != null ? currentTilt * 100 : null;
|
|
170861
171095
|
const isStopped = movementStatus === MovementStatus.Stopped;
|
|
171096
|
+
const inferTarget = (current100ths, existing100ths) => {
|
|
171097
|
+
if (isStopped) return current100ths;
|
|
171098
|
+
if (movementStatus === MovementStatus.Opening) {
|
|
171099
|
+
if (existing100ths != null && current100ths != null && existing100ths < current100ths) {
|
|
171100
|
+
return existing100ths;
|
|
171101
|
+
}
|
|
171102
|
+
return 0;
|
|
171103
|
+
}
|
|
171104
|
+
if (movementStatus === MovementStatus.Closing) {
|
|
171105
|
+
if (existing100ths != null && current100ths != null && existing100ths > current100ths) {
|
|
171106
|
+
return existing100ths;
|
|
171107
|
+
}
|
|
171108
|
+
return 1e4;
|
|
171109
|
+
}
|
|
171110
|
+
return existing100ths ?? current100ths;
|
|
171111
|
+
};
|
|
170862
171112
|
logger175.debug(
|
|
170863
171113
|
`Cover update for ${entity.entity_id}: state=${state.state}, lift=${currentLift}%, tilt=${currentTilt}%, movement=${MovementStatus[movementStatus]}`
|
|
170864
171114
|
);
|
|
@@ -170885,14 +171135,18 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
170885
171135
|
...this.features.positionAwareLift ? {
|
|
170886
171136
|
currentPositionLiftPercentage: currentLift,
|
|
170887
171137
|
currentPositionLiftPercent100ths: currentLift100ths,
|
|
170888
|
-
|
|
170889
|
-
|
|
171138
|
+
targetPositionLiftPercent100ths: inferTarget(
|
|
171139
|
+
currentLift100ths,
|
|
171140
|
+
this.state.targetPositionLiftPercent100ths
|
|
171141
|
+
)
|
|
170890
171142
|
} : {},
|
|
170891
171143
|
...this.features.positionAwareTilt ? {
|
|
170892
171144
|
currentPositionTiltPercentage: currentTilt,
|
|
170893
171145
|
currentPositionTiltPercent100ths: currentTilt100ths,
|
|
170894
|
-
|
|
170895
|
-
|
|
171146
|
+
targetPositionTiltPercent100ths: inferTarget(
|
|
171147
|
+
currentTilt100ths,
|
|
171148
|
+
this.state.targetPositionTiltPercent100ths
|
|
171149
|
+
)
|
|
170896
171150
|
} : {}
|
|
170897
171151
|
}
|
|
170898
171152
|
);
|
|
@@ -171114,6 +171368,9 @@ var adjustPositionForWriting2 = (position, agent) => {
|
|
|
171114
171368
|
return adjustPositionForWriting(position, featureFlags, matterSem);
|
|
171115
171369
|
};
|
|
171116
171370
|
var shouldSwapOpenClose = (agent) => {
|
|
171371
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171372
|
+
const entitySwap = homeAssistant.state.mapping?.coverSwapOpenClose;
|
|
171373
|
+
if (entitySwap !== void 0) return entitySwap;
|
|
171117
171374
|
const { featureFlags } = agent.env.get(BridgeDataProvider);
|
|
171118
171375
|
return featureFlags?.coverSwapOpenClose === true;
|
|
171119
171376
|
};
|
|
@@ -171210,25 +171467,6 @@ var CoverWindowCoveringServer = WindowCoveringServer2(config5);
|
|
|
171210
171467
|
|
|
171211
171468
|
// src/matter/endpoints/legacy/cover/index.ts
|
|
171212
171469
|
var logger177 = Logger.get("CoverDevice");
|
|
171213
|
-
var CoverPowerSourceServer = PowerSourceServer2({
|
|
171214
|
-
getBatteryPercent: (entity, agent) => {
|
|
171215
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171216
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
171217
|
-
if (batteryEntity) {
|
|
171218
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
171219
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
171220
|
-
if (battery != null) {
|
|
171221
|
-
return Math.max(0, Math.min(100, battery));
|
|
171222
|
-
}
|
|
171223
|
-
}
|
|
171224
|
-
const attrs = entity.attributes;
|
|
171225
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
171226
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
171227
|
-
return null;
|
|
171228
|
-
}
|
|
171229
|
-
return Number(level);
|
|
171230
|
-
}
|
|
171231
|
-
});
|
|
171232
171470
|
var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
|
|
171233
171471
|
const features2 = /* @__PURE__ */ new Set();
|
|
171234
171472
|
if (testBit(supportedFeatures, CoverSupportedFeatures.support_open)) {
|
|
@@ -171263,7 +171501,10 @@ var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
|
|
|
171263
171501
|
CoverWindowCoveringServer.with(...features2)
|
|
171264
171502
|
];
|
|
171265
171503
|
if (hasBattery) {
|
|
171266
|
-
return WindowCoveringDevice.with(
|
|
171504
|
+
return WindowCoveringDevice.with(
|
|
171505
|
+
...baseBehaviors,
|
|
171506
|
+
DefaultPowerSourceServer
|
|
171507
|
+
);
|
|
171267
171508
|
}
|
|
171268
171509
|
return WindowCoveringDevice.with(...baseBehaviors);
|
|
171269
171510
|
};
|
|
@@ -171384,25 +171625,6 @@ function EventDevice(homeAssistantEntity) {
|
|
|
171384
171625
|
// src/matter/endpoints/legacy/fan/index.ts
|
|
171385
171626
|
init_dist();
|
|
171386
171627
|
init_home_assistant_entity_behavior();
|
|
171387
|
-
var FanPowerSourceServer = PowerSourceServer2({
|
|
171388
|
-
getBatteryPercent: (entity, agent) => {
|
|
171389
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171390
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
171391
|
-
if (batteryEntity) {
|
|
171392
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
171393
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
171394
|
-
if (battery != null) {
|
|
171395
|
-
return Math.max(0, Math.min(100, battery));
|
|
171396
|
-
}
|
|
171397
|
-
}
|
|
171398
|
-
const attrs = entity.attributes;
|
|
171399
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
171400
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
171401
|
-
return null;
|
|
171402
|
-
}
|
|
171403
|
-
return Number(level);
|
|
171404
|
-
}
|
|
171405
|
-
});
|
|
171406
171628
|
function FanDevice2(homeAssistantEntity) {
|
|
171407
171629
|
const attributes7 = homeAssistantEntity.entity.state.attributes;
|
|
171408
171630
|
const supportedFeatures = attributes7.supported_features ?? 0;
|
|
@@ -171422,7 +171644,7 @@ function FanDevice2(homeAssistantEntity) {
|
|
|
171422
171644
|
BasicInformationServer2,
|
|
171423
171645
|
HomeAssistantEntityBehavior,
|
|
171424
171646
|
FanOnOffServer,
|
|
171425
|
-
|
|
171647
|
+
DefaultPowerSourceServer
|
|
171426
171648
|
) : OnOffPlugInUnitDevice.with(
|
|
171427
171649
|
IdentifyServer2,
|
|
171428
171650
|
BasicInformationServer2,
|
|
@@ -171457,7 +171679,7 @@ function FanDevice2(homeAssistantEntity) {
|
|
|
171457
171679
|
HomeAssistantEntityBehavior,
|
|
171458
171680
|
FanOnOffServer,
|
|
171459
171681
|
FanFanControlServer.with(...features2),
|
|
171460
|
-
|
|
171682
|
+
DefaultPowerSourceServer
|
|
171461
171683
|
) : FanDevice.with(
|
|
171462
171684
|
IdentifyServer2,
|
|
171463
171685
|
BasicInformationServer2,
|
|
@@ -171982,25 +172204,6 @@ var ColorTemperatureLightType = ColorTemperatureLightDevice.with(
|
|
|
171982
172204
|
|
|
171983
172205
|
// src/matter/endpoints/legacy/light/devices/dimmable-light.ts
|
|
171984
172206
|
init_home_assistant_entity_behavior();
|
|
171985
|
-
var LightPowerSourceServer = PowerSourceServer2({
|
|
171986
|
-
getBatteryPercent: (entity, agent) => {
|
|
171987
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171988
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
171989
|
-
if (batteryEntity) {
|
|
171990
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
171991
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
171992
|
-
if (battery != null) {
|
|
171993
|
-
return Math.max(0, Math.min(100, battery));
|
|
171994
|
-
}
|
|
171995
|
-
}
|
|
171996
|
-
const attrs = entity.attributes;
|
|
171997
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
171998
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
171999
|
-
return null;
|
|
172000
|
-
}
|
|
172001
|
-
return Number(level);
|
|
172002
|
-
}
|
|
172003
|
-
});
|
|
172004
172207
|
var DimmableLightType = DimmableLightDevice.with(
|
|
172005
172208
|
IdentifyServer2,
|
|
172006
172209
|
BasicInformationServer2,
|
|
@@ -172014,30 +172217,11 @@ var DimmableLightWithBatteryType = DimmableLightDevice.with(
|
|
|
172014
172217
|
HomeAssistantEntityBehavior,
|
|
172015
172218
|
LightOnOffServer,
|
|
172016
172219
|
LightLevelControlServer,
|
|
172017
|
-
|
|
172220
|
+
DefaultPowerSourceServer
|
|
172018
172221
|
);
|
|
172019
172222
|
|
|
172020
172223
|
// src/matter/endpoints/legacy/light/devices/extended-color-light.ts
|
|
172021
172224
|
init_home_assistant_entity_behavior();
|
|
172022
|
-
var LightPowerSourceServer2 = PowerSourceServer2({
|
|
172023
|
-
getBatteryPercent: (entity, agent) => {
|
|
172024
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
172025
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
172026
|
-
if (batteryEntity) {
|
|
172027
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
172028
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
172029
|
-
if (battery != null) {
|
|
172030
|
-
return Math.max(0, Math.min(100, battery));
|
|
172031
|
-
}
|
|
172032
|
-
}
|
|
172033
|
-
const attrs = entity.attributes;
|
|
172034
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
172035
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
172036
|
-
return null;
|
|
172037
|
-
}
|
|
172038
|
-
return Number(level);
|
|
172039
|
-
}
|
|
172040
|
-
});
|
|
172041
172225
|
var ExtendedColorLightType = (supportsColorControl, supportsTemperature, hasBattery = false) => {
|
|
172042
172226
|
const features2 = /* @__PURE__ */ new Set();
|
|
172043
172227
|
if (supportsColorControl) {
|
|
@@ -172054,7 +172238,7 @@ var ExtendedColorLightType = (supportsColorControl, supportsTemperature, hasBatt
|
|
|
172054
172238
|
LightOnOffServer,
|
|
172055
172239
|
LightLevelControlServer,
|
|
172056
172240
|
LightColorControlServer.with(...features2),
|
|
172057
|
-
|
|
172241
|
+
DefaultPowerSourceServer
|
|
172058
172242
|
);
|
|
172059
172243
|
}
|
|
172060
172244
|
return ExtendedColorLightDevice.with(
|
|
@@ -172069,25 +172253,6 @@ var ExtendedColorLightType = (supportsColorControl, supportsTemperature, hasBatt
|
|
|
172069
172253
|
|
|
172070
172254
|
// src/matter/endpoints/legacy/light/devices/on-off-light-device.ts
|
|
172071
172255
|
init_home_assistant_entity_behavior();
|
|
172072
|
-
var LightPowerSourceServer3 = PowerSourceServer2({
|
|
172073
|
-
getBatteryPercent: (entity, agent) => {
|
|
172074
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
172075
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
172076
|
-
if (batteryEntity) {
|
|
172077
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
172078
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
172079
|
-
if (battery != null) {
|
|
172080
|
-
return Math.max(0, Math.min(100, battery));
|
|
172081
|
-
}
|
|
172082
|
-
}
|
|
172083
|
-
const attrs = entity.attributes;
|
|
172084
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
172085
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
172086
|
-
return null;
|
|
172087
|
-
}
|
|
172088
|
-
return Number(level);
|
|
172089
|
-
}
|
|
172090
|
-
});
|
|
172091
172256
|
var OnOffLightType = OnOffLightDevice.with(
|
|
172092
172257
|
IdentifyServer2,
|
|
172093
172258
|
BasicInformationServer2,
|
|
@@ -172099,7 +172264,7 @@ var OnOffLightWithBatteryType = OnOffLightDevice.with(
|
|
|
172099
172264
|
BasicInformationServer2,
|
|
172100
172265
|
HomeAssistantEntityBehavior,
|
|
172101
172266
|
LightOnOffServer,
|
|
172102
|
-
|
|
172267
|
+
DefaultPowerSourceServer
|
|
172103
172268
|
);
|
|
172104
172269
|
|
|
172105
172270
|
// src/matter/endpoints/legacy/light/index.ts
|
|
@@ -172790,25 +172955,6 @@ var lockServerConfig = {
|
|
|
172790
172955
|
unlock: () => ({ action: "lock.unlock" }),
|
|
172791
172956
|
unlatch: () => ({ action: "lock.open" })
|
|
172792
172957
|
};
|
|
172793
|
-
var LockPowerSourceServer = PowerSourceServer2({
|
|
172794
|
-
getBatteryPercent: (entity, agent) => {
|
|
172795
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
172796
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
172797
|
-
if (batteryEntity) {
|
|
172798
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
172799
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
172800
|
-
if (battery != null) {
|
|
172801
|
-
return Math.max(0, Math.min(100, battery));
|
|
172802
|
-
}
|
|
172803
|
-
}
|
|
172804
|
-
const attrs = entity.attributes;
|
|
172805
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
172806
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
172807
|
-
return null;
|
|
172808
|
-
}
|
|
172809
|
-
return Number(level);
|
|
172810
|
-
}
|
|
172811
|
-
});
|
|
172812
172958
|
var LockDeviceType = DoorLockDevice.with(
|
|
172813
172959
|
BasicInformationServer2,
|
|
172814
172960
|
IdentifyServer2,
|
|
@@ -172820,7 +172966,7 @@ var LockWithBatteryDeviceType = DoorLockDevice.with(
|
|
|
172820
172966
|
IdentifyServer2,
|
|
172821
172967
|
HomeAssistantEntityBehavior,
|
|
172822
172968
|
LockServerWithPin(lockServerConfig),
|
|
172823
|
-
|
|
172969
|
+
DefaultPowerSourceServer
|
|
172824
172970
|
);
|
|
172825
172971
|
var LockWithUnlatchDeviceType = DoorLockDevice.with(
|
|
172826
172972
|
BasicInformationServer2,
|
|
@@ -172833,7 +172979,7 @@ var LockWithUnlatchAndBatteryDeviceType = DoorLockDevice.with(
|
|
|
172833
172979
|
IdentifyServer2,
|
|
172834
172980
|
HomeAssistantEntityBehavior,
|
|
172835
172981
|
LockServerWithPinAndUnbolt(lockServerConfig),
|
|
172836
|
-
|
|
172982
|
+
DefaultPowerSourceServer
|
|
172837
172983
|
);
|
|
172838
172984
|
function LockDevice(homeAssistantEntity) {
|
|
172839
172985
|
const attrs = homeAssistantEntity.entity.state.attributes;
|
|
@@ -173409,8 +173555,20 @@ var PumpType = PumpDevice.with(
|
|
|
173409
173555
|
PumpOnOffServer,
|
|
173410
173556
|
PumpConfigurationAndControlServer2
|
|
173411
173557
|
);
|
|
173558
|
+
var PumpWithBatteryType = PumpDevice.with(
|
|
173559
|
+
IdentifyServer2,
|
|
173560
|
+
BasicInformationServer2,
|
|
173561
|
+
HomeAssistantEntityBehavior,
|
|
173562
|
+
PumpOnOffServer,
|
|
173563
|
+
PumpConfigurationAndControlServer2,
|
|
173564
|
+
DefaultPowerSourceServer
|
|
173565
|
+
);
|
|
173412
173566
|
function PumpEndpoint(homeAssistantEntity) {
|
|
173413
|
-
|
|
173567
|
+
const attrs = homeAssistantEntity.entity.state.attributes;
|
|
173568
|
+
const hasBatteryAttr = attrs.battery_level != null || attrs.battery != null;
|
|
173569
|
+
const hasBatteryEntity = !!homeAssistantEntity.mapping?.batteryEntity;
|
|
173570
|
+
const device = hasBatteryAttr || hasBatteryEntity ? PumpWithBatteryType : PumpType;
|
|
173571
|
+
return device.set({ homeAssistantEntity });
|
|
173414
173572
|
}
|
|
173415
173573
|
|
|
173416
173574
|
// src/matter/endpoints/legacy/remote/index.ts
|
|
@@ -174931,7 +175089,7 @@ var Pm25SensorType = AirQualitySensorDevice.with(
|
|
|
174931
175089
|
|
|
174932
175090
|
// src/matter/endpoints/legacy/sensor/devices/temperature-humidity-sensor.ts
|
|
174933
175091
|
init_home_assistant_entity_behavior();
|
|
174934
|
-
var
|
|
175092
|
+
var temperatureConfig3 = {
|
|
174935
175093
|
getValue(entity, agent) {
|
|
174936
175094
|
const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
|
|
174937
175095
|
const state = entity.state;
|
|
@@ -174946,7 +175104,7 @@ var temperatureConfig2 = {
|
|
|
174946
175104
|
);
|
|
174947
175105
|
}
|
|
174948
175106
|
};
|
|
174949
|
-
var
|
|
175107
|
+
var humidityConfig4 = {
|
|
174950
175108
|
getValue(_entity, agent) {
|
|
174951
175109
|
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
174952
175110
|
const humidityEntity = homeAssistant.state.mapping?.humidityEntity;
|
|
@@ -174996,38 +175154,38 @@ var TemperatureHumiditySensorType = TemperatureSensorDevice.with(
|
|
|
174996
175154
|
BasicInformationServer2,
|
|
174997
175155
|
IdentifyServer2,
|
|
174998
175156
|
HomeAssistantEntityBehavior,
|
|
174999
|
-
TemperatureMeasurementServer2(
|
|
175000
|
-
HumidityMeasurementServer(
|
|
175157
|
+
TemperatureMeasurementServer2(temperatureConfig3),
|
|
175158
|
+
HumidityMeasurementServer(humidityConfig4)
|
|
175001
175159
|
);
|
|
175002
175160
|
var TemperatureHumiditySensorWithBatteryType = TemperatureSensorDevice.with(
|
|
175003
175161
|
BasicInformationServer2,
|
|
175004
175162
|
IdentifyServer2,
|
|
175005
175163
|
HomeAssistantEntityBehavior,
|
|
175006
|
-
TemperatureMeasurementServer2(
|
|
175007
|
-
HumidityMeasurementServer(
|
|
175164
|
+
TemperatureMeasurementServer2(temperatureConfig3),
|
|
175165
|
+
HumidityMeasurementServer(humidityConfig4),
|
|
175008
175166
|
PowerSourceServer2(batteryConfig4)
|
|
175009
175167
|
);
|
|
175010
175168
|
var TemperatureHumidityPressureSensorType = TemperatureSensorDevice.with(
|
|
175011
175169
|
BasicInformationServer2,
|
|
175012
175170
|
IdentifyServer2,
|
|
175013
175171
|
HomeAssistantEntityBehavior,
|
|
175014
|
-
TemperatureMeasurementServer2(
|
|
175015
|
-
HumidityMeasurementServer(
|
|
175172
|
+
TemperatureMeasurementServer2(temperatureConfig3),
|
|
175173
|
+
HumidityMeasurementServer(humidityConfig4),
|
|
175016
175174
|
PressureMeasurementServer2(pressureConfig2)
|
|
175017
175175
|
);
|
|
175018
175176
|
var TemperatureHumidityPressureSensorWithBatteryType = TemperatureSensorDevice.with(
|
|
175019
175177
|
BasicInformationServer2,
|
|
175020
175178
|
IdentifyServer2,
|
|
175021
175179
|
HomeAssistantEntityBehavior,
|
|
175022
|
-
TemperatureMeasurementServer2(
|
|
175023
|
-
HumidityMeasurementServer(
|
|
175180
|
+
TemperatureMeasurementServer2(temperatureConfig3),
|
|
175181
|
+
HumidityMeasurementServer(humidityConfig4),
|
|
175024
175182
|
PressureMeasurementServer2(pressureConfig2),
|
|
175025
175183
|
PowerSourceServer2(batteryConfig4)
|
|
175026
175184
|
);
|
|
175027
175185
|
|
|
175028
175186
|
// src/matter/endpoints/legacy/sensor/devices/temperature-pressure-sensor.ts
|
|
175029
175187
|
init_home_assistant_entity_behavior();
|
|
175030
|
-
var
|
|
175188
|
+
var temperatureConfig4 = {
|
|
175031
175189
|
getValue(entity, agent) {
|
|
175032
175190
|
const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
|
|
175033
175191
|
const state = entity.state;
|
|
@@ -175078,14 +175236,14 @@ var TemperaturePressureSensorType = TemperatureSensorDevice.with(
|
|
|
175078
175236
|
BasicInformationServer2,
|
|
175079
175237
|
IdentifyServer2,
|
|
175080
175238
|
HomeAssistantEntityBehavior,
|
|
175081
|
-
TemperatureMeasurementServer2(
|
|
175239
|
+
TemperatureMeasurementServer2(temperatureConfig4),
|
|
175082
175240
|
PressureMeasurementServer2(pressureConfig3)
|
|
175083
175241
|
);
|
|
175084
175242
|
var TemperaturePressureSensorWithBatteryType = TemperatureSensorDevice.with(
|
|
175085
175243
|
BasicInformationServer2,
|
|
175086
175244
|
IdentifyServer2,
|
|
175087
175245
|
HomeAssistantEntityBehavior,
|
|
175088
|
-
TemperatureMeasurementServer2(
|
|
175246
|
+
TemperatureMeasurementServer2(temperatureConfig4),
|
|
175089
175247
|
PressureMeasurementServer2(pressureConfig3),
|
|
175090
175248
|
PowerSourceServer2(batteryConfig5)
|
|
175091
175249
|
);
|
|
@@ -175215,25 +175373,7 @@ var SwitchWithBatteryEndpointType = OnOffPlugInUnitDevice.with(
|
|
|
175215
175373
|
IdentifyServer2,
|
|
175216
175374
|
HomeAssistantEntityBehavior,
|
|
175217
175375
|
SwitchOnOffServer,
|
|
175218
|
-
|
|
175219
|
-
getBatteryPercent: (entity, agent) => {
|
|
175220
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
175221
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
175222
|
-
if (batteryEntity) {
|
|
175223
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
175224
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
175225
|
-
if (battery != null) {
|
|
175226
|
-
return Math.max(0, Math.min(100, battery));
|
|
175227
|
-
}
|
|
175228
|
-
}
|
|
175229
|
-
const attrs = entity.attributes;
|
|
175230
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
175231
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
175232
|
-
return null;
|
|
175233
|
-
}
|
|
175234
|
-
return Number(level);
|
|
175235
|
-
}
|
|
175236
|
-
})
|
|
175376
|
+
DefaultPowerSourceServer
|
|
175237
175377
|
);
|
|
175238
175378
|
function SwitchDevice(homeAssistantEntity) {
|
|
175239
175379
|
const attrs = homeAssistantEntity.entity.state.attributes;
|
|
@@ -177430,8 +177570,19 @@ var ValveEndpointType = WaterValveDevice.with(
|
|
|
177430
177570
|
HomeAssistantEntityBehavior,
|
|
177431
177571
|
ValveServer
|
|
177432
177572
|
);
|
|
177573
|
+
var ValveWithBatteryEndpointType = WaterValveDevice.with(
|
|
177574
|
+
BasicInformationServer2,
|
|
177575
|
+
IdentifyServer2,
|
|
177576
|
+
HomeAssistantEntityBehavior,
|
|
177577
|
+
ValveServer,
|
|
177578
|
+
DefaultPowerSourceServer
|
|
177579
|
+
);
|
|
177433
177580
|
function ValveDevice(homeAssistantEntity) {
|
|
177434
|
-
|
|
177581
|
+
const attrs = homeAssistantEntity.entity.state.attributes;
|
|
177582
|
+
const hasBatteryAttr = attrs.battery_level != null || attrs.battery != null;
|
|
177583
|
+
const hasBatteryEntity = !!homeAssistantEntity.mapping?.batteryEntity;
|
|
177584
|
+
const device = hasBatteryAttr || hasBatteryEntity ? ValveWithBatteryEndpointType : ValveEndpointType;
|
|
177585
|
+
return device.set({ homeAssistantEntity });
|
|
177435
177586
|
}
|
|
177436
177587
|
|
|
177437
177588
|
// src/matter/endpoints/legacy/water-heater/index.ts
|
|
@@ -177552,6 +177703,7 @@ function WaterHeaterDevice(homeAssistantEntity) {
|
|
|
177552
177703
|
}
|
|
177553
177704
|
|
|
177554
177705
|
// src/matter/endpoints/legacy/create-legacy-endpoint-type.ts
|
|
177706
|
+
var legacyLogger = Logger.get("LegacyEndpointType");
|
|
177555
177707
|
function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
177556
177708
|
const domain = entity.entity_id.split(".")[0];
|
|
177557
177709
|
const customName = mapping?.customName;
|
|
@@ -177571,10 +177723,20 @@ function createLegacyEndpointType(entity, mapping, areaName, options) {
|
|
|
177571
177723
|
);
|
|
177572
177724
|
} else {
|
|
177573
177725
|
const factory = deviceCtrs[domain];
|
|
177574
|
-
if (
|
|
177726
|
+
if (factory) {
|
|
177727
|
+
type = factory({ entity, customName, mapping });
|
|
177728
|
+
} else if (options?.pluginDomainMappings?.has(domain)) {
|
|
177729
|
+
const mappedType = options.pluginDomainMappings.get(domain);
|
|
177730
|
+
const mappedFactory = matterDeviceTypeFactories[mappedType];
|
|
177731
|
+
if (mappedFactory) {
|
|
177732
|
+
legacyLogger.info(
|
|
177733
|
+
`Using plugin domain mapping for "${domain}" \u2192 "${mappedType}"`
|
|
177734
|
+
);
|
|
177735
|
+
type = mappedFactory({ entity, customName, mapping });
|
|
177736
|
+
}
|
|
177737
|
+
} else {
|
|
177575
177738
|
return void 0;
|
|
177576
177739
|
}
|
|
177577
|
-
type = factory({ entity, customName, mapping });
|
|
177578
177740
|
}
|
|
177579
177741
|
}
|
|
177580
177742
|
if (!type) {
|
|
@@ -177732,10 +177894,192 @@ var matterDeviceTypeFactories = {
|
|
|
177732
177894
|
})
|
|
177733
177895
|
};
|
|
177734
177896
|
|
|
177897
|
+
// src/matter/endpoints/composed/user-composed-endpoint.ts
|
|
177898
|
+
var logger198 = Logger.get("UserComposedEndpoint");
|
|
177899
|
+
function createEndpointId4(entityId, customName) {
|
|
177900
|
+
const baseName = customName || entityId;
|
|
177901
|
+
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
177902
|
+
}
|
|
177903
|
+
function buildEntityPayload3(registry2, entityId) {
|
|
177904
|
+
const state = registry2.initialState(entityId);
|
|
177905
|
+
if (!state) return void 0;
|
|
177906
|
+
const entity = registry2.entity(entityId);
|
|
177907
|
+
const deviceRegistry = registry2.deviceOf(entityId);
|
|
177908
|
+
return {
|
|
177909
|
+
entity_id: entityId,
|
|
177910
|
+
state,
|
|
177911
|
+
registry: entity,
|
|
177912
|
+
deviceRegistry
|
|
177913
|
+
};
|
|
177914
|
+
}
|
|
177915
|
+
var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
177916
|
+
entityId;
|
|
177917
|
+
mappedEntityIds;
|
|
177918
|
+
subEndpoints = /* @__PURE__ */ new Map();
|
|
177919
|
+
lastStates = /* @__PURE__ */ new Map();
|
|
177920
|
+
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
177921
|
+
static async create(config10) {
|
|
177922
|
+
const { registry: registry2, primaryEntityId, composedEntities } = config10;
|
|
177923
|
+
const primaryPayload = buildEntityPayload3(registry2, primaryEntityId);
|
|
177924
|
+
if (!primaryPayload) return void 0;
|
|
177925
|
+
let parentType = BridgedNodeEndpoint.with(
|
|
177926
|
+
BasicInformationServer2,
|
|
177927
|
+
IdentifyServer2,
|
|
177928
|
+
HomeAssistantEntityBehavior
|
|
177929
|
+
);
|
|
177930
|
+
if (config10.areaName) {
|
|
177931
|
+
const truncatedName = config10.areaName.length > 16 ? config10.areaName.substring(0, 16) : config10.areaName;
|
|
177932
|
+
parentType = parentType.with(
|
|
177933
|
+
FixedLabelServer.set({
|
|
177934
|
+
labelList: [{ label: "room", value: truncatedName }]
|
|
177935
|
+
})
|
|
177936
|
+
);
|
|
177937
|
+
}
|
|
177938
|
+
const endpointId = createEndpointId4(primaryEntityId, config10.customName);
|
|
177939
|
+
const parts = [];
|
|
177940
|
+
const subEndpointMap = /* @__PURE__ */ new Map();
|
|
177941
|
+
const mappedIds = [];
|
|
177942
|
+
const primaryType = createLegacyEndpointType(
|
|
177943
|
+
primaryPayload,
|
|
177944
|
+
config10.mapping,
|
|
177945
|
+
void 0,
|
|
177946
|
+
{ vacuumOnOff: registry2.isVacuumOnOffEnabled() }
|
|
177947
|
+
);
|
|
177948
|
+
if (!primaryType) {
|
|
177949
|
+
logger198.warn(
|
|
177950
|
+
`Cannot create endpoint type for primary entity ${primaryEntityId}`
|
|
177951
|
+
);
|
|
177952
|
+
return void 0;
|
|
177953
|
+
}
|
|
177954
|
+
const primarySub = new Endpoint(primaryType, {
|
|
177955
|
+
id: `${endpointId}_primary`
|
|
177956
|
+
});
|
|
177957
|
+
parts.push(primarySub);
|
|
177958
|
+
subEndpointMap.set(primaryEntityId, primarySub);
|
|
177959
|
+
for (let i = 0; i < composedEntities.length; i++) {
|
|
177960
|
+
const sub = composedEntities[i];
|
|
177961
|
+
if (!sub.entityId) continue;
|
|
177962
|
+
const subPayload = buildEntityPayload3(registry2, sub.entityId);
|
|
177963
|
+
if (!subPayload) {
|
|
177964
|
+
logger198.warn(
|
|
177965
|
+
`Cannot find entity state for composed sub-entity ${sub.entityId}`
|
|
177966
|
+
);
|
|
177967
|
+
continue;
|
|
177968
|
+
}
|
|
177969
|
+
const subMapping = {
|
|
177970
|
+
entityId: sub.entityId,
|
|
177971
|
+
matterDeviceType: sub.matterDeviceType
|
|
177972
|
+
};
|
|
177973
|
+
const subType = createLegacyEndpointType(subPayload, subMapping);
|
|
177974
|
+
if (!subType) {
|
|
177975
|
+
logger198.warn(
|
|
177976
|
+
`Cannot create endpoint type for composed sub-entity ${sub.entityId}`
|
|
177977
|
+
);
|
|
177978
|
+
continue;
|
|
177979
|
+
}
|
|
177980
|
+
const subEndpoint = new Endpoint(subType, {
|
|
177981
|
+
id: `${endpointId}_sub_${i}`
|
|
177982
|
+
});
|
|
177983
|
+
parts.push(subEndpoint);
|
|
177984
|
+
subEndpointMap.set(sub.entityId, subEndpoint);
|
|
177985
|
+
mappedIds.push(sub.entityId);
|
|
177986
|
+
}
|
|
177987
|
+
if (parts.length < 2) {
|
|
177988
|
+
logger198.warn(
|
|
177989
|
+
`User composed device ${primaryEntityId}: only ${parts.length} sub-endpoint(s), need at least 2 (primary + one sub-entity). Falling back to standalone.`
|
|
177990
|
+
);
|
|
177991
|
+
return void 0;
|
|
177992
|
+
}
|
|
177993
|
+
const parentTypeWithState = parentType.set({
|
|
177994
|
+
homeAssistantEntity: {
|
|
177995
|
+
entity: primaryPayload,
|
|
177996
|
+
customName: config10.customName,
|
|
177997
|
+
mapping: config10.mapping
|
|
177998
|
+
}
|
|
177999
|
+
});
|
|
178000
|
+
const endpoint = new _UserComposedEndpoint(
|
|
178001
|
+
parentTypeWithState,
|
|
178002
|
+
primaryEntityId,
|
|
178003
|
+
endpointId,
|
|
178004
|
+
parts,
|
|
178005
|
+
mappedIds
|
|
178006
|
+
);
|
|
178007
|
+
endpoint.subEndpoints = subEndpointMap;
|
|
178008
|
+
const labels = parts.map(
|
|
178009
|
+
(_, i) => i === 0 ? primaryEntityId.split(".")[0] : composedEntities[i - 1]?.entityId?.split(".")[0] ?? "?"
|
|
178010
|
+
).join("+");
|
|
178011
|
+
logger198.info(
|
|
178012
|
+
`Created user composed device ${primaryEntityId}: ${parts.length} sub-endpoint(s) [${labels}]`
|
|
178013
|
+
);
|
|
178014
|
+
return endpoint;
|
|
178015
|
+
}
|
|
178016
|
+
constructor(type, entityId, id, parts, mappedEntityIds) {
|
|
178017
|
+
super(type, { id, parts });
|
|
178018
|
+
this.entityId = entityId;
|
|
178019
|
+
this.mappedEntityIds = mappedEntityIds;
|
|
178020
|
+
}
|
|
178021
|
+
async updateStates(states) {
|
|
178022
|
+
this.scheduleUpdate(this, this.entityId, states);
|
|
178023
|
+
for (const [entityId, sub] of this.subEndpoints) {
|
|
178024
|
+
this.scheduleUpdate(sub, entityId, states);
|
|
178025
|
+
}
|
|
178026
|
+
}
|
|
178027
|
+
scheduleUpdate(endpoint, entityId, states) {
|
|
178028
|
+
const state = states[entityId];
|
|
178029
|
+
if (!state) return;
|
|
178030
|
+
const key = endpoint === this ? `_parent_:${entityId}` : entityId;
|
|
178031
|
+
const stateJson = JSON.stringify({
|
|
178032
|
+
s: state.state,
|
|
178033
|
+
a: state.attributes
|
|
178034
|
+
});
|
|
178035
|
+
if (this.lastStates.get(key) === stateJson) return;
|
|
178036
|
+
this.lastStates.set(key, stateJson);
|
|
178037
|
+
let debouncedFn = this.debouncedUpdates.get(key);
|
|
178038
|
+
if (!debouncedFn) {
|
|
178039
|
+
debouncedFn = debounce4(
|
|
178040
|
+
(ep, s) => this.flushUpdate(ep, s),
|
|
178041
|
+
50
|
|
178042
|
+
);
|
|
178043
|
+
this.debouncedUpdates.set(key, debouncedFn);
|
|
178044
|
+
}
|
|
178045
|
+
debouncedFn(endpoint, state);
|
|
178046
|
+
}
|
|
178047
|
+
async flushUpdate(endpoint, state) {
|
|
178048
|
+
try {
|
|
178049
|
+
await endpoint.construction.ready;
|
|
178050
|
+
} catch {
|
|
178051
|
+
return;
|
|
178052
|
+
}
|
|
178053
|
+
try {
|
|
178054
|
+
const current = endpoint.stateOf(HomeAssistantEntityBehavior).entity;
|
|
178055
|
+
await endpoint.setStateOf(HomeAssistantEntityBehavior, {
|
|
178056
|
+
entity: { ...current, state }
|
|
178057
|
+
});
|
|
178058
|
+
} catch (error) {
|
|
178059
|
+
if (error instanceof TransactionDestroyedError || error instanceof DestroyedDependencyError) {
|
|
178060
|
+
return;
|
|
178061
|
+
}
|
|
178062
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
178063
|
+
if (errorMessage.includes(
|
|
178064
|
+
"Endpoint storage inaccessible because endpoint is not a node and is not owned by another endpoint"
|
|
178065
|
+
)) {
|
|
178066
|
+
return;
|
|
178067
|
+
}
|
|
178068
|
+
throw error;
|
|
178069
|
+
}
|
|
178070
|
+
}
|
|
178071
|
+
async delete() {
|
|
178072
|
+
for (const fn of this.debouncedUpdates.values()) {
|
|
178073
|
+
fn.clear();
|
|
178074
|
+
}
|
|
178075
|
+
await super.delete();
|
|
178076
|
+
}
|
|
178077
|
+
};
|
|
178078
|
+
|
|
177735
178079
|
// src/matter/endpoints/legacy/legacy-endpoint.ts
|
|
177736
|
-
var
|
|
178080
|
+
var logger199 = Logger.get("LegacyEndpoint");
|
|
177737
178081
|
var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
177738
|
-
static async create(registry2, entityId, mapping) {
|
|
178082
|
+
static async create(registry2, entityId, mapping, pluginDomainMappings) {
|
|
177739
178083
|
const deviceRegistry = registry2.deviceOf(entityId);
|
|
177740
178084
|
let state = registry2.initialState(entityId);
|
|
177741
178085
|
const entity = registry2.entity(entityId);
|
|
@@ -177743,25 +178087,25 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177743
178087
|
return;
|
|
177744
178088
|
}
|
|
177745
178089
|
if (registry2.isAutoBatteryMappingEnabled() && registry2.isBatteryEntityUsed(entityId)) {
|
|
177746
|
-
|
|
178090
|
+
logger199.debug(
|
|
177747
178091
|
`Skipping ${entityId} - already auto-assigned as battery to another device`
|
|
177748
178092
|
);
|
|
177749
178093
|
return;
|
|
177750
178094
|
}
|
|
177751
178095
|
if (registry2.isAutoHumidityMappingEnabled() && registry2.isHumidityEntityUsed(entityId)) {
|
|
177752
|
-
|
|
178096
|
+
logger199.debug(
|
|
177753
178097
|
`Skipping ${entityId} - already auto-assigned as humidity to a temperature sensor`
|
|
177754
178098
|
);
|
|
177755
178099
|
return;
|
|
177756
178100
|
}
|
|
177757
178101
|
if (registry2.isAutoPressureMappingEnabled() && registry2.isPressureEntityUsed(entityId)) {
|
|
177758
|
-
|
|
178102
|
+
logger199.debug(
|
|
177759
178103
|
`Skipping ${entityId} - already auto-assigned as pressure to a temperature sensor`
|
|
177760
178104
|
);
|
|
177761
178105
|
return;
|
|
177762
178106
|
}
|
|
177763
178107
|
if (registry2.isAutoComposedDevicesEnabled() && registry2.isComposedSubEntityUsed(entityId)) {
|
|
177764
|
-
|
|
178108
|
+
logger199.debug(
|
|
177765
178109
|
`Skipping ${entityId} - already consumed by a composed device`
|
|
177766
178110
|
);
|
|
177767
178111
|
return;
|
|
@@ -177781,7 +178125,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177781
178125
|
humidityEntity: humidityEntityId
|
|
177782
178126
|
};
|
|
177783
178127
|
registry2.markHumidityEntityUsed(humidityEntityId);
|
|
177784
|
-
|
|
178128
|
+
logger199.debug(
|
|
177785
178129
|
`Auto-assigned humidity ${humidityEntityId} to ${entityId}`
|
|
177786
178130
|
);
|
|
177787
178131
|
}
|
|
@@ -177800,7 +178144,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177800
178144
|
pressureEntity: pressureEntityId
|
|
177801
178145
|
};
|
|
177802
178146
|
registry2.markPressureEntityUsed(pressureEntityId);
|
|
177803
|
-
|
|
178147
|
+
logger199.debug(
|
|
177804
178148
|
`Auto-assigned pressure ${pressureEntityId} to ${entityId}`
|
|
177805
178149
|
);
|
|
177806
178150
|
}
|
|
@@ -177818,7 +178162,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177818
178162
|
batteryEntity: batteryEntityId
|
|
177819
178163
|
};
|
|
177820
178164
|
registry2.markBatteryEntityUsed(batteryEntityId);
|
|
177821
|
-
|
|
178165
|
+
logger199.debug(
|
|
177822
178166
|
`Auto-assigned battery ${batteryEntityId} to ${entityId}`
|
|
177823
178167
|
);
|
|
177824
178168
|
}
|
|
@@ -177836,7 +178180,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177836
178180
|
powerEntity: powerEntityId
|
|
177837
178181
|
};
|
|
177838
178182
|
registry2.markPowerEntityUsed(powerEntityId);
|
|
177839
|
-
|
|
178183
|
+
logger199.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
|
|
177840
178184
|
}
|
|
177841
178185
|
}
|
|
177842
178186
|
}
|
|
@@ -177853,7 +178197,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177853
178197
|
energyEntity: energyEntityId
|
|
177854
178198
|
};
|
|
177855
178199
|
registry2.markEnergyEntityUsed(energyEntityId);
|
|
177856
|
-
|
|
178200
|
+
logger199.debug(
|
|
177857
178201
|
`Auto-assigned energy ${energyEntityId} to ${entityId}`
|
|
177858
178202
|
);
|
|
177859
178203
|
}
|
|
@@ -177869,7 +178213,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177869
178213
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
177870
178214
|
cleaningModeEntity: vacuumEntities.cleaningModeEntity
|
|
177871
178215
|
};
|
|
177872
|
-
|
|
178216
|
+
logger199.debug(
|
|
177873
178217
|
`Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity} to ${entityId}`
|
|
177874
178218
|
);
|
|
177875
178219
|
}
|
|
@@ -177879,7 +178223,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177879
178223
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
177880
178224
|
suctionLevelEntity: vacuumEntities.suctionLevelEntity
|
|
177881
178225
|
};
|
|
177882
|
-
|
|
178226
|
+
logger199.debug(
|
|
177883
178227
|
`Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity} to ${entityId}`
|
|
177884
178228
|
);
|
|
177885
178229
|
}
|
|
@@ -177889,7 +178233,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177889
178233
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
177890
178234
|
mopIntensityEntity: vacuumEntities.mopIntensityEntity
|
|
177891
178235
|
};
|
|
177892
|
-
|
|
178236
|
+
logger199.debug(
|
|
177893
178237
|
`Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity} to ${entityId}`
|
|
177894
178238
|
);
|
|
177895
178239
|
}
|
|
@@ -177904,7 +178248,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177904
178248
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
177905
178249
|
cleanAreaRooms
|
|
177906
178250
|
};
|
|
177907
|
-
|
|
178251
|
+
logger199.debug(
|
|
177908
178252
|
`Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA for ${entityId}`
|
|
177909
178253
|
);
|
|
177910
178254
|
}
|
|
@@ -177925,7 +178269,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177925
178269
|
rooms: roomsObj
|
|
177926
178270
|
}
|
|
177927
178271
|
};
|
|
177928
|
-
|
|
178272
|
+
logger199.debug(
|
|
177929
178273
|
`Auto-detected ${valetudoRooms.length} Valetudo segments for ${entityId}`
|
|
177930
178274
|
);
|
|
177931
178275
|
} else {
|
|
@@ -177942,7 +178286,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177942
178286
|
rooms: roomsObj
|
|
177943
178287
|
}
|
|
177944
178288
|
};
|
|
177945
|
-
|
|
178289
|
+
logger199.debug(
|
|
177946
178290
|
`Auto-detected ${roborockRooms.length} Roborock rooms for ${entityId}`
|
|
177947
178291
|
);
|
|
177948
178292
|
}
|
|
@@ -177950,6 +178294,23 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177950
178294
|
}
|
|
177951
178295
|
}
|
|
177952
178296
|
}
|
|
178297
|
+
if (registry2.isAutoComposedDevicesEnabled() && effectiveMapping?.composedEntities && effectiveMapping.composedEntities.length > 0) {
|
|
178298
|
+
const composedAreaName = registry2.getAreaName(entityId);
|
|
178299
|
+
const composed = await UserComposedEndpoint.create({
|
|
178300
|
+
registry: registry2,
|
|
178301
|
+
primaryEntityId: entityId,
|
|
178302
|
+
mapping: effectiveMapping,
|
|
178303
|
+
composedEntities: effectiveMapping.composedEntities,
|
|
178304
|
+
customName: effectiveMapping?.customName,
|
|
178305
|
+
areaName: composedAreaName
|
|
178306
|
+
});
|
|
178307
|
+
if (composed) {
|
|
178308
|
+
return composed;
|
|
178309
|
+
}
|
|
178310
|
+
logger199.warn(
|
|
178311
|
+
`User composed device creation failed for ${entityId}, falling back to standalone`
|
|
178312
|
+
);
|
|
178313
|
+
}
|
|
177953
178314
|
if (registry2.isAutoComposedDevicesEnabled()) {
|
|
177954
178315
|
const attrs = state.attributes;
|
|
177955
178316
|
if (entityId.startsWith("sensor.") && attrs.device_class === SensorDeviceClass.temperature && (effectiveMapping?.humidityEntity || effectiveMapping?.pressureEntity)) {
|
|
@@ -177966,13 +178327,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177966
178327
|
return composed;
|
|
177967
178328
|
}
|
|
177968
178329
|
const resolvedMatterType = mapping?.matterDeviceType ?? (entityId.startsWith("fan.") ? "fan" : void 0);
|
|
177969
|
-
if (resolvedMatterType === "air_purifier"
|
|
177970
|
-
const temperatureEntityId = registry2.findTemperatureEntityForDevice(
|
|
177971
|
-
|
|
177972
|
-
);
|
|
177973
|
-
const humidityEntityId = registry2.findHumidityEntityForDevice(
|
|
177974
|
-
entity.device_id
|
|
177975
|
-
);
|
|
178330
|
+
if (resolvedMatterType === "air_purifier") {
|
|
178331
|
+
const temperatureEntityId = effectiveMapping?.temperatureEntity || (entity.device_id ? registry2.findTemperatureEntityForDevice(entity.device_id) : void 0);
|
|
178332
|
+
const humidityEntityId = effectiveMapping?.humidityEntity || (entity.device_id ? registry2.findHumidityEntityForDevice(entity.device_id) : void 0);
|
|
177976
178333
|
if (temperatureEntityId || humidityEntityId) {
|
|
177977
178334
|
const composedAreaName = registry2.getAreaName(entityId);
|
|
177978
178335
|
const composed = await ComposedAirPurifierEndpoint.create({
|
|
@@ -178017,7 +178374,8 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
178017
178374
|
const areaName = registry2.getAreaName(entityId);
|
|
178018
178375
|
const type = createLegacyEndpointType(payload, effectiveMapping, areaName, {
|
|
178019
178376
|
vacuumOnOff: registry2.isVacuumOnOffEnabled(),
|
|
178020
|
-
cleaningModeOptions
|
|
178377
|
+
cleaningModeOptions,
|
|
178378
|
+
pluginDomainMappings
|
|
178021
178379
|
});
|
|
178022
178380
|
if (!type) {
|
|
178023
178381
|
return;
|
|
@@ -178028,7 +178386,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
178028
178386
|
}
|
|
178029
178387
|
constructor(type, entityId, customName, mappedEntityIds) {
|
|
178030
178388
|
super(type, entityId, customName, mappedEntityIds);
|
|
178031
|
-
this.flushUpdate =
|
|
178389
|
+
this.flushUpdate = debounce5(this.flushPendingUpdate.bind(this), 50);
|
|
178032
178390
|
}
|
|
178033
178391
|
lastState;
|
|
178034
178392
|
pendingMappedChange = false;
|
|
@@ -178045,11 +178403,11 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
178045
178403
|
}
|
|
178046
178404
|
if (mappedChanged) {
|
|
178047
178405
|
this.pendingMappedChange = true;
|
|
178048
|
-
|
|
178406
|
+
logger199.debug(
|
|
178049
178407
|
`Mapped entity change detected for ${this.entityId}, forcing update`
|
|
178050
178408
|
);
|
|
178051
178409
|
}
|
|
178052
|
-
|
|
178410
|
+
logger199.debug(
|
|
178053
178411
|
`State update received for ${this.entityId}: state=${state.state}`
|
|
178054
178412
|
);
|
|
178055
178413
|
this.lastState = state;
|
|
@@ -178093,7 +178451,7 @@ import {
|
|
|
178093
178451
|
getCollection
|
|
178094
178452
|
} from "home-assistant-js-websocket";
|
|
178095
178453
|
import { atLeastHaVersion } from "home-assistant-js-websocket/dist/util.js";
|
|
178096
|
-
var
|
|
178454
|
+
var logger200 = Logger.get("SubscribeEntities");
|
|
178097
178455
|
function processEvent(store, updates) {
|
|
178098
178456
|
const state = { ...store.state };
|
|
178099
178457
|
if (updates.a) {
|
|
@@ -178119,7 +178477,7 @@ function processEvent(store, updates) {
|
|
|
178119
178477
|
for (const entityId in updates.c) {
|
|
178120
178478
|
let entityState = state[entityId];
|
|
178121
178479
|
if (!entityState) {
|
|
178122
|
-
|
|
178480
|
+
logger200.warn("Received state update for unknown entity", entityId);
|
|
178123
178481
|
continue;
|
|
178124
178482
|
}
|
|
178125
178483
|
entityState = { ...entityState };
|
|
@@ -178189,7 +178547,7 @@ var subscribeEntities = (conn, onChange, entityIds) => entitiesColl(conn, entity
|
|
|
178189
178547
|
|
|
178190
178548
|
// src/services/bridges/entity-isolation-service.ts
|
|
178191
178549
|
init_esm();
|
|
178192
|
-
var
|
|
178550
|
+
var logger201 = Logger.get("EntityIsolation");
|
|
178193
178551
|
var EntityIsolationServiceImpl = class {
|
|
178194
178552
|
isolatedEntities = /* @__PURE__ */ new Map();
|
|
178195
178553
|
isolationCallbacks = /* @__PURE__ */ new Map();
|
|
@@ -178254,13 +178612,13 @@ var EntityIsolationServiceImpl = class {
|
|
|
178254
178612
|
}
|
|
178255
178613
|
const parsed = this.parseEndpointPath(msg);
|
|
178256
178614
|
if (!parsed) {
|
|
178257
|
-
|
|
178615
|
+
logger201.warn("Could not parse entity from error:", msg);
|
|
178258
178616
|
return false;
|
|
178259
178617
|
}
|
|
178260
178618
|
const { bridgeId, entityName } = parsed;
|
|
178261
178619
|
const callback = this.isolationCallbacks.get(bridgeId);
|
|
178262
178620
|
if (!callback) {
|
|
178263
|
-
|
|
178621
|
+
logger201.warn(
|
|
178264
178622
|
`No isolation callback registered for bridge ${bridgeId}, entity: ${entityName}`
|
|
178265
178623
|
);
|
|
178266
178624
|
return false;
|
|
@@ -178271,14 +178629,14 @@ var EntityIsolationServiceImpl = class {
|
|
|
178271
178629
|
}
|
|
178272
178630
|
const reason = `${classification}. Entity isolated to protect bridge stability.`;
|
|
178273
178631
|
this.isolatedEntities.set(key, { entityId: entityName, reason });
|
|
178274
|
-
|
|
178632
|
+
logger201.warn(
|
|
178275
178633
|
`Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
|
|
178276
178634
|
);
|
|
178277
178635
|
try {
|
|
178278
178636
|
await callback(entityName);
|
|
178279
178637
|
return true;
|
|
178280
178638
|
} catch (e) {
|
|
178281
|
-
|
|
178639
|
+
logger201.error(`Failed to isolate entity ${entityName}:`, e);
|
|
178282
178640
|
return false;
|
|
178283
178641
|
}
|
|
178284
178642
|
}
|
|
@@ -178521,6 +178879,16 @@ var BridgeEndpointManager = class extends Service {
|
|
|
178521
178879
|
}
|
|
178522
178880
|
}
|
|
178523
178881
|
}
|
|
178882
|
+
getPluginDomainMappings() {
|
|
178883
|
+
if (!this.pluginManager) return void 0;
|
|
178884
|
+
const mappings = this.pluginManager.getDomainMappings();
|
|
178885
|
+
if (mappings.size === 0) return void 0;
|
|
178886
|
+
const result = /* @__PURE__ */ new Map();
|
|
178887
|
+
for (const [domain, mapping] of mappings) {
|
|
178888
|
+
result.set(domain, mapping.matterDeviceType);
|
|
178889
|
+
}
|
|
178890
|
+
return result;
|
|
178891
|
+
}
|
|
178524
178892
|
getEntityMapping(entityId) {
|
|
178525
178893
|
return this.mappingStorage.getMapping(this.bridgeId, entityId);
|
|
178526
178894
|
}
|
|
@@ -178577,16 +178945,20 @@ var BridgeEndpointManager = class extends Service {
|
|
|
178577
178945
|
this.entityIds = this.registry.entityIds;
|
|
178578
178946
|
if (this.registry.isAutoComposedDevicesEnabled()) {
|
|
178579
178947
|
for (const eid of this.entityIds) {
|
|
178580
|
-
if (!eid.startsWith("fan.")) continue;
|
|
178581
178948
|
const m = this.getEntityMapping(eid);
|
|
178949
|
+
if (m?.composedEntities) {
|
|
178950
|
+
for (const sub of m.composedEntities) {
|
|
178951
|
+
if (sub.entityId) {
|
|
178952
|
+
this.registry.markComposedSubEntityUsed(sub.entityId);
|
|
178953
|
+
}
|
|
178954
|
+
}
|
|
178955
|
+
}
|
|
178956
|
+
if (!eid.startsWith("fan.")) continue;
|
|
178582
178957
|
const matterType = m?.matterDeviceType ?? "fan";
|
|
178583
178958
|
if (matterType !== "air_purifier") continue;
|
|
178584
178959
|
const ent = this.registry.entity(eid);
|
|
178585
|
-
|
|
178586
|
-
const
|
|
178587
|
-
ent.device_id
|
|
178588
|
-
);
|
|
178589
|
-
const humId = this.registry.findHumidityEntityForDevice(ent.device_id);
|
|
178960
|
+
const tempId = m?.temperatureEntity || (ent?.device_id ? this.registry.findTemperatureEntityForDevice(ent.device_id) : void 0);
|
|
178961
|
+
const humId = m?.humidityEntity || (ent?.device_id ? this.registry.findHumidityEntityForDevice(ent.device_id) : void 0);
|
|
178590
178962
|
if (tempId) this.registry.markComposedSubEntityUsed(tempId);
|
|
178591
178963
|
if (humId) this.registry.markComposedSubEntityUsed(humId);
|
|
178592
178964
|
}
|
|
@@ -178657,6 +179029,12 @@ var BridgeEndpointManager = class extends Service {
|
|
|
178657
179029
|
this.log.debug(`Skipping disabled entity: ${entityId}`);
|
|
178658
179030
|
continue;
|
|
178659
179031
|
}
|
|
179032
|
+
if (this.registry.isAutoComposedDevicesEnabled() && this.registry.isComposedSubEntityUsed(entityId)) {
|
|
179033
|
+
this.log.debug(
|
|
179034
|
+
`Skipping ${entityId} \u2014 already part of a composed device`
|
|
179035
|
+
);
|
|
179036
|
+
continue;
|
|
179037
|
+
}
|
|
178660
179038
|
if (entityId.length > MAX_ENTITY_ID_LENGTH) {
|
|
178661
179039
|
const reason = `Entity ID too long (${entityId.length} chars, max ${MAX_ENTITY_ID_LENGTH}). This would cause filesystem errors.`;
|
|
178662
179040
|
this.log.warn(`Skipping entity: ${entityId}. Reason: ${reason}`);
|
|
@@ -178666,10 +179044,12 @@ var BridgeEndpointManager = class extends Service {
|
|
|
178666
179044
|
let endpoint = existingEndpoints.find((e) => e.entityId === entityId);
|
|
178667
179045
|
if (!endpoint) {
|
|
178668
179046
|
try {
|
|
179047
|
+
const domainMappings = this.getPluginDomainMappings();
|
|
178669
179048
|
endpoint = await LegacyEndpoint.create(
|
|
178670
179049
|
this.registry,
|
|
178671
179050
|
entityId,
|
|
178672
|
-
mapping
|
|
179051
|
+
mapping,
|
|
179052
|
+
domainMappings
|
|
178673
179053
|
);
|
|
178674
179054
|
} catch (e) {
|
|
178675
179055
|
const reason = this.extractErrorReason(e);
|
|
@@ -179129,8 +179509,39 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
179129
179509
|
);
|
|
179130
179510
|
return [];
|
|
179131
179511
|
}
|
|
179512
|
+
let validSegmentIds;
|
|
179513
|
+
try {
|
|
179514
|
+
const segmentsResponse = await this.client.connection.sendMessagePromise({
|
|
179515
|
+
type: "vacuum/get_segments",
|
|
179516
|
+
entity_id: entityId
|
|
179517
|
+
});
|
|
179518
|
+
if (Array.isArray(segmentsResponse)) {
|
|
179519
|
+
validSegmentIds = new Set(segmentsResponse.map((s) => s.id));
|
|
179520
|
+
_BridgeRegistry.cleanAreaLogger.debug(
|
|
179521
|
+
`${entityId}: Current vacuum segments: ${[...validSegmentIds].join(", ")}`
|
|
179522
|
+
);
|
|
179523
|
+
}
|
|
179524
|
+
} catch {
|
|
179525
|
+
_BridgeRegistry.cleanAreaLogger.debug(
|
|
179526
|
+
`${entityId}: vacuum/get_segments not available, skipping stale entry detection`
|
|
179527
|
+
);
|
|
179528
|
+
}
|
|
179132
179529
|
const rooms = [];
|
|
179133
179530
|
for (const haAreaId of Object.keys(areaMapping)) {
|
|
179531
|
+
const segments = areaMapping[haAreaId];
|
|
179532
|
+
if (!segments || segments.length === 0) {
|
|
179533
|
+
_BridgeRegistry.cleanAreaLogger.debug(
|
|
179534
|
+
`${entityId}: Skipping HA area ${haAreaId} \u2014 no segments mapped`
|
|
179535
|
+
);
|
|
179536
|
+
continue;
|
|
179537
|
+
}
|
|
179538
|
+
if (validSegmentIds && !segments.some((sid) => validSegmentIds.has(sid))) {
|
|
179539
|
+
const areaName2 = this.registry.areas.get(haAreaId) ?? haAreaId;
|
|
179540
|
+
_BridgeRegistry.cleanAreaLogger.info(
|
|
179541
|
+
`${entityId}: Skipping stale HA area "${areaName2}" (${haAreaId}) \u2014 segments [${segments.join(", ")}] no longer exist on vacuum`
|
|
179542
|
+
);
|
|
179543
|
+
continue;
|
|
179544
|
+
}
|
|
179134
179545
|
const areaName = this.registry.areas.get(haAreaId) ?? haAreaId;
|
|
179135
179546
|
rooms.push({
|
|
179136
179547
|
areaId: hashAreaId(haAreaId),
|
|
@@ -179396,12 +179807,13 @@ function hashAreaId(areaId) {
|
|
|
179396
179807
|
// src/services/bridges/server-mode-bridge.ts
|
|
179397
179808
|
init_dist();
|
|
179398
179809
|
var AUTO_FORCE_SYNC_INTERVAL_MS2 = 9e4;
|
|
179810
|
+
var DEAD_SESSION_TIMEOUT_MS2 = 6e4;
|
|
179399
179811
|
var ServerModeBridge = class {
|
|
179400
|
-
constructor(
|
|
179812
|
+
constructor(logger204, dataProvider, endpointManager, server) {
|
|
179401
179813
|
this.dataProvider = dataProvider;
|
|
179402
179814
|
this.endpointManager = endpointManager;
|
|
179403
179815
|
this.server = server;
|
|
179404
|
-
this.log =
|
|
179816
|
+
this.log = logger204.get(`ServerModeBridge / ${dataProvider.id}`);
|
|
179405
179817
|
}
|
|
179406
179818
|
log;
|
|
179407
179819
|
status = {
|
|
@@ -179412,6 +179824,8 @@ var ServerModeBridge = class {
|
|
|
179412
179824
|
// broadcast updates via WebSocket so the frontend sees every transition.
|
|
179413
179825
|
onStatusChange;
|
|
179414
179826
|
autoForceSyncTimer = null;
|
|
179827
|
+
deadSessionTimer = null;
|
|
179828
|
+
staleSessionTimers = /* @__PURE__ */ new Map();
|
|
179415
179829
|
warmStartTimer = null;
|
|
179416
179830
|
// Tracks the last synced state JSON per entity to avoid pushing unchanged states.
|
|
179417
179831
|
lastSyncedState;
|
|
@@ -179593,6 +180007,33 @@ ${e?.toString()}`);
|
|
|
179593
180007
|
this.log.warn(
|
|
179594
180008
|
`All subscriptions lost \u2014 ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
|
|
179595
180009
|
);
|
|
180010
|
+
if (!this.deadSessionTimer) {
|
|
180011
|
+
this.deadSessionTimer = setTimeout(() => {
|
|
180012
|
+
this.deadSessionTimer = null;
|
|
180013
|
+
this.closeDeadSessions();
|
|
180014
|
+
}, DEAD_SESSION_TIMEOUT_MS2);
|
|
180015
|
+
this.log.info(
|
|
180016
|
+
`Scheduled dead session cleanup in ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s`
|
|
180017
|
+
);
|
|
180018
|
+
}
|
|
180019
|
+
} else if (totalSubs > 0 && this.deadSessionTimer) {
|
|
180020
|
+
clearTimeout(this.deadSessionTimer);
|
|
180021
|
+
this.deadSessionTimer = null;
|
|
180022
|
+
this.log.info(
|
|
180023
|
+
"Subscriptions recovered, canceled dead session cleanup"
|
|
180024
|
+
);
|
|
180025
|
+
}
|
|
180026
|
+
if (session.subscriptions.size === 0 && !this.staleSessionTimers.has(session.id)) {
|
|
180027
|
+
this.staleSessionTimers.set(
|
|
180028
|
+
session.id,
|
|
180029
|
+
setTimeout(() => {
|
|
180030
|
+
this.staleSessionTimers.delete(session.id);
|
|
180031
|
+
this.closeStaleSession(session.id);
|
|
180032
|
+
}, DEAD_SESSION_TIMEOUT_MS2)
|
|
180033
|
+
);
|
|
180034
|
+
} else if (session.subscriptions.size > 0 && this.staleSessionTimers.has(session.id)) {
|
|
180035
|
+
clearTimeout(this.staleSessionTimers.get(session.id));
|
|
180036
|
+
this.staleSessionTimers.delete(session.id);
|
|
179596
180037
|
}
|
|
179597
180038
|
};
|
|
179598
180039
|
sessionManager.subscriptionsChanged.on(this.sessionDiagHandler);
|
|
@@ -179621,6 +180062,62 @@ ${e?.toString()}`);
|
|
|
179621
180062
|
} catch {
|
|
179622
180063
|
}
|
|
179623
180064
|
}
|
|
180065
|
+
closeStaleSession(sessionId) {
|
|
180066
|
+
try {
|
|
180067
|
+
const sessionManager = this.server.env.get(SessionManager);
|
|
180068
|
+
for (const s of [...sessionManager.sessions]) {
|
|
180069
|
+
if (s.id === sessionId && !s.isClosing && s.subscriptions.size === 0) {
|
|
180070
|
+
this.log.warn(
|
|
180071
|
+
`Closing stale session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s)`
|
|
180072
|
+
);
|
|
180073
|
+
s.initiateClose().catch(() => {
|
|
180074
|
+
return s.initiateForceClose();
|
|
180075
|
+
}).catch(() => {
|
|
180076
|
+
}).finally(() => this.triggerMdnsReAnnounce());
|
|
180077
|
+
break;
|
|
180078
|
+
}
|
|
180079
|
+
}
|
|
180080
|
+
} catch {
|
|
180081
|
+
}
|
|
180082
|
+
}
|
|
180083
|
+
closeDeadSessions() {
|
|
180084
|
+
try {
|
|
180085
|
+
const sessionManager = this.server.env.get(SessionManager);
|
|
180086
|
+
const sessions = [...sessionManager.sessions];
|
|
180087
|
+
const closes = [];
|
|
180088
|
+
for (const s of sessions) {
|
|
180089
|
+
if (!s.isClosing && s.subscriptions.size === 0) {
|
|
180090
|
+
this.log.warn(
|
|
180091
|
+
`Closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s)`
|
|
180092
|
+
);
|
|
180093
|
+
closes.push(
|
|
180094
|
+
s.initiateClose().catch(() => {
|
|
180095
|
+
return s.initiateForceClose();
|
|
180096
|
+
})
|
|
180097
|
+
);
|
|
180098
|
+
}
|
|
180099
|
+
}
|
|
180100
|
+
if (closes.length > 0) {
|
|
180101
|
+
Promise.allSettled(closes).then(() => this.triggerMdnsReAnnounce());
|
|
180102
|
+
}
|
|
180103
|
+
} catch {
|
|
180104
|
+
}
|
|
180105
|
+
}
|
|
180106
|
+
/**
|
|
180107
|
+
* Force a fresh mDNS operational advertisement after session cleanup.
|
|
180108
|
+
* matter.js DeviceAdvertiser only re-announces when a subscription is
|
|
180109
|
+
* canceled BY THE PEER. When the server cancels after 3 delivery
|
|
180110
|
+
* timeouts, no re-announcement happens and the controller may not
|
|
180111
|
+
* realize it should reconnect (#266).
|
|
180112
|
+
*/
|
|
180113
|
+
triggerMdnsReAnnounce() {
|
|
180114
|
+
try {
|
|
180115
|
+
const advertiser = this.server.env.get(DeviceAdvertiser);
|
|
180116
|
+
advertiser.restartAdvertisement();
|
|
180117
|
+
this.log.info("Triggered mDNS re-announcement after session cleanup");
|
|
180118
|
+
} catch {
|
|
180119
|
+
}
|
|
180120
|
+
}
|
|
179624
180121
|
unwireSessionDiagnostics() {
|
|
179625
180122
|
try {
|
|
179626
180123
|
const sessionManager = this.server.env.get(SessionManager);
|
|
@@ -179638,6 +180135,14 @@ ${e?.toString()}`);
|
|
|
179638
180135
|
this.sessionDiagHandler = void 0;
|
|
179639
180136
|
this.sessionAddedHandler = void 0;
|
|
179640
180137
|
this.sessionDeletedHandler = void 0;
|
|
180138
|
+
if (this.deadSessionTimer) {
|
|
180139
|
+
clearTimeout(this.deadSessionTimer);
|
|
180140
|
+
this.deadSessionTimer = null;
|
|
180141
|
+
}
|
|
180142
|
+
for (const timer of this.staleSessionTimers.values()) {
|
|
180143
|
+
clearTimeout(timer);
|
|
180144
|
+
}
|
|
180145
|
+
this.staleSessionTimers.clear();
|
|
179641
180146
|
}
|
|
179642
180147
|
stopAutoForceSync() {
|
|
179643
180148
|
if (this.autoForceSyncTimer) {
|
|
@@ -179753,7 +180258,7 @@ init_service();
|
|
|
179753
180258
|
// src/matter/endpoints/server-mode-vacuum-endpoint.ts
|
|
179754
180259
|
init_esm();
|
|
179755
180260
|
init_home_assistant_entity_behavior();
|
|
179756
|
-
import
|
|
180261
|
+
import debounce6 from "debounce";
|
|
179757
180262
|
|
|
179758
180263
|
// src/matter/endpoints/legacy/vacuum/server-mode-vacuum-device.ts
|
|
179759
180264
|
init_home_assistant_entity_behavior();
|
|
@@ -179817,7 +180322,7 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
|
|
|
179817
180322
|
}
|
|
179818
180323
|
|
|
179819
180324
|
// src/matter/endpoints/server-mode-vacuum-endpoint.ts
|
|
179820
|
-
var
|
|
180325
|
+
var logger202 = Logger.get("ServerModeVacuumEndpoint");
|
|
179821
180326
|
var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEndpoint {
|
|
179822
180327
|
static async create(registry2, entityId, mapping) {
|
|
179823
180328
|
const deviceRegistry = registry2.deviceOf(entityId);
|
|
@@ -179827,7 +180332,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179827
180332
|
return void 0;
|
|
179828
180333
|
}
|
|
179829
180334
|
let effectiveMapping = mapping;
|
|
179830
|
-
|
|
180335
|
+
logger202.info(
|
|
179831
180336
|
`${entityId}: device_id=${entity.device_id}, manualBattery=${mapping?.batteryEntity ?? "none"}`
|
|
179832
180337
|
);
|
|
179833
180338
|
if (entity.device_id) {
|
|
@@ -179842,15 +180347,15 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179842
180347
|
batteryEntity: batteryEntityId
|
|
179843
180348
|
};
|
|
179844
180349
|
registry2.markBatteryEntityUsed(batteryEntityId);
|
|
179845
|
-
|
|
180350
|
+
logger202.info(`${entityId}: Auto-assigned battery ${batteryEntityId}`);
|
|
179846
180351
|
} else {
|
|
179847
180352
|
const attrs = state.attributes;
|
|
179848
180353
|
if (attrs.battery_level != null || attrs.battery != null) {
|
|
179849
|
-
|
|
180354
|
+
logger202.info(
|
|
179850
180355
|
`${entityId}: No battery entity found, using battery attribute from vacuum state`
|
|
179851
180356
|
);
|
|
179852
180357
|
} else {
|
|
179853
|
-
|
|
180358
|
+
logger202.warn(
|
|
179854
180359
|
`${entityId}: No battery entity found for device ${entity.device_id}`
|
|
179855
180360
|
);
|
|
179856
180361
|
}
|
|
@@ -179865,7 +180370,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179865
180370
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
179866
180371
|
cleaningModeEntity: vacuumEntities.cleaningModeEntity
|
|
179867
180372
|
};
|
|
179868
|
-
|
|
180373
|
+
logger202.info(
|
|
179869
180374
|
`${entityId}: Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity}`
|
|
179870
180375
|
);
|
|
179871
180376
|
}
|
|
@@ -179875,7 +180380,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179875
180380
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
179876
180381
|
suctionLevelEntity: vacuumEntities.suctionLevelEntity
|
|
179877
180382
|
};
|
|
179878
|
-
|
|
180383
|
+
logger202.info(
|
|
179879
180384
|
`${entityId}: Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity}`
|
|
179880
180385
|
);
|
|
179881
180386
|
}
|
|
@@ -179885,7 +180390,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179885
180390
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
179886
180391
|
mopIntensityEntity: vacuumEntities.mopIntensityEntity
|
|
179887
180392
|
};
|
|
179888
|
-
|
|
180393
|
+
logger202.info(
|
|
179889
180394
|
`${entityId}: Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity}`
|
|
179890
180395
|
);
|
|
179891
180396
|
}
|
|
@@ -179900,7 +180405,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179900
180405
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
179901
180406
|
cleanAreaRooms
|
|
179902
180407
|
};
|
|
179903
|
-
|
|
180408
|
+
logger202.info(
|
|
179904
180409
|
`${entityId}: Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA`
|
|
179905
180410
|
);
|
|
179906
180411
|
}
|
|
@@ -179921,7 +180426,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179921
180426
|
rooms: roomsObj
|
|
179922
180427
|
}
|
|
179923
180428
|
};
|
|
179924
|
-
|
|
180429
|
+
logger202.info(
|
|
179925
180430
|
`${entityId}: Auto-detected ${valetudoRooms.length} Valetudo segments`
|
|
179926
180431
|
);
|
|
179927
180432
|
} else {
|
|
@@ -179938,14 +180443,14 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179938
180443
|
rooms: roomsObj
|
|
179939
180444
|
}
|
|
179940
180445
|
};
|
|
179941
|
-
|
|
180446
|
+
logger202.info(
|
|
179942
180447
|
`${entityId}: Auto-detected ${roborockRooms.length} Roborock rooms`
|
|
179943
180448
|
);
|
|
179944
180449
|
}
|
|
179945
180450
|
}
|
|
179946
180451
|
}
|
|
179947
180452
|
} else {
|
|
179948
|
-
|
|
180453
|
+
logger202.warn(`${entityId}: No device_id \u2014 cannot auto-assign battery`);
|
|
179949
180454
|
}
|
|
179950
180455
|
const payload = {
|
|
179951
180456
|
entity_id: entityId,
|
|
@@ -179995,7 +180500,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179995
180500
|
flushUpdate;
|
|
179996
180501
|
constructor(type, entityId, customName, mappedEntityIds) {
|
|
179997
180502
|
super(type, entityId, customName, mappedEntityIds);
|
|
179998
|
-
this.flushUpdate =
|
|
180503
|
+
this.flushUpdate = debounce6(this.flushPendingUpdate.bind(this), 50);
|
|
179999
180504
|
}
|
|
180000
180505
|
async delete() {
|
|
180001
180506
|
this.flushUpdate.clear();
|
|
@@ -180009,11 +180514,11 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
180009
180514
|
}
|
|
180010
180515
|
if (mappedChanged) {
|
|
180011
180516
|
this.pendingMappedChange = true;
|
|
180012
|
-
|
|
180517
|
+
logger202.debug(
|
|
180013
180518
|
`Mapped entity change detected for ${this.entityId}, forcing update`
|
|
180014
180519
|
);
|
|
180015
180520
|
}
|
|
180016
|
-
|
|
180521
|
+
logger202.debug(
|
|
180017
180522
|
`State update received for ${this.entityId}: state=${state.state}`
|
|
180018
180523
|
);
|
|
180019
180524
|
this.lastState = state;
|
|
@@ -180427,10 +180932,10 @@ var BridgeEnvironmentFactory = class extends BridgeFactory {
|
|
|
180427
180932
|
// src/core/ioc/app-environment.ts
|
|
180428
180933
|
var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
180429
180934
|
constructor(rootEnv, options) {
|
|
180430
|
-
const
|
|
180935
|
+
const logger204 = rootEnv.get(LoggerService);
|
|
180431
180936
|
super({
|
|
180432
180937
|
id: "App",
|
|
180433
|
-
log:
|
|
180938
|
+
log: logger204.get("AppContainer"),
|
|
180434
180939
|
parent: rootEnv
|
|
180435
180940
|
});
|
|
180436
180941
|
this.options = options;
|
|
@@ -180443,8 +180948,8 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
180443
180948
|
}
|
|
180444
180949
|
construction;
|
|
180445
180950
|
async init() {
|
|
180446
|
-
const
|
|
180447
|
-
this.set(LoggerService,
|
|
180951
|
+
const logger204 = this.get(LoggerService);
|
|
180952
|
+
this.set(LoggerService, logger204);
|
|
180448
180953
|
this.set(AppStorage, new AppStorage(await this.load(StorageService)));
|
|
180449
180954
|
this.set(BridgeStorage, new BridgeStorage(await this.load(AppStorage)));
|
|
180450
180955
|
this.set(
|
|
@@ -180461,7 +180966,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
180461
180966
|
);
|
|
180462
180967
|
this.set(
|
|
180463
180968
|
HomeAssistantClient,
|
|
180464
|
-
new HomeAssistantClient(
|
|
180969
|
+
new HomeAssistantClient(logger204, this.options.homeAssistant)
|
|
180465
180970
|
);
|
|
180466
180971
|
this.set(
|
|
180467
180972
|
HomeAssistantConfig,
|
|
@@ -180469,7 +180974,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
180469
180974
|
);
|
|
180470
180975
|
this.set(
|
|
180471
180976
|
HomeAssistantActions,
|
|
180472
|
-
new HomeAssistantActions(
|
|
180977
|
+
new HomeAssistantActions(logger204, await this.load(HomeAssistantClient))
|
|
180473
180978
|
);
|
|
180474
180979
|
this.set(
|
|
180475
180980
|
HomeAssistantRegistry,
|
|
@@ -180505,7 +181010,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
180505
181010
|
this.set(
|
|
180506
181011
|
WebApi,
|
|
180507
181012
|
new WebApi(
|
|
180508
|
-
|
|
181013
|
+
logger204,
|
|
180509
181014
|
await this.load(BridgeService),
|
|
180510
181015
|
await this.load(HomeAssistantClient),
|
|
180511
181016
|
await this.load(HomeAssistantRegistry),
|
|
@@ -180531,7 +181036,7 @@ init_nodejs();
|
|
|
180531
181036
|
init_level_control();
|
|
180532
181037
|
|
|
180533
181038
|
// src/matter/patches/patch-level-control-tlv.ts
|
|
180534
|
-
var
|
|
181039
|
+
var logger203 = Logger.get("PatchLevelControlTlv");
|
|
180535
181040
|
function patchLevelControlTlv() {
|
|
180536
181041
|
let patched = 0;
|
|
180537
181042
|
const moveToLevelFields = LevelControl3.TlvMoveToLevelRequest.fieldDefinitions;
|
|
@@ -180545,11 +181050,11 @@ function patchLevelControlTlv() {
|
|
|
180545
181050
|
patched++;
|
|
180546
181051
|
}
|
|
180547
181052
|
if (patched > 0) {
|
|
180548
|
-
|
|
181053
|
+
logger203.info(
|
|
180549
181054
|
`Patched ${patched} LevelControl TLV schema(s): transitionTime is now optional (Google Home compatibility)`
|
|
180550
181055
|
);
|
|
180551
181056
|
} else {
|
|
180552
|
-
|
|
181057
|
+
logger203.warn(
|
|
180553
181058
|
"Failed to patch LevelControl TLV schemas \u2014 field definitions not found. Google Home brightness adjustment may not work."
|
|
180554
181059
|
);
|
|
180555
181060
|
}
|
|
@@ -180587,8 +181092,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
180587
181092
|
if (shouldSuppressError(reason)) {
|
|
180588
181093
|
return;
|
|
180589
181094
|
}
|
|
180590
|
-
console.error("Unhandled rejection:", reason);
|
|
180591
|
-
process.exit(1);
|
|
181095
|
+
console.error("Unhandled rejection (process continuing):", reason);
|
|
180592
181096
|
});
|
|
180593
181097
|
function registerFinalErrorHandlers() {
|
|
180594
181098
|
process.removeAllListeners("uncaughtException");
|
|
@@ -180614,8 +181118,7 @@ function registerFinalErrorHandlers() {
|
|
|
180614
181118
|
console.warn("Suppressed Matter.js internal error:", reason);
|
|
180615
181119
|
return;
|
|
180616
181120
|
}
|
|
180617
|
-
console.error("Unhandled rejection:", reason);
|
|
180618
|
-
process.exit(1);
|
|
181121
|
+
console.error("Unhandled rejection (process continuing):", reason);
|
|
180619
181122
|
});
|
|
180620
181123
|
}
|
|
180621
181124
|
async function startHandler(startOptions, webUiDist) {
|