@camstack/addon-provider-homeassistant 1.2.638 → 1.2.639

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.639] - 2026-10-29
11
+
12
+ ### Changed
13
+
14
+ - Home Assistant state changes reach CamStack once each, not once per listener.
15
+
10
16
  ## [1.2.638] - 2026-10-29
11
17
 
12
18
  ### Changed
package/dist/addon.js CHANGED
@@ -5354,8 +5354,10 @@ function subscribeEntities(opts) {
5354
5354
  * the same HA broker for overlapping entity sets. We keep ONE
5355
5355
  * upstream `subscribe_entities` to HA with the UNION of every
5356
5356
  * active subscription's entity ids, and fan inbound state changes
5357
- * out via `EventCategory.BrokerMessage` once per matching
5358
- * subscription.
5357
+ * out via `EventCategory.BrokerMessage` ONCE per change when at
5358
+ * least one subscription matches (the bus is shared and consumers
5359
+ * filter by `key`). A new subscriber's cache replay is the one
5360
+ * targeted emission: it carries that subscription's id.
5359
5361
  * - When the active union changes (subscribe / unsubscribe call),
5360
5362
  * we re-issue the upstream subscribe with the new set. HA accepts
5361
5363
  * this efficiently (server-side filter).
@@ -5367,6 +5369,10 @@ function subscribeEntities(opts) {
5367
5369
  * subscribe's initial `a` (add) frames.
5368
5370
  */
5369
5371
  var HA_KIND$1 = "home-assistant";
5372
+ /** `subscriptionId` of a `broker.message` that is not addressed to one
5373
+ * subscription (a live state change fanned out once). The payload type
5374
+ * requires the field; the empty string is the repo convention for "none". */
5375
+ var FANOUT_SUBSCRIPTION_ID = "";
5370
5376
  /**
5371
5377
  * Curated device-event allowlist for the per-broker bus-event aggregator
5372
5378
  * (Case 2). Home Assistant fires arbitrary events on its bus; subscribing
@@ -5645,7 +5651,10 @@ var HaIntegrationManager = class HaIntegrationManager {
5645
5651
  for (const entityId of changed) {
5646
5652
  const state = next[entityId] ?? null;
5647
5653
  if (state === null) continue;
5648
- for (const sub of this.subscriptions.values()) if (this.subscriptionMatches(sub, entityId)) this.emitBrokerMessage(sub.id, entityId, state);
5654
+ for (const sub of this.subscriptions.values()) if (this.subscriptionMatches(sub, entityId)) {
5655
+ this.emitBrokerMessage(FANOUT_SUBSCRIPTION_ID, entityId, state);
5656
+ break;
5657
+ }
5649
5658
  }
5650
5659
  }
5651
5660
  subscriptionMatches(sub, entityId) {
package/dist/addon.mjs CHANGED
@@ -5353,8 +5353,10 @@ function subscribeEntities(opts) {
5353
5353
  * the same HA broker for overlapping entity sets. We keep ONE
5354
5354
  * upstream `subscribe_entities` to HA with the UNION of every
5355
5355
  * active subscription's entity ids, and fan inbound state changes
5356
- * out via `EventCategory.BrokerMessage` once per matching
5357
- * subscription.
5356
+ * out via `EventCategory.BrokerMessage` ONCE per change when at
5357
+ * least one subscription matches (the bus is shared and consumers
5358
+ * filter by `key`). A new subscriber's cache replay is the one
5359
+ * targeted emission: it carries that subscription's id.
5358
5360
  * - When the active union changes (subscribe / unsubscribe call),
5359
5361
  * we re-issue the upstream subscribe with the new set. HA accepts
5360
5362
  * this efficiently (server-side filter).
@@ -5366,6 +5368,10 @@ function subscribeEntities(opts) {
5366
5368
  * subscribe's initial `a` (add) frames.
5367
5369
  */
5368
5370
  var HA_KIND$1 = "home-assistant";
5371
+ /** `subscriptionId` of a `broker.message` that is not addressed to one
5372
+ * subscription (a live state change fanned out once). The payload type
5373
+ * requires the field; the empty string is the repo convention for "none". */
5374
+ var FANOUT_SUBSCRIPTION_ID = "";
5369
5375
  /**
5370
5376
  * Curated device-event allowlist for the per-broker bus-event aggregator
5371
5377
  * (Case 2). Home Assistant fires arbitrary events on its bus; subscribing
@@ -5644,7 +5650,10 @@ var HaIntegrationManager = class HaIntegrationManager {
5644
5650
  for (const entityId of changed) {
5645
5651
  const state = next[entityId] ?? null;
5646
5652
  if (state === null) continue;
5647
- for (const sub of this.subscriptions.values()) if (this.subscriptionMatches(sub, entityId)) this.emitBrokerMessage(sub.id, entityId, state);
5653
+ for (const sub of this.subscriptions.values()) if (this.subscriptionMatches(sub, entityId)) {
5654
+ this.emitBrokerMessage(FANOUT_SUBSCRIPTION_ID, entityId, state);
5655
+ break;
5656
+ }
5648
5657
  }
5649
5658
  }
5650
5659
  subscriptionMatches(sub, entityId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.638",
3
+ "version": "1.2.639",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",