@enyo-energy/energy-app-sdk 0.0.138 → 0.0.139

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.
Files changed (45) hide show
  1. package/dist/cjs/index.cjs +2 -0
  2. package/dist/cjs/index.d.cts +2 -0
  3. package/dist/cjs/packages/eebus/eebus-feature-catalog.d.cts +57 -1
  4. package/dist/cjs/packages/eebus/eebus-hvac-client.d.cts +36 -0
  5. package/dist/cjs/packages/eebus/eebus-lpc-client.d.cts +31 -0
  6. package/dist/cjs/packages/eebus/eebus-mpc-client.d.cts +53 -0
  7. package/dist/cjs/packages/eebus/eebus-ohpcf-client.d.cts +72 -2
  8. package/dist/cjs/packages/eebus/eebus-setpoint-client.d.cts +37 -0
  9. package/dist/cjs/packages/eebus/eebus-spine-low-level.d.cts +36 -4
  10. package/dist/cjs/packages/eebus/eebus-use-case-registry.d.cts +40 -10
  11. package/dist/cjs/packages/eebus/energy-app-eebus.d.cts +6 -6
  12. package/dist/cjs/types/enyo-data-bus-value.d.cts +1 -1
  13. package/dist/cjs/types/enyo-eebus-errors.cjs +140 -0
  14. package/dist/cjs/types/enyo-eebus-errors.d.cts +110 -0
  15. package/dist/cjs/types/enyo-eebus-features.cjs +0 -15
  16. package/dist/cjs/types/enyo-eebus-features.d.cts +20 -6
  17. package/dist/cjs/types/enyo-eebus-use-cases.d.cts +84 -0
  18. package/dist/cjs/types/enyo-eebus.d.cts +53 -2
  19. package/dist/cjs/types/enyo-spine.cjs +172 -0
  20. package/dist/cjs/types/enyo-spine.d.cts +158 -0
  21. package/dist/cjs/version.cjs +1 -1
  22. package/dist/cjs/version.d.cts +1 -1
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +2 -0
  25. package/dist/packages/eebus/eebus-feature-catalog.d.ts +57 -1
  26. package/dist/packages/eebus/eebus-hvac-client.d.ts +36 -0
  27. package/dist/packages/eebus/eebus-lpc-client.d.ts +31 -0
  28. package/dist/packages/eebus/eebus-mpc-client.d.ts +53 -0
  29. package/dist/packages/eebus/eebus-ohpcf-client.d.ts +72 -2
  30. package/dist/packages/eebus/eebus-setpoint-client.d.ts +37 -0
  31. package/dist/packages/eebus/eebus-spine-low-level.d.ts +36 -4
  32. package/dist/packages/eebus/eebus-use-case-registry.d.ts +40 -10
  33. package/dist/packages/eebus/energy-app-eebus.d.ts +6 -6
  34. package/dist/types/enyo-data-bus-value.d.ts +1 -1
  35. package/dist/types/enyo-eebus-errors.d.ts +110 -0
  36. package/dist/types/enyo-eebus-errors.js +132 -0
  37. package/dist/types/enyo-eebus-features.d.ts +20 -6
  38. package/dist/types/enyo-eebus-features.js +0 -15
  39. package/dist/types/enyo-eebus-use-cases.d.ts +84 -0
  40. package/dist/types/enyo-eebus.d.ts +53 -2
  41. package/dist/types/enyo-spine.d.ts +158 -0
  42. package/dist/types/enyo-spine.js +169 -0
  43. package/dist/version.d.ts +1 -1
  44. package/dist/version.js +1 -1
  45. package/package.json +1 -1
@@ -50,9 +50,11 @@ __exportStar(require("./types/enyo-currency.cjs"), exports);
50
50
  __exportStar(require("./packages/energy-app-sequence-generator.cjs"), exports);
51
51
  __exportStar(require("./packages/energy-app-energy-prices.cjs"), exports);
52
52
  __exportStar(require("./packages/energy-app-modbus-rtu.cjs"), exports);
53
+ __exportStar(require("./types/enyo-spine.cjs"), exports);
53
54
  __exportStar(require("./types/enyo-eebus.cjs"), exports);
54
55
  __exportStar(require("./types/enyo-eebus-use-cases.cjs"), exports);
55
56
  __exportStar(require("./types/enyo-eebus-features.cjs"), exports);
57
+ __exportStar(require("./types/enyo-eebus-errors.cjs"), exports);
56
58
  __exportStar(require("./packages/energy-app-eebus.cjs"), exports);
57
59
  __exportStar(require("./types/enyo-mqtt.cjs"), exports);
58
60
  __exportStar(require("./packages/energy-app-mqtt.cjs"), exports);
@@ -34,9 +34,11 @@ export * from './types/enyo-currency.cjs';
34
34
  export * from './packages/energy-app-sequence-generator.cjs';
35
35
  export * from './packages/energy-app-energy-prices.cjs';
36
36
  export * from './packages/energy-app-modbus-rtu.cjs';
37
+ export * from './types/enyo-spine.cjs';
37
38
  export * from './types/enyo-eebus.cjs';
38
39
  export * from './types/enyo-eebus-use-cases.cjs';
39
40
  export * from './types/enyo-eebus-features.cjs';
41
+ export * from './types/enyo-eebus-errors.cjs';
40
42
  export * from './packages/energy-app-eebus.cjs';
41
43
  export * from './types/enyo-mqtt.cjs';
42
44
  export * from './packages/energy-app-mqtt.cjs';
@@ -1,4 +1,35 @@
1
- import { EebusRemoteFeatureCatalog } from '../../types/enyo-eebus-features.cjs';
1
+ import { EebusFeatureRole, EebusRemoteFeatureCatalog } from '../../types/enyo-eebus-features.cjs';
2
+ import { SpineEntityType, SpineFeatureType, SpineFunctionType } from '../../types/enyo-spine.cjs';
3
+ /**
4
+ * One match returned by {@link EebusFeatureCatalog.findFeatureAddresses}.
5
+ *
6
+ * Carries enough context for a caller to pick *which* entity it wants to
7
+ * target without having to walk the full {@link EebusRemoteFeatureCatalog}
8
+ * tree itself. {@link entityType} is the deciding field on heat pumps —
9
+ * it lets a caller say "the compressor's `Measurement`, not the heat
10
+ * pump's" without hard-coding entity addresses.
11
+ */
12
+ export interface EebusFeatureAddressMatch {
13
+ /** SPINE entity address that hosts the feature (e.g. `[3, 1]`) */
14
+ entity: number[];
15
+ /**
16
+ * SPINE entity type that hosts the feature, from the
17
+ * {@link SpineEntityType} catalogue
18
+ * (e.g. `SpineEntityType.HM_COMPRESSOR`,
19
+ * `SpineEntityType.HVAC_ROOM`).
20
+ */
21
+ entityType: SpineEntityType;
22
+ /** SPINE feature index within {@link entity} */
23
+ feature: number;
24
+ /**
25
+ * Functions the remote advertises as supported on this feature
26
+ * (e.g. `[SpineFunctionType.MeasurementListData,
27
+ * SpineFunctionType.MeasurementDescriptionListData]`). Useful for
28
+ * picking between entities that nominally host the same feature
29
+ * type but expose different functions.
30
+ */
31
+ supportedFunctions: SpineFunctionType[];
32
+ }
2
33
  /**
3
34
  * Per-peer SPINE entity/feature catalog for paired EEbus remotes.
4
35
  *
@@ -81,6 +112,31 @@ export interface EebusFeatureCatalog {
81
112
  * @returns Listener ID that can be passed to {@link removeListener} to cancel
82
113
  */
83
114
  onFeaturesChanged: (ski: string, listener: (catalog: EebusRemoteFeatureCatalog) => void) => string;
115
+ /**
116
+ * Enumerate every entity on a remote node that advertises a feature of
117
+ * the given type and role, with enough context for the caller to pick
118
+ * meaningfully between them.
119
+ *
120
+ * The canonical use case is multi-entity heat pumps: a Vaillant VR940
121
+ * advertises `Measurement` (server) on its `HeatPumpAppliance`,
122
+ * `Compressor`, `HVACRoom`, and `TemperatureSensor` entities. A caller
123
+ * that wants the compressor's electrical measurement (not the
124
+ * appliance-wide MPC roll-up) walks this list, filters by
125
+ * `entityType === 'Compressor'`, and passes the resulting `entity` /
126
+ * `feature` to {@link EebusSpineLowLevel.subscribe} (or to a typed
127
+ * use-case client's `address` option).
128
+ *
129
+ * The result is derived from the current {@link get} snapshot — it
130
+ * does not trigger a re-fetch from the remote. When the peer is not
131
+ * paired or not currently connected the call resolves to an empty
132
+ * array rather than throwing.
133
+ *
134
+ * @param ski Subject Key Identifier of the remote node
135
+ * @param featureType SPINE feature type from the {@link SpineFeatureType} catalogue (e.g. `SpineFeatureType.MEASUREMENT`, `SpineFeatureType.SMART_ENERGY_MANAGEMENT_PS`)
136
+ * @param role SPINE role to match: `'server'` for features the remote *hosts*, `'client'` for features it *consumes*
137
+ * @returns Every matching feature address on the peer, in catalog order
138
+ */
139
+ findFeatureAddresses: (ski: string, featureType: SpineFeatureType, role: EebusFeatureRole) => Promise<EebusFeatureAddressMatch[]>;
84
140
  /**
85
141
  * Remove a feature-catalog listener previously registered via
86
142
  * {@link onFeaturesChanged}.
@@ -1,4 +1,33 @@
1
+ import { SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
1
2
  import { EebusHvacOperationMode, EebusHvacZoneState } from '../../types/enyo-eebus-use-cases.cjs';
3
+ import { SpineEntityType } from '../../types/enyo-spine.cjs';
4
+ /**
5
+ * Per-call configuration for {@link EebusUseCaseRegistry.hvac}.
6
+ *
7
+ * Heat pumps expose `Hvac` on the entity that owns the zone, typically
8
+ * `HVACRoom`. Multi-zone peers may host the feature on more than one
9
+ * entity — pin the target via {@link address} or {@link prefer} to talk
10
+ * to a specific zone.
11
+ */
12
+ export interface HvacClientOptions {
13
+ /**
14
+ * Bind the client to a specific entity (and optionally feature index)
15
+ * on the remote. Wins over {@link prefer} when both are supplied.
16
+ */
17
+ address?: SpineRemoteTarget;
18
+ /**
19
+ * Resolution hint when {@link address} is omitted. Pin to a
20
+ * {@link SpineEntityType} value — typically
21
+ * {@link SpineEntityType.HVAC_ROOM} or
22
+ * {@link SpineEntityType.HEATING_ZONE} on a multi-zone heat pump.
23
+ */
24
+ prefer?: SpineEntityType | 'auto';
25
+ /**
26
+ * Override the internal `hvacOperationModeDescriptionListData` read
27
+ * timeout (default 5_000 ms).
28
+ */
29
+ descriptionReadTimeoutMs?: number;
30
+ }
2
31
  /**
3
32
  * Client for the EEBUS **Hvac** feature.
4
33
  *
@@ -16,6 +45,13 @@ import { EebusHvacOperationMode, EebusHvacZoneState } from '../../types/enyo-eeb
16
45
  *
17
46
  * Consumers that only act in one role simply never call the other half — there
18
47
  * is no `asManager` / `asAppliance` split.
48
+ *
49
+ * **Resolution.** The client resolves the remote `Hvac` feature via the
50
+ * SPINE feature catalog rather than the peer's `NodeManagement.UseCaseData`
51
+ * advertisement, so peers that expose `Hvac` without advertising a
52
+ * matching use case (e.g. Vaillant VR940) are supported.
53
+ * `EebusFeatureUnavailableError` is thrown only when no `Hvac` server
54
+ * feature exists on the peer at all.
19
55
  */
20
56
  export interface EebusHvacClient {
21
57
  /**
@@ -1,4 +1,35 @@
1
+ import { SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
1
2
  import { EebusLpcAck, EebusLpcFailsafe, EebusLpcLimit } from '../../types/enyo-eebus-use-cases.cjs';
3
+ import { SpineEntityType } from '../../types/enyo-spine.cjs';
4
+ /**
5
+ * Per-call configuration for {@link EebusUseCaseRegistry.lpc}.
6
+ *
7
+ * On flat peers (a single controllable system per node) the defaults
8
+ * resolve correctly. Multi-entity peers — notably heat pumps that host
9
+ * `LoadControl` on both a top-level `HeatPumpAppliance` entity and an
10
+ * inner controllable entity — should pin the client to the entity whose
11
+ * limit semantics they want.
12
+ */
13
+ export interface LpcClientOptions {
14
+ /**
15
+ * Bind the client to a specific entity (and optionally feature index)
16
+ * on the remote. Wins over {@link prefer} when both are supplied.
17
+ */
18
+ address?: SpineRemoteTarget;
19
+ /**
20
+ * Resolution hint when {@link address} is omitted. `'auto'` (default)
21
+ * keeps current first-match behaviour. Otherwise pin the resolver
22
+ * to a {@link SpineEntityType} value — typically
23
+ * {@link SpineEntityType.HM_HEAT_PUMP} for an appliance-level
24
+ * `LoadControl` server.
25
+ */
26
+ prefer?: SpineEntityType | 'auto';
27
+ /**
28
+ * Override the internal `loadControlLimitDescriptionListData` read
29
+ * timeout (default 5_000 ms).
30
+ */
31
+ descriptionReadTimeoutMs?: number;
32
+ }
2
33
  /**
3
34
  * Client for the EEBUS **Limitation of Power Consumption (LPC)** use case.
4
35
  *
@@ -1,4 +1,48 @@
1
+ import { SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
1
2
  import { EebusMpcReading } from '../../types/enyo-eebus-use-cases.cjs';
3
+ import { SpineEntityType } from '../../types/enyo-spine.cjs';
4
+ /**
5
+ * Per-call configuration for {@link EebusUseCaseRegistry.mpc}.
6
+ *
7
+ * Heat pumps frequently expose `Measurement` (server) on more than one
8
+ * entity — typically both the `HeatPumpAppliance` (whole-appliance
9
+ * roll-up) and the `Compressor` (compressor-only draw). Without targeting
10
+ * the SDK resolves the first match it encounters, which has historically
11
+ * meant consumers silently picked up the wrong vantage point. These
12
+ * options give the caller direct control.
13
+ */
14
+ export interface MpcClientOptions {
15
+ /**
16
+ * Bind the client to a specific entity (and optionally feature index)
17
+ * on the remote. Wins over {@link prefer} when both are supplied.
18
+ * Use {@link EebusFeatureCatalog.findFeatureAddresses} to enumerate
19
+ * candidates.
20
+ */
21
+ address?: SpineRemoteTarget;
22
+ /**
23
+ * Resolution hint when {@link address} is omitted. `'auto'` (the
24
+ * default) keeps current behaviour — first match wins. Otherwise
25
+ * pin the resolver to a {@link SpineEntityType} value — most
26
+ * commonly {@link SpineEntityType.HM_COMPRESSOR} or
27
+ * {@link SpineEntityType.HM_HEAT_PUMP} on heat-pump peers.
28
+ */
29
+ prefer?: SpineEntityType | 'auto';
30
+ /**
31
+ * Override the internal `measurementDescriptionListData` read timeout
32
+ * (default 5_000 ms). Useful for peers whose description-list reply is
33
+ * sluggish but functional — extend rather than disable.
34
+ */
35
+ descriptionReadTimeoutMs?: number;
36
+ /**
37
+ * When the internal description read fails (timeout or
38
+ * not-supported), fall back to extracting `scopeType` from each
39
+ * inbound notify (`acPowerTotal` → {@link EebusMpcReading.activePowerW},
40
+ * `acEnergyConsumed` → {@link EebusMpcReading.totalEnergyConsumedWh})
41
+ * so the client keeps emitting readings instead of going silent.
42
+ * Defaults to `true`.
43
+ */
44
+ fallbackToInlineScope?: boolean;
45
+ }
2
46
  /**
3
47
  * Client for the EEBUS **Monitoring of Power Consumption (MPC)** use case.
4
48
  *
@@ -8,6 +52,15 @@ import { EebusMpcReading } from '../../types/enyo-eebus-use-cases.cjs';
8
52
  * The client exposes both actor roles on a single interface:
9
53
  * - **EMS role (consume):** {@link getReading}, {@link onReading}
10
54
  * - **CS role (provide):** {@link provideReading}
55
+ *
56
+ * **Resolution.** From SDK 0.0.139 onward this client resolves the remote
57
+ * `Measurement` feature via the SPINE feature catalog rather than via the
58
+ * peer's advertised `monitoringOfPowerConsumption` use-case entry. Many
59
+ * non-certified peers (notably Vaillant heat pumps) expose the feature
60
+ * without advertising the use case; the previous resolution path silently
61
+ * no-op'd on them. The client now only throws
62
+ * `EebusFeatureUnavailableError` when no `Measurement` server feature
63
+ * exists at all on the peer.
11
64
  */
12
65
  export interface EebusMpcClient {
13
66
  /**
@@ -1,4 +1,38 @@
1
- import { EebusOhpcfFlexibility, EebusOhpcfIncentiveTable, EebusOhpcfPlanState } from '../../types/enyo-eebus-use-cases.cjs';
1
+ import { SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
2
+ import { EebusOhpcfAnnouncement, EebusOhpcfApplianceContext, EebusOhpcfFlavour, EebusOhpcfFlexibility, EebusOhpcfIncentiveTable, EebusOhpcfPlanState } from '../../types/enyo-eebus-use-cases.cjs';
3
+ /**
4
+ * Per-call configuration for {@link EebusUseCaseRegistry.ohpcf}.
5
+ *
6
+ * On Vaillant peers — where OHPCF is layered on `SmartEnergyManagementPs`
7
+ * and the feature lives on the `Compressor` sub-entity — pass
8
+ * {@link address} (or `prefer`-equivalent: `flavour: 'smartEnergyManagementPs'`)
9
+ * so the client targets the correct entity without falling back to raw
10
+ * SPINE writes.
11
+ */
12
+ export interface OhpcfClientOptions {
13
+ /**
14
+ * Pin the on-wire flavour. `'auto'` (the default) inspects the peer's
15
+ * feature catalog and selects whichever flavour it advertises.
16
+ */
17
+ flavour?: EebusOhpcfFlavour;
18
+ /**
19
+ * Bind the client to a specific entity (and optionally feature
20
+ * index). Required on multi-entity peers where the OHPCF-bearing
21
+ * feature is hosted on more than one entity. Use
22
+ * {@link EebusFeatureCatalog.findFeatureAddresses} with
23
+ * `SpineFeatureType.INCENTIVE_TABLE` or
24
+ * `SpineFeatureType.SMART_ENERGY_MANAGEMENT_PS` to enumerate
25
+ * candidates.
26
+ */
27
+ address?: SpineRemoteTarget;
28
+ /**
29
+ * Override the internal description-list read timeout (default
30
+ * 5_000 ms). Applies to the flavour-appropriate description function
31
+ * (`incentiveDescriptionData` or
32
+ * `smartEnergyManagementPsConfigurationData`).
33
+ */
34
+ descriptionReadTimeoutMs?: number;
35
+ }
2
36
  /**
3
37
  * Client for the EEBUS **Optimization of Self Consumption by Heat Pump
4
38
  * Compressor Flexibility (OHPCF)** use case.
@@ -11,10 +45,17 @@ import { EebusOhpcfFlexibility, EebusOhpcfIncentiveTable, EebusOhpcfPlanState }
11
45
  *
12
46
  * The client exposes both actor roles on a single interface:
13
47
  * - **CEM role:** {@link sendIncentiveTable}, {@link getCurrentPlanState},
14
- * {@link onFlexibilityUpdate}
48
+ * {@link onFlexibilityUpdate}, {@link onAnnouncement}, {@link activateNow}
15
49
  * - **Heat Pump role:** {@link provideFlexibility}, {@link providePlanState},
16
50
  * {@link onIncentiveTableReceived}
17
51
  *
52
+ * **Flavours.** OHPCF ships in two interoperable encodings — the
53
+ * canonical `IncentiveTable` flavour and Vaillant's
54
+ * `SmartEnergyManagementPs` flavour. Pin the flavour via
55
+ * {@link OhpcfClientOptions.flavour} when known, or rely on the default
56
+ * `'auto'` to probe the feature catalog. Methods that are flavour-specific
57
+ * are documented as such on each method.
58
+ *
18
59
  * @see https://techdocs.wago.com/Software/EEBUS_Connector/en-US/3657311371.html
19
60
  * @see https://github.com/enbility/eebus-go/pull/122
20
61
  */
@@ -22,6 +63,10 @@ export interface EebusOhpcfClient {
22
63
  /**
23
64
  * Send an incentive table to the heat pump. The heat pump will use
24
65
  * the table to plan its compressor operation over the covered horizon.
66
+ *
67
+ * **Flavour:** `incentiveTable`. Throws on a client pinned to
68
+ * `smartEnergyManagementPs` — use {@link activateNow} there instead.
69
+ *
25
70
  * @param table The incentive table to send
26
71
  */
27
72
  sendIncentiveTable: (table: EebusOhpcfIncentiveTable) => Promise<void>;
@@ -37,6 +82,31 @@ export interface EebusOhpcfClient {
37
82
  * @returns Listener ID that can be passed to {@link removeListener} to cancel
38
83
  */
39
84
  onFlexibilityUpdate: (listener: (flexibility: EebusOhpcfFlexibility) => void) => string;
85
+ /**
86
+ * Subscribe to OHPCF announcements emitted by the heat pump. Each
87
+ * announcement describes a planned consumption window the CEM may
88
+ * activate via {@link activateNow}.
89
+ *
90
+ * **Flavour:** `smartEnergyManagementPs`. Returns a no-op listener
91
+ * id on `incentiveTable` peers — those peers do not emit
92
+ * announcements.
93
+ *
94
+ * @param listener Callback invoked with each new announcement
95
+ * @returns Listener ID that can be passed to {@link removeListener} to cancel
96
+ */
97
+ onAnnouncement: (listener: (announcement: EebusOhpcfAnnouncement) => void) => string;
98
+ /**
99
+ * Activate a previously-announced consumption window on the heat
100
+ * pump. The heat pump starts the compressor under the parameters
101
+ * carried in {@link EebusOhpcfApplianceContext}.
102
+ *
103
+ * **Flavour:** `smartEnergyManagementPs`. Throws on a client pinned
104
+ * to `incentiveTable` — those peers schedule themselves from the
105
+ * incentive table without an explicit activation.
106
+ *
107
+ * @param context Activation context (announcement id + optional overrides)
108
+ */
109
+ activateNow: (context: EebusOhpcfApplianceContext) => Promise<void>;
40
110
  /**
41
111
  * Register a provider that reports the heat pump's current compressor
42
112
  * flexibility when a remote CEM reads it.
@@ -1,4 +1,34 @@
1
+ import { SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
1
2
  import { EebusSetpointValue } from '../../types/enyo-eebus-use-cases.cjs';
3
+ import { SpineEntityType } from '../../types/enyo-spine.cjs';
4
+ /**
5
+ * Per-call configuration for {@link EebusUseCaseRegistry.setpoint}.
6
+ *
7
+ * Heat pumps expose `Setpoint` on the entity that owns the zone — most
8
+ * commonly `HVACRoom`, occasionally `HeatingZone`. The default resolution
9
+ * scans the catalog and picks the first match. Pin the target via
10
+ * {@link address} or {@link prefer} when the peer hosts multiple
11
+ * candidates.
12
+ */
13
+ export interface SetpointClientOptions {
14
+ /**
15
+ * Bind the client to a specific entity (and optionally feature index)
16
+ * on the remote. Wins over {@link prefer} when both are supplied.
17
+ */
18
+ address?: SpineRemoteTarget;
19
+ /**
20
+ * Resolution hint when {@link address} is omitted. Pin to a
21
+ * {@link SpineEntityType} value — typically
22
+ * {@link SpineEntityType.HVAC_ROOM} or
23
+ * {@link SpineEntityType.HEATING_ZONE} on a multi-zone heat pump.
24
+ */
25
+ prefer?: SpineEntityType | 'auto';
26
+ /**
27
+ * Override the internal `setpointDescriptionListData` read timeout
28
+ * (default 5_000 ms).
29
+ */
30
+ descriptionReadTimeoutMs?: number;
31
+ }
2
32
  /**
3
33
  * Client for the EEBUS **Setpoint** feature.
4
34
  *
@@ -16,6 +46,13 @@ import { EebusSetpointValue } from '../../types/enyo-eebus-use-cases.cjs';
16
46
  *
17
47
  * Consumers that only act in one role simply never call the other half — there
18
48
  * is no `asManager` / `asAppliance` split.
49
+ *
50
+ * **Resolution.** The client resolves the remote `Setpoint` feature via
51
+ * the SPINE feature catalog rather than the peer's
52
+ * `NodeManagement.UseCaseData` advertisement. Peers that expose `Setpoint`
53
+ * without advertising a matching use case (e.g. Vaillant VR940) are now
54
+ * supported. `EebusFeatureUnavailableError` is thrown only when no
55
+ * `Setpoint` server feature exists on the peer at all.
19
56
  */
20
57
  export interface EebusSetpointClient {
21
58
  /**
@@ -1,4 +1,4 @@
1
- import { EebusDataPoint } from '../../types/enyo-eebus.cjs';
1
+ import { EebusDataPoint, SpineRemoteTarget } from '../../types/enyo-eebus.cjs';
2
2
  /**
3
3
  * Low-level SPINE escape hatch for direct feature data access.
4
4
  *
@@ -17,34 +17,66 @@ import { EebusDataPoint } from '../../types/enyo-eebus.cjs';
17
17
  * `'Measurement'`, `'LoadControl'`, `'DeviceConfiguration'`,
18
18
  * `'Identification'`, `'IncentiveTable'`, `'TimeSeries'`, `'Hvac'`,
19
19
  * `'SmartEnergyManagementPs'`, and many more — consult the SPINE spec.
20
+ *
21
+ * **Entity targeting.** Heat pumps and other multi-entity peers routinely
22
+ * expose the same `featureType` on more than one entity (e.g. `Measurement`
23
+ * on both `HeatPumpAppliance` and `Compressor`). Without a {@link SpineRemoteTarget}
24
+ * the SDK picks the first matching entity it resolves, which can deliver
25
+ * notifies from the wrong vantage point. Pass a `target` to scope reads /
26
+ * writes / subscriptions to a specific entity; inbound data points then
27
+ * carry `source` on every event so consumers can attribute multi-entity
28
+ * subscriptions. Use {@link EebusFeatureCatalog.findFeatureAddresses} to
29
+ * enumerate candidates before targeting.
20
30
  */
21
31
  export interface EebusSpineLowLevel {
22
32
  /**
23
33
  * Read specific data points from a SPINE feature on a remote device.
34
+ *
35
+ * When `target` is omitted the SDK reads from whichever entity it
36
+ * resolves first — fine on flat peers, ambiguous on peers that expose
37
+ * the feature type on multiple entities. Pass `target` to bind the read
38
+ * to a specific entity.
39
+ *
24
40
  * @param ski Subject Key Identifier of the target device
25
41
  * @param featureType SPINE feature type name (e.g. `'Measurement'`)
26
42
  * @param functionName Specific function or data set to read (e.g. `'measurementListData'`)
43
+ * @param target Optional remote entity (and feature) to scope the read to
27
44
  * @returns The data point containing the raw value, timestamp, and optional unit
28
45
  */
29
- readData: (ski: string, featureType: string, functionName: string) => Promise<EebusDataPoint>;
46
+ readData: (ski: string, featureType: string, functionName: string, target?: SpineRemoteTarget) => Promise<EebusDataPoint>;
30
47
  /**
31
48
  * Write data or send a command to a SPINE feature on a remote device.
49
+ *
50
+ * When `target` is omitted the SDK writes to whichever entity it
51
+ * resolves first. Use `target` to bind the write to a specific entity
52
+ * (e.g. `SmartEnergyManagementPs` on `Compressor` rather than on
53
+ * `HeatPumpAppliance`).
54
+ *
32
55
  * @param ski Subject Key Identifier of the target device
33
56
  * @param featureType SPINE feature type name (e.g. `'LoadControl'`)
34
57
  * @param functionName Specific function or command to invoke (e.g. `'loadControlLimitListData'`)
35
58
  * @param payload The raw data payload to send — caller is responsible for matching the SPINE schema
59
+ * @param target Optional remote entity (and feature) to scope the write to
36
60
  */
37
- writeData: (ski: string, featureType: string, functionName: string, payload: unknown) => Promise<void>;
61
+ writeData: (ski: string, featureType: string, functionName: string, payload: unknown, target?: SpineRemoteTarget) => Promise<void>;
38
62
  /**
39
63
  * Subscribe to automatic notifications when a SPINE feature's data changes.
40
64
  * Sets up a SPINE binding so the local device is notified whenever the
41
65
  * subscribed data changes.
66
+ *
67
+ * When `target` is omitted the subscription matches the feature type
68
+ * across every entity that hosts it on the remote, and the listener is
69
+ * invoked once per source — inspect {@link EebusDataPoint.source} to
70
+ * attribute each notify. Pass `target` to bind the subscription to a
71
+ * single entity (the recommended shape on multi-entity peers).
72
+ *
42
73
  * @param ski Subject Key Identifier of the target device
43
74
  * @param featureType SPINE feature type name to subscribe to
44
75
  * @param listener Callback invoked with updated data whenever the value changes
76
+ * @param target Optional remote entity (and feature) to scope the subscription to
45
77
  * @returns Listener ID that can be passed to {@link removeListener} to cancel the subscription
46
78
  */
47
- subscribe: (ski: string, featureType: string, listener: (data: EebusDataPoint) => void) => string;
79
+ subscribe: (ski: string, featureType: string, listener: (data: EebusDataPoint) => void, target?: SpineRemoteTarget) => string;
48
80
  /**
49
81
  * Remove a subscription previously registered via {@link subscribe}.
50
82
  * @param listenerId The ID returned by the registration method
@@ -1,10 +1,10 @@
1
- import { EebusHvacClient } from './eebus-hvac-client.cjs';
2
- import { EebusLpcClient } from './eebus-lpc-client.cjs';
1
+ import { EebusHvacClient, HvacClientOptions } from './eebus-hvac-client.cjs';
2
+ import { EebusLpcClient, LpcClientOptions } from './eebus-lpc-client.cjs';
3
3
  import { EebusLppClient } from './eebus-lpp-client.cjs';
4
4
  import { EebusMgcpClient } from './eebus-mgcp-client.cjs';
5
- import { EebusMpcClient } from './eebus-mpc-client.cjs';
6
- import { EebusOhpcfClient } from './eebus-ohpcf-client.cjs';
7
- import { EebusSetpointClient } from './eebus-setpoint-client.cjs';
5
+ import { EebusMpcClient, MpcClientOptions } from './eebus-mpc-client.cjs';
6
+ import { EebusOhpcfClient, OhpcfClientOptions } from './eebus-ohpcf-client.cjs';
7
+ import { EebusSetpointClient, SetpointClientOptions } from './eebus-setpoint-client.cjs';
8
8
  /**
9
9
  * Registry of typed EEBUS use-case clients, scoped per remote device (SKI).
10
10
  *
@@ -43,9 +43,17 @@ export interface EebusUseCaseRegistry {
43
43
  /**
44
44
  * Get the **Limitation of Power Consumption** client for a remote node.
45
45
  * LPC limits are obligations the remote MUST respect.
46
+ *
47
+ * Multi-entity peers (e.g. a heat pump that hosts `LoadControl` on
48
+ * more than one entity) should pass {@link LpcClientOptions.address}
49
+ * or {@link LpcClientOptions.prefer} to pin the client to a specific
50
+ * entity. Omitting `options` keeps the existing first-match
51
+ * behaviour.
52
+ *
46
53
  * @param ski Subject Key Identifier of the remote node
54
+ * @param options Optional address/timeout configuration
47
55
  */
48
- lpc: (ski: string) => EebusLpcClient;
56
+ lpc: (ski: string, options?: LpcClientOptions) => EebusLpcClient;
49
57
  /**
50
58
  * Get the **Limitation of Power Production** client for a remote node.
51
59
  * LPP limits are recommendations the remote SHOULD respect.
@@ -61,28 +69,50 @@ export interface EebusUseCaseRegistry {
61
69
  /**
62
70
  * Get the **Monitoring of Power Consumption** client for a remote node.
63
71
  * Read-only telemetry from a controllable system reporting its own consumption.
72
+ *
73
+ * Heat pumps that host `Measurement` on both `HeatPumpAppliance` and
74
+ * `Compressor` should pass {@link MpcClientOptions.prefer} (or
75
+ * {@link MpcClientOptions.address} when the address is already
76
+ * known). Without a hint the client picks the first server match the
77
+ * SDK resolves.
78
+ *
79
+ * The default options enable `fallbackToInlineScope`, so a single
80
+ * slow `measurementDescriptionListData` read on a flaky peer no
81
+ * longer silences the client — it falls back to extracting scope
82
+ * from inbound notifies.
83
+ *
64
84
  * @param ski Subject Key Identifier of the remote node
85
+ * @param options Optional address/timeout/fallback configuration
65
86
  */
66
- mpc: (ski: string) => EebusMpcClient;
87
+ mpc: (ski: string, options?: MpcClientOptions) => EebusMpcClient;
67
88
  /**
68
89
  * Get the **Optimization of Self Consumption by Heat Pump Compressor
69
90
  * Flexibility** client for a remote node. Incentive-table-driven heat
70
91
  * pump coordination.
92
+ *
93
+ * Two on-wire flavours exist (see {@link OhpcfClientOptions.flavour}):
94
+ * `IncentiveTable` (canonical) and `SmartEnergyManagementPs`
95
+ * (Vaillant). `auto` (the default) probes the feature catalog and
96
+ * picks whichever the peer advertises.
97
+ *
71
98
  * @param ski Subject Key Identifier of the remote node
99
+ * @param options Optional address/flavour configuration
72
100
  */
73
- ohpcf: (ski: string) => EebusOhpcfClient;
101
+ ohpcf: (ski: string, options?: OhpcfClientOptions) => EebusOhpcfClient;
74
102
  /**
75
103
  * Get the **Setpoint** client for a remote node. Manages target values
76
104
  * for controllable parameters such as per-zone heat-pump temperature
77
105
  * setpoints. Pair with {@link hvac} to read measured values.
78
106
  * @param ski Subject Key Identifier of the remote node
107
+ * @param options Optional address/timeout configuration
79
108
  */
80
- setpoint: (ski: string) => EebusSetpointClient;
109
+ setpoint: (ski: string, options?: SetpointClientOptions) => EebusSetpointClient;
81
110
  /**
82
111
  * Get the **Hvac** client for a remote node. Observes heating/cooling
83
112
  * operation mode and per-zone state on a heat-pump appliance. Pair with
84
113
  * {@link setpoint} to write target values.
85
114
  * @param ski Subject Key Identifier of the remote node
115
+ * @param options Optional address/timeout configuration
86
116
  */
87
- hvac: (ski: string) => EebusHvacClient;
117
+ hvac: (ski: string, options?: HvacClientOptions) => EebusHvacClient;
88
118
  }
@@ -4,17 +4,17 @@ import { EebusIdentityService } from './eebus-identity-service.cjs';
4
4
  import { EebusSpineLowLevel } from './eebus-spine-low-level.cjs';
5
5
  import { EebusUseCaseRegistry } from './eebus-use-case-registry.cjs';
6
6
  export { EebusDeviceManagement } from './eebus-device-management.cjs';
7
- export { EebusFeatureCatalog } from './eebus-feature-catalog.cjs';
7
+ export { EebusFeatureCatalog, EebusFeatureAddressMatch } from './eebus-feature-catalog.cjs';
8
8
  export { EebusIdentityService } from './eebus-identity-service.cjs';
9
9
  export { EebusSpineLowLevel } from './eebus-spine-low-level.cjs';
10
10
  export { EebusUseCaseRegistry } from './eebus-use-case-registry.cjs';
11
- export { EebusHvacClient } from './eebus-hvac-client.cjs';
12
- export { EebusLpcClient } from './eebus-lpc-client.cjs';
11
+ export { EebusHvacClient, HvacClientOptions } from './eebus-hvac-client.cjs';
12
+ export { EebusLpcClient, LpcClientOptions } from './eebus-lpc-client.cjs';
13
13
  export { EebusLppClient } from './eebus-lpp-client.cjs';
14
14
  export { EebusMgcpClient } from './eebus-mgcp-client.cjs';
15
- export { EebusMpcClient } from './eebus-mpc-client.cjs';
16
- export { EebusOhpcfClient } from './eebus-ohpcf-client.cjs';
17
- export { EebusSetpointClient } from './eebus-setpoint-client.cjs';
15
+ export { EebusMpcClient, MpcClientOptions } from './eebus-mpc-client.cjs';
16
+ export { EebusOhpcfClient, OhpcfClientOptions } from './eebus-ohpcf-client.cjs';
17
+ export { EebusSetpointClient, SetpointClientOptions } from './eebus-setpoint-client.cjs';
18
18
  /**
19
19
  * Interface for EEbus (SHIP/SPINE) device communication in enyo packages.
20
20
  *
@@ -206,7 +206,7 @@ export declare enum EnyoDataBusMessageEnum {
206
206
  StartCalibrationV1 = "StartCalibrationV1",
207
207
  StopCalibrationV1 = "StopCalibrationV1"
208
208
  }
209
- export type EnyoDataBusMessageResolution = '10s' | '30s' | '1m' | '15m' | '1h' | '1d' | 'dynamic';
209
+ export type EnyoDataBusMessageResolution = '1s' | '10s' | '30s' | '1m' | '15m' | '1h' | '1d' | 'dynamic';
210
210
  /**
211
211
  * Optional addressing information for a {@link EnyoDataBusMessage}. When omitted
212
212
  * the message is broadcast to all subscribers; when set, the message is only