@riddix/hamh 2.1.0-alpha.568 → 2.1.0-alpha.570

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.
@@ -145651,6 +145651,53 @@ var init_service = __esm({
145651
145651
  }
145652
145652
  });
145653
145653
 
145654
+ // src/services/diagnostics/diagnostic-event-bus.ts
145655
+ var MAX_EVENTS, eventCounter, DiagnosticEventBusImpl, diagnosticEventBus;
145656
+ var init_diagnostic_event_bus = __esm({
145657
+ "src/services/diagnostics/diagnostic-event-bus.ts"() {
145658
+ "use strict";
145659
+ MAX_EVENTS = 500;
145660
+ eventCounter = 0;
145661
+ DiagnosticEventBusImpl = class {
145662
+ events = [];
145663
+ listeners = /* @__PURE__ */ new Set();
145664
+ emit(type, message, options) {
145665
+ const event3 = {
145666
+ id: `diag_${++eventCounter}`,
145667
+ timestamp: Date.now(),
145668
+ type,
145669
+ message,
145670
+ bridgeId: options?.bridgeId,
145671
+ bridgeName: options?.bridgeName,
145672
+ entityId: options?.entityId,
145673
+ details: options?.details
145674
+ };
145675
+ this.events.push(event3);
145676
+ if (this.events.length > MAX_EVENTS) {
145677
+ this.events = this.events.slice(-MAX_EVENTS);
145678
+ }
145679
+ for (const listener of this.listeners) {
145680
+ try {
145681
+ listener(event3);
145682
+ } catch {
145683
+ }
145684
+ }
145685
+ }
145686
+ subscribe(listener) {
145687
+ this.listeners.add(listener);
145688
+ return () => this.listeners.delete(listener);
145689
+ }
145690
+ getRecentEvents(limit = 100) {
145691
+ return this.events.slice(-limit);
145692
+ }
145693
+ get totalEventCount() {
145694
+ return eventCounter;
145695
+ }
145696
+ };
145697
+ diagnosticEventBus = new DiagnosticEventBusImpl();
145698
+ }
145699
+ });
145700
+
145654
145701
  // ../common/dist/bridge-data.js
145655
145702
  var BridgeStatus;
