@riddix/hamh 2.1.0-alpha.827 → 2.1.0-alpha.829

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.
@@ -132628,7 +132628,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
132628
132628
  customFanSpeedTags: config11.customFanSpeedTags,
132629
132629
  fanWindPresets: config11.fanWindPresets,
132630
132630
  fanRestoreSpeedOnPowerOn: config11.fanRestoreSpeedOnPowerOn,
132631
- composedEntities: config11.composedEntities
132631
+ composedEntities: config11.composedEntities,
132632
+ disableMomentaryFlip: config11.disableMomentaryFlip
132632
132633
  });
132633
132634
  mappingsRestored++;
132634
132635
  }
@@ -132784,7 +132785,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
132784
132785
  customServiceAreas: config11.customServiceAreas,
132785
132786
  customFanSpeedTags: config11.customFanSpeedTags,
132786
132787
  fanWindPresets: config11.fanWindPresets,
132787
- composedEntities: config11.composedEntities
132788
+ composedEntities: config11.composedEntities,
132789
+ disableMomentaryFlip: config11.disableMomentaryFlip
132788
132790
  });
132789
132791
  mappingsRestored++;
132790
132792
  }
@@ -133641,7 +133643,8 @@ function entityMappingApi(mappingStorage) {
133641
133643
  climateKeepModeOnIdle: body.climateKeepModeOnIdle,
133642
133644
  climateExposeFan: body.climateExposeFan,
133643
133645
  climateAutoMode: body.climateAutoMode,
133644
- composedEntities: body.composedEntities
133646
+ composedEntities: body.composedEntities,
133647
+ disableMomentaryFlip: body.disableMomentaryFlip
133645
133648
  };
133646
133649
  const config11 = await mappingStorage.setMapping(request);
133647
133650
  res.status(200).json(config11);
@@ -134127,7 +134130,8 @@ function configToProfileEntry(config11) {
134127
134130
  disableClimateFanControl: config11.disableClimateFanControl,
134128
134131
  climateKeepModeOnIdle: config11.climateKeepModeOnIdle,
134129
134132
  climateExposeFan: config11.climateExposeFan,
134130
- climateAutoMode: config11.climateAutoMode
134133
+ climateAutoMode: config11.climateAutoMode,
134134
+ disableMomentaryFlip: config11.disableMomentaryFlip
134131
134135
  };
134132
134136
  }
134133
134137
  function mappingProfileApi(mappingStorage) {
@@ -134261,7 +134265,8 @@ function mappingProfileApi(mappingStorage) {
134261
134265
  disableClimateFanControl: entry.disableClimateFanControl,
134262
134266
  climateKeepModeOnIdle: entry.climateKeepModeOnIdle,
134263
134267
  climateExposeFan: entry.climateExposeFan,
134264
- climateAutoMode: entry.climateAutoMode
134268
+ climateAutoMode: entry.climateAutoMode,
134269
+ disableMomentaryFlip: entry.disableMomentaryFlip
134265
134270
  });
134266
134271
  applied++;
