@riddix/hamh 2.1.0-alpha.516 → 2.1.0-alpha.518

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.
@@ -166866,6 +166866,7 @@ function ensureCommissioningConfig(server) {
166866
166866
 
166867
166867
  // src/services/bridges/bridge.ts
166868
166868
  var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
166869
+ var DEAD_SESSION_TIMEOUT_MS = 3 * 60 * 1e3;
166869
166870
  var Bridge = class {
166870
166871
  constructor(env, logger203, dataProvider, endpointManager) {
166871
166872
  this.dataProvider = dataProvider;
@@ -166888,6 +166889,7 @@ var Bridge = class {
166888
166889
  // (e.g. Stopped → Starting → Running).
166889
166890
  onStatusChange;
166890
166891
  autoForceSyncTimer = null;
166892
+ deadSessionTimer = null;
166891
166893
  // Tracks the last synced state JSON per entity to avoid pushing unchanged states.
166892
166894
  // Key: entity_id, Value: JSON.stringify of entity.state
166893
166895
  lastSyncedStates = /* @__PURE__ */ new Map();
@@ -167064,6 +167066,21 @@ ${e?.toString()}`);
167064
167066
  this.log.warn(
167065
167067
  `All subscriptions lost \u2014 ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
167066
167068
  );
167069
+ if (!this.deadSessionTimer) {
167070
+ this.deadSessionTimer = setTimeout(() => {
167071
+ this.deadSessionTimer = null;
167072
+ this.closeDeadSessions();
167073
+ }, DEAD_SESSION_TIMEOUT_MS);
167074
+ this.log.info(
167075
+ `Scheduled dead session cleanup in ${DEAD_SESSION_TIMEOUT_MS / 1e3}s`
167076
+ );
167077
+ }
167078
+ } else if (totalSubs > 0 && this.deadSessionTimer) {
167079
+ clearTimeout(this.deadSessionTimer);
167080
+ this.deadSessionTimer = null;
167081
+ this.log.info(
167082
+ "Subscriptions recovered, canceled dead session cleanup"
167083
+ );
167067
167084
  }
167068
167085
  };
167069
167086
  sessionManager.subscriptionsChanged.on(this.sessionDiagHandler);
@@ -167092,6 +167109,22 @@ ${e?.toString()}`);
167092
167109
  } catch {
167093
167110
  }
167094
167111
  }
167112
+ closeDeadSessions() {
167113
+ try {
167114
+ const sessionManager = this.server.env.get(SessionManager);
167115
+ const sessions = [...sessionManager.sessions];
167116
+ for (const s of sessions) {
167117
+ if (!s.isClosing && s.subscriptions.size === 0) {
167118
+ this.log.warn(
167119
+ `Force-closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS / 1e3}s)`
167120
+ );
167121
+ s.initiateForceClose().catch(() => {
167122
+ });
167123
+ }
167124
+ }
167125
+ } catch {
167126
+ }
167127
+ }
167095
167128
  unwireSessionDiagnostics() {
167096
167129
  try {
167097
167130
  const sessionManager = this.server.env.get(SessionManager);
@@ -167109,6 +167142,10 @@ ${e?.toString()}`);
167109
167142
  this.sessionDiagHandler = void 0;
167110
167143
  this.sessionAddedHandler = void 0;
167111
167144
  this.sessionDeletedHandler = void 0;
167145
+ if (this.deadSessionTimer) {
167146
+ clearTimeout(this.deadSessionTimer);
167147
+ this.deadSessionTimer = null;
167148
+ }
167112
167149
  }
