@riddix/hamh 2.1.0-alpha.872 → 2.1.0-alpha.873

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.
@@ -158205,6 +158205,139 @@ function ensureCommissioningConfig(server) {
158205
158205
  // src/services/bridges/bridge.ts
158206
158206
  init_diagnostic_event_bus();
158207
158207
 
158208
+ // src/services/bridges/entity-isolation-service.ts
158209
+ init_esm();
158210
+ init_diagnostic_event_bus();
158211
+ var logger204 = Logger.get("EntityIsolation");
158212
+ var EntityIsolationServiceImpl = class {
158213
+ isolatedEntities = /* @__PURE__ */ new Map();
158214
+ isolationCallbacks = /* @__PURE__ */ new Map();
158215
+ /**
158216
+ * Register a callback to be called when an entity needs to be isolated.
158217
+ * The callback should remove the entity from the bridge's aggregator.
158218
+ */
158219
+ registerIsolationCallback(bridgeId, callback) {
158220
+ this.isolationCallbacks.set(bridgeId, callback);
158221
+ }
158222
+ unregisterIsolationCallback(bridgeId) {
158223
+ this.isolationCallbacks.delete(bridgeId);
158224
+ }
158225
+ /**
158226
+ * Parse the endpoint path from a Matter.js error message and extract the entity name.
158227
+ * Example path: "ed5b4f8d042e4599b833f21da4ededba.aggregator.Küchenlicht.onOff.on"
158228
+ * Returns: { bridgeId: "ed5b4f8d...", entityName: "Küchenlicht" }
158229
+ */
158230
+ parseEndpointPath(errorMessage) {
158231
+ const match = errorMessage.match(/([a-f0-9]{32})\.aggregator\.([^.\s>]+)/i);
158232
+ if (match) {
158233
+ return {
158234
+ bridgeId: match[1],
158235
+ entityName: match[2]
158236
+ };
158237
+ }
158238
+ return null;
158239
+ }
158240
+ classifyError(msg) {
158241
+ if (msg.includes("Invalid intervalMs")) {
158242
+ return "Subscription timing error (Invalid intervalMs)";
158243
+ }
158244
+ if (msg.includes("Behaviors have errors")) {
158245
+ return "Behavior initialization failure";
158246
+ }
158247
+ if (msg.includes("TransactionDestroyedError")) {
158248
+ return "Transaction destroyed during operation";
158249
+ }
158250
+ if (msg.includes("DestroyedDependencyError")) {
158251
+ return "Dependency destroyed during operation";
158252
+ }
158253
+ if (msg.includes("UninitializedDependencyError")) {
158254
+ return "Uninitialized dependency access";
158255
+ }
158256
+ if (msg.includes("Endpoint storage inaccessible")) {
158257
+ return "Endpoint storage inaccessible";
158258
+ }
158259
+ if (msg.includes("Error initializing part")) {
158260
+ return "Endpoint construction failure";
158261
+ }
158262
+ if (msg.includes("aggregator.")) {
158263
+ return "Runtime error in endpoint";
158264
+ }
158265
+ return null;
158266
+ }
158267
+ /**
158268
+ * Attempt to isolate an entity based on an error.
158269
+ * Returns true if the entity was successfully identified and isolation was triggered.
158270
+ */
158271
+ async isolateFromError(error) {
158272
+ const msg = error instanceof Error ? error.message : String(error);
158273
+ const classification = this.classifyError(msg);
158274
+ if (!classification) {
158275
+ return false;
158276
+ }
158277
+ const parsed = this.parseEndpointPath(msg);
158278
+ if (!parsed) {
158279
+ logger204.warn("Could not parse entity from error:", msg);
158280
+ return false;
158281
+ }
158282
+ const { bridgeId, entityName } = parsed;
158283
+ const callback = this.isolationCallbacks.get(bridgeId);
158284
+ if (!callback) {
158285
+ logger204.warn(
158286
+ `No isolation callback registered for bridge ${bridgeId}, entity: ${entityName}`
158287
+ );
158288
+ return false;
158289
+ }
158290
+ const key = `${bridgeId}:${entityName}`;
158291
+ if (this.isolatedEntities.has(key)) {
158292
+ return true;
158293
+ }
158294
+ const reason = `${classification}. Entity isolated to protect bridge stability.`;
158295
+ this.isolatedEntities.set(key, {
158296
+ entityId: entityName,
158297
+ reason,
158298
+ failedAt: (/* @__PURE__ */ new Date()).toISOString()
158299
+ });
158300
+ logger204.warn(
158301
+ `Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
158302
+ );
158303
+ diagnosticEventBus.emit("entity_error", `Entity isolated: ${entityName}`, {
158304
+ bridgeId,
158305
+ entityId: entityName,
158306
+ details: { reason: classification }
158307
+ });
158308
+ try {
158309
+ await callback(entityName);
158310
+ return true;
158311
+ } catch (e) {
158312
+ logger204.error(`Failed to isolate entity ${entityName}:`, e);
158313
+ return false;
158314
+ }
158315
+ }
158316
+ /**
158317
+ * Get all isolated entities for a specific bridge.
158318
+ */
158319
+ getIsolatedEntities(bridgeId) {
158320
+ const result = [];
158321
+ for (const [key, entity] of this.isolatedEntities) {
158322
+ if (key.startsWith(`${bridgeId}:`)) {
158323
+ result.push(entity);
158324
+ }
158325
+ }
158326
+ return result;
158327
+ }
158328
+ /**
158329
+ * Clear isolated entities for a bridge (e.g., on restart).
158330
+ */
158331
+ clearIsolatedEntities(bridgeId) {
158332
+ for (const key of this.isolatedEntities.keys()) {
158333
+ if (key.startsWith(`${bridgeId}:`)) {
158334
+ this.isolatedEntities.delete(key);
158335
+ }
158336
+ }
158337
+ }
158338
+ };
158339
+ var EntityIsolationService = new EntityIsolationServiceImpl();
158340
+
158208
158341
  // src/services/bridges/session-supervisor.ts
158209
158342
  init_dist();
158210
158343
  init_esm7();
@@ -159441,6 +159574,7 @@ var Bridge = class {
159441
159574
  }
159442
159575
  async runStart() {
159443
159576
  this.lastSyncedStates.clear();
159577
+ EntityIsolationService.clearIsolatedEntities(this.id);
159444
159578
  try {
159445
159579
  this.setStatus({
159446
159580
  code: BridgeStatus.Starting,
@@ -159974,7 +160108,7 @@ init_esm();
159974
160108
  init_esm7();
159975
160109
  import crypto6 from "node:crypto";
159976
160110
  init_home_assistant_entity_behavior();
159977
- var logger204 = Logger.get("BasicInformationServer");
160111
+ var logger205 = Logger.get("BasicInformationServer");
159978
160112
  var appliedUniqueIds = /* @__PURE__ */ new Map();
159979
160113
  var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer {
159980
160114
  async initialize() {
@@ -160020,7 +160154,7 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
160020
160154
  // records keyed on it can be shed (#385).
160021
160155
  uniqueId: this.frozenUniqueId(anchor)
160022
160156
  });
160023
- logger204.debug(
160157
+ logger205.debug(
160024
160158
  `[${entity.entity_id}] basicInfo vendor=${this.state.vendorName} product=${this.state.productName} label=${this.state.productLabel} serial=${this.state.serialNumber} node=${this.state.nodeLabel} uniqueId=${this.state.uniqueId}`
160025
160159
  );
160026
160160
  }
@@ -160050,7 +160184,7 @@ function isValidVendorId(value) {
160050
160184
  // src/matter/behaviors/electrical-energy-measurement-server.ts
160051
160185
  init_esm();
160052
160186
  init_home_assistant_entity_behavior();
160053
- var logger205 = Logger.get("ElectricalEnergyMeasurementServer");
160187
+ var logger206 = Logger.get("ElectricalEnergyMeasurementServer");
160054
160188
  var FeaturedBase = ElectricalEnergyMeasurementServer.with("CumulativeEnergy", "ImportedEnergy");
160055
160189
  var ElectricalEnergyMeasurementServerBase = class extends FeaturedBase {
160056
160190
  async initialize() {
@@ -160059,7 +160193,7 @@ var ElectricalEnergyMeasurementServerBase = class extends FeaturedBase {
160059
160193
  const entityId = homeAssistant.entityId;
160060
160194
  const energyEntity = homeAssistant.state.mapping?.energyEntity;
160061
160195
  if (energyEntity) {
160062
- logger205.debug(
160196
+ logger206.debug(
160063
160197
  `[${entityId}] ElectricalEnergyMeasurement using mapped energy entity: ${energyEntity}`
160064
160198
  );
160065
160199
  }
@@ -160115,7 +160249,7 @@ var HaElectricalEnergyMeasurementServer = ElectricalEnergyMeasurementServerBase.
160115
160249
  // src/matter/behaviors/electrical-power-measurement-server.ts
160116
160250
  init_esm();
160117
160251
  init_home_assistant_entity_behavior();
160118
- var logger206 = Logger.get("ElectricalPowerMeasurementServer");
160252
+ var logger207 = Logger.get("ElectricalPowerMeasurementServer");
160119
160253
  var FeaturedBase2 = ElectricalPowerMeasurementServer.with("AlternatingCurrent");
160120
160254
  var ElectricalPowerMeasurementServerBase = class extends FeaturedBase2 {
160121
160255
  async initialize() {
@@ -160124,7 +160258,7 @@ var ElectricalPowerMeasurementServerBase = class extends FeaturedBase2 {
160124
160258
  const entityId = homeAssistant.entityId;
160125
160259
  const powerEntity = homeAssistant.state.mapping?.powerEntity;
160126
160260
  if (powerEntity) {
160127
- logger206.debug(
160261
+ logger207.debug(
160128
160262
  `[${entityId}] ElectricalPowerMeasurement using mapped power entity: ${powerEntity}`
160129
160263
  );
160130
160264
  }
@@ -160257,7 +160391,7 @@ init_home_assistant_entity_behavior();
160257
160391
  // src/matter/behaviors/humidity-measurement-server.ts
160258
160392
  init_esm();
160259
160393
  init_home_assistant_entity_behavior();
160260
- var logger207 = Logger.get("HumidityMeasurementServer");
160394
+ var logger208 = Logger.get("HumidityMeasurementServer");
160261
160395
  var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementServer {
160262
160396
  async initialize() {
160263
160397
  await super.initialize();
@@ -160270,7 +160404,7 @@ var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementSer
160270
160404
  return;
160271
160405
  }
160272
160406
  const humidity = this.getHumidity(this.state.config, entity.state);
160273
- logger207.debug(
160407
+ logger208.debug(
160274
160408
  `Humidity ${entity.state.entity_id} raw=${entity.state.state} measuredValue=${humidity}`
160275
160409
  );
160276
160410
  applyPatchState(this.state, {
@@ -160300,7 +160434,7 @@ function HumidityMeasurementServer(config8) {
160300
160434
  // src/matter/behaviors/power-source-server.ts
160301
160435
  init_esm();
160302
160436
  init_home_assistant_entity_behavior();
160303
- var logger208 = Logger.get("PowerSourceServer");
160437
+ var logger209 = Logger.get("PowerSourceServer");
160304
160438
  var FeaturedBase3 = PowerSourceServer.with("Battery", "Rechargeable");
160305
160439
  var PowerSourceServerBase = class extends FeaturedBase3 {
160306
160440
  async initialize() {
@@ -160312,17 +160446,17 @@ var PowerSourceServerBase = class extends FeaturedBase3 {
160312
160446
  applyPatchState(this.state, {
160313
160447
  endpointList: [endpointNumber]
160314
160448
  });
160315
- logger208.debug(
160449
+ logger209.debug(
160316
160450
  `[${entityId}] PowerSource initialized with endpointList=[${endpointNumber}]`
160317
160451
  );
160318
160452
  } else {
160319
- logger208.warn(
160453
+ logger209.warn(
160320
160454
  `[${entityId}] PowerSource endpoint number is null during initialize - endpointList will be empty!`
160321
160455
  );
160322
160456
  }
160323
160457
  const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
160324
160458
  if (batteryEntity) {
160325
- logger208.debug(
160459
+ logger209.debug(
160326
160460
  `[${entityId}] PowerSource using mapped battery entity: ${batteryEntity}`
160327
160461
  );
160328
160462
  }
@@ -160698,7 +160832,7 @@ function notifyLightTurnedOff(entityId, haLastChanged) {
160698
160832
  sweepLastTurnOff(now);
160699
160833
  lastTurnOffTimestamps.set(entityId, { ts: now, haLastChanged });
160700
160834
  }
160701
- var logger209 = Logger.get("LevelControlServer");
160835
+ var logger210 = Logger.get("LevelControlServer");
160702
160836
  var FeaturedBase5 = LevelControlServer.with("OnOff", "Lighting");
160703
160837
  var LevelControlServerBase = class extends FeaturedBase5 {
160704
160838
  pendingTransitionTime;
@@ -160716,7 +160850,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160716
160850
  try {
160717
160851
  await super.initialize();
160718
160852
  } catch (error) {
160719
- logger209.error("super.initialize() failed:", error);
160853
+ logger210.error("super.initialize() failed:", error);
160720
160854
  throw error;
160721
160855
  }
160722
160856
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
@@ -160834,7 +160968,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160834
160968
  expectedLevel: remembered,
160835
160969
  timestamp: now2
160836
160970
  });
160837
- logger209.debug(
160971
+ logger210.debug(
160838
160972
  `[${entityId}] Storing level ${level} without calling HA - moveToLevel arrived ${sinceTurnOff}ms after a Matter off while still off (#434)`
160839
160973
  );
160840
160974
  return;
@@ -160845,7 +160979,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160845
160979
  const lastTurnOn = lastTurnOnTimestamps.get(entityId);
160846
160980
  const timeSinceTurnOn = lastTurnOn ? Date.now() - lastTurnOn : Infinity;
160847
160981
  if (level >= this.maxLevel && timeSinceTurnOn < 200) {
160848
- logger209.debug(
160982
+ logger210.debug(
160849
160983
  `[${entityId}] Ignoring moveToLevel(${level}) - Alexa brightness reset detected (${timeSinceTurnOn}ms after turn-on)`
160850
160984
  );
160851
160985
  return;
@@ -160891,7 +161025,7 @@ function LevelControlServer2(config8) {
160891
161025
  }
160892
161026
 
160893
161027
  // src/matter/behaviors/on-off-server.ts
160894
- var logger210 = Logger.get("OnOffServer");
161028
+ var logger211 = Logger.get("OnOffServer");
160895
161029
  var optimisticOnOffState = /* @__PURE__ */ new Map();
160896
161030
  var OPTIMISTIC_TIMEOUT_MS2 = 3e3;
160897
161031
  function sweepOptimisticOnOff(now) {
@@ -160955,7 +161089,7 @@ var OnOffServerBase = class extends OnOffServer {
160955
161089
  if (!action) {
160956
161090
  return;
160957
161091
  }
160958
- logger210.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
161092
+ logger211.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
160959
161093
  notifyLightTurnedOn(homeAssistant.entityId);
160960
161094
  if (!skipMomentaryFlip) {
160961
161095
  const now = Date.now();
@@ -160986,7 +161120,7 @@ var OnOffServerBase = class extends OnOffServer {
160986
161120
  if (!action) {
160987
161121
  return;
160988
161122
  }
160989
- logger210.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
161123
+ logger211.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
160990
161124
  const now = Date.now();
160991
161125
  sweepOptimisticOnOff(now);
160992
161126
  optimisticOnOffState.set(homeAssistant.entityId, {
@@ -161020,7 +161154,7 @@ function setOptimisticOnOff(entityId, expectedOnOff) {
161020
161154
  }
161021
161155
 
161022
161156
  // src/matter/behaviors/fan-control-server.ts
161023
- var logger211 = Logger.get("FanControlServer");
161157
+ var logger212 = Logger.get("FanControlServer");
161024
161158
  var defaultStepSize = 33.33;
161025
161159
  var minSpeedMax = 3;
161026
161160
  var maxSpeedMax = 100;
@@ -161360,7 +161494,7 @@ var FanControlServerBase = class extends FeaturedBase6 {
161360
161494
  const wasOff = homeAssistant.entity.state?.state === "off" || this.agent.has(OnOffBehavior) && !this.agent.get(OnOffBehavior).state.onOff;
161361
161495
  const remembered = this.remembered();
161362
161496
  if (wasOff) {
161363
- logger211.debug(
161497
+ logger212.debug(
161364
161498
  `[${homeAssistant.entityId}] power-on write ${percentage}%: restore flag=${restoreOnPowerOn}, last speed=${remembered.percent}`
161365
161499
  );
161366
161500
  }
@@ -161553,7 +161687,7 @@ var FanControlServerBase = class extends FeaturedBase6 {
161553
161687
  const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
161554
161688
  setOptimisticOnOff(entityId, on);
161555
161689
  } catch (e) {
161556
- logger211.debug(
161690
+ logger212.debug(
161557
161691
  `syncOnOff(${on}) failed: ${e instanceof Error ? e.message : String(e)}`
161558
161692
  );
161559
161693
  }
@@ -161696,7 +161830,7 @@ var FanOnOffServer = OnOffServer2({
161696
161830
  });
161697
161831
 
161698
161832
  // src/matter/endpoints/composed/composed-air-purifier-endpoint.ts
161699
- var logger212 = Logger.get("ComposedAirPurifierEndpoint");
161833
+ var logger213 = Logger.get("ComposedAirPurifierEndpoint");
161700
161834
  var temperatureConfig = {
161701
161835
  getValue(entity, agent) {
161702
161836
  const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
@@ -161914,7 +162048,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
161914
162048
  config8.powerEntityId ? "+Pwr" : "",
161915
162049
  config8.energyEntityId ? "+Nrg" : ""
161916
162050
  ].filter(Boolean).join("");
161917
- logger212.info(
162051
+ logger213.info(
161918
162052
  `Created composed air purifier ${primaryEntityId}: ${clusterLabels}`
161919
162053
  );
161920
162054
  return endpoint;
@@ -162232,12 +162366,12 @@ var ClimateHumidityMeasurementServer = HumidityMeasurementServer(humidityConfig2
162232
162366
  // src/matter/endpoints/legacy/climate/behaviors/climate-on-off-server.ts
162233
162367
  init_esm();
162234
162368
  init_home_assistant_entity_behavior();
162235
- var logger213 = Logger.get("ClimateOnOffServer");
162369
+ var logger214 = Logger.get("ClimateOnOffServer");
162236
162370
  var ClimateOnOffServer = OnOffServer2({
162237
162371
  turnOn: (_value, agent) => {
162238
162372
  const entity = agent.get(HomeAssistantEntityBehavior).entity;
162239
162373
  if (entity.state.state !== "off" && agent.get(OnOffServer).state.onOff) {
162240
- logger213.debug(
162374
+ logger214.debug(
162241
162375
  `[${entity.entity_id}] Skipping redundant OnOff.on(), cached state "${entity.state.state}"`
162242
162376
  );
162243
162377
  return void 0;
@@ -162272,7 +162406,7 @@ init_home_assistant_entity_behavior();
162272
162406
  init_esm();
162273
162407
  init_home_assistant_entity_behavior();
162274
162408
  init_transaction_is_offline();
162275
- var logger214 = Logger.get("ThermostatServer");
162409
+ var logger215 = Logger.get("ThermostatServer");
162276
162410
  var SystemMode = Thermostat3.SystemMode;
162277
162411
  var RunningMode = Thermostat3.ThermostatRunningMode;
162278
162412
  var nudgingSetpoints = /* @__PURE__ */ new Set();
@@ -162351,7 +162485,7 @@ function clearInactiveSetpointState(self, scope) {
162351
162485
  }
162352
162486
  function thermostatPreInitialize(self) {
162353
162487
  const currentLocal = self.state.localTemperature;
162354
- logger214.debug(
162488
+ logger215.debug(
162355
162489
  `initialize: features - heating=${self.features.heating}, cooling=${self.features.cooling}`
162356
162490
  );
162357
162491
  const localValue = typeof currentLocal === "number" && !Number.isNaN(currentLocal) ? currentLocal : currentLocal === null ? null : 2100;
@@ -162398,7 +162532,7 @@ function thermostatPreInitialize(self) {
162398
162532
  } else {
162399
162533
  clearInactiveSetpointState(self, "Cool");
162400
162534
  }
162401
- logger214.debug(
162535
+ logger215.debug(
162402
162536
  `initialize: after force-set - local=${self.state.localTemperature}`
162403
162537
  );
162404
162538
  self.state.thermostatRunningState = runningStateAllOff;
@@ -162491,7 +162625,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162491
162625
  maxCoolLimit,
162492
162626
  "cool"
162493
162627
  );
162494
- logger214.debug(
162628
+ logger215.debug(
162495
162629
  `update: limits heat=[${minHeatLimit}, ${maxHeatLimit}], cool=[${minCoolLimit}, ${maxCoolLimit}], systemMode=${systemMode}, runningMode=${runningMode}`
162496
162630
  );
162497
162631
  let controlSequence = config8.getControlSequence(entity.state, this.agent);
@@ -162567,18 +162701,18 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162567
162701
  */
162568
162702
  // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Called via thermostatPostInitialize + prototype copy
162569
162703
  heatingSetpointChanging(value, _oldValue, context) {
162570
- logger214.debug(
162704
+ logger215.debug(
162571
162705
  `heatingSetpointChanging: value=${value}, oldValue=${_oldValue}, isOffline=${transactionIsOffline(context)}`
162572
162706
  );
162573
162707
  if (transactionIsOffline(context)) {
162574
- logger214.debug(
162708
+ logger215.debug(
162575
162709
  "heatingSetpointChanging: skipping - transaction is offline"
162576
162710
  );
162577
162711
  return;
162578
162712
  }
162579
162713
  const next = Temperature.celsius(value / 100);
162580
162714
  if (!next) {
162581
- logger214.debug("heatingSetpointChanging: skipping - invalid temperature");
162715
+ logger215.debug("heatingSetpointChanging: skipping - invalid temperature");
162582
162716
  return;
162583
162717
  }
162584
162718
  this.agent.asLocalActor(() => {
@@ -162589,7 +162723,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162589
162723
  this.agent
162590
162724
  );
162591
162725
  const currentMode2 = this.state.systemMode;
162592
- logger214.debug(
162726
+ logger215.debug(
162593
162727
  `heatingSetpointChanging: supportsRange=${supportsRange}, systemMode=${currentMode2}, features.heating=${this.features.heating}, features.cooling=${this.features.cooling}`
162594
162728
  );
162595
162729
  if (!supportsRange) {
@@ -162599,12 +162733,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162599
162733
  const isOff = currentMode2 === Thermostat3.SystemMode.Off;
162600
162734
  if (isOff && this.features.heating) {
162601
162735
  if (nudgingSetpoints.has(homeAssistant.entityId)) {
162602
- logger214.debug(
162736
+ logger215.debug(
162603
162737
  `heatingSetpointChanging: skipping auto-resume - nudge write in progress`
162604
162738
  );
162605
162739
  return;
162606
162740
  }
162607
- logger214.info(
162741
+ logger215.info(
162608
162742
  `heatingSetpointChanging: auto-resume - switching to Heat (was Off)`
162609
162743
  );
162610
162744
  const modeAction = config8.setSystemMode(
@@ -162613,17 +162747,17 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162613
162747
  );
162614
162748
  homeAssistant.callAction(modeAction);
162615
162749
  } else if (!isAutoMode && !isHeatingMode) {
162616
- logger214.debug(
162750
+ logger215.debug(
162617
162751
  `heatingSetpointChanging: skipping - not in heating/auto mode (mode=${currentMode2}, haMode=${haHvacMode})`
162618
162752
  );
162619
162753
  return;
162620
162754
  }
162621
- logger214.debug(
162755
+ logger215.debug(
162622
162756
  `heatingSetpointChanging: proceeding - isAutoMode=${isAutoMode}, isHeatingMode=${isHeatingMode}, isOff=${isOff}, haMode=${haHvacMode}`
162623
162757
  );
162624
162758
  }
162625
162759
  const coolingSetpoint = this.features.cooling ? this.state.occupiedCoolingSetpoint : value;
162626
- logger214.debug(
162760
+ logger215.debug(
162627
162761
  `heatingSetpointChanging: calling setTemperature with heat=${next.celsius(true)}, cool=${coolingSetpoint}`
162628
162762
  );
162629
162763
  this.setTemperature(
@@ -162662,12 +162796,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162662
162796
  const isOff = currentMode2 === Thermostat3.SystemMode.Off;
162663
162797
  if (isOff && !this.features.heating && this.features.cooling) {
162664
162798
  if (nudgingSetpoints.has(homeAssistant.entityId)) {
162665
- logger214.debug(
162799
+ logger215.debug(
162666
162800
  `coolingSetpointChanging: skipping auto-resume - nudge write in progress`
162667
162801
  );
162668
162802
  return;
162669
162803
  }
162670
- logger214.info(
162804
+ logger215.info(
162671
162805
  `coolingSetpointChanging: auto-resume - switching to Cool (was Off)`
162672
162806
  );
162673
162807
  const modeAction = config8.setSystemMode(
@@ -162676,12 +162810,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162676
162810
  );
162677
162811
  homeAssistant.callAction(modeAction);
162678
162812
  } else if (!isAutoMode && !isCoolingMode) {
162679
- logger214.debug(
162813
+ logger215.debug(
162680
162814
  `coolingSetpointChanging: skipping - not in cooling/auto mode (mode=${currentMode2}, haMode=${haHvacMode})`
162681
162815
  );
162682
162816
  return;
162683
162817
  }
162684
- logger214.debug(
162818
+ logger215.debug(
162685
162819
  `coolingSetpointChanging: proceeding - isAutoMode=${isAutoMode}, isCoolingMode=${isCoolingMode}, isOff=${isOff}, haMode=${haHvacMode}`
162686
162820
  );
162687
162821
  }
@@ -162795,7 +162929,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162795
162929
  const effectiveMax = max ?? 5e3;
162796
162930
  if (value == null || Number.isNaN(value)) {
162797
162931
  const defaultValue = type === "heat" ? 2e3 : 2400;
162798
- logger214.debug(
162932
+ logger215.debug(
162799
162933
  `${type} setpoint is undefined, using default: ${defaultValue}`
162800
162934
  );
162801
162935
  return Math.max(effectiveMin, Math.min(effectiveMax, defaultValue));
@@ -163373,7 +163507,7 @@ function ClimateDevice(homeAssistantEntity, includeBasicInformation = true) {
163373
163507
  }
163374
163508
 
163375
163509
  // src/matter/endpoints/composed/composed-climate-fan-endpoint.ts
163376
- var logger215 = Logger.get("ComposedClimateFanEndpoint");
163510
+ var logger216 = Logger.get("ComposedClimateFanEndpoint");
163377
163511
  function createEndpointId3(entityId, customName) {
163378
163512
  const baseName = customName || entityId;
163379
163513
  return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
@@ -163411,7 +163545,7 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
163411
163545
  climateSub = new Endpoint(climateType, { id: `${endpointId}_climate` });
163412
163546
  } catch (error) {
163413
163547
  const message = error instanceof Error ? error.message : String(error);
163414
- logger215.warn(
163548
+ logger216.warn(
163415
163549
  `Companion fan: climate sub build failed for ${primaryEntityId}: ${message}`
163416
163550
  );
163417
163551
  return void 0;
@@ -163455,7 +163589,7 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
163455
163589
  endpointId,
163456
163590
  [climateSub, fanSub]
163457
163591
  );
163458
- logger215.info(`Created composed climate+fan endpoint ${primaryEntityId}`);
163592
+ logger216.info(`Created composed climate+fan endpoint ${primaryEntityId}`);
163459
163593
  return endpoint;
163460
163594
  }
163461
163595
  constructor(type, entityId, id, parts) {
@@ -163550,7 +163684,7 @@ init_home_assistant_entity_behavior();
163550
163684
  // src/matter/behaviors/pressure-measurement-server.ts
163551
163685
  init_esm();
163552
163686
  init_home_assistant_entity_behavior();
163553
- var logger216 = Logger.get("PressureMeasurementServer");
163687
+ var logger217 = Logger.get("PressureMeasurementServer");
163554
163688
  var MIN_PRESSURE = 300;
163555
163689
  var MAX_PRESSURE = 1100;
163556
163690
  var PressureMeasurementServerBase = class extends PressureMeasurementServer {
@@ -163578,7 +163712,7 @@ var PressureMeasurementServerBase = class extends PressureMeasurementServer {
163578
163712
  }
163579
163713
  const rounded = Math.round(value);
163580
163714
  if (rounded < MIN_PRESSURE || rounded > MAX_PRESSURE) {
163581
- logger216.warn(
163715
+ logger217.warn(
163582
163716
  `Pressure value ${rounded} (raw: ${value}) for ${entity.entity_id} is outside valid range [${MIN_PRESSURE}-${MAX_PRESSURE}], ignoring`
163583
163717
  );
163584
163718
  return null;
@@ -163597,7 +163731,7 @@ function PressureMeasurementServer2(config8) {
163597
163731
  }
163598
163732
 
163599
163733
  // src/matter/endpoints/composed/composed-sensor-endpoint.ts
163600
- var logger217 = Logger.get("ComposedSensorEndpoint");
163734
+ var logger218 = Logger.get("ComposedSensorEndpoint");
163601
163735
  var temperatureConfig2 = {
163602
163736
  getValue(entity, agent) {
163603
163737
  const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
@@ -163775,7 +163909,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
163775
163909
  if (config8.pressureEntityId && pressSub) {
163776
163910
  endpoint.subEndpoints.set(config8.pressureEntityId, pressSub);
163777
163911
  }
163778
- logger217.info(
163912
+ logger218.info(
163779
163913
  `Created composed sensor ${primaryEntityId} with ${parts.length} sub-endpoint(s): T${humSub ? "+H" : ""}${pressSub ? "+P" : ""}${config8.batteryEntityId ? "+Bat" : ""}${config8.powerEntityId ? "+Pwr" : ""}${config8.energyEntityId ? "+Nrg" : ""}`
163780
163914
  );
163781
163915
  return endpoint;
@@ -163912,7 +164046,7 @@ init_home_assistant_entity_behavior();
163912
164046
  // src/matter/behaviors/mode-select-server.ts
163913
164047
  init_esm();
163914
164048
  init_home_assistant_entity_behavior();
163915
- var logger218 = Logger.get("ModeSelectServer");
164049
+ var logger219 = Logger.get("ModeSelectServer");
163916
164050
  function buildSupportedModes(options) {
163917
164051
  return options.map((label, index) => ({
163918
164052
  label: label.length > 64 ? label.substring(0, 64) : label,
@@ -163949,13 +164083,13 @@ var ModeSelectServerBase = class extends ModeSelectServer {
163949
164083
  const options = config8.getOptions(homeAssistant.entity);
163950
164084
  const { newMode } = request;
163951
164085
  if (newMode < 0 || newMode >= options.length) {
163952
- logger218.warn(
164086
+ logger219.warn(
163953
164087
  `[${homeAssistant.entityId}] Invalid mode ${newMode}, options: [${options.join(", ")}]`
163954
164088
  );
163955
164089
  return;
163956
164090
  }
163957
164091
  const option = options[newMode];
163958
- logger218.info(
164092
+ logger219.info(
163959
164093
  `[${homeAssistant.entityId}] changeToMode(${newMode}) -> "${option}"`
163960
164094
  );
163961
164095
  applyPatchState(this.state, { currentMode: newMode });
@@ -164506,7 +164640,7 @@ var CoAlarmWithBatteryType = SmokeCoAlarmDevice.with(
164506
164640
  );
164507
164641
 
164508
164642
  // src/matter/endpoints/legacy/binary-sensor/index.ts
164509
- var logger219 = Logger.get("BinarySensorDevice");
164643
+ var logger220 = Logger.get("BinarySensorDevice");
164510
164644
  var deviceClasses = {
164511
164645
  [BinarySensorDeviceClass.CarbonMonoxide]: CoAlarmType,
164512
164646
  [BinarySensorDeviceClass.Gas]: CoAlarmType,
@@ -164557,11 +164691,11 @@ function BinarySensorDevice(homeAssistantEntity) {
164557
164691
  const originalTypeName = type.name;
164558
164692
  if (hasBattery && batteryTypes.has(type)) {
164559
164693
  type = batteryTypes.get(type);
164560
- logger219.info(
164694
+ logger220.info(
164561
164695
  `[${entityId}] Using battery variant: ${originalTypeName} -> ${type.name}, batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"}`
164562
164696
  );
164563
164697
  } else if (hasBattery) {
164564
- logger219.warn(
164698
+ logger220.warn(
164565
164699
  `[${entityId}] Has battery but no variant available for ${originalTypeName}`
164566
164700
  );
164567
164701
  }
@@ -164648,7 +164782,7 @@ init_home_assistant_entity_behavior();
164648
164782
  init_esm();
164649
164783
  init_home_assistant_actions();
164650
164784
  init_home_assistant_entity_behavior();
164651
- var logger220 = Logger.get("WindowCoveringServer");
164785
+ var logger221 = Logger.get("WindowCoveringServer");
164652
164786
  var MovementStatus = WindowCovering3.MovementStatus;
164653
164787
  var FeaturedBase7 = WindowCoveringServer.with(
164654
164788
  "Lift",
@@ -164859,7 +164993,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164859
164993
  }
164860
164994
  return existing100ths ?? current100ths;
164861
164995
  };
164862
- logger220.debug(
164996
+ logger221.debug(
164863
164997
  `Cover update for ${entity.entity_id}: state=${state.state}, lift=${currentLift}%, tilt=${currentTilt}%, ha=${MovementStatus[movementStatus]}, effective=${MovementStatus[globalStatus]}`
164864
164998
  );
164865
164999
  const overrideType = config8.getCoverType?.(state, this.agent);
@@ -164904,9 +165038,9 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164904
165038
  );
164905
165039
  if (Object.keys(appliedPatch).length > 0) {
164906
165040
  const hasOperationalChange = "operationalStatus" in appliedPatch;
164907
- const log = hasOperationalChange ? logger220.info : logger220.debug;
165041
+ const log = hasOperationalChange ? logger221.info : logger221.debug;
164908
165042
  log.call(
164909
- logger220,
165043
+ logger221,
164910
165044
  `Cover ${entity.entity_id} state changed: ${JSON.stringify(appliedPatch)}`
164911
165045
  );
164912
165046
  }
@@ -165015,7 +165149,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165015
165149
  }
165016
165150
  });
165017
165151
  } catch (error) {
165018
- logger220.debug(
165152
+ logger221.debug(
165019
165153
  `Optimistic ${axis} timeout write failed (endpoint may be closing): ${error}`
165020
165154
  );
165021
165155
  }
@@ -165050,7 +165184,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165050
165184
  const currentTilt = this.state.currentPositionTiltPercent100ths ?? 0;
165051
165185
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
165052
165186
  const flags2 = this.state.config.getDiagnosticFlags?.(this.agent);
165053
- logger220.info(
165187
+ logger221.info(
165054
165188
  `handleMovement ${homeAssistant.entityId}: type=${MovementType[type]}, direction=${MovementDirection[direction]}, target=${targetPercent100ths}, currentLift=${currentLift}, currentTilt=${currentTilt}${flags2 ? `, ${flags2}` : ""}`
165055
165189
  );
165056
165190
  if (type === MovementType.Lift) {
@@ -165069,7 +165203,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165069
165203
  }
165070
165204
  } else if (type === MovementType.Tilt) {
165071
165205
  if (targetPercent100ths == null && this.lastLiftMovementDirection === direction && Date.now() - this.lastLiftMovementMs < 50) {
165072
- logger220.info(
165206
+ logger221.info(
165073
165207
  `Skipping tilt ${MovementDirection[direction]}, lift already moving in same direction`
165074
165208
  );
165075
165209
  return;
@@ -165114,7 +165248,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165114
165248
  } else {
165115
165249
  this.startOptimisticMovement("lift", MovementStatus.Opening, end);
165116
165250
  }
165117
- logger220.info(
165251
+ logger221.info(
165118
165252
  `handleLiftOpen ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
165119
165253
  );
165120
165254
  homeAssistant.callAction(action);
@@ -165130,7 +165264,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165130
165264
  } else {
165131
165265
  this.startOptimisticMovement("lift", MovementStatus.Closing, end);
165132
165266
  }
165133
- logger220.info(
165267
+ logger221.info(
165134
165268
  `handleLiftClose ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
165135
165269
  );
165136
165270
  homeAssistant.callAction(action);
@@ -165160,7 +165294,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165160
165294
  const isFirstInSequence = timeSinceLastCommand > _WindowCoveringServerBase.COMMAND_SEQUENCE_THRESHOLD_MS;
165161
165295
  const overrideMs = this.resolveDebounceOverride(homeAssistant);
165162
165296
  const debounceMs = overrideMs != null ? overrideMs : isFirstInSequence ? _WindowCoveringServerBase.DEBOUNCE_INITIAL_MS : _WindowCoveringServerBase.DEBOUNCE_SUBSEQUENT_MS;
165163
- logger220.debug(
165297
+ logger221.debug(
165164
165298
  `Lift command: target=${targetPosition}%, debounce=${debounceMs}ms (${overrideMs != null ? "override" : isFirstInSequence ? "initial" : "subsequent"})`
165165
165299
  );
165166
165300
  if (st.liftTimer) {
@@ -165192,7 +165326,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165192
165326
  this.startOptimisticMovement("tilt", MovementStatus.Opening, end);
165193
165327
  }
165194
165328
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
165195
- logger220.info(
165329
+ logger221.info(
165196
165330
  `handleTiltOpen ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
165197
165331
  );
165198
165332
  homeAssistant.callAction(action);
@@ -165210,7 +165344,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165210
165344
  this.startOptimisticMovement("tilt", MovementStatus.Closing, end);
165211
165345
  }
165212
165346
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
165213
- logger220.info(
165347
+ logger221.info(
165214
165348
  `handleTiltClose ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
165215
165349
  );
165216
165350
  homeAssistant.callAction(action);
@@ -165240,7 +165374,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
165240
165374
  const isFirstInSequence = timeSinceLastCommand > _WindowCoveringServerBase.COMMAND_SEQUENCE_THRESHOLD_MS;
165241
165375
  const overrideMs = this.resolveDebounceOverride(homeAssistant);
165242
165376
  const debounceMs = overrideMs != null ? overrideMs : isFirstInSequence ? _WindowCoveringServerBase.DEBOUNCE_INITIAL_MS : _WindowCoveringServerBase.DEBOUNCE_SUBSEQUENT_MS;
165243
- logger220.debug(
165377
+ logger221.debug(
165244
165378
  `Tilt command: target=${targetPosition}%, debounce=${debounceMs}ms (${overrideMs != null ? "override" : isFirstInSequence ? "initial" : "subsequent"})`
165245
165379
  );
165246
165380
  if (st.tiltTimer) {
@@ -165292,7 +165426,7 @@ function adjustPositionForWriting(position, flags2, matterSemantics) {
165292
165426
  }
165293
165427
 
165294
165428
  // src/matter/endpoints/legacy/cover/behaviors/cover-window-covering-server.ts
165295
- var logger221 = Logger.get("CoverWindowCoveringServer");
165429
+ var logger222 = Logger.get("CoverWindowCoveringServer");
165296
165430
  var attributes6 = (entity) => entity.attributes;
165297
165431
  var DEVICE_CLASS_TO_MATTER_TYPE = {
165298
165432
  curtain: {
@@ -165370,7 +165504,7 @@ var adjustPositionForReading2 = (position, agent) => {
165370
165504
  const { featureFlags } = agent.env.get(BridgeDataProvider);
165371
165505
  const matterSem = usesMatterSemantics(agent);
165372
165506
  const result = adjustPositionForReading(position, featureFlags, matterSem);
165373
- logger221.debug(`adjustPositionForReading: HA=${position}%, result=${result}%`);
165507
+ logger222.debug(`adjustPositionForReading: HA=${position}%, result=${result}%`);
165374
165508
  return result;
165375
165509
  };
165376
165510
  var adjustPositionForWriting2 = (position, agent) => {
@@ -165595,14 +165729,14 @@ var CoverAsDimmableLightWithBatteryType = DimmableLightDevice.with(
165595
165729
  );
165596
165730
 
165597
165731
  // src/matter/endpoints/legacy/cover/index.ts
165598
- var logger222 = Logger.get("CoverDevice");
165732
+ var logger223 = Logger.get("CoverDevice");
165599
165733
  var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
165600
165734
  const features = /* @__PURE__ */ new Set();
165601
165735
  if (testBit(supportedFeatures, CoverSupportedFeatures.support_open)) {
165602
165736
  features.add("Lift");
165603
165737
  features.add("PositionAwareLift");
165604
165738
  } else {
165605
- logger222.warn(
165739
+ logger223.warn(
165606
165740
  `[${entityId}] Cover has no support_open feature (supported_features=${supportedFeatures}), adding Lift anyway`
165607
165741
  );
165608
165742
  features.add("Lift");
@@ -165617,7 +165751,7 @@ var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
165617
165751
  features.add("PositionAwareTilt");
165618
165752
  }
165619
165753
  }
165620
- logger222.info(
165754
+ logger223.info(
165621
165755
  `[${entityId}] Creating WindowCovering with features: [${[...features].join(", ")}], supported_features=${supportedFeatures}`
165622
165756
  );
165623
165757
  const baseBehaviors2 = [
@@ -165641,16 +165775,16 @@ function CoverDevice(homeAssistantEntity) {
165641
165775
  const hasBatteryEntity = !!homeAssistantEntity.mapping?.batteryEntity;
165642
165776
  const hasBattery = hasBatteryAttr || hasBatteryEntity;
165643
165777
  if (hasBattery) {
165644
- logger222.info(
165778
+ logger223.info(
165645
165779
  `[${entityId}] Creating cover with PowerSource cluster, batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"}`
165646
165780
  );
165647
165781
  } else {
165648
- logger222.debug(
165782
+ logger223.debug(
165649
165783
  `[${entityId}] Creating cover without battery (batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"})`
165650
165784
  );
165651
165785
  }
165652
165786
  if (homeAssistantEntity.mapping?.coverExposeAsDimmableLight) {
165653
- logger222.info(`[${entityId}] Exposing cover as a Dimmable Light (#372)`);
165787
+ logger223.info(`[${entityId}] Exposing cover as a Dimmable Light (#372)`);
165654
165788
  const type = hasBattery ? CoverAsDimmableLightWithBatteryType : CoverAsDimmableLightType;
165655
165789
  return type.set({ homeAssistantEntity });
165656
165790
  }
@@ -165765,7 +165899,7 @@ function DishwasherEndpoint(homeAssistantEntity) {
165765
165899
  // src/matter/behaviors/generic-switch-server.ts
165766
165900
  init_esm();
165767
165901
  init_home_assistant_entity_behavior();
165768
- var logger223 = Logger.get("GenericSwitchServer");
165902
+ var logger224 = Logger.get("GenericSwitchServer");
165769
165903
  var SimpleBase = SwitchServer.with(
165770
165904
  "MomentarySwitch",
165771
165905
  "MomentarySwitchRelease",
@@ -165807,7 +165941,7 @@ var HaGenericSwitchServerBase = class extends SimpleBase {
165807
165941
  await super.initialize();
165808
165942
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
165809
165943
  const entityId = homeAssistant.entityId;
165810
- logger223.debug(`[${entityId}] GenericSwitch initialized (simple)`);
165944
+ logger224.debug(`[${entityId}] GenericSwitch initialized (simple)`);
165811
165945
  this.reactTo(homeAssistant.onChange, this.handleEventChange);
165812
165946
  }
165813
165947
  handleEventChange() {
@@ -165818,7 +165952,7 @@ var HaGenericSwitchServerBase = class extends SimpleBase {
165818
165952
  const eventType = attrs.event_type;
165819
165953
  if (!eventType) return;
165820
165954
  const entityId = homeAssistant.entityId;
165821
- logger223.debug(`[${entityId}] Event fired: ${eventType}`);
165955
+ logger224.debug(`[${entityId}] Event fired: ${eventType}`);
165822
165956
  this.triggerPress(eventType);
165823
165957
  }
165824
165958
  triggerPress(eventType) {
@@ -165864,7 +165998,7 @@ var HaGenericSwitchServerMultiBase = class extends FullBase {
165864
165998
  await super.initialize();
165865
165999
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
165866
166000
  const entityId = homeAssistant.entityId;
165867
- logger223.debug(`[${entityId}] GenericSwitch initialized (multi)`);
166001
+ logger224.debug(`[${entityId}] GenericSwitch initialized (multi)`);
165868
166002
  this.reactTo(homeAssistant.onChange, this.handleEventChange);
165869
166003
  }
165870
166004
  handleEventChange() {
@@ -165875,7 +166009,7 @@ var HaGenericSwitchServerMultiBase = class extends FullBase {
165875
166009
  const eventType = attrs.event_type;
165876
166010
  if (!eventType) return;
165877
166011
  const entityId = homeAssistant.entityId;
165878
- logger223.debug(`[${entityId}] Event fired: ${eventType}`);
166012
+ logger224.debug(`[${entityId}] Event fired: ${eventType}`);
165879
166013
  this.triggerPress(eventType);
165880
166014
  }
165881
166015
  triggerPress(eventType) {
@@ -166252,7 +166386,7 @@ init_nodejs();
166252
166386
  init_home_assistant_entity_behavior();
166253
166387
  var OperationalState4 = RvcOperationalState4.OperationalState;
166254
166388
  var ErrorState = RvcOperationalState4.ErrorState;
166255
- var logger224 = Logger.get("RvcOperationalStateServer");
166389
+ var logger225 = Logger.get("RvcOperationalStateServer");
166256
166390
  var activeStates = /* @__PURE__ */ new Set([
166257
166391
  OperationalState4.Running,
166258
166392
  OperationalState4.SeekingCharger
@@ -166304,7 +166438,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
166304
166438
  { force: true }
166305
166439
  );
166306
166440
  if (activeStates.has(previousState) && !activeStates.has(newState)) {
166307
- logger224.info(
166441
+ logger225.info(
166308
166442
  `Operation completed: ${OperationalState4[previousState]} -> ${OperationalState4[newState]}`
166309
166443
  );
166310
166444
  try {
@@ -166317,7 +166451,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
166317
166451
  this.context
166318
166452
  );
166319
166453
  } catch (e) {
166320
- logger224.debug("Failed to emit operationCompletion event:", e);
166454
+ logger225.debug("Failed to emit operationCompletion event:", e);
166321
166455
  }
166322
166456
  }
166323
166457
  }
@@ -166352,7 +166486,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
166352
166486
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
166353
166487
  homeAssistant.callAction(goHomeAction(void 0, this.agent));
166354
166488
  } else {
166355
- logger224.warn("GoHome command received but no goHome action configured");
166489
+ logger225.warn("GoHome command received but no goHome action configured");
166356
166490
  }
166357
166491
  return {
166358
166492
  commandResponseState: {
@@ -166372,7 +166506,7 @@ function RvcOperationalStateServer2(config8) {
166372
166506
  }
166373
166507
 
166374
166508
  // src/matter/endpoints/legacy/lawn-mower/behaviors/lawn-mower-rvc-operational-state-server.ts
166375
- var logger225 = Logger.get("LawnMowerRvcOperationalStateServer");
166509
+ var logger226 = Logger.get("LawnMowerRvcOperationalStateServer");
166376
166510
  function mapLawnMowerOperationalState(entity) {
166377
166511
  const state = entity.state;
166378
166512
  switch (state) {
@@ -166388,7 +166522,7 @@ function mapLawnMowerOperationalState(entity) {
166388
166522
  case "unavailable":
166389
166523
  return RvcOperationalState4.OperationalState.Error;
166390
166524
  default:
166391
- logger225.info(`Unknown lawn_mower state "${state}", treating as Stopped`);
166525
+ logger226.info(`Unknown lawn_mower state "${state}", treating as Stopped`);
166392
166526
  return RvcOperationalState4.OperationalState.Stopped;
166393
166527
  }
166394
166528
  }
@@ -166442,7 +166576,7 @@ function inferCleanedAreaProgress(cleanedSqm, orderedAreas) {
166442
166576
  }
166443
166577
 
166444
166578
  // src/matter/behaviors/rvc-run-mode-server.ts
166445
- var logger226 = Logger.get("RvcRunModeServer");
166579
+ var logger227 = Logger.get("RvcRunModeServer");
166446
166580
  var ROOM_MODE_BASE = 100;
166447
166581
  function isRoomMode(mode) {
166448
166582
  return mode >= ROOM_MODE_BASE;
@@ -166568,7 +166702,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166568
166702
  const s = getSession(this.endpoint);
166569
166703
  if (s.loggedShortCircuits.has(reason)) return;
166570
166704
  s.loggedShortCircuits.add(reason);
166571
- logger226.info(message);
166705
+ logger227.info(message);
166572
166706
  }
166573
166707
  /**
166574
166708
  * Read the currentRoomEntity sensor and update currentArea + progress
@@ -166625,7 +166759,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166625
166759
  }
166626
166760
  }
166627
166761
  if (matchedAreaId === null) {
166628
- logger226.info(
166762
+ logger227.info(
166629
166763
  `currentRoom sensor: no match for "${roomName}" (segmentId=${segmentId}), activeAreas=[${s.activeAreas.join(", ")}], supportedAreas=[${serviceArea.state.supportedAreas.map((a) => `${a.areaId}:${a.areaInfo.locationInfo?.locationName}`).join(", ")}]`
166630
166764
  );
166631
166765
  return;
@@ -166635,14 +166769,14 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166635
166769
  s.completedAreas.add(s.lastCurrentArea);
166636
166770
  }
166637
166771
  s.lastCurrentArea = matchedAreaId;
166638
- logger226.info(
166772
+ logger227.info(
166639
166773
  `currentRoom sensor: transition to area ${matchedAreaId} ("${roomName}"), completed: [${[...s.completedAreas].join(", ")}]`
166640
166774
  );
166641
166775
  this.trySetCurrentArea(matchedAreaId);
166642
166776
  } catch (e) {
166643
166777
  const msg = e instanceof Error ? e.message : String(e);
166644
166778
  if (!msg.includes("No provider for") && !msg.includes("not supported")) {
166645
- logger226.warn(`currentRoom sensor update failed: ${msg}`);
166779
+ logger227.warn(`currentRoom sensor update failed: ${msg}`);
166646
166780
  }
166647
166781
  }
166648
166782
  }
@@ -166722,7 +166856,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166722
166856
  cleaned,
166723
166857
  ordered
166724
166858
  );
166725
- logger226.debug(
166859
+ logger227.debug(
166726
166860
  `cleanedArea: raw=${raw} baseline=${s.cleanedAreaBaseline} cleaned=${cleaned} sizes=[${ordered.map((o) => `${o.areaId}:${o.sizeSqm}`).join(",")}] -> current=${currentArea} completed=[${completed.join(",")}]`
166727
166861
  );
166728
166862
  for (const id of completed) {
@@ -166736,7 +166870,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166736
166870
  } catch (e) {
166737
166871
  const msg = e instanceof Error ? e.message : String(e);
166738
166872
  if (!msg.includes("No provider for") && !msg.includes("not supported")) {
166739
- logger226.warn(`cleanedArea room update failed: ${msg}`);
166873
+ logger227.warn(`cleanedArea room update failed: ${msg}`);
166740
166874
  }
166741
166875
  }
166742
166876
  }
@@ -166751,7 +166885,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166751
166885
  const serviceArea = this.agent.get(ServiceAreaBehavior);
166752
166886
  if (serviceArea.state.currentArea !== areaId) {
166753
166887
  serviceArea.state.currentArea = areaId;
166754
- logger226.debug(`currentArea set to ${areaId}`);
166888
+ logger227.debug(`currentArea set to ${areaId}`);
166755
166889
  }
166756
166890
  this.updateProgress(serviceArea, areaId);
166757
166891
  } catch {
@@ -167034,7 +167168,7 @@ init_nodejs();
167034
167168
 
167035
167169
  // src/matter/behaviors/color-control-server.ts
167036
167170
  init_home_assistant_entity_behavior();
167037
- var logger227 = Logger.get("ColorControlServer");
167171
+ var logger228 = Logger.get("ColorControlServer");
167038
167172
  var optimisticColorState = /* @__PURE__ */ new Map();
167039
167173
  var OPTIMISTIC_TIMEOUT_MS3 = 3e3;
167040
167174
  var OPTIMISTIC_TOLERANCE2 = 5;
@@ -167073,7 +167207,7 @@ var ColorControlServerBase = class extends FeaturedBase8 {
167073
167207
  if (this.state.startUpColorTemperatureMireds == null) {
167074
167208
  this.state.startUpColorTemperatureMireds = defaultMireds;
167075
167209
  }
167076
- logger227.debug(
167210
+ logger228.debug(
167077
167211
  `initialize: set ColorTemperature defaults - min=${this.state.colorTempPhysicalMinMireds}, max=${this.state.colorTempPhysicalMaxMireds}, current=${this.state.colorTemperatureMireds}`
167078
167212
  );
167079
167213
  }
@@ -167627,7 +167761,7 @@ init_home_assistant_entity_behavior();
167627
167761
  init_esm();
167628
167762
  init_types2();
167629
167763
  init_home_assistant_entity_behavior();
167630
- var logger228 = Logger.get("LockServer");
167764
+ var logger229 = Logger.get("LockServer");
167631
167765
  var SUPPORTED_SLOT = 1;
167632
167766
  function normalizeSupportedIndex(index) {
167633
167767
  if (index === 0 || index === SUPPORTED_SLOT) {
@@ -167968,7 +168102,7 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167968
168102
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167969
168103
  const action = this.state.config.lock(void 0, this.agent);
167970
168104
  const hasPinProvided = !!request.pinCode;
167971
- logger228.debug(
168105
+ logger229.debug(
167972
168106
  `lockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}`
167973
168107
  );
167974
168108
  if (request.pinCode) {
@@ -167981,12 +168115,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167981
168115
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167982
168116
  const action = this.state.config.unlock(void 0, this.agent);
167983
168117
  const hasPinProvided = !!request.pinCode;
167984
- logger228.debug(
168118
+ logger229.debug(
167985
168119
  `unlockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}`
167986
168120
  );
167987
168121
  if (this.state.requirePinForRemoteOperation) {
167988
168122
  if (!request.pinCode) {
167989
- logger228.info(
168123
+ logger229.info(
167990
168124
  `unlockDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
167991
168125
  );
167992
168126
  throw new StatusResponseError(
@@ -167996,12 +168130,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167996
168130
  }
167997
168131
  const providedPin = new TextDecoder().decode(request.pinCode);
167998
168132
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
167999
- logger228.info(
168133
+ logger229.info(
168000
168134
  `unlockDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
168001
168135
  );
168002
168136
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
168003
168137
  }
168004
- logger228.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
168138
+ logger229.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
168005
168139
  action.data = { ...action.data, code: providedPin };
168006
168140
  }
168007
168141
  homeAssistant.callAction(action);
@@ -168143,7 +168277,7 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
168143
168277
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
168144
168278
  const action = this.state.config.lock(void 0, this.agent);
168145
168279
  const hasPinProvided = !!request.pinCode;
168146
- logger228.debug(
168280
+ logger229.debug(
168147
168281
  `lockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}`
168148
168282
  );
168149
168283
  if (request.pinCode) {
@@ -168157,12 +168291,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
168157
168291
  const unlatchConfig = this.state.config.unlatch;
168158
168292
  const action = unlatchConfig ? unlatchConfig(void 0, this.agent) : this.state.config.unlock(void 0, this.agent);
168159
168293
  const hasPinProvided = !!request.pinCode;
168160
- logger228.debug(
168294
+ logger229.debug(
168161
168295
  `unlockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}, usingUnlatch: ${!!unlatchConfig}`
168162
168296
  );
168163
168297
  if (this.state.requirePinForRemoteOperation) {
168164
168298
  if (!request.pinCode) {
168165
- logger228.info(
168299
+ logger229.info(
168166
168300
  `unlockDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
168167
168301
  );
168168
168302
  throw new StatusResponseError(
@@ -168172,12 +168306,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
168172
168306
  }
168173
168307
  const providedPin = new TextDecoder().decode(request.pinCode);
168174
168308
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
168175
- logger228.info(
168309
+ logger229.info(
168176
168310
  `unlockDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
168177
168311
  );
168178
168312
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
168179
168313
  }
168180
- logger228.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
168314
+ logger229.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
168181
168315
  action.data = { ...action.data, code: providedPin };
168182
168316
  }
168183
168317
  homeAssistant.callAction(action);
@@ -168186,12 +168320,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
168186
168320
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
168187
168321
  const action = this.state.config.unlock(void 0, this.agent);
168188
168322
  const hasPinProvided = !!request.pinCode;
168189
- logger228.debug(
168323
+ logger229.debug(
168190
168324
  `unboltDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}`
168191
168325
  );
168192
168326
  if (this.state.requirePinForRemoteOperation) {
168193
168327
  if (!request.pinCode) {
168194
- logger228.info(
168328
+ logger229.info(
168195
168329
  `unboltDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
168196
168330
  );
168197
168331
  throw new StatusResponseError(
@@ -168201,12 +168335,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
168201
168335
  }
168202
168336
  const providedPin = new TextDecoder().decode(request.pinCode);
168203
168337
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
168204
- logger228.info(
168338
+ logger229.info(
168205
168339
  `unboltDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
168206
168340
  );
168207
168341
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
168208
168342
  }
168209
- logger228.debug(`unboltDoor PIN verified for ${homeAssistant.entityId}`);
168343
+ logger229.debug(`unboltDoor PIN verified for ${homeAssistant.entityId}`);
168210
168344
  action.data = { ...action.data, code: providedPin };
168211
168345
  }
168212
168346
  homeAssistant.callAction(action);
@@ -168345,7 +168479,7 @@ init_home_assistant_entity_behavior();
168345
168479
  init_dist();
168346
168480
  init_esm();
168347
168481
  init_home_assistant_entity_behavior();
168348
- var logger229 = Logger.get("MediaPlayerKeypadInputServer");
168482
+ var logger230 = Logger.get("MediaPlayerKeypadInputServer");
168349
168483
  var MediaPlayerKeypadInputServer = class extends KeypadInputServer {
168350
168484
  sendKey(request) {
168351
168485
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
@@ -168356,12 +168490,12 @@ var MediaPlayerKeypadInputServer = class extends KeypadInputServer {
168356
168490
  const features = attributes9.supported_features ?? 0;
168357
168491
  const action = this.mapKeyToAction(request.keyCode, features);
168358
168492
  if (!action) {
168359
- logger229.debug(
168493
+ logger230.debug(
168360
168494
  `Unsupported key code ${request.keyCode} for ${homeAssistant.entityId}`
168361
168495
  );
168362
168496
  return { status: KeypadInput3.Status.UnsupportedKey };
168363
168497
  }
168364
- logger229.debug(
168498
+ logger230.debug(
168365
168499
  `sendKey(${request.keyCode}) \u2192 ${action} for ${homeAssistant.entityId}`
168366
168500
  );
168367
168501
  homeAssistant.callAction({ action });
@@ -168640,7 +168774,7 @@ init_home_assistant_entity_behavior();
168640
168774
  // src/matter/behaviors/speaker-level-control-server.ts
168641
168775
  init_esm();
168642
168776
  init_home_assistant_entity_behavior();
168643
- var logger230 = Logger.get("SpeakerLevelControlServer");
168777
+ var logger231 = Logger.get("SpeakerLevelControlServer");
168644
168778
  var optimisticLevelState2 = /* @__PURE__ */ new Map();
168645
168779
  var OPTIMISTIC_TIMEOUT_MS4 = 3e3;
168646
168780
  var OPTIMISTIC_TOLERANCE3 = 5;
@@ -168683,7 +168817,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
168683
168817
  currentLevel = Math.min(Math.max(minLevel, currentLevel), maxLevel);
168684
168818
  }
168685
168819
  const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
168686
- logger230.debug(
168820
+ logger231.debug(
168687
168821
  `[${entityId}] Volume update: HA=${currentLevelPercent != null ? Math.round(currentLevelPercent * 100) : "null"}% -> currentLevel=${currentLevel}`
168688
168822
  );
168689
168823
  const optimistic = optimisticLevelState2.get(entity.entity_id);
@@ -168731,7 +168865,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
168731
168865
  const config8 = this.state.config;
168732
168866
  const entityId = homeAssistant.entity.entity_id;
168733
168867
  const levelPercent = level / 254;
168734
- logger230.debug(
168868
+ logger231.debug(
168735
168869
  `[${entityId}] Volume command: level=${level} -> HA volume_level=${levelPercent}`
168736
168870
  );
168737
168871
  const current = config8.getValuePercent(
@@ -169769,7 +169903,7 @@ function mapEvseStatus(rawState, chargingSwitchOn) {
169769
169903
  }
169770
169904
 
169771
169905
  // src/matter/endpoints/legacy/sensor/devices/energy-evse.ts
169772
- var logger231 = Logger.get("EnergyEvse");
169906
+ var logger232 = Logger.get("EnergyEvse");
169773
169907
  var MIN_CHARGE_CURRENT_MA = 6e3;
169774
169908
  var MAX_CHARGE_CURRENT_MA = 32e3;
169775
169909
  var CIRCUIT_CAPACITY_MA = 32e3;
@@ -169853,7 +169987,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169853
169987
  dispatched = true;
169854
169988
  }
169855
169989
  if (!dispatched) {
169856
- logger231.debug(
169990
+ logger232.debug(
169857
169991
  `enableCharging ignored for ${homeAssistant.entityId}: no charging switch or current limit mapped`
169858
169992
  );
169859
169993
  return;
@@ -169893,7 +170027,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169893
170027
  chargingEnabledUntil: null
169894
170028
  });
169895
170029
  } catch (error) {
169896
- logger231.debug(
170030
+ logger232.debug(
169897
170031
  `EVSE charge-window expiry write failed (endpoint may be closing): ${error}`
169898
170032
  );
169899
170033
  } finally {
@@ -169924,7 +170058,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169924
170058
  chargingEnabledUntil: null
169925
170059
  });
169926
170060
  } else {
169927
- logger231.debug(
170061
+ logger232.debug(
169928
170062
  `disable ignored for ${homeAssistant.entityId}: no charging switch mapped`
169929
170063
  );
169930
170064
  }
@@ -170613,7 +170747,7 @@ init_home_assistant_entity_behavior();
170613
170747
  // src/matter/behaviors/pm25-concentration-measurement-server.ts
170614
170748
  init_esm();
170615
170749
  init_home_assistant_entity_behavior();
170616
- var logger232 = Logger.get("Pm25ConcentrationMeasurementServer");
170750
+ var logger233 = Logger.get("Pm25ConcentrationMeasurementServer");
170617
170751
  var Pm25ConcentrationMeasurementServerBase = Pm25ConcentrationMeasurementServer.with(
170618
170752
  ConcentrationMeasurement3.Feature.NumericMeasurement
170619
170753
  );
@@ -170637,11 +170771,11 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
170637
170771
  if (this.state.measurementMedium === void 0) {
170638
170772
  this.state.measurementMedium = ConcentrationMeasurement3.MeasurementMedium.Air;
170639
170773
  }
170640
- logger232.debug(
170774
+ logger233.debug(
170641
170775
  "Pm25ConcentrationMeasurementServer: before super.initialize()"
170642
170776
  );
170643
170777
  await super.initialize();
170644
- logger232.debug(
170778
+ logger233.debug(
170645
170779
  "Pm25ConcentrationMeasurementServer: after super.initialize()"
170646
170780
  );
170647
170781
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
@@ -170664,7 +170798,7 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
170664
170798
  };
170665
170799
 
170666
170800
  // src/matter/endpoints/legacy/sensor/devices/pm25-sensor.ts
170667
- var logger233 = Logger.get("Pm25AirQualityServer");
170801
+ var logger234 = Logger.get("Pm25AirQualityServer");
170668
170802
  var Pm25AirQualityServerBase = AirQualityServer.with(
170669
170803
  AirQuality3.Feature.Fair,
170670
170804
  AirQuality3.Feature.Moderate,
@@ -170676,9 +170810,9 @@ var Pm25AirQualityServer = class extends Pm25AirQualityServerBase {
170676
170810
  if (this.state.airQuality === void 0) {
170677
170811
  this.state.airQuality = AirQuality3.AirQualityEnum.Unknown;
170678
170812
  }
170679
- logger233.debug("Pm25AirQualityServer: before super.initialize()");
170813
+ logger234.debug("Pm25AirQualityServer: before super.initialize()");
170680
170814
  await super.initialize();
170681
- logger233.debug("Pm25AirQualityServer: after super.initialize()");
170815
+ logger234.debug("Pm25AirQualityServer: after super.initialize()");
170682
170816
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
170683
170817
  this.update(homeAssistant.entity);
170684
170818
  this.reactTo(homeAssistant.onChange, this.update, { offline: true });
@@ -170931,7 +171065,7 @@ var TvocConcentrationMeasurementServer = class extends TvocConcentrationMeasurem
170931
171065
  };
170932
171066
 
170933
171067
  // src/matter/endpoints/legacy/sensor/devices/tvoc-sensor.ts
170934
- var logger234 = Logger.get("TvocSensor");
171068
+ var logger235 = Logger.get("TvocSensor");
170935
171069
  function airQualityFromUgm3(value) {
170936
171070
  if (value <= 300) return AirQuality3.AirQualityEnum.Good;
170937
171071
  if (value <= 1e3) return AirQuality3.AirQualityEnum.Fair;
@@ -170972,17 +171106,17 @@ var TvocAirQualityServer = class extends TvocAirQualityServerBase {
170972
171106
  const attributes9 = entity.state.attributes;
170973
171107
  const deviceClass = attributes9.device_class;
170974
171108
  let airQuality = AirQuality3.AirQualityEnum.Unknown;
170975
- logger234.debug(
171109
+ logger235.debug(
170976
171110
  `[${entity.entity_id}] TVOC update: state="${state}", device_class="${deviceClass}"`
170977
171111
  );
170978
171112
  if (state != null && !Number.isNaN(+state)) {
170979
171113
  const value = +state;
170980
171114
  airQuality = deviceClass === SensorDeviceClass.volatile_organic_compounds ? airQualityFromUgm3(value) : airQualityFromPpb(value);
170981
- logger234.debug(
171115
+ logger235.debug(
170982
171116
  `[${entity.entity_id}] TVOC value=${value} (${deviceClass}) -> airQuality=${AirQuality3.AirQualityEnum[airQuality]}`
170983
171117
  );
170984
171118
  } else {
170985
- logger234.warn(
171119
+ logger235.warn(
170986
171120
  `[${entity.entity_id}] TVOC state not a valid number: "${state}"`
170987
171121
  );
170988
171122
  }
@@ -171392,13 +171526,13 @@ init_home_assistant_entity_behavior();
171392
171526
  init_dist();
171393
171527
  init_esm();
171394
171528
  init_home_assistant_entity_behavior();
171395
- var logger235 = Logger.get("VacuumIdentifyServer");
171529
+ var logger236 = Logger.get("VacuumIdentifyServer");
171396
171530
  var VacuumIdentifyServer = class extends IdentifyServer2 {
171397
171531
  identifyInHomeAssistant(source) {
171398
171532
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
171399
171533
  const features = homeAssistant.entity.state.attributes.supported_features ?? 0;
171400
171534
  if (testBit(features, VacuumDeviceFeature.LOCATE)) {
171401
- logger235.info(`${source} \u2192 vacuum.locate for ${homeAssistant.entityId}`);
171535
+ logger236.info(`${source} \u2192 vacuum.locate for ${homeAssistant.entityId}`);
171402
171536
  homeAssistant.callAction({ action: "vacuum.locate" });
171403
171537
  return;
171404
171538
  }
@@ -171406,7 +171540,7 @@ var VacuumIdentifyServer = class extends IdentifyServer2 {
171406
171540
  super.identifyInHomeAssistant(source);
171407
171541
  return;
171408
171542
  }
171409
- logger235.warn(
171543
+ logger236.warn(
171410
171544
  `${source} for ${homeAssistant.entityId}, LOCATE not in supported_features (${features}), trying vacuum.locate anyway`
171411
171545
  );
171412
171546
  homeAssistant.callAction({ action: "vacuum.locate" });
@@ -171590,7 +171724,7 @@ init_esm();
171590
171724
  // src/matter/behaviors/service-area-server.ts
171591
171725
  init_esm();
171592
171726
  init_home_assistant_entity_behavior();
171593
- var logger236 = Logger.get("ServiceAreaServer");
171727
+ var logger237 = Logger.get("ServiceAreaServer");
171594
171728
  function orderSelection(areas, agent) {
171595
171729
  try {
171596
171730
  const ascending = agent?.get(HomeAssistantEntityBehavior).state.mapping?.vacuumAscendingRoomOrder === true;
@@ -171605,7 +171739,7 @@ var ServiceAreaWithProgress = ServiceAreaBehavior.with(
171605
171739
  var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171606
171740
  selectAreas(request) {
171607
171741
  const { newAreas } = request;
171608
- logger236.info(
171742
+ logger237.info(
171609
171743
  `ServiceArea selectAreas called with: ${JSON.stringify(newAreas)}`
171610
171744
  );
171611
171745
  const uniqueAreas = orderSelection([...new Set(newAreas)], this.agent);
@@ -171614,7 +171748,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171614
171748
  (id) => !supportedAreaIds.includes(id)
171615
171749
  );
171616
171750
  if (invalidAreas.length > 0) {
171617
- logger236.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171751
+ logger237.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171618
171752
  return {
171619
171753
  status: ServiceArea3.SelectAreasStatus.UnsupportedArea,
171620
171754
  statusText: `Invalid area IDs: ${invalidAreas.join(", ")}`
@@ -171626,7 +171760,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171626
171760
  status: ServiceArea3.OperationalStatus.Pending
171627
171761
  }));
171628
171762
  this.state.currentArea = null;
171629
- logger236.info(
171763
+ logger237.info(
171630
171764
  `ServiceArea: Stored ${uniqueAreas.length} areas for cleaning: ${uniqueAreas.join(", ")}`
171631
171765
  );
171632
171766
  return {
@@ -171647,7 +171781,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171647
171781
  ServiceAreaServerBase2.State = State;
171648
171782
  })(ServiceAreaServerBase || (ServiceAreaServerBase = {}));
171649
171783
  function ServiceAreaServer2(initialState) {
171650
- logger236.info(
171784
+ logger237.info(
171651
171785
  `Creating ServiceAreaServer with ${initialState.supportedAreas.length} areas`
171652
171786
  );
171653
171787
  return ServiceAreaServerBase.set({
@@ -171664,7 +171798,7 @@ var ServiceAreaWithMapsAndProgress = ServiceAreaBehavior.with(
171664
171798
  var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress {
171665
171799
  selectAreas(request) {
171666
171800
  const { newAreas } = request;
171667
- logger236.info(
171801
+ logger237.info(
171668
171802
  `ServiceArea selectAreas called with: ${JSON.stringify(newAreas)}`
171669
171803
  );
171670
171804
  const uniqueAreas = orderSelection([...new Set(newAreas)], this.agent);
@@ -171673,7 +171807,7 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171673
171807
  (id) => !supportedAreaIds.includes(id)
171674
171808
  );
171675
171809
  if (invalidAreas.length > 0) {
171676
- logger236.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171810
+ logger237.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171677
171811
  return {
171678
171812
  status: ServiceArea3.SelectAreasStatus.UnsupportedArea,
171679
171813
  statusText: `Invalid area IDs: ${invalidAreas.join(", ")}`
@@ -171685,7 +171819,7 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171685
171819
  status: ServiceArea3.OperationalStatus.Pending
171686
171820
  }));
171687
171821
  this.state.currentArea = null;
171688
- logger236.info(
171822
+ logger237.info(
171689
171823
  `ServiceArea: Stored ${uniqueAreas.length} areas for cleaning: ${uniqueAreas.join(", ")}`
171690
171824
  );
171691
171825
  return {
@@ -171706,14 +171840,14 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171706
171840
  ServiceAreaServerWithMapsBase2.State = State;
171707
171841
  })(ServiceAreaServerWithMapsBase || (ServiceAreaServerWithMapsBase = {}));
171708
171842
  function ServiceAreaServerWithMaps(initialState) {
171709
- logger236.info(
171843
+ logger237.info(
171710
171844
  `Creating ServiceAreaServer with Maps: ${initialState.supportedAreas.length} areas, ${initialState.supportedMaps.length} maps`
171711
171845
  );
171712
171846
  for (const map of initialState.supportedMaps) {
171713
171847
  const areaCount = initialState.supportedAreas.filter(
171714
171848
  (a) => a.mapId === map.mapId
171715
171849
  ).length;
171716
- logger236.info(` Map ${map.mapId}: "${map.name}" (${areaCount} areas)`);
171850
+ logger237.info(` Map ${map.mapId}: "${map.name}" (${areaCount} areas)`);
171717
171851
  }
171718
171852
  return ServiceAreaServerWithMapsBase.set({
171719
171853
  supportedAreas: initialState.supportedAreas,
@@ -171725,7 +171859,7 @@ function ServiceAreaServerWithMaps(initialState) {
171725
171859
  }
171726
171860
 
171727
171861
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-service-area-server.ts
171728
- var logger237 = Logger.get("VacuumServiceAreaServer");
171862
+ var logger238 = Logger.get("VacuumServiceAreaServer");
171729
171863
  function toAreaId(roomId) {
171730
171864
  if (typeof roomId === "number") {
171731
171865
  return roomId;
@@ -171804,13 +171938,13 @@ function createVacuumServiceAreaServer(attributes9, roomEntities, includeUnnamed
171804
171938
  let rooms;
171805
171939
  if (roomEntities && roomEntities.length > 0) {
171806
171940
  rooms = buttonEntitiesToRooms(roomEntities, attributes9);
171807
- logger237.info(
171941
+ logger238.info(
171808
171942
  `Using ${rooms.length} button entities as rooms: ${rooms.map((r) => r.name).join(", ")}`
171809
171943
  );
171810
171944
  } else {
171811
171945
  rooms = parseVacuumRooms(attributes9, includeUnnamedRooms);
171812
171946
  if (rooms.length > 0) {
171813
- logger237.info(
171947
+ logger238.info(
171814
171948
  `Using ${rooms.length} rooms from attributes: ${rooms.map((r) => r.name).join(", ")}`
171815
171949
  );
171816
171950
  }
@@ -171864,7 +171998,7 @@ function createCustomServiceAreaServer(customAreas) {
171864
171998
  landmarkInfo: null
171865
171999
  }
171866
172000
  }));
171867
- logger237.info(
172001
+ logger238.info(
171868
172002
  `Using ${customAreas.length} custom service areas: ${customAreas.map((a) => a.name).join(", ")}`
171869
172003
  );
171870
172004
  return ServiceAreaServer2({
@@ -171886,7 +172020,7 @@ function createCleanAreaServiceAreaServer(cleanAreaRooms) {
171886
172020
  landmarkInfo: null
171887
172021
  }
171888
172022
  }));
171889
- logger237.info(
172023
+ logger238.info(
171890
172024
  `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA: ${cleanAreaRooms.map((r) => r.name).join(", ")}`
171891
172025
  );
171892
172026
  return ServiceAreaServer2({
@@ -171922,11 +172056,11 @@ function getVacuumServiceAreas(attributes9, mapping) {
171922
172056
  }
171923
172057
 
171924
172058
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
171925
- var logger238 = Logger.get("VacuumRvcRunModeServer");
172059
+ var logger239 = Logger.get("VacuumRvcRunModeServer");
171926
172060
  function buildValetudoSegmentAction(vacuumEntityId, segmentIds, valetudoIdentifier) {
171927
172061
  const identifier = valetudoIdentifier || vacuumEntityId.replace(/^vacuum\.valetudo_/, "");
171928
172062
  const topic = `valetudo/${identifier}/MapSegmentationCapability/clean/set`;
171929
- logger238.info(
172063
+ logger239.info(
171930
172064
  `Valetudo: mqtt.publish to ${topic}, segments: ${segmentIds.join(", ")}`
171931
172065
  );
171932
172066
  return {
@@ -172031,14 +172165,14 @@ function mergeBatchData(areas) {
172031
172165
  function handleCustomServiceAreas(selectedAreas, customAreas, session) {
172032
172166
  const matched = selectedAreas.map((areaId) => ({ areaId, area: customAreas[areaId - 1] })).filter((m) => !!m.area);
172033
172167
  if (matched.length === 0) {
172034
- logger238.warn(
172168
+ logger239.warn(
172035
172169
  `Custom service areas: no match for selected IDs ${selectedAreas.join(", ")}`
172036
172170
  );
172037
172171
  return { action: "vacuum.start" };
172038
172172
  }
172039
172173
  const batchArea = matched.find(({ area }) => area.batchDispatch === true);
172040
172174
  if (batchArea) {
172041
- logger238.info(
172175
+ logger239.info(
172042
172176
  `Custom service areas (batch): single call for ${matched.length} room(s): ${matched.map(({ area }) => area.name).join(", ")}`
172043
172177
  );
172044
172178
  session.pendingDispatches = [];
@@ -172059,7 +172193,7 @@ function handleCustomServiceAreas(selectedAreas, customAreas, session) {
172059
172193
  }
172060
172194
  };
172061
172195
  }
172062
- logger238.info(
172196
+ logger239.info(
172063
172197
  `Custom service areas: ${matched.length} room(s) queued: ${matched.map(({ area }) => `${area.service} (${area.name})`).join(", ")}`
172064
172198
  );
172065
172199
  session.pendingDispatches = matched.slice(1).map(({ areaId, area }) => ({
@@ -172117,7 +172251,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172117
172251
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
172118
172252
  const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
172119
172253
  if (haAreaIds.length > 0) {
172120
- logger238.info(`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`);
172254
+ logger239.info(`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`);
172121
172255
  return {
172122
172256
  action: {
172123
172257
  action: "vacuum.clean_area",
@@ -172137,7 +172271,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172137
172271
  }
172138
172272
  }
172139
172273
  if (matched.length > 0) {
172140
- logger238.info(
172274
+ logger239.info(
172141
172275
  `Roborock: ${matched.length} room button(s) queued: ${matched.map((m) => m.entityId).join(", ")}`
172142
172276
  );
172143
172277
  return {
@@ -172172,12 +172306,12 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172172
172306
  }
172173
172307
  }
172174
172308
  if (roomIds.length > 0) {
172175
- logger238.info(`Starting cleaning with selected areas: ${roomIds.join(", ")}`);
172309
+ logger239.info(`Starting cleaning with selected areas: ${roomIds.join(", ")}`);
172176
172310
  if (isDreameVacuum(attributes9)) {
172177
172311
  if (targetMapName) {
172178
172312
  const vacName = entityId.replace("vacuum.", "");
172179
172313
  const selectedMapEntity = `select.${vacName}_selected_map`;
172180
- logger238.info(
172314
+ logger239.info(
172181
172315
  `Dreame multi-floor: switching to map "${targetMapName}" via ${selectedMapEntity}`
172182
172316
  );
172183
172317
  seam.callAction({
@@ -172205,7 +172339,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172205
172339
  }
172206
172340
  if (isEcovacsVacuum(attributes9)) {
172207
172341
  const roomIdStr = roomIds.join(",");
172208
- logger238.info(`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`);
172342
+ logger239.info(`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`);
172209
172343
  return {
172210
172344
  action: {
172211
172345
  action: "vacuum.send_command",
@@ -172217,7 +172351,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172217
172351
  pending: []
172218
172352
  };
172219
172353
  }
172220
- logger238.warn(
172354
+ logger239.warn(
172221
172355
  `Room cleaning via send_command not supported for this vacuum type. Rooms: ${roomIds.join(", ")}. Falling back to vacuum.start`
172222
172356
  );
172223
172357
  }
@@ -172226,7 +172360,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
172226
172360
  var vacuumRvcRunModeConfig = {
172227
172361
  getCurrentMode: (entity) => {
172228
172362
  const isCleaning = vacuumIsCleaning(entity.state);
172229
- logger238.debug(
172363
+ logger239.debug(
172230
172364
  `Vacuum state: "${entity.state}", isCleaning: ${isCleaning}, currentMode: ${isCleaning ? "Cleaning" : "Idle"}`
172231
172365
  );
172232
172366
  return isCleaning ? 1 /* Cleaning */ : 0 /* Idle */;
@@ -172265,7 +172399,7 @@ var vacuumRvcRunModeConfig = {
172265
172399
  }
172266
172400
  } catch {
172267
172401
  }
172268
- logger238.info("Starting regular cleaning (no areas selected)");
172402
+ logger239.info("Starting regular cleaning (no areas selected)");
172269
172403
  return { action: "vacuum.start" };
172270
172404
  },
172271
172405
  returnToBase: () => ({ action: "vacuum.return_to_base" }),
@@ -172280,7 +172414,7 @@ var vacuumRvcRunModeConfig = {
172280
172414
  const homeAssistant = agent.get(HomeAssistantEntityBehavior);
172281
172415
  const entity = homeAssistant.entity;
172282
172416
  const attributes9 = entity.state.attributes;
172283
- logger238.info(`cleanRoom called: roomMode=${roomMode}`);
172417
+ logger239.info(`cleanRoom called: roomMode=${roomMode}`);
172284
172418
  const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
172285
172419
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
172286
172420
  const sorted = [...cleanAreaRooms].sort(
@@ -172289,7 +172423,7 @@ var vacuumRvcRunModeConfig = {
172289
172423
  const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
172290
172424
  if (areaIndex >= 0 && areaIndex < sorted.length) {
172291
172425
  const area = sorted[areaIndex];
172292
- logger238.info(
172426
+ logger239.info(
172293
172427
  `cleanRoom: CLEAN_AREA "${area.name}" \u2192 vacuum.clean_area(${area.haAreaId})`
172294
172428
  );
172295
172429
  return {
@@ -172306,7 +172440,7 @@ var vacuumRvcRunModeConfig = {
172306
172440
  const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
172307
172441
  if (areaIndex >= 0 && areaIndex < sorted.length) {
172308
172442
  const area = sorted[areaIndex];
172309
- logger238.info(
172443
+ logger239.info(
172310
172444
  `cleanRoom: custom service area "${area.name}" \u2192 ${area.service}`
172311
172445
  );
172312
172446
  return {
@@ -172327,7 +172461,7 @@ var vacuumRvcRunModeConfig = {
172327
172461
  }
172328
172462
  const rooms = parseVacuumRooms(attributes9);
172329
172463
  const numericIdFromMode = getRoomIdFromMode(roomMode);
172330
- logger238.info(
172464
+ logger239.info(
172331
172465
  `cleanRoom: numericIdFromMode=${numericIdFromMode}, available rooms: ${JSON.stringify(rooms.map((r) => ({ id: r.id, name: r.name, modeValue: getRoomModeValue(r) })))}`
172332
172466
  );
172333
172467
  const room = rooms.find((r) => getRoomModeValue(r) === roomMode);
@@ -172337,7 +172471,7 @@ var vacuumRvcRunModeConfig = {
172337
172471
  if (room.mapName) {
172338
172472
  const vacuumName = vacuumEntityId.replace("vacuum.", "");
172339
172473
  const selectedMapEntity = `select.${vacuumName}_selected_map`;
172340
- logger238.info(
172474
+ logger239.info(
172341
172475
  `Dreame multi-floor: switching to map "${room.mapName}" via ${selectedMapEntity}`
172342
172476
  );
172343
172477
  homeAssistant.callAction({
@@ -172346,7 +172480,7 @@ var vacuumRvcRunModeConfig = {
172346
172480
  data: { option: room.mapName }
172347
172481
  });
172348
172482
  }
172349
- logger238.debug(
172483
+ logger239.debug(
172350
172484
  `Dreame vacuum detected, using dreame_vacuum.vacuum_clean_segment for room ${room.name} (commandId: ${commandId3}, id: ${room.id})`
172351
172485
  );
172352
172486
  return {
@@ -172357,7 +172491,7 @@ var vacuumRvcRunModeConfig = {
172357
172491
  };
172358
172492
  }
172359
172493
  if (isRoborockVacuum(attributes9) || isXiaomiMiotVacuum(attributes9)) {
172360
- logger238.debug(
172494
+ logger239.debug(
172361
172495
  `Using vacuum.send_command with app_segment_clean for room ${room.name} (commandId: ${commandId3}, id: ${room.id})`
172362
172496
  );
172363
172497
  return {
@@ -172370,7 +172504,7 @@ var vacuumRvcRunModeConfig = {
172370
172504
  }
172371
172505
  if (isEcovacsVacuum(attributes9)) {
172372
172506
  const roomIdStr = String(commandId3);
172373
- logger238.info(
172507
+ logger239.info(
172374
172508
  `Ecovacs vacuum: Using spot_area for room ${room.name} (id: ${roomIdStr})`
172375
172509
  );
172376
172510
  return {
@@ -172385,7 +172519,7 @@ var vacuumRvcRunModeConfig = {
172385
172519
  }
172386
172520
  };
172387
172521
  }
172388
- logger238.warn(
172522
+ logger239.warn(
172389
172523
  `Room cleaning via send_command not supported for this vacuum type. Room: ${room.name} (id=${commandId3}). Falling back to vacuum.start`
172390
172524
  );
172391
172525
  }
@@ -172402,20 +172536,20 @@ function createVacuumRvcRunModeServer(attributes9, includeUnnamedRooms = false,
172402
172536
  customAreas,
172403
172537
  disableRoomModes
172404
172538
  );
172405
- logger238.info(
172539
+ logger239.info(
172406
172540
  `Creating VacuumRvcRunModeServer with ${rooms.length} rooms, ${supportedModes2.length} total modes`
172407
172541
  );
172408
172542
  if (rooms.length > 0) {
172409
- logger238.info(`Rooms found: ${rooms.map((r) => r.name).join(", ")}`);
172543
+ logger239.info(`Rooms found: ${rooms.map((r) => r.name).join(", ")}`);
172410
172544
  }
172411
172545
  if (filteredCount > 0) {
172412
172546
  const filtered = allRooms.filter((r) => !rooms.some((x) => x.id === r.id));
172413
- logger238.info(
172547
+ logger239.info(
172414
172548
  `Filtered out ${filteredCount} unnamed room(s): ${filtered.map((r) => r.name).join(", ")}`
172415
172549
  );
172416
172550
  }
172417
172551
  if (allRooms.length === 0) {
172418
- logger238.debug(
172552
+ logger239.debug(
172419
172553
  `No rooms found. Attributes: rooms=${JSON.stringify(attributes9.rooms)}, segments=${JSON.stringify(attributes9.segments)}, room_list=${attributes9.room_list}`
172420
172554
  );
172421
172555
  }
@@ -172449,7 +172583,7 @@ function createCleanAreaRvcRunModeServer(cleanAreaRooms) {
172449
172583
  modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
172450
172584
  });
172451
172585
  }
172452
- logger238.info(
172586
+ logger239.info(
172453
172587
  `Creating CLEAN_AREA RvcRunModeServer with ${cleanAreaRooms.length} HA areas, ${modes.length} total modes`
172454
172588
  );
172455
172589
  return RvcRunModeServer2(vacuumRvcRunModeConfig, {
@@ -172539,7 +172673,7 @@ init_nodejs();
172539
172673
 
172540
172674
  // src/matter/behaviors/rvc-clean-mode-server.ts
172541
172675
  init_home_assistant_entity_behavior();
172542
- var logger239 = Logger.get("RvcCleanModeServerBase");
172676
+ var logger240 = Logger.get("RvcCleanModeServerBase");
172543
172677
  var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeServer {
172544
172678
  // Pending mode from a recent changeToMode command.
172545
172679
  // Prevents stale HA state (from a different entity like select.xxx)
@@ -172586,14 +172720,14 @@ var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeS
172586
172720
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
172587
172721
  const { newMode } = request;
172588
172722
  if (newMode !== this.state.currentMode && !this.state.supportedModes.some((m) => m.mode === newMode)) {
172589
- logger239.warn(`changeToMode(${newMode}) rejected: unsupported mode`);
172723
+ logger240.warn(`changeToMode(${newMode}) rejected: unsupported mode`);
172590
172724
  return {
172591
172725
  status: ModeBase3.ModeChangeStatus.UnsupportedMode,
172592
172726
  statusText: `Unsupported mode: ${newMode}`
172593
172727
  };
172594
172728
  }
172595
172729
  const modeLabel = this.state.supportedModes.find((m) => m.mode === newMode);
172596
- logger239.info(
172730
+ logger240.info(
172597
172731
  `changeToMode(${newMode}) "${modeLabel?.label ?? "unknown"}" for ${homeAssistant.entityId}`
172598
172732
  );
172599
172733
  this.pendingMode = newMode;
@@ -172601,7 +172735,7 @@ var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeS
172601
172735
  this.state.currentMode = newMode;
172602
172736
  const action = this.state.config.setCleanMode(newMode, this.agent);
172603
172737
  if (action) {
172604
- logger239.info(
172738
+ logger240.info(
172605
172739
  `changeToMode: dispatching action ${action.action} \u2192 ${action.target ?? homeAssistant.entityId}`
172606
172740
  );
172607
172741
  homeAssistant.callAction(action);
@@ -172634,7 +172768,7 @@ function RvcCleanModeServer2(config8, initialState) {
172634
172768
  }
172635
172769
 
172636
172770
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-clean-mode-server.ts
172637
- var logger240 = Logger.get("VacuumRvcCleanModeServer");
172771
+ var logger241 = Logger.get("VacuumRvcCleanModeServer");
172638
172772
  var MODE_VACUUM = 0;
172639
172773
  var MODE_VACUUM_AND_MOP = 1;
172640
172774
  var MODE_MOP = 2;
@@ -172904,7 +173038,7 @@ function findMatchingCleanOption(ct, availableOptions) {
172904
173038
  const match = availableOptions.find((o) => classifyCleanOption(o) === type);
172905
173039
  if (match) return match;
172906
173040
  }
172907
- logger240.warn(
173041
+ logger241.warn(
172908
173042
  `No match for ${CLEAN_TYPE_LABELS[ct]} in [${availableOptions.join(", ")}]`
172909
173043
  );
172910
173044
  return availableOptions[0];
@@ -172913,7 +173047,7 @@ function buildCleaningModeAction(targetCleanType, agent) {
172913
173047
  const selectEntityId = getCleaningModeSelectEntity(agent);
172914
173048
  const { options } = readSelectEntity(selectEntityId, agent);
172915
173049
  const optionToUse = findMatchingCleanOption(targetCleanType, options);
172916
- logger240.info(
173050
+ logger241.info(
172917
173051
  `Switching cleaning mode to: ${optionToUse} via ${selectEntityId}`
172918
173052
  );
172919
173053
  return {
@@ -173002,7 +173136,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173002
173136
  }
173003
173137
  }
173004
173138
  if (speedMode !== void 0) {
173005
- logger240.debug(
173139
+ logger241.debug(
173006
173140
  `Current mode: Vacuum + fan_speed="${speedState}" -> mode ${speedMode}`
173007
173141
  );
173008
173142
  return speedMode;
@@ -173023,7 +173157,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173023
173157
  }
173024
173158
  }
173025
173159
  if (mopMode !== void 0) {
173026
- logger240.debug(
173160
+ logger241.debug(
173027
173161
  `Current mode: Mop + intensity="${state}" -> mode ${mopMode}`
173028
173162
  );
173029
173163
  return mopMode;
@@ -173041,14 +173175,14 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173041
173175
  const homeAssistant = agent.get(HomeAssistantEntityBehavior);
173042
173176
  const vacuumEntityId = homeAssistant.entityId;
173043
173177
  const mapping = homeAssistant.state.mapping;
173044
- logger240.info(
173178
+ logger241.info(
173045
173179
  `setCleanMode(${mode}) for ${vacuumEntityId}, suctionEntity=${mapping?.suctionLevelEntity ?? "none"}, mopEntity=${mapping?.mopIntensityEntity ?? "none"}, fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])}, customTags=${JSON.stringify(customFanSpeedTags ?? {})}`
173046
173180
  );
173047
173181
  if (mopIntensityList && mopIntensityList.length > 0 && isMopIntensityMode(mode)) {
173048
173182
  const mopIndex = mode - MOP_INTENSITY_MODE_BASE;
173049
173183
  const mopName = mopIntensityList[mopIndex];
173050
173184
  if (!mopName) {
173051
- logger240.warn(`Invalid mop intensity mode index: ${mopIndex}`);
173185
+ logger241.warn(`Invalid mop intensity mode index: ${mopIndex}`);
173052
173186
  return void 0;
173053
173187
  }
173054
173188
  if (hasCleanTypes) {
@@ -173061,18 +173195,18 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173061
173195
  mapping.mopIntensityEntity,
173062
173196
  agent
173063
173197
  );
173064
- logger240.info(
173198
+ logger241.info(
173065
173199
  `Mop intensity entity ${mapping.mopIntensityEntity}: current="${state}", options=${JSON.stringify(options ?? [])}`
173066
173200
  );
173067
173201
  let option = matchMopIntensityOption(mopName, options);
173068
173202
  if (!option && options && mopIndex < options.length) {
173069
173203
  option = options[mopIndex];
173070
- logger240.info(
173204
+ logger241.info(
173071
173205
  `Positional match for mop "${mopName}" -> "${option}" (index ${mopIndex})`
173072
173206
  );
173073
173207
  }
173074
173208
  if (option) {
173075
- logger240.info(
173209
+ logger241.info(
173076
173210
  `Setting mop intensity to: ${option} via ${mapping.mopIntensityEntity}`
173077
173211
  );
173078
173212
  return {
@@ -173081,11 +173215,11 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173081
173215
  target: mapping.mopIntensityEntity
173082
173216
  };
173083
173217
  }
173084
- logger240.warn(
173218
+ logger241.warn(
173085
173219
  `No match for mop intensity "${mopName}" in options: [${(options ?? []).join(", ")}]`
173086
173220
  );
173087
173221
  } else {
173088
- logger240.warn(
173222
+ logger241.warn(
173089
173223
  `Mop intensity mode ${mode} requested but no mopIntensityEntity configured`
173090
173224
  );
173091
173225
  }
@@ -173095,7 +173229,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173095
173229
  const fanSpeedIndex = mode - FAN_SPEED_MODE_BASE;
173096
173230
  const fanSpeedName = fanSpeedList[fanSpeedIndex];
173097
173231
  if (!fanSpeedName) {
173098
- logger240.warn(`Invalid fan speed mode index: ${fanSpeedIndex}`);
173232
+ logger241.warn(`Invalid fan speed mode index: ${fanSpeedIndex}`);
173099
173233
  return void 0;
173100
173234
  }
173101
173235
  if (mapping?.suctionLevelEntity) {
@@ -173108,7 +173242,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173108
173242
  mapping.suctionLevelEntity,
173109
173243
  agent
173110
173244
  );
173111
- logger240.info(
173245
+ logger241.info(
173112
173246
  `Suction entity ${mapping.suctionLevelEntity}: current="${state}", options=${JSON.stringify(options ?? [])}`
173113
173247
  );
173114
173248
  let option = matchFanSpeedOption(
@@ -173118,12 +173252,12 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173118
173252
  );
173119
173253
  if (!option && options && fanSpeedIndex < options.length) {
173120
173254
  option = options[fanSpeedIndex];
173121
- logger240.info(
173255
+ logger241.info(
173122
173256
  `Positional match for fan "${fanSpeedName}" -> "${option}" (index ${fanSpeedIndex})`
173123
173257
  );
173124
173258
  }
173125
173259
  if (option) {
173126
- logger240.info(
173260
+ logger241.info(
173127
173261
  `Setting suction to: ${option} via ${mapping.suctionLevelEntity}`
173128
173262
  );
173129
173263
  return {
@@ -173132,7 +173266,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173132
173266
  target: mapping.suctionLevelEntity
173133
173267
  };
173134
173268
  }
173135
- logger240.warn(
173269
+ logger241.warn(
173136
173270
  `No match for fan speed "${fanSpeedName}" in suction options: [${(options ?? []).join(", ")}]`
173137
173271
  );
173138
173272
  return void 0;
@@ -173142,7 +173276,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173142
173276
  buildCleaningModeAction(0 /* Sweeping */, agent)
173143
173277
  );
173144
173278
  }
173145
- logger240.info(
173279
+ logger241.info(
173146
173280
  `Setting fan speed to: ${fanSpeedName} via vacuum.set_fan_speed`
173147
173281
  );
173148
173282
  return {
@@ -173152,7 +173286,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173152
173286
  };
173153
173287
  }
173154
173288
  if (!hasCleanTypes) {
173155
- logger240.debug(
173289
+ logger241.debug(
173156
173290
  `Ignoring cleaning type change (mode=${mode}): no cleaning mode entity`
173157
173291
  );
173158
173292
  return void 0;
@@ -173164,7 +173298,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
173164
173298
  agent
173165
173299
  );
173166
173300
  const optionToUse = findMatchingCleanOption(cleanType, availableOptions);
173167
- logger240.info(
173301
+ logger241.info(
173168
173302
  `Setting cleaning mode to: ${optionToUse} (mode=${mode}) via ${selectEntityId}`
173169
173303
  );
173170
173304
  return {
@@ -173182,10 +173316,10 @@ function createVacuumRvcCleanModeServer(_attributes, fanSpeedList, mopIntensityL
173182
173316
  cleaningModeOptions,
173183
173317
  customFanSpeedTags
173184
173318
  );
173185
- logger240.info(
173319
+ logger241.info(
173186
173320
  `Creating VacuumRvcCleanModeServer with ${supportedModes2.length} modes (fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])}, cleaningModeOptions=${JSON.stringify(cleaningModeOptions ?? [])}, customTags=${JSON.stringify(customFanSpeedTags ?? {})})`
173187
173321
  );
173188
- logger240.info(
173322
+ logger241.info(
173189
173323
  `Modes: ${supportedModes2.map((m) => `${m.mode}:${m.label}[${m.modeTags.map((t) => t.value).join(",")}]`).join(", ")}`
173190
173324
  );
173191
173325
  const initialState = {
@@ -173248,7 +173382,7 @@ function resolveMopIntensityList(mopIntensityEntity) {
173248
173382
  init_dist();
173249
173383
  init_esm();
173250
173384
  init_home_assistant_entity_behavior();
173251
- var logger241 = Logger.get("VacuumRvcOperationalStateServer");
173385
+ var logger242 = Logger.get("VacuumRvcOperationalStateServer");
173252
173386
  function batteryFromAttributes(attrs) {
173253
173387
  const raw = attrs.battery_level ?? attrs.battery;
173254
173388
  if (raw == null) return null;
@@ -173301,16 +173435,16 @@ function mapVacuumOperationalState(entity, batteryPercent = batteryFromAttribute
173301
173435
  operationalState = RvcOperationalState4.OperationalState.Error;
173302
173436
  } else {
173303
173437
  if (state.toLowerCase().includes("clean")) {
173304
- logger241.info(
173438
+ logger242.info(
173305
173439
  `Unknown vacuum state "${state}" contains 'clean', treating as Running`
173306
173440
  );
173307
173441
  operationalState = RvcOperationalState4.OperationalState.Running;
173308
173442
  } else {
173309
- logger241.info(`Unknown vacuum state "${state}", treating as Stopped`);
173443
+ logger242.info(`Unknown vacuum state "${state}", treating as Stopped`);
173310
173444
  operationalState = RvcOperationalState4.OperationalState.Stopped;
173311
173445
  }
173312
173446
  }
173313
- logger241.debug(
173447
+ logger242.debug(
173314
173448
  `Vacuum operationalState: "${state}" -> ${RvcOperationalState4.OperationalState[operationalState]}`
173315
173449
  );
173316
173450
  return operationalState;
@@ -173339,7 +173473,7 @@ var VacuumRvcOperationalStateServer = RvcOperationalStateServer2({
173339
173473
  });
173340
173474
 
173341
173475
  // src/matter/endpoints/legacy/vacuum/index.ts
173342
- var logger242 = Logger.get("VacuumDevice");
173476
+ var logger243 = Logger.get("VacuumDevice");
173343
173477
  var VacuumEndpointType = RoboticVacuumCleanerDevice.with(
173344
173478
  BasicInformationServer2,
173345
173479
  VacuumIdentifyServer,
@@ -173353,7 +173487,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173353
173487
  const entityId = homeAssistantEntity.entity.entity_id;
173354
173488
  const attributes9 = homeAssistantEntity.entity.state.attributes;
173355
173489
  const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
173356
- logger242.info(
173490
+ logger243.info(
173357
173491
  `Creating vacuum endpoint for ${entityId}, mapping: ${JSON.stringify(homeAssistantEntity.mapping ?? "none")}`
173358
173492
  );
173359
173493
  const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
@@ -173366,32 +173500,32 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173366
173500
  )
173367
173501
  ).set({ homeAssistantEntity });
173368
173502
  if (includeOnOff) {
173369
- logger242.info(`${entityId}: Adding OnOff cluster (vacuumOnOff flag enabled)`);
173503
+ logger243.info(`${entityId}: Adding OnOff cluster (vacuumOnOff flag enabled)`);
173370
173504
  device = device.with(VacuumOnOffServer);
173371
173505
  }
173372
173506
  device = device.with(VacuumPowerSourceServer);
173373
173507
  const roomEntities = homeAssistantEntity.mapping?.roomEntities;
173374
173508
  const rooms = parseVacuumRooms(attributes9);
173375
- logger242.info(
173509
+ logger243.info(
173376
173510
  `${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}, cleanAreaRooms=${cleanAreaRooms?.length ?? 0}`
173377
173511
  );
173378
173512
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
173379
- logger242.info(
173513
+ logger243.info(
173380
173514
  `${entityId}: Adding ServiceArea (${cleanAreaRooms.length} HA areas via CLEAN_AREA)`
173381
173515
  );
173382
173516
  device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
173383
173517
  } else if (customAreas && customAreas.length > 0) {
173384
- logger242.info(
173518
+ logger243.info(
173385
173519
  `${entityId}: Adding ServiceArea (${customAreas.length} custom areas)`
173386
173520
  );
173387
173521
  device = device.with(createCustomServiceAreaServer(customAreas));
173388
173522
  } else if (rooms.length > 0 || roomEntities && roomEntities.length > 0) {
173389
- logger242.info(`${entityId}: Adding ServiceArea (${rooms.length} rooms)`);
173523
+ logger243.info(`${entityId}: Adding ServiceArea (${rooms.length} rooms)`);
173390
173524
  device = device.with(
173391
173525
  createVacuumServiceAreaServer(attributes9, roomEntities)
173392
173526
  );
173393
173527
  } else {
173394
- logger242.info(`${entityId}: Adding ServiceArea (default single-area)`);
173528
+ logger243.info(`${entityId}: Adding ServiceArea (default single-area)`);
173395
173529
  device = device.with(createDefaultServiceAreaServer());
173396
173530
  }
173397
173531
  const fanSpeedList = resolveFanSpeedList(
@@ -173402,7 +173536,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173402
173536
  homeAssistantEntity.mapping?.mopIntensityEntity
173403
173537
  );
173404
173538
  if (cleaningModeOptions || fanSpeedList || mopIntensityList) {
173405
- logger242.info(
173539
+ logger243.info(
173406
173540
  `${entityId}: Adding RvcCleanMode (multi-mode, cleaningModeOptions=${JSON.stringify(cleaningModeOptions ?? [])}, fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])})`
173407
173541
  );
173408
173542
  device = device.with(
@@ -173415,7 +173549,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173415
173549
  )
173416
173550
  );
173417
173551
  } else {
173418
- logger242.info(`${entityId}: Adding RvcCleanMode (default single-mode)`);
173552
+ logger243.info(`${entityId}: Adding RvcCleanMode (default single-mode)`);
173419
173553
  device = device.with(createDefaultRvcCleanModeServer());
173420
173554
  }
173421
173555
  return device;
@@ -173581,7 +173715,7 @@ var WaterHeaterThermostatServer = ThermostatServer2(
173581
173715
  );
173582
173716
 
173583
173717
  // src/matter/endpoints/legacy/water-heater/index.ts
173584
- var logger243 = Logger.get("WaterHeaterDevice");
173718
+ var logger244 = Logger.get("WaterHeaterDevice");
173585
173719
  var WaterHeaterDeviceType = ThermostatDevice.with(
173586
173720
  BasicInformationServer2,
173587
173721
  IdentifyServer2,
@@ -173597,7 +173731,7 @@ function toMatterTemp2(value) {
173597
173731
  }
173598
173732
  function WaterHeaterDevice2(homeAssistantEntity) {
173599
173733
  const attributes9 = homeAssistantEntity.entity.state.attributes;
173600
- logger243.debug(
173734
+ logger244.debug(
173601
173735
  `Creating device for ${homeAssistantEntity.entity.entity_id}, min_temp=${attributes9.min_temp}, max_temp=${attributes9.max_temp}`
173602
173736
  );
173603
173737
  const minLimit = toMatterTemp2(attributes9.min_temp) ?? 0;
@@ -173840,7 +173974,7 @@ function activeHeatSource(attributes9) {
173840
173974
  }
173841
173975
 
173842
173976
  // src/matter/endpoints/legacy/water-heater/behaviors/water-heater-management-server.ts
173843
- var logger244 = Logger.get("WaterHeaterManagementServer");
173977
+ var logger245 = Logger.get("WaterHeaterManagementServer");
173844
173978
  var MAX_TIMER_MS2 = 2147483647;
173845
173979
  var boostSessions = /* @__PURE__ */ new WeakMap();
173846
173980
  function clearBoostTimer(endpoint) {
@@ -174086,7 +174220,7 @@ var WaterHeaterManagementServerBase = class _WaterHeaterManagementServerBase ext
174086
174220
  armBoostTimer(durationSeconds) {
174087
174221
  const delay = durationSeconds * 1e3;
174088
174222
  if (!Number.isFinite(delay) || delay <= 0 || delay > MAX_TIMER_MS2) {
174089
- logger244.debug(
174223
+ logger245.debug(
174090
174224
  `Boost duration ${durationSeconds}s outside the timer range, boost stays active until CancelBoost`
174091
174225
  );
174092
174226
  return;
@@ -174100,7 +174234,7 @@ var WaterHeaterManagementServerBase = class _WaterHeaterManagementServerBase ext
174100
174234
  agent.get(_WaterHeaterManagementServerBase).endBoost({ restoreMode: true });
174101
174235
  });
174102
174236
  } catch (error) {
174103
- logger244.debug(
174237
+ logger245.debug(
174104
174238
  `Boost expiry failed (endpoint may be closing): ${error}`
174105
174239
  );
174106
174240
  }
@@ -174203,13 +174337,13 @@ function WaterHeaterModeServer2(mapping, initialMode) {
174203
174337
  }
174204
174338
 
174205
174339
  // src/matter/endpoints/legacy/water-heater/water-heater-management-device.ts
174206
- var logger245 = Logger.get("WaterHeaterManagementDevice");
174340
+ var logger246 = Logger.get("WaterHeaterManagementDevice");
174207
174341
  function WaterHeaterManagementDevice(homeAssistantEntity) {
174208
174342
  const entityState = homeAssistantEntity.entity.state;
174209
174343
  const attributes9 = entityState.attributes;
174210
174344
  const modeMapping = buildModeMapping(attributes9);
174211
174345
  const initialMode = currentMode(modeMapping, entityState.state, attributes9);
174212
- logger245.debug(
174346
+ logger246.debug(
174213
174347
  `Creating Matter 1.4 water heater for ${homeAssistantEntity.entity.entity_id}, modes=[${modeMapping.supportedModes.map((m) => `${m.mode}:${m.label}`).join(", ")}], boostMode=${modeMapping.boostOperationMode ?? "none"}`
174214
174348
  );
174215
174349
  const minLimit = toMatterTemp2(attributes9.min_temp) ?? 0;
@@ -174483,7 +174617,7 @@ var matterDeviceTypeFactories = {
174483
174617
  };
174484
174618
 
174485
174619
  // src/matter/endpoints/composed/user-composed-endpoint.ts
174486
- var logger246 = Logger.get("UserComposedEndpoint");
174620
+ var logger247 = Logger.get("UserComposedEndpoint");
174487
174621
  function stripBasicInformation(type) {
174488
174622
  const behaviors = { ...type.behaviors };
174489
174623
  delete behaviors.bridgedDeviceBasicInformation;
@@ -174559,7 +174693,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174559
174693
  { vacuumOnOff: registry3.isVacuumOnOffEnabled() }
174560
174694
  );
174561
174695
  if (!primaryType) {
174562
- logger246.warn(
174696
+ logger247.warn(
174563
174697
  `Cannot create endpoint type for primary entity ${primaryEntityId}`
174564
174698
  );
174565
174699
  return void 0;
@@ -174574,7 +174708,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174574
174708
  if (!sub.entityId) continue;
174575
174709
  const subPayload = buildEntityPayload4(registry3, sub.entityId);
174576
174710
  if (!subPayload) {
174577
- logger246.warn(
174711
+ logger247.warn(
174578
174712
  `Cannot find state for composed sub-entity ${sub.entityId}, it does not exist in Home Assistant (removed or renamed?)`
174579
174713
  );
174580
174714
  continue;
@@ -174589,7 +174723,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174589
174723
  config8.areaName
174590
174724
  );
174591
174725
  if (!subType) {
174592
- logger246.warn(
174726
+ logger247.warn(
174593
174727
  `Cannot create endpoint type for composed sub-entity ${sub.entityId}`
174594
174728
  );
174595
174729
  continue;
@@ -174602,7 +174736,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174602
174736
  mappedIds.push(sub.entityId);
174603
174737
  }
174604
174738
  if (parts.length < 2) {
174605
- logger246.warn(
174739
+ logger247.warn(
174606
174740
  `User composed device ${primaryEntityId}: only ${parts.length} sub-endpoint(s), need at least 2 (primary + one sub-entity). Falling back to standalone.`
174607
174741
  );
174608
174742
  return void 0;
@@ -174626,7 +174760,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174626
174760
  const labels = parts.map(
174627
174761
  (_, i) => i === 0 ? primaryEntityId.split(".")[0] : composedEntities[i - 1]?.entityId?.split(".")[0] ?? "?"
174628
174762
  ).join("+");
174629
- logger246.info(
174763
+ logger247.info(
174630
174764
  `Created user composed device ${primaryEntityId}: ${parts.length} sub-endpoint(s) [${labels}]`
174631
174765
  );
174632
174766
  return endpoint;
@@ -174732,7 +174866,7 @@ function asStandaloneEndpointType(type) {
174732
174866
  }
174733
174867
 
174734
174868
  // src/matter/endpoints/legacy/legacy-endpoint.ts
174735
- var logger247 = Logger.get("LegacyEndpoint");
174869
+ var logger248 = Logger.get("LegacyEndpoint");
174736
174870
  var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174737
174871
  constructor(type, entityId, customName, mappedEntityIds, throttleMs, endpointId, vacuumEffective) {
174738
174872
  super(type, entityId, customName, mappedEntityIds, endpointId);
@@ -174748,25 +174882,25 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174748
174882
  return;
174749
174883
  }
174750
174884
  if (registry3.isAutoBatteryMappingEnabled() && registry3.isBatteryEntityUsed(entityId)) {
174751
- logger247.debug(
174885
+ logger248.debug(
174752
174886
  `Skipping ${entityId} - already auto-assigned as battery to another device`
174753
174887
  );
174754
174888
  return;
174755
174889
  }
174756
174890
  if (registry3.isAutoHumidityMappingEnabled() && registry3.isHumidityEntityUsed(entityId)) {
174757
- logger247.debug(
174891
+ logger248.debug(
174758
174892
  `Skipping ${entityId} - already auto-assigned as humidity to a temperature sensor`
174759
174893
  );
174760
174894
  return;
174761
174895
  }
174762
174896
  if (registry3.isAutoPressureMappingEnabled() && registry3.isPressureEntityUsed(entityId)) {
174763
- logger247.debug(
174897
+ logger248.debug(
174764
174898
  `Skipping ${entityId} - already auto-assigned as pressure to a temperature sensor`
174765
174899
  );
174766
174900
  return;
174767
174901
  }
174768
174902
  if (registry3.isAutoComposedDevicesEnabled() && registry3.isComposedSubEntityUsed(entityId)) {
174769
- logger247.debug(
174903
+ logger248.debug(
174770
174904
  `Skipping ${entityId} - already consumed by a composed device`
174771
174905
  );
174772
174906
  return;
@@ -174786,7 +174920,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174786
174920
  humidityEntity: humidityEntityId
174787
174921
  };
174788
174922
  registry3.markHumidityEntityUsed(humidityEntityId);
174789
- logger247.debug(
174923
+ logger248.debug(
174790
174924
  `Auto-assigned humidity ${humidityEntityId} to ${entityId}`
174791
174925
  );
174792
174926
  }
@@ -174805,7 +174939,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174805
174939
  pressureEntity: pressureEntityId
174806
174940
  };
174807
174941
  registry3.markPressureEntityUsed(pressureEntityId);
174808
- logger247.debug(
174942
+ logger248.debug(
174809
174943
  `Auto-assigned pressure ${pressureEntityId} to ${entityId}`
174810
174944
  );
174811
174945
  }
@@ -174823,7 +174957,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174823
174957
  batteryEntity: batteryEntityId
174824
174958
  };
174825
174959
  registry3.markBatteryEntityUsed(batteryEntityId);
174826
- logger247.debug(
174960
+ logger248.debug(
174827
174961
  `Auto-assigned battery ${batteryEntityId} to ${entityId}`
174828
174962
  );
174829
174963
  }
@@ -174840,7 +174974,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174840
174974
  entityId: effectiveMapping?.entityId ?? entityId,
174841
174975
  faultEntity: faultEntityId
174842
174976
  };
174843
- logger247.debug(`Auto-assigned fault ${faultEntityId} to ${entityId}`);
174977
+ logger248.debug(`Auto-assigned fault ${faultEntityId} to ${entityId}`);
174844
174978
  }
174845
174979
  }
174846
174980
  if (!mapping?.powerEntity) {
@@ -174856,7 +174990,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174856
174990
  powerEntity: powerEntityId
174857
174991
  };
174858
174992
  registry3.markPowerEntityUsed(powerEntityId);
174859
- logger247.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
174993
+ logger248.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
174860
174994
  }
174861
174995
  }
174862
174996
  }
@@ -174873,7 +175007,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174873
175007
  energyEntity: energyEntityId
174874
175008
  };
174875
175009
  registry3.markEnergyEntityUsed(energyEntityId);
174876
- logger247.debug(
175010
+ logger248.debug(
174877
175011
  `Auto-assigned energy ${energyEntityId} to ${entityId}`
174878
175012
  );
174879
175013
  }
@@ -174889,7 +175023,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174889
175023
  entityId: effectiveMapping?.entityId ?? entityId,
174890
175024
  cleaningModeEntity: vacuumEntities.cleaningModeEntity
174891
175025
  };
174892
- logger247.info(
175026
+ logger248.info(
174893
175027
  `Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity} to ${entityId}`
174894
175028
  );
174895
175029
  }
@@ -174899,7 +175033,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174899
175033
  entityId: effectiveMapping?.entityId ?? entityId,
174900
175034
  suctionLevelEntity: vacuumEntities.suctionLevelEntity
174901
175035
  };
174902
- logger247.info(
175036
+ logger248.info(
174903
175037
  `Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity} to ${entityId}`
174904
175038
  );
174905
175039
  }
@@ -174909,7 +175043,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174909
175043
  entityId: effectiveMapping?.entityId ?? entityId,
174910
175044
  mopIntensityEntity: vacuumEntities.mopIntensityEntity
174911
175045
  };
174912
- logger247.info(
175046
+ logger248.info(
174913
175047
  `Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity} to ${entityId}`
174914
175048
  );
174915
175049
  }
@@ -174919,7 +175053,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174919
175053
  entityId: effectiveMapping?.entityId ?? entityId,
174920
175054
  currentRoomEntity: vacuumEntities.currentRoomEntity
174921
175055
  };
174922
- logger247.info(
175056
+ logger248.info(
174923
175057
  `Auto-assigned currentRoom ${vacuumEntities.currentRoomEntity} to ${entityId}`
174924
175058
  );
174925
175059
  }
@@ -174934,7 +175068,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174934
175068
  entityId: effectiveMapping?.entityId ?? entityId,
174935
175069
  cleanAreaRooms
174936
175070
  };
174937
- logger247.info(
175071
+ logger248.info(
174938
175072
  `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA for ${entityId}`
174939
175073
  );
174940
175074
  }
@@ -174955,7 +175089,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174955
175089
  rooms: roomsObj
174956
175090
  }
174957
175091
  };
174958
- logger247.debug(
175092
+ logger248.debug(
174959
175093
  `Auto-detected ${valetudoRooms.length} Valetudo segments for ${entityId}`
174960
175094
  );
174961
175095
  } else {
@@ -174972,7 +175106,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174972
175106
  rooms: roomsObj
174973
175107
  }
174974
175108
  };
174975
- logger247.debug(
175109
+ logger248.debug(
174976
175110
  `Auto-detected ${roborockRooms.length} Roborock rooms for ${entityId}`
174977
175111
  );
174978
175112
  }
@@ -174981,7 +175115,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174981
175115
  }
174982
175116
  }
174983
175117
  if (standalone && ((effectiveMapping?.composedEntities?.length ?? 0) > 0 || effectiveMapping?.climateExposeFan === true)) {
174984
- logger247.warn(
175118
+ logger248.warn(
174985
175119
  `Composed mappings are not supported in server mode, exposing ${entityId} as a flat standalone endpoint`
174986
175120
  );
174987
175121
  }
@@ -175000,7 +175134,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
175000
175134
  if (composed) {
175001
175135
  return composed;
175002
175136
  }
175003
- logger247.warn(
175137
+ logger248.warn(
175004
175138
  `User composed device creation failed for ${entityId}, falling back to standalone`
175005
175139
  );
175006
175140
  }
@@ -175065,7 +175199,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
175065
175199
  if (composed) {
175066
175200
  return composed;
175067
175201
  }
175068
- logger247.warn(
175202
+ logger248.warn(
175069
175203
  `Companion fan creation failed for ${entityId}, falling back to standalone`
175070
175204
  );
175071
175205
  }
@@ -175143,11 +175277,11 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
175143
175277
  }
175144
175278
  if (mappedChanged) {
175145
175279
  this.pendingMappedChange = true;
175146
- logger247.debug(
175280
+ logger248.debug(
175147
175281
  `Mapped entity change detected for ${this.entityId}, forcing update`
175148
175282
  );
175149
175283
  }
175150
- logger247.debug(
175284
+ logger248.debug(
175151
175285
  `State update received for ${this.entityId}: state=${state.state}`
175152
175286
  );
175153
175287
  this.lastState = state;
@@ -175378,7 +175512,7 @@ init_esm3();
175378
175512
  init_esm();
175379
175513
  init_types2();
175380
175514
  init_esm4();
175381
- var logger248 = Logger.get("CameraWebRtcRequestor");
175515
+ var logger249 = Logger.get("CameraWebRtcRequestor");
175382
175516
  var registry2 = /* @__PURE__ */ new Map();
175383
175517
  var pendingDeliveries = /* @__PURE__ */ new Map();
175384
175518
  var invokeTransport = defaultInvoke;
@@ -175412,19 +175546,19 @@ function deliverAnswerDeferred(sessionId, sdp, onGiveUp) {
175412
175546
  return;
175413
175547
  }
175414
175548
  if (await sendAnswer(sessionId, sdp)) {
175415
- logger248.info(`answer delivered for session ${sessionId}`);
175549
+ logger249.info(`answer delivered for session ${sessionId}`);
175416
175550
  return;
175417
175551
  }
175418
175552
  }
175419
175553
  if (registry2.get(sessionId) !== owner || pendingDeliveries.get(sessionId) !== timer) {
175420
175554
  return;
175421
175555
  }
175422
- logger248.info(
175556
+ logger249.info(
175423
175557
  `answer delivery failed for session ${sessionId}, giving up`
175424
175558
  );
175425
175559
  await onGiveUp();
175426
175560
  } catch (err) {
175427
- logger248.info(
175561
+ logger249.info(
175428
175562
  `answer delivery for session ${sessionId} threw: ${errText(err)}`
175429
175563
  );
175430
175564
  } finally {
@@ -175449,11 +175583,11 @@ function sendAnswer(sessionId, sdp) {
175449
175583
  async function invokeRequestor(sessionId, command, fields) {
175450
175584
  const registration = registry2.get(sessionId);
175451
175585
  if (!registration) {
175452
- logger248.info(`requestor ${command}: no session ${sessionId} registered`);
175586
+ logger249.info(`requestor ${command}: no session ${sessionId} registered`);
175453
175587
  return false;
175454
175588
  }
175455
175589
  if (registration.session.isClosed) {
175456
- logger248.info(`requestor ${command}: session ${sessionId} already closed`);
175590
+ logger249.info(`requestor ${command}: session ${sessionId} already closed`);
175457
175591
  return false;
175458
175592
  }
175459
175593
  const request = {
@@ -175465,7 +175599,7 @@ async function invokeRequestor(sessionId, command, fields) {
175465
175599
  try {
175466
175600
  return await invokeTransport({ registration, request });
175467
175601
  } catch (err) {
175468
- logger248.info(
175602
+ logger249.info(
175469
175603
  `requestor ${command} failed for session ${sessionId}: ${errText(err)}`
175470
175604
  );
175471
175605
  return false;
@@ -175500,7 +175634,7 @@ async function defaultInvoke({
175500
175634
  for (const entry of chunk) {
175501
175635
  if (entry.kind === "cmd-status") {
175502
175636
  if (entry.status !== Status2.Success) {
175503
- logger248.info(
175637
+ logger249.info(
175504
175638
  `requestor ${request.command} status ${entry.status} for session ${String(request.fields.webRtcSessionId)}`
175505
175639
  );
175506
175640
  return false;
@@ -175520,7 +175654,7 @@ function errText(err) {
175520
175654
  }
175521
175655
 
175522
175656
  // src/plugins/builtin/camera/webrtc-provider-server.ts
175523
- var logger249 = Logger.get("CameraWebRtc");
175657
+ var logger250 = Logger.get("CameraWebRtc");
175524
175658
  var nextGlobalSessionId = 0;
175525
175659
  function mintSessionId() {
175526
175660
  for (let i = 0; i <= 65534; i++) {
@@ -175534,14 +175668,14 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175534
175668
  solicitOffer(request) {
175535
175669
  const id = mintSessionId();
175536
175670
  this.trackSession(id, request.streamUsage, request.originatingEndpointId);
175537
- logger249.info(
175671
+ logger250.info(
175538
175672
  `solicitOffer session=${id} (${this.state.entityId}), deferred offer`
175539
175673
  );
175540
175674
  void this.state.bridge.startSession(id, this.state.entityId, {
175541
175675
  iceServers: request.iceServers,
175542
175676
  iceTransportPolicy: request.iceTransportPolicy
175543
175677
  }).catch(
175544
- (err) => logger249.info(
175678
+ (err) => logger250.info(
175545
175679
  `solicitOffer startSession failed for ${this.state.entityId}: ${errText2(err)}`
175546
175680
  )
175547
175681
  );
@@ -175549,7 +175683,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175549
175683
  }
175550
175684
  async provideOffer(request) {
175551
175685
  const id = request.webRtcSessionId ?? mintSessionId();
175552
- logger249.info(
175686
+ logger250.info(
175553
175687
  `provideOffer entry: entityId=${this.state.entityId} session=${id} (sdp ${request.sdp.length} chars)`
175554
175688
  );
175555
175689
  if (request.webRtcSessionId == null) {
@@ -175583,7 +175717,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175583
175717
  );
175584
175718
  } catch (err) {
175585
175719
  const message = errText2(err);
175586
- logger249.info(
175720
+ logger250.info(
175587
175721
  `provideOffer failed for ${this.state.entityId} session=${id}: ${message}`
175588
175722
  );
175589
175723
  unregisterRequestor(id);
@@ -175595,7 +175729,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175595
175729
  StatusCode.Failure
175596
175730
  );
175597
175731
  }
175598
- logger249.info(
175732
+ logger250.info(
175599
175733
  `provideOffer answer computed for ${this.state.entityId} session=${id} (${answerSdp.length} chars); delivering via requestor`
175600
175734
  );
175601
175735
  const bridge = this.state.bridge;
@@ -175614,7 +175748,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175614
175748
  return { webRtcSessionId: id };
175615
175749
  }
175616
175750
  provideAnswer(request) {
175617
- logger249.info(
175751
+ logger250.info(
175618
175752
  `provideAnswer session=${request.webRtcSessionId} (sdp ${request.sdp.length} chars, ${this.state.entityId})`
175619
175753
  );
175620
175754
  return this.state.bridge.acceptControllerAnswer(
@@ -175623,7 +175757,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175623
175757
  );
175624
175758
  }
175625
175759
  async provideIceCandidates(request) {
175626
- logger249.info(
175760
+ logger250.info(
175627
175761
  `provideIceCandidates session=${request.webRtcSessionId}: ${request.iceCandidates.length} candidate(s) (${this.state.entityId})`
175628
175762
  );
175629
175763
  for (const c of request.iceCandidates) {
@@ -175636,7 +175770,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175636
175770
  }
175637
175771
  }
175638
175772
  async endSession(request) {
175639
- logger249.info(
175773
+ logger250.info(
175640
175774
  `endSession session=${request.webRtcSessionId} (${this.state.entityId})`
175641
175775
  );
175642
175776
  await this.state.bridge.endSession(request.webRtcSessionId);
@@ -175757,7 +175891,7 @@ import {
175757
175891
  createLongLivedTokenAuth as createLongLivedTokenAuth2
175758
175892
  } from "home-assistant-js-websocket";
175759
175893
  import { RTCPeerConnection } from "werift";
175760
- var logger250 = Logger.get("CameraWebRtc");
175894
+ var logger251 = Logger.get("CameraWebRtc");
175761
175895
  var DEFAULT_HA_WEBRTC_TIMEOUT_MS = 15e3;
175762
175896
  var haWebRtcTimeoutMs = DEFAULT_HA_WEBRTC_TIMEOUT_MS;
175763
175897
  var WebRtcBridge = class {
@@ -175804,7 +175938,7 @@ var WebRtcBridge = class {
175804
175938
  const haOffer = await haPeer.createOffer();
175805
175939
  await haPeer.setLocalDescription(haOffer);
175806
175940
  const haOfferSdp = this.localSdp(haPeer);
175807
- logger250.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175941
+ logger251.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175808
175942
  const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
175809
175943
  entityId,
175810
175944
  haOfferSdp,
@@ -175827,12 +175961,12 @@ var WebRtcBridge = class {
175827
175961
  const controllerOffer = await controllerPeer.createOffer();
175828
175962
  await controllerPeer.setLocalDescription(controllerOffer);
175829
175963
  const sdp = this.localSdp(controllerPeer);
175830
- logger250.info(
175964
+ logger251.info(
175831
175965
  `controller offer created for ${entityId} (${sdp.length} chars)`
175832
175966
  );
175833
175967
  return { sdp, iceCandidates };
175834
175968
  } catch (err) {
175835
- logger250.info(`startSession failed for ${entityId}: ${errText3(err)}`);
175969
+ logger251.info(`startSession failed for ${entityId}: ${errText3(err)}`);
175836
175970
  await this.endSession(matterSessionId);
175837
175971
  throw err;
175838
175972
  }
@@ -175862,7 +175996,7 @@ var WebRtcBridge = class {
175862
175996
  const haOffer = await haPeer.createOffer();
175863
175997
  await haPeer.setLocalDescription(haOffer);
175864
175998
  const haOfferSdp = this.localSdp(haPeer);
175865
- logger250.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175999
+ logger251.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175866
176000
  const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
175867
176001
  entityId,
175868
176002
  haOfferSdp,
@@ -175881,12 +176015,12 @@ var WebRtcBridge = class {
175881
176015
  const controllerAnswer = await controllerPeer.createAnswer();
175882
176016
  await controllerPeer.setLocalDescription(controllerAnswer);
175883
176017
  const answerSdp = this.localSdp(controllerPeer);
175884
- logger250.info(
176018
+ logger251.info(
175885
176019
  `controller answer created for ${entityId} (${answerSdp.length} chars)`
175886
176020
  );
175887
176021
  return answerSdp;
175888
176022
  } catch (err) {
175889
- logger250.info(
176023
+ logger251.info(
175890
176024
  `acceptControllerOffer failed for ${entityId}: ${errText3(err)}`
175891
176025
  );
175892
176026
  await this.endSession(matterSessionId);
@@ -175897,14 +176031,14 @@ var WebRtcBridge = class {
175897
176031
  async acceptControllerAnswer(matterSessionId, sdp) {
175898
176032
  const session = this.sessions.get(matterSessionId);
175899
176033
  if (!session) return;
175900
- logger250.debug(`controller answer applied for ${session.entityId}`);
176034
+ logger251.debug(`controller answer applied for ${session.entityId}`);
175901
176035
  await session.controllerPeer.setRemoteDescription({ type: "answer", sdp });
175902
176036
  }
175903
176037
  /** Add a remote ICE candidate from the Matter controller. */
175904
176038
  async addControllerIceCandidate(matterSessionId, candidate, sdpMid, sdpMLineIndex) {
175905
176039
  const session = this.sessions.get(matterSessionId);
175906
176040
  if (!session) return;
175907
- logger250.debug(
176041
+ logger251.debug(
175908
176042
  `controller ICE candidate for ${session.entityId}: ${candidate}`
175909
176043
  );
175910
176044
  await session.controllerPeer.addIceCandidate({
@@ -175918,12 +176052,12 @@ var WebRtcBridge = class {
175918
176052
  async closeExistingPeers(matterSessionId) {
175919
176053
  const prior = this.sessions.get(matterSessionId);
175920
176054
  if (!prior) return;
175921
- logger250.info(
176055
+ logger251.info(
175922
176056
  `replacing session ${matterSessionId} (${prior.entityId}), closing prior peers`
175923
176057
  );
175924
176058
  if (prior.haUnsubscribe) {
175925
176059
  await Promise.resolve(prior.haUnsubscribe()).catch(
175926
- (err) => logger250.debug(`HA unsubscribe failed: ${errText3(err)}`)
176060
+ (err) => logger251.debug(`HA unsubscribe failed: ${errText3(err)}`)
175927
176061
  );
175928
176062
  }
175929
176063
  await prior.haPeer.close().catch(() => {
@@ -175936,11 +176070,11 @@ var WebRtcBridge = class {
175936
176070
  async endSession(matterSessionId) {
175937
176071
  const session = this.sessions.get(matterSessionId);
175938
176072
  if (!session) return;
175939
- logger250.info(`ending session ${matterSessionId} (${session.entityId})`);
176073
+ logger251.info(`ending session ${matterSessionId} (${session.entityId})`);
175940
176074
  this.sessions.delete(matterSessionId);
175941
176075
  if (session.haUnsubscribe) {
175942
176076
  await Promise.resolve(session.haUnsubscribe()).catch(
175943
- (err) => logger250.debug(`HA unsubscribe failed: ${errText3(err)}`)
176077
+ (err) => logger251.debug(`HA unsubscribe failed: ${errText3(err)}`)
175944
176078
  );
175945
176079
  }
175946
176080
  await session.haPeer.close().catch(() => {
@@ -175970,11 +176104,11 @@ var WebRtcBridge = class {
175970
176104
  headers: { Authorization: `Bearer ${this.config.haToken}` }
175971
176105
  });
175972
176106
  } catch (err) {
175973
- logger250.info(`snapshot fetch failed for ${entityId}: ${errText3(err)}`);
176107
+ logger251.info(`snapshot fetch failed for ${entityId}: ${errText3(err)}`);
175974
176108
  throw err;
175975
176109
  }
175976
176110
  if (!res.ok) {
175977
- logger250.info(
176111
+ logger251.info(
175978
176112
  `snapshot fetch failed for ${entityId}: camera_proxy ${res.status}`
175979
176113
  );
175980
176114
  throw new Error(`HA camera_proxy ${entityId}: ${res.status}`);
@@ -175991,10 +176125,10 @@ var WebRtcBridge = class {
175991
176125
  // Forward every track HA sends into the matching pre-added controller sender.
175992
176126
  forwardHaTracks(haPeer, senders, entityId) {
175993
176127
  haPeer.onTrack.subscribe((track) => {
175994
- logger250.info(`onTrack ${track.kind} from HA (${entityId})`);
176128
+ logger251.info(`onTrack ${track.kind} from HA (${entityId})`);
175995
176129
  const transceiver = senders.get(track.kind);
175996
176130
  if (!transceiver) {
175997
- logger250.info(
176131
+ logger251.info(
175998
176132
  `no controller transceiver for ${track.kind} (${entityId})`
175999
176133
  );
176000
176134
  return;
@@ -176003,7 +176137,7 @@ var WebRtcBridge = class {
176003
176137
  track.onReceiveRtp.subscribe((rtp) => {
176004
176138
  if (!firstLogged) {
176005
176139
  firstLogged = true;
176006
- logger250.info(`first RTP forwarded for ${track.kind} (${entityId})`);
176140
+ logger251.info(`first RTP forwarded for ${track.kind} (${entityId})`);
176007
176141
  }
176008
176142
  transceiver.sender.sendRtp(rtp);
176009
176143
  });
@@ -176012,10 +176146,10 @@ var WebRtcBridge = class {
176012
176146
  // Log connection/ice state transitions (these events fire on change only).
176013
176147
  wireStateLogging(peer, label, entityId) {
176014
176148
  peer.connectionStateChange.subscribe(
176015
- (s) => logger250.info(`${label} connectionState=${s} (${entityId})`)
176149
+ (s) => logger251.info(`${label} connectionState=${s} (${entityId})`)
176016
176150
  );
176017
176151
  peer.iceConnectionStateChange.subscribe(
176018
- (s) => logger250.info(`${label} iceConnectionState=${s} (${entityId})`)
176152
+ (s) => logger251.info(`${label} iceConnectionState=${s} (${entityId})`)
176019
176153
  );
176020
176154
  }
176021
176155
  // Map the Matter ICE struct onto werift's config. Only the controller peer
@@ -176029,11 +176163,11 @@ var WebRtcBridge = class {
176029
176163
  }))
176030
176164
  );
176031
176165
  if (iceServers.length === 0) {
176032
- logger250.info(`controller peer using default ICE servers (${entityId})`);
176166
+ logger251.info(`controller peer using default ICE servers (${entityId})`);
176033
176167
  return void 0;
176034
176168
  }
176035
176169
  const policy = ice?.iceTransportPolicy === "relay" || ice?.iceTransportPolicy === "all" ? ice.iceTransportPolicy : void 0;
176036
- logger250.info(
176170
+ logger251.info(
176037
176171
  `controller peer using ${iceServers.length} controller ICE server(s)${policy ? ` policy=${policy}` : ""} (${entityId})`
176038
176172
  );
176039
176173
  return policy ? { iceServers, iceTransportPolicy: policy } : { iceServers };
@@ -176047,13 +176181,13 @@ var WebRtcBridge = class {
176047
176181
  feedHaCandidate(entityId, haPeer, candidate) {
176048
176182
  const value = candidate?.candidate;
176049
176183
  if (!value) return;
176050
- logger250.debug(`HA ICE candidate for ${entityId}: ${value}`);
176184
+ logger251.debug(`HA ICE candidate for ${entityId}: ${value}`);
176051
176185
  void haPeer.addIceCandidate({
176052
176186
  candidate: value,
176053
176187
  sdpMid: candidate?.sdpMid ?? void 0,
176054
176188
  sdpMLineIndex: candidate?.sdpMLineIndex ?? void 0
176055
176189
  }).catch(
176056
- (e) => logger250.debug(
176190
+ (e) => logger251.debug(
176057
176191
  `HA addIceCandidate failed for ${entityId}: ${errText3(e)}`
176058
176192
  )
176059
176193
  );
@@ -176082,7 +176216,7 @@ var WebRtcBridge = class {
176082
176216
  reject(err);
176083
176217
  });
176084
176218
  timer = setTimeout(() => {
176085
- logger250.info(
176219
+ logger251.info(
176086
176220
  `HA WebRTC timed out after ${haWebRtcTimeoutMs}ms for ${entityId}`
176087
176221
  );
176088
176222
  fail(
@@ -176100,7 +176234,7 @@ var WebRtcBridge = class {
176100
176234
  if (msg.session_id) sessionId = msg.session_id;
176101
176235
  const ans = msg.answer;
176102
176236
  settle(() => {
176103
- logger250.info(
176237
+ logger251.info(
176104
176238
  `HA answer received for ${entityId} (${ans.length} chars)`
176105
176239
  );
176106
176240
  resolve11(ans);
@@ -176109,7 +176243,7 @@ var WebRtcBridge = class {
176109
176243
  break;
176110
176244
  case "error": {
176111
176245
  const detail = msg.message ?? msg.code ?? "unknown error";
176112
- logger250.info(`HA WebRTC error for ${entityId}: ${detail}`);
176246
+ logger251.info(`HA WebRTC error for ${entityId}: ${detail}`);
176113
176247
  fail(new Error(`HA WebRTC error: ${detail}`));
176114
176248
  break;
176115
176249
  }
@@ -177266,7 +177400,7 @@ import {
177266
177400
  getCollection
177267
177401
  } from "home-assistant-js-websocket";
177268
177402
  import { atLeastHaVersion } from "home-assistant-js-websocket/dist/util.js";
177269
- var logger251 = Logger.get("SubscribeEntities");
177403
+ var logger252 = Logger.get("SubscribeEntities");
177270
177404
  function processEvent(store, updates) {
177271
177405
  const state = { ...store.state };
177272
177406
  if (updates.a) {
@@ -177292,7 +177426,7 @@ function processEvent(store, updates) {
177292
177426
  for (const entityId in updates.c) {
177293
177427
  let entityState = state[entityId];
177294
177428
  if (!entityState) {
177295
- logger251.warn("Received state update for unknown entity", entityId);
177429
+ logger252.warn("Received state update for unknown entity", entityId);
177296
177430
  continue;
177297
177431
  }
177298
177432
  entityState = { ...entityState };
@@ -178179,138 +178313,130 @@ function hashAreaId(areaId) {
178179
178313
  return Math.abs(hash2);
178180
178314
  }
178181
178315
 
178182
- // src/services/bridges/entity-isolation-service.ts
178183
- init_esm();
178184
- init_diagnostic_event_bus();
178185
- var logger252 = Logger.get("EntityIsolation");
178186
- var EntityIsolationServiceImpl = class {
178187
- isolatedEntities = /* @__PURE__ */ new Map();
178188
- isolationCallbacks = /* @__PURE__ */ new Map();
178189
- /**
178190
- * Register a callback to be called when an entity needs to be isolated.
178191
- * The callback should remove the entity from the bridge's aggregator.
178192
- */
178193
- registerIsolationCallback(bridgeId, callback) {
178194
- this.isolationCallbacks.set(bridgeId, callback);
178316
+ // src/services/bridges/entity-mapping-sync.ts
178317
+ var EntityMappingSync = class {
178318
+ constructor(registry3, getMapping, log) {
178319
+ this.registry = registry3;
178320
+ this.getMapping = getMapping;
178321
+ this.log = log;
178195
178322
  }
178196
- unregisterIsolationCallback(bridgeId) {
178197
- this.isolationCallbacks.delete(bridgeId);
178323
+ registry;
178324
+ getMapping;
178325
+ log;
178326
+ retryScheduled = false;
178327
+ retryTimer = null;
178328
+ // deviceId -> primary entityId of endpoints that auto-map but carry no
178329
+ // battery, bounds the per-state-batch check to a map hit
178330
+ candidates = /* @__PURE__ */ new Map();
178331
+ // Only endpoints the auto-mapping applies to belong in the candidates: a
178332
+ // manual or disabled mapping, or a sensor endpoint sharing the device,
178333
+ // must not claim the slot (last writer would win) and stall the recovery.
178334
+ eligible(entityId) {
178335
+ const mapping = this.getMapping(entityId);
178336
+ if (mapping?.batteryEntity || mapping?.disableBatteryMapping) return false;
178337
+ if (entityId.startsWith("sensor.") || entityId.startsWith("binary_sensor.")) {
178338
+ return false;
178339
+ }
178340
+ return entityId.startsWith("vacuum.") || !!this.registry.isAutoBatteryMappingEnabled?.();
178198
178341
  }
178199
- /**
178200
- * Parse the endpoint path from a Matter.js error message and extract the entity name.
178201
- * Example path: "ed5b4f8d042e4599b833f21da4ededba.aggregator.Küchenlicht.onOff.on"
178202
- * Returns: { bridgeId: "ed5b4f8d...", entityName: "Küchenlicht" }
178203
- */
178204
- parseEndpointPath(errorMessage) {
178205
- const match = errorMessage.match(/([a-f0-9]{32})\.aggregator\.([^.\s>]+)/i);
178206
- if (match) {
178207
- return {
178208
- bridgeId: match[1],
178209
- entityName: match[2]
178210
- };
178211
- }
178212
- return null;
178342
+ // the auto-resolved battery is part of the endpoint shape, so a sensor
178343
+ // that appears later must change the fingerprint and rebuild. JSON tuple
178344
+ // so mapping text can never collide with a battery marker.
178345
+ computeFingerprint(mapping, entityId) {
178346
+ const battery = entityId ? this.registry.batteryFingerprintFor(entityId, mapping) : "";
178347
+ return JSON.stringify([mapping ?? null, battery || null]);
178213
178348
  }
178214
- classifyError(msg) {
178215
- if (msg.includes("Invalid intervalMs")) {
178216
- return "Subscription timing error (Invalid intervalMs)";
178217
- }
178218
- if (msg.includes("Behaviors have errors")) {
178219
- return "Behavior initialization failure";
178220
- }
178221
- if (msg.includes("TransactionDestroyedError")) {
178222
- return "Transaction destroyed during operation";
178223
- }
178224
- if (msg.includes("DestroyedDependencyError")) {
178225
- return "Dependency destroyed during operation";
178226
- }
178227
- if (msg.includes("UninitializedDependencyError")) {
178228
- return "Uninitialized dependency access";
178229
- }
178230
- if (msg.includes("Endpoint storage inaccessible")) {
178231
- return "Endpoint storage inaccessible";
178232
- }
178233
- if (msg.includes("Error initializing part")) {
178234
- return "Endpoint construction failure";
178235
- }
178236
- if (msg.includes("aggregator.")) {
178237
- return "Runtime error in endpoint";
178349
+ // Live fingerprint for reconcile compares: when the resolver finds nothing
178350
+ // right now but the stored fingerprint maps a sensor that still exists on
178351
+ // the SAME device, keep it. An unavailable snapshot (HA restart) must not
178352
+ // strip the mapping and rebuild the endpoint battery-less.
178353
+ compareFingerprint(mapping, entityId, storedFingerprint) {
178354
+ const fingerprint = this.computeFingerprint(mapping, entityId);
178355
+ if (fingerprintBattery(fingerprint) != null || !storedFingerprint)
178356
+ return fingerprint;
178357
+ if (!this.eligible(entityId)) return fingerprint;
178358
+ const battery = fingerprintBattery(storedFingerprint);
178359
+ if (!battery) return fingerprint;
178360
+ const deviceId = this.registry.entity(entityId)?.device_id;
178361
+ const stillSameDevice = !!deviceId && this.registry.fullEntities[battery]?.device_id === deviceId;
178362
+ return stillSameDevice ? JSON.stringify([mapping ?? null, battery]) : fingerprint;
178363
+ }
178364
+ // The stored fingerprint must reflect what the endpoint actually maps: a
178365
+ // battery resolved while it was built without one (sensor outage during a
178366
+ // forced rebuild) would otherwise never trigger the catch-up.
178367
+ fingerprintAsBuilt(mapping, entityId, mappedEntityIds) {
178368
+ const fingerprint = this.computeFingerprint(mapping, entityId);
178369
+ const battery = fingerprintBattery(fingerprint);
178370
+ if (battery == null) return fingerprint;
178371
+ return (mappedEntityIds ?? []).includes(battery) ? fingerprint : JSON.stringify([mapping ?? null, null]);
178372
+ }
178373
+ rebuildCandidates(entries) {
178374
+ this.candidates.clear();
178375
+ for (const [entityId, fingerprint] of entries) {
178376
+ if (fingerprintBattery(fingerprint) != null) continue;
178377
+ if (!this.eligible(entityId)) continue;
178378
+ const deviceId = this.registry.entity(entityId)?.device_id;
178379
+ if (deviceId) this.candidates.set(deviceId, entityId);
178238
178380
  }
178239
- return null;
178240
178381
  }
178241
- /**
178242
- * Attempt to isolate an entity based on an error.
178243
- * Returns true if the entity was successfully identified and isolation was triggered.
178244
- */
178245
- async isolateFromError(error) {
178246
- const msg = error instanceof Error ? error.message : String(error);
178247
- const classification = this.classifyError(msg);
178248
- if (!classification) {
178249
- return false;
178382
+ // battery-less auto-map endpoints watch their device's sensors, an
178383
+ // unresolved battery is not mapped so it would never arrive otherwise
178384
+ candidateSensorIds() {
178385
+ if (this.candidates.size === 0) return [];
178386
+ const ids = [];
178387
+ for (const entity of Object.values(this.registry.fullEntities)) {
178388
+ if (!entity.device_id) continue;
178389
+ if (!this.candidates.has(entity.device_id)) continue;
178390
+ if (entity.entity_id.startsWith("sensor.") || entity.entity_id.startsWith("binary_sensor.")) {
178391
+ ids.push(entity.entity_id);
178392
+ }
178250
178393
  }
178251
- const parsed = this.parseEndpointPath(msg);
178252
- if (!parsed) {
178253
- logger252.warn("Could not parse entity from error:", msg);
178254
- return false;
178394
+ return ids;
178395
+ }
178396
+ // An endpoint built while its battery sensor was unavailable stays
178397
+ // battery-less, because registry ticks only refresh on structural changes.
178398
+ // When a same-device sensor state arrives, re-resolve and rebuild once.
178399
+ maybeRetry(states, changed, observing, refresh) {
178400
+ if (!observing || this.retryScheduled || this.candidates.size === 0) {
178401
+ return;
178255
178402
  }
178256
- const { bridgeId, entityName } = parsed;
178257
- const callback = this.isolationCallbacks.get(bridgeId);
178258
- if (!callback) {
178259
- logger252.warn(
178260
- `No isolation callback registered for bridge ${bridgeId}, entity: ${entityName}`
178403
+ for (const id of changed ?? Object.keys(states)) {
178404
+ if (!id.startsWith("sensor.") && !id.startsWith("binary_sensor."))
178405
+ continue;
178406
+ const deviceId = this.registry.fullEntities[id]?.device_id;
178407
+ if (!deviceId) continue;
178408
+ const entityId = this.candidates.get(deviceId);
178409
+ if (!entityId) continue;
178410
+ this.registry.forgetBatteryCacheForDevice(deviceId);
178411
+ const resolved = this.registry.batteryFingerprintFor(
178412
+ entityId,
178413
+ this.getMapping(entityId)
178261
178414
  );
178262
- return false;
178263
- }
178264
- const key = `${bridgeId}:${entityName}`;
178265
- if (this.isolatedEntities.has(key)) {
178266
- return true;
178267
- }
178268
- const reason = `${classification}. Entity isolated to protect bridge stability.`;
178269
- this.isolatedEntities.set(key, {
178270
- entityId: entityName,
178271
- reason,
178272
- failedAt: (/* @__PURE__ */ new Date()).toISOString()
178273
- });
178274
- logger252.warn(
178275
- `Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
178276
- );
178277
- diagnosticEventBus.emit("entity_error", `Entity isolated: ${entityName}`, {
178278
- bridgeId,
178279
- entityId: entityName,
178280
- details: { reason: classification }
178281
- });
178282
- try {
178283
- await callback(entityName);
178284
- return true;
178285
- } catch (e) {
178286
- logger252.error(`Failed to isolate entity ${entityName}:`, e);
178287
- return false;
178415
+ if (!resolved) continue;
178416
+ this.retryScheduled = true;
178417
+ this.log.info(
178418
+ `Battery sensor ${resolved} appeared for ${entityId}, rebuilding`
178419
+ );
178420
+ this.retryTimer = setTimeout(() => {
178421
+ this.retryTimer = null;
178422
+ refresh().catch((e) => this.log.warn("Battery retry refresh failed:", e)).finally(() => {
178423
+ this.retryScheduled = false;
178424
+ });
178425
+ }, 0);
178426
+ return;
178288
178427
  }
178289
178428
  }
178290
- /**
178291
- * Get all isolated entities for a specific bridge.
178292
- */
178293
- getIsolatedEntities(bridgeId) {
178294
- const result = [];
178295
- for (const [key, entity] of this.isolatedEntities) {
178296
- if (key.startsWith(`${bridgeId}:`)) {
178297
- result.push(entity);
178298
- }
178429
+ cancelRetry() {
178430
+ if (this.retryTimer) {
178431
+ clearTimeout(this.retryTimer);
178432
+ this.retryTimer = null;
178299
178433
  }
178300
- return result;
178434
+ this.retryScheduled = false;
178301
178435
  }
178302
- /**
178303
- * Clear isolated entities for a bridge (e.g., on restart).
178304
- */
178305
- clearIsolatedEntities(bridgeId) {
178306
- for (const key of this.isolatedEntities.keys()) {
178307
- if (key.startsWith(`${bridgeId}:`)) {
178308
- this.isolatedEntities.delete(key);
178309
- }
178310
- }
178436
+ get retryPending() {
178437
+ return this.retryScheduled;
178311
178438
  }
178312
178439
  };
178313
- var EntityIsolationService = new EntityIsolationServiceImpl();
178314
178440
 
178315
178441
  // src/services/bridges/bridge-endpoint-manager.ts
178316
178442
  var MAX_ENTITY_ID_LENGTH = 150;
@@ -178338,6 +178464,11 @@ var BridgeEndpointManager = class extends Service {
178338
178464
  identityStorage,
178339
178465
  mappingStorage
178340
178466
  );
178467
+ this.mappingSync = new EntityMappingSync(
178468
+ registry3,
178469
+ (entityId) => this.getEntityMapping(entityId),
178470
+ log
178471
+ );
178341
178472
  EntityIsolationService.registerIsolationCallback(
178342
178473
  bridgeId,
178343
178474
  this.isolateEntity.bind(this)
@@ -178361,6 +178492,7 @@ var BridgeEndpointManager = class extends Service {
178361
178492
  observingRequested = false;
178362
178493
  _failedEntities = [];
178363
178494
  mappingFingerprints = /* @__PURE__ */ new Map();
178495
+ mappingSync;
178364
178496
  // entityId -> first absence stamp (grace window)
178365
178497
  pendingRemovals = /* @__PURE__ */ new Map();
178366
178498
  removalRecheckTimer = null;
@@ -178698,95 +178830,6 @@ var BridgeEndpointManager = class extends Service {
178698
178830
  getEntityMapping(entityId) {
178699
178831
  return this.mappingStorage.getMapping(this.bridgeId, entityId);
178700
178832
  }
178701
- // #450: an endpoint built while its battery sensor was unavailable stays
178702
- // battery-less, because registry ticks only refresh on structural changes.
178703
- // When a same-device sensor state arrives, re-resolve and rebuild.
178704
- batteryRetryScheduled = false;
178705
- batteryRetryTimer = null;
178706
- // deviceId -> primary entityId of endpoints that auto-map but carry no
178707
- // battery, bounds the per-state-batch check to a map hit
178708
- batteryRetryCandidates = /* @__PURE__ */ new Map();
178709
- // Only endpoints the auto-mapping applies to belong here: a manual or
178710
- // disabled mapping, or a sensor endpoint sharing the device, must not
178711
- // claim the slot (last writer would win) and stall the recovery.
178712
- batteryRetryEligible(entityId) {
178713
- const mapping = this.getEntityMapping(entityId);
178714
- if (mapping?.batteryEntity || mapping?.disableBatteryMapping) return false;
178715
- if (entityId.startsWith("sensor.") || entityId.startsWith("binary_sensor.")) {
178716
- return false;
178717
- }
178718
- return entityId.startsWith("vacuum.") || !!this.registry.isAutoBatteryMappingEnabled?.();
178719
- }
178720
- rebuildBatteryRetryCandidates() {
178721
- this.batteryRetryCandidates.clear();
178722
- for (const part of this.root.parts) {
178723
- if (!hasEntityIdentity(part)) continue;
178724
- const fingerprint = this.mappingFingerprints.get(part.entityId);
178725
- if (fingerprint === void 0) continue;
178726
- if (fingerprintBattery(fingerprint) != null) continue;
178727
- if (!this.batteryRetryEligible(part.entityId)) continue;
178728
- const deviceId = this.registry.entity(part.entityId)?.device_id;
178729
- if (deviceId) this.batteryRetryCandidates.set(deviceId, part.entityId);
178730
- }
178731
- }
178732
- maybeRetryBatteryMapping(states, changed) {
178733
- if (!this.observingRequested || this.batteryRetryScheduled || this.batteryRetryCandidates.size === 0) {
178734
- return;
178735
- }
178736
- for (const id of changed ?? Object.keys(states)) {
178737
- if (!id.startsWith("sensor.") && !id.startsWith("binary_sensor."))
178738
- continue;
178739
- const deviceId = this.registry.fullEntities[id]?.device_id;
178740
- if (!deviceId) continue;
178741
- const entityId = this.batteryRetryCandidates.get(deviceId);
178742
- if (!entityId) continue;
178743
- this.registry.forgetBatteryCacheForDevice(deviceId);
178744
- const resolved = this.registry.batteryFingerprintFor(
178745
- entityId,
178746
- this.getEntityMapping(entityId)
178747
- );
178748
- if (!resolved) continue;
178749
- this.batteryRetryScheduled = true;
178750
- this.log.info(
178751
- `Battery sensor ${resolved} appeared for ${entityId}, rebuilding`
178752
- );
178753
- this.batteryRetryTimer = setTimeout(() => {
178754
- this.batteryRetryTimer = null;
178755
- this.refreshDevices().catch((e) => this.log.warn("Battery retry refresh failed:", e)).finally(() => {
178756
- this.batteryRetryScheduled = false;
178757
- });
178758
- }, 0);
178759
- return;
178760
- }
178761
- }
178762
- computeMappingFingerprint(mapping, entityId) {
178763
- const battery = entityId ? this.registry.batteryFingerprintFor(entityId, mapping) : "";
178764
- return JSON.stringify([mapping ?? null, battery || null]);
178765
- }
178766
- // Live fingerprint for reconcile compares: when the resolver finds nothing
178767
- // right now but the stored fingerprint maps a sensor that still exists on
178768
- // the SAME device, keep it. An unavailable snapshot (HA restart) must not
178769
- // strip the mapping and rebuild the endpoint battery-less (#450).
178770
- compareFingerprint(mapping, entityId, storedFingerprint) {
178771
- const fingerprint = this.computeMappingFingerprint(mapping, entityId);
178772
- if (fingerprintBattery(fingerprint) != null || !storedFingerprint)
178773
- return fingerprint;
178774
- if (!this.batteryRetryEligible(entityId)) return fingerprint;
178775
- const battery = fingerprintBattery(storedFingerprint);
178776
- if (!battery) return fingerprint;
178777
- const deviceId = this.registry.entity(entityId)?.device_id;
178778
- const stillSameDevice = !!deviceId && this.registry.fullEntities[battery]?.device_id === deviceId;
178779
- return stillSameDevice ? JSON.stringify([mapping ?? null, battery]) : fingerprint;
178780
- }
178781
- // The stored fingerprint must reflect what this endpoint actually maps: a
178782
- // battery resolved while the endpoint was built without one (sensor outage
178783
- // during a forced rebuild) would otherwise never trigger the catch-up (#450).
178784
- fingerprintAsBuilt(mapping, entityId, endpoint) {
178785
- const fingerprint = this.computeMappingFingerprint(mapping, entityId);
178786
- const battery = fingerprintBattery(fingerprint);
178787
- if (battery == null) return fingerprint;
178788
- return (endpoint.mappedEntityIds ?? []).includes(battery) ? fingerprint : JSON.stringify([mapping ?? null, null]);
178789
- }
178790
178833
  async dispose() {
178791
178834
  this.stopObserving();
178792
178835
  if (this.removalRecheckTimer) {
@@ -178829,14 +178872,8 @@ var BridgeEndpointManager = class extends Service {
178829
178872
  }
178830
178873
  }
178831
178874
  }
178832
- if (this.batteryRetryCandidates.size > 0) {
178833
- for (const entity of Object.values(this.registry.fullEntities)) {
178834
- if (!entity.device_id) continue;
178835
- if (!this.batteryRetryCandidates.has(entity.device_id)) continue;
178836
- if (entity.entity_id.startsWith("sensor.") || entity.entity_id.startsWith("binary_sensor.")) {
178837
- ids.add(entity.entity_id);
178838
- }
178839
- }
178875
+ for (const id of this.mappingSync.candidateSensorIds()) {
178876
+ ids.add(id);
178840
178877
  }
178841
178878
  return [...ids];
178842
178879
  }
@@ -178852,11 +178889,7 @@ var BridgeEndpointManager = class extends Service {
178852
178889
  clearTimeout(this.removalRecheckTimer);
178853
178890
  this.removalRecheckTimer = null;
178854
178891
  }
178855
- if (this.batteryRetryTimer) {
178856
- clearTimeout(this.batteryRetryTimer);
178857
- this.batteryRetryTimer = null;
178858
- }
178859
- this.batteryRetryScheduled = false;
178892
+ this.mappingSync.cancelRetry();
178860
178893
  }
178861
178894
  async refreshDevices() {
178862
178895
  this.registry.refresh();
@@ -179009,7 +179042,7 @@ var BridgeEndpointManager = class extends Service {
179009
179042
  } else {
179010
179043
  const currentMapping = this.getEntityMapping(endpoint.entityId);
179011
179044
  const storedFp = this.mappingFingerprints.get(endpoint.entityId) ?? "";
179012
- const currentFp = this.compareFingerprint(
179045
+ const currentFp = this.mappingSync.compareFingerprint(
179013
179046
  currentMapping,
179014
179047
  endpoint.entityId,
179015
179048
  storedFp
@@ -179100,7 +179133,11 @@ var BridgeEndpointManager = class extends Service {
179100
179133
  await this.root.add(endpoint);
179101
179134
  this.mappingFingerprints.set(
179102
179135
  entityId,
179103
- this.fingerprintAsBuilt(mapping, entityId, endpoint)
179136
+ this.mappingSync.fingerprintAsBuilt(
179137
+ mapping,
179138
+ entityId,
179139
+ endpoint.mappedEntityIds
179140
+ )
179104
179141
  );
179105
179142
  } catch (e) {
179106
179143
  const errorMessage = e instanceof Error ? e.message : String(e);
@@ -179114,7 +179151,12 @@ var BridgeEndpointManager = class extends Service {
179114
179151
  }
179115
179152
  }
179116
179153
  await this.reconcileAreaSwitches();
179117
- this.rebuildBatteryRetryCandidates();
179154
+ this.mappingSync.rebuildCandidates(
179155
+ [...this.root.parts].filter(hasEntityIdentity).flatMap((p) => {
179156
+ const fp = this.mappingFingerprints.get(p.entityId);
179157
+ return fp === void 0 ? [] : [[p.entityId, fp]];
179158
+ })
179159
+ );
179118
179160
  if (this.observingRequested) {
179119
179161
  this.startObserving();
179120
179162
  }
@@ -179258,7 +179300,12 @@ var BridgeEndpointManager = class extends Service {
179258
179300
  async runUpdateStates(states, changed) {
179259
179301
  const startMs = performance.now();
179260
179302
  this.registry.mergeExternalStates(states);
179261
- this.maybeRetryBatteryMapping(states, changed);
179303
+ this.mappingSync.maybeRetry(
179304
+ states,
179305
+ changed,
179306
+ this.observingRequested,
179307
+ () => this.refreshDevices()
179308
+ );
179262
179309
  const allEndpoints = [...this.root.parts].filter(isEntityPart);
179263
179310
  const endpoints = changed === null ? allEndpoints : allEndpoints.filter(
179264
179311
  (e) => changed.has(e.entityId) || (e.mappedEntityIds ?? []).some((id) => changed.has(id))
@@ -180009,6 +180056,11 @@ var ServerModeEndpointManager = class extends Service {
180009
180056
  identityStorage,
180010
180057
  mappingStorage
180011
180058
  );
180059
+ this.mappingSync = new EntityMappingSync(
180060
+ registry3,
180061
+ (entityId) => this.getEntityMapping(entityId),
180062
+ log
180063
+ );
180012
180064
  }
180013
180065
  serverNode;
180014
180066
  client;
@@ -180022,6 +180074,7 @@ var ServerModeEndpointManager = class extends Service {
180022
180074
  observingRequested = false;
180023
180075
  _failedEntities = [];
180024
180076
  endpoints = /* @__PURE__ */ new Map();
180077
+ mappingSync;
180025
180078
  // Same grace as the aggregator manager: server mode deleted on the FIRST
180026
180079
  // refresh an entity was absent, so one partial HA snapshot re-minted the
180027
180080
  // device (#438).
@@ -180044,83 +180097,6 @@ var ServerModeEndpointManager = class extends Service {
180044
180097
  getEntityMapping(entityId) {
180045
180098
  return this.mappingStorage.getMapping(this.dataProvider.id, entityId);
180046
180099
  }
180047
- // #450: an endpoint built while its battery sensor was unavailable stays
180048
- // battery-less, because registry ticks only refresh on structural changes.
180049
- // When a same-device sensor state arrives, re-resolve and rebuild.
180050
- batteryRetryScheduled = false;
180051
- batteryRetryTimer = null;
180052
- // deviceId -> primary entityId of endpoints that auto-map but carry no
180053
- // battery, bounds the per-state-batch check to a map hit
180054
- batteryRetryCandidates = /* @__PURE__ */ new Map();
180055
- // Only endpoints the auto-mapping applies to belong here: a manual or
180056
- // disabled mapping, or a sensor endpoint sharing the device, must not
180057
- // claim the slot (last writer would win) and stall the recovery.
180058
- batteryRetryEligible(entityId) {
180059
- const mapping = this.getEntityMapping(entityId);
180060
- if (mapping?.batteryEntity || mapping?.disableBatteryMapping) return false;
180061
- if (entityId.startsWith("sensor.") || entityId.startsWith("binary_sensor.")) {
180062
- return false;
180063
- }
180064
- return entityId.startsWith("vacuum.") || !!this.registry.isAutoBatteryMappingEnabled?.();
180065
- }
180066
- rebuildBatteryRetryCandidates() {
180067
- this.batteryRetryCandidates.clear();
180068
- for (const [entityId, entry] of this.endpoints) {
180069
- if (fingerprintBattery(entry.fingerprint) != null) continue;
180070
- if (!this.batteryRetryEligible(entityId)) continue;
180071
- const deviceId = this.registry.entity(entityId)?.device_id;
180072
- if (deviceId) this.batteryRetryCandidates.set(deviceId, entityId);
180073
- }
180074
- }
180075
- maybeRetryBatteryMapping(states) {
180076
- if (!this.observingRequested || this.batteryRetryScheduled || this.batteryRetryCandidates.size === 0) {
180077
- return;
180078
- }
180079
- for (const id of Object.keys(states)) {
180080
- if (!id.startsWith("sensor.") && !id.startsWith("binary_sensor."))
180081
- continue;
180082
- const deviceId = this.registry.fullEntities[id]?.device_id;
180083
- if (!deviceId) continue;
180084
- const entityId = this.batteryRetryCandidates.get(deviceId);
180085
- if (!entityId) continue;
180086
- this.registry.forgetBatteryCacheForDevice(deviceId);
180087
- const resolved = this.registry.batteryFingerprintFor(
180088
- entityId,
180089
- this.getEntityMapping(entityId)
180090
- );
180091
- if (!resolved) continue;
180092
- this.batteryRetryScheduled = true;
180093
- this.log.info(
180094
- `Battery sensor ${resolved} appeared for ${entityId}, rebuilding`
180095
- );
180096
- this.batteryRetryTimer = setTimeout(() => {
180097
- this.batteryRetryTimer = null;
180098
- this.refreshDevices().catch((e) => this.log.warn("Battery retry refresh failed:", e)).finally(() => {
180099
- this.batteryRetryScheduled = false;
180100
- });
180101
- }, 0);
180102
- return;
180103
- }
180104
- }
180105
- computeMappingFingerprint(mapping, entityId) {
180106
- const battery = entityId ? this.registry.batteryFingerprintFor(entityId, mapping) : "";
180107
- return JSON.stringify([mapping ?? null, battery || null]);
180108
- }
180109
- // Live fingerprint for reconcile compares: when the resolver finds nothing
180110
- // right now but the stored fingerprint maps a sensor that still exists on
180111
- // the SAME device, keep it. An unavailable snapshot (HA restart) must not
180112
- // strip the mapping and rebuild the endpoint battery-less (#450).
180113
- compareFingerprint(mapping, entityId, storedFingerprint) {
180114
- const fingerprint = this.computeMappingFingerprint(mapping, entityId);
180115
- if (fingerprintBattery(fingerprint) != null || !storedFingerprint)
180116
- return fingerprint;
180117
- if (!this.batteryRetryEligible(entityId)) return fingerprint;
180118
- const battery = fingerprintBattery(storedFingerprint);
180119
- if (!battery) return fingerprint;
180120
- const deviceId = this.registry.entity(entityId)?.device_id;
180121
- const stillSameDevice = !!deviceId && this.registry.fullEntities[battery]?.device_id === deviceId;
180122
- return stillSameDevice ? JSON.stringify([mapping ?? null, battery]) : fingerprint;
180123
- }
180124
180100
  async dispose() {
180125
180101
  this.stopObserving();
180126
180102
  if (this.removalRecheckTimer) {
@@ -180160,14 +180136,8 @@ var ServerModeEndpointManager = class extends Service {
180160
180136
  ids.add(mappedId);
180161
180137
  }
180162
180138
  }
180163
- if (this.batteryRetryCandidates.size > 0) {
180164
- for (const entity of Object.values(this.registry.fullEntities)) {
180165
- if (!entity.device_id) continue;
180166
- if (!this.batteryRetryCandidates.has(entity.device_id)) continue;
180167
- if (entity.entity_id.startsWith("sensor.") || entity.entity_id.startsWith("binary_sensor.")) {
180168
- ids.add(entity.entity_id);
180169
- }
180170
- }
180139
+ for (const id of this.mappingSync.candidateSensorIds()) {
180140
+ ids.add(id);
180171
180141
  }
180172
180142
  return [...ids];
180173
180143
  }
@@ -180183,11 +180153,7 @@ var ServerModeEndpointManager = class extends Service {
180183
180153
  clearTimeout(this.removalRecheckTimer);
180184
180154
  this.removalRecheckTimer = null;
180185
180155
  }
180186
- if (this.batteryRetryTimer) {
180187
- clearTimeout(this.batteryRetryTimer);
180188
- this.batteryRetryTimer = null;
180189
- }
180190
- this.batteryRetryScheduled = false;
180156
+ this.mappingSync.cancelRetry();
180191
180157
  }
180192
180158
  /** Primary first (the entity the first include matcher tests true for). */
180193
180159
  orderEntityIds(ids) {
@@ -180382,9 +180348,12 @@ var ServerModeEndpointManager = class extends Service {
180382
180348
  });
180383
180349
  continue;
180384
180350
  }
180385
- const fingerprint = this.computeMappingFingerprint(mapping, entityId);
180386
180351
  const existing = this.endpoints.get(entityId);
180387
- if (existing && existing.fingerprint === this.compareFingerprint(mapping, entityId, existing.fingerprint)) {
180352
+ if (existing && existing.fingerprint === this.mappingSync.compareFingerprint(
180353
+ mapping,
180354
+ entityId,
180355
+ existing.fingerprint
180356
+ )) {
180388
180357
  this.log.debug(`Device endpoint already exists for ${entityId}`);
180389
180358
  continue;
180390
180359
  }
@@ -180453,9 +180422,14 @@ var ServerModeEndpointManager = class extends Service {
180453
180422
  continue;
180454
180423
  }
180455
180424
  await this.serverNode.addDevice(endpoint);
180456
- const builtBattery = fingerprintBattery(fingerprint);
180457
- const asBuilt = builtBattery != null && !endpoint.mappedEntityIds.includes(builtBattery) ? JSON.stringify([mapping ?? null, null]) : fingerprint;
180458
- this.endpoints.set(entityId, { endpoint, fingerprint: asBuilt });
180425
+ this.endpoints.set(entityId, {
180426
+ endpoint,
180427
+ fingerprint: this.mappingSync.fingerprintAsBuilt(
180428
+ mapping,
180429
+ entityId,
180430
+ endpoint.mappedEntityIds
180431
+ )
180432
+ });
180459
180433
  for (const [id, owner] of this.parkedEndpointIds) {
180460
180434
  if (id === endpointId || owner === entityId) {
180461
180435
  this.parkedEndpointIds.delete(id);
@@ -180483,7 +180457,11 @@ var ServerModeEndpointManager = class extends Service {
180483
180457
  if (lifecycle === this.lifecycle) {
180484
180458
  this.scheduleRemovalRecheck();
180485
180459
  }
180486
- this.rebuildBatteryRetryCandidates();
180460
+ this.mappingSync.rebuildCandidates(
180461
+ [...this.endpoints].map(
180462
+ ([entityId, entry]) => [entityId, entry.fingerprint]
180463
+ )
180464
+ );
180487
180465
  if (this.observingRequested) {
180488
180466
  this.startObserving();
180489
180467
  }
@@ -180491,7 +180469,12 @@ var ServerModeEndpointManager = class extends Service {
180491
180469
  }
180492
180470
  async updateStates(states) {
180493
180471
  this.registry.mergeExternalStates(states);
180494
- this.maybeRetryBatteryMapping(states);
180472
+ this.mappingSync.maybeRetry(
180473
+ states,
180474
+ null,
180475
+ this.observingRequested,
180476
+ () => this.refreshDevices()
180477
+ );
180495
180478
  for (const [entityId, entry] of this.endpoints) {
180496
180479
  try {
180497
180480
  await entry.endpoint.updateStates(states);