@riddix/hamh 2.0.41 → 2.0.43
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 +62 -33
- package/dist/backend/cli.js +309 -181
- package/dist/frontend/assets/{index-CExdZqNu.js → index-eVn09I6J.js} +154 -154
- package/dist/frontend/index.html +1 -1
- package/package.json +4 -4
package/dist/backend/cli.js
CHANGED
|
@@ -146781,7 +146781,7 @@ var init_bridge_config_schema = __esm({
|
|
|
146781
146781
|
},
|
|
146782
146782
|
autoComposedDevices: {
|
|
146783
146783
|
title: "Auto Composed Devices",
|
|
146784
|
-
description: "Master toggle: combine related entities from the same Home Assistant device into a single Matter endpoint. Turns on battery, humidity, pressure, power, and energy auto-mapping at once
|
|
146784
|
+
description: "Master toggle: combine related entities from the same Home Assistant device into a single Matter endpoint. Turns on battery, humidity, pressure, power, and energy auto-mapping at once, a Shelly Plug shows up as one device with power monitoring instead of several siblings.",
|
|
146785
146785
|
type: "boolean",
|
|
146786
146786
|
default: false
|
|
146787
146787
|
},
|
|
@@ -146799,13 +146799,13 @@ var init_bridge_config_schema = __esm({
|
|
|
146799
146799
|
},
|
|
146800
146800
|
preferEntityRegistryName: {
|
|
146801
146801
|
title: "Prefer Entity Registry Name (HA 2026.4 workaround)",
|
|
146802
|
-
description: "Use the entity registry name (or original_name) as nodeLabel instead of the composed friendly_name. Since Home Assistant 2026.4, friendly_name is prefixed with the device name, which breaks voice commands that relied on the short entity name. Resolution order: customName \u2192 registry name \u2192 registry original_name \u2192 friendly_name \u2192 entity_id. Matter has no alias concept
|
|
146802
|
+
description: "Use the entity registry name (or original_name) as nodeLabel instead of the composed friendly_name. Since Home Assistant 2026.4, friendly_name is prefixed with the device name, which breaks voice commands that relied on the short entity name. Resolution order: customName \u2192 registry name \u2192 registry original_name \u2192 friendly_name \u2192 entity_id. Matter has no alias concept, this only changes which single name is reported.",
|
|
146803
146803
|
type: "boolean",
|
|
146804
146804
|
default: false
|
|
146805
146805
|
},
|
|
146806
146806
|
vacuumOnOff: {
|
|
146807
146807
|
title: "Vacuum: Include OnOff Cluster (Alexa)",
|
|
146808
|
-
description: "Add an OnOff cluster to robot vacuum endpoints. Alexa REQUIRES this (PowerController) to show robotic vacuums in the app. Without it, Alexa commissions the device but never displays it. In Server Mode this is enabled automatically
|
|
146808
|
+
description: "Add an OnOff cluster to robot vacuum endpoints. Alexa REQUIRES this (PowerController) to show robotic vacuums in the app. Without it, Alexa commissions the device but never displays it. In Server Mode this is enabled automatically, only check this for bridge mode. WARNING: OnOff is NOT part of the Matter RVC device type specification. Enabling this may break Apple Home (shows 'Updating') and Google Home.",
|
|
146809
146809
|
type: "boolean"
|
|
146810
146810
|
},
|
|
146811
146811
|
alexaPreserveBrightnessOnTurnOn: {
|
|
@@ -147874,6 +147874,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
147874
147874
|
valetudoIdentifier: config10.valetudoIdentifier,
|
|
147875
147875
|
coverSwapOpenClose: config10.coverSwapOpenClose,
|
|
147876
147876
|
disableClimateOnOff: config10.disableClimateOnOff,
|
|
147877
|
+
disableClimateFanControl: config10.disableClimateFanControl,
|
|
147877
147878
|
customServiceAreas: config10.customServiceAreas,
|
|
147878
147879
|
customFanSpeedTags: config10.customFanSpeedTags,
|
|
147879
147880
|
composedEntities: config10.composedEntities
|
|
@@ -148020,6 +148021,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
148020
148021
|
valetudoIdentifier: config10.valetudoIdentifier,
|
|
148021
148022
|
coverSwapOpenClose: config10.coverSwapOpenClose,
|
|
148022
148023
|
disableClimateOnOff: config10.disableClimateOnOff,
|
|
148024
|
+
disableClimateFanControl: config10.disableClimateFanControl,
|
|
148023
148025
|
customServiceAreas: config10.customServiceAreas,
|
|
148024
148026
|
customFanSpeedTags: config10.customFanSpeedTags,
|
|
148025
148027
|
composedEntities: config10.composedEntities
|
|
@@ -148594,7 +148596,14 @@ function addLogEntry(entry) {
|
|
|
148594
148596
|
function logsApi(_logger) {
|
|
148595
148597
|
const router = express5.Router();
|
|
148596
148598
|
router.get("/", (req, res) => {
|
|
148597
|
-
const {
|
|
148599
|
+
const {
|
|
148600
|
+
level,
|
|
148601
|
+
search,
|
|
148602
|
+
category,
|
|
148603
|
+
facility,
|
|
148604
|
+
limit = "100",
|
|
148605
|
+
offset = "0"
|
|
148606
|
+
} = req.query;
|
|
148598
148607
|
const limitNum = Math.min(
|
|
148599
148608
|
500,
|
|
148600
148609
|
Math.max(1, parseInt(limit, 10) || 100)
|
|
@@ -148605,6 +148614,18 @@ function logsApi(_logger) {
|
|
|
148605
148614
|
const levels = level.split(",").map((l) => l.toLowerCase().trim());
|
|
148606
148615
|
entries = entries.filter((e) => levels.includes(e.level.toLowerCase()));
|
|
148607
148616
|
}
|
|
148617
|
+
if (category && typeof category === "string") {
|
|
148618
|
+
const cats = category.split(",").map((c) => c.toLowerCase().trim());
|
|
148619
|
+
entries = entries.filter(
|
|
148620
|
+
(e) => e.category != null && cats.includes(e.category.toLowerCase())
|
|
148621
|
+
);
|
|
148622
|
+
}
|
|
148623
|
+
if (facility && typeof facility === "string") {
|
|
148624
|
+
const facLower = facility.toLowerCase();
|
|
148625
|
+
entries = entries.filter(
|
|
148626
|
+
(e) => e.facility?.toLowerCase().includes(facLower)
|
|
148627
|
+
);
|
|
148628
|
+
}
|
|
148608
148629
|
if (search && typeof search === "string") {
|
|
148609
148630
|
const searchLower = search.toLowerCase();
|
|
148610
148631
|
entries = entries.filter(
|
|
@@ -148840,6 +148861,7 @@ function entityMappingApi(mappingStorage) {
|
|
|
148840
148861
|
valetudoIdentifier: body.valetudoIdentifier,
|
|
148841
148862
|
coverSwapOpenClose: body.coverSwapOpenClose,
|
|
148842
148863
|
disableClimateOnOff: body.disableClimateOnOff,
|
|
148864
|
+
disableClimateFanControl: body.disableClimateFanControl,
|
|
148843
148865
|
composedEntities: body.composedEntities
|
|
148844
148866
|
};
|
|
148845
148867
|
const config10 = await mappingStorage.setMapping(request);
|
|
@@ -149303,7 +149325,8 @@ function configToProfileEntry(config10) {
|
|
|
149303
149325
|
customFanSpeedTags: config10.customFanSpeedTags,
|
|
149304
149326
|
valetudoIdentifier: config10.valetudoIdentifier,
|
|
149305
149327
|
coverSwapOpenClose: config10.coverSwapOpenClose,
|
|
149306
|
-
disableClimateOnOff: config10.disableClimateOnOff
|
|
149328
|
+
disableClimateOnOff: config10.disableClimateOnOff,
|
|
149329
|
+
disableClimateFanControl: config10.disableClimateFanControl
|
|
149307
149330
|
};
|
|
149308
149331
|
}
|
|
149309
149332
|
function mappingProfileApi(mappingStorage) {
|
|
@@ -149425,7 +149448,8 @@ function mappingProfileApi(mappingStorage) {
|
|
|
149425
149448
|
customFanSpeedTags: entry.customFanSpeedTags,
|
|
149426
149449
|
valetudoIdentifier: entry.valetudoIdentifier,
|
|
149427
149450
|
coverSwapOpenClose: entry.coverSwapOpenClose,
|
|
149428
|
-
disableClimateOnOff: entry.disableClimateOnOff
|
|
149451
|
+
disableClimateOnOff: entry.disableClimateOnOff,
|
|
149452
|
+
disableClimateFanControl: entry.disableClimateFanControl
|
|
149429
149453
|
});
|
|
149430
149454
|
applied++;
|
|
149431
149455
|
} catch (e) {
|
|
@@ -151603,6 +151627,17 @@ init_esm7();
|
|
|
151603
151627
|
|
|
151604
151628
|
// src/core/app/logger.ts
|
|
151605
151629
|
init_esm();
|
|
151630
|
+
var MATTER_TRAFFIC_FACILITIES = /* @__PURE__ */ new Set([
|
|
151631
|
+
"InteractionServer",
|
|
151632
|
+
"MessageExchange",
|
|
151633
|
+
"MessageChannel",
|
|
151634
|
+
"ServerSubscription",
|
|
151635
|
+
"IncomingInteractionServerMessenger",
|
|
151636
|
+
"ExchangeManager"
|
|
151637
|
+
]);
|
|
151638
|
+
function categoryFor(facility) {
|
|
151639
|
+
return MATTER_TRAFFIC_FACILITIES.has(facility) ? "matter-traffic" : void 0;
|
|
151640
|
+
}
|
|
151606
151641
|
function logLevelFromString(level) {
|
|
151607
151642
|
const customNames = {
|
|
151608
151643
|
SILLY: -1 /* SILLY */
|
|
@@ -151648,6 +151683,26 @@ var LoggerService = class {
|
|
|
151648
151683
|
MessageExchange: resolvedProtocolLevel
|
|
151649
151684
|
};
|
|
151650
151685
|
Logger.format = options.disableColors ? LogFormat.PLAIN : LogFormat.ANSI;
|
|
151686
|
+
const destinationLevel = this.customLogLevelMapping[this._level] ?? this._level;
|
|
151687
|
+
Logger.destinations["hamh-buffer"] = LogDestination({
|
|
151688
|
+
name: "hamh-buffer",
|
|
151689
|
+
level: destinationLevel,
|
|
151690
|
+
facilityLevels: {
|
|
151691
|
+
MessageChannel: resolvedProtocolLevel,
|
|
151692
|
+
MessageExchange: resolvedProtocolLevel
|
|
151693
|
+
},
|
|
151694
|
+
write: (text, message) => {
|
|
151695
|
+
const category = categoryFor(message.facility);
|
|
151696
|
+
if (!category) return;
|
|
151697
|
+
addLogEntry({
|
|
151698
|
+
timestamp: message.now.toISOString(),
|
|
151699
|
+
level: logLevelToString(message.level).toLowerCase(),
|
|
151700
|
+
message: text,
|
|
151701
|
+
facility: message.facility,
|
|
151702
|
+
category
|
|
151703
|
+
});
|
|
151704
|
+
}
|
|
151705
|
+
});
|
|
151651
151706
|
}
|
|
151652
151707
|
get(nameOrService) {
|
|
151653
151708
|
let name;
|
|
@@ -152743,7 +152798,7 @@ var HomeAssistantRegistry = class extends Service {
|
|
|
152743
152798
|
let refreshing = false;
|
|
152744
152799
|
this.autoRefresh = setInterval(async () => {
|
|
152745
152800
|
if (refreshing) {
|
|
152746
|
-
logger146.debug("Skipping registry refresh
|
|
152801
|
+
logger146.debug("Skipping registry refresh, previous tick still running");
|
|
152747
152802
|
return;
|
|
152748
152803
|
}
|
|
152749
152804
|
refreshing = true;
|
|
@@ -153295,9 +153350,10 @@ var EntityMappingStorage = class extends Service {
|
|
|
153295
153350
|
valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0,
|
|
153296
153351
|
coverSwapOpenClose: request.coverSwapOpenClose || void 0,
|
|
153297
153352
|
disableClimateOnOff: request.disableClimateOnOff || void 0,
|
|
153353
|
+
disableClimateFanControl: request.disableClimateFanControl || void 0,
|
|
153298
153354
|
composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
|
|
153299
153355
|
};
|
|
153300
|
-
if (!config10.matterDeviceType && !config10.customName && !config10.customProductName && !config10.customVendorName && !config10.customSerialNumber && 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.currentRoomEntity && !config10.valetudoIdentifier && !config10.coverSwapOpenClose && !config10.disableClimateOnOff && (!config10.composedEntities || config10.composedEntities.length === 0)) {
|
|
153356
|
+
if (!config10.matterDeviceType && !config10.customName && !config10.customProductName && !config10.customVendorName && !config10.customSerialNumber && 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.currentRoomEntity && !config10.valetudoIdentifier && !config10.coverSwapOpenClose && !config10.disableClimateOnOff && !config10.disableClimateFanControl && (!config10.composedEntities || config10.composedEntities.length === 0)) {
|
|
153301
153357
|
bridgeMap.delete(request.entityId);
|
|
153302
153358
|
} else {
|
|
153303
153359
|
bridgeMap.set(request.entityId, config10);
|
|
@@ -165331,7 +165387,7 @@ var ServerModeServerNode = class extends ServerNode {
|
|
|
165331
165387
|
/**
|
|
165332
165388
|
* Update root-level BasicInformation with entity-specific data.
|
|
165333
165389
|
* In server mode, controllers (Apple Home, Alexa) read the root node's
|
|
165334
|
-
* BasicInformation
|
|
165390
|
+
* BasicInformation, not the device endpoint's BridgedDeviceBasicInformation.
|
|
165335
165391
|
* Without this, server-mode devices show bridge defaults (e.g. "riddix" / "MatterHub").
|
|
165336
165392
|
*/
|
|
165337
165393
|
async updateDeviceIdentity(entityId, device, mapping, friendlyName) {
|
|
@@ -167516,7 +167572,9 @@ function createBridgeServerConfig(data) {
|
|
|
167516
167572
|
hardwareVersion: data.basicInformation.hardwareVersion,
|
|
167517
167573
|
softwareVersion: data.basicInformation.softwareVersion,
|
|
167518
167574
|
hardwareVersionString: data.basicInformation.hardwareVersionString,
|
|
167519
|
-
|
|
167575
|
+
// Keep the root string aligned with the numeric softwareVersion. Aqara
|
|
167576
|
+
// stalls bridge registration when the two diverge (#316).
|
|
167577
|
+
softwareVersionString: String(data.basicInformation.softwareVersion),
|
|
167520
167578
|
...data.countryCode ? { location: data.countryCode } : {}
|
|
167521
167579
|
},
|
|
167522
167580
|
subscriptions: {
|
|
@@ -167840,7 +167898,7 @@ ${e?.toString()}`);
|
|
|
167840
167898
|
);
|
|
167841
167899
|
if (totalSubs === 0 && sessions.length > 0) {
|
|
167842
167900
|
this.log.warn(
|
|
167843
|
-
`All subscriptions lost
|
|
167901
|
+
`All subscriptions lost, ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
|
|
167844
167902
|
);
|
|
167845
167903
|
if (!this.deadSessionTimer) {
|
|
167846
167904
|
this.deadSessionTimer = setTimeout(() => {
|
|
@@ -167888,7 +167946,7 @@ ${e?.toString()}`);
|
|
|
167888
167946
|
for (const s of [...sessionManager.sessions]) {
|
|
167889
167947
|
if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
|
|
167890
167948
|
this.log.info(
|
|
167891
|
-
`Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs)
|
|
167949
|
+
`Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs), replaced by session ${newSession.id}`
|
|
167892
167950
|
);
|
|
167893
167951
|
s.initiateForceClose().catch(() => {
|
|
167894
167952
|
});
|
|
@@ -168343,7 +168401,7 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
|
|
|
168343
168401
|
await super.initialize();
|
|
168344
168402
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
168345
168403
|
this.update(homeAssistant.entity);
|
|
168346
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168404
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168347
168405
|
}
|
|
168348
168406
|
update(entity) {
|
|
168349
168407
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -168409,7 +168467,7 @@ var ElectricalEnergyMeasurementServerBase = class extends FeaturedBase {
|
|
|
168409
168467
|
);
|
|
168410
168468
|
}
|
|
168411
168469
|
this.update();
|
|
168412
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168470
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168413
168471
|
}
|
|
168414
168472
|
update() {
|
|
168415
168473
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -168469,7 +168527,7 @@ var ElectricalPowerMeasurementServerBase = class extends ElectricalPowerMeasurem
|
|
|
168469
168527
|
);
|
|
168470
168528
|
}
|
|
168471
168529
|
this.update();
|
|
168472
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168530
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168473
168531
|
}
|
|
168474
168532
|
update() {
|
|
168475
168533
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -168522,7 +168580,7 @@ var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementSer
|
|
|
168522
168580
|
await super.initialize();
|
|
168523
168581
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
168524
168582
|
this.update(homeAssistant.entity);
|
|
168525
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168583
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168526
168584
|
}
|
|
168527
168585
|
update(entity) {
|
|
168528
168586
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -168586,7 +168644,7 @@ var PowerSourceServerBase = class extends FeaturedBase2 {
|
|
|
168586
168644
|
);
|
|
168587
168645
|
}
|
|
168588
168646
|
this.update(homeAssistant.entity);
|
|
168589
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168647
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168590
168648
|
}
|
|
168591
168649
|
update(entity) {
|
|
168592
168650
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -168672,7 +168730,7 @@ var TemperatureMeasurementServerBase = class extends TemperatureMeasurementServe
|
|
|
168672
168730
|
await super.initialize();
|
|
168673
168731
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
168674
168732
|
this.update(homeAssistant.entity);
|
|
168675
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168733
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168676
168734
|
}
|
|
168677
168735
|
update(entity) {
|
|
168678
168736
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -168714,7 +168772,7 @@ var HepaFilterMonitoringServerBase = class extends FeaturedBase3 {
|
|
|
168714
168772
|
await super.initialize();
|
|
168715
168773
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
168716
168774
|
this.update(homeAssistant.entity);
|
|
168717
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
168775
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
168718
168776
|
}
|
|
168719
168777
|
update(entity) {
|
|
168720
168778
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -169192,7 +169250,7 @@ var FeaturedBase5 = FanControlServer.with(
|
|
|
169192
169250
|
"Rocking",
|
|
169193
169251
|
"Wind"
|
|
169194
169252
|
).set({
|
|
169195
|
-
// rockSupport / windSupport are Fixed quality attributes
|
|
169253
|
+
// rockSupport / windSupport are Fixed quality attributes, they MUST be set
|
|
169196
169254
|
// via .set() at behavior creation time, NOT in initialize().
|
|
169197
169255
|
// Without these, controllers reject attempts to enable rocking/wind.
|
|
169198
169256
|
rockSupport: { rockUpDown: true },
|
|
@@ -169968,7 +170026,7 @@ var PressureMeasurementServerBase = class extends PressureMeasurementServer {
|
|
|
169968
170026
|
await super.initialize();
|
|
169969
170027
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
169970
170028
|
this.update(homeAssistant.entity);
|
|
169971
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170029
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
169972
170030
|
}
|
|
169973
170031
|
update(entity) {
|
|
169974
170032
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -170528,7 +170586,7 @@ var BooleanStateServerBase = class extends BooleanStateServer {
|
|
|
170528
170586
|
await super.initialize();
|
|
170529
170587
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
170530
170588
|
this.update(homeAssistant.entity);
|
|
170531
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170589
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
170532
170590
|
}
|
|
170533
170591
|
update(entity) {
|
|
170534
170592
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -170606,7 +170664,7 @@ var PirOccupancySensingServer = class extends PirOccupancySensingServerBase {
|
|
|
170606
170664
|
await super.initialize();
|
|
170607
170665
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
170608
170666
|
this.update(homeAssistant.entity);
|
|
170609
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170667
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
170610
170668
|
}
|
|
170611
170669
|
update(entity) {
|
|
170612
170670
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -170674,7 +170732,7 @@ var OccupancySensingServer2 = class extends OccupancySensingServerBase {
|
|
|
170674
170732
|
await super.initialize();
|
|
170675
170733
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
170676
170734
|
this.update(homeAssistant.entity);
|
|
170677
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170735
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
170678
170736
|
}
|
|
170679
170737
|
update(entity) {
|
|
170680
170738
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -170789,7 +170847,7 @@ var SmokeAlarmServerImpl = class extends SmokeAlarmServerWithFeature {
|
|
|
170789
170847
|
await super.initialize();
|
|
170790
170848
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
170791
170849
|
this.update(homeAssistant.entity);
|
|
170792
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170850
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
170793
170851
|
}
|
|
170794
170852
|
update(entity) {
|
|
170795
170853
|
const isOn = this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state.state === "on";
|
|
@@ -170803,7 +170861,7 @@ var CoAlarmServerImpl = class extends CoAlarmServerWithFeature {
|
|
|
170803
170861
|
await super.initialize();
|
|
170804
170862
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
170805
170863
|
this.update(homeAssistant.entity);
|
|
170806
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
170864
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
170807
170865
|
}
|
|
170808
170866
|
update(entity) {
|
|
170809
170867
|
const isOn = this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state.state === "on";
|
|
@@ -171084,6 +171142,23 @@ var ClimateOnOffServer = OnOffServer2({
|
|
|
171084
171142
|
|
|
171085
171143
|
// src/matter/endpoints/legacy/climate/behaviors/climate-thermostat-server.ts
|
|
171086
171144
|
init_dist();
|
|
171145
|
+
|
|
171146
|
+
// src/utils/converters/snap-to-step.ts
|
|
171147
|
+
function snapToStep(target, current, step) {
|
|
171148
|
+
if (step == null || !Number.isFinite(step) || step <= 0) return target;
|
|
171149
|
+
const ratio = target / step;
|
|
171150
|
+
const lower = Math.floor(ratio) * step;
|
|
171151
|
+
const upper = Math.ceil(ratio) * step;
|
|
171152
|
+
if (lower === upper) return target;
|
|
171153
|
+
const distLower = target - lower;
|
|
171154
|
+
const distUpper = upper - target;
|
|
171155
|
+
if (distLower < distUpper) return lower;
|
|
171156
|
+
if (distUpper < distLower) return upper;
|
|
171157
|
+
if (current == null || !Number.isFinite(current)) return upper;
|
|
171158
|
+
return target > current ? upper : lower;
|
|
171159
|
+
}
|
|
171160
|
+
|
|
171161
|
+
// src/matter/endpoints/legacy/climate/behaviors/climate-thermostat-server.ts
|
|
171087
171162
|
init_home_assistant_entity_behavior();
|
|
171088
171163
|
|
|
171089
171164
|
// src/matter/behaviors/thermostat-server.ts
|
|
@@ -171279,7 +171354,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
|
|
|
171279
171354
|
// Heat/Cool/Off but SKIPS Auto (see #handleSystemModeChange in Matter.js).
|
|
171280
171355
|
// Without this, switching Heat→Auto leaves runningMode stale at Heat.
|
|
171281
171356
|
// 889010b set for ALL modes (conflicted with reactor), 0678d35 set for NONE
|
|
171282
|
-
// (stale in Auto). da04b2e's Auto-only approach is correct
|
|
171357
|
+
// (stale in Auto). da04b2e's Auto-only approach is correct, the issues
|
|
171283
171358
|
// reported after it were caused by localTemperature fallback, not runningMode.
|
|
171284
171359
|
...this.features.heating && this.features.cooling && systemMode === Thermostat3.SystemMode.Auto ? { thermostatRunningMode: runningMode } : {}
|
|
171285
171360
|
});
|
|
@@ -171564,7 +171639,7 @@ var CoolingOnlyThermostatServerBase = class extends CoolingOnlyFeaturedBase {
|
|
|
171564
171639
|
static State = class extends CoolingOnlyFeaturedBase.State {
|
|
171565
171640
|
config;
|
|
171566
171641
|
};
|
|
171567
|
-
// Each variant MUST define its own initialize()
|
|
171642
|
+
// Each variant MUST define its own initialize(), see HeatingOnly comment above.
|
|
171568
171643
|
async initialize() {
|
|
171569
171644
|
thermostatPreInitialize(this);
|
|
171570
171645
|
await super.initialize();
|
|
@@ -171586,7 +171661,7 @@ var HeatingAndCoolingThermostatServerBase = class extends HeatingAndCoolingFeatu
|
|
|
171586
171661
|
static State = class extends HeatingAndCoolingFeaturedBase.State {
|
|
171587
171662
|
config;
|
|
171588
171663
|
};
|
|
171589
|
-
// Each variant MUST define its own initialize()
|
|
171664
|
+
// Each variant MUST define its own initialize(), see HeatingOnly comment above.
|
|
171590
171665
|
async initialize() {
|
|
171591
171666
|
thermostatPreInitialize(this);
|
|
171592
171667
|
await super.initialize();
|
|
@@ -171667,6 +171742,18 @@ var getTemp = (agent, entity, attributeName) => {
|
|
|
171667
171742
|
return Temperature.withUnit(+temperature3, unit);
|
|
171668
171743
|
}
|
|
171669
171744
|
};
|
|
171745
|
+
var getStep = (entity) => {
|
|
171746
|
+
const raw = attributes4(entity).target_temp_step;
|
|
171747
|
+
if (raw == null) return void 0;
|
|
171748
|
+
const num = typeof raw === "string" ? parseFloat(raw) : raw;
|
|
171749
|
+
return Number.isFinite(num) && num > 0 ? num : void 0;
|
|
171750
|
+
};
|
|
171751
|
+
var getRefTemp = (entity, attr) => {
|
|
171752
|
+
const raw = attributes4(entity)[attr];
|
|
171753
|
+
if (raw == null) return void 0;
|
|
171754
|
+
const num = typeof raw === "string" ? parseFloat(raw) : raw;
|
|
171755
|
+
return Number.isFinite(num) ? num : void 0;
|
|
171756
|
+
};
|
|
171670
171757
|
var systemModeToHvacMode = {
|
|
171671
171758
|
[Thermostat3.SystemMode.Auto]: ClimateHvacMode.heat_cool,
|
|
171672
171759
|
[Thermostat3.SystemMode.Precooling]: ClimateHvacMode.cool,
|
|
@@ -171745,7 +171832,7 @@ var config4 = {
|
|
|
171745
171832
|
const direction = getHeatCoolOnlyDirection(entity, agent);
|
|
171746
171833
|
return direction === "cooling" ? Thermostat3.SystemMode.Cool : Thermostat3.SystemMode.Heat;
|
|
171747
171834
|
}
|
|
171748
|
-
const hasMatterAuto = modes.includes(ClimateHvacMode.heat_cool) || modes.includes(ClimateHvacMode.
|
|
171835
|
+
const hasMatterAuto = modes.includes(ClimateHvacMode.heat_cool) && (modes.includes(ClimateHvacMode.heat) || modes.includes(ClimateHvacMode.cool));
|
|
171749
171836
|
if (hasMatterAuto) {
|
|
171750
171837
|
return systemMode;
|
|
171751
171838
|
}
|
|
@@ -171759,11 +171846,34 @@ var config4 = {
|
|
|
171759
171846
|
if (hasCooling && !hasHeating) {
|
|
171760
171847
|
return Thermostat3.SystemMode.Cool;
|
|
171761
171848
|
}
|
|
171849
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171850
|
+
const entityId = homeAssistant.entityId;
|
|
171762
171851
|
const action = attributes4(entity).hvac_action;
|
|
171763
171852
|
if (action === ClimateHvacAction.cooling) {
|
|
171853
|
+
lastHvacDirection.set(entityId, "cooling");
|
|
171764
171854
|
return Thermostat3.SystemMode.Cool;
|
|
171765
171855
|
}
|
|
171766
|
-
|
|
171856
|
+
if (action === ClimateHvacAction.heating) {
|
|
171857
|
+
lastHvacDirection.set(entityId, "heating");
|
|
171858
|
+
return Thermostat3.SystemMode.Heat;
|
|
171859
|
+
}
|
|
171860
|
+
const remembered = lastHvacDirection.get(entityId);
|
|
171861
|
+
if (remembered) {
|
|
171862
|
+
return remembered === "cooling" ? Thermostat3.SystemMode.Cool : Thermostat3.SystemMode.Heat;
|
|
171863
|
+
}
|
|
171864
|
+
const current = attributes4(entity).current_temperature;
|
|
171865
|
+
const target = attributes4(entity).temperature;
|
|
171866
|
+
if (typeof current === "number" && typeof target === "number") {
|
|
171867
|
+
if (current > target) {
|
|
171868
|
+
lastHvacDirection.set(entityId, "cooling");
|
|
171869
|
+
return Thermostat3.SystemMode.Cool;
|
|
171870
|
+
}
|
|
171871
|
+
if (current < target) {
|
|
171872
|
+
lastHvacDirection.set(entityId, "heating");
|
|
171873
|
+
return Thermostat3.SystemMode.Heat;
|
|
171874
|
+
}
|
|
171875
|
+
}
|
|
171876
|
+
return Thermostat3.SystemMode.Cool;
|
|
171767
171877
|
}
|
|
171768
171878
|
return systemMode;
|
|
171769
171879
|
},
|
|
@@ -171825,19 +171935,37 @@ var config4 = {
|
|
|
171825
171935
|
data: { hvac_mode: targetMode }
|
|
171826
171936
|
};
|
|
171827
171937
|
},
|
|
171828
|
-
setTargetTemperature: (value, agent) =>
|
|
171829
|
-
|
|
171830
|
-
|
|
171831
|
-
|
|
171832
|
-
|
|
171833
|
-
|
|
171834
|
-
|
|
171835
|
-
|
|
171836
|
-
|
|
171837
|
-
|
|
171838
|
-
|
|
171839
|
-
|
|
171840
|
-
|
|
171938
|
+
setTargetTemperature: (value, agent) => {
|
|
171939
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171940
|
+
const entity = homeAssistant.entity.state;
|
|
171941
|
+
const unit = getUnit(agent);
|
|
171942
|
+
const target = value.toUnit(unit);
|
|
171943
|
+
const step = getStep(entity);
|
|
171944
|
+
const current = getRefTemp(entity, "temperature") ?? getRefTemp(entity, "target_temperature");
|
|
171945
|
+
return {
|
|
171946
|
+
action: "climate.set_temperature",
|
|
171947
|
+
data: {
|
|
171948
|
+
temperature: snapToStep(target, current, step)
|
|
171949
|
+
}
|
|
171950
|
+
};
|
|
171951
|
+
},
|
|
171952
|
+
setTargetTemperatureRange: ({ low, high }, agent) => {
|
|
171953
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171954
|
+
const entity = homeAssistant.entity.state;
|
|
171955
|
+
const unit = getUnit(agent);
|
|
171956
|
+
const step = getStep(entity);
|
|
171957
|
+
const lowTarget = low.toUnit(unit);
|
|
171958
|
+
const highTarget = high.toUnit(unit);
|
|
171959
|
+
const lowCurrent = getRefTemp(entity, "target_temp_low") ?? getRefTemp(entity, "temperature");
|
|
171960
|
+
const highCurrent = getRefTemp(entity, "target_temp_high") ?? getRefTemp(entity, "temperature");
|
|
171961
|
+
return {
|
|
171962
|
+
action: "climate.set_temperature",
|
|
171963
|
+
data: {
|
|
171964
|
+
target_temp_low: snapToStep(lowTarget, lowCurrent, step),
|
|
171965
|
+
target_temp_high: snapToStep(highTarget, highCurrent, step)
|
|
171966
|
+
}
|
|
171967
|
+
};
|
|
171968
|
+
}
|
|
171841
171969
|
};
|
|
171842
171970
|
function ClimateThermostatServer(initialState = {}, features2) {
|
|
171843
171971
|
return ThermostatServer2(config4, initialState, features2);
|
|
@@ -171917,10 +172045,7 @@ function ClimateDevice(homeAssistantEntity) {
|
|
|
171917
172045
|
}
|
|
171918
172046
|
const supportsHumidity = attributes7.current_humidity != null || testBit(supportedFeatures, ClimateDeviceFeature.TARGET_HUMIDITY);
|
|
171919
172047
|
const supportsOnOff = testBit(supportedFeatures, ClimateDeviceFeature.TURN_ON) && testBit(supportedFeatures, ClimateDeviceFeature.TURN_OFF) && homeAssistantEntity.mapping?.disableClimateOnOff !== true;
|
|
171920
|
-
const supportsFanMode = testBit(
|
|
171921
|
-
supportedFeatures,
|
|
171922
|
-
ClimateDeviceFeature.FAN_MODE
|
|
171923
|
-
);
|
|
172048
|
+
const supportsFanMode = testBit(supportedFeatures, ClimateDeviceFeature.FAN_MODE) && homeAssistantEntity.mapping?.disableClimateFanControl !== true;
|
|
171924
172049
|
const initialState = {
|
|
171925
172050
|
// Pass actual current_temperature for initial state.
|
|
171926
172051
|
// If unavailable (null/undefined), update() will fall back to the
|
|
@@ -171934,7 +172059,7 @@ function ClimateDevice(homeAssistantEntity) {
|
|
|
171934
172059
|
minCoolSetpointLimit: toMatterTemp(attributes7.min_temp) ?? 0,
|
|
171935
172060
|
maxCoolSetpointLimit: toMatterTemp(attributes7.max_temp) ?? 5e3
|
|
171936
172061
|
};
|
|
171937
|
-
const autoMode = supportsHeating && supportsCooling &&
|
|
172062
|
+
const autoMode = supportsHeating && supportsCooling && attributes7.hvac_modes.includes(ClimateHvacMode.heat_cool) && (attributes7.hvac_modes.includes(ClimateHvacMode.heat) || attributes7.hvac_modes.includes(ClimateHvacMode.cool));
|
|
171938
172063
|
return ClimateDeviceType(
|
|
171939
172064
|
supportsOnOff,
|
|
171940
172065
|
supportsHumidity,
|
|
@@ -172059,6 +172184,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
172059
172184
|
this.state.targetPositionTiltPercent100ths = null;
|
|
172060
172185
|
}
|
|
172061
172186
|
}
|
|
172187
|
+
this.state.type = this.features.lift && this.features.tilt ? WindowCovering3.WindowCoveringType.TiltBlindLift : this.features.tilt ? WindowCovering3.WindowCoveringType.TiltBlindTiltOnly : WindowCovering3.WindowCoveringType.Rollershade;
|
|
172062
172188
|
await super.initialize();
|
|
172063
172189
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
172064
172190
|
this.update(homeAssistant.entity);
|
|
@@ -172177,7 +172303,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
172177
172303
|
} else if (type === MovementType.Tilt) {
|
|
172178
172304
|
if (targetPercent100ths == null && this.lastLiftMovementDirection === direction && Date.now() - this.lastLiftMovementMs < 50) {
|
|
172179
172305
|
logger179.info(
|
|
172180
|
-
`Skipping tilt ${MovementDirection[direction]}
|
|
172306
|
+
`Skipping tilt ${MovementDirection[direction]}, lift already moving in same direction`
|
|
172181
172307
|
);
|
|
172182
172308
|
return;
|
|
172183
172309
|
}
|
|
@@ -172351,6 +172477,13 @@ var DEVICE_CLASS_TO_MATTER_TYPE = {
|
|
|
172351
172477
|
shade: {
|
|
172352
172478
|
type: WindowCovering3.WindowCoveringType.Rollershade,
|
|
172353
172479
|
endProductType: WindowCovering3.EndProductType.RollerShade
|
|
172480
|
+
},
|
|
172481
|
+
// Velux-style motorized roof/casement windows. There's no Matter
|
|
172482
|
+
// WindowCoveringType for "window", so we map to lift-only Rollershade
|
|
172483
|
+
// and use Unknown end-product to avoid implying a specific physical form.
|
|
172484
|
+
window: {
|
|
172485
|
+
type: WindowCovering3.WindowCoveringType.Rollershade,
|
|
172486
|
+
endProductType: WindowCovering3.EndProductType.Unknown
|
|
172354
172487
|
}
|
|
172355
172488
|
};
|
|
172356
172489
|
var deviceClassMapping = (entity) => {
|
|
@@ -172359,12 +172492,21 @@ var deviceClassMapping = (entity) => {
|
|
|
172359
172492
|
const mapping = DEVICE_CLASS_TO_MATTER_TYPE[raw.toLowerCase()];
|
|
172360
172493
|
if (!mapping) return void 0;
|
|
172361
172494
|
const supportedFeatures = attributes5(entity).supported_features ?? 0;
|
|
172495
|
+
const hasLift = (supportedFeatures & CoverSupportedFeatures.support_open) !== 0;
|
|
172362
172496
|
const hasTilt = (supportedFeatures & CoverSupportedFeatures.support_open_tilt) !== 0;
|
|
172363
|
-
if (mapping.type === WindowCovering3.WindowCoveringType.TiltBlindTiltOnly
|
|
172364
|
-
|
|
172365
|
-
|
|
172366
|
-
|
|
172367
|
-
|
|
172497
|
+
if (mapping.type === WindowCovering3.WindowCoveringType.TiltBlindTiltOnly) {
|
|
172498
|
+
if (!hasTilt) {
|
|
172499
|
+
return {
|
|
172500
|
+
type: WindowCovering3.WindowCoveringType.Rollershade,
|
|
172501
|
+
endProductType: mapping.endProductType
|
|
172502
|
+
};
|
|
172503
|
+
}
|
|
172504
|
+
if (hasLift) {
|
|
172505
|
+
return {
|
|
172506
|
+
type: WindowCovering3.WindowCoveringType.TiltBlindLift,
|
|
172507
|
+
endProductType: mapping.endProductType
|
|
172508
|
+
};
|
|
172509
|
+
}
|
|
172368
172510
|
}
|
|
172369
172511
|
return mapping;
|
|
172370
172512
|
};
|
|
@@ -174596,7 +174738,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase8 {
|
|
|
174596
174738
|
*
|
|
174597
174739
|
* The base class registers a reactor on onOff$Changed that sets
|
|
174598
174740
|
* currentLevel = onLevel. This is designed for lights (restore brightness
|
|
174599
|
-
* on power-on) but is wrong for speakers
|
|
174741
|
+
* on power-on) but is wrong for speakers, it overwrites the correct
|
|
174600
174742
|
* volume (e.g. 191 for 75%) with a stale onLevel value, causing Google
|
|
174601
174743
|
* Home to display the wrong percentage (Issue #79).
|
|
174602
174744
|
*/
|
|
@@ -174943,7 +175085,7 @@ var AirQualitySensorServerImpl = class extends AirQualityServerWithFeatures {
|
|
|
174943
175085
|
await super.initialize();
|
|
174944
175086
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
174945
175087
|
this.update(homeAssistant.entity);
|
|
174946
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175088
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
174947
175089
|
}
|
|
174948
175090
|
update(entity) {
|
|
174949
175091
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175054,7 +175196,7 @@ var CarbonMonoxideConcentrationMeasurementServer2 = class extends CarbonMonoxide
|
|
|
175054
175196
|
await super.initialize();
|
|
175055
175197
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175056
175198
|
this.update(homeAssistant.entity);
|
|
175057
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175199
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175058
175200
|
}
|
|
175059
175201
|
update(entity) {
|
|
175060
175202
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175085,7 +175227,7 @@ var CoAirQualityServer = class extends CoAirQualityServerBase {
|
|
|
175085
175227
|
await super.initialize();
|
|
175086
175228
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175087
175229
|
this.update(homeAssistant.entity);
|
|
175088
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175230
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175089
175231
|
}
|
|
175090
175232
|
update(entity) {
|
|
175091
175233
|
const state = entity.state.state;
|
|
@@ -175125,7 +175267,7 @@ var StandalonePowerServer = class extends ElectricalPowerMeasurementServer {
|
|
|
175125
175267
|
await super.initialize();
|
|
175126
175268
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175127
175269
|
this.update(homeAssistant.entity);
|
|
175128
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175270
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175129
175271
|
}
|
|
175130
175272
|
update(entity) {
|
|
175131
175273
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175183,7 +175325,7 @@ var StandaloneEnergyServer = class extends EnergyFeaturedBase {
|
|
|
175183
175325
|
await super.initialize();
|
|
175184
175326
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175185
175327
|
this.update(homeAssistant.entity);
|
|
175186
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175328
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175187
175329
|
}
|
|
175188
175330
|
update(entity) {
|
|
175189
175331
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175239,7 +175381,7 @@ var FlowMeasurementServerBase = class extends FlowMeasurementServer {
|
|
|
175239
175381
|
await super.initialize();
|
|
175240
175382
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175241
175383
|
this.update(homeAssistant.entity);
|
|
175242
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175384
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175243
175385
|
}
|
|
175244
175386
|
update(entity) {
|
|
175245
175387
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175331,7 +175473,7 @@ var FormaldehydeConcentrationMeasurementServer2 = class extends FormaldehydeConc
|
|
|
175331
175473
|
await super.initialize();
|
|
175332
175474
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175333
175475
|
this.update(homeAssistant.entity);
|
|
175334
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175476
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175335
175477
|
}
|
|
175336
175478
|
update(entity) {
|
|
175337
175479
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175362,7 +175504,7 @@ var FormaldehydeAirQualityServer = class extends FormaldehydeAirQualityServerBas
|
|
|
175362
175504
|
await super.initialize();
|
|
175363
175505
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175364
175506
|
this.update(homeAssistant.entity);
|
|
175365
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175507
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175366
175508
|
}
|
|
175367
175509
|
update(entity) {
|
|
175368
175510
|
const state = entity.state.state;
|
|
@@ -175421,7 +175563,7 @@ var IlluminanceMeasurementServerBase = class extends IlluminanceMeasurementServe
|
|
|
175421
175563
|
await super.initialize();
|
|
175422
175564
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175423
175565
|
this.update(homeAssistant.entity);
|
|
175424
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175566
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175425
175567
|
}
|
|
175426
175568
|
update(entity) {
|
|
175427
175569
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175505,7 +175647,7 @@ var NitrogenDioxideConcentrationMeasurementServer2 = class extends NitrogenDioxi
|
|
|
175505
175647
|
await super.initialize();
|
|
175506
175648
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175507
175649
|
this.update(homeAssistant.entity);
|
|
175508
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175650
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175509
175651
|
}
|
|
175510
175652
|
update(entity) {
|
|
175511
175653
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175535,7 +175677,7 @@ var No2AirQualityServer = class extends No2AirQualityServerBase {
|
|
|
175535
175677
|
await super.initialize();
|
|
175536
175678
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175537
175679
|
this.update(homeAssistant.entity);
|
|
175538
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175680
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175539
175681
|
}
|
|
175540
175682
|
update(entity) {
|
|
175541
175683
|
const state = entity.state.state;
|
|
@@ -175598,7 +175740,7 @@ var OzoneConcentrationMeasurementServer2 = class extends OzoneConcentrationMeasu
|
|
|
175598
175740
|
await super.initialize();
|
|
175599
175741
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175600
175742
|
this.update(homeAssistant.entity);
|
|
175601
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175743
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175602
175744
|
}
|
|
175603
175745
|
update(entity) {
|
|
175604
175746
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175628,7 +175770,7 @@ var OzoneAirQualityServer = class extends OzoneAirQualityServerBase {
|
|
|
175628
175770
|
await super.initialize();
|
|
175629
175771
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175630
175772
|
this.update(homeAssistant.entity);
|
|
175631
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175773
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175632
175774
|
}
|
|
175633
175775
|
update(entity) {
|
|
175634
175776
|
const state = entity.state.state;
|
|
@@ -175691,7 +175833,7 @@ var Pm1ConcentrationMeasurementServer2 = class extends Pm1ConcentrationMeasureme
|
|
|
175691
175833
|
await super.initialize();
|
|
175692
175834
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175693
175835
|
this.update(homeAssistant.entity);
|
|
175694
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175836
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175695
175837
|
}
|
|
175696
175838
|
update(entity) {
|
|
175697
175839
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175721,7 +175863,7 @@ var Pm1AirQualityServer = class extends Pm1AirQualityServerBase {
|
|
|
175721
175863
|
await super.initialize();
|
|
175722
175864
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175723
175865
|
this.update(homeAssistant.entity);
|
|
175724
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175866
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175725
175867
|
}
|
|
175726
175868
|
update(entity) {
|
|
175727
175869
|
const state = entity.state.state;
|
|
@@ -175804,7 +175946,7 @@ var RadonConcentrationMeasurementServer2 = class extends RadonConcentrationMeasu
|
|
|
175804
175946
|
await super.initialize();
|
|
175805
175947
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175806
175948
|
this.update(homeAssistant.entity);
|
|
175807
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175949
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175808
175950
|
}
|
|
175809
175951
|
update(entity) {
|
|
175810
175952
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -175834,7 +175976,7 @@ var RadonAirQualityServer = class extends RadonAirQualityServerBase {
|
|
|
175834
175976
|
await super.initialize();
|
|
175835
175977
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175836
175978
|
this.update(homeAssistant.entity);
|
|
175837
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
175979
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175838
175980
|
}
|
|
175839
175981
|
update(entity) {
|
|
175840
175982
|
const state = entity.state.state;
|
|
@@ -175952,7 +176094,7 @@ var TvocConcentrationMeasurementServer = class extends TvocConcentrationMeasurem
|
|
|
175952
176094
|
await super.initialize();
|
|
175953
176095
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
175954
176096
|
this.update(homeAssistant.entity);
|
|
175955
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176097
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
175956
176098
|
}
|
|
175957
176099
|
update(entity) {
|
|
175958
176100
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -176002,7 +176144,7 @@ var TvocAirQualityServer = class extends TvocAirQualityServerBase {
|
|
|
176002
176144
|
await super.initialize();
|
|
176003
176145
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176004
176146
|
this.update(homeAssistant.entity);
|
|
176005
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176147
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176006
176148
|
}
|
|
176007
176149
|
update(entity) {
|
|
176008
176150
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -176069,7 +176211,7 @@ var CarbonDioxideConcentrationMeasurementServer2 = class extends CarbonDioxideCo
|
|
|
176069
176211
|
await super.initialize();
|
|
176070
176212
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176071
176213
|
this.update(homeAssistant.entity);
|
|
176072
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176214
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176073
176215
|
}
|
|
176074
176216
|
update(entity) {
|
|
176075
176217
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -176102,7 +176244,7 @@ var Co2AirQualityServer = class extends Co2AirQualityServerBase {
|
|
|
176102
176244
|
await super.initialize();
|
|
176103
176245
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176104
176246
|
this.update(homeAssistant.entity);
|
|
176105
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176247
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176106
176248
|
}
|
|
176107
176249
|
update(entity) {
|
|
176108
176250
|
const state = entity.state.state;
|
|
@@ -176165,7 +176307,7 @@ var Pm10ConcentrationMeasurementServer2 = class extends Pm10ConcentrationMeasure
|
|
|
176165
176307
|
await super.initialize();
|
|
176166
176308
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176167
176309
|
this.update(homeAssistant.entity);
|
|
176168
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176310
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176169
176311
|
}
|
|
176170
176312
|
update(entity) {
|
|
176171
176313
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -176197,7 +176339,7 @@ var Pm10AirQualityServer = class extends Pm10AirQualityServerBase {
|
|
|
176197
176339
|
await super.initialize();
|
|
176198
176340
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176199
176341
|
this.update(homeAssistant.entity);
|
|
176200
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176342
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176201
176343
|
}
|
|
176202
176344
|
update(entity) {
|
|
176203
176345
|
const state = entity.state.state;
|
|
@@ -176269,7 +176411,7 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
|
|
|
176269
176411
|
);
|
|
176270
176412
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176271
176413
|
this.update(homeAssistant.entity);
|
|
176272
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176414
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176273
176415
|
}
|
|
176274
176416
|
update(entity) {
|
|
176275
176417
|
if (!entity.state || !entity.state.attributes) {
|
|
@@ -176304,7 +176446,7 @@ var Pm25AirQualityServer = class extends Pm25AirQualityServerBase {
|
|
|
176304
176446
|
logger189.debug("Pm25AirQualityServer: after super.initialize()");
|
|
176305
176447
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
176306
176448
|
this.update(homeAssistant.entity);
|
|
176307
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
176449
|
+
this.reactTo(homeAssistant.onChange, this.update, { offline: true });
|
|
176308
176450
|
}
|
|
176309
176451
|
update(entity) {
|
|
176310
176452
|
const state = entity.state.state;
|
|
@@ -176601,7 +176743,7 @@ function SensorDevice(homeAssistantEntity) {
|
|
|
176601
176743
|
if (deviceClass) {
|
|
176602
176744
|
diagnosticEventBus.emit(
|
|
176603
176745
|
"entity_warning",
|
|
176604
|
-
`Sensor "${homeAssistantEntity.entity.entity_id}" has unsupported device_class "${deviceClass}"
|
|
176746
|
+
`Sensor "${homeAssistantEntity.entity.entity_id}" has unsupported device_class "${deviceClass}", skipped`,
|
|
176605
176747
|
{
|
|
176606
176748
|
entityId: homeAssistantEntity.entity.entity_id,
|
|
176607
176749
|
details: { device_class: deviceClass }
|
|
@@ -176688,6 +176830,7 @@ init_dist();
|
|
|
176688
176830
|
init_esm();
|
|
176689
176831
|
init_home_assistant_entity_behavior();
|
|
176690
176832
|
var logger190 = Logger.get("VacuumIdentifyServer");
|
|
176833
|
+
var IDENTIFY_BUTTON_SUFFIXES = ["_identify", "_locate", "_find_me"];
|
|
176691
176834
|
var VacuumIdentifyServer = class extends IdentifyServer2 {
|
|
176692
176835
|
triggerEffect(effect) {
|
|
176693
176836
|
this.#locate("triggerEffect");
|
|
@@ -176702,16 +176845,40 @@ var VacuumIdentifyServer = class extends IdentifyServer2 {
|
|
|
176702
176845
|
#locate(source) {
|
|
176703
176846
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
176704
176847
|
const features2 = homeAssistant.entity.state.attributes.supported_features ?? 0;
|
|
176705
|
-
|
|
176706
|
-
if (!hasLocate) {
|
|
176707
|
-
logger190.warn(
|
|
176708
|
-
`${source} for ${homeAssistant.entityId} \u2014 LOCATE not in supported_features (${features2}), calling vacuum.locate anyway`
|
|
176709
|
-
);
|
|
176710
|
-
} else {
|
|
176848
|
+
if (testBit(features2, VacuumDeviceFeature.LOCATE)) {
|
|
176711
176849
|
logger190.info(`${source} \u2192 vacuum.locate for ${homeAssistant.entityId}`);
|
|
176850
|
+
homeAssistant.callAction({ action: "vacuum.locate" });
|
|
176851
|
+
return;
|
|
176712
176852
|
}
|
|
176853
|
+
const sibling = this.#findIdentifyButton(homeAssistant);
|
|
176854
|
+
if (sibling) {
|
|
176855
|
+
logger190.info(
|
|
176856
|
+
`${source} \u2192 button.press ${sibling} for ${homeAssistant.entityId}`
|
|
176857
|
+
);
|
|
176858
|
+
homeAssistant.callAction({ action: "button.press", target: sibling });
|
|
176859
|
+
return;
|
|
176860
|
+
}
|
|
176861
|
+
logger190.warn(
|
|
176862
|
+
`${source} for ${homeAssistant.entityId}, LOCATE not in supported_features (${features2}), trying vacuum.locate anyway`
|
|
176863
|
+
);
|
|
176713
176864
|
homeAssistant.callAction({ action: "vacuum.locate" });
|
|
176714
176865
|
}
|
|
176866
|
+
#findIdentifyButton(homeAssistant) {
|
|
176867
|
+
const deviceId = homeAssistant.entity.registry?.device_id;
|
|
176868
|
+
if (!deviceId) return void 0;
|
|
176869
|
+
const registry2 = this.env.get(HomeAssistantRegistry);
|
|
176870
|
+
for (const entity of Object.values(registry2.entities)) {
|
|
176871
|
+
if (entity.device_id !== deviceId) continue;
|
|
176872
|
+
if (!entity.entity_id.startsWith("button.")) continue;
|
|
176873
|
+
const uniqueId = entity.unique_id ?? "";
|
|
176874
|
+
if (IDENTIFY_BUTTON_SUFFIXES.some(
|
|
176875
|
+
(s) => entity.entity_id.endsWith(s) || uniqueId.endsWith(s)
|
|
176876
|
+
)) {
|
|
176877
|
+
return entity.entity_id;
|
|
176878
|
+
}
|
|
176879
|
+
}
|
|
176880
|
+
return void 0;
|
|
176881
|
+
}
|
|
176715
176882
|
};
|
|
176716
176883
|
|
|
176717
176884
|
// src/matter/behaviors/rvc-run-mode-server.ts
|
|
@@ -176822,7 +176989,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
|
|
|
176822
176989
|
if (!currentRoomEntityId) {
|
|
176823
176990
|
this.logShortCircuitOnce(
|
|
176824
176991
|
"no-mapping",
|
|
176825
|
-
"currentRoom sensor: no currentRoomEntity in mapping
|
|
176992
|
+
"currentRoom sensor: no currentRoomEntity in mapping, auto-detect did not run or sensor not on same HA device"
|
|
176826
176993
|
);
|
|
176827
176994
|
return;
|
|
176828
176995
|
}
|
|
@@ -176835,26 +177002,22 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
|
|
|
176835
177002
|
);
|
|
176836
177003
|
return;
|
|
176837
177004
|
}
|
|
176838
|
-
if (s.activeAreas.length === 0) {
|
|
176839
|
-
this.logShortCircuitOnce(
|
|
176840
|
-
"no-active-areas",
|
|
176841
|
-
`currentRoom sensor: activeAreas empty while cleaning \u2014 sensor=${currentRoomEntityId} state="${roomState.state}"`
|
|
176842
|
-
);
|
|
176843
|
-
return;
|
|
176844
|
-
}
|
|
176845
177005
|
const serviceArea = this.agent.get(ServiceAreaBehavior);
|
|
177006
|
+
const externalSession = s.activeAreas.length === 0;
|
|
177007
|
+
const supportedAreaIds = serviceArea.state.supportedAreas.map(
|
|
177008
|
+
(a) => a.areaId
|
|
177009
|
+
);
|
|
177010
|
+
const isAllowedArea = (id) => externalSession ? supportedAreaIds.includes(id) : s.activeAreas.includes(id);
|
|
176846
177011
|
const sensorAttrs = roomState.attributes;
|
|
176847
177012
|
const segmentId = sensorAttrs.segment_id ?? sensorAttrs.room_id;
|
|
176848
177013
|
const roomName = roomState.state;
|
|
176849
177014
|
let matchedAreaId = null;
|
|
176850
|
-
if (segmentId != null) {
|
|
176851
|
-
|
|
176852
|
-
matchedAreaId = segmentId;
|
|
176853
|
-
}
|
|
177015
|
+
if (segmentId != null && isAllowedArea(segmentId)) {
|
|
177016
|
+
matchedAreaId = segmentId;
|
|
176854
177017
|
}
|
|
176855
177018
|
if (matchedAreaId === null && segmentId != null) {
|
|
176856
177019
|
for (const area of serviceArea.state.supportedAreas) {
|
|
176857
|
-
if (
|
|
177020
|
+
if (isAllowedArea(area.areaId) && area.areaId % 1e4 === segmentId) {
|
|
176858
177021
|
matchedAreaId = area.areaId;
|
|
176859
177022
|
break;
|
|
176860
177023
|
}
|
|
@@ -176864,7 +177027,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
|
|
|
176864
177027
|
const area = serviceArea.state.supportedAreas.find(
|
|
176865
177028
|
(a) => a.areaInfo.locationInfo?.locationName?.toLowerCase() === roomName.toLowerCase()
|
|
176866
177029
|
);
|
|
176867
|
-
if (area &&
|
|
177030
|
+
if (area && isAllowedArea(area.areaId)) {
|
|
176868
177031
|
matchedAreaId = area.areaId;
|
|
176869
177032
|
}
|
|
176870
177033
|
}
|
|
@@ -177608,9 +177771,8 @@ function buildSupportedModes2(attributes7, includeUnnamedRooms = false, customAr
|
|
|
177608
177771
|
}
|
|
177609
177772
|
return modes;
|
|
177610
177773
|
}
|
|
177611
|
-
function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant
|
|
177774
|
+
function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant) {
|
|
177612
177775
|
const matched = selectedAreas.map((areaId) => customAreas[areaId - 1]).filter(Boolean);
|
|
177613
|
-
serviceArea.state.selectedAreas = [];
|
|
177614
177776
|
if (matched.length === 0) {
|
|
177615
177777
|
logger194.warn(
|
|
177616
177778
|
`Custom service areas: no match for selected IDs ${selectedAreas.join(", ")}`
|
|
@@ -177680,14 +177842,12 @@ var vacuumRvcRunModeConfig = {
|
|
|
177680
177842
|
return handleCustomServiceAreas(
|
|
177681
177843
|
selectedAreas,
|
|
177682
177844
|
customAreas,
|
|
177683
|
-
homeAssistant
|
|
177684
|
-
serviceArea
|
|
177845
|
+
homeAssistant
|
|
177685
177846
|
);
|
|
177686
177847
|
}
|
|
177687
177848
|
const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
|
|
177688
177849
|
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
177689
177850
|
const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
|
|
177690
|
-
serviceArea.state.selectedAreas = [];
|
|
177691
177851
|
if (haAreaIds.length > 0) {
|
|
177692
177852
|
logger194.info(
|
|
177693
177853
|
`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`
|
|
@@ -177713,7 +177873,6 @@ var vacuumRvcRunModeConfig = {
|
|
|
177713
177873
|
logger194.info(
|
|
177714
177874
|
`Roborock: Pressing button entities for selected rooms: ${buttonEntityIds.join(", ")}`
|
|
177715
177875
|
);
|
|
177716
|
-
serviceArea.state.selectedAreas = [];
|
|
177717
177876
|
for (let i = 1; i < buttonEntityIds.length; i++) {
|
|
177718
177877
|
homeAssistant.callAction({
|
|
177719
177878
|
action: "button.press",
|
|
@@ -177728,7 +177887,6 @@ var vacuumRvcRunModeConfig = {
|
|
|
177728
177887
|
}
|
|
177729
177888
|
const vacuumEntityId = homeAssistant.entityId;
|
|
177730
177889
|
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
177731
|
-
serviceArea.state.selectedAreas = [];
|
|
177732
177890
|
return buildValetudoSegmentAction(
|
|
177733
177891
|
vacuumEntityId,
|
|
177734
177892
|
selectedAreas,
|
|
@@ -177751,7 +177909,6 @@ var vacuumRvcRunModeConfig = {
|
|
|
177751
177909
|
logger194.info(
|
|
177752
177910
|
`Starting cleaning with selected areas: ${roomIds.join(", ")}`
|
|
177753
177911
|
);
|
|
177754
|
-
serviceArea.state.selectedAreas = [];
|
|
177755
177912
|
if (isDreameVacuum(attributes7)) {
|
|
177756
177913
|
if (targetMapName) {
|
|
177757
177914
|
const vacName = vacuumEntityId.replace("vacuum.", "");
|
|
@@ -178209,33 +178366,24 @@ function buildSupportedModes3(fanSpeedList, mopIntensityList, cleaningModeOption
|
|
|
178209
178366
|
}
|
|
178210
178367
|
return modes;
|
|
178211
178368
|
}
|
|
178212
|
-
var
|
|
178213
|
-
|
|
178214
|
-
|
|
178215
|
-
|
|
178216
|
-
"Vacuuming",
|
|
178217
|
-
"Sweep",
|
|
178218
|
-
"vacuum",
|
|
178219
|
-
"sweeping"
|
|
178220
|
-
],
|
|
178221
|
-
[1 /* Mopping */]: ["Mopping", "Mop", "mopping", "mop", "wet_mop"],
|
|
178222
|
-
[2 /* SweepingAndMopping */]: [
|
|
178223
|
-
"Sweeping and mopping",
|
|
178224
|
-
"Vacuum and mop",
|
|
178225
|
-
"Vacuum & Mop",
|
|
178226
|
-
"Vacuum & mop",
|
|
178227
|
-
"vacuum_and_mop",
|
|
178228
|
-
"sweeping_and_mopping"
|
|
178229
|
-
],
|
|
178230
|
-
[3 /* MoppingAfterSweeping */]: [
|
|
178231
|
-
"Mopping after sweeping",
|
|
178232
|
-
"mopping_after_sweeping",
|
|
178233
|
-
"Vacuum then mop",
|
|
178234
|
-
"Mop after vacuum",
|
|
178235
|
-
"vacuum_then_mop",
|
|
178236
|
-
"mop_after_vacuum"
|
|
178237
|
-
]
|
|
178369
|
+
var CLEAN_TOKENS = {
|
|
178370
|
+
vacuum: /\b(vacuum|vacuuming|sweep|sweeping|suction)\b/i,
|
|
178371
|
+
mop: /\b(mop|mopping|wipe|wet|wash|scrub)\b/i,
|
|
178372
|
+
sequential: /\b(then|after|before|followed|following|first|secondly|sequentially)\b/i
|
|
178238
178373
|
};
|
|
178374
|
+
function normalizeCleanLabel(s) {
|
|
178375
|
+
return s.toLowerCase().replace(/[_\-+&/. ]+/g, " ").replace(/\band\b/g, " ").trim();
|
|
178376
|
+
}
|
|
178377
|
+
function classifyCleanOption(option) {
|
|
178378
|
+
const s = normalizeCleanLabel(option);
|
|
178379
|
+
const hasVac = CLEAN_TOKENS.vacuum.test(s);
|
|
178380
|
+
const hasMop = CLEAN_TOKENS.mop.test(s);
|
|
178381
|
+
const hasSeq = CLEAN_TOKENS.sequential.test(s);
|
|
178382
|
+
if (hasVac && hasMop && hasSeq) return 3 /* MoppingAfterSweeping */;
|
|
178383
|
+
if (hasVac && hasMop) return 2 /* SweepingAndMopping */;
|
|
178384
|
+
if (hasMop) return 1 /* Mopping */;
|
|
178385
|
+
return 0 /* Sweeping */;
|
|
178386
|
+
}
|
|
178239
178387
|
var CLEAN_TYPE_LABELS = {
|
|
178240
178388
|
[0 /* Sweeping */]: "Sweeping",
|
|
178241
178389
|
[1 /* Mopping */]: "Mopping",
|
|
@@ -178368,17 +178516,7 @@ function matchMopIntensityOption(name, availableOptions) {
|
|
|
178368
178516
|
}
|
|
178369
178517
|
function parseCleanType(modeString) {
|
|
178370
178518
|
if (!modeString) return 0 /* Sweeping */;
|
|
178371
|
-
|
|
178372
|
-
if (s.includes("mopping after") || s.includes("after sweeping") || s.includes("then_mop") || s.includes("then mop")) {
|
|
178373
|
-
return 3 /* MoppingAfterSweeping */;
|
|
178374
|
-
}
|
|
178375
|
-
if (s.includes("and") || s.includes("sweeping and mopping")) {
|
|
178376
|
-
return 2 /* SweepingAndMopping */;
|
|
178377
|
-
}
|
|
178378
|
-
if (s === "mopping" || s.includes("mop")) {
|
|
178379
|
-
return 1 /* Mopping */;
|
|
178380
|
-
}
|
|
178381
|
-
return 0 /* Sweeping */;
|
|
178519
|
+
return classifyCleanOption(modeString);
|
|
178382
178520
|
}
|
|
178383
178521
|
function cleanTypeToModeId(ct) {
|
|
178384
178522
|
switch (ct) {
|
|
@@ -178419,30 +178557,20 @@ var CLEAN_TYPE_FALLBACK = {
|
|
|
178419
178557
|
[3 /* MoppingAfterSweeping */]: 2 /* SweepingAndMopping */
|
|
178420
178558
|
};
|
|
178421
178559
|
function findMatchingCleanOption(ct, availableOptions) {
|
|
178422
|
-
|
|
178423
|
-
|
|
178560
|
+
if (!availableOptions || availableOptions.length === 0) {
|
|
178561
|
+
return CLEAN_TYPE_LABELS[ct];
|
|
178562
|
+
}
|
|
178424
178563
|
const typesToTry = [ct];
|
|
178425
178564
|
const fallback = CLEAN_TYPE_FALLBACK[ct];
|
|
178426
178565
|
if (fallback !== void 0) typesToTry.push(fallback);
|
|
178427
178566
|
for (const type of typesToTry) {
|
|
178428
|
-
const
|
|
178429
|
-
|
|
178430
|
-
const match = availableOptions.find(
|
|
178431
|
-
(o) => o.toLowerCase() === alias.toLowerCase()
|
|
178432
|
-
);
|
|
178433
|
-
if (match) return match;
|
|
178434
|
-
}
|
|
178435
|
-
for (const alias of typeAliases) {
|
|
178436
|
-
const match = availableOptions.find(
|
|
178437
|
-
(o) => o.toLowerCase().includes(alias.toLowerCase())
|
|
178438
|
-
);
|
|
178439
|
-
if (match) return match;
|
|
178440
|
-
}
|
|
178567
|
+
const match = availableOptions.find((o) => classifyCleanOption(o) === type);
|
|
178568
|
+
if (match) return match;
|
|
178441
178569
|
}
|
|
178442
178570
|
logger196.warn(
|
|
178443
178571
|
`No match for ${CLEAN_TYPE_LABELS[ct]} in [${availableOptions.join(", ")}]`
|
|
178444
178572
|
);
|
|
178445
|
-
return
|
|
178573
|
+
return availableOptions[0];
|
|
178446
178574
|
}
|
|
178447
178575
|
function buildCleaningModeAction(targetCleanType, agent) {
|
|
178448
178576
|
const selectEntityId = getCleaningModeSelectEntity(agent);
|
|
@@ -178577,7 +178705,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
|
|
|
178577
178705
|
const vacuumEntityId = homeAssistant.entityId;
|
|
178578
178706
|
const mapping = homeAssistant.state.mapping;
|
|
178579
178707
|
logger196.info(
|
|
178580
|
-
`setCleanMode(${mode}) for ${vacuumEntityId}
|
|
178708
|
+
`setCleanMode(${mode}) for ${vacuumEntityId}, suctionEntity=${mapping?.suctionLevelEntity ?? "none"}, mopEntity=${mapping?.mopIntensityEntity ?? "none"}, fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])}, customTags=${JSON.stringify(customFanSpeedTags ?? {})}`
|
|
178581
178709
|
);
|
|
178582
178710
|
if (mopIntensityList && mopIntensityList.length > 0 && isMopIntensityMode(mode)) {
|
|
178583
178711
|
const mopIndex = mode - MOP_INTENSITY_MODE_BASE;
|
|
@@ -180544,7 +180672,7 @@ var BridgeEndpointManager = class extends Service {
|
|
|
180544
180672
|
this.mappingFingerprints.delete(endpoint.entityId);
|
|
180545
180673
|
} else if (this.registry.isAutoComposedDevicesEnabled() && this.registry.isComposedSubEntityUsed(endpoint.entityId)) {
|
|
180546
180674
|
this.log.info(
|
|
180547
|
-
`Deleting standalone endpoint ${endpoint.entityId}
|
|
180675
|
+
`Deleting standalone endpoint ${endpoint.entityId}, consumed by composed device`
|
|
180548
180676
|
);
|
|
180549
180677
|
try {
|
|
180550
180678
|
await endpoint.delete();
|
|
@@ -180582,14 +180710,14 @@ var BridgeEndpointManager = class extends Service {
|
|
|
180582
180710
|
if (!memoryLimitReached && isHeapUnderPressure()) {
|
|
180583
180711
|
memoryLimitReached = true;
|
|
180584
180712
|
this.log.error(
|
|
180585
|
-
"Memory pressure detected
|
|
180713
|
+
"Memory pressure detected, skipping remaining entities to prevent OOM crash. Reduce the number of entities in this bridge or increase the Node.js heap size (NODE_OPTIONS=--max-old-space-size=1024)."
|
|
180586
180714
|
);
|
|
180587
180715
|
}
|
|
180588
180716
|
if (memoryLimitReached) {
|
|
180589
180717
|
if (!existingEndpoints.some((e) => e.entityId === entityId)) {
|
|
180590
180718
|
this._failedEntities.push({
|
|
180591
180719
|
entityId,
|
|
180592
|
-
reason: "Skipped due to memory pressure
|
|
180720
|
+
reason: "Skipped due to memory pressure, reduce entities or increase heap size"
|
|
180593
180721
|
});
|
|
180594
180722
|
}
|
|
180595
180723
|
continue;
|
|
@@ -180601,7 +180729,7 @@ var BridgeEndpointManager = class extends Service {
|
|
|
180601
180729
|
}
|
|
180602
180730
|
if (this.registry.isAutoComposedDevicesEnabled() && this.registry.isComposedSubEntityUsed(entityId)) {
|
|
180603
180731
|
this.log.debug(
|
|
180604
|
-
`Skipping ${entityId}
|
|
180732
|
+
`Skipping ${entityId}, already part of a composed device`
|
|
180605
180733
|
);
|
|
180606
180734
|
continue;
|
|
180607
180735
|
}
|
|
@@ -180701,7 +180829,7 @@ var BridgeEndpointManager = class extends Service {
|
|
|
180701
180829
|
}
|
|
180702
180830
|
/**
|
|
180703
180831
|
* Log detailed behavior error information for debugging "Behaviors have errors".
|
|
180704
|
-
* Matter.js EndpointBehaviorsError extends AggregateError
|
|
180832
|
+
* Matter.js EndpointBehaviorsError extends AggregateError, the `errors` array
|
|
180705
180833
|
* contains individual behavior crash errors (one per failed behavior).
|
|
180706
180834
|
*/
|
|
180707
180835
|
logDetailedError(entityId, error) {
|
|
@@ -180850,7 +180978,7 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
180850
180978
|
* Check if auto composed devices mode is enabled.
|
|
180851
180979
|
* When enabled, temperature sensors with auto-mapped humidity/pressure/battery
|
|
180852
180980
|
* build real Matter Composed Devices (BridgedNodeEndpoint with sub-endpoints)
|
|
180853
|
-
* rather than stacking extra clusters onto a flat TemperatureSensor
|
|
180981
|
+
* rather than stacking extra clusters onto a flat TemperatureSensor.
|
|
180854
180982
|
* Apple Home, Google Home, and Alexa render each sub-endpoint using its
|
|
180855
180983
|
* own device type.
|
|
180856
180984
|
*/
|
|
@@ -180996,8 +181124,8 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
180996
181124
|
} else if (id.endsWith("_mode")) {
|
|
180997
181125
|
const options = state.attributes?.options;
|
|
180998
181126
|
if (options?.some(
|
|
180999
|
-
(o) => /^(vacuum|mop|sweep|vacuum_and_mop|vacuum_then_mop|mopping|sweeping|sweeping_and_mopping|mopping_after_sweeping)$/i.test(
|
|
181000
|
-
o
|
|
181127
|
+
(o) => /^(vacuum|mop|sweep|sweep_mop|sweep_before_mopping|sweep_then_mop|vacuum_and_mop|vacuum_then_mop|mopping|sweeping|sweeping_and_mopping|mopping_after_sweeping)$/i.test(
|
|
181128
|
+
o.replace(/\s+/g, "_")
|
|
181001
181129
|
)
|
|
181002
181130
|
)) {
|
|
181003
181131
|
cleaningModeEntity = entity.entity_id;
|
|
@@ -181155,14 +181283,14 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
181155
181283
|
const segments = areaMapping[haAreaId];
|
|
181156
181284
|
if (!segments || segments.length === 0) {
|
|
181157
181285
|
_BridgeRegistry.cleanAreaLogger.debug(
|
|
181158
|
-
`${entityId}: Skipping HA area ${haAreaId}
|
|
181286
|
+
`${entityId}: Skipping HA area ${haAreaId}, no segments mapped`
|
|
181159
181287
|
);
|
|
181160
181288
|
continue;
|
|
181161
181289
|
}
|
|
181162
181290
|
if (validSegmentIds && !segments.some((sid) => validSegmentIds.has(sid))) {
|
|
181163
181291
|
const areaName2 = this.registry.areas.get(haAreaId) ?? haAreaId;
|
|
181164
181292
|
_BridgeRegistry.cleanAreaLogger.info(
|
|
181165
|
-
`${entityId}: Skipping stale HA area "${areaName2}" (${haAreaId})
|
|
181293
|
+
`${entityId}: Skipping stale HA area "${areaName2}" (${haAreaId}), segments [${segments.join(", ")}] no longer exist on vacuum`
|
|
181166
181294
|
);
|
|
181167
181295
|
continue;
|
|
181168
181296
|
}
|
|
@@ -181638,7 +181766,7 @@ ${e?.toString()}`);
|
|
|
181638
181766
|
);
|
|
181639
181767
|
if (totalSubs === 0 && sessions.length > 0) {
|
|
181640
181768
|
this.log.warn(
|
|
181641
|
-
`All subscriptions lost
|
|
181769
|
+
`All subscriptions lost, ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
|
|
181642
181770
|
);
|
|
181643
181771
|
if (!this.deadSessionTimer) {
|
|
181644
181772
|
this.deadSessionTimer = setTimeout(() => {
|
|
@@ -181677,7 +181805,7 @@ ${e?.toString()}`);
|
|
|
181677
181805
|
for (const s of [...sessionManager.sessions]) {
|
|
181678
181806
|
if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
|
|
181679
181807
|
this.log.info(
|
|
181680
|
-
`Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs)
|
|
181808
|
+
`Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs), replaced by session ${newSession.id}`
|
|
181681
181809
|
);
|
|
181682
181810
|
s.initiateForceClose().catch(() => {
|
|
181683
181811
|
});
|
|
@@ -182098,7 +182226,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
182098
182226
|
}
|
|
182099
182227
|
}
|
|
182100
182228
|
} else {
|
|
182101
|
-
logger205.warn(`${entityId}: No device_id
|
|
182229
|
+
logger205.warn(`${entityId}: No device_id, cannot auto-assign battery`);
|
|
182102
182230
|
}
|
|
182103
182231
|
const payload = {
|
|
182104
182232
|
entity_id: entityId,
|
|
@@ -182154,7 +182282,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
182154
182282
|
* Previous approaches that pushed state through
|
|
182155
182283
|
* HomeAssistantEntityBehavior failed because the reactor writes
|
|
182156
182284
|
* (RvcOperationalStateServer.update()) run inside the postCommit
|
|
182157
|
-
* phase of the HAEntityBehavior transaction
|
|
182285
|
+
* phase of the HAEntityBehavior transaction, those writes are
|
|
182158
182286
|
* buffered but never committed, so no attrsChanged event reaches
|
|
182159
182287
|
* the ServerSubscription.
|
|
182160
182288
|
*
|
|
@@ -182400,11 +182528,11 @@ var ServerModeEndpointManager = class extends Service {
|
|
|
182400
182528
|
}
|
|
182401
182529
|
if (isHeapUnderPressure()) {
|
|
182402
182530
|
this.log.error(
|
|
182403
|
-
"Memory pressure detected
|
|
182531
|
+
"Memory pressure detected, cannot create device endpoint. Reduce entities on other bridges or increase the Node.js heap size (NODE_OPTIONS=--max-old-space-size=1024)."
|
|
182404
182532
|
);
|
|
182405
182533
|
this._failedEntities.push({
|
|
182406
182534
|
entityId,
|
|
182407
|
-
reason: "Skipped due to memory pressure
|
|
182535
|
+
reason: "Skipped due to memory pressure, reduce entities or increase heap size"
|
|
182408
182536
|
});
|
|
182409
182537
|
return;
|
|
182410
182538
|
}
|
|
@@ -182794,7 +182922,7 @@ function patchLevelControlTlv() {
|
|
|
182794
182922
|
);
|
|
182795
182923
|
} else {
|
|
182796
182924
|
logger206.warn(
|
|
182797
|
-
"Failed to patch LevelControl TLV schemas
|
|
182925
|
+
"Failed to patch LevelControl TLV schemas, field definitions not found. Google Home brightness adjustment may not work."
|
|
182798
182926
|
);
|
|
182799
182927
|
}
|
|
182800
182928
|
}
|