167113
167150
  stopAutoForceSync() {
167114
167151
  if (this.autoForceSyncTimer) {
@@ -167276,6 +167313,7 @@ function getMappedEntityIds(mapping) {
167276
167313
  if (!mapping) return [];
167277
167314
  const ids = [];
167278
167315
  if (mapping.batteryEntity) ids.push(mapping.batteryEntity);
167316
+ if (mapping.temperatureEntity) ids.push(mapping.temperatureEntity);
167279
167317
  if (mapping.humidityEntity) ids.push(mapping.humidityEntity);
167280
167318
  if (mapping.pressureEntity) ids.push(mapping.pressureEntity);
167281
167319
  if (mapping.cleaningModeEntity) ids.push(mapping.cleaningModeEntity);
@@ -178732,6 +178770,9 @@ var BridgeEndpointManager = class extends Service {
178732
178770
  continue;
178733
178771
  }
178734
178772
  if (this.registry.isAutoComposedDevicesEnabled() && this.registry.isComposedSubEntityUsed(entityId)) {
178773
+ this.log.debug(
178774
+ `Skipping ${entityId} \u2014 already part of a composed device`
178775
+ );
178735
178776
  continue;
178736
178777
  }
178737
178778
  if (entityId.length > MAX_ENTITY_ID_LENGTH) {
@@ -179504,6 +179545,7 @@ function hashAreaId(areaId) {
179504
179545
  // src/services/bridges/server-mode-bridge.ts
179505
179546
  init_dist();
179506
179547
  var AUTO_FORCE_SYNC_INTERVAL_MS2 = 9e4;
179548
+ var DEAD_SESSION_TIMEOUT_MS2 = 3 * 60 * 1e3;
179507
179549
  var ServerModeBridge = class {
179508
179550
  constructor(logger203, dataProvider, endpointManager, server) {
179509
179551
  this.dataProvider = dataProvider;
@@ -179520,6 +179562,7 @@ var ServerModeBridge = class {
179520
179562
  // broadcast updates via WebSocket so the frontend sees every transition.
179521
179563
  onStatusChange;
179522
179564
  autoForceSyncTimer = null;
179565
+ deadSessionTimer = null;
179523
179566
  warmStartTimer = null;
179524
179567
  // Tracks the last synced state JSON per entity to avoid pushing unchanged states.
179525
179568
  lastSyncedState;
@@ -179701,6 +179744,21 @@ ${e?.toString()}`);
179701
179744
  this.log.warn(
179702
179745
  `All subscriptions lost \u2014 ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
179703
179746
  );
179747
+ if (!this.deadSessionTimer) {
179748
+ this.deadSessionTimer = setTimeout(() => {
179749
+ this.deadSessionTimer = null;
179750
+ this.closeDeadSessions();
179751
+ }, DEAD_SESSION_TIMEOUT_MS2);
179752
+ this.log.info(
179753
+ `Scheduled dead session cleanup in ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s`
179754
+ );
179755
+ }
179756
+ } else if (totalSubs > 0 && this.deadSessionTimer) {
179757
+ clearTimeout(this.deadSessionTimer);
179758
+ this.deadSessionTimer = null;
179759
+ this.log.info(
179760
+ "Subscriptions recovered, canceled dead session cleanup"
179761
+ );
179704
179762
  }
179705
179763
  };
179706
179764
  sessionManager.subscriptionsChanged.on(this.sessionDiagHandler);
@@ -179729,6 +179787,22 @@ ${e?.toString()}`);
179729
179787
  } catch {
179730
179788
  }
179731
179789
  }
179790
+ closeDeadSessions() {
179791
+ try {
179792
+ const sessionManager = this.server.env.get(SessionManager);
179793
+ const sessions = [...sessionManager.sessions];
179794
+ for (const s of sessions) {
179795
+ if (!s.isClosing && s.subscriptions.size === 0) {
179796
+ this.log.warn(
179797
+ `Force-closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s)`
179798
+ );
179799
+ s.initiateForceClose().catch(() => {
179800
+ });
179801
+ }
179802
+ }
179803
+ } catch {
179804
+ }
179805
+ }
179732
179806
  unwireSessionDiagnostics() {
179733
179807
  try {
179734
179808
  const sessionManager = this.server.env.get(SessionManager);
@@ -179746,6 +179820,10 @@ ${e?.toString()}`);
179746
179820
  this.sessionDiagHandler = void 0;
179747
179821
  this.sessionAddedHandler = void 0;
179748
179822
  this.sessionDeletedHandler = void 0;
179823
+ if (this.deadSessionTimer) {
179824
+ clearTimeout(this.deadSessionTimer);
179825
+ this.deadSessionTimer = null;
179826
+ }
179749
179827
  }
179750
179828
  stopAutoForceSync() {
179751
179829
  if (this.autoForceSyncTimer) {