134267
134272
  } catch (e) {
@@ -138475,9 +138480,10 @@ var EntityMappingStorage = class extends Service {
138475
138480
  climateKeepModeOnIdle: request.climateKeepModeOnIdle || void 0,
138476
138481
  climateExposeFan: request.climateExposeFan || void 0,
138477
138482
  climateAutoMode: request.climateAutoMode || void 0,
138478
- composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
138483
+ composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0,
138484
+ disableMomentaryFlip: request.disableMomentaryFlip || void 0
138479
138485
  };
138480
- if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.disableBatteryMapping && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.lockUsercodeService && config11.lockUsercodeSlot === void 0 && config11.lockPinMinLength === void 0 && config11.lockPinMaxLength === void 0 && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
138486
+ if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.disableBatteryMapping && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.lockUsercodeService && config11.lockUsercodeSlot === void 0 && config11.lockPinMinLength === void 0 && config11.lockPinMaxLength === void 0 && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0) && !config11.disableMomentaryFlip) {
138481
138487
  bridgeMap.delete(request.entityId);
138482
138488
  } else {
138483
138489
  bridgeMap.set(request.entityId, config11);
@@ -155969,6 +155975,11 @@ function parseSessionMaxAgeHours(raw) {
155969
155975
  if (n > max) return max;
155970
155976
  return n;
155971
155977
  }
155978
+ var DEAD_SESSION_TIMEOUT_MS = 6e4;
155979
+ var FAST_DEAD_SESSION_TIMEOUT_MS = 5e3;
155980
+ function deadSessionTimeoutMs(flags2) {
155981
+ return flags2?.fastSessionRecovery ? FAST_DEAD_SESSION_TIMEOUT_MS : DEAD_SESSION_TIMEOUT_MS;
155982
+ }
155972
155983
  var STALE_SESSION_QUIET_WINDOW_MS = 5 * 60 * 1e3;
155973
155984
  function staleSessionQuietWindowMs(flags2) {
155974
155985
  return flags2?.fastSessionRecovery ? 0 : STALE_SESSION_QUIET_WINDOW_MS;
@@ -156003,11 +156014,6 @@ function seedExistingSessionStarts(startedAt, sessions, now = Date.now()) {
156003
156014
 
156004
156015
  // src/services/bridges/bridge.ts
156005
156016
  var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
156006
- var DEAD_SESSION_TIMEOUT_MS = 6e4;
156007
- var FAST_DEAD_SESSION_TIMEOUT_MS = 5e3;
156008
- function deadSessionTimeoutMs(flags2) {
156009
- return flags2?.fastSessionRecovery ? FAST_DEAD_SESSION_TIMEOUT_MS : DEAD_SESSION_TIMEOUT_MS;
156010
- }
156011
156017
  var SHUTDOWN_SESSION_CLOSE_TIMEOUT_MS = 2500;
156012
156018
  var MDNS_ADDRESS_CHECK_INTERVAL_MS = 6e4;
156013
156019
  var Bridge = class {
@@ -158281,20 +158287,25 @@ var OnOffServerBase = class extends OnOffServer {
158281
158287
  }
158282
158288
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
158283
158289
  const action = turnOn ? turnOn(void 0, this.agent) : defaultOnOffAction(homeAssistant.entityId, true);
158284
- applyPatchState(this.state, { onOff: true });
158290
+ const skipMomentaryFlip = turnOff === null && homeAssistant.state.mapping?.disableMomentaryFlip;
158291
+ if (!skipMomentaryFlip) {
158292
+ applyPatchState(this.state, { onOff: true });
158293
+ }
158285
158294
  if (!action) {
158286
158295
  return;
158287
158296
  }
158288
158297
  logger207.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
158289
158298
  notifyLightTurnedOn(homeAssistant.entityId);
158290
- const now = Date.now();
158291
- sweepOptimisticOnOff(now);
158292
- optimisticOnOffState.set(homeAssistant.entityId, {
158293
- expectedOnOff: true,
158294
- timestamp: now
158295
- });
158299
+ if (!skipMomentaryFlip) {
158300
+ const now = Date.now();
158301
+ sweepOptimisticOnOff(now);
158302
+ optimisticOnOffState.set(homeAssistant.entityId, {
158303
+ expectedOnOff: true,
158304
+ timestamp: now
158305
+ });
158306
+ }
158296
158307
  homeAssistant.callAction(action);
158297
- if (turnOff === null) {
158308
+ if (turnOff === null && !skipMomentaryFlip) {
158298
158309
  setTimeout(this.callback(this.autoReset), 1e3);
158299
158310
  }
158300
158311
  }
@@ -161768,6 +161779,9 @@ var ButtonOnOffServerBase = class extends OnOffServer {
161768
161779
  on() {
161769
161780
  const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
161770
161781
  homeAssistant.callAction({ action: "button.press" });
161782
+ if (homeAssistant.state.mapping?.disableMomentaryFlip) {
161783
+ return;
161784
+ }
161771
161785
  setTimeout(this.callback(this.resetToOff), 1e3);
161772
161786
  }
161773
161787
  off() {
@@ -172989,7 +173003,6 @@ init_esm7();
172989
173003
  import * as os10 from "node:os";
172990
173004
  init_diagnostic_event_bus();
172991
173005
  var AUTO_FORCE_SYNC_INTERVAL_MS2 = 9e4;
172992
- var DEAD_SESSION_TIMEOUT_MS2 = 6e4;
172993
173006
  var SHUTDOWN_SESSION_CLOSE_TIMEOUT_MS2 = 2500;
172994
173007
  var MDNS_ADDRESS_CHECK_INTERVAL_MS2 = 6e4;
172995
173008
  function makeWarmStartState(state, now = (/* @__PURE__ */ new Date()).toISOString()) {
@@ -173272,17 +173285,34 @@ ${e?.toString()}`);
173272
173285
  this.log.debug(
173273
173286
  `Session ${session.id} (peer ${session.peerNodeId}): subscriptions=${session.subscriptions.size} | total: sessions=${sessions.length} subscriptions=${totalSubs}`
173274
173287
  );
173288
+ diagnosticEventBus.emit(
173289
+ "subscription_changed",
173290
+ `Session ${session.id}: ${session.subscriptions.size} subs (total ${totalSubs})`,
173291
+ {
173292
+ bridgeId: this.data.id,
173293
+ bridgeName: this.data.name,
173294
+ details: {
173295
+ sessionId: session.id,
173296
+ sessionSubs: session.subscriptions.size,
173297
+ totalSessions: sessions.length,
173298
+ totalSubs
173299
+ }
173300
+ }
173301
+ );
173275
173302
  if (totalSubs === 0 && sessions.length > 0) {
173276
173303
  this.log.warn(
173277
173304
  `All subscriptions lost, ${sessions.length} session(s) still active, waiting for controller to re-subscribe`
173278
173305
  );
173279
173306
  if (!this.deadSessionTimer) {
173307
+ const timeoutMs = deadSessionTimeoutMs(
173308
+ this.dataProvider.featureFlags
173309
+ );
173280
173310
  this.deadSessionTimer = setTimeout(() => {
173281
173311
  this.deadSessionTimer = null;
173282
173312
  this.closeDeadSessions();
173283
- }, DEAD_SESSION_TIMEOUT_MS2);
173313
+ }, timeoutMs);
173284
173314
  this.log.info(
173285
- `Scheduled dead session cleanup in ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s`
173315
+ `Scheduled dead session cleanup in ${timeoutMs / 1e3}s`
173286
173316
  );
173287
173317
  }
173288
173318
  } else if (totalSubs > 0 && this.deadSessionTimer) {
@@ -173298,7 +173328,7 @@ ${e?.toString()}`);
173298
173328
  setTimeout(() => {
173299
173329
  this.staleSessionTimers.delete(session.id);
173300
173330
  this.closeStaleSession(session.id);
173301
- }, DEAD_SESSION_TIMEOUT_MS2)
173331
+ }, deadSessionTimeoutMs(this.dataProvider.featureFlags))
173302
173332
  );
173303
173333
  } else if (session.subscriptions.size > 0 && this.staleSessionTimers.has(session.id)) {
173304
173334
  clearTimeout(this.staleSessionTimers.get(session.id));
@@ -173311,6 +173341,15 @@ ${e?.toString()}`);
173311
173341
  this.log.info(
173312
173342
  `Session opened: id=${newSession.id} peer=${newSession.peerNodeId}`
173313
173343
  );
173344
+ diagnosticEventBus.emit(
173345
+ "session_opened",
173346
+ `Session ${newSession.id} opened (peer ${newSession.peerNodeId})`,
173347
+ {
173348
+ bridgeId: this.data.id,
173349
+ bridgeName: this.data.name,
173350
+ details: { sessionId: newSession.id }
173351
+ }
173352
+ );
173314
173353
  for (const s of [...sessionManager.sessions]) {
173315
173354
  if (s !== newSession && !s.isClosing && s.peerNodeId === newSession.peerNodeId && s.fabric?.fabricIndex === newSession.fabric?.fabricIndex && s.subscriptions.size === 0) {
173316
173355
  this.log.info(
@@ -173359,6 +173398,18 @@ ${e?.toString()}`);
173359
173398
  this.log.warn(
173360
173399
  `Session closed: id=${session.id} peer=${session.peerNodeId} | remaining sessions=${sessions.length}`
173361
173400
  );
173401
+ diagnosticEventBus.emit(
173402
+ "session_closed",
173403
+ `Session ${session.id} closed (peer ${session.peerNodeId})`,
173404
+ {
173405
+ bridgeId: this.data.id,
173406
+ bridgeName: this.data.name,
173407
+ details: {
173408
+ sessionId: session.id,
173409
+ remainingSessions: sessions.length
173410
+ }
173411
+ }
173412
+ );
173362
173413
  };
173363
173414
  sessionManager.sessions.added.on(this.sessionAddedHandler);
173364
173415
  sessionManager.sessions.deleted.on(this.sessionDeletedHandler);
@@ -173386,12 +173437,12 @@ ${e?.toString()}`);
173386
173437
  setTimeout(() => {
173387
173438
  this.staleSessionTimers.delete(sessionId);
173388
173439
  this.closeStaleSession(sessionId);
173389
- }, DEAD_SESSION_TIMEOUT_MS2)
173440
+ }, deadSessionTimeoutMs(this.dataProvider.featureFlags))
173390
173441
  );
173391
173442
  break;
173392
173443
  }
173393
173444
  this.log.warn(
173394
- `Closing stale session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s, no traffic for ${idleSec}s)`
173445
+ `Closing stale session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${deadSessionTimeoutMs(this.dataProvider.featureFlags) / 1e3}s, no traffic for ${idleSec}s)`
173395
173446
  );
173396
173447
  s.initiateClose().catch(() => {
173397
173448
  return s.initiateForceClose({
@@ -173426,7 +173477,7 @@ ${e?.toString()}`);
173426
173477
  continue;
173427
173478
  }
173428
173479
  this.log.warn(
173429
- `Closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${DEAD_SESSION_TIMEOUT_MS2 / 1e3}s, no traffic for ${idleSec}s)`
173480
+ `Closing dead session ${s.id} (peer ${s.peerNodeId}, no subscriptions for ${deadSessionTimeoutMs(this.dataProvider.featureFlags) / 1e3}s, no traffic for ${idleSec}s)`
173430
173481
  );
173431
173482
  closes.push(
173432
173483
  s.initiateClose().catch(() => {
@@ -173440,7 +173491,7 @@ ${e?.toString()}`);
173440
173491
  this.deadSessionTimer = setTimeout(() => {
173441
173492
  this.deadSessionTimer = null;
173442
173493
  this.closeDeadSessions();
173443
- }, DEAD_SESSION_TIMEOUT_MS2);
173494
+ }, deadSessionTimeoutMs(this.dataProvider.featureFlags));
173444
173495
  }
173445
173496
  if (closes.length > 0) {
173446
173497
  Promise.allSettled(closes).then(() => this.triggerMdnsReAnnounce());