145656
145703
  var init_bridge_data = __esm({
@@ -146135,6 +146182,7 @@ var init_binary_sensor = __esm({
146135
146182
  BinarySensorDeviceClass2["Power"] = "power";
146136
146183
  BinarySensorDeviceClass2["Presence"] = "presence";
146137
146184
  BinarySensorDeviceClass2["Problem"] = "problem";
146185
+ BinarySensorDeviceClass2["Rain"] = "rain";
146138
146186
  BinarySensorDeviceClass2["Running"] = "running";
146139
146187
  BinarySensorDeviceClass2["Safety"] = "safety";
146140
146188
  BinarySensorDeviceClass2["Smoke"] = "smoke";
@@ -146359,6 +146407,7 @@ var init_sensor = __esm({
146359
146407
  SensorDeviceClass2["precipitation"] = "precipitation";
146360
146408
  SensorDeviceClass2["precipitation_intensity"] = "precipitation_intensity";
146361
146409
  SensorDeviceClass2["pressure"] = "pressure";
146410
+ SensorDeviceClass2["radon"] = "radon";
146362
146411
  SensorDeviceClass2["reactive_power"] = "reactive_power";
146363
146412
  SensorDeviceClass2["signal_strength"] = "signal_strength";
146364
146413
  SensorDeviceClass2["sound_pressure"] = "sound_pressure";
@@ -147214,6 +147263,7 @@ var init_home_assistant_actions = __esm({
147214
147263
  init_service();
147215
147264
  init_debounce_context();
147216
147265
  init_retry();
147266
+ init_diagnostic_event_bus();
147217
147267
  defaultConfig = {
147218
147268
  retryAttempts: 3,
147219
147269
  retryBaseDelayMs: 100,
@@ -147253,6 +147303,14 @@ var init_home_assistant_actions = __esm({
147253
147303
  `Failed to call action '${action}' for entity '${entity_id ?? "(no target)"}': ${errorMsg}`
147254
147304
  );
147255
147305
  });
147306
+ diagnosticEventBus.emit(
147307
+ "command_received",
147308
+ `Action ${action} for ${entity_id ?? "(no target)"}`,
147309
+ {
147310
+ entityId: entity_id ?? calls[0].entityId,
147311
+ details: { action, data }
147312
+ }
147313
+ );
147256
147314
  this.fireEvent("hamh_action", {
147257
147315
  entity_id: entity_id ?? calls[0].entityId,
147258
147316
  action,
@@ -147460,49 +147518,7 @@ import nocache from "nocache";
147460
147518
 
147461
147519
  // src/services/diagnostics/diagnostic-service.ts
147462
147520
  init_esm();
147463
-
147464
- // src/services/diagnostics/diagnostic-event-bus.ts
147465
- var MAX_EVENTS = 500;
147466
- var eventCounter = 0;
147467
- var DiagnosticEventBusImpl = class {
147468
- events = [];
147469
- listeners = /* @__PURE__ */ new Set();
147470
- emit(type, message, options) {
147471
- const event3 = {
147472
- id: `diag_${++eventCounter}`,
147473
- timestamp: Date.now(),
147474
- type,
147475
- message,
147476
- bridgeId: options?.bridgeId,
147477
- bridgeName: options?.bridgeName,
147478
- entityId: options?.entityId,
147479
- details: options?.details
147480
- };
147481
- this.events.push(event3);
147482
- if (this.events.length > MAX_EVENTS) {
147483
- this.events = this.events.slice(-MAX_EVENTS);
147484
- }
147485
- for (const listener of this.listeners) {
147486
- try {
147487
- listener(event3);
147488
- } catch {
147489
- }
147490
- }
147491
- }
147492
- subscribe(listener) {
147493
- this.listeners.add(listener);
147494
- return () => this.listeners.delete(listener);
147495
- }
147496
- getRecentEvents(limit = 100) {
147497
- return this.events.slice(-limit);
147498
- }
147499
- get totalEventCount() {
147500
- return eventCounter;
147501
- }
147502
- };
147503
- var diagnosticEventBus = new DiagnosticEventBusImpl();
147504
-
147505
- // src/services/diagnostics/diagnostic-service.ts
147521
+ init_diagnostic_event_bus();
147506
147522
  var logger141 = Logger.get("DiagnosticService");
147507
147523
  var ignoredStateKeys = /* @__PURE__ */ new Set([
147508
147524
  "homeAssistantEntity",
@@ -148456,13 +148472,20 @@ var totalMemMB = Math.round(os.totalmem() / 1024 / 1024);
148456
148472
  var defaultMaxSize = totalMemMB < 2048 ? 200 : 1e3;
148457
148473
  var logBuffer = {
148458
148474
  entries: [],
148459
- maxSize: defaultMaxSize
148475
+ maxSize: defaultMaxSize,
148476
+ listeners: /* @__PURE__ */ new Set()
148460
148477
  };
148461
148478
  function addLogEntry(entry) {
148462
148479
  logBuffer.entries.push(entry);
148463
148480
  if (logBuffer.entries.length > logBuffer.maxSize) {
148464
148481
  logBuffer.entries.shift();
148465
148482
  }
148483
+ for (const listener of logBuffer.listeners) {
148484
+ try {
148485
+ listener(entry);
148486
+ } catch {
148487
+ }
148488
+ }
148466
148489
  }
148467
148490
  function logsApi(_logger) {
148468
148491
  const router = express5.Router();
@@ -148519,10 +148542,12 @@ function logsApi(_logger) {
148519
148542
  for (const log of recentLogs) {
148520
148543
  sendLog(log);
148521
148544
  }
148545
+ logBuffer.listeners.add(sendLog);
148522
148546
  const intervalId = setInterval(() => {
148523
148547
  res.write(": keepalive\n\n");
148524
148548
  }, 3e4);
148525
148549
  req.on("close", () => {
148550
+ logBuffer.listeners.delete(sendLog);
148526
148551
  clearInterval(intervalId);
148527
148552
  });
148528
148553
  });
@@ -151154,6 +151179,7 @@ function replaceBase(dist) {
151154
151179
  }
151155
151180
 
151156
151181
  // src/api/websocket-api.ts
151182
+ init_diagnostic_event_bus();
151157
151183
  import { WebSocketServer as WebSocketServer2 } from "ws";
151158
151184
  var WebSocketApi = class {
151159
151185
  constructor(log, bridgeService) {
@@ -166496,9 +166522,11 @@ function validatePluginDevice(device) {
166496
166522
  var PluginManager = class {
166497
166523
  instances = /* @__PURE__ */ new Map();
166498
166524
  domainMappings = /* @__PURE__ */ new Map();
166525
+ domainMappingOwners = /* @__PURE__ */ new Map();
166499
166526
  storageDir;
166500
166527
  bridgeId;
166501
166528
  runner = new SafePluginRunner();
166529
+ registry;
166502
166530
  /** Callback invoked when a plugin registers a new device */
166503
166531
  onDeviceRegistered;
166504
166532
  /** Callback invoked when a plugin removes a device */
@@ -166509,6 +166537,9 @@ var PluginManager = class {
166509
166537
  this.bridgeId = bridgeId;
166510
166538
  this.storageDir = storageDir;
166511
166539
  }
166540
+ setRegistry(registry2) {
166541
+ this.registry = registry2;
166542
+ }
166512
166543
  /**
166513
166544
  * Load and register a built-in plugin instance.
166514
166545
  */
@@ -166639,6 +166670,7 @@ var PluginManager = class {
166639
166670
  );
166640
166671
  }
166641
166672
  this.domainMappings.set(mapping.domain, mapping);
166673
+ this.domainMappingOwners.set(mapping.domain, plugin.name);
166642
166674
  pluginLogger.info(
166643
166675
  `Registered domain mapping: ${mapping.domain} \u2192 ${mapping.matterDeviceType}`
166644
166676
  );
@@ -166754,6 +166786,12 @@ var PluginManager = class {
166754
166786
  if (instance) {
166755
166787
  instance.metadata.enabled = false;
166756
166788
  }
166789
+ for (const [domain, owner] of this.domainMappingOwners) {
166790
+ if (owner === pluginName) {
166791
+ this.domainMappings.delete(domain);
166792
+ this.domainMappingOwners.delete(domain);
166793
+ }
166794
+ }
166757
166795
  }
166758
166796
  enablePlugin(pluginName) {
166759
166797
  this.runner.resetCircuitBreaker(pluginName);
@@ -166774,6 +166812,7 @@ var PluginManager = class {
166774
166812
  const instance = this.instances.get(pluginName);
166775
166813
  if (!instance) return false;
166776
166814
  instance.metadata.config = config10;
166815
+ this.registry?.updateConfig(pluginName, config10);
166777
166816
  if (instance.plugin.onConfigChanged) {
166778
166817
  await this.runner.run(
166779
166818
  pluginName,
@@ -167114,6 +167153,7 @@ function ensureCommissioningConfig(server) {
167114
167153
  }
167115
167154
 
167116
167155
  // src/services/bridges/bridge.ts
167156
+ init_diagnostic_event_bus();
167117
167157
  var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
167118
167158
  var DEAD_SESSION_TIMEOUT_MS = 6e4;
167119
167159
  var Bridge = class {
@@ -167336,6 +167376,20 @@ ${e?.toString()}`);
167336
167376
  this.log.info(
167337
167377
  `Session ${session.id} (peer ${session.peerNodeId}): subscriptions=${session.subscriptions.size} | total: sessions=${sessions.length} subscriptions=${totalSubs}`
167338
167378
  );
167379
+ diagnosticEventBus.emit(
167380
+ "subscription_changed",
167381
+ `Session ${session.id}: ${session.subscriptions.size} subs (total ${totalSubs})`,
167382
+ {
167383
+ bridgeId: this.data.id,
167384
+ bridgeName: this.data.name,
167385
+ details: {
167386
+ sessionId: session.id,
167387
+ sessionSubs: session.subscriptions.size,
167388
+ totalSessions: sessions.length,
167389
+ totalSubs
167390
+ }
167391
+ }
167392
+ );
167339
167393
  if (totalSubs === 0 && sessions.length > 0) {
167340
167394
  this.log.warn(
167341
167395
  `All subscriptions lost \u2014 ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
@@ -167374,6 +167428,15 @@ ${e?.toString()}`);
167374
167428
  this.log.info(
167375
167429
  `Session opened: id=${newSession.id} peer=${newSession.peerNodeId}`
167376
167430
  );
167431
+ diagnosticEventBus.emit(
167432
+ "session_opened",
167433
+ `Session ${newSession.id} opened (peer ${newSession.peerNodeId})`,
167434
+ {
167435
+ bridgeId: this.data.id,
167436
+ bridgeName: this.data.name,
167437
+ details: { sessionId: newSession.id }
167438
+ }
167439
+ );
167377
167440
  for (const s of [...sessionManager.sessions]) {
167378
167441
  if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
167379
167442
  this.log.info(
@@ -167389,6 +167452,18 @@ ${e?.toString()}`);
167389
167452
  this.log.warn(
167390
167453
  `Session closed: id=${session.id} peer=${session.peerNodeId} | remaining sessions=${sessions.length}`
167391
167454
  );
167455
+ diagnosticEventBus.emit(
167456
+ "session_closed",
167457
+ `Session ${session.id} closed (peer ${session.peerNodeId})`,
167458
+ {
167459
+ bridgeId: this.data.id,
167460
+ bridgeName: this.data.name,
167461
+ details: {
167462
+ sessionId: session.id,
167463
+ remainingSessions: sessions.length
167464
+ }
167465
+ }
167466
+ );
167392
167467
  };
167393
167468
  sessionManager.sessions.added.on(this.sessionAddedHandler);
167394
167469
  sessionManager.sessions.deleted.on(this.sessionDeletedHandler);
@@ -167818,7 +167893,7 @@ var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer
167818
167893
  this.reactTo(homeAssistant.onChange, this.update);
167819
167894
  }
167820
167895
  update(entity) {
167821
- if (!entity.state) {
167896
+ if (!entity.state || !entity.state.attributes) {
167822
167897
  return;
167823
167898
  }
167824
167899
  const { basicInformation } = this.env.get(BridgeDataProvider);
@@ -167994,7 +168069,7 @@ var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementSer
167994
168069
  this.reactTo(homeAssistant.onChange, this.update);
167995
168070
  }
167996
168071
  update(entity) {
167997
- if (!entity.state) {
168072
+ if (!entity.state || !entity.state.attributes) {
167998
168073
  return;
167999
168074
  }
168000
168075
  const humidity = this.getHumidity(this.state.config, entity.state);
@@ -168058,7 +168133,7 @@ var PowerSourceServerBase = class extends FeaturedBase2 {
168058
168133
  this.reactTo(homeAssistant.onChange, this.update);
168059
168134
  }
168060
168135
  update(entity) {
168061
- if (!entity.state) {
168136
+ if (!entity.state || !entity.state.attributes) {
168062
168137
  return;
168063
168138
  }
168064
168139
  const config10 = this.state.config;
@@ -168144,7 +168219,7 @@ var TemperatureMeasurementServerBase = class extends TemperatureMeasurementServe
168144
168219
  this.reactTo(homeAssistant.onChange, this.update);
168145
168220
  }
168146
168221
  update(entity) {
168147
- if (!entity.state) {
168222
+ if (!entity.state || !entity.state.attributes) {
168148
168223
  return;
168149
168224
  }
168150
168225
  applyPatchState(this.state, {
@@ -168186,7 +168261,7 @@ var HepaFilterMonitoringServerBase = class extends FeaturedBase3 {
168186
168261
  this.reactTo(homeAssistant.onChange, this.update);
168187
168262
  }
168188
168263
  update(entity) {
168189
- if (!entity.state) {
168264
+ if (!entity.state || !entity.state.attributes) {
168190
168265
  return;
168191
168266
  }
168192
168267
  const filterLife = this.getFilterLife(this.state.config, entity.state);
@@ -168526,7 +168601,11 @@ var OnOffServerBase = class extends OnOffServer {
168526
168601
  this.update(homeAssistant.entity);
168527
168602
  this.reactTo(homeAssistant.onChange, this.update);
168528
168603
  }
168529
- update({ state }) {
168604
+ update(entity) {
168605
+ if (!entity.state || !entity.state.attributes) {
168606
+ return;
168607
+ }
168608
+ const { state } = entity;
168530
168609
  const onOff = this.isOn(state);
168531
168610
  const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
168532
168611
  const optimistic = optimisticOnOffState.get(entityId);
@@ -169380,7 +169459,7 @@ var PressureMeasurementServerBase = class extends PressureMeasurementServer {
169380
169459
  this.reactTo(homeAssistant.onChange, this.update);
169381
169460
  }
169382
169461
  update(entity) {
169383
- if (!entity.state) {
169462
+ if (!entity.state || !entity.state.attributes) {
169384
169463
  return;
169385
169464
  }
169386
169465
  const pressure = this.getPressure(entity.state);
@@ -169735,7 +169814,7 @@ var ModeSelectServerBase = class extends ModeSelectServer {
169735
169814
  this.reactTo(homeAssistant.onChange, this.update);
169736
169815
  }
169737
169816
  update(entity) {
169738
- if (!entity.state) {
169817
+ if (!entity.state || !entity.state.attributes) {
169739
169818
  return;
169740
169819
  }
169741
169820
  const config10 = this.state.config;
@@ -169940,7 +170019,7 @@ var BooleanStateServerBase = class extends BooleanStateServer {
169940
170019
  this.reactTo(homeAssistant.onChange, this.update);
169941
170020
  }
169942
170021
  update(entity) {
169943
- if (!entity.state) {
170022
+ if (!entity.state || !entity.state.attributes) {
169944
170023
  return;
169945
170024
  }
169946
170025
  const newState = this.getStateValue(entity.state);
@@ -170016,7 +170095,7 @@ var PirOccupancySensingServer = class extends PirOccupancySensingServerBase {
170016
170095
  this.reactTo(homeAssistant.onChange, this.update);
170017
170096
  }
170018
170097
  update(entity) {
170019
- if (!entity.state) {
170098
+ if (!entity.state || !entity.state.attributes) {
170020
170099
  return;
170021
170100
  }
170022
170101
  const { state } = entity;
@@ -170084,7 +170163,7 @@ var OccupancySensingServer2 = class extends OccupancySensingServerBase {
170084
170163
  this.reactTo(homeAssistant.onChange, this.update);
170085
170164
  }
170086
170165
  update(entity) {
170087
- if (!entity.state) {
170166
+ if (!entity.state || !entity.state.attributes) {
170088
170167
  return;
170089
170168
  }
170090
170169
  const { state } = entity;
@@ -170174,6 +170253,15 @@ var OnOffSensorWithBatteryType = OnOffSensorDevice.with(
170174
170253
  })
170175
170254
  );
170176
170255
 
170256
+ // src/matter/endpoints/legacy/binary-sensor/rain-sensor.ts
170257
+ init_home_assistant_entity_behavior();
170258
+ var RainSensorType = RainSensorDevice.with(
170259
+ BasicInformationServer2,
170260
+ IdentifyServer2,
170261
+ HomeAssistantEntityBehavior,
170262
+ BooleanStateServer2()
170263
+ );
170264
+
170177
170265
  // ../../node_modules/.pnpm/@matter+main@0.16.10/node_modules/@matter/main/dist/esm/forwards/behaviors/smoke-co-alarm.js
170178
170266
  init_nodejs();
170179
170267
 
@@ -170303,7 +170391,8 @@ var deviceClasses = {
170303
170391
  [BinarySensorDeviceClass.Occupancy]: OccupancySensorType,
170304
170392
  [BinarySensorDeviceClass.Presence]: OccupancySensorType,
170305
170393
  [BinarySensorDeviceClass.Smoke]: SmokeAlarmType,
170306
- [BinarySensorDeviceClass.Moisture]: WaterLeakDetectorType
170394
+ [BinarySensorDeviceClass.Moisture]: WaterLeakDetectorType,
170395
+ [BinarySensorDeviceClass.Rain]: RainSensorType
170307
170396
  };
170308
170397
  var batteryTypes = /* @__PURE__ */ new Map([
170309
170398
  [ContactSensorType, ContactSensorWithBatteryType],
@@ -170336,15 +170425,6 @@ function BinarySensorDevice(homeAssistantEntity) {
170336
170425
  return type.set({ homeAssistantEntity });
170337
170426
  }
170338
170427
 
170339
- // src/matter/endpoints/legacy/binary-sensor/rain-sensor.ts
170340
- init_home_assistant_entity_behavior();
170341
- var RainSensorType = RainSensorDevice.with(
170342
- BasicInformationServer2,
170343
- IdentifyServer2,
170344
- HomeAssistantEntityBehavior,
170345
- BooleanStateServer2()
170346
- );
170347
-
170348
170428
  // src/matter/endpoints/legacy/button/index.ts
170349
170429
  init_home_assistant_entity_behavior();
170350
170430
  var ButtonOnOffServerBase = class extends OnOffServer.with("Lighting") {
@@ -171463,7 +171543,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
171463
171543
  this.reactTo(homeAssistant.onChange, this.update);
171464
171544
  }
171465
171545
  update(entity) {
171466
- if (!entity.state) {
171546
+ if (!entity.state || !entity.state.attributes) {
171467
171547
  return;
171468
171548
  }
171469
171549
  const config10 = this.state.config;
@@ -172883,7 +172963,7 @@ var LockServerBase = class extends DoorLockServer {
172883
172963
  this.reactTo(homeAssistant.onChange, this.update);
172884
172964
  }
172885
172965
  update(entity) {
172886
- if (!entity.state) {
172966
+ if (!entity.state || !entity.state.attributes) {
172887
172967
  return;
172888
172968
  }
172889
172969
  applyPatchState(this.state, {
@@ -172955,7 +173035,7 @@ var LockServerWithPinBase = class extends PinCredentialBase {
172955
173035
  this.reactTo(homeAssistant.onChange, this.update);
172956
173036
  }
172957
173037
  update(entity) {
172958
- if (!entity.state) {
173038
+ if (!entity.state || !entity.state.attributes) {
172959
173039
  return;
172960
173040
  }
172961
173041
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
@@ -173149,7 +173229,7 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
173149
173229
  this.reactTo(homeAssistant.onChange, this.update);
173150
173230
  }
173151
173231
  update(entity) {
173152
- if (!entity.state) {
173232
+ if (!entity.state || !entity.state.attributes) {
173153
173233
  return;
173154
173234
  }
173155
173235
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
@@ -173511,7 +173591,7 @@ var MediaInputServerBase = class extends MediaInputServer {
173511
173591
  this.reactTo(homeAssistant.onChange, this.update);
173512
173592
  }
173513
173593
  update(entity) {
173514
- if (!entity.state) {
173594
+ if (!entity.state || !entity.state.attributes) {
173515
173595
  return;
173516
173596
  }
173517
173597
  const config10 = this.state.config;
@@ -173718,7 +173798,7 @@ var SpeakerLevelControlServerBase = class extends FeaturedBase9 {
173718
173798
  this.reactTo(homeAssistant.onChange, this.update);
173719
173799
  }
173720
173800
  update(entity) {
173721
- if (!entity.state) {
173801
+ if (!entity.state || !entity.state.attributes) {
173722
173802
  return;
173723
173803
  }
173724
173804
  const { state } = entity;
@@ -173907,7 +173987,7 @@ var PumpConfigurationAndControlServerBase = class extends PumpConfigurationAndCo
173907
173987
  this.reactTo(homeAssistant.onChange, this.update);
173908
173988
  }
173909
173989
  update(entity) {
173910
- if (!entity.state) {
173990
+ if (!entity.state || !entity.state.attributes) {
173911
173991
  return;
173912
173992
  }
173913
173993
  const isOn = this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state.state === "on";
@@ -174208,7 +174288,7 @@ var CarbonMonoxideConcentrationMeasurementServer2 = class extends CarbonMonoxide
174208
174288
  this.reactTo(homeAssistant.onChange, this.update);
174209
174289
  }
174210
174290
  update(entity) {
174211
- if (!entity.state) {
174291
+ if (!entity.state || !entity.state.attributes) {
174212
174292
  return;
174213
174293
  }
174214
174294
  const state = entity.state.state;
@@ -174387,7 +174467,7 @@ var FlowMeasurementServerBase = class extends FlowMeasurementServer {
174387
174467
  this.reactTo(homeAssistant.onChange, this.update);
174388
174468
  }
174389
174469
  update(entity) {
174390
- if (!entity.state) {
174470
+ if (!entity.state || !entity.state.attributes) {
174391
174471
  return;
174392
174472
  }
174393
174473
  applyPatchState(this.state, {
@@ -174479,7 +174559,7 @@ var FormaldehydeConcentrationMeasurementServer2 = class extends FormaldehydeConc
174479
174559
  this.reactTo(homeAssistant.onChange, this.update);
174480
174560
  }
174481
174561
  update(entity) {
174482
- if (!entity.state) {
174562
+ if (!entity.state || !entity.state.attributes) {
174483
174563
  return;
174484
174564
  }
174485
174565
  const state = entity.state.state;
@@ -174569,7 +174649,7 @@ var IlluminanceMeasurementServerBase = class extends IlluminanceMeasurementServe
174569
174649
  this.reactTo(homeAssistant.onChange, this.update);
174570
174650
  }
174571
174651
  update(entity) {
174572
- if (!entity.state) {
174652
+ if (!entity.state || !entity.state.attributes) {
174573
174653
  return;
174574
174654
  }
174575
174655
  const illuminance = this.getIlluminance(this.state.config, entity.state);
@@ -174653,7 +174733,7 @@ var NitrogenDioxideConcentrationMeasurementServer2 = class extends NitrogenDioxi
174653
174733
  this.reactTo(homeAssistant.onChange, this.update);
174654
174734
  }
174655
174735
  update(entity) {
174656
- if (!entity.state) {
174736
+ if (!entity.state || !entity.state.attributes) {
174657
174737
  return;
174658
174738
  }
174659
174739
  const state = entity.state.state;
@@ -174746,7 +174826,7 @@ var OzoneConcentrationMeasurementServer2 = class extends OzoneConcentrationMeasu
174746
174826
  this.reactTo(homeAssistant.onChange, this.update);
174747
174827
  }
174748
174828
  update(entity) {
174749
- if (!entity.state) {
174829
+ if (!entity.state || !entity.state.attributes) {
174750
174830
  return;
174751
174831
  }
174752
174832
  const state = entity.state.state;
@@ -174839,7 +174919,7 @@ var Pm1ConcentrationMeasurementServer2 = class extends Pm1ConcentrationMeasureme
174839
174919
  this.reactTo(homeAssistant.onChange, this.update);
174840
174920
  }
174841
174921
  update(entity) {
174842
- if (!entity.state) {
174922
+ if (!entity.state || !entity.state.attributes) {
174843
174923
  return;
174844
174924
  }
174845
174925
  const state = entity.state.state;
@@ -174952,7 +175032,7 @@ var RadonConcentrationMeasurementServer2 = class extends RadonConcentrationMeasu
174952
175032
  this.reactTo(homeAssistant.onChange, this.update);
174953
175033
  }
174954
175034
  update(entity) {
174955
- if (!entity.state) {
175035
+ if (!entity.state || !entity.state.attributes) {
174956
175036
  return;
174957
175037
  }
174958
175038
  const state = entity.state.state;
@@ -175100,7 +175180,7 @@ var TvocConcentrationMeasurementServer = class extends TvocConcentrationMeasurem
175100
175180
  this.reactTo(homeAssistant.onChange, this.update);
175101
175181
  }
175102
175182
  update(entity) {
175103
- if (!entity.state) {
175183
+ if (!entity.state || !entity.state.attributes) {
175104
175184
  return;
175105
175185
  }
175106
175186
  const state = entity.state.state;
@@ -175181,6 +175261,7 @@ var TvocSensorType = AirQualitySensorDevice.with(
175181
175261
 
175182
175262
  // src/matter/endpoints/legacy/sensor/index.ts
175183
175263
  init_dist();
175264
+ init_diagnostic_event_bus();
175184
175265
 
175185
175266
  // src/matter/behaviors/carbon-dioxide-concentration-measurement-server.ts
175186
175267
  init_home_assistant_entity_behavior();
@@ -175213,7 +175294,7 @@ var CarbonDioxideConcentrationMeasurementServer2 = class extends CarbonDioxideCo
175213
175294
  this.reactTo(homeAssistant.onChange, this.update);
175214
175295
  }
175215
175296
  update(entity) {
175216
- if (!entity.state) {
175297
+ if (!entity.state || !entity.state.attributes) {
175217
175298
  return;
175218
175299
  }
175219
175300
  const state = entity.state.state;
@@ -175309,7 +175390,7 @@ var Pm10ConcentrationMeasurementServer2 = class extends Pm10ConcentrationMeasure
175309
175390
  this.reactTo(homeAssistant.onChange, this.update);
175310
175391
  }
175311
175392
  update(entity) {
175312
- if (!entity.state) {
175393
+ if (!entity.state || !entity.state.attributes) {
175313
175394
  return;
175314
175395
  }
175315
175396
  const state = entity.state.state;
@@ -175413,7 +175494,7 @@ var Pm25ConcentrationMeasurementServer2 = class extends Pm25ConcentrationMeasure
175413
175494
  this.reactTo(homeAssistant.onChange, this.update);
175414
175495
  }
175415
175496
  update(entity) {
175416
- if (!entity.state) {
175497
+ if (!entity.state || !entity.state.attributes) {
175417
175498
  return;
175418
175499
  }
175419
175500
  const state = entity.state.state;
@@ -175730,6 +175811,9 @@ function SensorDevice(homeAssistantEntity) {
175730
175811
  if (deviceClass === SensorDeviceClass.pm1) {
175731
175812
  return Pm1SensorType.set({ homeAssistantEntity });
175732
175813
  }
175814
+ if (deviceClass === SensorDeviceClass.radon) {
175815
+ return RadonSensorType.set({ homeAssistantEntity });
175816
+ }
175733
175817
  if (deviceClass === SensorDeviceClass.power || deviceClass === SensorDeviceClass.energy || deviceClass === SensorDeviceClass.voltage || deviceClass === SensorDeviceClass.current) {
175734
175818
  return ElectricalSensorType.set({ homeAssistantEntity });
175735
175819
  }
@@ -175886,7 +175970,7 @@ var RvcRunModeServerBase = class extends RvcRunModeServer {
175886
175970
  this.reactTo(homeAssistant.onChange, this.update);
175887
175971
  }
175888
175972
  update(entity) {
175889
- if (!entity.state) {
175973
+ if (!entity.state || !entity.state.attributes) {
175890
175974
  return;
175891
175975
  }
175892
175976
  const previousMode = this.state.currentMode;
@@ -177153,7 +177237,7 @@ var RvcCleanModeServerBase = class _RvcCleanModeServerBase extends RvcCleanModeS
177153
177237
  this.reactTo(homeAssistant.onChange, this.update);
177154
177238
  }
177155
177239
  update(entity) {
177156
- if (!entity.state) {
177240
+ if (!entity.state || !entity.state.attributes) {
177157
177241
  return;
177158
177242
  }
177159
177243
  const reportedMode = this.state.config.getCurrentMode(
@@ -177929,7 +178013,7 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
177929
178013
  this.reactTo(homeAssistant.onChange, this.update);
177930
178014
  }
177931
178015
  update(entity) {
177932
- if (!entity.state) {
178016
+ if (!entity.state || !entity.state.attributes) {
177933
178017
  return;
177934
178018
  }
177935
178019
  const newState = this.state.config.getOperationalState(
@@ -178186,7 +178270,7 @@ var ValveConfigurationAndControlServerBase = class extends ValveConfigurationAnd
178186
178270
  this.reactTo(homeAssistant.onChange, this.update);
178187
178271
  }
178188
178272
  update(entity) {
178189
- if (!entity.state) {
178273
+ if (!entity.state || !entity.state.attributes) {
178190
178274
  return;
178191
178275
  }
178192
178276
  const config10 = this.state.config;
@@ -179078,6 +179162,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
179078
179162
  }
179079
179163
  };
179080
179164
 
179165
+ // src/services/bridges/bridge-endpoint-manager.ts
179166
+ init_diagnostic_event_bus();
179167
+
179081
179168
  // src/services/home-assistant/api/subscribe-entities.ts
179082
179169
  init_esm();
179083
179170
  import crypto7 from "node:crypto";
@@ -179181,6 +179268,7 @@ var subscribeEntities = (conn, onChange, entityIds) => entitiesColl(conn, entity
179181
179268
 
179182
179269
  // src/services/bridges/entity-isolation-service.ts
179183
179270
  init_esm();
179271
+ init_diagnostic_event_bus();
179184
179272
  var logger202 = Logger.get("EntityIsolation");
179185
179273
  var EntityIsolationServiceImpl = class {
179186
179274
  isolatedEntities = /* @__PURE__ */ new Map();
@@ -179266,6 +179354,11 @@ var EntityIsolationServiceImpl = class {
179266
179354
  logger202.warn(
179267
179355
  `Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
179268
179356
  );
179357
+ diagnosticEventBus.emit("entity_error", `Entity isolated: ${entityName}`, {
179358
+ bridgeId,
179359
+ entityId: entityName,
179360
+ details: { reason: classification }
179361
+ });
179269
179362
  try {
179270
179363
  await callback(entityName);
179271
179364
  return true;
@@ -179731,10 +179824,19 @@ var BridgeEndpointManager = class extends Service {
179731
179824
  }
179732
179825
  }
179733
179826
  const latencyMs = Math.round((performance.now() - startMs) * 100) / 100;
179734
- if (latencyMs > 200) {
179735
- this.log.warn(
179736
- `Slow state update: ${endpoints.length} endpoints in ${latencyMs}ms` + (failedCount > 0 ? ` (${failedCount} failed)` : "")
179737
- );
179827
+ if (latencyMs > 200 || failedCount > 0) {
179828
+ const msg = `State update: ${endpoints.length} endpoints in ${latencyMs}ms` + (failedCount > 0 ? ` (${failedCount} failed)` : "");
179829
+ if (latencyMs > 200) {
179830
+ this.log.warn(`Slow ${msg}`);
179831
+ }
179832
+ diagnosticEventBus.emit("state_update", msg, {
179833
+ bridgeId: this.bridgeId,
179834
+ details: {
179835
+ endpointCount: endpoints.length,
179836
+ failedCount,
179837
+ latencyMs
179838
+ }
179839
+ });
179738
179840
  }
179739
179841
  }
179740
179842
  /**
@@ -180464,6 +180566,7 @@ function hashAreaId(areaId) {
180464
180566
 
180465
180567
  // src/services/bridges/server-mode-bridge.ts
180466
180568
  init_dist();
180569
+ init_diagnostic_event_bus();
180467
180570
  var AUTO_FORCE_SYNC_INTERVAL_MS2 = 9e4;
180468
180571
  var DEAD_SESSION_TIMEOUT_MS2 = 6e4;
180469
180572
  var ServerModeBridge = class {
@@ -181554,6 +181657,7 @@ var BridgeEnvironment = class _BridgeEnvironment extends EnvironmentBase {
181554
181657
  if (this.storageLocation) {
181555
181658
  pluginManager = new PluginManager(bridgeId, this.storageLocation);
181556
181659
  pluginRegistry = new PluginRegistry(this.storageLocation);
181660
+ pluginManager.setRegistry(pluginRegistry);
181557
181661
  pluginInstaller = new PluginInstaller(this.storageLocation);
181558
181662
  }
181559
181663
  this.set(