@riddix/hamh 2.1.0-alpha.862 → 2.1.0-alpha.864

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.
@@ -1767,8 +1767,8 @@ var init_Cancelable = __esm({
1767
1767
  };
1768
1768
  return result;
1769
1769
  }
1770
- static set logger(logger254) {
1771
- this.#logger = logger254;
1770
+ static set logger(logger255) {
1771
+ this.#logger = logger255;
1772
1772
  }
1773
1773
  static get logger() {
1774
1774
  return this.#logger;
@@ -3475,13 +3475,13 @@ var init_Logger = __esm({
3475
3475
  *
3476
3476
  * @deprecated use {@link destinations}
3477
3477
  */
3478
- static addLogger(identifier, logger254, options) {
3478
+ static addLogger(identifier, logger255, options) {
3479
3479
  if (identifier in this.destinations) {
3480
3480
  throw new ImplementationError(`Logger "${identifier}" already exists`);
3481
3481
  }
3482
3482
  const dest = LogDestination({ name: identifier });
3483
3483
  const legacy = adaptDestinationToLegacy(dest);
3484
- legacy.log = logger254;
3484
+ legacy.log = logger255;
3485
3485
  if (options?.defaultLogLevel !== void 0) {
3486
3486
  legacy.defaultLogLevel = options.defaultLogLevel;
3487
3487
  }
@@ -5687,8 +5687,8 @@ var init_Construction = __esm({
5687
5687
  }
5688
5688
  }
5689
5689
  #unhandledError(...args) {
5690
- const logger254 = Logger.get(this.#subject.constructor.name);
5691
- logger254.error(...args);
5690
+ const logger255 = Logger.get(this.#subject.constructor.name);
5691
+ logger255.error(...args);
5692
5692
  }
5693
5693
  #createErrorHandler(name) {
5694
5694
  return (e) => {
@@ -64126,8 +64126,8 @@ var init_NodeSession = __esm({
64126
64126
  return session?.type === SessionType.Unicast;
64127
64127
  }
64128
64128
  NodeSession2.is = is;
64129
- function logNew(logger254, operation, session, messenger, fabric, peerNodeId) {
64130
- logger254.info(
64129
+ function logNew(logger255, operation, session, messenger, fabric, peerNodeId) {
64130
+ logger255.info(
64131
64131
  session.via,
64132
64132
  `${operation} session with`,
64133
64133
  Diagnostic.strong(PeerAddress({ fabricIndex: fabric.fabricIndex, nodeId: peerNodeId }).toString()),
@@ -118041,11 +118041,11 @@ var init_Api = __esm({
118041
118041
  }
118042
118042
  Api2.resourceFor = resourceFor;
118043
118043
  function log(level, facility, id, ...message) {
118044
- let logger254 = loggers.get(facility);
118045
- if (!logger254) {
118046
- loggers.set(facility, logger254 = Logger.get(facility));
118044
+ let logger255 = loggers.get(facility);
118045
+ if (!logger255) {
118046
+ loggers.set(facility, logger255 = Logger.get(facility));
118047
118047
  }
118048
- logger254[level](Diagnostic.via(id || "(anon)"), message);
118048
+ logger255[level](Diagnostic.via(id || "(anon)"), message);
118049
118049
  }
118050
118050
  Api2.log = log;
118051
118051
  function logRequest(facility, id, method, target) {
@@ -132771,6 +132771,14 @@ var init_esm7 = __esm({
132771
132771
  }
132772
132772
  });
132773
132773
 
132774
+ // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/protocol.js
132775
+ var init_protocol3 = __esm({
132776
+ "../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/protocol.js"() {
132777
+ init_nodejs();
132778
+ init_esm4();
132779
+ }
132780
+ });
132781
+
132774
132782
  // src/utils/debounce-context.ts
132775
132783
  import debounce from "debounce";
132776
132784
  var DebounceContext;
@@ -132850,7 +132858,7 @@ async function withRetry(fn, options = {}) {
132850
132858
  return await fn();
132851
132859
  } catch (error) {
132852
132860
  lastError = error;
132853
- if (attempt === opts.maxAttempts) {
132861
+ if (attempt === opts.maxAttempts || options.shouldRetry?.(error) === false) {
132854
132862
  break;
132855
132863
  }
132856
132864
  const delayMs = Math.min(
@@ -132914,6 +132922,12 @@ var init_retry = __esm({
132914
132922
  get isOpen() {
132915
132923
  return this.state === "open";
132916
132924
  }
132925
+ // Open AND still inside the reset window. Callers that pre-check
132926
+ // availability must use this, not isOpen, or the half-open probe never
132927
+ // happens and the breaker stays latched forever (#446).
132928
+ get isBlocking() {
132929
+ return this.state === "open" && Date.now() - this.lastFailureTime < this.resetTimeoutMs;
132930
+ }
132917
132931
  reset() {
132918
132932
  this.failures = 0;
132919
132933
  this.state = "closed";
@@ -132950,8 +132964,7 @@ var init_send_ha_message = __esm({
132950
132964
  });
132951
132965
 
132952
132966
  // src/services/home-assistant/home-assistant-actions.ts
132953
- import { callService } from "home-assistant-js-websocket";
132954
- var defaultConfig, HomeAssistantActions;
132967
+ var TARGET_FAILURE_THRESHOLD, defaultConfig, HomeAssistantActions;
132955
132968
  var init_home_assistant_actions = __esm({
132956
132969
  "src/services/home-assistant/home-assistant-actions.ts"() {
132957
132970
  "use strict";
@@ -132960,6 +132973,7 @@ var init_home_assistant_actions = __esm({
132960
132973
  init_retry();
132961
132974
  init_send_ha_message();
132962
132975
  init_diagnostic_event_bus();
132976
+ TARGET_FAILURE_THRESHOLD = 3;
132963
132977
  defaultConfig = {
132964
132978
  retryAttempts: 3,
132965
132979
  retryBaseDelayMs: 100,
@@ -132968,10 +132982,10 @@ var init_home_assistant_actions = __esm({
132968
132982
  circuitBreakerResetMs: 3e4
132969
132983
  };
132970
132984
  HomeAssistantActions = class extends Service {
132971
- constructor(logger254, client, config8) {
132985
+ constructor(logger255, client, config8) {
132972
132986
  super("HomeAssistantActions");
132973
132987
  this.client = client;
132974
- this.log = logger254.get(this);
132988
+ this.log = logger255.get(this);
132975
132989
  this.config = { ...defaultConfig, ...config8 };
132976
132990
  this.circuitBreaker = new CircuitBreaker(
132977
132991
  this.config.circuitBreakerThreshold,
@@ -132979,6 +132993,13 @@ var init_home_assistant_actions = __esm({
132979
132993
  );
132980
132994
  }
132981
132995
  client;
132996
+ // #446: a Matter command must not report success while HA cannot take the
132997
+ // call. Only the transport counts here: the breaker is app-wide, so ten
132998
+ // failures from one broken entity would otherwise make every device on
132999
+ // every bridge fail.
133000
+ get available() {
133001
+ return this.client.haRunning;
133002
+ }
132982
133003
  log;
132983
133004
  debounceContext = new DebounceContext(
132984
133005
  this.processAction.bind(this)
@@ -132987,6 +133008,27 @@ var init_home_assistant_actions = __esm({
132987
133008
  config;
132988
133009
  consecutiveFailures = 0;
132989
133010
  lastSuccessTime = Date.now();
133011
+ // Per entity, not app wide: the shared breaker would let one broken entity
133012
+ // make every device on every bridge fail (#446).
133013
+ targetFailures = /* @__PURE__ */ new Map();
133014
+ // A target that just failed repeatedly is reported as unavailable, so the
133015
+ // controller sees the failure on that device instead of a false success.
133016
+ isTargetBlocked(entityId) {
133017
+ const entry = this.targetFailures.get(entityId);
133018
+ return entry != null && Date.now() < entry.blockedUntil;
133019
+ }
133020
+ recordTargetResult(entityId, failed) {
133021
+ if (!entityId) return;
133022
+ if (!failed) {
133023
+ this.targetFailures.delete(entityId);
133024
+ return;
133025
+ }
133026
+ const count = (this.targetFailures.get(entityId)?.count ?? 0) + 1;
133027
+ this.targetFailures.set(entityId, {
133028
+ count,
133029
+ blockedUntil: count >= TARGET_FAILURE_THRESHOLD ? Date.now() + this.config.circuitBreakerResetMs : 0
133030
+ });
133031
+ }
132990
133032
  processAction(_key, calls) {
132991
133033
  const skipTarget = calls[0].target === false;
132992
133034
  const entity_id = skipTarget ? void 0 : calls[0].target || calls[0].entityId;
@@ -132994,7 +133036,9 @@ var init_home_assistant_actions = __esm({
132994
133036
  const data = Object.assign({}, ...calls.map((c) => c.data));
132995
133037
  const [domain, actionName] = action.split(".");
132996
133038
  const target = entity_id ? { entity_id } : {};
132997
- this.callAction(domain, actionName, data, target, false).catch((error) => {
133039
+ const origin = calls[0].entityId;
133040
+ this.callAction(domain, actionName, data, target, false).then(() => this.recordTargetResult(origin, false)).catch((error) => {
133041
+ this.recordTargetResult(origin, true);
132998
133042
  const errorMsg = this.formatError(error);
132999
133043
  this.log.error(
133000
133044
  `Failed to call action '${action}' for entity '${entity_id ?? "(no target)"}': ${errorMsg}`
@@ -133030,13 +133074,17 @@ var init_home_assistant_actions = __esm({
133030
133074
  const result = await this.circuitBreaker.execute(
133031
133075
  () => withRetry(
133032
133076
  async () => {
133033
- const res = await callService(
133077
+ const res = await sendHaMessage(
133034
133078
  this.client.connection,
133035
- domain,
133036
- action,
133037
- data,
133038
- target,
133039
- returnResponse
133079
+ {
133080
+ type: "call_service",
133081
+ domain,
133082
+ service: action,
133083
+ service_data: data,
133084
+ target,
133085
+ return_response: returnResponse
133086
+ },
133087
+ this.client.messageTimeoutMs
133040
133088
  );
133041
133089
  return res;
133042
133090
  },
@@ -133044,6 +133092,9 @@ var init_home_assistant_actions = __esm({
133044
133092
  maxAttempts: this.config.retryAttempts,
133045
133093
  baseDelayMs: this.config.retryBaseDelayMs,
133046
133094
  maxDelayMs: this.config.retryMaxDelayMs,
133095
+ // A timeout does not mean HA ignored the call, it may have run it.
133096
+ // Repeating a button press or a script would be worse than failing.
133097
+ shouldRetry: (error) => !(error instanceof Error && error.message.includes("timed out")),
133047
133098
  onRetry: (attempt, error, delayMs) => {
133048
133099
  const errorMsg = this.formatError(error);
133049
133100
  this.log.warn(
@@ -133117,6 +133168,14 @@ var init_home_assistant_actions = __esm({
133117
133168
  }
133118
133169
  });
133119
133170
 
133171
+ // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/types.js
133172
+ var init_types2 = __esm({
133173
+ "../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/types.js"() {
133174
+ init_nodejs();
133175
+ init_esm3();
133176
+ }
133177
+ });
133178
+
133120
133179
  // src/utils/async-observable.ts
133121
133180
  var AsyncObservable2;
133122
133181
  var init_async_observable = __esm({
@@ -133127,6 +133186,17 @@ var init_async_observable = __esm({
133127
133186
  }
133128
133187
  });
133129
133188
 
133189
+ // src/utils/transaction-is-offline.ts
133190
+ function transactionIsOffline(context) {
133191
+ return !context || hasLocalActor(context);
133192
+ }
133193
+ var init_transaction_is_offline = __esm({
133194
+ "src/utils/transaction-is-offline.ts"() {
133195
+ "use strict";
133196
+ init_protocol3();
133197
+ }
133198
+ });
133199
+
133130
133200
  // src/matter/behaviors/home-assistant-entity-behavior.ts
133131
133201
  var home_assistant_entity_behavior_exports = {};
133132
133202
  __export(home_assistant_entity_behavior_exports, {
@@ -133138,8 +133208,10 @@ var init_home_assistant_entity_behavior = __esm({
133138
133208
  "use strict";
133139
133209
  init_dist();
133140
133210
  init_esm7();
133211
+ init_types2();
133141
133212
  init_home_assistant_actions();
133142
133213
  init_async_observable();
133214
+ init_transaction_is_offline();
133143
133215
  HomeAssistantEntityBehavior = class extends Behavior {
133144
133216
  static id = ClusterId2.homeAssistantEntity;
133145
133217
  get entityId() {
@@ -133154,7 +133226,24 @@ var init_home_assistant_entity_behavior = __esm({
133154
133226
  get isAvailable() {
133155
133227
  return this.entity.state.state !== "unavailable" && this.entity.state.state !== "unknown";
133156
133228
  }
133229
+ // #446: fail the command instead of telling the controller it worked while
133230
+ // the call never reaches HA. `=== false` on purpose: test stubs do not
133231
+ // define `available`, and undefined must read as "no opinion".
133232
+ // ponytail: commands only. Attribute writes that fan and thermostat handle
133233
+ // in reactors run as a local actor, so they still go through and rely on HA
133234
+ // state to correct them. Plumb it there too if that shows up in reports.
133235
+ assertAvailable() {
133236
+ const actions = this.env.get(HomeAssistantActions);
133237
+ const blocked = actions.available === false || actions.isTargetBlocked?.(this.entityId) === true;
133238
+ if (blocked && !transactionIsOffline(this.context)) {
133239
+ throw new StatusResponseError(
133240
+ "Home Assistant is not reachable",
133241
+ StatusCode.Failure
133242
+ );
133243
+ }
133244
+ }
133157
133245
  callAction(action) {
133246
+ this.assertAvailable();
133158
133247
  const actions = this.env.get(HomeAssistantActions);
133159
133248
  actions.call(action, this.entityId);
133160
133249
  }
@@ -133317,10 +133406,10 @@ var DiagnosticService = class {
133317
133406
  };
133318
133407
 
133319
133408
  // src/api/access-log.ts
133320
- function accessLogger(logger254) {
133409
+ function accessLogger(logger255) {
133321
133410
  return (req, res, next) => {
133322
133411
  res.on("finish", () => {
133323
- logger254.debug(
133412
+ logger255.debug(
133324
133413
  `${req.method} ${decodeURI(req.originalUrl)} ${res.statusCode} ${res.statusMessage} from ${req.socket.remoteAddress}`
133325
133414
  );
133326
133415
  });
@@ -138058,7 +138147,7 @@ var WebSocketApi = class {
138058
138147
 
138059
138148
  // src/api/web-api.ts
138060
138149
  var WebApi = class extends Service {
138061
- constructor(logger254, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, identityStorage, lockCredentialStorage, settingsStorage, backupService, props) {
138150
+ constructor(logger255, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, identityStorage, lockCredentialStorage, settingsStorage, backupService, props) {
138062
138151
  super("WebApi");
138063
138152
  this.bridgeService = bridgeService;
138064
138153
  this.haClient = haClient;
@@ -138070,8 +138159,8 @@ var WebApi = class extends Service {
138070
138159
  this.settingsStorage = settingsStorage;
138071
138160
  this.backupService = backupService;
138072
138161
  this.props = props;
138073
- this.logger = logger254;
138074
- this.log = logger254.get(this);
138162
+ this.logger = logger255;
138163
+ this.log = logger255.get(this);
138075
138164
  this.accessLogger = accessLogger(this.log.createChild("Access Log"));
138076
138165
  this.startTime = Date.now();
138077
138166
  this.wsApi = new WebSocketApi(
@@ -138492,12 +138581,9 @@ var BetterLogger = class _BetterLogger extends Logger {
138492
138581
  // src/core/app/mdns.ts
138493
138582
  init_esm();
138494
138583
  init_esm7();
138584
+ init_protocol3();
138495
138585
  import * as os5 from "node:os";
138496
138586
 
138497
- // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/protocol.js
138498
- init_nodejs();
138499
- init_esm4();
138500
-
138501
138587
  // src/core/app/filtered-network.ts
138502
138588
  init_esm6();
138503
138589
  function filterAdvertisedIpv6(ipV6) {
@@ -139273,10 +139359,10 @@ function isTransientConnectError(reason) {
139273
139359
  return msg.includes("socket hang up") || msg.includes("tls") || msg.includes("TLS");
139274
139360
  }
139275
139361
  var HomeAssistantClient = class extends Service {
139276
- constructor(logger254, options) {
139362
+ constructor(logger255, options) {
139277
139363
  super("HomeAssistantClient");
139278
139364
  this.options = options;
139279
- this.log = logger254.get(this);
139365
+ this.log = logger255.get(this);
139280
139366
  }
139281
139367
  options;
139282
139368
  static Options = /* @__PURE__ */ Symbol.for("HomeAssistantClientProps");
@@ -139305,6 +139391,9 @@ var HomeAssistantClient = class extends Service {
139305
139391
  get accessToken() {
139306
139392
  return this.options.accessToken;
139307
139393
  }
139394
+ get messageTimeoutMs() {
139395
+ return this.options.messageTimeoutMs;
139396
+ }
139308
139397
  async initialize() {
139309
139398
  this._connection = await this.createConnection(this.options);
139310
139399
  this.watchRunningState(this._connection);
@@ -139546,6 +139635,9 @@ var HomeAssistantRegistry = class extends Service {
139546
139635
  get snapshotGeneration() {
139547
139636
  return this._snapshotGeneration;
139548
139637
  }
139638
+ // Last HA uptime stamp the auto-refresh saw, so a restart between ticks
139639
+ // still drives one reconcile (#438).
139640
+ lastRunningSince = 0;
139549
139641
  _devices = {};
139550
139642
  get devices() {
139551
139643
  return this._devices;
@@ -139589,8 +139681,11 @@ var HomeAssistantRegistry = class extends Service {
139589
139681
  }
139590
139682
  refreshing = true;
139591
139683
  try {
139684
+ const runningSince = this.client.runningSince;
139685
+ const restarted = runningSince !== this.lastRunningSince;
139592
139686
  const changed = await this.reload();
139593
- if (changed) {
139687
+ this.lastRunningSince = runningSince;
139688
+ if (changed || restarted) {
139594
139689
  await onRefresh();
139595
139690
  }
139596
139691
  } catch (e) {
@@ -155126,9 +155221,8 @@ var WindowCoveringDevice = WindowCoveringDeviceDefinition;
155126
155221
  init_nodejs();
155127
155222
  init_esm5();
155128
155223
 
155129
- // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/types.js
155130
- init_nodejs();
155131
- init_esm3();
155224
+ // src/matter/endpoints/server-mode-server-node.ts
155225
+ init_types2();
155132
155226
 
155133
155227
  // src/utils/sanitize-matter-string.ts
155134
155228
  function sanitizeMatterString(value) {
@@ -155312,6 +155406,9 @@ import * as path12 from "node:path";
155312
155406
  // src/plugins/plugin-device-factory.ts
155313
155407
  init_esm();
155314
155408
 
155409
+ // src/matter/behaviors/identify-server.ts
155410
+ init_esm();
155411
+
155315
155412
  // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/behaviors.js
155316
155413
  init_nodejs();
155317
155414
 
@@ -156507,14 +156604,138 @@ init_wi_fi_network_diagnostics2();
156507
156604
  init_ClientBehavior();
156508
156605
  var WiFiNetworkManagementClientConstructor = ClientBehavior(WiFiNetworkManagement3);
156509
156606
 
156607
+ // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/clusters.js
156608
+ init_nodejs();
156609
+
156610
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156611
+ init_access_control();
156612
+ init_actions();
156613
+ init_administrator_commissioning();
156614
+
156615
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/alarm-base.js
156616
+ init_ClusterType();
156617
+ init_esm2();
156618
+ var AlarmBase3 = ClusterType(AlarmBase2);
156619
+
156620
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156621
+ init_basic_information();
156622
+ init_binding();
156623
+ init_bridged_device_basic_information();
156624
+ init_commissioner_control();
156625
+
156626
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/concentration-measurement.js
156627
+ init_ClusterType();
156628
+ init_esm2();
156629
+ var ConcentrationMeasurement3 = ClusterType(ConcentrationMeasurement2);
156630
+
156631
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156632
+ init_descriptor();
156633
+ init_diagnostic_logs();
156634
+ init_ethernet_network_diagnostics();
156635
+ init_general_commissioning();
156636
+ init_general_diagnostics();
156637
+ init_group_key_management();
156638
+ init_groupcast();
156639
+ init_icd_management();
156640
+ init_identify();
156641
+
156642
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/label.js
156643
+ init_ClusterType();
156644
+ init_esm2();
156645
+ var Label3 = ClusterType(Label2);
156646
+
156647
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156648
+ init_localization_configuration();
156649
+ init_network_commissioning();
156650
+ init_operational_credentials();
156651
+ init_ota_software_update_provider();
156652
+ init_ota_software_update_requestor();
156653
+ init_power_source();
156654
+ init_power_source_configuration();
156655
+
156656
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/resource-monitoring.js
156657
+ init_ClusterType();
156658
+ init_esm2();
156659
+ var ResourceMonitoring3 = ClusterType(ResourceMonitoring2);
156660
+
156661
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156662
+ init_software_diagnostics();
156663
+ init_thread_network_diagnostics();
156664
+ init_time_format_localization();
156665
+ init_time_synchronization();
156666
+ init_tls_certificate_management();
156667
+ init_tls_client_management();
156668
+ init_unit_localization();
156669
+
156670
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/web-rtc-transport-definitions.js
156671
+ init_ClusterType();
156672
+ init_esm2();
156673
+ var WebRtcTransportDefinitions3 = ClusterType(WebRtcTransportDefinitions2);
156674
+
156675
+ // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
156676
+ init_wi_fi_network_diagnostics();
156677
+
156510
156678
  // src/matter/behaviors/identify-server.ts
156679
+ init_home_assistant_entity_behavior();
156680
+ var logger198 = Logger.get("IdentifyServer");
156681
+ var IDENTIFY_BUTTON_SUFFIXES = ["_identify", "_locate", "_find_me"];
156511
156682
  var IdentifyServer2 = class extends IdentifyServer {
156683
+ identify(request) {
156684
+ if (request.identifyTime > 0) {
156685
+ this.identifyInHomeAssistant("identify");
156686
+ }
156687
+ return super.identify(request);
156688
+ }
156689
+ triggerEffect(effect) {
156690
+ if (effect.effectIdentifier !== Identify3.EffectIdentifier.StopEffect && effect.effectIdentifier !== Identify3.EffectIdentifier.FinishEffect) {
156691
+ this.identifyInHomeAssistant("triggerEffect");
156692
+ }
156693
+ return super.triggerEffect(effect);
156694
+ }
156695
+ identifyInHomeAssistant(source) {
156696
+ if (!this.agent.has(HomeAssistantEntityBehavior)) return;
156697
+ const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
156698
+ const target = this.findIdentifyEntity(homeAssistant);
156699
+ if (!target) {
156700
+ logger198.debug(
156701
+ `${source} for ${homeAssistant.entityId}, no identify entity on this device`
156702
+ );
156703
+ return;
156704
+ }
156705
+ logger198.info(
156706
+ `${source} \u2192 button.press ${target} for ${homeAssistant.entityId}`
156707
+ );
156708
+ homeAssistant.callAction({ action: "button.press", target });
156709
+ }
156710
+ // Searches the FULL registry: an identify button rarely matches the bridge
156711
+ // filter, same reason the battery and problem lookups do it.
156712
+ findIdentifyEntity(homeAssistant) {
156713
+ const deviceId = homeAssistant.entity.registry?.device_id;
156714
+ if (!deviceId) return void 0;
156715
+ const registry3 = this.env.maybeGet(HomeAssistantRegistry);
156716
+ if (!registry3) return void 0;
156717
+ let byName;
156718
+ for (const entity of Object.values(registry3.entities)) {
156719
+ if (entity.device_id !== deviceId) continue;
156720
+ if (entity.disabled_by != null) continue;
156721
+ if (!entity.entity_id.startsWith("button.")) continue;
156722
+ const deviceClass = registry3.states[entity.entity_id]?.attributes?.device_class;
156723
+ if (deviceClass === "identify") return entity.entity_id;
156724
+ const uniqueId = entity.unique_id ?? "";
156725
+ if (byName == null && IDENTIFY_BUTTON_SUFFIXES.some(
156726
+ (s) => entity.entity_id.endsWith(s) || uniqueId.endsWith(s)
156727
+ )) {
156728
+ byName = entity.entity_id;
156729
+ }
156730
+ }
156731
+ return byName;
156732
+ }
156512
156733
  };
156513
156734
 
156514
156735
  // src/matter/endpoints/validate-endpoint-type.ts
156515
156736
  init_esm();
156516
156737
  init_esm7();
156517
- var logger198 = Logger.get("EndpointValidation");
156738
+ var logger199 = Logger.get("EndpointValidation");
156518
156739
  function toCamelCase(name) {
156519
156740
  return name.charAt(0).toLowerCase() + name.slice(1);
156520
156741
  }
@@ -156544,12 +156765,12 @@ function validateEndpointType(endpointType, entityId) {
156544
156765
  }
156545
156766
  const prefix = entityId ? `[${entityId}] ` : "";
156546
156767
  if (missingMandatory.length > 0) {
156547
- logger198.warn(
156768
+ logger199.warn(
156548
156769
  `${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): missing mandatory clusters: ${missingMandatory.join(", ")}`
156549
156770
  );
156550
156771
  }
156551
156772
  if (availableOptional.length > 0) {
156552
- logger198.debug(
156773
+ logger199.debug(
156553
156774
  `${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): optional clusters not used: ${availableOptional.join(", ")}`
156554
156775
  );
156555
156776
  }
@@ -156673,7 +156894,7 @@ var BridgeDataProvider = class extends Service {
156673
156894
 
156674
156895
  // src/utils/apply-patch-state.ts
156675
156896
  init_esm();
156676
- var logger199 = Logger.get("ApplyPatchState");
156897
+ var logger200 = Logger.get("ApplyPatchState");
156677
156898
  function applyPatchState(state, patch, options) {
156678
156899
  return applyPatch(state, patch, options?.force);
156679
156900
  }
@@ -156700,23 +156921,23 @@ function applyPatch(state, patch, force = false) {
156700
156921
  if (errorMessage.includes(
156701
156922
  "Endpoint storage inaccessible because endpoint is not a node and is not owned by another endpoint"
156702
156923
  )) {
156703
- logger199.debug(
156924
+ logger200.debug(
156704
156925
  `Suppressed endpoint storage error, patch not applied: ${JSON.stringify(actualPatch)}`
156705
156926
  );
156706
156927
  return actualPatch;
156707
156928
  }
156708
156929
  if (errorMessage.includes("synchronous-transaction-conflict")) {
156709
- logger199.warn(
156930
+ logger200.warn(
156710
156931
  `Transaction conflict, state update DROPPED: ${JSON.stringify(actualPatch)}`
156711
156932
  );
156712
156933
  return actualPatch;
156713
156934
  }
156714
156935
  failedKeys.push(key);
156715
- logger199.warn(`Failed to set property '${key}': ${errorMessage}`);
156936
+ logger200.warn(`Failed to set property '${key}': ${errorMessage}`);
156716
156937
  }
156717
156938
  }
156718
156939
  if (failedKeys.length > 0) {
156719
- logger199.warn(
156940
+ logger200.warn(
156720
156941
  `${failedKeys.length} properties failed to update: [${failedKeys.join(", ")}]`
156721
156942
  );
156722
156943
  }
@@ -156786,7 +157007,7 @@ function truncate(maxLength, value) {
156786
157007
  }
156787
157008
 
156788
157009
  // src/plugins/plugin-device-factory.ts
156789
- var logger200 = Logger.get("PluginDeviceFactory");
157010
+ var logger201 = Logger.get("PluginDeviceFactory");
156790
157011
  var deviceTypeMap = {
156791
157012
  on_off_light: () => OnOffLightDevice.with(
156792
157013
  IdentifyServer2,
@@ -156892,7 +157113,7 @@ var deviceTypeMap = {
156892
157113
  function createPluginEndpointType(deviceType) {
156893
157114
  const factory = deviceTypeMap[deviceType];
156894
157115
  if (!factory) {
156895
- logger200.warn(`Unsupported plugin device type: "${deviceType}"`);
157116
+ logger201.warn(`Unsupported plugin device type: "${deviceType}"`);
156896
157117
  return void 0;
156897
157118
  }
156898
157119
  const endpoint = factory();
@@ -156905,7 +157126,7 @@ function getSupportedPluginDeviceTypes() {
156905
157126
 
156906
157127
  // src/plugins/safe-plugin-runner.ts
156907
157128
  init_esm();
156908
- var logger201 = Logger.get("SafePluginRunner");
157129
+ var logger202 = Logger.get("SafePluginRunner");
156909
157130
  var DEFAULT_TIMEOUT_MS = 1e4;
156910
157131
  var CIRCUIT_BREAKER_THRESHOLD = 3;
156911
157132
  var SafePluginRunner = class {
@@ -156938,7 +157159,7 @@ var SafePluginRunner = class {
156938
157159
  async run(pluginName, operation, fn, timeoutMs = DEFAULT_TIMEOUT_MS) {
156939
157160
  const state = this.getState(pluginName);
156940
157161
  if (state.disabled) {
156941
- logger201.debug(
157162
+ logger202.debug(
156942
157163
  `Plugin "${pluginName}" is disabled (circuit breaker open), skipping ${operation}`
156943
157164
  );
156944
157165
  return void 0;
@@ -156956,13 +157177,13 @@ var SafePluginRunner = class {
156956
157177
  timeout.clear();
156957
157178
  state.failures++;
156958
157179
  state.lastError = error instanceof Error ? error.message : String(error);
156959
- logger201.error(
157180
+ logger202.error(
156960
157181
  `Plugin "${pluginName}" failed during ${operation} (failure ${state.failures}/${CIRCUIT_BREAKER_THRESHOLD}): ${state.lastError}`
156961
157182
  );
156962
157183
  if (state.failures >= CIRCUIT_BREAKER_THRESHOLD) {
156963
157184
  state.disabled = true;
156964
157185
  state.disabledAt = Date.now();
156965
- logger201.error(
157186
+ logger202.error(
156966
157187
  `Plugin "${pluginName}" DISABLED after ${CIRCUIT_BREAKER_THRESHOLD} consecutive failures. Last error: ${state.lastError}`
156967
157188
  );
156968
157189
  }
@@ -156985,7 +157206,7 @@ var SafePluginRunner = class {
156985
157206
  return result;
156986
157207
  } catch (error) {
156987
157208
  timeout.clear();
156988
- logger201.error(
157209
+ logger202.error(
156989
157210
  `Plugin "${pluginName}" failed during ${operation}: ${error instanceof Error ? error.message : String(error)}`
156990
157211
  );
156991
157212
  return void 0;
@@ -157006,13 +157227,13 @@ var SafePluginRunner = class {
157006
157227
  } catch (error) {
157007
157228
  state.failures++;
157008
157229
  state.lastError = error instanceof Error ? error.message : String(error);
157009
- logger201.error(
157230
+ logger202.error(
157010
157231
  `Plugin "${pluginName}" failed during ${operation} (sync, failure ${state.failures}/${CIRCUIT_BREAKER_THRESHOLD}): ${state.lastError}`
157011
157232
  );
157012
157233
  if (state.failures >= CIRCUIT_BREAKER_THRESHOLD) {
157013
157234
  state.disabled = true;
157014
157235
  state.disabledAt = Date.now();
157015
- logger201.error(
157236
+ logger202.error(
157016
157237
  `Plugin "${pluginName}" DISABLED after ${CIRCUIT_BREAKER_THRESHOLD} consecutive failures.`
157017
157238
  );
157018
157239
  }
@@ -157038,7 +157259,7 @@ var SafePluginRunner = class {
157038
157259
  };
157039
157260
 
157040
157261
  // src/plugins/plugin-manager.ts
157041
- var logger202 = Logger.get("PluginManager");
157262
+ var logger203 = Logger.get("PluginManager");
157042
157263
  var PLUGIN_API_VERSION = 1;
157043
157264
  var MAX_PLUGIN_DEVICE_ID_LENGTH = 100;
157044
157265
  var LEGACY_ENABLED_KEY = "__enabled";
@@ -157133,7 +157354,7 @@ var PluginManager = class {
157133
157354
  throw new Error(`Plugin at ${packagePath} package.json missing "main"`);
157134
157355
  }
157135
157356
  if (manifest.hamhPluginApiVersion != null && manifest.hamhPluginApiVersion !== PLUGIN_API_VERSION) {
157136
- logger202.warn(
157357
+ logger203.warn(
157137
157358
  `Plugin "${manifest.name}" declares API version ${manifest.hamhPluginApiVersion}, current is ${PLUGIN_API_VERSION}. It may not work correctly.`
157138
157359
  );
157139
157360
  }
@@ -157164,7 +157385,7 @@ var PluginManager = class {
157164
157385
  };
157165
157386
  await this.register(plugin, metadata);
157166
157387
  } catch (e) {
157167
- logger202.error(`Failed to load external plugin from ${packagePath}:`, e);
157388
+ logger203.error(`Failed to load external plugin from ${packagePath}:`, e);
157168
157389
  throw e;
157169
157390
  }
157170
157391
  }
@@ -157189,7 +157410,7 @@ var PluginManager = class {
157189
157410
  }
157190
157411
  if (enabled === false) {
157191
157412
  metadata.enabled = false;
157192
- logger202.info(`Plugin "${plugin.name}" stays disabled (persisted)`);
157413
+ logger203.info(`Plugin "${plugin.name}" stays disabled (persisted)`);
157193
157414
  }
157194
157415
  const devices = /* @__PURE__ */ new Map();
157195
157416
  const pluginLogger = Logger.get(`Plugin:${plugin.name}`);
@@ -157277,7 +157498,7 @@ var PluginManager = class {
157277
157498
  }),
157278
157499
  suspending: false
157279
157500
  });
157280
- logger202.info(
157501
+ logger203.info(
157281
157502
  `Registered plugin: ${plugin.name} v${plugin.version} (${metadata.source})`
157282
157503
  );
157283
157504
  }
@@ -157302,13 +157523,13 @@ var PluginManager = class {
157302
157523
  async startPlugin(name, instance) {
157303
157524
  if (!instance.metadata.enabled) return;
157304
157525
  if (this.runner.isDisabled(name)) {
157305
- logger202.warn(
157526
+ logger203.warn(
157306
157527
  `Plugin "${name}" is disabled (circuit breaker), skipping start`
157307
157528
  );
157308
157529
  instance.metadata.enabled = false;
157309
157530
  return;
157310
157531
  }
157311
- logger202.info(`Starting plugin: ${name}`);
157532
+ logger203.info(`Starting plugin: ${name}`);
157312
157533
  const epoch = ++instance.epoch;
157313
157534
  await this.runner.run(
157314
157535
  name,
@@ -157367,7 +157588,7 @@ var PluginManager = class {
157367
157588
  storage2.flush();
157368
157589
  }
157369
157590
  instance.started = false;
157370
- logger202.info(`Plugin "${name}" shut down`);
157591
+ logger203.info(`Plugin "${name}" shut down`);
157371
157592
  });
157372
157593
  }
157373
157594
  this.instances.clear();
@@ -157463,13 +157684,13 @@ var PluginManager = class {
157463
157684
  instance.metadata.config = pending;
157464
157685
  instance.pendingConfig = void 0;
157465
157686
  } catch (e) {
157466
- logger202.warn(
157687
+ logger203.warn(
157467
157688
  `Failed to persist the parked config for "${pluginName}", it stays parked:`,
157468
157689
  e
157469
157690
  );
157470
157691
  }
157471
157692
  }
157472
- logger202.info(`Starting plugin: ${pluginName}`);
157693
+ logger203.info(`Starting plugin: ${pluginName}`);
157473
157694
  const epoch = ++instance.epoch;
157474
157695
  await this.runner.run(
157475
157696
  pluginName,
@@ -157502,7 +157723,7 @@ var PluginManager = class {
157502
157723
  return JSON.parse(fs10.readFileSync(this.stateFile, "utf-8"));
157503
157724
  }
157504
157725
  } catch (e) {
157505
- logger202.warn(`Failed to read the plugin state file:`, e);
157726
+ logger203.warn(`Failed to read the plugin state file:`, e);
157506
157727
  }
157507
157728
  return {};
157508
157729
  }
@@ -157513,7 +157734,7 @@ var PluginManager = class {
157513
157734
  fs10.mkdirSync(path12.dirname(this.stateFile), { recursive: true });
157514
157735
  fs10.writeFileSync(this.stateFile, JSON.stringify(state, null, 2));
157515
157736
  } catch (e) {
157516
- logger202.warn(
157737
+ logger203.warn(
157517
157738
  `Failed to persist enabled=${enabled} for "${pluginName}":`,
157518
157739
  e
157519
157740
  );
@@ -157547,7 +157768,7 @@ var PluginManager = class {
157547
157768
  if (instance.plugin.onConfigChanged) {
157548
157769
  if (!instance.metadata.enabled) {
157549
157770
  instance.pendingConfig = config8;
157550
- logger202.info(
157771
+ logger203.info(
157551
157772
  `Plugin "${pluginName}" is disabled, the config applies on enable`
157552
157773
  );
157553
157774
  } else {
@@ -157567,6 +157788,7 @@ var PluginManager = class {
157567
157788
  init_dist();
157568
157789
  init_esm7();
157569
157790
  import * as os9 from "node:os";
157791
+ init_protocol3();
157570
157792
 
157571
157793
  // src/utils/json/create-bridge-server-config.ts
157572
157794
  import crypto5 from "node:crypto";
@@ -157823,6 +158045,7 @@ var SecondaryNetworkInterfaceEndpointDefinition = MutableEndpoint({
157823
158045
  Object.freeze(SecondaryNetworkInterfaceEndpointDefinition);
157824
158046
 
157825
158047
  // src/utils/json/create-bridge-server-config.ts
158048
+ init_types2();
157826
158049
  function createBridgeServerConfig(data, options) {
157827
158050
  return {
157828
158051
  type: ServerNode.RootEndpoint,
@@ -157919,6 +158142,7 @@ async function runMdnsAddressWatchTick(deps) {
157919
158142
  }
157920
158143
 
157921
158144
  // src/utils/ensure-commissioning-config.ts
158145
+ init_protocol3();
157922
158146
  var ServerNodeConfigProvider = class extends CommissioningConfigProvider {
157923
158147
  #node;
157924
158148
  constructor(node) {
@@ -157966,6 +158190,10 @@ function deadSessionTimeoutMs(flags2) {
157966
158190
  return flags2?.fastSessionRecovery ? FAST_DEAD_SESSION_TIMEOUT_MS : DEAD_SESSION_TIMEOUT_MS;
157967
158191
  }
157968
158192
  var STALE_SESSION_QUIET_WINDOW_MS = 5 * 60 * 1e3;
158193
+ var PRIMING_GRACE_MS = 3e4;
158194
+ function replacedSessionTimeoutMs(flags2) {
158195
+ return Math.max(deadSessionTimeoutMs(flags2), PRIMING_GRACE_MS);
158196
+ }
157969
158197
  function staleSessionQuietWindowMs(flags2) {
157970
158198
  return flags2?.fastSessionRecovery ? 0 : STALE_SESSION_QUIET_WINDOW_MS;
157971
158199
  }
@@ -158112,11 +158340,11 @@ var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
158112
158340
  var SHUTDOWN_SESSION_CLOSE_TIMEOUT_MS = 2500;
158113
158341
  var MDNS_ADDRESS_CHECK_INTERVAL_MS = 6e4;
158114
158342
  var Bridge = class {
158115
- constructor(env, logger254, dataProvider, endpointManager, serverOptions) {
158343
+ constructor(env, logger255, dataProvider, endpointManager, serverOptions) {
158116
158344
  this.dataProvider = dataProvider;
158117
158345
  this.endpointManager = endpointManager;
158118
158346
  this.serverOptions = serverOptions;
158119
- this.log = logger254.get(`Bridge / ${dataProvider.id}`);
158347
+ this.log = logger255.get(`Bridge / ${dataProvider.id}`);
158120
158348
  this.server = new BridgeServerNode(
158121
158349
  env,
158122
158350
  this.dataProvider,
@@ -158574,12 +158802,18 @@ ${e?.toString()}`);
158574
158802
  for (const s of [...sessionManager.sessions]) {
158575
158803
  if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
158576
158804
  this.log.info(
158577
- `Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs), replaced by session ${newSession.id}`
158805
+ `Session ${s.id} (peer ${s.peerNodeId}, 0 subs) replaced by session ${newSession.id}, closing it once it goes quiet`
158806
+ );
158807
+ const staleId = s.id;
158808
+ const armed = this.staleSessionTimers.get(staleId);
158809
+ if (armed) clearTimeout(armed);
158810
+ this.staleSessionTimers.set(
158811
+ staleId,
158812
+ setTimeout(() => {
158813
+ this.staleSessionTimers.delete(staleId);
158814
+ this.closeStaleSession(staleId, PRIMING_GRACE_MS);
158815
+ }, replacedSessionTimeoutMs(this.dataProvider.featureFlags))
158578
158816
  );
158579
- s.initiateForceClose({
158580
- cause: new Error("stale session replaced by new session")
158581
- }).catch(() => {
158582
- });
158583
158817
  }
158584
158818
  }
158585
158819
  const quietWindowMs = staleSessionQuietWindowMs(
@@ -158615,6 +158849,11 @@ ${e?.toString()}`);
158615
158849
  };
158616
158850
  this.sessionDeletedHandler = (session) => {
158617
158851
  this.sessionStartedAt.delete(session.id);
158852
+ const armed = this.staleSessionTimers.get(session.id);
158853
+ if (armed) {
158854
+ clearTimeout(armed);
158855
+ this.staleSessionTimers.delete(session.id);
158856
+ }
158618
158857
  const sessions = [...sessionManager.sessions];
158619
158858
  this.log.warn(
158620
158859
  `Session closed: id=${session.id} peer=${session.peerNodeId} | remaining sessions=${sessions.length}`
@@ -158713,7 +158952,7 @@ ${e?.toString()}`);
158713
158952
  );
158714
158953
  });
158715
158954
  }
158716
- closeStaleSession(sessionId) {
158955
+ closeStaleSession(sessionId, minQuietMs = 0) {
158717
158956
  try {
158718
158957
  const sessionManager = this.server.env.get(SessionManager);
158719
158958
  for (const s of [...sessionManager.sessions]) {
@@ -158723,7 +158962,10 @@ ${e?.toString()}`);
158723
158962
  const idleSec = Math.round((Date.now() - s.timestamp) / 1e3);
158724
158963
  if (!staleSessionShouldClose(
158725
158964
  s,
158726
- staleSessionQuietWindowMs(this.dataProvider.featureFlags)
158965
+ Math.max(
158966
+ staleSessionQuietWindowMs(this.dataProvider.featureFlags),
158967
+ minQuietMs
158968
+ )
158727
158969
  )) {
158728
158970
  this.log.info(
158729
158971
  `Keeping session ${s.id} (peer ${s.peerNodeId}, 0 subs, last traffic ${idleSec}s ago)`
@@ -158732,7 +158974,7 @@ ${e?.toString()}`);
158732
158974
  sessionId,
158733
158975
  setTimeout(() => {
158734
158976
  this.staleSessionTimers.delete(sessionId);
158735
- this.closeStaleSession(sessionId);
158977
+ this.closeStaleSession(sessionId, minQuietMs);
158736
158978
  }, deadSessionTimeoutMs(this.dataProvider.featureFlags))
158737
158979
  );
158738
158980
  break;
@@ -158761,6 +159003,9 @@ ${e?.toString()}`);
158761
159003
  if (s.isClosing || s.subscriptions.size > 0) {
158762
159004
  continue;
158763
159005
  }
159006
+ if (this.staleSessionTimers.has(s.id)) {
159007
+ continue;
159008
+ }
158764
159009
  const idleSec = Math.round((Date.now() - s.timestamp) / 1e3);
158765
159010
  if (!staleSessionShouldClose(
158766
159011
  s,
@@ -159403,77 +159648,6 @@ var EntityStateProvider = class extends Service {
159403
159648
  }
159404
159649
  };
159405
159650
 
159406
- // ../../node_modules/.pnpm/@matter+main@0.17.9/node_modules/@matter/main/dist/esm/clusters.js
159407
- init_nodejs();
159408
-
159409
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159410
- init_access_control();
159411
- init_actions();
159412
- init_administrator_commissioning();
159413
-
159414
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/alarm-base.js
159415
- init_ClusterType();
159416
- init_esm2();
159417
- var AlarmBase3 = ClusterType(AlarmBase2);
159418
-
159419
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159420
- init_basic_information();
159421
- init_binding();
159422
- init_bridged_device_basic_information();
159423
- init_commissioner_control();
159424
-
159425
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/concentration-measurement.js
159426
- init_ClusterType();
159427
- init_esm2();
159428
- var ConcentrationMeasurement3 = ClusterType(ConcentrationMeasurement2);
159429
-
159430
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159431
- init_descriptor();
159432
- init_diagnostic_logs();
159433
- init_ethernet_network_diagnostics();
159434
- init_general_commissioning();
159435
- init_general_diagnostics();
159436
- init_group_key_management();
159437
- init_groupcast();
159438
- init_icd_management();
159439
- init_identify();
159440
-
159441
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/label.js
159442
- init_ClusterType();
159443
- init_esm2();
159444
- var Label3 = ClusterType(Label2);
159445
-
159446
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159447
- init_localization_configuration();
159448
- init_network_commissioning();
159449
- init_operational_credentials();
159450
- init_ota_software_update_provider();
159451
- init_ota_software_update_requestor();
159452
- init_power_source();
159453
- init_power_source_configuration();
159454
-
159455
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/resource-monitoring.js
159456
- init_ClusterType();
159457
- init_esm2();
159458
- var ResourceMonitoring3 = ClusterType(ResourceMonitoring2);
159459
-
159460
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159461
- init_software_diagnostics();
159462
- init_thread_network_diagnostics();
159463
- init_time_format_localization();
159464
- init_time_synchronization();
159465
- init_tls_certificate_management();
159466
- init_tls_client_management();
159467
- init_unit_localization();
159468
-
159469
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/web-rtc-transport-definitions.js
159470
- init_ClusterType();
159471
- init_esm2();
159472
- var WebRtcTransportDefinitions3 = ClusterType(WebRtcTransportDefinitions2);
159473
-
159474
- // ../../node_modules/.pnpm/@matter+types@0.17.9/node_modules/@matter/types/dist/esm/clusters/index.js
159475
- init_wi_fi_network_diagnostics();
159476
-
159477
159651
  // src/utils/converters/fan-mode.ts
159478
159652
  var FanMode = class _FanMode {
159479
159653
  constructor(mode, sequence) {
@@ -159662,7 +159836,7 @@ init_esm();
159662
159836
  init_esm7();
159663
159837
  import crypto6 from "node:crypto";
159664
159838
  init_home_assistant_entity_behavior();
159665
- var logger203 = Logger.get("BasicInformationServer");
159839
+ var logger204 = Logger.get("BasicInformationServer");
159666
159840
  var appliedUniqueIds = /* @__PURE__ */ new Map();
159667
159841
  var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer {
159668
159842
  async initialize() {
@@ -159708,7 +159882,7 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
159708
159882
  // records keyed on it can be shed (#385).
159709
159883
  uniqueId: this.frozenUniqueId(anchor)
159710
159884
  });
159711
- logger203.debug(
159885
+ logger204.debug(
159712
159886
  `[${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}`
159713
159887
  );
159714
159888
  }
@@ -159738,7 +159912,7 @@ function isValidVendorId(value) {
159738
159912
  // src/matter/behaviors/electrical-energy-measurement-server.ts
159739
159913
  init_esm();
159740
159914
  init_home_assistant_entity_behavior();
159741
- var logger204 = Logger.get("ElectricalEnergyMeasurementServer");
159915
+ var logger205 = Logger.get("ElectricalEnergyMeasurementServer");
159742
159916
  var FeaturedBase = ElectricalEnergyMeasurementServer.with("CumulativeEnergy", "ImportedEnergy");
159743
159917
  var ElectricalEnergyMeasurementServerBase = class extends FeaturedBase {
159744
159918
  async initialize() {
@@ -159747,7 +159921,7 @@ var ElectricalEnergyMeasurementServerBase = class extends FeaturedBase {
159747
159921
  const entityId = homeAssistant.entityId;
159748
159922
  const energyEntity = homeAssistant.state.mapping?.energyEntity;
159749
159923
  if (energyEntity) {
159750
- logger204.debug(
159924
+ logger205.debug(
159751
159925
  `[${entityId}] ElectricalEnergyMeasurement using mapped energy entity: ${energyEntity}`
159752
159926
  );
159753
159927
  }
@@ -159803,7 +159977,7 @@ var HaElectricalEnergyMeasurementServer = ElectricalEnergyMeasurementServerBase.
159803
159977
  // src/matter/behaviors/electrical-power-measurement-server.ts
159804
159978
  init_esm();
159805
159979
  init_home_assistant_entity_behavior();
159806
- var logger205 = Logger.get("ElectricalPowerMeasurementServer");
159980
+ var logger206 = Logger.get("ElectricalPowerMeasurementServer");
159807
159981
  var FeaturedBase2 = ElectricalPowerMeasurementServer.with("AlternatingCurrent");
159808
159982
  var ElectricalPowerMeasurementServerBase = class extends FeaturedBase2 {
159809
159983
  async initialize() {
@@ -159812,7 +159986,7 @@ var ElectricalPowerMeasurementServerBase = class extends FeaturedBase2 {
159812
159986
  const entityId = homeAssistant.entityId;
159813
159987
  const powerEntity = homeAssistant.state.mapping?.powerEntity;
159814
159988
  if (powerEntity) {
159815
- logger205.debug(
159989
+ logger206.debug(
159816
159990
  `[${entityId}] ElectricalPowerMeasurement using mapped power entity: ${powerEntity}`
159817
159991
  );
159818
159992
  }
@@ -159951,7 +160125,7 @@ init_home_assistant_entity_behavior();
159951
160125
  // src/matter/behaviors/humidity-measurement-server.ts
159952
160126
  init_esm();
159953
160127
  init_home_assistant_entity_behavior();
159954
- var logger206 = Logger.get("HumidityMeasurementServer");
160128
+ var logger207 = Logger.get("HumidityMeasurementServer");
159955
160129
  var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementServer {
159956
160130
  async initialize() {
159957
160131
  await super.initialize();
@@ -159964,7 +160138,7 @@ var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementSer
159964
160138
  return;
159965
160139
  }
159966
160140
  const humidity = this.getHumidity(this.state.config, entity.state);
159967
- logger206.debug(
160141
+ logger207.debug(
159968
160142
  `Humidity ${entity.state.entity_id} raw=${entity.state.state} measuredValue=${humidity}`
159969
160143
  );
159970
160144
  applyPatchState(this.state, {
@@ -159994,7 +160168,7 @@ function HumidityMeasurementServer(config8) {
159994
160168
  // src/matter/behaviors/power-source-server.ts
159995
160169
  init_esm();
159996
160170
  init_home_assistant_entity_behavior();
159997
- var logger207 = Logger.get("PowerSourceServer");
160171
+ var logger208 = Logger.get("PowerSourceServer");
159998
160172
  var FeaturedBase3 = PowerSourceServer.with("Battery", "Rechargeable");
159999
160173
  var PowerSourceServerBase = class extends FeaturedBase3 {
160000
160174
  async initialize() {
@@ -160006,17 +160180,17 @@ var PowerSourceServerBase = class extends FeaturedBase3 {
160006
160180
  applyPatchState(this.state, {
160007
160181
  endpointList: [endpointNumber]
160008
160182
  });
160009
- logger207.debug(
160183
+ logger208.debug(
160010
160184
  `[${entityId}] PowerSource initialized with endpointList=[${endpointNumber}]`
160011
160185
  );
160012
160186
  } else {
160013
- logger207.warn(
160187
+ logger208.warn(
160014
160188
  `[${entityId}] PowerSource endpoint number is null during initialize - endpointList will be empty!`
160015
160189
  );
160016
160190
  }
160017
160191
  const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
160018
160192
  if (batteryEntity) {
160019
- logger207.debug(
160193
+ logger208.debug(
160020
160194
  `[${entityId}] PowerSource using mapped battery entity: ${batteryEntity}`
160021
160195
  );
160022
160196
  }
@@ -160337,12 +160511,8 @@ var FanSpeed = class _FanSpeed {
160337
160511
  }
160338
160512
  };
160339
160513
 
160340
- // src/utils/transaction-is-offline.ts
160341
- function transactionIsOffline(context) {
160342
- return !context || hasLocalActor(context);
160343
- }
160344
-
160345
160514
  // src/matter/behaviors/fan-control-server.ts
160515
+ init_transaction_is_offline();
160346
160516
  init_home_assistant_entity_behavior();
160347
160517
 
160348
160518
  // src/matter/behaviors/on-off-server.ts
@@ -160396,7 +160566,7 @@ function notifyLightTurnedOff(entityId, haLastChanged) {
160396
160566
  sweepLastTurnOff(now);
160397
160567
  lastTurnOffTimestamps.set(entityId, { ts: now, haLastChanged });
160398
160568
  }
160399
- var logger208 = Logger.get("LevelControlServer");
160569
+ var logger209 = Logger.get("LevelControlServer");
160400
160570
  var FeaturedBase5 = LevelControlServer.with("OnOff", "Lighting");
160401
160571
  var LevelControlServerBase = class extends FeaturedBase5 {
160402
160572
  pendingTransitionTime;
@@ -160414,7 +160584,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160414
160584
  try {
160415
160585
  await super.initialize();
160416
160586
  } catch (error) {
160417
- logger208.error("super.initialize() failed:", error);
160587
+ logger209.error("super.initialize() failed:", error);
160418
160588
  throw error;
160419
160589
  }
160420
160590
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
@@ -160532,7 +160702,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160532
160702
  expectedLevel: remembered,
160533
160703
  timestamp: now2
160534
160704
  });
160535
- logger208.debug(
160705
+ logger209.debug(
160536
160706
  `[${entityId}] Storing level ${level} without calling HA - moveToLevel arrived ${sinceTurnOff}ms after a Matter off while still off (#434)`
160537
160707
  );
160538
160708
  return;
@@ -160543,7 +160713,7 @@ var LevelControlServerBase = class extends FeaturedBase5 {
160543
160713
  const lastTurnOn = lastTurnOnTimestamps.get(entityId);
160544
160714
  const timeSinceTurnOn = lastTurnOn ? Date.now() - lastTurnOn : Infinity;
160545
160715
  if (level >= this.maxLevel && timeSinceTurnOn < 200) {
160546
- logger208.debug(
160716
+ logger209.debug(
160547
160717
  `[${entityId}] Ignoring moveToLevel(${level}) - Alexa brightness reset detected (${timeSinceTurnOn}ms after turn-on)`
160548
160718
  );
160549
160719
  return;
@@ -160589,7 +160759,7 @@ function LevelControlServer2(config8) {
160589
160759
  }
160590
160760
 
160591
160761
  // src/matter/behaviors/on-off-server.ts
160592
- var logger209 = Logger.get("OnOffServer");
160762
+ var logger210 = Logger.get("OnOffServer");
160593
160763
  var optimisticOnOffState = /* @__PURE__ */ new Map();
160594
160764
  var OPTIMISTIC_TIMEOUT_MS2 = 3e3;
160595
160765
  function sweepOptimisticOnOff(now) {
@@ -160653,7 +160823,7 @@ var OnOffServerBase = class extends OnOffServer {
160653
160823
  if (!action) {
160654
160824
  return;
160655
160825
  }
160656
- logger209.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
160826
+ logger210.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
160657
160827
  notifyLightTurnedOn(homeAssistant.entityId);
160658
160828
  if (!skipMomentaryFlip) {
160659
160829
  const now = Date.now();
@@ -160684,7 +160854,7 @@ var OnOffServerBase = class extends OnOffServer {
160684
160854
  if (!action) {
160685
160855
  return;
160686
160856
  }
160687
- logger209.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
160857
+ logger210.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
160688
160858
  const now = Date.now();
160689
160859
  sweepOptimisticOnOff(now);
160690
160860
  optimisticOnOffState.set(homeAssistant.entityId, {
@@ -160718,7 +160888,7 @@ function setOptimisticOnOff(entityId, expectedOnOff) {
160718
160888
  }
160719
160889
 
160720
160890
  // src/matter/behaviors/fan-control-server.ts
160721
- var logger210 = Logger.get("FanControlServer");
160891
+ var logger211 = Logger.get("FanControlServer");
160722
160892
  var defaultStepSize = 33.33;
160723
160893
  var minSpeedMax = 3;
160724
160894
  var maxSpeedMax = 100;
@@ -161025,6 +161195,7 @@ var FanControlServerBase = class extends FeaturedBase6 {
161025
161195
  homeAssistant.callAction(action);
161026
161196
  return;
161027
161197
  }
161198
+ homeAssistant.assertAvailable();
161028
161199
  const entityId = homeAssistant.entityId;
161029
161200
  const actions = this.env.get(HomeAssistantActions);
161030
161201
  const st = getFanDebounce(this.endpoint);
@@ -161057,7 +161228,7 @@ var FanControlServerBase = class extends FeaturedBase6 {
161057
161228
  const wasOff = homeAssistant.entity.state?.state === "off" || this.agent.has(OnOffBehavior) && !this.agent.get(OnOffBehavior).state.onOff;
161058
161229
  const remembered = this.remembered();
161059
161230
  if (wasOff) {
161060
- logger210.debug(
161231
+ logger211.debug(
161061
161232
  `[${homeAssistant.entityId}] power-on write ${percentage}%: restore flag=${restoreOnPowerOn}, last speed=${remembered.percent}`
161062
161233
  );
161063
161234
  }
@@ -161250,7 +161421,7 @@ var FanControlServerBase = class extends FeaturedBase6 {
161250
161421
  const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
161251
161422
  setOptimisticOnOff(entityId, on);
161252
161423
  } catch (e) {
161253
- logger210.debug(
161424
+ logger211.debug(
161254
161425
  `syncOnOff(${on}) failed: ${e instanceof Error ? e.message : String(e)}`
161255
161426
  );
161256
161427
  }
@@ -161393,7 +161564,7 @@ var FanOnOffServer = OnOffServer2({
161393
161564
  });
161394
161565
 
161395
161566
  // src/matter/endpoints/composed/composed-air-purifier-endpoint.ts
161396
- var logger211 = Logger.get("ComposedAirPurifierEndpoint");
161567
+ var logger212 = Logger.get("ComposedAirPurifierEndpoint");
161397
161568
  var temperatureConfig = {
161398
161569
  getValue(entity, agent) {
161399
161570
  const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
@@ -161611,7 +161782,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
161611
161782
  config8.powerEntityId ? "+Pwr" : "",
161612
161783
  config8.energyEntityId ? "+Nrg" : ""
161613
161784
  ].filter(Boolean).join("");
161614
- logger211.info(
161785
+ logger212.info(
161615
161786
  `Created composed air purifier ${primaryEntityId}: ${clusterLabels}`
161616
161787
  );
161617
161788
  return endpoint;
@@ -161929,12 +162100,12 @@ var ClimateHumidityMeasurementServer = HumidityMeasurementServer(humidityConfig2
161929
162100
  // src/matter/endpoints/legacy/climate/behaviors/climate-on-off-server.ts
161930
162101
  init_esm();
161931
162102
  init_home_assistant_entity_behavior();
161932
- var logger212 = Logger.get("ClimateOnOffServer");
162103
+ var logger213 = Logger.get("ClimateOnOffServer");
161933
162104
  var ClimateOnOffServer = OnOffServer2({
161934
162105
  turnOn: (_value, agent) => {
161935
162106
  const entity = agent.get(HomeAssistantEntityBehavior).entity;
161936
162107
  if (entity.state.state !== "off" && agent.get(OnOffServer).state.onOff) {
161937
- logger212.debug(
162108
+ logger213.debug(
161938
162109
  `[${entity.entity_id}] Skipping redundant OnOff.on(), cached state "${entity.state.state}"`
161939
162110
  );
161940
162111
  return void 0;
@@ -161968,7 +162139,8 @@ init_home_assistant_entity_behavior();
161968
162139
  // src/matter/behaviors/thermostat-server.ts
161969
162140
  init_esm();
161970
162141
  init_home_assistant_entity_behavior();
161971
- var logger213 = Logger.get("ThermostatServer");
162142
+ init_transaction_is_offline();
162143
+ var logger214 = Logger.get("ThermostatServer");
161972
162144
  var SystemMode = Thermostat3.SystemMode;
161973
162145
  var RunningMode = Thermostat3.ThermostatRunningMode;
161974
162146
  var nudgingSetpoints = /* @__PURE__ */ new Set();
@@ -162047,7 +162219,7 @@ function clearInactiveSetpointState(self, scope) {
162047
162219
  }
162048
162220
  function thermostatPreInitialize(self) {
162049
162221
  const currentLocal = self.state.localTemperature;
162050
- logger213.debug(
162222
+ logger214.debug(
162051
162223
  `initialize: features - heating=${self.features.heating}, cooling=${self.features.cooling}`
162052
162224
  );
162053
162225
  const localValue = typeof currentLocal === "number" && !Number.isNaN(currentLocal) ? currentLocal : currentLocal === null ? null : 2100;
@@ -162094,7 +162266,7 @@ function thermostatPreInitialize(self) {
162094
162266
  } else {
162095
162267
  clearInactiveSetpointState(self, "Cool");
162096
162268
  }
162097
- logger213.debug(
162269
+ logger214.debug(
162098
162270
  `initialize: after force-set - local=${self.state.localTemperature}`
162099
162271
  );
162100
162272
  self.state.thermostatRunningState = runningStateAllOff;
@@ -162187,7 +162359,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162187
162359
  maxCoolLimit,
162188
162360
  "cool"
162189
162361
  );
162190
- logger213.debug(
162362
+ logger214.debug(
162191
162363
  `update: limits heat=[${minHeatLimit}, ${maxHeatLimit}], cool=[${minCoolLimit}, ${maxCoolLimit}], systemMode=${systemMode}, runningMode=${runningMode}`
162192
162364
  );
162193
162365
  let controlSequence = config8.getControlSequence(entity.state, this.agent);
@@ -162260,18 +162432,18 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162260
162432
  */
162261
162433
  // biome-ignore lint/correctness/noUnusedPrivateClassMembers: Called via thermostatPostInitialize + prototype copy
162262
162434
  heatingSetpointChanging(value, _oldValue, context) {
162263
- logger213.debug(
162435
+ logger214.debug(
162264
162436
  `heatingSetpointChanging: value=${value}, oldValue=${_oldValue}, isOffline=${transactionIsOffline(context)}`
162265
162437
  );
162266
162438
  if (transactionIsOffline(context)) {
162267
- logger213.debug(
162439
+ logger214.debug(
162268
162440
  "heatingSetpointChanging: skipping - transaction is offline"
162269
162441
  );
162270
162442
  return;
162271
162443
  }
162272
162444
  const next = Temperature.celsius(value / 100);
162273
162445
  if (!next) {
162274
- logger213.debug("heatingSetpointChanging: skipping - invalid temperature");
162446
+ logger214.debug("heatingSetpointChanging: skipping - invalid temperature");
162275
162447
  return;
162276
162448
  }
162277
162449
  this.agent.asLocalActor(() => {
@@ -162282,7 +162454,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162282
162454
  this.agent
162283
162455
  );
162284
162456
  const currentMode2 = this.state.systemMode;
162285
- logger213.debug(
162457
+ logger214.debug(
162286
162458
  `heatingSetpointChanging: supportsRange=${supportsRange}, systemMode=${currentMode2}, features.heating=${this.features.heating}, features.cooling=${this.features.cooling}`
162287
162459
  );
162288
162460
  if (!supportsRange) {
@@ -162292,12 +162464,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162292
162464
  const isOff = currentMode2 === Thermostat3.SystemMode.Off;
162293
162465
  if (isOff && this.features.heating) {
162294
162466
  if (nudgingSetpoints.has(homeAssistant.entityId)) {
162295
- logger213.debug(
162467
+ logger214.debug(
162296
162468
  `heatingSetpointChanging: skipping auto-resume - nudge write in progress`
162297
162469
  );
162298
162470
  return;
162299
162471
  }
162300
- logger213.info(
162472
+ logger214.info(
162301
162473
  `heatingSetpointChanging: auto-resume - switching to Heat (was Off)`
162302
162474
  );
162303
162475
  const modeAction = config8.setSystemMode(
@@ -162306,17 +162478,17 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162306
162478
  );
162307
162479
  homeAssistant.callAction(modeAction);
162308
162480
  } else if (!isAutoMode && !isHeatingMode) {
162309
- logger213.debug(
162481
+ logger214.debug(
162310
162482
  `heatingSetpointChanging: skipping - not in heating/auto mode (mode=${currentMode2}, haMode=${haHvacMode})`
162311
162483
  );
162312
162484
  return;
162313
162485
  }
162314
- logger213.debug(
162486
+ logger214.debug(
162315
162487
  `heatingSetpointChanging: proceeding - isAutoMode=${isAutoMode}, isHeatingMode=${isHeatingMode}, isOff=${isOff}, haMode=${haHvacMode}`
162316
162488
  );
162317
162489
  }
162318
162490
  const coolingSetpoint = this.features.cooling ? this.state.occupiedCoolingSetpoint : value;
162319
- logger213.debug(
162491
+ logger214.debug(
162320
162492
  `heatingSetpointChanging: calling setTemperature with heat=${next.celsius(true)}, cool=${coolingSetpoint}`
162321
162493
  );
162322
162494
  this.setTemperature(
@@ -162355,12 +162527,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162355
162527
  const isOff = currentMode2 === Thermostat3.SystemMode.Off;
162356
162528
  if (isOff && !this.features.heating && this.features.cooling) {
162357
162529
  if (nudgingSetpoints.has(homeAssistant.entityId)) {
162358
- logger213.debug(
162530
+ logger214.debug(
162359
162531
  `coolingSetpointChanging: skipping auto-resume - nudge write in progress`
162360
162532
  );
162361
162533
  return;
162362
162534
  }
162363
- logger213.info(
162535
+ logger214.info(
162364
162536
  `coolingSetpointChanging: auto-resume - switching to Cool (was Off)`
162365
162537
  );
162366
162538
  const modeAction = config8.setSystemMode(
@@ -162369,12 +162541,12 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162369
162541
  );
162370
162542
  homeAssistant.callAction(modeAction);
162371
162543
  } else if (!isAutoMode && !isCoolingMode) {
162372
- logger213.debug(
162544
+ logger214.debug(
162373
162545
  `coolingSetpointChanging: skipping - not in cooling/auto mode (mode=${currentMode2}, haMode=${haHvacMode})`
162374
162546
  );
162375
162547
  return;
162376
162548
  }
162377
- logger213.debug(
162549
+ logger214.debug(
162378
162550
  `coolingSetpointChanging: proceeding - isAutoMode=${isAutoMode}, isCoolingMode=${isCoolingMode}, isOff=${isOff}, haMode=${haHvacMode}`
162379
162551
  );
162380
162552
  }
@@ -162488,7 +162660,7 @@ var ThermostatServerBase = class extends FullFeaturedBase {
162488
162660
  const effectiveMax = max ?? 5e3;
162489
162661
  if (value == null || Number.isNaN(value)) {
162490
162662
  const defaultValue = type === "heat" ? 2e3 : 2400;
162491
- logger213.debug(
162663
+ logger214.debug(
162492
162664
  `${type} setpoint is undefined, using default: ${defaultValue}`
162493
162665
  );
162494
162666
  return Math.max(effectiveMin, Math.min(effectiveMax, defaultValue));
@@ -163066,7 +163238,7 @@ function ClimateDevice(homeAssistantEntity, includeBasicInformation = true) {
163066
163238
  }
163067
163239
 
163068
163240
  // src/matter/endpoints/composed/composed-climate-fan-endpoint.ts
163069
- var logger214 = Logger.get("ComposedClimateFanEndpoint");
163241
+ var logger215 = Logger.get("ComposedClimateFanEndpoint");
163070
163242
  function createEndpointId3(entityId, customName) {
163071
163243
  const baseName = customName || entityId;
163072
163244
  return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
@@ -163104,7 +163276,7 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
163104
163276
  climateSub = new Endpoint(climateType, { id: `${endpointId}_climate` });
163105
163277
  } catch (error) {
163106
163278
  const message = error instanceof Error ? error.message : String(error);
163107
- logger214.warn(
163279
+ logger215.warn(
163108
163280
  `Companion fan: climate sub build failed for ${primaryEntityId}: ${message}`
163109
163281
  );
163110
163282
  return void 0;
@@ -163148,7 +163320,7 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
163148
163320
  endpointId,
163149
163321
  [climateSub, fanSub]
163150
163322
  );
163151
- logger214.info(`Created composed climate+fan endpoint ${primaryEntityId}`);
163323
+ logger215.info(`Created composed climate+fan endpoint ${primaryEntityId}`);
163152
163324
  return endpoint;
163153
163325
  }
163154
163326
  constructor(type, entityId, id, parts) {
@@ -163243,7 +163415,7 @@ init_home_assistant_entity_behavior();
163243
163415
  // src/matter/behaviors/pressure-measurement-server.ts
163244
163416
  init_esm();
163245
163417
  init_home_assistant_entity_behavior();
163246
- var logger215 = Logger.get("PressureMeasurementServer");
163418
+ var logger216 = Logger.get("PressureMeasurementServer");
163247
163419
  var MIN_PRESSURE = 300;
163248
163420
  var MAX_PRESSURE = 1100;
163249
163421
  var PressureMeasurementServerBase = class extends PressureMeasurementServer {
@@ -163271,7 +163443,7 @@ var PressureMeasurementServerBase = class extends PressureMeasurementServer {
163271
163443
  }
163272
163444
  const rounded = Math.round(value);
163273
163445
  if (rounded < MIN_PRESSURE || rounded > MAX_PRESSURE) {
163274
- logger215.warn(
163446
+ logger216.warn(
163275
163447
  `Pressure value ${rounded} (raw: ${value}) for ${entity.entity_id} is outside valid range [${MIN_PRESSURE}-${MAX_PRESSURE}], ignoring`
163276
163448
  );
163277
163449
  return null;
@@ -163290,7 +163462,7 @@ function PressureMeasurementServer2(config8) {
163290
163462
  }
163291
163463
 
163292
163464
  // src/matter/endpoints/composed/composed-sensor-endpoint.ts
163293
- var logger216 = Logger.get("ComposedSensorEndpoint");
163465
+ var logger217 = Logger.get("ComposedSensorEndpoint");
163294
163466
  var temperatureConfig2 = {
163295
163467
  getValue(entity, agent) {
163296
163468
  const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
@@ -163468,7 +163640,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
163468
163640
  if (config8.pressureEntityId && pressSub) {
163469
163641
  endpoint.subEndpoints.set(config8.pressureEntityId, pressSub);
163470
163642
  }
163471
- logger216.info(
163643
+ logger217.info(
163472
163644
  `Created composed sensor ${primaryEntityId} with ${parts.length} sub-endpoint(s): T${humSub ? "+H" : ""}${pressSub ? "+P" : ""}${config8.batteryEntityId ? "+Bat" : ""}${config8.powerEntityId ? "+Pwr" : ""}${config8.energyEntityId ? "+Nrg" : ""}`
163473
163645
  );
163474
163646
  return endpoint;
@@ -163605,7 +163777,7 @@ init_home_assistant_entity_behavior();
163605
163777
  // src/matter/behaviors/mode-select-server.ts
163606
163778
  init_esm();
163607
163779
  init_home_assistant_entity_behavior();
163608
- var logger217 = Logger.get("ModeSelectServer");
163780
+ var logger218 = Logger.get("ModeSelectServer");
163609
163781
  function buildSupportedModes(options) {
163610
163782
  return options.map((label, index) => ({
163611
163783
  label: label.length > 64 ? label.substring(0, 64) : label,
@@ -163642,13 +163814,13 @@ var ModeSelectServerBase = class extends ModeSelectServer {
163642
163814
  const options = config8.getOptions(homeAssistant.entity);
163643
163815
  const { newMode } = request;
163644
163816
  if (newMode < 0 || newMode >= options.length) {
163645
- logger217.warn(
163817
+ logger218.warn(
163646
163818
  `[${homeAssistant.entityId}] Invalid mode ${newMode}, options: [${options.join(", ")}]`
163647
163819
  );
163648
163820
  return;
163649
163821
  }
163650
163822
  const option = options[newMode];
163651
- logger217.info(
163823
+ logger218.info(
163652
163824
  `[${homeAssistant.entityId}] changeToMode(${newMode}) -> "${option}"`
163653
163825
  );
163654
163826
  applyPatchState(this.state, { currentMode: newMode });
@@ -164199,7 +164371,7 @@ var CoAlarmWithBatteryType = SmokeCoAlarmDevice.with(
164199
164371
  );
164200
164372
 
164201
164373
  // src/matter/endpoints/legacy/binary-sensor/index.ts
164202
- var logger218 = Logger.get("BinarySensorDevice");
164374
+ var logger219 = Logger.get("BinarySensorDevice");
164203
164375
  var deviceClasses = {
164204
164376
  [BinarySensorDeviceClass.CarbonMonoxide]: CoAlarmType,
164205
164377
  [BinarySensorDeviceClass.Gas]: CoAlarmType,
@@ -164250,11 +164422,11 @@ function BinarySensorDevice(homeAssistantEntity) {
164250
164422
  const originalTypeName = type.name;
164251
164423
  if (hasBattery && batteryTypes.has(type)) {
164252
164424
  type = batteryTypes.get(type);
164253
- logger218.info(
164425
+ logger219.info(
164254
164426
  `[${entityId}] Using battery variant: ${originalTypeName} -> ${type.name}, batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"}`
164255
164427
  );
164256
164428
  } else if (hasBattery) {
164257
- logger218.warn(
164429
+ logger219.warn(
164258
164430
  `[${entityId}] Has battery but no variant available for ${originalTypeName}`
164259
164431
  );
164260
164432
  }
@@ -164341,7 +164513,7 @@ init_home_assistant_entity_behavior();
164341
164513
  init_esm();
164342
164514
  init_home_assistant_actions();
164343
164515
  init_home_assistant_entity_behavior();
164344
- var logger219 = Logger.get("WindowCoveringServer");
164516
+ var logger220 = Logger.get("WindowCoveringServer");
164345
164517
  var MovementStatus = WindowCovering3.MovementStatus;
164346
164518
  var FeaturedBase7 = WindowCoveringServer.with(
164347
164519
  "Lift",
@@ -164552,7 +164724,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164552
164724
  }
164553
164725
  return existing100ths ?? current100ths;
164554
164726
  };
164555
- logger219.debug(
164727
+ logger220.debug(
164556
164728
  `Cover update for ${entity.entity_id}: state=${state.state}, lift=${currentLift}%, tilt=${currentTilt}%, ha=${MovementStatus[movementStatus]}, effective=${MovementStatus[globalStatus]}`
164557
164729
  );
164558
164730
  const overrideType = config8.getCoverType?.(state, this.agent);
@@ -164597,9 +164769,9 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164597
164769
  );
164598
164770
  if (Object.keys(appliedPatch).length > 0) {
164599
164771
  const hasOperationalChange = "operationalStatus" in appliedPatch;
164600
- const log = hasOperationalChange ? logger219.info : logger219.debug;
164772
+ const log = hasOperationalChange ? logger220.info : logger220.debug;
164601
164773
  log.call(
164602
- logger219,
164774
+ logger220,
164603
164775
  `Cover ${entity.entity_id} state changed: ${JSON.stringify(appliedPatch)}`
164604
164776
  );
164605
164777
  }
@@ -164708,7 +164880,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164708
164880
  }
164709
164881
  });
164710
164882
  } catch (error) {
164711
- logger219.debug(
164883
+ logger220.debug(
164712
164884
  `Optimistic ${axis} timeout write failed (endpoint may be closing): ${error}`
164713
164885
  );
164714
164886
  }
@@ -164718,12 +164890,32 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164718
164890
  optimistic[axis] = { status: status3, startedAt, timer, expectedRestEnd };
164719
164891
  this.writeOperationalStatus({ [axis]: status3 });
164720
164892
  }
164893
+ // matter.js runs handleMovement as a worker, so a throw in there cannot fail
164894
+ // the command. The commands that start movement check up front instead, and
164895
+ // the HA call is deferred past the debounce anyway, outside the transaction
164896
+ // where a rollback could not undo the optimistic target (#446).
164897
+ async upOrOpen() {
164898
+ this.agent.get(HomeAssistantEntityBehavior).assertAvailable();
164899
+ return super.upOrOpen();
164900
+ }
164901
+ async downOrClose() {
164902
+ this.agent.get(HomeAssistantEntityBehavior).assertAvailable();
164903
+ return super.downOrClose();
164904
+ }
164905
+ async goToLiftPercentage(request) {
164906
+ this.agent.get(HomeAssistantEntityBehavior).assertAvailable();
164907
+ return super.goToLiftPercentage(request);
164908
+ }
164909
+ async goToTiltPercentage(request) {
164910
+ this.agent.get(HomeAssistantEntityBehavior).assertAvailable();
164911
+ return super.goToTiltPercentage(request);
164912
+ }
164721
164913
  async handleMovement(type, _, direction, targetPercent100ths) {
164722
164914
  const currentLift = this.state.currentPositionLiftPercent100ths ?? 0;
164723
164915
  const currentTilt = this.state.currentPositionTiltPercent100ths ?? 0;
164724
164916
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
164725
164917
  const flags2 = this.state.config.getDiagnosticFlags?.(this.agent);
164726
- logger219.info(
164918
+ logger220.info(
164727
164919
  `handleMovement ${homeAssistant.entityId}: type=${MovementType[type]}, direction=${MovementDirection[direction]}, target=${targetPercent100ths}, currentLift=${currentLift}, currentTilt=${currentTilt}${flags2 ? `, ${flags2}` : ""}`
164728
164920
  );
164729
164921
  if (type === MovementType.Lift) {
@@ -164742,7 +164934,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164742
164934
  }
164743
164935
  } else if (type === MovementType.Tilt) {
164744
164936
  if (targetPercent100ths == null && this.lastLiftMovementDirection === direction && Date.now() - this.lastLiftMovementMs < 50) {
164745
- logger219.info(
164937
+ logger220.info(
164746
164938
  `Skipping tilt ${MovementDirection[direction]}, lift already moving in same direction`
164747
164939
  );
164748
164940
  return;
@@ -164787,7 +164979,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164787
164979
  } else {
164788
164980
  this.startOptimisticMovement("lift", MovementStatus.Opening, end);
164789
164981
  }
164790
- logger219.info(
164982
+ logger220.info(
164791
164983
  `handleLiftOpen ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
164792
164984
  );
164793
164985
  homeAssistant.callAction(action);
@@ -164803,7 +164995,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164803
164995
  } else {
164804
164996
  this.startOptimisticMovement("lift", MovementStatus.Closing, end);
164805
164997
  }
164806
- logger219.info(
164998
+ logger220.info(
164807
164999
  `handleLiftClose ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
164808
165000
  );
164809
165001
  homeAssistant.callAction(action);
@@ -164833,7 +165025,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164833
165025
  const isFirstInSequence = timeSinceLastCommand > _WindowCoveringServerBase.COMMAND_SEQUENCE_THRESHOLD_MS;
164834
165026
  const overrideMs = this.resolveDebounceOverride(homeAssistant);
164835
165027
  const debounceMs = overrideMs != null ? overrideMs : isFirstInSequence ? _WindowCoveringServerBase.DEBOUNCE_INITIAL_MS : _WindowCoveringServerBase.DEBOUNCE_SUBSEQUENT_MS;
164836
- logger219.debug(
165028
+ logger220.debug(
164837
165029
  `Lift command: target=${targetPosition}%, debounce=${debounceMs}ms (${overrideMs != null ? "override" : isFirstInSequence ? "initial" : "subsequent"})`
164838
165030
  );
164839
165031
  if (st.liftTimer) {
@@ -164865,7 +165057,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164865
165057
  this.startOptimisticMovement("tilt", MovementStatus.Opening, end);
164866
165058
  }
164867
165059
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
164868
- logger219.info(
165060
+ logger220.info(
164869
165061
  `handleTiltOpen ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
164870
165062
  );
164871
165063
  homeAssistant.callAction(action);
@@ -164883,7 +165075,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164883
165075
  this.startOptimisticMovement("tilt", MovementStatus.Closing, end);
164884
165076
  }
164885
165077
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
164886
- logger219.info(
165078
+ logger220.info(
164887
165079
  `handleTiltClose ${homeAssistant.entityId}: calling action=${action.action}, atRest=${atRest}, ${this.state.config.getDiagnosticFlags?.(this.agent) ?? ""}`
164888
165080
  );
164889
165081
  homeAssistant.callAction(action);
@@ -164913,7 +165105,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
164913
165105
  const isFirstInSequence = timeSinceLastCommand > _WindowCoveringServerBase.COMMAND_SEQUENCE_THRESHOLD_MS;
164914
165106
  const overrideMs = this.resolveDebounceOverride(homeAssistant);
164915
165107
  const debounceMs = overrideMs != null ? overrideMs : isFirstInSequence ? _WindowCoveringServerBase.DEBOUNCE_INITIAL_MS : _WindowCoveringServerBase.DEBOUNCE_SUBSEQUENT_MS;
164916
- logger219.debug(
165108
+ logger220.debug(
164917
165109
  `Tilt command: target=${targetPosition}%, debounce=${debounceMs}ms (${overrideMs != null ? "override" : isFirstInSequence ? "initial" : "subsequent"})`
164918
165110
  );
164919
165111
  if (st.tiltTimer) {
@@ -164965,7 +165157,7 @@ function adjustPositionForWriting(position, flags2, matterSemantics) {
164965
165157
  }
164966
165158
 
164967
165159
  // src/matter/endpoints/legacy/cover/behaviors/cover-window-covering-server.ts
164968
- var logger220 = Logger.get("CoverWindowCoveringServer");
165160
+ var logger221 = Logger.get("CoverWindowCoveringServer");
164969
165161
  var attributes6 = (entity) => entity.attributes;
164970
165162
  var DEVICE_CLASS_TO_MATTER_TYPE = {
164971
165163
  curtain: {
@@ -165037,7 +165229,7 @@ var adjustPositionForReading2 = (position, agent) => {
165037
165229
  const { featureFlags } = agent.env.get(BridgeDataProvider);
165038
165230
  const matterSem = usesMatterSemantics(agent);
165039
165231
  const result = adjustPositionForReading(position, featureFlags, matterSem);
165040
- logger220.debug(`adjustPositionForReading: HA=${position}%, result=${result}%`);
165232
+ logger221.debug(`adjustPositionForReading: HA=${position}%, result=${result}%`);
165041
165233
  return result;
165042
165234
  };
165043
165235
  var adjustPositionForWriting2 = (position, agent) => {
@@ -165262,14 +165454,14 @@ var CoverAsDimmableLightWithBatteryType = DimmableLightDevice.with(
165262
165454
  );
165263
165455
 
165264
165456
  // src/matter/endpoints/legacy/cover/index.ts
165265
- var logger221 = Logger.get("CoverDevice");
165457
+ var logger222 = Logger.get("CoverDevice");
165266
165458
  var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
165267
165459
  const features = /* @__PURE__ */ new Set();
165268
165460
  if (testBit(supportedFeatures, CoverSupportedFeatures.support_open)) {
165269
165461
  features.add("Lift");
165270
165462
  features.add("PositionAwareLift");
165271
165463
  } else {
165272
- logger221.warn(
165464
+ logger222.warn(
165273
165465
  `[${entityId}] Cover has no support_open feature (supported_features=${supportedFeatures}), adding Lift anyway`
165274
165466
  );
165275
165467
  features.add("Lift");
@@ -165284,7 +165476,7 @@ var CoverDeviceType = (supportedFeatures, hasBattery, entityId) => {
165284
165476
  features.add("PositionAwareTilt");
165285
165477
  }
165286
165478
  }
165287
- logger221.info(
165479
+ logger222.info(
165288
165480
  `[${entityId}] Creating WindowCovering with features: [${[...features].join(", ")}], supported_features=${supportedFeatures}`
165289
165481
  );
165290
165482
  const baseBehaviors2 = [
@@ -165308,16 +165500,16 @@ function CoverDevice(homeAssistantEntity) {
165308
165500
  const hasBatteryEntity = !!homeAssistantEntity.mapping?.batteryEntity;
165309
165501
  const hasBattery = hasBatteryAttr || hasBatteryEntity;
165310
165502
  if (hasBattery) {
165311
- logger221.info(
165503
+ logger222.info(
165312
165504
  `[${entityId}] Creating cover with PowerSource cluster, batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"}`
165313
165505
  );
165314
165506
  } else {
165315
- logger221.debug(
165507
+ logger222.debug(
165316
165508
  `[${entityId}] Creating cover without battery (batteryAttr=${hasBatteryAttr}, batteryEntity=${homeAssistantEntity.mapping?.batteryEntity ?? "none"})`
165317
165509
  );
165318
165510
  }
165319
165511
  if (homeAssistantEntity.mapping?.coverExposeAsDimmableLight) {
165320
- logger221.info(`[${entityId}] Exposing cover as a Dimmable Light (#372)`);
165512
+ logger222.info(`[${entityId}] Exposing cover as a Dimmable Light (#372)`);
165321
165513
  const type = hasBattery ? CoverAsDimmableLightWithBatteryType : CoverAsDimmableLightType;
165322
165514
  return type.set({ homeAssistantEntity });
165323
165515
  }
@@ -165432,7 +165624,7 @@ function DishwasherEndpoint(homeAssistantEntity) {
165432
165624
  // src/matter/behaviors/generic-switch-server.ts
165433
165625
  init_esm();
165434
165626
  init_home_assistant_entity_behavior();
165435
- var logger222 = Logger.get("GenericSwitchServer");
165627
+ var logger223 = Logger.get("GenericSwitchServer");
165436
165628
  var SimpleBase = SwitchServer.with(
165437
165629
  "MomentarySwitch",
165438
165630
  "MomentarySwitchRelease",
@@ -165474,7 +165666,7 @@ var HaGenericSwitchServerBase = class extends SimpleBase {
165474
165666
  await super.initialize();
165475
165667
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
165476
165668
  const entityId = homeAssistant.entityId;
165477
- logger222.debug(`[${entityId}] GenericSwitch initialized (simple)`);
165669
+ logger223.debug(`[${entityId}] GenericSwitch initialized (simple)`);
165478
165670
  this.reactTo(homeAssistant.onChange, this.handleEventChange);
165479
165671
  }
165480
165672
  handleEventChange() {
@@ -165485,7 +165677,7 @@ var HaGenericSwitchServerBase = class extends SimpleBase {
165485
165677
  const eventType = attrs.event_type;
165486
165678
  if (!eventType) return;
165487
165679
  const entityId = homeAssistant.entityId;
165488
- logger222.debug(`[${entityId}] Event fired: ${eventType}`);
165680
+ logger223.debug(`[${entityId}] Event fired: ${eventType}`);
165489
165681
  this.triggerPress(eventType);
165490
165682
  }
165491
165683
  triggerPress(eventType) {
@@ -165531,7 +165723,7 @@ var HaGenericSwitchServerMultiBase = class extends FullBase {
165531
165723
  await super.initialize();
165532
165724
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
165533
165725
  const entityId = homeAssistant.entityId;
165534
- logger222.debug(`[${entityId}] GenericSwitch initialized (multi)`);
165726
+ logger223.debug(`[${entityId}] GenericSwitch initialized (multi)`);
165535
165727
  this.reactTo(homeAssistant.onChange, this.handleEventChange);
165536
165728
  }
165537
165729
  handleEventChange() {
@@ -165542,7 +165734,7 @@ var HaGenericSwitchServerMultiBase = class extends FullBase {
165542
165734
  const eventType = attrs.event_type;
165543
165735
  if (!eventType) return;
165544
165736
  const entityId = homeAssistant.entityId;
165545
- logger222.debug(`[${entityId}] Event fired: ${eventType}`);
165737
+ logger223.debug(`[${entityId}] Event fired: ${eventType}`);
165546
165738
  this.triggerPress(eventType);
165547
165739
  }
165548
165740
  triggerPress(eventType) {
@@ -165919,7 +166111,7 @@ init_nodejs();
165919
166111
  init_home_assistant_entity_behavior();
165920
166112
  var OperationalState4 = RvcOperationalState4.OperationalState;
165921
166113
  var ErrorState = RvcOperationalState4.ErrorState;
165922
- var logger223 = Logger.get("RvcOperationalStateServer");
166114
+ var logger224 = Logger.get("RvcOperationalStateServer");
165923
166115
  var activeStates = /* @__PURE__ */ new Set([
165924
166116
  OperationalState4.Running,
165925
166117
  OperationalState4.SeekingCharger
@@ -165971,7 +166163,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
165971
166163
  { force: true }
165972
166164
  );
165973
166165
  if (activeStates.has(previousState) && !activeStates.has(newState)) {
165974
- logger223.info(
166166
+ logger224.info(
165975
166167
  `Operation completed: ${OperationalState4[previousState]} -> ${OperationalState4[newState]}`
165976
166168
  );
165977
166169
  try {
@@ -165984,7 +166176,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
165984
166176
  this.context
165985
166177
  );
165986
166178
  } catch (e) {
165987
- logger223.debug("Failed to emit operationCompletion event:", e);
166179
+ logger224.debug("Failed to emit operationCompletion event:", e);
165988
166180
  }
165989
166181
  }
165990
166182
  }
@@ -166019,7 +166211,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
166019
166211
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
166020
166212
  homeAssistant.callAction(goHomeAction(void 0, this.agent));
166021
166213
  } else {
166022
- logger223.warn("GoHome command received but no goHome action configured");
166214
+ logger224.warn("GoHome command received but no goHome action configured");
166023
166215
  }
166024
166216
  return {
166025
166217
  commandResponseState: {
@@ -166039,7 +166231,7 @@ function RvcOperationalStateServer2(config8) {
166039
166231
  }
166040
166232
 
166041
166233
  // src/matter/endpoints/legacy/lawn-mower/behaviors/lawn-mower-rvc-operational-state-server.ts
166042
- var logger224 = Logger.get("LawnMowerRvcOperationalStateServer");
166234
+ var logger225 = Logger.get("LawnMowerRvcOperationalStateServer");
166043
166235
  function mapLawnMowerOperationalState(entity) {
166044
166236
  const state = entity.state;
166045
166237
  switch (state) {
@@ -166055,7 +166247,7 @@ function mapLawnMowerOperationalState(entity) {
166055
166247
  case "unavailable":
166056
166248
  return RvcOperationalState4.OperationalState.Error;
166057
166249
  default:
166058
- logger224.info(`Unknown lawn_mower state "${state}", treating as Stopped`);
166250
+ logger225.info(`Unknown lawn_mower state "${state}", treating as Stopped`);
166059
166251
  return RvcOperationalState4.OperationalState.Stopped;
166060
166252
  }
166061
166253
  }
@@ -166109,7 +166301,7 @@ function inferCleanedAreaProgress(cleanedSqm, orderedAreas) {
166109
166301
  }
166110
166302
 
166111
166303
  // src/matter/behaviors/rvc-run-mode-server.ts
166112
- var logger225 = Logger.get("RvcRunModeServer");
166304
+ var logger226 = Logger.get("RvcRunModeServer");
166113
166305
  var ROOM_MODE_BASE = 100;
166114
166306
  function isRoomMode(mode) {
166115
166307
  return mode >= ROOM_MODE_BASE;
@@ -166235,7 +166427,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166235
166427
  const s = getSession(this.endpoint);
166236
166428
  if (s.loggedShortCircuits.has(reason)) return;
166237
166429
  s.loggedShortCircuits.add(reason);
166238
- logger225.info(message);
166430
+ logger226.info(message);
166239
166431
  }
166240
166432
  /**
166241
166433
  * Read the currentRoomEntity sensor and update currentArea + progress
@@ -166292,7 +166484,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166292
166484
  }
166293
166485
  }
166294
166486
  if (matchedAreaId === null) {
166295
- logger225.info(
166487
+ logger226.info(
166296
166488
  `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(", ")}]`
166297
166489
  );
166298
166490
  return;
@@ -166302,14 +166494,14 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166302
166494
  s.completedAreas.add(s.lastCurrentArea);
166303
166495
  }
166304
166496
  s.lastCurrentArea = matchedAreaId;
166305
- logger225.info(
166497
+ logger226.info(
166306
166498
  `currentRoom sensor: transition to area ${matchedAreaId} ("${roomName}"), completed: [${[...s.completedAreas].join(", ")}]`
166307
166499
  );
166308
166500
  this.trySetCurrentArea(matchedAreaId);
166309
166501
  } catch (e) {
166310
166502
  const msg = e instanceof Error ? e.message : String(e);
166311
166503
  if (!msg.includes("No provider for") && !msg.includes("not supported")) {
166312
- logger225.warn(`currentRoom sensor update failed: ${msg}`);
166504
+ logger226.warn(`currentRoom sensor update failed: ${msg}`);
166313
166505
  }
166314
166506
  }
166315
166507
  }
@@ -166389,7 +166581,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166389
166581
  cleaned,
166390
166582
  ordered
166391
166583
  );
166392
- logger225.debug(
166584
+ logger226.debug(
166393
166585
  `cleanedArea: raw=${raw} baseline=${s.cleanedAreaBaseline} cleaned=${cleaned} sizes=[${ordered.map((o) => `${o.areaId}:${o.sizeSqm}`).join(",")}] -> current=${currentArea} completed=[${completed.join(",")}]`
166394
166586
  );
166395
166587
  for (const id of completed) {
@@ -166403,7 +166595,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166403
166595
  } catch (e) {
166404
166596
  const msg = e instanceof Error ? e.message : String(e);
166405
166597
  if (!msg.includes("No provider for") && !msg.includes("not supported")) {
166406
- logger225.warn(`cleanedArea room update failed: ${msg}`);
166598
+ logger226.warn(`cleanedArea room update failed: ${msg}`);
166407
166599
  }
166408
166600
  }
166409
166601
  }
@@ -166418,7 +166610,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
166418
166610
  const serviceArea = this.agent.get(ServiceAreaBehavior);
166419
166611
  if (serviceArea.state.currentArea !== areaId) {
166420
166612
  serviceArea.state.currentArea = areaId;
166421
- logger225.debug(`currentArea set to ${areaId}`);
166613
+ logger226.debug(`currentArea set to ${areaId}`);
166422
166614
  }
166423
166615
  this.updateProgress(serviceArea, areaId);
166424
166616
  } catch {
@@ -166701,7 +166893,7 @@ init_nodejs();
166701
166893
 
166702
166894
  // src/matter/behaviors/color-control-server.ts
166703
166895
  init_home_assistant_entity_behavior();
166704
- var logger226 = Logger.get("ColorControlServer");
166896
+ var logger227 = Logger.get("ColorControlServer");
166705
166897
  var optimisticColorState = /* @__PURE__ */ new Map();
166706
166898
  var OPTIMISTIC_TIMEOUT_MS3 = 3e3;
166707
166899
  var OPTIMISTIC_TOLERANCE2 = 5;
@@ -166740,7 +166932,7 @@ var ColorControlServerBase = class extends FeaturedBase8 {
166740
166932
  if (this.state.startUpColorTemperatureMireds == null) {
166741
166933
  this.state.startUpColorTemperatureMireds = defaultMireds;
166742
166934
  }
166743
- logger226.debug(
166935
+ logger227.debug(
166744
166936
  `initialize: set ColorTemperature defaults - min=${this.state.colorTempPhysicalMinMireds}, max=${this.state.colorTempPhysicalMaxMireds}, current=${this.state.colorTemperatureMireds}`
166745
166937
  );
166746
166938
  }
@@ -167294,8 +167486,9 @@ init_home_assistant_entity_behavior();
167294
167486
 
167295
167487
  // src/matter/behaviors/lock-server.ts
167296
167488
  init_esm();
167489
+ init_types2();
167297
167490
  init_home_assistant_entity_behavior();
167298
- var logger227 = Logger.get("LockServer");
167491
+ var logger228 = Logger.get("LockServer");
167299
167492
  var SUPPORTED_SLOT = 1;
167300
167493
  function normalizeSupportedIndex(index) {
167301
167494
  if (index === 0 || index === SUPPORTED_SLOT) {
@@ -167636,7 +167829,7 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167636
167829
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167637
167830
  const action = this.state.config.lock(void 0, this.agent);
167638
167831
  const hasPinProvided = !!request.pinCode;
167639
- logger227.debug(
167832
+ logger228.debug(
167640
167833
  `lockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}`
167641
167834
  );
167642
167835
  if (request.pinCode) {
@@ -167649,12 +167842,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167649
167842
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167650
167843
  const action = this.state.config.unlock(void 0, this.agent);
167651
167844
  const hasPinProvided = !!request.pinCode;
167652
- logger227.debug(
167845
+ logger228.debug(
167653
167846
  `unlockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}`
167654
167847
  );
167655
167848
  if (this.state.requirePinForRemoteOperation) {
167656
167849
  if (!request.pinCode) {
167657
- logger227.info(
167850
+ logger228.info(
167658
167851
  `unlockDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
167659
167852
  );
167660
167853
  throw new StatusResponseError(
@@ -167664,12 +167857,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
167664
167857
  }
167665
167858
  const providedPin = new TextDecoder().decode(request.pinCode);
167666
167859
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
167667
- logger227.info(
167860
+ logger228.info(
167668
167861
  `unlockDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
167669
167862
  );
167670
167863
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
167671
167864
  }
167672
- logger227.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
167865
+ logger228.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
167673
167866
  action.data = { ...action.data, code: providedPin };
167674
167867
  }
167675
167868
  homeAssistant.callAction(action);
@@ -167811,7 +168004,7 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
167811
168004
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167812
168005
  const action = this.state.config.lock(void 0, this.agent);
167813
168006
  const hasPinProvided = !!request.pinCode;
167814
- logger227.debug(
168007
+ logger228.debug(
167815
168008
  `lockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}`
167816
168009
  );
167817
168010
  if (request.pinCode) {
@@ -167825,12 +168018,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
167825
168018
  const unlatchConfig = this.state.config.unlatch;
167826
168019
  const action = unlatchConfig ? unlatchConfig(void 0, this.agent) : this.state.config.unlock(void 0, this.agent);
167827
168020
  const hasPinProvided = !!request.pinCode;
167828
- logger227.debug(
168021
+ logger228.debug(
167829
168022
  `unlockDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}, usingUnlatch: ${!!unlatchConfig}`
167830
168023
  );
167831
168024
  if (this.state.requirePinForRemoteOperation) {
167832
168025
  if (!request.pinCode) {
167833
- logger227.info(
168026
+ logger228.info(
167834
168027
  `unlockDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
167835
168028
  );
167836
168029
  throw new StatusResponseError(
@@ -167840,12 +168033,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
167840
168033
  }
167841
168034
  const providedPin = new TextDecoder().decode(request.pinCode);
167842
168035
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
167843
- logger227.info(
168036
+ logger228.info(
167844
168037
  `unlockDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
167845
168038
  );
167846
168039
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
167847
168040
  }
167848
- logger227.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
168041
+ logger228.debug(`unlockDoor PIN verified for ${homeAssistant.entityId}`);
167849
168042
  action.data = { ...action.data, code: providedPin };
167850
168043
  }
167851
168044
  homeAssistant.callAction(action);
@@ -167854,12 +168047,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
167854
168047
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
167855
168048
  const action = this.state.config.unlock(void 0, this.agent);
167856
168049
  const hasPinProvided = !!request.pinCode;
167857
- logger227.debug(
168050
+ logger228.debug(
167858
168051
  `unboltDoor called for ${homeAssistant.entityId}, PIN provided: ${hasPinProvided}, requirePin: ${this.state.requirePinForRemoteOperation}`
167859
168052
  );
167860
168053
  if (this.state.requirePinForRemoteOperation) {
167861
168054
  if (!request.pinCode) {
167862
- logger227.info(
168055
+ logger228.info(
167863
168056
  `unboltDoor REJECTED for ${homeAssistant.entityId} - no PIN provided`
167864
168057
  );
167865
168058
  throw new StatusResponseError(
@@ -167869,12 +168062,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
167869
168062
  }
167870
168063
  const providedPin = new TextDecoder().decode(request.pinCode);
167871
168064
  if (!verifyStoredPinHelper(this.env, homeAssistant.entityId, providedPin)) {
167872
- logger227.info(
168065
+ logger228.info(
167873
168066
  `unboltDoor REJECTED for ${homeAssistant.entityId} - invalid PIN`
167874
168067
  );
167875
168068
  throw new StatusResponseError("Invalid PIN code", StatusCode.Failure);
167876
168069
  }
167877
- logger227.debug(`unboltDoor PIN verified for ${homeAssistant.entityId}`);
168070
+ logger228.debug(`unboltDoor PIN verified for ${homeAssistant.entityId}`);
167878
168071
  action.data = { ...action.data, code: providedPin };
167879
168072
  }
167880
168073
  homeAssistant.callAction(action);
@@ -168013,7 +168206,7 @@ init_home_assistant_entity_behavior();
168013
168206
  init_dist();
168014
168207
  init_esm();
168015
168208
  init_home_assistant_entity_behavior();
168016
- var logger228 = Logger.get("MediaPlayerKeypadInputServer");
168209
+ var logger229 = Logger.get("MediaPlayerKeypadInputServer");
168017
168210
  var MediaPlayerKeypadInputServer = class extends KeypadInputServer {
168018
168211
  sendKey(request) {
168019
168212
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
@@ -168024,12 +168217,12 @@ var MediaPlayerKeypadInputServer = class extends KeypadInputServer {
168024
168217
  const features = attributes9.supported_features ?? 0;
168025
168218
  const action = this.mapKeyToAction(request.keyCode, features);
168026
168219
  if (!action) {
168027
- logger228.debug(
168220
+ logger229.debug(
168028
168221
  `Unsupported key code ${request.keyCode} for ${homeAssistant.entityId}`
168029
168222
  );
168030
168223
  return { status: KeypadInput3.Status.UnsupportedKey };
168031
168224
  }
168032
- logger228.debug(
168225
+ logger229.debug(
168033
168226
  `sendKey(${request.keyCode}) \u2192 ${action} for ${homeAssistant.entityId}`
168034
168227
  );
168035
168228
  homeAssistant.callAction({ action });
@@ -168308,7 +168501,7 @@ init_home_assistant_entity_behavior();
168308
168501
  // src/matter/behaviors/speaker-level-control-server.ts
168309
168502
  init_esm();
168310
168503
  init_home_assistant_entity_behavior();
168311
- var logger229 = Logger.get("SpeakerLevelControlServer");
168504
+ var logger230 = Logger.get("SpeakerLevelControlServer");
168312
168505
  var optimisticLevelState2 = /* @__PURE__ */ new Map();
168313
168506
  var OPTIMISTIC_TIMEOUT_MS4 = 3e3;
168314
168507
  var OPTIMISTIC_TOLERANCE3 = 5;
@@ -168351,7 +168544,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
168351
168544
  currentLevel = Math.min(Math.max(minLevel, currentLevel), maxLevel);
168352
168545
  }
168353
168546
  const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
168354
- logger229.debug(
168547
+ logger230.debug(
168355
168548
  `[${entityId}] Volume update: HA=${currentLevelPercent != null ? Math.round(currentLevelPercent * 100) : "null"}% -> currentLevel=${currentLevel}`
168356
168549
  );
168357
168550
  const optimistic = optimisticLevelState2.get(entity.entity_id);
@@ -168399,7 +168592,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
168399
168592
  const config8 = this.state.config;
168400
168593
  const entityId = homeAssistant.entity.entity_id;
168401
168594
  const levelPercent = level / 254;
168402
- logger229.debug(
168595
+ logger230.debug(
168403
168596
  `[${entityId}] Volume command: level=${level} -> HA volume_level=${levelPercent}`
168404
168597
  );
168405
168598
  const current = config8.getValuePercent(
@@ -169286,6 +169479,7 @@ var ElectricalUtilityMeterType = ElectricalUtilityMeterDevice.with(
169286
169479
 
169287
169480
  // src/matter/endpoints/legacy/sensor/devices/energy-evse.ts
169288
169481
  init_esm();
169482
+ init_types2();
169289
169483
  init_home_assistant_actions();
169290
169484
  init_home_assistant_entity_behavior();
169291
169485
 
@@ -169343,7 +169537,7 @@ function mapEvseStatus(rawState, chargingSwitchOn) {
169343
169537
  }
169344
169538
 
169345
169539
  // src/matter/endpoints/legacy/sensor/devices/energy-evse.ts
169346
- var logger230 = Logger.get("EnergyEvse");
169540
+ var logger231 = Logger.get("EnergyEvse");
169347
169541
  var MIN_CHARGE_CURRENT_MA = 6e3;
169348
169542
  var MAX_CHARGE_CURRENT_MA = 32e3;
169349
169543
  var CIRCUIT_CAPACITY_MA = 32e3;
@@ -169427,7 +169621,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169427
169621
  dispatched = true;
169428
169622
  }
169429
169623
  if (!dispatched) {
169430
- logger230.debug(
169624
+ logger231.debug(
169431
169625
  `enableCharging ignored for ${homeAssistant.entityId}: no charging switch or current limit mapped`
169432
169626
  );
169433
169627
  return;
@@ -169467,7 +169661,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169467
169661
  chargingEnabledUntil: null
169468
169662
  });
169469
169663
  } catch (error) {
169470
- logger230.debug(
169664
+ logger231.debug(
169471
169665
  `EVSE charge-window expiry write failed (endpoint may be closing): ${error}`
169472
169666
  );
169473
169667
  } finally {
@@ -169498,7 +169692,7 @@ var EvseStatusServer = class _EvseStatusServer extends EnergyEvseServer {
169498
169692
  chargingEnabledUntil: null
169499
169693
  });
169500
169694
  } else {
169501
- logger230.debug(
169695
+ logger231.debug(
169502
169696
  `disable ignored for ${homeAssistant.entityId}: no charging switch mapped`
169503
169697
  );
169504
169698
  }
@@ -170303,7 +170497,7 @@ var TvocConcentrationMeasurementServer = class extends TvocConcentrationMeasurem
170303
170497
  };
170304
170498
 
170305
170499
  // src/matter/endpoints/legacy/sensor/devices/tvoc-sensor.ts
170306
- var logger231 = Logger.get("TvocSensor");
170500
+ var logger232 = Logger.get("TvocSensor");
170307
170501
  function airQualityFromUgm3(value) {
170308
170502
  if (value <= 300) return AirQuality3.AirQualityEnum.Good;
170309
170503
  if (value <= 1e3) return AirQuality3.AirQualityEnum.Fair;
@@ -170344,17 +170538,17 @@ var TvocAirQualityServer = class extends TvocAirQualityServerBase {
170344
170538
  const attributes9 = entity.state.attributes;
170345
170539
  const deviceClass = attributes9.device_class;
170346
170540
  let airQuality = AirQuality3.AirQualityEnum.Unknown;
170347
- logger231.debug(
170541
+ logger232.debug(
170348
170542
  `[${entity.entity_id}] TVOC update: state="${state}", device_class="${deviceClass}"`
170349
170543
  );
170350
170544
  if (state != null && !Number.isNaN(+state)) {
170351
170545
  const value = +state;
170352
170546
  airQuality = deviceClass === SensorDeviceClass.volatile_organic_compounds ? airQualityFromUgm3(value) : airQualityFromPpb(value);
170353
- logger231.debug(
170547
+ logger232.debug(
170354
170548
  `[${entity.entity_id}] TVOC value=${value} (${deviceClass}) -> airQuality=${AirQuality3.AirQualityEnum[airQuality]}`
170355
170549
  );
170356
170550
  } else {
170357
- logger231.warn(
170551
+ logger232.warn(
170358
170552
  `[${entity.entity_id}] TVOC state not a valid number: "${state}"`
170359
170553
  );
170360
170554
  }
@@ -170371,6 +170565,7 @@ var TvocSensorType = AirQualitySensorDevice.with(
170371
170565
 
170372
170566
  // src/matter/endpoints/legacy/sensor/index.ts
170373
170567
  init_dist();
170568
+ init_types2();
170374
170569
  init_diagnostic_event_bus();
170375
170570
 
170376
170571
  // src/matter/behaviors/carbon-dioxide-concentration-measurement-server.ts
@@ -170568,7 +170763,7 @@ init_home_assistant_entity_behavior();
170568
170763
  // src/matter/behaviors/pm25-concentration-measurement-server.ts
170569
170764
  init_esm();
170570
170765
  init_home_assistant_entity_behavior();
170571
- var logger232 = Logger.get("Pm25ConcentrationMeasurementServer");
170766
+ var logger233 = Logger.get("Pm25ConcentrationMeasurementServer");
170572
170767
  var Pm25ConcentrationMeasurementServerBase = Pm25ConcentrationMeasurementServer.with(
170573
170768
  ConcentrationMeasurement3.Feature.NumericMeasurement
170574
170769
  );
@@ -170592,11 +170787,11 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
170592
170787
  if (this.state.measurementMedium === void 0) {
170593
170788
  this.state.measurementMedium = ConcentrationMeasurement3.MeasurementMedium.Air;
170594
170789
  }
170595
- logger232.debug(
170790
+ logger233.debug(
170596
170791
  "Pm25ConcentrationMeasurementServer: before super.initialize()"
170597
170792
  );
170598
170793
  await super.initialize();
170599
- logger232.debug(
170794
+ logger233.debug(
170600
170795
  "Pm25ConcentrationMeasurementServer: after super.initialize()"
170601
170796
  );
170602
170797
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
@@ -170619,7 +170814,7 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
170619
170814
  };
170620
170815
 
170621
170816
  // src/matter/endpoints/legacy/sensor/devices/pm25-sensor.ts
170622
- var logger233 = Logger.get("Pm25AirQualityServer");
170817
+ var logger234 = Logger.get("Pm25AirQualityServer");
170623
170818
  var Pm25AirQualityServerBase = AirQualityServer.with(
170624
170819
  AirQuality3.Feature.Fair,
170625
170820
  AirQuality3.Feature.Moderate,
@@ -170631,9 +170826,9 @@ var Pm25AirQualityServer = class extends Pm25AirQualityServerBase {
170631
170826
  if (this.state.airQuality === void 0) {
170632
170827
  this.state.airQuality = AirQuality3.AirQualityEnum.Unknown;
170633
170828
  }
170634
- logger233.debug("Pm25AirQualityServer: before super.initialize()");
170829
+ logger234.debug("Pm25AirQualityServer: before super.initialize()");
170635
170830
  await super.initialize();
170636
- logger233.debug("Pm25AirQualityServer: after super.initialize()");
170831
+ logger234.debug("Pm25AirQualityServer: after super.initialize()");
170637
170832
  const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
170638
170833
  this.update(homeAssistant.entity);
170639
170834
  this.reactTo(homeAssistant.onChange, this.update, { offline: true });
@@ -171058,56 +171253,25 @@ init_home_assistant_entity_behavior();
171058
171253
  init_dist();
171059
171254
  init_esm();
171060
171255
  init_home_assistant_entity_behavior();
171061
- var logger234 = Logger.get("VacuumIdentifyServer");
171062
- var IDENTIFY_BUTTON_SUFFIXES = ["_identify", "_locate", "_find_me"];
171256
+ var logger235 = Logger.get("VacuumIdentifyServer");
171063
171257
  var VacuumIdentifyServer = class extends IdentifyServer2 {
171064
- triggerEffect(effect) {
171065
- this.#locate("triggerEffect");
171066
- return super.triggerEffect(effect);
171067
- }
171068
- identify(request) {
171069
- if (request.identifyTime > 0) {
171070
- this.#locate("identify");
171071
- }
171072
- return super.identify(request);
171073
- }
171074
- #locate(source) {
171258
+ identifyInHomeAssistant(source) {
171075
171259
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
171076
171260
  const features = homeAssistant.entity.state.attributes.supported_features ?? 0;
171077
171261
  if (testBit(features, VacuumDeviceFeature.LOCATE)) {
171078
- logger234.info(`${source} \u2192 vacuum.locate for ${homeAssistant.entityId}`);
171262
+ logger235.info(`${source} \u2192 vacuum.locate for ${homeAssistant.entityId}`);
171079
171263
  homeAssistant.callAction({ action: "vacuum.locate" });
171080
171264
  return;
171081
171265
  }
171082
- const sibling = this.#findIdentifyButton(homeAssistant);
171083
- if (sibling) {
171084
- logger234.info(
171085
- `${source} \u2192 button.press ${sibling} for ${homeAssistant.entityId}`
171086
- );
171087
- homeAssistant.callAction({ action: "button.press", target: sibling });
171266
+ if (this.findIdentifyEntity(homeAssistant)) {
171267
+ super.identifyInHomeAssistant(source);
171088
171268
  return;
171089
171269
  }
171090
- logger234.warn(
171270
+ logger235.warn(
171091
171271
  `${source} for ${homeAssistant.entityId}, LOCATE not in supported_features (${features}), trying vacuum.locate anyway`
171092
171272
  );
171093
171273
  homeAssistant.callAction({ action: "vacuum.locate" });
171094
171274
  }
171095
- #findIdentifyButton(homeAssistant) {
171096
- const deviceId = homeAssistant.entity.registry?.device_id;
171097
- if (!deviceId) return void 0;
171098
- const registry3 = this.env.get(HomeAssistantRegistry);
171099
- for (const entity of Object.values(registry3.entities)) {
171100
- if (entity.device_id !== deviceId) continue;
171101
- if (!entity.entity_id.startsWith("button.")) continue;
171102
- const uniqueId = entity.unique_id ?? "";
171103
- if (IDENTIFY_BUTTON_SUFFIXES.some(
171104
- (s) => entity.entity_id.endsWith(s) || uniqueId.endsWith(s)
171105
- )) {
171106
- return entity.entity_id;
171107
- }
171108
- }
171109
- return void 0;
171110
- }
171111
171275
  };
171112
171276
 
171113
171277
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
@@ -171287,7 +171451,7 @@ init_esm();
171287
171451
  // src/matter/behaviors/service-area-server.ts
171288
171452
  init_esm();
171289
171453
  init_home_assistant_entity_behavior();
171290
- var logger235 = Logger.get("ServiceAreaServer");
171454
+ var logger236 = Logger.get("ServiceAreaServer");
171291
171455
  function orderSelection(areas, agent) {
171292
171456
  try {
171293
171457
  const ascending = agent?.get(HomeAssistantEntityBehavior).state.mapping?.vacuumAscendingRoomOrder === true;
@@ -171302,7 +171466,7 @@ var ServiceAreaWithProgress = ServiceAreaBehavior.with(
171302
171466
  var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171303
171467
  selectAreas(request) {
171304
171468
  const { newAreas } = request;
171305
- logger235.info(
171469
+ logger236.info(
171306
171470
  `ServiceArea selectAreas called with: ${JSON.stringify(newAreas)}`
171307
171471
  );
171308
171472
  const uniqueAreas = orderSelection([...new Set(newAreas)], this.agent);
@@ -171311,7 +171475,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171311
171475
  (id) => !supportedAreaIds.includes(id)
171312
171476
  );
171313
171477
  if (invalidAreas.length > 0) {
171314
- logger235.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171478
+ logger236.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171315
171479
  return {
171316
171480
  status: ServiceArea3.SelectAreasStatus.UnsupportedArea,
171317
171481
  statusText: `Invalid area IDs: ${invalidAreas.join(", ")}`
@@ -171323,7 +171487,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171323
171487
  status: ServiceArea3.OperationalStatus.Pending
171324
171488
  }));
171325
171489
  this.state.currentArea = null;
171326
- logger235.info(
171490
+ logger236.info(
171327
171491
  `ServiceArea: Stored ${uniqueAreas.length} areas for cleaning: ${uniqueAreas.join(", ")}`
171328
171492
  );
171329
171493
  return {
@@ -171344,7 +171508,7 @@ var ServiceAreaServerBase = class extends ServiceAreaWithProgress {
171344
171508
  ServiceAreaServerBase2.State = State;
171345
171509
  })(ServiceAreaServerBase || (ServiceAreaServerBase = {}));
171346
171510
  function ServiceAreaServer2(initialState) {
171347
- logger235.info(
171511
+ logger236.info(
171348
171512
  `Creating ServiceAreaServer with ${initialState.supportedAreas.length} areas`
171349
171513
  );
171350
171514
  return ServiceAreaServerBase.set({
@@ -171361,7 +171525,7 @@ var ServiceAreaWithMapsAndProgress = ServiceAreaBehavior.with(
171361
171525
  var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress {
171362
171526
  selectAreas(request) {
171363
171527
  const { newAreas } = request;
171364
- logger235.info(
171528
+ logger236.info(
171365
171529
  `ServiceArea selectAreas called with: ${JSON.stringify(newAreas)}`
171366
171530
  );
171367
171531
  const uniqueAreas = orderSelection([...new Set(newAreas)], this.agent);
@@ -171370,7 +171534,7 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171370
171534
  (id) => !supportedAreaIds.includes(id)
171371
171535
  );
171372
171536
  if (invalidAreas.length > 0) {
171373
- logger235.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171537
+ logger236.warn(`Invalid area IDs requested: ${invalidAreas.join(", ")}`);
171374
171538
  return {
171375
171539
  status: ServiceArea3.SelectAreasStatus.UnsupportedArea,
171376
171540
  statusText: `Invalid area IDs: ${invalidAreas.join(", ")}`
@@ -171382,7 +171546,7 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171382
171546
  status: ServiceArea3.OperationalStatus.Pending
171383
171547
  }));
171384
171548
  this.state.currentArea = null;
171385
- logger235.info(
171549
+ logger236.info(
171386
171550
  `ServiceArea: Stored ${uniqueAreas.length} areas for cleaning: ${uniqueAreas.join(", ")}`
171387
171551
  );
171388
171552
  return {
@@ -171403,14 +171567,14 @@ var ServiceAreaServerWithMapsBase = class extends ServiceAreaWithMapsAndProgress
171403
171567
  ServiceAreaServerWithMapsBase2.State = State;
171404
171568
  })(ServiceAreaServerWithMapsBase || (ServiceAreaServerWithMapsBase = {}));
171405
171569
  function ServiceAreaServerWithMaps(initialState) {
171406
- logger235.info(
171570
+ logger236.info(
171407
171571
  `Creating ServiceAreaServer with Maps: ${initialState.supportedAreas.length} areas, ${initialState.supportedMaps.length} maps`
171408
171572
  );
171409
171573
  for (const map of initialState.supportedMaps) {
171410
171574
  const areaCount = initialState.supportedAreas.filter(
171411
171575
  (a) => a.mapId === map.mapId
171412
171576
  ).length;
171413
- logger235.info(` Map ${map.mapId}: "${map.name}" (${areaCount} areas)`);
171577
+ logger236.info(` Map ${map.mapId}: "${map.name}" (${areaCount} areas)`);
171414
171578
  }
171415
171579
  return ServiceAreaServerWithMapsBase.set({
171416
171580
  supportedAreas: initialState.supportedAreas,
@@ -171422,7 +171586,7 @@ function ServiceAreaServerWithMaps(initialState) {
171422
171586
  }
171423
171587
 
171424
171588
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-service-area-server.ts
171425
- var logger236 = Logger.get("VacuumServiceAreaServer");
171589
+ var logger237 = Logger.get("VacuumServiceAreaServer");
171426
171590
  function toAreaId(roomId) {
171427
171591
  if (typeof roomId === "number") {
171428
171592
  return roomId;
@@ -171501,13 +171665,13 @@ function createVacuumServiceAreaServer(attributes9, roomEntities, includeUnnamed
171501
171665
  let rooms;
171502
171666
  if (roomEntities && roomEntities.length > 0) {
171503
171667
  rooms = buttonEntitiesToRooms(roomEntities, attributes9);
171504
- logger236.info(
171668
+ logger237.info(
171505
171669
  `Using ${rooms.length} button entities as rooms: ${rooms.map((r) => r.name).join(", ")}`
171506
171670
  );
171507
171671
  } else {
171508
171672
  rooms = parseVacuumRooms(attributes9, includeUnnamedRooms);
171509
171673
  if (rooms.length > 0) {
171510
- logger236.info(
171674
+ logger237.info(
171511
171675
  `Using ${rooms.length} rooms from attributes: ${rooms.map((r) => r.name).join(", ")}`
171512
171676
  );
171513
171677
  }
@@ -171561,7 +171725,7 @@ function createCustomServiceAreaServer(customAreas) {
171561
171725
  landmarkInfo: null
171562
171726
  }
171563
171727
  }));
171564
- logger236.info(
171728
+ logger237.info(
171565
171729
  `Using ${customAreas.length} custom service areas: ${customAreas.map((a) => a.name).join(", ")}`
171566
171730
  );
171567
171731
  return ServiceAreaServer2({
@@ -171583,7 +171747,7 @@ function createCleanAreaServiceAreaServer(cleanAreaRooms) {
171583
171747
  landmarkInfo: null
171584
171748
  }
171585
171749
  }));
171586
- logger236.info(
171750
+ logger237.info(
171587
171751
  `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA: ${cleanAreaRooms.map((r) => r.name).join(", ")}`
171588
171752
  );
171589
171753
  return ServiceAreaServer2({
@@ -171619,11 +171783,11 @@ function getVacuumServiceAreas(attributes9, mapping) {
171619
171783
  }
171620
171784
 
171621
171785
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
171622
- var logger237 = Logger.get("VacuumRvcRunModeServer");
171786
+ var logger238 = Logger.get("VacuumRvcRunModeServer");
171623
171787
  function buildValetudoSegmentAction(vacuumEntityId, segmentIds, valetudoIdentifier) {
171624
171788
  const identifier = valetudoIdentifier || vacuumEntityId.replace(/^vacuum\.valetudo_/, "");
171625
171789
  const topic = `valetudo/${identifier}/MapSegmentationCapability/clean/set`;
171626
- logger237.info(
171790
+ logger238.info(
171627
171791
  `Valetudo: mqtt.publish to ${topic}, segments: ${segmentIds.join(", ")}`
171628
171792
  );
171629
171793
  return {
@@ -171728,14 +171892,14 @@ function mergeBatchData(areas) {
171728
171892
  function handleCustomServiceAreas(selectedAreas, customAreas, session) {
171729
171893
  const matched = selectedAreas.map((areaId) => ({ areaId, area: customAreas[areaId - 1] })).filter((m) => !!m.area);
171730
171894
  if (matched.length === 0) {
171731
- logger237.warn(
171895
+ logger238.warn(
171732
171896
  `Custom service areas: no match for selected IDs ${selectedAreas.join(", ")}`
171733
171897
  );
171734
171898
  return { action: "vacuum.start" };
171735
171899
  }
171736
171900
  const batchArea = matched.find(({ area }) => area.batchDispatch === true);
171737
171901
  if (batchArea) {
171738
- logger237.info(
171902
+ logger238.info(
171739
171903
  `Custom service areas (batch): single call for ${matched.length} room(s): ${matched.map(({ area }) => area.name).join(", ")}`
171740
171904
  );
171741
171905
  session.pendingDispatches = [];
@@ -171756,7 +171920,7 @@ function handleCustomServiceAreas(selectedAreas, customAreas, session) {
171756
171920
  }
171757
171921
  };
171758
171922
  }
171759
- logger237.info(
171923
+ logger238.info(
171760
171924
  `Custom service areas: ${matched.length} room(s) queued: ${matched.map(({ area }) => `${area.service} (${area.name})`).join(", ")}`
171761
171925
  );
171762
171926
  session.pendingDispatches = matched.slice(1).map(({ areaId, area }) => ({
@@ -171814,7 +171978,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171814
171978
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
171815
171979
  const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
171816
171980
  if (haAreaIds.length > 0) {
171817
- logger237.info(`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`);
171981
+ logger238.info(`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`);
171818
171982
  return {
171819
171983
  action: {
171820
171984
  action: "vacuum.clean_area",
@@ -171834,7 +171998,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171834
171998
  }
171835
171999
  }
171836
172000
  if (matched.length > 0) {
171837
- logger237.info(
172001
+ logger238.info(
171838
172002
  `Roborock: ${matched.length} room button(s) queued: ${matched.map((m) => m.entityId).join(", ")}`
171839
172003
  );
171840
172004
  return {
@@ -171869,12 +172033,12 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171869
172033
  }
171870
172034
  }
171871
172035
  if (roomIds.length > 0) {
171872
- logger237.info(`Starting cleaning with selected areas: ${roomIds.join(", ")}`);
172036
+ logger238.info(`Starting cleaning with selected areas: ${roomIds.join(", ")}`);
171873
172037
  if (isDreameVacuum(attributes9)) {
171874
172038
  if (targetMapName) {
171875
172039
  const vacName = entityId.replace("vacuum.", "");
171876
172040
  const selectedMapEntity = `select.${vacName}_selected_map`;
171877
- logger237.info(
172041
+ logger238.info(
171878
172042
  `Dreame multi-floor: switching to map "${targetMapName}" via ${selectedMapEntity}`
171879
172043
  );
171880
172044
  seam.callAction({
@@ -171902,7 +172066,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171902
172066
  }
171903
172067
  if (isEcovacsVacuum(attributes9)) {
171904
172068
  const roomIdStr = roomIds.join(",");
171905
- logger237.info(`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`);
172069
+ logger238.info(`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`);
171906
172070
  return {
171907
172071
  action: {
171908
172072
  action: "vacuum.send_command",
@@ -171914,7 +172078,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171914
172078
  pending: []
171915
172079
  };
171916
172080
  }
171917
- logger237.warn(
172081
+ logger238.warn(
171918
172082
  `Room cleaning via send_command not supported for this vacuum type. Rooms: ${roomIds.join(", ")}. Falling back to vacuum.start`
171919
172083
  );
171920
172084
  }
@@ -171923,7 +172087,7 @@ function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam)
171923
172087
  var vacuumRvcRunModeConfig = {
171924
172088
  getCurrentMode: (entity) => {
171925
172089
  const isCleaning = vacuumIsCleaning(entity.state);
171926
- logger237.debug(
172090
+ logger238.debug(
171927
172091
  `Vacuum state: "${entity.state}", isCleaning: ${isCleaning}, currentMode: ${isCleaning ? "Cleaning" : "Idle"}`
171928
172092
  );
171929
172093
  return isCleaning ? 1 /* Cleaning */ : 0 /* Idle */;
@@ -171962,7 +172126,7 @@ var vacuumRvcRunModeConfig = {
171962
172126
  }
171963
172127
  } catch {
171964
172128
  }
171965
- logger237.info("Starting regular cleaning (no areas selected)");
172129
+ logger238.info("Starting regular cleaning (no areas selected)");
171966
172130
  return { action: "vacuum.start" };
171967
172131
  },
171968
172132
  returnToBase: () => ({ action: "vacuum.return_to_base" }),
@@ -171977,7 +172141,7 @@ var vacuumRvcRunModeConfig = {
171977
172141
  const homeAssistant = agent.get(HomeAssistantEntityBehavior);
171978
172142
  const entity = homeAssistant.entity;
171979
172143
  const attributes9 = entity.state.attributes;
171980
- logger237.info(`cleanRoom called: roomMode=${roomMode}`);
172144
+ logger238.info(`cleanRoom called: roomMode=${roomMode}`);
171981
172145
  const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
171982
172146
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
171983
172147
  const sorted = [...cleanAreaRooms].sort(
@@ -171986,7 +172150,7 @@ var vacuumRvcRunModeConfig = {
171986
172150
  const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
171987
172151
  if (areaIndex >= 0 && areaIndex < sorted.length) {
171988
172152
  const area = sorted[areaIndex];
171989
- logger237.info(
172153
+ logger238.info(
171990
172154
  `cleanRoom: CLEAN_AREA "${area.name}" \u2192 vacuum.clean_area(${area.haAreaId})`
171991
172155
  );
171992
172156
  return {
@@ -172003,7 +172167,7 @@ var vacuumRvcRunModeConfig = {
172003
172167
  const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
172004
172168
  if (areaIndex >= 0 && areaIndex < sorted.length) {
172005
172169
  const area = sorted[areaIndex];
172006
- logger237.info(
172170
+ logger238.info(
172007
172171
  `cleanRoom: custom service area "${area.name}" \u2192 ${area.service}`
172008
172172
  );
172009
172173
  return {
@@ -172024,7 +172188,7 @@ var vacuumRvcRunModeConfig = {
172024
172188
  }
172025
172189
  const rooms = parseVacuumRooms(attributes9);
172026
172190
  const numericIdFromMode = getRoomIdFromMode(roomMode);
172027
- logger237.info(
172191
+ logger238.info(
172028
172192
  `cleanRoom: numericIdFromMode=${numericIdFromMode}, available rooms: ${JSON.stringify(rooms.map((r) => ({ id: r.id, name: r.name, modeValue: getRoomModeValue(r) })))}`
172029
172193
  );
172030
172194
  const room = rooms.find((r) => getRoomModeValue(r) === roomMode);
@@ -172034,7 +172198,7 @@ var vacuumRvcRunModeConfig = {
172034
172198
  if (room.mapName) {
172035
172199
  const vacuumName = vacuumEntityId.replace("vacuum.", "");
172036
172200
  const selectedMapEntity = `select.${vacuumName}_selected_map`;
172037
- logger237.info(
172201
+ logger238.info(
172038
172202
  `Dreame multi-floor: switching to map "${room.mapName}" via ${selectedMapEntity}`
172039
172203
  );
172040
172204
  homeAssistant.callAction({
@@ -172043,7 +172207,7 @@ var vacuumRvcRunModeConfig = {
172043
172207
  data: { option: room.mapName }
172044
172208
  });
172045
172209
  }
172046
- logger237.debug(
172210
+ logger238.debug(
172047
172211
  `Dreame vacuum detected, using dreame_vacuum.vacuum_clean_segment for room ${room.name} (commandId: ${commandId3}, id: ${room.id})`
172048
172212
  );
172049
172213
  return {
@@ -172054,7 +172218,7 @@ var vacuumRvcRunModeConfig = {
172054
172218
  };
172055
172219
  }
172056
172220
  if (isRoborockVacuum(attributes9) || isXiaomiMiotVacuum(attributes9)) {
172057
- logger237.debug(
172221
+ logger238.debug(
172058
172222
  `Using vacuum.send_command with app_segment_clean for room ${room.name} (commandId: ${commandId3}, id: ${room.id})`
172059
172223
  );
172060
172224
  return {
@@ -172067,7 +172231,7 @@ var vacuumRvcRunModeConfig = {
172067
172231
  }
172068
172232
  if (isEcovacsVacuum(attributes9)) {
172069
172233
  const roomIdStr = String(commandId3);
172070
- logger237.info(
172234
+ logger238.info(
172071
172235
  `Ecovacs vacuum: Using spot_area for room ${room.name} (id: ${roomIdStr})`
172072
172236
  );
172073
172237
  return {
@@ -172082,7 +172246,7 @@ var vacuumRvcRunModeConfig = {
172082
172246
  }
172083
172247
  };
172084
172248
  }
172085
- logger237.warn(
172249
+ logger238.warn(
172086
172250
  `Room cleaning via send_command not supported for this vacuum type. Room: ${room.name} (id=${commandId3}). Falling back to vacuum.start`
172087
172251
  );
172088
172252
  }
@@ -172099,20 +172263,20 @@ function createVacuumRvcRunModeServer(attributes9, includeUnnamedRooms = false,
172099
172263
  customAreas,
172100
172264
  disableRoomModes
172101
172265
  );
172102
- logger237.info(
172266
+ logger238.info(
172103
172267
  `Creating VacuumRvcRunModeServer with ${rooms.length} rooms, ${supportedModes2.length} total modes`
172104
172268
  );
172105
172269
  if (rooms.length > 0) {
172106
- logger237.info(`Rooms found: ${rooms.map((r) => r.name).join(", ")}`);
172270
+ logger238.info(`Rooms found: ${rooms.map((r) => r.name).join(", ")}`);
172107
172271
  }
172108
172272
  if (filteredCount > 0) {
172109
172273
  const filtered = allRooms.filter((r) => !rooms.some((x) => x.id === r.id));
172110
- logger237.info(
172274
+ logger238.info(
172111
172275
  `Filtered out ${filteredCount} unnamed room(s): ${filtered.map((r) => r.name).join(", ")}`
172112
172276
  );
172113
172277
  }
172114
172278
  if (allRooms.length === 0) {
172115
- logger237.debug(
172279
+ logger238.debug(
172116
172280
  `No rooms found. Attributes: rooms=${JSON.stringify(attributes9.rooms)}, segments=${JSON.stringify(attributes9.segments)}, room_list=${attributes9.room_list}`
172117
172281
  );
172118
172282
  }
@@ -172146,7 +172310,7 @@ function createCleanAreaRvcRunModeServer(cleanAreaRooms) {
172146
172310
  modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
172147
172311
  });
172148
172312
  }
172149
- logger237.info(
172313
+ logger238.info(
172150
172314
  `Creating CLEAN_AREA RvcRunModeServer with ${cleanAreaRooms.length} HA areas, ${modes.length} total modes`
172151
172315
  );
172152
172316
  return RvcRunModeServer2(vacuumRvcRunModeConfig, {
@@ -172236,7 +172400,7 @@ init_nodejs();
172236
172400
 
172237
172401
  // src/matter/behaviors/rvc-clean-mode-server.ts
172238
172402
  init_home_assistant_entity_behavior();
172239
- var logger238 = Logger.get("RvcCleanModeServerBase");
172403
+ var logger239 = Logger.get("RvcCleanModeServerBase");
172240
172404
  var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeServer {
172241
172405
  // Pending mode from a recent changeToMode command.
172242
172406
  // Prevents stale HA state (from a different entity like select.xxx)
@@ -172283,14 +172447,14 @@ var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeS
172283
172447
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
172284
172448
  const { newMode } = request;
172285
172449
  if (newMode !== this.state.currentMode && !this.state.supportedModes.some((m) => m.mode === newMode)) {
172286
- logger238.warn(`changeToMode(${newMode}) rejected: unsupported mode`);
172450
+ logger239.warn(`changeToMode(${newMode}) rejected: unsupported mode`);
172287
172451
  return {
172288
172452
  status: ModeBase3.ModeChangeStatus.UnsupportedMode,
172289
172453
  statusText: `Unsupported mode: ${newMode}`
172290
172454
  };
172291
172455
  }
172292
172456
  const modeLabel = this.state.supportedModes.find((m) => m.mode === newMode);
172293
- logger238.info(
172457
+ logger239.info(
172294
172458
  `changeToMode(${newMode}) "${modeLabel?.label ?? "unknown"}" for ${homeAssistant.entityId}`
172295
172459
  );
172296
172460
  this.pendingMode = newMode;
@@ -172298,7 +172462,7 @@ var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeS
172298
172462
  this.state.currentMode = newMode;
172299
172463
  const action = this.state.config.setCleanMode(newMode, this.agent);
172300
172464
  if (action) {
172301
- logger238.info(
172465
+ logger239.info(
172302
172466
  `changeToMode: dispatching action ${action.action} \u2192 ${action.target ?? homeAssistant.entityId}`
172303
172467
  );
172304
172468
  homeAssistant.callAction(action);
@@ -172331,7 +172495,7 @@ function RvcCleanModeServer2(config8, initialState) {
172331
172495
  }
172332
172496
 
172333
172497
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-clean-mode-server.ts
172334
- var logger239 = Logger.get("VacuumRvcCleanModeServer");
172498
+ var logger240 = Logger.get("VacuumRvcCleanModeServer");
172335
172499
  var MODE_VACUUM = 0;
172336
172500
  var MODE_VACUUM_AND_MOP = 1;
172337
172501
  var MODE_MOP = 2;
@@ -172601,7 +172765,7 @@ function findMatchingCleanOption(ct, availableOptions) {
172601
172765
  const match = availableOptions.find((o) => classifyCleanOption(o) === type);
172602
172766
  if (match) return match;
172603
172767
  }
172604
- logger239.warn(
172768
+ logger240.warn(
172605
172769
  `No match for ${CLEAN_TYPE_LABELS[ct]} in [${availableOptions.join(", ")}]`
172606
172770
  );
172607
172771
  return availableOptions[0];
@@ -172610,7 +172774,7 @@ function buildCleaningModeAction(targetCleanType, agent) {
172610
172774
  const selectEntityId = getCleaningModeSelectEntity(agent);
172611
172775
  const { options } = readSelectEntity(selectEntityId, agent);
172612
172776
  const optionToUse = findMatchingCleanOption(targetCleanType, options);
172613
- logger239.info(
172777
+ logger240.info(
172614
172778
  `Switching cleaning mode to: ${optionToUse} via ${selectEntityId}`
172615
172779
  );
172616
172780
  return {
@@ -172699,7 +172863,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172699
172863
  }
172700
172864
  }
172701
172865
  if (speedMode !== void 0) {
172702
- logger239.debug(
172866
+ logger240.debug(
172703
172867
  `Current mode: Vacuum + fan_speed="${speedState}" -> mode ${speedMode}`
172704
172868
  );
172705
172869
  return speedMode;
@@ -172720,7 +172884,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172720
172884
  }
172721
172885
  }
172722
172886
  if (mopMode !== void 0) {
172723
- logger239.debug(
172887
+ logger240.debug(
172724
172888
  `Current mode: Mop + intensity="${state}" -> mode ${mopMode}`
172725
172889
  );
172726
172890
  return mopMode;
@@ -172738,14 +172902,14 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172738
172902
  const homeAssistant = agent.get(HomeAssistantEntityBehavior);
172739
172903
  const vacuumEntityId = homeAssistant.entityId;
172740
172904
  const mapping = homeAssistant.state.mapping;
172741
- logger239.info(
172905
+ logger240.info(
172742
172906
  `setCleanMode(${mode}) for ${vacuumEntityId}, suctionEntity=${mapping?.suctionLevelEntity ?? "none"}, mopEntity=${mapping?.mopIntensityEntity ?? "none"}, fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])}, customTags=${JSON.stringify(customFanSpeedTags ?? {})}`
172743
172907
  );
172744
172908
  if (mopIntensityList && mopIntensityList.length > 0 && isMopIntensityMode(mode)) {
172745
172909
  const mopIndex = mode - MOP_INTENSITY_MODE_BASE;
172746
172910
  const mopName = mopIntensityList[mopIndex];
172747
172911
  if (!mopName) {
172748
- logger239.warn(`Invalid mop intensity mode index: ${mopIndex}`);
172912
+ logger240.warn(`Invalid mop intensity mode index: ${mopIndex}`);
172749
172913
  return void 0;
172750
172914
  }
172751
172915
  if (hasCleanTypes) {
@@ -172758,18 +172922,18 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172758
172922
  mapping.mopIntensityEntity,
172759
172923
  agent
172760
172924
  );
172761
- logger239.info(
172925
+ logger240.info(
172762
172926
  `Mop intensity entity ${mapping.mopIntensityEntity}: current="${state}", options=${JSON.stringify(options ?? [])}`
172763
172927
  );
172764
172928
  let option = matchMopIntensityOption(mopName, options);
172765
172929
  if (!option && options && mopIndex < options.length) {
172766
172930
  option = options[mopIndex];
172767
- logger239.info(
172931
+ logger240.info(
172768
172932
  `Positional match for mop "${mopName}" -> "${option}" (index ${mopIndex})`
172769
172933
  );
172770
172934
  }
172771
172935
  if (option) {
172772
- logger239.info(
172936
+ logger240.info(
172773
172937
  `Setting mop intensity to: ${option} via ${mapping.mopIntensityEntity}`
172774
172938
  );
172775
172939
  return {
@@ -172778,11 +172942,11 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172778
172942
  target: mapping.mopIntensityEntity
172779
172943
  };
172780
172944
  }
172781
- logger239.warn(
172945
+ logger240.warn(
172782
172946
  `No match for mop intensity "${mopName}" in options: [${(options ?? []).join(", ")}]`
172783
172947
  );
172784
172948
  } else {
172785
- logger239.warn(
172949
+ logger240.warn(
172786
172950
  `Mop intensity mode ${mode} requested but no mopIntensityEntity configured`
172787
172951
  );
172788
172952
  }
@@ -172792,7 +172956,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172792
172956
  const fanSpeedIndex = mode - FAN_SPEED_MODE_BASE;
172793
172957
  const fanSpeedName = fanSpeedList[fanSpeedIndex];
172794
172958
  if (!fanSpeedName) {
172795
- logger239.warn(`Invalid fan speed mode index: ${fanSpeedIndex}`);
172959
+ logger240.warn(`Invalid fan speed mode index: ${fanSpeedIndex}`);
172796
172960
  return void 0;
172797
172961
  }
172798
172962
  if (mapping?.suctionLevelEntity) {
@@ -172805,7 +172969,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172805
172969
  mapping.suctionLevelEntity,
172806
172970
  agent
172807
172971
  );
172808
- logger239.info(
172972
+ logger240.info(
172809
172973
  `Suction entity ${mapping.suctionLevelEntity}: current="${state}", options=${JSON.stringify(options ?? [])}`
172810
172974
  );
172811
172975
  let option = matchFanSpeedOption(
@@ -172815,12 +172979,12 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172815
172979
  );
172816
172980
  if (!option && options && fanSpeedIndex < options.length) {
172817
172981
  option = options[fanSpeedIndex];
172818
- logger239.info(
172982
+ logger240.info(
172819
172983
  `Positional match for fan "${fanSpeedName}" -> "${option}" (index ${fanSpeedIndex})`
172820
172984
  );
172821
172985
  }
172822
172986
  if (option) {
172823
- logger239.info(
172987
+ logger240.info(
172824
172988
  `Setting suction to: ${option} via ${mapping.suctionLevelEntity}`
172825
172989
  );
172826
172990
  return {
@@ -172829,7 +172993,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172829
172993
  target: mapping.suctionLevelEntity
172830
172994
  };
172831
172995
  }
172832
- logger239.warn(
172996
+ logger240.warn(
172833
172997
  `No match for fan speed "${fanSpeedName}" in suction options: [${(options ?? []).join(", ")}]`
172834
172998
  );
172835
172999
  return void 0;
@@ -172839,7 +173003,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172839
173003
  buildCleaningModeAction(0 /* Sweeping */, agent)
172840
173004
  );
172841
173005
  }
172842
- logger239.info(
173006
+ logger240.info(
172843
173007
  `Setting fan speed to: ${fanSpeedName} via vacuum.set_fan_speed`
172844
173008
  );
172845
173009
  return {
@@ -172849,7 +173013,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172849
173013
  };
172850
173014
  }
172851
173015
  if (!hasCleanTypes) {
172852
- logger239.debug(
173016
+ logger240.debug(
172853
173017
  `Ignoring cleaning type change (mode=${mode}): no cleaning mode entity`
172854
173018
  );
172855
173019
  return void 0;
@@ -172861,7 +173025,7 @@ function createCleanModeConfig(fanSpeedList, mopIntensityList, cleaningModeOptio
172861
173025
  agent
172862
173026
  );
172863
173027
  const optionToUse = findMatchingCleanOption(cleanType, availableOptions);
172864
- logger239.info(
173028
+ logger240.info(
172865
173029
  `Setting cleaning mode to: ${optionToUse} (mode=${mode}) via ${selectEntityId}`
172866
173030
  );
172867
173031
  return {
@@ -172879,10 +173043,10 @@ function createVacuumRvcCleanModeServer(_attributes, fanSpeedList, mopIntensityL
172879
173043
  cleaningModeOptions,
172880
173044
  customFanSpeedTags
172881
173045
  );
172882
- logger239.info(
173046
+ logger240.info(
172883
173047
  `Creating VacuumRvcCleanModeServer with ${supportedModes2.length} modes (fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])}, cleaningModeOptions=${JSON.stringify(cleaningModeOptions ?? [])}, customTags=${JSON.stringify(customFanSpeedTags ?? {})})`
172884
173048
  );
172885
- logger239.info(
173049
+ logger240.info(
172886
173050
  `Modes: ${supportedModes2.map((m) => `${m.mode}:${m.label}[${m.modeTags.map((t) => t.value).join(",")}]`).join(", ")}`
172887
173051
  );
172888
173052
  const initialState = {
@@ -172945,7 +173109,7 @@ function resolveMopIntensityList(mopIntensityEntity) {
172945
173109
  init_dist();
172946
173110
  init_esm();
172947
173111
  init_home_assistant_entity_behavior();
172948
- var logger240 = Logger.get("VacuumRvcOperationalStateServer");
173112
+ var logger241 = Logger.get("VacuumRvcOperationalStateServer");
172949
173113
  function batteryFromAttributes(attrs) {
172950
173114
  const raw = attrs.battery_level ?? attrs.battery;
172951
173115
  if (raw == null) return null;
@@ -172996,16 +173160,16 @@ function mapVacuumOperationalState(entity, batteryPercent = batteryFromAttribute
172996
173160
  operationalState = RvcOperationalState4.OperationalState.Error;
172997
173161
  } else {
172998
173162
  if (state.toLowerCase().includes("clean")) {
172999
- logger240.info(
173163
+ logger241.info(
173000
173164
  `Unknown vacuum state "${state}" contains 'clean', treating as Running`
173001
173165
  );
173002
173166
  operationalState = RvcOperationalState4.OperationalState.Running;
173003
173167
  } else {
173004
- logger240.info(`Unknown vacuum state "${state}", treating as Stopped`);
173168
+ logger241.info(`Unknown vacuum state "${state}", treating as Stopped`);
173005
173169
  operationalState = RvcOperationalState4.OperationalState.Stopped;
173006
173170
  }
173007
173171
  }
173008
- logger240.debug(
173172
+ logger241.debug(
173009
173173
  `Vacuum operationalState: "${state}" -> ${RvcOperationalState4.OperationalState[operationalState]}`
173010
173174
  );
173011
173175
  return operationalState;
@@ -173034,7 +173198,7 @@ var VacuumRvcOperationalStateServer = RvcOperationalStateServer2({
173034
173198
  });
173035
173199
 
173036
173200
  // src/matter/endpoints/legacy/vacuum/index.ts
173037
- var logger241 = Logger.get("VacuumDevice");
173201
+ var logger242 = Logger.get("VacuumDevice");
173038
173202
  var VacuumEndpointType = RoboticVacuumCleanerDevice.with(
173039
173203
  BasicInformationServer2,
173040
173204
  VacuumIdentifyServer,
@@ -173048,7 +173212,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173048
173212
  const entityId = homeAssistantEntity.entity.entity_id;
173049
173213
  const attributes9 = homeAssistantEntity.entity.state.attributes;
173050
173214
  const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
173051
- logger241.info(
173215
+ logger242.info(
173052
173216
  `Creating vacuum endpoint for ${entityId}, mapping: ${JSON.stringify(homeAssistantEntity.mapping ?? "none")}`
173053
173217
  );
173054
173218
  const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
@@ -173061,32 +173225,32 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173061
173225
  )
173062
173226
  ).set({ homeAssistantEntity });
173063
173227
  if (includeOnOff) {
173064
- logger241.info(`${entityId}: Adding OnOff cluster (vacuumOnOff flag enabled)`);
173228
+ logger242.info(`${entityId}: Adding OnOff cluster (vacuumOnOff flag enabled)`);
173065
173229
  device = device.with(VacuumOnOffServer);
173066
173230
  }
173067
173231
  device = device.with(VacuumPowerSourceServer);
173068
173232
  const roomEntities = homeAssistantEntity.mapping?.roomEntities;
173069
173233
  const rooms = parseVacuumRooms(attributes9);
173070
- logger241.info(
173234
+ logger242.info(
173071
173235
  `${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}, cleanAreaRooms=${cleanAreaRooms?.length ?? 0}`
173072
173236
  );
173073
173237
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
173074
- logger241.info(
173238
+ logger242.info(
173075
173239
  `${entityId}: Adding ServiceArea (${cleanAreaRooms.length} HA areas via CLEAN_AREA)`
173076
173240
  );
173077
173241
  device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
173078
173242
  } else if (customAreas && customAreas.length > 0) {
173079
- logger241.info(
173243
+ logger242.info(
173080
173244
  `${entityId}: Adding ServiceArea (${customAreas.length} custom areas)`
173081
173245
  );
173082
173246
  device = device.with(createCustomServiceAreaServer(customAreas));
173083
173247
  } else if (rooms.length > 0 || roomEntities && roomEntities.length > 0) {
173084
- logger241.info(`${entityId}: Adding ServiceArea (${rooms.length} rooms)`);
173248
+ logger242.info(`${entityId}: Adding ServiceArea (${rooms.length} rooms)`);
173085
173249
  device = device.with(
173086
173250
  createVacuumServiceAreaServer(attributes9, roomEntities)
173087
173251
  );
173088
173252
  } else {
173089
- logger241.info(`${entityId}: Adding ServiceArea (default single-area)`);
173253
+ logger242.info(`${entityId}: Adding ServiceArea (default single-area)`);
173090
173254
  device = device.with(createDefaultServiceAreaServer());
173091
173255
  }
173092
173256
  const fanSpeedList = resolveFanSpeedList(
@@ -173097,7 +173261,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173097
173261
  homeAssistantEntity.mapping?.mopIntensityEntity
173098
173262
  );
173099
173263
  if (cleaningModeOptions || fanSpeedList || mopIntensityList) {
173100
- logger241.info(
173264
+ logger242.info(
173101
173265
  `${entityId}: Adding RvcCleanMode (multi-mode, cleaningModeOptions=${JSON.stringify(cleaningModeOptions ?? [])}, fanSpeedList=${JSON.stringify(fanSpeedList ?? [])}, mopIntensityList=${JSON.stringify(mopIntensityList ?? [])})`
173102
173266
  );
173103
173267
  device = device.with(
@@ -173110,7 +173274,7 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
173110
173274
  )
173111
173275
  );
173112
173276
  } else {
173113
- logger241.info(`${entityId}: Adding RvcCleanMode (default single-mode)`);
173277
+ logger242.info(`${entityId}: Adding RvcCleanMode (default single-mode)`);
173114
173278
  device = device.with(createDefaultRvcCleanModeServer());
173115
173279
  }
173116
173280
  return device;
@@ -173276,7 +173440,7 @@ var WaterHeaterThermostatServer = ThermostatServer2(
173276
173440
  );
173277
173441
 
173278
173442
  // src/matter/endpoints/legacy/water-heater/index.ts
173279
- var logger242 = Logger.get("WaterHeaterDevice");
173443
+ var logger243 = Logger.get("WaterHeaterDevice");
173280
173444
  var WaterHeaterDeviceType = ThermostatDevice.with(
173281
173445
  BasicInformationServer2,
173282
173446
  IdentifyServer2,
@@ -173292,7 +173456,7 @@ function toMatterTemp2(value) {
173292
173456
  }
173293
173457
  function WaterHeaterDevice2(homeAssistantEntity) {
173294
173458
  const attributes9 = homeAssistantEntity.entity.state.attributes;
173295
- logger242.debug(
173459
+ logger243.debug(
173296
173460
  `Creating device for ${homeAssistantEntity.entity.entity_id}, min_temp=${attributes9.min_temp}, max_temp=${attributes9.max_temp}`
173297
173461
  );
173298
173462
  const minLimit = toMatterTemp2(attributes9.min_temp) ?? 0;
@@ -173378,6 +173542,7 @@ var WaterHeaterBoostMemoryBehavior = class extends Behavior {
173378
173542
  // src/matter/endpoints/legacy/water-heater/behaviors/water-heater-management-server.ts
173379
173543
  init_dist();
173380
173544
  init_esm();
173545
+ init_types2();
173381
173546
  init_home_assistant_entity_behavior();
173382
173547
 
173383
173548
  // src/matter/endpoints/legacy/water-heater/water-heater-modes.ts
@@ -173534,7 +173699,7 @@ function activeHeatSource(attributes9) {
173534
173699
  }
173535
173700
 
173536
173701
  // src/matter/endpoints/legacy/water-heater/behaviors/water-heater-management-server.ts
173537
- var logger243 = Logger.get("WaterHeaterManagementServer");
173702
+ var logger244 = Logger.get("WaterHeaterManagementServer");
173538
173703
  var MAX_TIMER_MS2 = 2147483647;
173539
173704
  var boostSessions = /* @__PURE__ */ new WeakMap();
173540
173705
  function clearBoostTimer(endpoint) {
@@ -173780,7 +173945,7 @@ var WaterHeaterManagementServerBase = class _WaterHeaterManagementServerBase ext
173780
173945
  armBoostTimer(durationSeconds) {
173781
173946
  const delay = durationSeconds * 1e3;
173782
173947
  if (!Number.isFinite(delay) || delay <= 0 || delay > MAX_TIMER_MS2) {
173783
- logger243.debug(
173948
+ logger244.debug(
173784
173949
  `Boost duration ${durationSeconds}s outside the timer range, boost stays active until CancelBoost`
173785
173950
  );
173786
173951
  return;
@@ -173794,7 +173959,7 @@ var WaterHeaterManagementServerBase = class _WaterHeaterManagementServerBase ext
173794
173959
  agent.get(_WaterHeaterManagementServerBase).endBoost({ restoreMode: true });
173795
173960
  });
173796
173961
  } catch (error) {
173797
- logger243.debug(
173962
+ logger244.debug(
173798
173963
  `Boost expiry failed (endpoint may be closing): ${error}`
173799
173964
  );
173800
173965
  }
@@ -173897,13 +174062,13 @@ function WaterHeaterModeServer2(mapping, initialMode) {
173897
174062
  }
173898
174063
 
173899
174064
  // src/matter/endpoints/legacy/water-heater/water-heater-management-device.ts
173900
- var logger244 = Logger.get("WaterHeaterManagementDevice");
174065
+ var logger245 = Logger.get("WaterHeaterManagementDevice");
173901
174066
  function WaterHeaterManagementDevice(homeAssistantEntity) {
173902
174067
  const entityState = homeAssistantEntity.entity.state;
173903
174068
  const attributes9 = entityState.attributes;
173904
174069
  const modeMapping = buildModeMapping(attributes9);
173905
174070
  const initialMode = currentMode(modeMapping, entityState.state, attributes9);
173906
- logger244.debug(
174071
+ logger245.debug(
173907
174072
  `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"}`
173908
174073
  );
173909
174074
  const minLimit = toMatterTemp2(attributes9.min_temp) ?? 0;
@@ -174174,7 +174339,7 @@ var matterDeviceTypeFactories = {
174174
174339
  };
174175
174340
 
174176
174341
  // src/matter/endpoints/composed/user-composed-endpoint.ts
174177
- var logger245 = Logger.get("UserComposedEndpoint");
174342
+ var logger246 = Logger.get("UserComposedEndpoint");
174178
174343
  function stripBasicInformation(type) {
174179
174344
  const behaviors = { ...type.behaviors };
174180
174345
  delete behaviors.bridgedDeviceBasicInformation;
@@ -174250,7 +174415,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174250
174415
  { vacuumOnOff: registry3.isVacuumOnOffEnabled() }
174251
174416
  );
174252
174417
  if (!primaryType) {
174253
- logger245.warn(
174418
+ logger246.warn(
174254
174419
  `Cannot create endpoint type for primary entity ${primaryEntityId}`
174255
174420
  );
174256
174421
  return void 0;
@@ -174265,7 +174430,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174265
174430
  if (!sub.entityId) continue;
174266
174431
  const subPayload = buildEntityPayload4(registry3, sub.entityId);
174267
174432
  if (!subPayload) {
174268
- logger245.warn(
174433
+ logger246.warn(
174269
174434
  `Cannot find state for composed sub-entity ${sub.entityId}, it does not exist in Home Assistant (removed or renamed?)`
174270
174435
  );
174271
174436
  continue;
@@ -174280,7 +174445,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174280
174445
  config8.areaName
174281
174446
  );
174282
174447
  if (!subType) {
174283
- logger245.warn(
174448
+ logger246.warn(
174284
174449
  `Cannot create endpoint type for composed sub-entity ${sub.entityId}`
174285
174450
  );
174286
174451
  continue;
@@ -174293,7 +174458,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174293
174458
  mappedIds.push(sub.entityId);
174294
174459
  }
174295
174460
  if (parts.length < 2) {
174296
- logger245.warn(
174461
+ logger246.warn(
174297
174462
  `User composed device ${primaryEntityId}: only ${parts.length} sub-endpoint(s), need at least 2 (primary + one sub-entity). Falling back to standalone.`
174298
174463
  );
174299
174464
  return void 0;
@@ -174317,7 +174482,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
174317
174482
  const labels = parts.map(
174318
174483
  (_, i) => i === 0 ? primaryEntityId.split(".")[0] : composedEntities[i - 1]?.entityId?.split(".")[0] ?? "?"
174319
174484
  ).join("+");
174320
- logger245.info(
174485
+ logger246.info(
174321
174486
  `Created user composed device ${primaryEntityId}: ${parts.length} sub-endpoint(s) [${labels}]`
174322
174487
  );
174323
174488
  return endpoint;
@@ -174423,7 +174588,7 @@ function asStandaloneEndpointType(type) {
174423
174588
  }
174424
174589
 
174425
174590
  // src/matter/endpoints/legacy/legacy-endpoint.ts
174426
- var logger246 = Logger.get("LegacyEndpoint");
174591
+ var logger247 = Logger.get("LegacyEndpoint");
174427
174592
  var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174428
174593
  constructor(type, entityId, customName, mappedEntityIds, throttleMs, endpointId, vacuumEffective) {
174429
174594
  super(type, entityId, customName, mappedEntityIds, endpointId);
@@ -174439,25 +174604,25 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174439
174604
  return;
174440
174605
  }
174441
174606
  if (registry3.isAutoBatteryMappingEnabled() && registry3.isBatteryEntityUsed(entityId)) {
174442
- logger246.debug(
174607
+ logger247.debug(
174443
174608
  `Skipping ${entityId} - already auto-assigned as battery to another device`
174444
174609
  );
174445
174610
  return;
174446
174611
  }
174447
174612
  if (registry3.isAutoHumidityMappingEnabled() && registry3.isHumidityEntityUsed(entityId)) {
174448
- logger246.debug(
174613
+ logger247.debug(
174449
174614
  `Skipping ${entityId} - already auto-assigned as humidity to a temperature sensor`
174450
174615
  );
174451
174616
  return;
174452
174617
  }
174453
174618
  if (registry3.isAutoPressureMappingEnabled() && registry3.isPressureEntityUsed(entityId)) {
174454
- logger246.debug(
174619
+ logger247.debug(
174455
174620
  `Skipping ${entityId} - already auto-assigned as pressure to a temperature sensor`
174456
174621
  );
174457
174622
  return;
174458
174623
  }
174459
174624
  if (registry3.isAutoComposedDevicesEnabled() && registry3.isComposedSubEntityUsed(entityId)) {
174460
- logger246.debug(
174625
+ logger247.debug(
174461
174626
  `Skipping ${entityId} - already consumed by a composed device`
174462
174627
  );
174463
174628
  return;
@@ -174477,7 +174642,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174477
174642
  humidityEntity: humidityEntityId
174478
174643
  };
174479
174644
  registry3.markHumidityEntityUsed(humidityEntityId);
174480
- logger246.debug(
174645
+ logger247.debug(
174481
174646
  `Auto-assigned humidity ${humidityEntityId} to ${entityId}`
174482
174647
  );
174483
174648
  }
@@ -174496,7 +174661,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174496
174661
  pressureEntity: pressureEntityId
174497
174662
  };
174498
174663
  registry3.markPressureEntityUsed(pressureEntityId);
174499
- logger246.debug(
174664
+ logger247.debug(
174500
174665
  `Auto-assigned pressure ${pressureEntityId} to ${entityId}`
174501
174666
  );
174502
174667
  }
@@ -174514,7 +174679,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174514
174679
  batteryEntity: batteryEntityId
174515
174680
  };
174516
174681
  registry3.markBatteryEntityUsed(batteryEntityId);
174517
- logger246.debug(
174682
+ logger247.debug(
174518
174683
  `Auto-assigned battery ${batteryEntityId} to ${entityId}`
174519
174684
  );
174520
174685
  }
@@ -174531,7 +174696,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174531
174696
  entityId: effectiveMapping?.entityId ?? entityId,
174532
174697
  faultEntity: faultEntityId
174533
174698
  };
174534
- logger246.debug(`Auto-assigned fault ${faultEntityId} to ${entityId}`);
174699
+ logger247.debug(`Auto-assigned fault ${faultEntityId} to ${entityId}`);
174535
174700
  }
174536
174701
  }
174537
174702
  if (!mapping?.powerEntity) {
@@ -174547,7 +174712,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174547
174712
  powerEntity: powerEntityId
174548
174713
  };
174549
174714
  registry3.markPowerEntityUsed(powerEntityId);
174550
- logger246.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
174715
+ logger247.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
174551
174716
  }
174552
174717
  }
174553
174718
  }
@@ -174564,7 +174729,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174564
174729
  energyEntity: energyEntityId
174565
174730
  };
174566
174731
  registry3.markEnergyEntityUsed(energyEntityId);
174567
- logger246.debug(
174732
+ logger247.debug(
174568
174733
  `Auto-assigned energy ${energyEntityId} to ${entityId}`
174569
174734
  );
174570
174735
  }
@@ -174580,7 +174745,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174580
174745
  entityId: effectiveMapping?.entityId ?? entityId,
174581
174746
  cleaningModeEntity: vacuumEntities.cleaningModeEntity
174582
174747
  };
174583
- logger246.info(
174748
+ logger247.info(
174584
174749
  `Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity} to ${entityId}`
174585
174750
  );
174586
174751
  }
@@ -174590,7 +174755,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174590
174755
  entityId: effectiveMapping?.entityId ?? entityId,
174591
174756
  suctionLevelEntity: vacuumEntities.suctionLevelEntity
174592
174757
  };
174593
- logger246.info(
174758
+ logger247.info(
174594
174759
  `Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity} to ${entityId}`
174595
174760
  );
174596
174761
  }
@@ -174600,7 +174765,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174600
174765
  entityId: effectiveMapping?.entityId ?? entityId,
174601
174766
  mopIntensityEntity: vacuumEntities.mopIntensityEntity
174602
174767
  };
174603
- logger246.info(
174768
+ logger247.info(
174604
174769
  `Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity} to ${entityId}`
174605
174770
  );
174606
174771
  }
@@ -174610,7 +174775,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174610
174775
  entityId: effectiveMapping?.entityId ?? entityId,
174611
174776
  currentRoomEntity: vacuumEntities.currentRoomEntity
174612
174777
  };
174613
- logger246.info(
174778
+ logger247.info(
174614
174779
  `Auto-assigned currentRoom ${vacuumEntities.currentRoomEntity} to ${entityId}`
174615
174780
  );
174616
174781
  }
@@ -174625,7 +174790,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174625
174790
  entityId: effectiveMapping?.entityId ?? entityId,
174626
174791
  cleanAreaRooms
174627
174792
  };
174628
- logger246.info(
174793
+ logger247.info(
174629
174794
  `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA for ${entityId}`
174630
174795
  );
174631
174796
  }
@@ -174646,7 +174811,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174646
174811
  rooms: roomsObj
174647
174812
  }
174648
174813
  };
174649
- logger246.debug(
174814
+ logger247.debug(
174650
174815
  `Auto-detected ${valetudoRooms.length} Valetudo segments for ${entityId}`
174651
174816
  );
174652
174817
  } else {
@@ -174663,7 +174828,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174663
174828
  rooms: roomsObj
174664
174829
  }
174665
174830
  };
174666
- logger246.debug(
174831
+ logger247.debug(
174667
174832
  `Auto-detected ${roborockRooms.length} Roborock rooms for ${entityId}`
174668
174833
  );
174669
174834
  }
@@ -174672,7 +174837,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174672
174837
  }
174673
174838
  }
174674
174839
  if (standalone && ((effectiveMapping?.composedEntities?.length ?? 0) > 0 || effectiveMapping?.climateExposeFan === true)) {
174675
- logger246.warn(
174840
+ logger247.warn(
174676
174841
  `Composed mappings are not supported in server mode, exposing ${entityId} as a flat standalone endpoint`
174677
174842
  );
174678
174843
  }
@@ -174691,7 +174856,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174691
174856
  if (composed) {
174692
174857
  return composed;
174693
174858
  }
174694
- logger246.warn(
174859
+ logger247.warn(
174695
174860
  `User composed device creation failed for ${entityId}, falling back to standalone`
174696
174861
  );
174697
174862
  }
@@ -174756,7 +174921,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174756
174921
  if (composed) {
174757
174922
  return composed;
174758
174923
  }
174759
- logger246.warn(
174924
+ logger247.warn(
174760
174925
  `Companion fan creation failed for ${entityId}, falling back to standalone`
174761
174926
  );
174762
174927
  }
@@ -174834,11 +174999,11 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
174834
174999
  }
174835
175000
  if (mappedChanged) {
174836
175001
  this.pendingMappedChange = true;
174837
- logger246.debug(
175002
+ logger247.debug(
174838
175003
  `Mapped entity change detected for ${this.entityId}, forcing update`
174839
175004
  );
174840
175005
  }
174841
- logger246.debug(
175006
+ logger247.debug(
174842
175007
  `State update received for ${this.entityId}: state=${state.state}`
174843
175008
  );
174844
175009
  this.lastState = state;
@@ -175059,12 +175224,14 @@ var CameraAvStreamServer = class extends Base4 {
175059
175224
  // src/plugins/builtin/camera/webrtc-provider-server.ts
175060
175225
  init_esm();
175061
175226
  init_esm7();
175227
+ init_types2();
175062
175228
  init_esm3();
175063
175229
 
175064
175230
  // src/plugins/builtin/camera/requestor-client.ts
175065
175231
  init_esm();
175232
+ init_types2();
175066
175233
  init_esm4();
175067
- var logger247 = Logger.get("CameraWebRtcRequestor");
175234
+ var logger248 = Logger.get("CameraWebRtcRequestor");
175068
175235
  var registry2 = /* @__PURE__ */ new Map();
175069
175236
  var pendingDeliveries = /* @__PURE__ */ new Map();
175070
175237
  var invokeTransport = defaultInvoke;
@@ -175098,19 +175265,19 @@ function deliverAnswerDeferred(sessionId, sdp, onGiveUp) {
175098
175265
  return;
175099
175266
  }
175100
175267
  if (await sendAnswer(sessionId, sdp)) {
175101
- logger247.info(`answer delivered for session ${sessionId}`);
175268
+ logger248.info(`answer delivered for session ${sessionId}`);
175102
175269
  return;
175103
175270
  }
175104
175271
  }
175105
175272
  if (registry2.get(sessionId) !== owner || pendingDeliveries.get(sessionId) !== timer) {
175106
175273
  return;
175107
175274
  }
175108
- logger247.info(
175275
+ logger248.info(
175109
175276
  `answer delivery failed for session ${sessionId}, giving up`
175110
175277
  );
175111
175278
  await onGiveUp();
175112
175279
  } catch (err) {
175113
- logger247.info(
175280
+ logger248.info(
175114
175281
  `answer delivery for session ${sessionId} threw: ${errText(err)}`
175115
175282
  );
175116
175283
  } finally {
@@ -175135,11 +175302,11 @@ function sendAnswer(sessionId, sdp) {
175135
175302
  async function invokeRequestor(sessionId, command, fields) {
175136
175303
  const registration = registry2.get(sessionId);
175137
175304
  if (!registration) {
175138
- logger247.info(`requestor ${command}: no session ${sessionId} registered`);
175305
+ logger248.info(`requestor ${command}: no session ${sessionId} registered`);
175139
175306
  return false;
175140
175307
  }
175141
175308
  if (registration.session.isClosed) {
175142
- logger247.info(`requestor ${command}: session ${sessionId} already closed`);
175309
+ logger248.info(`requestor ${command}: session ${sessionId} already closed`);
175143
175310
  return false;
175144
175311
  }
175145
175312
  const request = {
@@ -175151,7 +175318,7 @@ async function invokeRequestor(sessionId, command, fields) {
175151
175318
  try {
175152
175319
  return await invokeTransport({ registration, request });
175153
175320
  } catch (err) {
175154
- logger247.info(
175321
+ logger248.info(
175155
175322
  `requestor ${command} failed for session ${sessionId}: ${errText(err)}`
175156
175323
  );
175157
175324
  return false;
@@ -175186,7 +175353,7 @@ async function defaultInvoke({
175186
175353
  for (const entry of chunk) {
175187
175354
  if (entry.kind === "cmd-status") {
175188
175355
  if (entry.status !== Status2.Success) {
175189
- logger247.info(
175356
+ logger248.info(
175190
175357
  `requestor ${request.command} status ${entry.status} for session ${String(request.fields.webRtcSessionId)}`
175191
175358
  );
175192
175359
  return false;
@@ -175206,7 +175373,7 @@ function errText(err) {
175206
175373
  }
175207
175374
 
175208
175375
  // src/plugins/builtin/camera/webrtc-provider-server.ts
175209
- var logger248 = Logger.get("CameraWebRtc");
175376
+ var logger249 = Logger.get("CameraWebRtc");
175210
175377
  var nextGlobalSessionId = 0;
175211
175378
  function mintSessionId() {
175212
175379
  for (let i = 0; i <= 65534; i++) {
@@ -175220,14 +175387,14 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175220
175387
  solicitOffer(request) {
175221
175388
  const id = mintSessionId();
175222
175389
  this.trackSession(id, request.streamUsage, request.originatingEndpointId);
175223
- logger248.info(
175390
+ logger249.info(
175224
175391
  `solicitOffer session=${id} (${this.state.entityId}), deferred offer`
175225
175392
  );
175226
175393
  void this.state.bridge.startSession(id, this.state.entityId, {
175227
175394
  iceServers: request.iceServers,
175228
175395
  iceTransportPolicy: request.iceTransportPolicy
175229
175396
  }).catch(
175230
- (err) => logger248.info(
175397
+ (err) => logger249.info(
175231
175398
  `solicitOffer startSession failed for ${this.state.entityId}: ${errText2(err)}`
175232
175399
  )
175233
175400
  );
@@ -175235,7 +175402,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175235
175402
  }
175236
175403
  async provideOffer(request) {
175237
175404
  const id = request.webRtcSessionId ?? mintSessionId();
175238
- logger248.info(
175405
+ logger249.info(
175239
175406
  `provideOffer entry: entityId=${this.state.entityId} session=${id} (sdp ${request.sdp.length} chars)`
175240
175407
  );
175241
175408
  if (request.webRtcSessionId == null) {
@@ -175269,7 +175436,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175269
175436
  );
175270
175437
  } catch (err) {
175271
175438
  const message = errText2(err);
175272
- logger248.info(
175439
+ logger249.info(
175273
175440
  `provideOffer failed for ${this.state.entityId} session=${id}: ${message}`
175274
175441
  );
175275
175442
  unregisterRequestor(id);
@@ -175281,7 +175448,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175281
175448
  StatusCode.Failure
175282
175449
  );
175283
175450
  }
175284
- logger248.info(
175451
+ logger249.info(
175285
175452
  `provideOffer answer computed for ${this.state.entityId} session=${id} (${answerSdp.length} chars); delivering via requestor`
175286
175453
  );
175287
175454
  const bridge = this.state.bridge;
@@ -175300,7 +175467,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175300
175467
  return { webRtcSessionId: id };
175301
175468
  }
175302
175469
  provideAnswer(request) {
175303
- logger248.info(
175470
+ logger249.info(
175304
175471
  `provideAnswer session=${request.webRtcSessionId} (sdp ${request.sdp.length} chars, ${this.state.entityId})`
175305
175472
  );
175306
175473
  return this.state.bridge.acceptControllerAnswer(
@@ -175309,7 +175476,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175309
175476
  );
175310
175477
  }
175311
175478
  async provideIceCandidates(request) {
175312
- logger248.info(
175479
+ logger249.info(
175313
175480
  `provideIceCandidates session=${request.webRtcSessionId}: ${request.iceCandidates.length} candidate(s) (${this.state.entityId})`
175314
175481
  );
175315
175482
  for (const c of request.iceCandidates) {
@@ -175322,7 +175489,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
175322
175489
  }
175323
175490
  }
175324
175491
  async endSession(request) {
175325
- logger248.info(
175492
+ logger249.info(
175326
175493
  `endSession session=${request.webRtcSessionId} (${this.state.entityId})`
175327
175494
  );
175328
175495
  await this.state.bridge.endSession(request.webRtcSessionId);
@@ -175443,7 +175610,7 @@ import {
175443
175610
  createLongLivedTokenAuth as createLongLivedTokenAuth2
175444
175611
  } from "home-assistant-js-websocket";
175445
175612
  import { RTCPeerConnection } from "werift";
175446
- var logger249 = Logger.get("CameraWebRtc");
175613
+ var logger250 = Logger.get("CameraWebRtc");
175447
175614
  var DEFAULT_HA_WEBRTC_TIMEOUT_MS = 15e3;
175448
175615
  var haWebRtcTimeoutMs = DEFAULT_HA_WEBRTC_TIMEOUT_MS;
175449
175616
  var WebRtcBridge = class {
@@ -175490,7 +175657,7 @@ var WebRtcBridge = class {
175490
175657
  const haOffer = await haPeer.createOffer();
175491
175658
  await haPeer.setLocalDescription(haOffer);
175492
175659
  const haOfferSdp = this.localSdp(haPeer);
175493
- logger249.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175660
+ logger250.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175494
175661
  const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
175495
175662
  entityId,
175496
175663
  haOfferSdp,
@@ -175513,12 +175680,12 @@ var WebRtcBridge = class {
175513
175680
  const controllerOffer = await controllerPeer.createOffer();
175514
175681
  await controllerPeer.setLocalDescription(controllerOffer);
175515
175682
  const sdp = this.localSdp(controllerPeer);
175516
- logger249.info(
175683
+ logger250.info(
175517
175684
  `controller offer created for ${entityId} (${sdp.length} chars)`
175518
175685
  );
175519
175686
  return { sdp, iceCandidates };
175520
175687
  } catch (err) {
175521
- logger249.info(`startSession failed for ${entityId}: ${errText3(err)}`);
175688
+ logger250.info(`startSession failed for ${entityId}: ${errText3(err)}`);
175522
175689
  await this.endSession(matterSessionId);
175523
175690
  throw err;
175524
175691
  }
@@ -175548,7 +175715,7 @@ var WebRtcBridge = class {
175548
175715
  const haOffer = await haPeer.createOffer();
175549
175716
  await haPeer.setLocalDescription(haOffer);
175550
175717
  const haOfferSdp = this.localSdp(haPeer);
175551
- logger249.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175718
+ logger250.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
175552
175719
  const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
175553
175720
  entityId,
175554
175721
  haOfferSdp,
@@ -175567,12 +175734,12 @@ var WebRtcBridge = class {
175567
175734
  const controllerAnswer = await controllerPeer.createAnswer();
175568
175735
  await controllerPeer.setLocalDescription(controllerAnswer);
175569
175736
  const answerSdp = this.localSdp(controllerPeer);
175570
- logger249.info(
175737
+ logger250.info(
175571
175738
  `controller answer created for ${entityId} (${answerSdp.length} chars)`
175572
175739
  );
175573
175740
  return answerSdp;
175574
175741
  } catch (err) {
175575
- logger249.info(
175742
+ logger250.info(
175576
175743
  `acceptControllerOffer failed for ${entityId}: ${errText3(err)}`
175577
175744
  );
175578
175745
  await this.endSession(matterSessionId);
@@ -175583,14 +175750,14 @@ var WebRtcBridge = class {
175583
175750
  async acceptControllerAnswer(matterSessionId, sdp) {
175584
175751
  const session = this.sessions.get(matterSessionId);
175585
175752
  if (!session) return;
175586
- logger249.debug(`controller answer applied for ${session.entityId}`);
175753
+ logger250.debug(`controller answer applied for ${session.entityId}`);
175587
175754
  await session.controllerPeer.setRemoteDescription({ type: "answer", sdp });
175588
175755
  }
175589
175756
  /** Add a remote ICE candidate from the Matter controller. */
175590
175757
  async addControllerIceCandidate(matterSessionId, candidate, sdpMid, sdpMLineIndex) {
175591
175758
  const session = this.sessions.get(matterSessionId);
175592
175759
  if (!session) return;
175593
- logger249.debug(
175760
+ logger250.debug(
175594
175761
  `controller ICE candidate for ${session.entityId}: ${candidate}`
175595
175762
  );
175596
175763
  await session.controllerPeer.addIceCandidate({
@@ -175604,12 +175771,12 @@ var WebRtcBridge = class {
175604
175771
  async closeExistingPeers(matterSessionId) {
175605
175772
  const prior = this.sessions.get(matterSessionId);
175606
175773
  if (!prior) return;
175607
- logger249.info(
175774
+ logger250.info(
175608
175775
  `replacing session ${matterSessionId} (${prior.entityId}), closing prior peers`
175609
175776
  );
175610
175777
  if (prior.haUnsubscribe) {
175611
175778
  await Promise.resolve(prior.haUnsubscribe()).catch(
175612
- (err) => logger249.debug(`HA unsubscribe failed: ${errText3(err)}`)
175779
+ (err) => logger250.debug(`HA unsubscribe failed: ${errText3(err)}`)
175613
175780
  );
175614
175781
  }
175615
175782
  await prior.haPeer.close().catch(() => {
@@ -175622,11 +175789,11 @@ var WebRtcBridge = class {
175622
175789
  async endSession(matterSessionId) {
175623
175790
  const session = this.sessions.get(matterSessionId);
175624
175791
  if (!session) return;
175625
- logger249.info(`ending session ${matterSessionId} (${session.entityId})`);
175792
+ logger250.info(`ending session ${matterSessionId} (${session.entityId})`);
175626
175793
  this.sessions.delete(matterSessionId);
175627
175794
  if (session.haUnsubscribe) {
175628
175795
  await Promise.resolve(session.haUnsubscribe()).catch(
175629
- (err) => logger249.debug(`HA unsubscribe failed: ${errText3(err)}`)
175796
+ (err) => logger250.debug(`HA unsubscribe failed: ${errText3(err)}`)
175630
175797
  );
175631
175798
  }
175632
175799
  await session.haPeer.close().catch(() => {
@@ -175656,11 +175823,11 @@ var WebRtcBridge = class {
175656
175823
  headers: { Authorization: `Bearer ${this.config.haToken}` }
175657
175824
  });
175658
175825
  } catch (err) {
175659
- logger249.info(`snapshot fetch failed for ${entityId}: ${errText3(err)}`);
175826
+ logger250.info(`snapshot fetch failed for ${entityId}: ${errText3(err)}`);
175660
175827
  throw err;
175661
175828
  }
175662
175829
  if (!res.ok) {
175663
- logger249.info(
175830
+ logger250.info(
175664
175831
  `snapshot fetch failed for ${entityId}: camera_proxy ${res.status}`
175665
175832
  );
175666
175833
  throw new Error(`HA camera_proxy ${entityId}: ${res.status}`);
@@ -175677,10 +175844,10 @@ var WebRtcBridge = class {
175677
175844
  // Forward every track HA sends into the matching pre-added controller sender.
175678
175845
  forwardHaTracks(haPeer, senders, entityId) {
175679
175846
  haPeer.onTrack.subscribe((track) => {
175680
- logger249.info(`onTrack ${track.kind} from HA (${entityId})`);
175847
+ logger250.info(`onTrack ${track.kind} from HA (${entityId})`);
175681
175848
  const transceiver = senders.get(track.kind);
175682
175849
  if (!transceiver) {
175683
- logger249.info(
175850
+ logger250.info(
175684
175851
  `no controller transceiver for ${track.kind} (${entityId})`
175685
175852
  );
175686
175853
  return;
@@ -175689,7 +175856,7 @@ var WebRtcBridge = class {
175689
175856
  track.onReceiveRtp.subscribe((rtp) => {
175690
175857
  if (!firstLogged) {
175691
175858
  firstLogged = true;
175692
- logger249.info(`first RTP forwarded for ${track.kind} (${entityId})`);
175859
+ logger250.info(`first RTP forwarded for ${track.kind} (${entityId})`);
175693
175860
  }
175694
175861
  transceiver.sender.sendRtp(rtp);
175695
175862
  });
@@ -175698,10 +175865,10 @@ var WebRtcBridge = class {
175698
175865
  // Log connection/ice state transitions (these events fire on change only).
175699
175866
  wireStateLogging(peer, label, entityId) {
175700
175867
  peer.connectionStateChange.subscribe(
175701
- (s) => logger249.info(`${label} connectionState=${s} (${entityId})`)
175868
+ (s) => logger250.info(`${label} connectionState=${s} (${entityId})`)
175702
175869
  );
175703
175870
  peer.iceConnectionStateChange.subscribe(
175704
- (s) => logger249.info(`${label} iceConnectionState=${s} (${entityId})`)
175871
+ (s) => logger250.info(`${label} iceConnectionState=${s} (${entityId})`)
175705
175872
  );
175706
175873
  }
175707
175874
  // Map the Matter ICE struct onto werift's config. Only the controller peer
@@ -175715,11 +175882,11 @@ var WebRtcBridge = class {
175715
175882
  }))
175716
175883
  );
175717
175884
  if (iceServers.length === 0) {
175718
- logger249.info(`controller peer using default ICE servers (${entityId})`);
175885
+ logger250.info(`controller peer using default ICE servers (${entityId})`);
175719
175886
  return void 0;
175720
175887
  }
175721
175888
  const policy = ice?.iceTransportPolicy === "relay" || ice?.iceTransportPolicy === "all" ? ice.iceTransportPolicy : void 0;
175722
- logger249.info(
175889
+ logger250.info(
175723
175890
  `controller peer using ${iceServers.length} controller ICE server(s)${policy ? ` policy=${policy}` : ""} (${entityId})`
175724
175891
  );
175725
175892
  return policy ? { iceServers, iceTransportPolicy: policy } : { iceServers };
@@ -175733,13 +175900,13 @@ var WebRtcBridge = class {
175733
175900
  feedHaCandidate(entityId, haPeer, candidate) {
175734
175901
  const value = candidate?.candidate;
175735
175902
  if (!value) return;
175736
- logger249.debug(`HA ICE candidate for ${entityId}: ${value}`);
175903
+ logger250.debug(`HA ICE candidate for ${entityId}: ${value}`);
175737
175904
  void haPeer.addIceCandidate({
175738
175905
  candidate: value,
175739
175906
  sdpMid: candidate?.sdpMid ?? void 0,
175740
175907
  sdpMLineIndex: candidate?.sdpMLineIndex ?? void 0
175741
175908
  }).catch(
175742
- (e) => logger249.debug(
175909
+ (e) => logger250.debug(
175743
175910
  `HA addIceCandidate failed for ${entityId}: ${errText3(e)}`
175744
175911
  )
175745
175912
  );
@@ -175768,7 +175935,7 @@ var WebRtcBridge = class {
175768
175935
  reject(err);
175769
175936
  });
175770
175937
  timer = setTimeout(() => {
175771
- logger249.info(
175938
+ logger250.info(
175772
175939
  `HA WebRTC timed out after ${haWebRtcTimeoutMs}ms for ${entityId}`
175773
175940
  );
175774
175941
  fail(
@@ -175786,7 +175953,7 @@ var WebRtcBridge = class {
175786
175953
  if (msg.session_id) sessionId = msg.session_id;
175787
175954
  const ans = msg.answer;
175788
175955
  settle(() => {
175789
- logger249.info(
175956
+ logger250.info(
175790
175957
  `HA answer received for ${entityId} (${ans.length} chars)`
175791
175958
  );
175792
175959
  resolve11(ans);
@@ -175795,7 +175962,7 @@ var WebRtcBridge = class {
175795
175962
  break;
175796
175963
  case "error": {
175797
175964
  const detail = msg.message ?? msg.code ?? "unknown error";
175798
- logger249.info(`HA WebRTC error for ${entityId}: ${detail}`);
175965
+ logger250.info(`HA WebRTC error for ${entityId}: ${detail}`);
175799
175966
  fail(new Error(`HA WebRTC error: ${detail}`));
175800
175967
  break;
175801
175968
  }
@@ -175969,7 +176136,7 @@ var CameraPlugin = class {
175969
176136
  // src/plugins/builtin/security/security-plugin.ts
175970
176137
  init_esm();
175971
176138
  import {
175972
- callService as callService2,
176139
+ callService,
175973
176140
  createConnection as createConnection4,
175974
176141
  createLongLivedTokenAuth as createLongLivedTokenAuth3
175975
176142
  } from "home-assistant-js-websocket";
@@ -176821,7 +176988,7 @@ var SecurityPlugin = class {
176821
176988
  let timer;
176822
176989
  try {
176823
176990
  await Promise.race([
176824
- callService2(connection, domain, service, void 0, {
176991
+ callService(connection, domain, service, void 0, {
176825
176992
  entity_id: entityId
176826
176993
  }),
176827
176994
  new Promise((_, reject) => {
@@ -176952,7 +177119,7 @@ import {
176952
177119
  getCollection
176953
177120
  } from "home-assistant-js-websocket";
176954
177121
  import { atLeastHaVersion } from "home-assistant-js-websocket/dist/util.js";
176955
- var logger250 = Logger.get("SubscribeEntities");
177122
+ var logger251 = Logger.get("SubscribeEntities");
176956
177123
  function processEvent(store, updates) {
176957
177124
  const state = { ...store.state };
176958
177125
  if (updates.a) {
@@ -176978,7 +177145,7 @@ function processEvent(store, updates) {
176978
177145
  for (const entityId in updates.c) {
176979
177146
  let entityState = state[entityId];
176980
177147
  if (!entityState) {
176981
- logger250.warn("Received state update for unknown entity", entityId);
177148
+ logger251.warn("Received state update for unknown entity", entityId);
176982
177149
  continue;
176983
177150
  }
176984
177151
  entityState = { ...entityState };
@@ -177067,7 +177234,7 @@ var subscribeEntities = (conn, onChange, entityIds) => {
177067
177234
  // src/services/bridges/entity-isolation-service.ts
177068
177235
  init_esm();
177069
177236
  init_diagnostic_event_bus();
177070
- var logger251 = Logger.get("EntityIsolation");
177237
+ var logger252 = Logger.get("EntityIsolation");
177071
177238
  var EntityIsolationServiceImpl = class {
177072
177239
  isolatedEntities = /* @__PURE__ */ new Map();
177073
177240
  isolationCallbacks = /* @__PURE__ */ new Map();
@@ -177135,13 +177302,13 @@ var EntityIsolationServiceImpl = class {
177135
177302
  }
177136
177303
  const parsed = this.parseEndpointPath(msg);
177137
177304
  if (!parsed) {
177138
- logger251.warn("Could not parse entity from error:", msg);
177305
+ logger252.warn("Could not parse entity from error:", msg);
177139
177306
  return false;
177140
177307
  }
177141
177308
  const { bridgeId, entityName } = parsed;
177142
177309
  const callback = this.isolationCallbacks.get(bridgeId);
177143
177310
  if (!callback) {
177144
- logger251.warn(
177311
+ logger252.warn(
177145
177312
  `No isolation callback registered for bridge ${bridgeId}, entity: ${entityName}`
177146
177313
  );
177147
177314
  return false;
@@ -177156,7 +177323,7 @@ var EntityIsolationServiceImpl = class {
177156
177323
  reason,
177157
177324
  failedAt: (/* @__PURE__ */ new Date()).toISOString()
177158
177325
  });
177159
- logger251.warn(
177326
+ logger252.warn(
177160
177327
  `Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
177161
177328
  );
177162
177329
  diagnosticEventBus.emit("entity_error", `Entity isolated: ${entityName}`, {
@@ -177168,7 +177335,7 @@ var EntityIsolationServiceImpl = class {
177168
177335
  await callback(entityName);
177169
177336
  return true;
177170
177337
  } catch (e) {
177171
- logger251.error(`Failed to isolate entity ${entityName}:`, e);
177338
+ logger252.error(`Failed to isolate entity ${entityName}:`, e);
177172
177339
  return false;
177173
177340
  }
177174
177341
  }
@@ -177249,6 +177416,9 @@ var BridgeEndpointManager = class extends Service {
177249
177416
  // entityId -> first absence stamp (grace window)
177250
177417
  pendingRemovals = /* @__PURE__ */ new Map();
177251
177418
  removalRecheckTimer = null;
177419
+ // Bumped on every stop, so a refresh that was already running cannot arm a
177420
+ // timer on a bridge that has since stopped (#438).
177421
+ lifecycle = 0;
177252
177422
  pluginEndpoints = /* @__PURE__ */ new Map();
177253
177423
  pluginStateUpdating = /* @__PURE__ */ new Set();
177254
177424
  pluginListeners = /* @__PURE__ */ new Map();
@@ -177281,11 +177451,36 @@ var BridgeEndpointManager = class extends Service {
177281
177451
  );
177282
177452
  return;
177283
177453
  }
177454
+ const supplied = device.endpointType;
177284
177455
  const initialState = {};
177285
177456
  for (const cluster2 of device.clusters) {
177457
+ if (cluster2.clusterId === "pluginDevice" && supplied.behaviors?.pluginDevice == null && supplied.behaviors?.bridgedDeviceBasicInformation == null) {
177458
+ this.log.warn(
177459
+ `Plugin "${pluginName}": device "${device.id}" declares a "pluginDevice" cluster without owning that behavior, ignoring it`
177460
+ );
177461
+ continue;
177462
+ }
177286
177463
  initialState[cluster2.clusterId] = cluster2.attributes;
177287
177464
  }
177288
- const base = device.endpointType;
177465
+ const hasOwnIdentity = supplied.behaviors?.bridgedDeviceBasicInformation != null;
177466
+ const ownsPluginDevice = supplied.behaviors?.pluginDevice != null;
177467
+ const mutable = typeof supplied.with === "function" && typeof supplied.set === "function";
177468
+ if (!mutable && Object.keys(initialState).length > 0) {
177469
+ this.log.warn(
177470
+ `Plugin "${pluginName}": endpointType for device "${device.id}" cannot take its cluster config, skipping it`
177471
+ );
177472
+ return;
177473
+ }
177474
+ if (!hasOwnIdentity && (!mutable || ownsPluginDevice)) {
177475
+ this.log.warn(
177476
+ `Plugin "${pluginName}": device "${device.id}" mounts without BridgedDeviceBasicInformation, controllers may not show it`
177477
+ );
177478
+ }
177479
+ let base = device.endpointType;
177480
+ if (mutable && !hasOwnIdentity && !ownsPluginDevice) {
177481
+ base = base.with(PluginBasicInformationServer, PluginDeviceBehavior);
177482
+ initialState.pluginDevice = { device, pluginName };
177483
+ }
177289
177484
  endpoint = new Endpoint(
177290
177485
  Object.keys(initialState).length > 0 ? base.set(initialState) : base,
177291
177486
  { id: `plugin_${device.id}` }
@@ -177533,11 +177728,12 @@ var BridgeEndpointManager = class extends Service {
177533
177728
  this.removalRecheckTimer = null;
177534
177729
  }
177535
177730
  if (this.pendingRemovals.size === 0) return;
177731
+ const lifecycle = this.lifecycle;
177536
177732
  this.removalRecheckTimer = setTimeout(() => {
177537
177733
  this.removalRecheckTimer = null;
177538
177734
  this.refreshDevices().catch((e) => {
177539
177735
  this.log.warn("Endpoint removal recheck failed:", e);
177540
- this.scheduleRemovalRecheck();
177736
+ if (lifecycle === this.lifecycle) this.scheduleRemovalRecheck();
177541
177737
  });
177542
177738
  }, ENDPOINT_REMOVAL_GRACE_MS + 5e3);
177543
177739
  }
@@ -177608,6 +177804,7 @@ var BridgeEndpointManager = class extends Service {
177608
177804
  }
177609
177805
  stopObserving() {
177610
177806
  this.observingRequested = false;
177807
+ this.lifecycle++;
177611
177808
  this.clearSubscription();
177612
177809
  if (this.removalRecheckTimer) {
177613
177810
  clearTimeout(this.removalRecheckTimer);
@@ -177616,6 +177813,7 @@ var BridgeEndpointManager = class extends Service {
177616
177813
  }
177617
177814
  async refreshDevices() {
177618
177815
  this.registry.refresh();
177816
+ const lifecycle = this.lifecycle;
177619
177817
  const endpoints = [...this.root.parts].filter(hasEntityIdentity).filter((p) => !(p instanceof VacuumAreaSwitchEndpoint));
177620
177818
  const fullEntities = this.registry.fullEntities;
177621
177819
  if (!this.client.haRunning || Object.keys(fullEntities).length === 0) {
@@ -177789,7 +177987,9 @@ var BridgeEndpointManager = class extends Service {
177789
177987
  }
177790
177988
  }
177791
177989
  }
177792
- this.scheduleRemovalRecheck();
177990
+ if (lifecycle === this.lifecycle) {
177991
+ this.scheduleRemovalRecheck();
177992
+ }
177793
177993
  let memoryLimitReached = false;
177794
177994
  for (const entityId of this.entityIds) {
177795
177995
  if (!memoryLimitReached && isHeapUnderPressure()) {
@@ -178088,7 +178288,7 @@ var BridgeEndpointManager = class extends Service {
178088
178288
  init_dist();
178089
178289
  init_esm();
178090
178290
  init_send_ha_message();
178091
- import { callService as callService3 } from "home-assistant-js-websocket";
178291
+ import { callService as callService2 } from "home-assistant-js-websocket";
178092
178292
  import { keys as keys2, pickBy, values as values3 } from "lodash-es";
178093
178293
  var BridgeRegistry = class _BridgeRegistry {
178094
178294
  constructor(registry3, dataProvider, client) {
@@ -178478,7 +178678,7 @@ var BridgeRegistry = class _BridgeRegistry {
178478
178678
  async resolveRoborockRooms(entityId) {
178479
178679
  if (!this.client) return [];
178480
178680
  try {
178481
- const raw = await callService3(
178681
+ const raw = await callService2(
178482
178682
  this.client.connection,
178483
178683
  "roborock",
178484
178684
  "get_maps",
@@ -178857,6 +179057,7 @@ function hashAreaId(areaId) {
178857
179057
  init_dist();
178858
179058
  init_esm7();
178859
179059
  import * as os10 from "node:os";
179060
+ init_protocol3();
178860
179061
  init_diagnostic_event_bus();
178861
179062
  var imWrapMarker2 = /* @__PURE__ */ Symbol("hamh.wedgeImWrap");
178862
179063
  var commandMessageTypes2 = [
@@ -178872,11 +179073,11 @@ function makeWarmStartState(state, now = (/* @__PURE__ */ new Date()).toISOStrin
178872
179073
  return { ...state, last_updated: now };
178873
179074
  }
178874
179075
  var ServerModeBridge = class {
178875
- constructor(logger254, dataProvider, endpointManager, server) {
179076
+ constructor(logger255, dataProvider, endpointManager, server) {
178876
179077
  this.dataProvider = dataProvider;
178877
179078
  this.endpointManager = endpointManager;
178878
179079
  this.server = server;
178879
- this.log = logger254.get(`ServerModeBridge / ${dataProvider.id}`);
179080
+ this.log = logger255.get(`ServerModeBridge / ${dataProvider.id}`);
178880
179081
  }
178881
179082
  dataProvider;
178882
179083
  endpointManager;
@@ -179256,12 +179457,18 @@ ${e?.toString()}`);
179256
179457
  for (const s of [...sessionManager.sessions]) {
179257
179458
  if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
179258
179459
  this.log.info(
179259
- `Closing stale session ${s.id} (peer ${s.peerNodeId}, 0 subs), replaced by session ${newSession.id}`
179460
+ `Session ${s.id} (peer ${s.peerNodeId}, 0 subs) replaced by session ${newSession.id}, closing it once it goes quiet`
179461
+ );
179462
+ const staleId = s.id;
179463
+ const armed = this.staleSessionTimers.get(staleId);
179464
+ if (armed) clearTimeout(armed);
179465
+ this.staleSessionTimers.set(
179466
+ staleId,
179467
+ setTimeout(() => {
179468
+ this.staleSessionTimers.delete(staleId);
179469
+ this.closeStaleSession(staleId, PRIMING_GRACE_MS);
179470
+ }, replacedSessionTimeoutMs(this.dataProvider.featureFlags))
179260
179471
  );
179261
- s.initiateForceClose({
179262
- cause: new Error("stale session replaced by new session")
179263
- }).catch(() => {
179264
- });
179265
179472
  }
179266
179473
  }
179267
179474
  const quietWindowMs = staleSessionQuietWindowMs(
@@ -179297,6 +179504,11 @@ ${e?.toString()}`);
179297
179504
  };
179298
179505
  this.sessionDeletedHandler = (session) => {
179299
179506
  this.sessionStartedAt.delete(session.id);
179507
+ const armed = this.staleSessionTimers.get(session.id);
179508
+ if (armed) {
179509
+ clearTimeout(armed);
179510
+ this.staleSessionTimers.delete(session.id);
179511
+ }
179300
179512
  const sessions = [...sessionManager.sessions];
179301
179513
  this.log.warn(
179302
179514
  `Session closed: id=${session.id} peer=${session.peerNodeId} | remaining sessions=${sessions.length}`
@@ -179405,7 +179617,7 @@ ${e?.toString()}`);
179405
179617
  );
179406
179618
  });
179407
179619
  }
179408
- closeStaleSession(sessionId) {
179620
+ closeStaleSession(sessionId, minQuietMs = 0) {
179409
179621
  try {
179410
179622
  const sessionManager = this.server.env.get(SessionManager);
179411
179623
  for (const s of [...sessionManager.sessions]) {
@@ -179415,7 +179627,10 @@ ${e?.toString()}`);
179415
179627
  const idleSec = Math.round((Date.now() - s.timestamp) / 1e3);
179416
179628
  if (!staleSessionShouldClose(
179417
179629
  s,
179418
- staleSessionQuietWindowMs(this.dataProvider.featureFlags)
179630
+ Math.max(
179631
+ staleSessionQuietWindowMs(this.dataProvider.featureFlags),
179632
+ minQuietMs
179633
+ )
179419
179634
  )) {
179420
179635
  this.log.info(
179421
179636
  `Keeping session ${s.id} (peer ${s.peerNodeId}, 0 subs, last traffic ${idleSec}s ago)`
@@ -179424,7 +179639,7 @@ ${e?.toString()}`);
179424
179639
  sessionId,
179425
179640
  setTimeout(() => {
179426
179641
  this.staleSessionTimers.delete(sessionId);
179427
- this.closeStaleSession(sessionId);
179642
+ this.closeStaleSession(sessionId, minQuietMs);
179428
179643
  }, deadSessionTimeoutMs(this.dataProvider.featureFlags))
179429
179644
  );
179430
179645
  break;
@@ -179453,6 +179668,9 @@ ${e?.toString()}`);
179453
179668
  if (s.isClosing || s.subscriptions.size > 0) {
179454
179669
  continue;
179455
179670
  }
179671
+ if (this.staleSessionTimers.has(s.id)) {
179672
+ continue;
179673
+ }
179456
179674
  const idleSec = Math.round((Date.now() - s.timestamp) / 1e3);
179457
179675
  if (!staleSessionShouldClose(
179458
179676
  s,
@@ -180018,7 +180236,7 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
180018
180236
  }
180019
180237
 
180020
180238
  // src/matter/endpoints/server-mode-vacuum-endpoint.ts
180021
- var logger252 = Logger.get("ServerModeVacuumEndpoint");
180239
+ var logger253 = Logger.get("ServerModeVacuumEndpoint");
180022
180240
  var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEndpoint {
180023
180241
  static async create(registry3, entityId, mapping, endpointId) {
180024
180242
  const deviceRegistry = registry3.deviceOf(entityId);
@@ -180031,7 +180249,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180031
180249
  if (mapping?.disableBatteryMapping && mapping.batteryEntity) {
180032
180250
  effectiveMapping = { ...mapping, batteryEntity: void 0 };
180033
180251
  }
180034
- logger252.info(
180252
+ logger253.info(
180035
180253
  `${entityId}: device_id=${entity.device_id}, manualBattery=${mapping?.batteryEntity ?? "none"}`
180036
180254
  );
180037
180255
  if (entity.device_id) {
@@ -180046,15 +180264,15 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180046
180264
  batteryEntity: batteryEntityId
180047
180265
  };
180048
180266
  registry3.markBatteryEntityUsed(batteryEntityId);
180049
- logger252.info(`${entityId}: Auto-assigned battery ${batteryEntityId}`);
180267
+ logger253.info(`${entityId}: Auto-assigned battery ${batteryEntityId}`);
180050
180268
  } else {
180051
180269
  const attrs = state.attributes;
180052
180270
  if (attrs.battery_level != null || attrs.battery != null) {
180053
- logger252.info(
180271
+ logger253.info(
180054
180272
  `${entityId}: No battery entity found, using battery attribute from vacuum state`
180055
180273
  );
180056
180274
  } else {
180057
- logger252.warn(
180275
+ logger253.warn(
180058
180276
  `${entityId}: No battery entity found for device ${entity.device_id}`
180059
180277
  );
180060
180278
  }
@@ -180069,7 +180287,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180069
180287
  entityId: effectiveMapping?.entityId ?? entityId,
180070
180288
  cleaningModeEntity: vacuumEntities.cleaningModeEntity
180071
180289
  };
180072
- logger252.info(
180290
+ logger253.info(
180073
180291
  `${entityId}: Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity}`
180074
180292
  );
180075
180293
  }
@@ -180079,7 +180297,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180079
180297
  entityId: effectiveMapping?.entityId ?? entityId,
180080
180298
  suctionLevelEntity: vacuumEntities.suctionLevelEntity
180081
180299
  };
180082
- logger252.info(
180300
+ logger253.info(
180083
180301
  `${entityId}: Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity}`
180084
180302
  );
180085
180303
  }
@@ -180089,7 +180307,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180089
180307
  entityId: effectiveMapping?.entityId ?? entityId,
180090
180308
  mopIntensityEntity: vacuumEntities.mopIntensityEntity
180091
180309
  };
180092
- logger252.info(
180310
+ logger253.info(
180093
180311
  `${entityId}: Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity}`
180094
180312
  );
180095
180313
  }
@@ -180099,7 +180317,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180099
180317
  entityId: effectiveMapping?.entityId ?? entityId,
180100
180318
  currentRoomEntity: vacuumEntities.currentRoomEntity
180101
180319
  };
180102
- logger252.info(
180320
+ logger253.info(
180103
180321
  `${entityId}: Auto-assigned currentRoom ${vacuumEntities.currentRoomEntity}`
180104
180322
  );
180105
180323
  }
@@ -180114,7 +180332,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180114
180332
  entityId: effectiveMapping?.entityId ?? entityId,
180115
180333
  cleanAreaRooms
180116
180334
  };
180117
- logger252.info(
180335
+ logger253.info(
180118
180336
  `${entityId}: Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA`
180119
180337
  );
180120
180338
  }
@@ -180135,7 +180353,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180135
180353
  rooms: roomsObj
180136
180354
  }
180137
180355
  };
180138
- logger252.info(
180356
+ logger253.info(
180139
180357
  `${entityId}: Auto-detected ${valetudoRooms.length} Valetudo segments`
180140
180358
  );
180141
180359
  } else {
@@ -180152,14 +180370,14 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180152
180370
  rooms: roomsObj
180153
180371
  }
180154
180372
  };
180155
- logger252.info(
180373
+ logger253.info(
180156
180374
  `${entityId}: Auto-detected ${roborockRooms.length} Roborock rooms`
180157
180375
  );
180158
180376
  }
180159
180377
  }
180160
180378
  }
180161
180379
  } else {
180162
- logger252.warn(`${entityId}: No device_id, cannot auto-assign battery`);
180380
+ logger253.warn(`${entityId}: No device_id, cannot auto-assign battery`);
180163
180381
  }
180164
180382
  const payload = {
180165
180383
  entity_id: entityId,
@@ -180232,11 +180450,11 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
180232
180450
  }
180233
180451
  if (mappedChanged) {
180234
180452
  this.pendingMappedChange = true;
180235
- logger252.debug(
180453
+ logger253.debug(
180236
180454
  `Mapped entity change detected for ${this.entityId}, forcing update`
180237
180455
  );
180238
180456
  }
180239
- logger252.debug(
180457
+ logger253.debug(
180240
180458
  `State update received for ${this.entityId}: state=${state.state}`
180241
180459
  );
180242
180460
  this.lastState = state;
@@ -180307,6 +180525,12 @@ var ServerModeEndpointManager = class extends Service {
180307
180525
  // device (#438).
180308
180526
  pendingRemovals = /* @__PURE__ */ new Map();
180309
180527
  removalRecheckTimer = null;
180528
+ // endpoint id -> entity that closed but may come back (disable). Its number
180529
+ // is still parked, so nobody else may mount on that id (#438).
180530
+ parkedEndpointIds = /* @__PURE__ */ new Map();
180531
+ // Bumped on every stop, so a refresh that was already running cannot arm a
180532
+ // timer on a bridge that has since stopped.
180533
+ lifecycle = 0;
180310
180534
  get failedEntities() {
180311
180535
  return this._failedEntities;
180312
180536
  }
@@ -180369,6 +180593,7 @@ var ServerModeEndpointManager = class extends Service {
180369
180593
  }
180370
180594
  stopObserving() {
180371
180595
  this.observingRequested = false;
180596
+ this.lifecycle++;
180372
180597
  this.clearSubscription();
180373
180598
  if (this.removalRecheckTimer) {
180374
180599
  clearTimeout(this.removalRecheckTimer);
@@ -180426,11 +180651,12 @@ var ServerModeEndpointManager = class extends Service {
180426
180651
  this.removalRecheckTimer = null;
180427
180652
  }
180428
180653
  if (this.pendingRemovals.size === 0) return;
180654
+ const lifecycle = this.lifecycle;
180429
180655
  this.removalRecheckTimer = setTimeout(() => {
180430
180656
  this.removalRecheckTimer = null;
180431
180657
  this.refreshDevices().catch((e) => {
180432
180658
  this.log.warn("Endpoint removal recheck failed:", e);
180433
- this.scheduleRemovalRecheck();
180659
+ if (lifecycle === this.lifecycle) this.scheduleRemovalRecheck();
180434
180660
  });
180435
180661
  }, ENDPOINT_REMOVAL_GRACE_MS + 5e3);
180436
180662
  }
@@ -180450,6 +180676,7 @@ var ServerModeEndpointManager = class extends Service {
180450
180676
  }
180451
180677
  async refreshDevices() {
180452
180678
  this.registry.refresh();
180679
+ const lifecycle = this.lifecycle;
180453
180680
  const fullEntities = this.registry.fullEntities;
180454
180681
  try {
180455
180682
  if (!this.client.haRunning || Object.keys(fullEntities).length === 0) {
@@ -180539,6 +180766,17 @@ var ServerModeEndpointManager = class extends Service {
180539
180766
  const confirmedRemoved = this.removableAfterGrace(genuinelyRemoved);
180540
180767
  let structureChanged = removed.length > genuinelyRemoved.length || confirmedRemoved.length > 0;
180541
180768
  await this.removeEndpoints(confirmedRemoved);
180769
+ for (const entityId of orderedIds) {
180770
+ const mapping = this.getEntityMapping(entityId);
180771
+ if (!mapping?.disabled) continue;
180772
+ for (const [id, owner] of this.parkedEndpointIds) {
180773
+ if (owner === entityId) this.parkedEndpointIds.delete(id);
180774
+ }
180775
+ this.parkedEndpointIds.set(
180776
+ this.endpoints.get(entityId)?.endpoint.id ?? resolvedByEntity.get(entityId)?.endpointId ?? createEndpointId(entityId, mapping.customName),
180777
+ entityId
180778
+ );
180779
+ }
180542
180780
  for (const entityId of orderedIds) {
180543
180781
  const mapping = this.getEntityMapping(entityId);
180544
180782
  if (mapping?.disabled) {
@@ -180585,10 +180823,11 @@ var ServerModeEndpointManager = class extends Service {
180585
180823
  const collision = [...this.endpoints.entries()].find(
180586
180824
  ([, entry]) => entry.endpoint.id === endpointId
180587
180825
  );
180588
- if (collision) {
180826
+ const parkedBy = this.parkedEndpointIds.get(endpointId);
180827
+ if (collision || parkedBy != null && parkedBy !== entityId) {
180589
180828
  this._failedEntities.push({
180590
180829
  entityId,
180591
- reason: `Endpoint id collides with ${collision[0]}. Set distinct custom names.`
180830
+ reason: `Endpoint id collides with ${collision?.[0] ?? parkedBy}. Set distinct custom names.`
180592
180831
  });
180593
180832
  continue;
180594
180833
  }
@@ -180626,6 +180865,11 @@ var ServerModeEndpointManager = class extends Service {
180626
180865
  }
180627
180866
  await this.serverNode.addDevice(endpoint);
180628
180867
  this.endpoints.set(entityId, { endpoint, fingerprint });
180868
+ for (const [id, owner] of this.parkedEndpointIds) {
180869
+ if (id === endpointId || owner === entityId) {
180870
+ this.parkedEndpointIds.delete(id);
180871
+ }
180872
+ }
180629
180873
  structureChanged = true;
180630
180874
  this.log.info(`Server mode: Added device ${entityId}`);
180631
180875
  } catch (e) {
@@ -180645,7 +180889,9 @@ var ServerModeEndpointManager = class extends Service {
180645
180889
  }
180646
180890
  }
180647
180891
  } finally {
180648
- this.scheduleRemovalRecheck();
180892
+ if (lifecycle === this.lifecycle) {
180893
+ this.scheduleRemovalRecheck();
180894
+ }
180649
180895
  if (this.observingRequested) {
180650
180896
  this.startObserving();
180651
180897
  }
@@ -180887,10 +181133,10 @@ var BridgeEnvironmentFactory = class extends BridgeFactory {
180887
181133
  // src/core/ioc/app-environment.ts
180888
181134
  var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180889
181135
  constructor(rootEnv, options) {
180890
- const logger254 = rootEnv.get(LoggerService);
181136
+ const logger255 = rootEnv.get(LoggerService);
180891
181137
  super({
180892
181138
  id: "App",
180893
- log: logger254.get("AppContainer"),
181139
+ log: logger255.get("AppContainer"),
180894
181140
  parent: rootEnv
180895
181141
  });
180896
181142
  this.options = options;
@@ -180904,8 +181150,8 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180904
181150
  }
180905
181151
  construction;
180906
181152
  async init() {
180907
- const logger254 = this.get(LoggerService);
180908
- this.set(LoggerService, logger254);
181153
+ const logger255 = this.get(LoggerService);
181154
+ this.set(LoggerService, logger255);
180909
181155
  this.set(AppStorage, new AppStorage(await this.load(StorageService)));
180910
181156
  this.set(BridgeStorage, new BridgeStorage(await this.load(AppStorage)));
180911
181157
  this.set(
@@ -180926,7 +181172,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180926
181172
  );
180927
181173
  this.set(
180928
181174
  HomeAssistantClient,
180929
- new HomeAssistantClient(logger254, this.options.homeAssistant)
181175
+ new HomeAssistantClient(logger255, this.options.homeAssistant)
180930
181176
  );
180931
181177
  this.set(
180932
181178
  HomeAssistantConfig,
@@ -180934,7 +181180,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180934
181180
  );
180935
181181
  this.set(
180936
181182
  HomeAssistantActions,
180937
- new HomeAssistantActions(logger254, await this.load(HomeAssistantClient))
181183
+ new HomeAssistantActions(logger255, await this.load(HomeAssistantClient))
180938
181184
  );
180939
181185
  this.set(
180940
181186
  HomeAssistantRegistry,
@@ -180970,7 +181216,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180970
181216
  this.set(
180971
181217
  WebApi,
180972
181218
  new WebApi(
180973
- logger254,
181219
+ logger255,
180974
181220
  await this.load(BridgeService),
180975
181221
  await this.load(HomeAssistantClient),
180976
181222
  await this.load(HomeAssistantRegistry),
@@ -180991,7 +181237,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
180991
181237
 
180992
181238
  // src/matter/patches/patch-level-control-tlv.ts
180993
181239
  init_esm();
180994
- var logger253 = Logger.get("PatchLevelControlTlv");
181240
+ var logger254 = Logger.get("PatchLevelControlTlv");
180995
181241
  var optionalFieldModels = /* @__PURE__ */ new WeakSet();
180996
181242
  var fieldModelMandatoryGetterPatched = false;
180997
181243
  function patchLevelControlTlv() {
@@ -181047,11 +181293,11 @@ function patchLevelControlTlv() {
181047
181293
  patched++;
181048
181294
  }
181049
181295
  if (patched > 0) {
181050
- logger253.info(
181296
+ logger254.info(
181051
181297
  `Patched ${patched} LevelControl TLV schema(s): transitionTime is now optional (Google Home compatibility)`
181052
181298
  );
181053
181299
  } else {
181054
- logger253.warn(
181300
+ logger254.warn(
181055
181301
  "Failed to patch LevelControl TLV schemas, field definitions not found. Google Home brightness adjustment may not work.",
181056
181302
  {
181057
181303
  moveToLevel: describeFields(
@@ -182793,6 +183039,7 @@ export {
182793
183039
  @matter/main/dist/esm/version.js:
182794
183040
  @matter/main/dist/esm/index.js:
182795
183041
  @matter/main/dist/esm/protocol.js:
183042
+ @matter/main/dist/esm/types.js:
182796
183043
  @matter/types/dist/esm/clusters/fan-control.js:
182797
183044
  @matter/node/dist/esm/behaviors/fan-control/FanControlBehavior.js:
182798
183045
  @matter/node/dist/esm/behaviors/fan-control/FanControlServer.js:
@@ -183223,7 +183470,6 @@ export {
183223
183470
  @matter/node/dist/esm/devices/index.js:
183224
183471
  @matter/main/dist/esm/devices.js:
183225
183472
  @matter/main/dist/esm/node.js:
183226
- @matter/main/dist/esm/types.js:
183227
183473
  @matter/node/dist/esm/behaviors/account-login/index.js:
183228
183474
  @matter/node/dist/esm/behaviors/actions/ActionsClient.js:
183229
183475
  @matter/node/dist/esm/behaviors/actions/index.js:
@@ -183448,6 +183694,13 @@ export {
183448
183694
  @matter/node/dist/esm/behaviors/zone-management/index.js:
183449
183695
  @matter/node/dist/esm/behaviors/index.js:
183450
183696
  @matter/main/dist/esm/behaviors.js:
183697
+ @matter/types/dist/esm/clusters/alarm-base.js:
183698
+ @matter/types/dist/esm/clusters/concentration-measurement.js:
183699
+ @matter/types/dist/esm/clusters/label.js:
183700
+ @matter/types/dist/esm/clusters/resource-monitoring.js:
183701
+ @matter/types/dist/esm/clusters/web-rtc-transport-definitions.js:
183702
+ @matter/types/dist/esm/clusters/index.js:
183703
+ @matter/main/dist/esm/clusters.js:
183451
183704
  @matter/node/dist/esm/endpoints/base.js:
183452
183705
  @matter/node/dist/esm/endpoints/bridged-node.js:
183453
183706
  @matter/node/dist/esm/endpoints/device-energy-management.js:
@@ -183459,13 +183712,6 @@ export {
183459
183712
  @matter/node/dist/esm/endpoints/secondary-network-interface.js:
183460
183713
  @matter/node/dist/esm/endpoints/index.js:
183461
183714
  @matter/main/dist/esm/endpoints.js:
183462
- @matter/types/dist/esm/clusters/alarm-base.js:
183463
- @matter/types/dist/esm/clusters/concentration-measurement.js:
183464
- @matter/types/dist/esm/clusters/label.js:
183465
- @matter/types/dist/esm/clusters/resource-monitoring.js:
183466
- @matter/types/dist/esm/clusters/web-rtc-transport-definitions.js:
183467
- @matter/types/dist/esm/clusters/index.js:
183468
- @matter/main/dist/esm/clusters.js:
183469
183715
  @matter/main/dist/esm/model.js:
183470
183716
  @matter/main/dist/esm/forwards/clusters/level-control.js:
183471
183717
  @matter/main/dist/esm/forwards/behaviors/boolean-state.js: