@riddix/hamh 2.1.0-alpha.558 → 2.1.0-alpha.560

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.
@@ -177856,6 +177856,21 @@ var advertisedOperationalStates = [
177856
177856
  OperationalState4.Docked
177857
177857
  ];
177858
177858
  var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
177859
+ /**
177860
+ * Alternating nonce that forces a structural difference in operationalError
177861
+ * on every update call. matter.js's Datasource uses isDeepEqual to detect
177862
+ * attribute changes — writing the same value is silently ignored, so no
177863
+ * subscription report is generated. By toggling errorStateDetails between
177864
+ * absent and "" (an optional, semantically meaningless field when
177865
+ * errorStateId is NoError), we guarantee the struct is never deep-equal to
177866
+ * its predecessor, which makes matter.js emit attrsChanged and produce a
177867
+ * subscription report.
177868
+ *
177869
+ * This works around a matter.js 0.16.x bug where the subscription
177870
+ * heartbeat timer (sendInterval) fails to fire for certain sessions,
177871
+ * causing Apple Home (iOS via Apple TV proxy) to show "Updating...".
177872
+ */
177873
+ keepaliveNonce = false;
177859
177874
  async initialize() {
177860
177875
  this.state.operationalStateList = advertisedOperationalStates.map((id) => ({
177861
177876
  operationalStateId: id
@@ -177876,13 +177891,17 @@ var RvcOperationalStateServerBase = class extends RvcOperationalStateServer {
177876
177891
  this.agent
177877
177892
  );
177878
177893
  const previousState = this.state.operationalState;
177894
+ this.keepaliveNonce = !this.keepaliveNonce;
177895
+ const errorStateId = newState === OperationalState4.Error ? ErrorState.Stuck : ErrorState.NoError;
177896
+ const operationalError = { errorStateId };
177897
+ if (this.keepaliveNonce) {
177898
+ operationalError.errorStateDetails = "";
177899
+ }
177879
177900
  applyPatchState(
177880
177901
  this.state,
177881
177902
  {
177882
177903
  operationalState: newState,
177883
- operationalError: {
177884
- errorStateId: newState === OperationalState4.Error ? ErrorState.Stuck : ErrorState.NoError
177885
- }
177904
+ operationalError
177886
177905
  },
177887
177906
  { force: true }
177888
177907
  );
@@ -181105,30 +181124,34 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
181105
181124
  }
181106
181125
  lastState;
181107
181126
  pendingMappedChange = false;
181108
- /** Timestamp of the last non-empty state push to matter.js */
181109
- lastNonEmptyPush = Date.now();
181110
181127
  flushUpdate;
181128
+ /** Periodic keepalive timer that re-pushes the last known state so
181129
+ * Apple Home (iOS) doesn't show "Updating..." due to stale
181130
+ * subscription data when the vacuum is idle and no HA events fire. */
181131
+ keepaliveTimer;
181111
181132
  constructor(type, entityId, customName, mappedEntityIds) {
181112
181133
  super(type, entityId, customName, mappedEntityIds);
181113
181134
  this.flushUpdate = debounce6(this.flushPendingUpdate.bind(this), 50);
181135
+ this.keepaliveTimer = setInterval(() => {
181136
+ if (this.lastState) {
181137
+ this.pendingMappedChange = true;
181138
+ this.flushUpdate(this.lastState);
181139
+ }
181140
+ }, 55e3);
181114
181141
  }
181115
181142
  async delete() {
181143
+ if (this.keepaliveTimer) {
181144
+ clearInterval(this.keepaliveTimer);
181145
+ this.keepaliveTimer = void 0;
181146
+ }
181116
181147
  this.flushUpdate.clear();
181117
181148
  await super.delete();
181118
181149
  }
181119
181150
  async updateStates(states) {
181120
181151
  const state = states[this.entityId] ?? {};
181121
181152
  const mappedChanged = this.hasMappedEntityChanged(states);
181122
- const stateUnchanged = !mappedChanged && state.state === this.lastState?.state && JSON.stringify(state.attributes) === JSON.stringify(this.lastState?.attributes);
181123
- if (stateUnchanged) {
181124
- const now = Date.now();
181125
- if (now - this.lastNonEmptyPush < 6e4) {
181126
- return;
181127
- }
181128
- this.lastNonEmptyPush = now;
181129
- this.pendingMappedChange = true;
181130
- } else {
181131
- this.lastNonEmptyPush = Date.now();
181153
+ if (!mappedChanged && state.state === this.lastState?.state && JSON.stringify(state.attributes) === JSON.stringify(this.lastState?.attributes)) {
181154
+ return;
181132
181155
  }
181133
181156
  if (mappedChanged) {
181134
181157
  this.pendingMappedChange = true;