@enyo-energy/energy-app-sdk 0.0.135 → 0.0.137

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.
@@ -52,6 +52,7 @@ __exportStar(require("./packages/energy-app-energy-prices.cjs"), exports);
52
52
  __exportStar(require("./packages/energy-app-modbus-rtu.cjs"), exports);
53
53
  __exportStar(require("./types/enyo-eebus.cjs"), exports);
54
54
  __exportStar(require("./types/enyo-eebus-use-cases.cjs"), exports);
55
+ __exportStar(require("./types/enyo-eebus-features.cjs"), exports);
55
56
  __exportStar(require("./packages/energy-app-eebus.cjs"), exports);
56
57
  __exportStar(require("./types/enyo-mqtt.cjs"), exports);
57
58
  __exportStar(require("./packages/energy-app-mqtt.cjs"), exports);
@@ -36,6 +36,7 @@ export * from './packages/energy-app-energy-prices.cjs';
36
36
  export * from './packages/energy-app-modbus-rtu.cjs';
37
37
  export * from './types/enyo-eebus.cjs';
38
38
  export * from './types/enyo-eebus-use-cases.cjs';
39
+ export * from './types/enyo-eebus-features.cjs';
39
40
  export * from './packages/energy-app-eebus.cjs';
40
41
  export * from './types/enyo-mqtt.cjs';
41
42
  export * from './packages/energy-app-mqtt.cjs';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,90 @@
1
+ import { EebusRemoteFeatureCatalog } from '../../types/enyo-eebus-features.cjs';
2
+ /**
3
+ * Per-peer SPINE entity/feature catalog for paired EEbus remotes.
4
+ *
5
+ * Exposes the lib's `RemoteDevice` view — the set of entities and
6
+ * features the peer actually advertises via
7
+ * `NodeManagement.DetailedDiscoveryData`, kept in sync by the SDK as the
8
+ * remote emits `NodeManagement.NotifyChange` events.
9
+ *
10
+ * Use this service in preference to {@link EebusIdentityService.getSupportedUseCases}
11
+ * when gating package behaviour on remote capability. Non-certified peers
12
+ * and simulators routinely under-populate `NodeManagement.UseCaseData`
13
+ * while still exposing the matching SPINE features (e.g. a `LoadControl`
14
+ * server with `loadControlLimitDescriptionData` of
15
+ * `limitDirection: 'consume'` but no corresponding
16
+ * `limitationOfPowerConsumption` use case). Feature-level gates work on
17
+ * these peers; use-case gates do not.
18
+ *
19
+ * Identity, like the use-case list, is observable rather than one-shot:
20
+ * remotes add or remove entities and features after a firmware update or
21
+ * a runtime mode change. Always pair {@link get} with
22
+ * {@link onFeaturesChanged} for any package that reacts to peer
23
+ * capabilities, otherwise the package will keep operating against a
24
+ * stale snapshot.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Feature-based LPC gate that works on peers with incomplete UseCaseData
29
+ * const catalog = await eebus.features.get(ski);
30
+ * const loadControl = catalog.entities
31
+ * .flatMap(e => e.features)
32
+ * .find(f =>
33
+ * f.type === 'LoadControl'
34
+ * && f.role === 'server'
35
+ * && f.supportedFunctions.some(s => s.function === 'loadControlLimitListData'),
36
+ * );
37
+ * if (loadControl) {
38
+ * await eebus.useCases.lpc(ski).setConsumptionLimit({ value: 11000, isActive: true });
39
+ * }
40
+ *
41
+ * // React to the peer adding or removing features at runtime
42
+ * const listenerId = eebus.features.onFeaturesChanged(ski, next => {
43
+ * refreshCapabilityGates(next);
44
+ * });
45
+ * ```
46
+ */
47
+ export interface EebusFeatureCatalog {
48
+ /**
49
+ * Get the current SPINE entity/feature catalog snapshot for a remote node.
50
+ *
51
+ * The snapshot reflects the most recent `NodeManagement.DetailedDiscoveryData`
52
+ * state the SDK has observed; it does not trigger a re-fetch from the
53
+ * remote. To observe live additions, removals, and updates use
54
+ * {@link onFeaturesChanged}.
55
+ *
56
+ * If the peer identified by `ski` is not paired or not currently
57
+ * connected, the returned snapshot resolves with `found: false` and an
58
+ * empty `entities` list rather than throwing — so packages can use the
59
+ * call as a capability gate without wrapping it in `try`/`catch`.
60
+ *
61
+ * @param ski Subject Key Identifier of the remote node
62
+ * @returns The current entity/feature catalog snapshot
63
+ */
64
+ get: (ski: string) => Promise<EebusRemoteFeatureCatalog>;
65
+ /**
66
+ * Subscribe to feature/entity catalog changes for a remote node.
67
+ *
68
+ * The listener is invoked with the full updated snapshot whenever the
69
+ * lib emits `featureAdded`, `featureUpdated`, `featureRemoved`,
70
+ * `entityAdded`, or `entityRemoved` for the peer. The payload shape
71
+ * matches {@link get} so subscribers can replace their cached catalog
72
+ * on every event without diffing.
73
+ *
74
+ * Subscriptions are scoped to the peer identified by `ski`. If the
75
+ * peer disconnects, the listener remains registered and resumes
76
+ * delivering events when the peer reconnects — packages do not need
77
+ * to re-subscribe after a transient disconnect.
78
+ *
79
+ * @param ski Subject Key Identifier of the remote node
80
+ * @param listener Callback invoked with the full updated catalog snapshot
81
+ * @returns Listener ID that can be passed to {@link removeListener} to cancel
82
+ */
83
+ onFeaturesChanged: (ski: string, listener: (catalog: EebusRemoteFeatureCatalog) => void) => string;
84
+ /**
85
+ * Remove a feature-catalog listener previously registered via
86
+ * {@link onFeaturesChanged}.
87
+ * @param listenerId The ID returned by the registration method
88
+ */
89
+ removeListener: (listenerId: string) => void;
90
+ }
@@ -1,8 +1,10 @@
1
1
  import { EebusDeviceManagement } from './eebus-device-management.cjs';
2
+ import { EebusFeatureCatalog } from './eebus-feature-catalog.cjs';
2
3
  import { EebusIdentityService } from './eebus-identity-service.cjs';
3
4
  import { EebusSpineLowLevel } from './eebus-spine-low-level.cjs';
4
5
  import { EebusUseCaseRegistry } from './eebus-use-case-registry.cjs';
5
6
  export { EebusDeviceManagement } from './eebus-device-management.cjs';
7
+ export { EebusFeatureCatalog } from './eebus-feature-catalog.cjs';
6
8
  export { EebusIdentityService } from './eebus-identity-service.cjs';
7
9
  export { EebusSpineLowLevel } from './eebus-spine-low-level.cjs';
8
10
  export { EebusUseCaseRegistry } from './eebus-use-case-registry.cjs';
@@ -16,10 +18,11 @@ export { EebusSetpointClient } from './eebus-setpoint-client.cjs';
16
18
  /**
17
19
  * Interface for EEbus (SHIP/SPINE) device communication in enyo packages.
18
20
  *
19
- * The API is split into four orthogonal concerns, each its own sub-interface:
21
+ * The API is split into five orthogonal concerns, each its own sub-interface:
20
22
  *
21
23
  * - {@link devices} — SHIP-level device lifecycle: discovery, pairing, connection
22
24
  * - {@link identity} — NID: observable per-node identity, diagnosis state, use-case discovery
25
+ * - {@link features} — observable per-peer SPINE entity/feature catalog
23
26
  * - {@link useCases} — typed use-case clients: LPC, LPP, MGCP, MPC, OHPCF, Setpoint, Hvac
24
27
  * - {@link spine} — low-level SPINE escape hatch for features not yet wrapped
25
28
  *
@@ -41,16 +44,21 @@ export { EebusSetpointClient } from './eebus-setpoint-client.cjs';
41
44
  * console.log(`${identity.brandName} ${identity.deviceName} v${identity.softwareRevision}`);
42
45
  * eebus.identity.onIdentityChanged(device.ski, next => updateStatusBadge(next));
43
46
  *
44
- * // 3. Use casestyped, role-aware
45
- * const supported = await eebus.identity.getSupportedUseCases(device.ski);
46
- * if (supported.some(u => u.name === 'limitationOfPowerConsumption')) {
47
+ * // 3. Feature cataloggate behaviour on what the peer actually advertises
48
+ * const catalog = await eebus.features.get(device.ski);
49
+ * const hasLpcServer = catalog.entities
50
+ * .flatMap(e => e.features)
51
+ * .some(f => f.type === 'LoadControl' && f.role === 'server');
52
+ *
53
+ * // 4. Use cases — typed, role-aware
54
+ * if (hasLpcServer) {
47
55
  * await eebus.useCases.lpc(device.ski).setConsumptionLimit({
48
56
  * value: 11000,
49
57
  * isActive: true,
50
58
  * });
51
59
  * }
52
60
  *
53
- * // 4. Escape hatch — raw SPINE for unmodelled features
61
+ * // 5. Escape hatch — raw SPINE for unmodelled features
54
62
  * const dp = await eebus.spine.readData(device.ski, 'DeviceConfiguration', 'keyValueListData');
55
63
  * ```
56
64
  */
@@ -59,6 +67,12 @@ export interface EnergyAppEebus {
59
67
  devices: EebusDeviceManagement;
60
68
  /** EEBUS Node Identification (NID) — observable identity + use-case discovery */
61
69
  identity: EebusIdentityService;
70
+ /**
71
+ * Observable per-peer SPINE entity/feature catalog. Prefer feature-level
72
+ * gates from this catalog over use-case gates from {@link identity} when
73
+ * the peer is known to under-populate `NodeManagement.UseCaseData`.
74
+ */
75
+ features: EebusFeatureCatalog;
62
76
  /** Typed use-case clients for the implemented EEBUS use cases */
63
77
  useCases: EebusUseCaseRegistry;
64
78
  /** Low-level SPINE escape hatch for features not yet wrapped by a typed client */
@@ -122,6 +122,7 @@ var EnyoDataBusMessageEnum;
122
122
  EnyoDataBusMessageEnum["PauseChargingV1"] = "PauseChargingV1";
123
123
  EnyoDataBusMessageEnum["ResumeChargingV1"] = "ResumeChargingV1";
124
124
  EnyoDataBusMessageEnum["ChangeChargingPowerV1"] = "ChangeChargingPowerV1";
125
+ EnyoDataBusMessageEnum["ChangeChargeModeV1"] = "ChangeChargeModeV1";
125
126
  EnyoDataBusMessageEnum["SetChargingScheduleV1"] = "SetChargingScheduleV1";
126
127
  EnyoDataBusMessageEnum["StartChargeV1"] = "StartChargeV1";
127
128
  EnyoDataBusMessageEnum["StopChargeV1"] = "StopChargeV1";
@@ -162,6 +163,8 @@ var EnyoDataBusMessageEnum;
162
163
  EnyoDataBusMessageEnum["StartAirConditioningV1"] = "StartAirConditioningV1";
163
164
  EnyoDataBusMessageEnum["StopAirConditioningV1"] = "StopAirConditioningV1";
164
165
  EnyoDataBusMessageEnum["VehicleSocUpdateV1"] = "VehicleSocUpdateV1";
166
+ EnyoDataBusMessageEnum["StartCalibrationV1"] = "StartCalibrationV1";
167
+ EnyoDataBusMessageEnum["StopCalibrationV1"] = "StopCalibrationV1";
165
168
  })(EnyoDataBusMessageEnum || (exports.EnyoDataBusMessageEnum = EnyoDataBusMessageEnum = {}));
166
169
  /**
167
170
  * Possible answers an appliance can give when acknowledging a command.
@@ -162,6 +162,7 @@ export declare enum EnyoDataBusMessageEnum {
162
162
  PauseChargingV1 = "PauseChargingV1",
163
163
  ResumeChargingV1 = "ResumeChargingV1",
164
164
  ChangeChargingPowerV1 = "ChangeChargingPowerV1",
165
+ ChangeChargeModeV1 = "ChangeChargeModeV1",
165
166
  SetChargingScheduleV1 = "SetChargingScheduleV1",
166
167
  StartChargeV1 = "StartChargeV1",
167
168
  StopChargeV1 = "StopChargeV1",
@@ -201,7 +202,9 @@ export declare enum EnyoDataBusMessageEnum {
201
202
  AirConditioningTemperaturesUpdateV1 = "AirConditioningTemperaturesUpdateV1",
202
203
  StartAirConditioningV1 = "StartAirConditioningV1",
203
204
  StopAirConditioningV1 = "StopAirConditioningV1",
204
- VehicleSocUpdateV1 = "VehicleSocUpdateV1"
205
+ VehicleSocUpdateV1 = "VehicleSocUpdateV1",
206
+ StartCalibrationV1 = "StartCalibrationV1",
207
+ StopCalibrationV1 = "StopCalibrationV1"
205
208
  }
206
209
  export type EnyoDataBusMessageResolution = '10s' | '30s' | '1m' | '15m' | '1h' | '1d' | 'dynamic';
207
210
  /**
@@ -562,6 +565,36 @@ export interface EnyoDataBusChangeChargingPowerV1 extends EnyoDataBusMessage {
562
565
  reason?: EnyoDataBusCommandReason;
563
566
  };
564
567
  }
568
+ /**
569
+ * Command message to change the charge mode of an active or upcoming
570
+ * charging session on a specific charger. Allows switching between e.g.
571
+ * immediate, cost-optimized, or price-limit charging without stopping
572
+ * and restarting the session.
573
+ *
574
+ * The receiving integration should answer with an
575
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
576
+ * message's `id` to indicate whether the mode change was accepted,
577
+ * rejected, or is not supported.
578
+ */
579
+ export interface EnyoDataBusChangeChargeModeV1 extends EnyoDataBusMessage {
580
+ type: 'message';
581
+ message: EnyoDataBusMessageEnum.ChangeChargeModeV1;
582
+ /** ID of the charger appliance whose charge mode should be changed */
583
+ applianceId: string;
584
+ data: {
585
+ /** The new charge mode to apply to the session */
586
+ chargeMode: EnyoChargeModeEnum;
587
+ /**
588
+ * Optional ISO timestamp for target completion time. Relevant for
589
+ * modes such as {@link EnyoChargeModeEnum.CostOptimized} or
590
+ * {@link EnyoChargeModeEnum.PriceLimit} that need a deadline to
591
+ * plan against.
592
+ */
593
+ completeChargeAtIso?: string;
594
+ /** Optional reason why this command was issued */
595
+ reason?: EnyoDataBusCommandReason;
596
+ };
597
+ }
565
598
  export interface EnyoDataBusSetChargingScheduleV1 extends EnyoDataBusMessage {
566
599
  type: 'message';
567
600
  message: EnyoDataBusMessageEnum.SetChargingScheduleV1;
@@ -1399,3 +1432,44 @@ export interface EnyoDataBusVehicleSocUpdateV1 extends EnyoDataBusMessage {
1399
1432
  batterySizeKwh?: number;
1400
1433
  };
1401
1434
  }
1435
+ /**
1436
+ * Command message to start a calibration routine on a specific appliance.
1437
+ * Calibration is a vendor- and appliance-specific procedure (e.g. zeroing
1438
+ * a meter, learning a power range, aligning sensors); the targeted
1439
+ * integration decides what calibration entails for the given appliance.
1440
+ *
1441
+ * The receiving integration must answer with an
1442
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
1443
+ * message's `id` to indicate whether the calibration was accepted,
1444
+ * rejected, or is not supported by the appliance.
1445
+ */
1446
+ export interface EnyoDataBusStartCalibrationV1 extends EnyoDataBusMessage {
1447
+ type: 'message';
1448
+ message: EnyoDataBusMessageEnum.StartCalibrationV1;
1449
+ /** ID of the appliance to start calibration on */
1450
+ applianceId: string;
1451
+ data: {
1452
+ /** Optional reason why this command was issued */
1453
+ reason?: EnyoDataBusCommandReason;
1454
+ };
1455
+ }
1456
+ /**
1457
+ * Command message to stop a calibration routine that is currently running
1458
+ * on a specific appliance. The targeted integration is expected to abort
1459
+ * any in-progress calibration for the addressed appliance.
1460
+ *
1461
+ * The receiving integration must answer with an
1462
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
1463
+ * message's `id` to indicate whether the stop request was accepted,
1464
+ * rejected, or is not supported by the appliance.
1465
+ */
1466
+ export interface EnyoDataBusStopCalibrationV1 extends EnyoDataBusMessage {
1467
+ type: 'message';
1468
+ message: EnyoDataBusMessageEnum.StopCalibrationV1;
1469
+ /** ID of the appliance to stop calibration on */
1470
+ applianceId: string;
1471
+ data: {
1472
+ /** Optional reason why this command was issued */
1473
+ reason?: EnyoDataBusCommandReason;
1474
+ };
1475
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * Types describing the SPINE feature/entity catalog advertised by a remote
4
+ * EEbus peer.
5
+ *
6
+ * The catalog is the **authoritative source of truth** for what a peer can
7
+ * actually do. It is derived from the lib's `RemoteDevice` view, which is
8
+ * itself kept in sync with `NodeManagement.DetailedDiscoveryData` replies
9
+ * and `NodeManagement.NotifyChange` events from the remote.
10
+ *
11
+ * Prefer feature/role gates based on this catalog over use-case gates from
12
+ * {@link EebusUseCaseSupport}: many non-certified peers and simulators
13
+ * implement working SPINE features (e.g. a `LoadControl` server with a
14
+ * `loadControlLimitDescriptionData` of `limitDirection: 'consume'`) without
15
+ * advertising the matching use case in `NodeManagement.UseCaseData`.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Types describing the SPINE feature/entity catalog advertised by a remote
3
+ * EEbus peer.
4
+ *
5
+ * The catalog is the **authoritative source of truth** for what a peer can
6
+ * actually do. It is derived from the lib's `RemoteDevice` view, which is
7
+ * itself kept in sync with `NodeManagement.DetailedDiscoveryData` replies
8
+ * and `NodeManagement.NotifyChange` events from the remote.
9
+ *
10
+ * Prefer feature/role gates based on this catalog over use-case gates from
11
+ * {@link EebusUseCaseSupport}: many non-certified peers and simulators
12
+ * implement working SPINE features (e.g. a `LoadControl` server with a
13
+ * `loadControlLimitDescriptionData` of `limitDirection: 'consume'`) without
14
+ * advertising the matching use case in `NodeManagement.UseCaseData`.
15
+ */
16
+ /**
17
+ * SPINE role under which a feature is advertised by the remote node.
18
+ *
19
+ * The set is intentionally widened with `string` so that lib upgrades that
20
+ * introduce new SPINE role variants do not break consumer code that
21
+ * pattern-matches on the role.
22
+ */
23
+ export type EebusFeatureRole = 'client' | 'server' | 'special' | string;
24
+ /**
25
+ * SPINE address triple identifying a feature within the EEbus topology.
26
+ *
27
+ * - {@link entity} addresses the entity within the remote node (e.g. `[1]`
28
+ * for a flat node, `[1, 1]` when the node nests sub-entities such as a
29
+ * compressor under a heat-pump appliance).
30
+ * - {@link feature} addresses the feature within that entity.
31
+ * - {@link device} optionally carries the remote node's SPINE
32
+ * `NetworkAddressDeviceID`. Usually omitted because the surrounding
33
+ * {@link EebusRemoteFeatureCatalog.deviceAddress} already provides it.
34
+ */
35
+ export interface EebusFeatureAddress {
36
+ /** SPINE entity address — a sequence of integers identifying the entity within the node */
37
+ entity: number[];
38
+ /** SPINE feature address within the entity */
39
+ feature: number;
40
+ /** Optional SPINE `NetworkAddressDeviceID` of the remote node */
41
+ device?: string;
42
+ }
43
+ /**
44
+ * A SPINE function the remote advertises as supported on a feature,
45
+ * together with the operations (read / write) the remote permits on it.
46
+ *
47
+ * The operation payloads are intentionally opaque (`object`) — SPINE
48
+ * permits per-function filters and bindings whose shape varies by
49
+ * function and is irrelevant to most callers. Pass them through verbatim
50
+ * when forwarding to {@link EebusSpineLowLevel}.
51
+ */
52
+ export interface EebusSupportedFunction {
53
+ /** SPINE function/data-set name (e.g. `'loadControlLimitListData'`, `'measurementListData'`) */
54
+ function: string;
55
+ /** Operations the remote permits on this function */
56
+ possibleOperations: {
57
+ /** Present when the remote permits reads; payload mirrors the SPINE `read` operation parameters */
58
+ read?: object;
59
+ /** Present when the remote permits writes; payload mirrors the SPINE `write` operation parameters */
60
+ write?: object;
61
+ };
62
+ }
63
+ /**
64
+ * A single SPINE feature advertised by a remote entity.
65
+ *
66
+ * The {@link type} is a wire string (e.g. `'LoadControl'`,
67
+ * `'Measurement'`, `'DeviceClassification'`) rather than a closed enum
68
+ * so that lib upgrades that introduce new SPINE feature types do not
69
+ * break existing packages — see {@link EebusSpineLowLevel} for the same
70
+ * rationale applied to the low-level escape hatch.
71
+ */
72
+ export interface EebusRemoteFeature {
73
+ /** SPINE address triple for this feature */
74
+ address: EebusFeatureAddress;
75
+ /** SPINE feature type wire string (e.g. `'LoadControl'`, `'Measurement'`) */
76
+ type: string;
77
+ /** SPINE role under which the feature is advertised */
78
+ role: EebusFeatureRole;
79
+ /** Functions the remote advertises as supported on this feature */
80
+ supportedFunctions: EebusSupportedFunction[];
81
+ /** Optional manufacturer-provided label */
82
+ label?: string;
83
+ /** Optional manufacturer-provided description */
84
+ description?: string;
85
+ }
86
+ /**
87
+ * A SPINE entity advertised by a remote node.
88
+ *
89
+ * A node usually exposes a `DeviceInformation` entity (the node itself)
90
+ * plus one or more application-specific entities (e.g. `EVSE`, `EV`,
91
+ * `HeatPumpAppliance`, `Compressor`). Sub-entities are flattened into
92
+ * this list with their full {@link address} path preserved (e.g. `[1, 1]`
93
+ * for a compressor under a heat-pump appliance), so consumers can
94
+ * reconstruct the hierarchy when needed.
95
+ */
96
+ export interface EebusRemoteEntity {
97
+ /** SPINE entity address — a sequence of integers identifying the entity (e.g. `[1]` or `[1, 1]`) */
98
+ address: number[];
99
+ /** SPINE entity type wire string (e.g. `'HeatPumpAppliance'`, `'Compressor'`, `'EVSE'`) */
100
+ type: string;
101
+ /** Optional manufacturer-provided label */
102
+ label?: string;
103
+ /** Optional manufacturer-provided description */
104
+ description?: string;
105
+ /** Features advertised on this entity */
106
+ features: EebusRemoteFeature[];
107
+ }
108
+ /**
109
+ * Snapshot of the full SPINE entity/feature catalog advertised by a
110
+ * remote EEbus peer.
111
+ *
112
+ * Returned by {@link EebusFeatureCatalog.get} and delivered to
113
+ * {@link EebusFeatureCatalog.onFeaturesChanged} listeners. The shape is
114
+ * intentionally identical between the two so that change subscribers can
115
+ * drop and replace their cached catalog on every event without diffing.
116
+ *
117
+ * When the peer identified by {@link ski} is not known (never paired or
118
+ * not currently connected), {@link found} is `false` and {@link entities}
119
+ * is an empty array — the call resolves cleanly rather than throwing, so
120
+ * packages can use the snapshot as a feature gate without try/catch.
121
+ */
122
+ export interface EebusRemoteFeatureCatalog {
123
+ /** Subject Key Identifier of the remote node this catalog describes */
124
+ ski: string;
125
+ /** Whether the peer is currently known to the SDK (paired AND reachable) */
126
+ found: boolean;
127
+ /** Remote node's SPINE `NetworkAddressDeviceID`, when known */
128
+ deviceAddress?: string;
129
+ /** SPINE entities advertised by the remote node, flattened with their address path preserved */
130
+ entities: EebusRemoteEntity[];
131
+ }
@@ -9,7 +9,7 @@ exports.getSdkVersion = getSdkVersion;
9
9
  /**
10
10
  * Current version of the enyo Energy App SDK.
11
11
  */
12
- exports.SDK_VERSION = '0.0.135';
12
+ exports.SDK_VERSION = '0.0.137';
13
13
  /**
14
14
  * Gets the current SDK version.
15
15
  * @returns The semantic version string of the SDK
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "0.0.135";
8
+ export declare const SDK_VERSION = "0.0.137";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/dist/index.d.ts CHANGED
@@ -36,6 +36,7 @@ export * from './packages/energy-app-energy-prices.js';
36
36
  export * from './packages/energy-app-modbus-rtu.js';
37
37
  export * from './types/enyo-eebus.js';
38
38
  export * from './types/enyo-eebus-use-cases.js';
39
+ export * from './types/enyo-eebus-features.js';
39
40
  export * from './packages/energy-app-eebus.js';
40
41
  export * from './types/enyo-mqtt.js';
41
42
  export * from './packages/energy-app-mqtt.js';
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ export * from './packages/energy-app-energy-prices.js';
36
36
  export * from './packages/energy-app-modbus-rtu.js';
37
37
  export * from './types/enyo-eebus.js';
38
38
  export * from './types/enyo-eebus-use-cases.js';
39
+ export * from './types/enyo-eebus-features.js';
39
40
  export * from './packages/energy-app-eebus.js';
40
41
  export * from './types/enyo-mqtt.js';
41
42
  export * from './packages/energy-app-mqtt.js';
@@ -0,0 +1,90 @@
1
+ import { EebusRemoteFeatureCatalog } from '../../types/enyo-eebus-features.js';
2
+ /**
3
+ * Per-peer SPINE entity/feature catalog for paired EEbus remotes.
4
+ *
5
+ * Exposes the lib's `RemoteDevice` view — the set of entities and
6
+ * features the peer actually advertises via
7
+ * `NodeManagement.DetailedDiscoveryData`, kept in sync by the SDK as the
8
+ * remote emits `NodeManagement.NotifyChange` events.
9
+ *
10
+ * Use this service in preference to {@link EebusIdentityService.getSupportedUseCases}
11
+ * when gating package behaviour on remote capability. Non-certified peers
12
+ * and simulators routinely under-populate `NodeManagement.UseCaseData`
13
+ * while still exposing the matching SPINE features (e.g. a `LoadControl`
14
+ * server with `loadControlLimitDescriptionData` of
15
+ * `limitDirection: 'consume'` but no corresponding
16
+ * `limitationOfPowerConsumption` use case). Feature-level gates work on
17
+ * these peers; use-case gates do not.
18
+ *
19
+ * Identity, like the use-case list, is observable rather than one-shot:
20
+ * remotes add or remove entities and features after a firmware update or
21
+ * a runtime mode change. Always pair {@link get} with
22
+ * {@link onFeaturesChanged} for any package that reacts to peer
23
+ * capabilities, otherwise the package will keep operating against a
24
+ * stale snapshot.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Feature-based LPC gate that works on peers with incomplete UseCaseData
29
+ * const catalog = await eebus.features.get(ski);
30
+ * const loadControl = catalog.entities
31
+ * .flatMap(e => e.features)
32
+ * .find(f =>
33
+ * f.type === 'LoadControl'
34
+ * && f.role === 'server'
35
+ * && f.supportedFunctions.some(s => s.function === 'loadControlLimitListData'),
36
+ * );
37
+ * if (loadControl) {
38
+ * await eebus.useCases.lpc(ski).setConsumptionLimit({ value: 11000, isActive: true });
39
+ * }
40
+ *
41
+ * // React to the peer adding or removing features at runtime
42
+ * const listenerId = eebus.features.onFeaturesChanged(ski, next => {
43
+ * refreshCapabilityGates(next);
44
+ * });
45
+ * ```
46
+ */
47
+ export interface EebusFeatureCatalog {
48
+ /**
49
+ * Get the current SPINE entity/feature catalog snapshot for a remote node.
50
+ *
51
+ * The snapshot reflects the most recent `NodeManagement.DetailedDiscoveryData`
52
+ * state the SDK has observed; it does not trigger a re-fetch from the
53
+ * remote. To observe live additions, removals, and updates use
54
+ * {@link onFeaturesChanged}.
55
+ *
56
+ * If the peer identified by `ski` is not paired or not currently
57
+ * connected, the returned snapshot resolves with `found: false` and an
58
+ * empty `entities` list rather than throwing — so packages can use the
59
+ * call as a capability gate without wrapping it in `try`/`catch`.
60
+ *
61
+ * @param ski Subject Key Identifier of the remote node
62
+ * @returns The current entity/feature catalog snapshot
63
+ */
64
+ get: (ski: string) => Promise<EebusRemoteFeatureCatalog>;
65
+ /**
66
+ * Subscribe to feature/entity catalog changes for a remote node.
67
+ *
68
+ * The listener is invoked with the full updated snapshot whenever the
69
+ * lib emits `featureAdded`, `featureUpdated`, `featureRemoved`,
70
+ * `entityAdded`, or `entityRemoved` for the peer. The payload shape
71
+ * matches {@link get} so subscribers can replace their cached catalog
72
+ * on every event without diffing.
73
+ *
74
+ * Subscriptions are scoped to the peer identified by `ski`. If the
75
+ * peer disconnects, the listener remains registered and resumes
76
+ * delivering events when the peer reconnects — packages do not need
77
+ * to re-subscribe after a transient disconnect.
78
+ *
79
+ * @param ski Subject Key Identifier of the remote node
80
+ * @param listener Callback invoked with the full updated catalog snapshot
81
+ * @returns Listener ID that can be passed to {@link removeListener} to cancel
82
+ */
83
+ onFeaturesChanged: (ski: string, listener: (catalog: EebusRemoteFeatureCatalog) => void) => string;
84
+ /**
85
+ * Remove a feature-catalog listener previously registered via
86
+ * {@link onFeaturesChanged}.
87
+ * @param listenerId The ID returned by the registration method
88
+ */
89
+ removeListener: (listenerId: string) => void;
90
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,10 @@
1
1
  import { EebusDeviceManagement } from './eebus-device-management.js';
2
+ import { EebusFeatureCatalog } from './eebus-feature-catalog.js';
2
3
  import { EebusIdentityService } from './eebus-identity-service.js';
3
4
  import { EebusSpineLowLevel } from './eebus-spine-low-level.js';
4
5
  import { EebusUseCaseRegistry } from './eebus-use-case-registry.js';
5
6
  export { EebusDeviceManagement } from './eebus-device-management.js';
7
+ export { EebusFeatureCatalog } from './eebus-feature-catalog.js';
6
8
  export { EebusIdentityService } from './eebus-identity-service.js';
7
9
  export { EebusSpineLowLevel } from './eebus-spine-low-level.js';
8
10
  export { EebusUseCaseRegistry } from './eebus-use-case-registry.js';
@@ -16,10 +18,11 @@ export { EebusSetpointClient } from './eebus-setpoint-client.js';
16
18
  /**
17
19
  * Interface for EEbus (SHIP/SPINE) device communication in enyo packages.
18
20
  *
19
- * The API is split into four orthogonal concerns, each its own sub-interface:
21
+ * The API is split into five orthogonal concerns, each its own sub-interface:
20
22
  *
21
23
  * - {@link devices} — SHIP-level device lifecycle: discovery, pairing, connection
22
24
  * - {@link identity} — NID: observable per-node identity, diagnosis state, use-case discovery
25
+ * - {@link features} — observable per-peer SPINE entity/feature catalog
23
26
  * - {@link useCases} — typed use-case clients: LPC, LPP, MGCP, MPC, OHPCF, Setpoint, Hvac
24
27
  * - {@link spine} — low-level SPINE escape hatch for features not yet wrapped
25
28
  *
@@ -41,16 +44,21 @@ export { EebusSetpointClient } from './eebus-setpoint-client.js';
41
44
  * console.log(`${identity.brandName} ${identity.deviceName} v${identity.softwareRevision}`);
42
45
  * eebus.identity.onIdentityChanged(device.ski, next => updateStatusBadge(next));
43
46
  *
44
- * // 3. Use casestyped, role-aware
45
- * const supported = await eebus.identity.getSupportedUseCases(device.ski);
46
- * if (supported.some(u => u.name === 'limitationOfPowerConsumption')) {
47
+ * // 3. Feature cataloggate behaviour on what the peer actually advertises
48
+ * const catalog = await eebus.features.get(device.ski);
49
+ * const hasLpcServer = catalog.entities
50
+ * .flatMap(e => e.features)
51
+ * .some(f => f.type === 'LoadControl' && f.role === 'server');
52
+ *
53
+ * // 4. Use cases — typed, role-aware
54
+ * if (hasLpcServer) {
47
55
  * await eebus.useCases.lpc(device.ski).setConsumptionLimit({
48
56
  * value: 11000,
49
57
  * isActive: true,
50
58
  * });
51
59
  * }
52
60
  *
53
- * // 4. Escape hatch — raw SPINE for unmodelled features
61
+ * // 5. Escape hatch — raw SPINE for unmodelled features
54
62
  * const dp = await eebus.spine.readData(device.ski, 'DeviceConfiguration', 'keyValueListData');
55
63
  * ```
56
64
  */
@@ -59,6 +67,12 @@ export interface EnergyAppEebus {
59
67
  devices: EebusDeviceManagement;
60
68
  /** EEBUS Node Identification (NID) — observable identity + use-case discovery */
61
69
  identity: EebusIdentityService;
70
+ /**
71
+ * Observable per-peer SPINE entity/feature catalog. Prefer feature-level
72
+ * gates from this catalog over use-case gates from {@link identity} when
73
+ * the peer is known to under-populate `NodeManagement.UseCaseData`.
74
+ */
75
+ features: EebusFeatureCatalog;
62
76
  /** Typed use-case clients for the implemented EEBUS use cases */
63
77
  useCases: EebusUseCaseRegistry;
64
78
  /** Low-level SPINE escape hatch for features not yet wrapped by a typed client */
@@ -162,6 +162,7 @@ export declare enum EnyoDataBusMessageEnum {
162
162
  PauseChargingV1 = "PauseChargingV1",
163
163
  ResumeChargingV1 = "ResumeChargingV1",
164
164
  ChangeChargingPowerV1 = "ChangeChargingPowerV1",
165
+ ChangeChargeModeV1 = "ChangeChargeModeV1",
165
166
  SetChargingScheduleV1 = "SetChargingScheduleV1",
166
167
  StartChargeV1 = "StartChargeV1",
167
168
  StopChargeV1 = "StopChargeV1",
@@ -201,7 +202,9 @@ export declare enum EnyoDataBusMessageEnum {
201
202
  AirConditioningTemperaturesUpdateV1 = "AirConditioningTemperaturesUpdateV1",
202
203
  StartAirConditioningV1 = "StartAirConditioningV1",
203
204
  StopAirConditioningV1 = "StopAirConditioningV1",
204
- VehicleSocUpdateV1 = "VehicleSocUpdateV1"
205
+ VehicleSocUpdateV1 = "VehicleSocUpdateV1",
206
+ StartCalibrationV1 = "StartCalibrationV1",
207
+ StopCalibrationV1 = "StopCalibrationV1"
205
208
  }
206
209
  export type EnyoDataBusMessageResolution = '10s' | '30s' | '1m' | '15m' | '1h' | '1d' | 'dynamic';
207
210
  /**
@@ -562,6 +565,36 @@ export interface EnyoDataBusChangeChargingPowerV1 extends EnyoDataBusMessage {
562
565
  reason?: EnyoDataBusCommandReason;
563
566
  };
564
567
  }
568
+ /**
569
+ * Command message to change the charge mode of an active or upcoming
570
+ * charging session on a specific charger. Allows switching between e.g.
571
+ * immediate, cost-optimized, or price-limit charging without stopping
572
+ * and restarting the session.
573
+ *
574
+ * The receiving integration should answer with an
575
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
576
+ * message's `id` to indicate whether the mode change was accepted,
577
+ * rejected, or is not supported.
578
+ */
579
+ export interface EnyoDataBusChangeChargeModeV1 extends EnyoDataBusMessage {
580
+ type: 'message';
581
+ message: EnyoDataBusMessageEnum.ChangeChargeModeV1;
582
+ /** ID of the charger appliance whose charge mode should be changed */
583
+ applianceId: string;
584
+ data: {
585
+ /** The new charge mode to apply to the session */
586
+ chargeMode: EnyoChargeModeEnum;
587
+ /**
588
+ * Optional ISO timestamp for target completion time. Relevant for
589
+ * modes such as {@link EnyoChargeModeEnum.CostOptimized} or
590
+ * {@link EnyoChargeModeEnum.PriceLimit} that need a deadline to
591
+ * plan against.
592
+ */
593
+ completeChargeAtIso?: string;
594
+ /** Optional reason why this command was issued */
595
+ reason?: EnyoDataBusCommandReason;
596
+ };
597
+ }
565
598
  export interface EnyoDataBusSetChargingScheduleV1 extends EnyoDataBusMessage {
566
599
  type: 'message';
567
600
  message: EnyoDataBusMessageEnum.SetChargingScheduleV1;
@@ -1399,3 +1432,44 @@ export interface EnyoDataBusVehicleSocUpdateV1 extends EnyoDataBusMessage {
1399
1432
  batterySizeKwh?: number;
1400
1433
  };
1401
1434
  }
1435
+ /**
1436
+ * Command message to start a calibration routine on a specific appliance.
1437
+ * Calibration is a vendor- and appliance-specific procedure (e.g. zeroing
1438
+ * a meter, learning a power range, aligning sensors); the targeted
1439
+ * integration decides what calibration entails for the given appliance.
1440
+ *
1441
+ * The receiving integration must answer with an
1442
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
1443
+ * message's `id` to indicate whether the calibration was accepted,
1444
+ * rejected, or is not supported by the appliance.
1445
+ */
1446
+ export interface EnyoDataBusStartCalibrationV1 extends EnyoDataBusMessage {
1447
+ type: 'message';
1448
+ message: EnyoDataBusMessageEnum.StartCalibrationV1;
1449
+ /** ID of the appliance to start calibration on */
1450
+ applianceId: string;
1451
+ data: {
1452
+ /** Optional reason why this command was issued */
1453
+ reason?: EnyoDataBusCommandReason;
1454
+ };
1455
+ }
1456
+ /**
1457
+ * Command message to stop a calibration routine that is currently running
1458
+ * on a specific appliance. The targeted integration is expected to abort
1459
+ * any in-progress calibration for the addressed appliance.
1460
+ *
1461
+ * The receiving integration must answer with an
1462
+ * {@link EnyoDataBusCommandAcknowledgeV1} message that references this
1463
+ * message's `id` to indicate whether the stop request was accepted,
1464
+ * rejected, or is not supported by the appliance.
1465
+ */
1466
+ export interface EnyoDataBusStopCalibrationV1 extends EnyoDataBusMessage {
1467
+ type: 'message';
1468
+ message: EnyoDataBusMessageEnum.StopCalibrationV1;
1469
+ /** ID of the appliance to stop calibration on */
1470
+ applianceId: string;
1471
+ data: {
1472
+ /** Optional reason why this command was issued */
1473
+ reason?: EnyoDataBusCommandReason;
1474
+ };
1475
+ }
@@ -119,6 +119,7 @@ export var EnyoDataBusMessageEnum;
119
119
  EnyoDataBusMessageEnum["PauseChargingV1"] = "PauseChargingV1";
120
120
  EnyoDataBusMessageEnum["ResumeChargingV1"] = "ResumeChargingV1";
121
121
  EnyoDataBusMessageEnum["ChangeChargingPowerV1"] = "ChangeChargingPowerV1";
122
+ EnyoDataBusMessageEnum["ChangeChargeModeV1"] = "ChangeChargeModeV1";
122
123
  EnyoDataBusMessageEnum["SetChargingScheduleV1"] = "SetChargingScheduleV1";
123
124
  EnyoDataBusMessageEnum["StartChargeV1"] = "StartChargeV1";
124
125
  EnyoDataBusMessageEnum["StopChargeV1"] = "StopChargeV1";
@@ -159,6 +160,8 @@ export var EnyoDataBusMessageEnum;
159
160
  EnyoDataBusMessageEnum["StartAirConditioningV1"] = "StartAirConditioningV1";
160
161
  EnyoDataBusMessageEnum["StopAirConditioningV1"] = "StopAirConditioningV1";
161
162
  EnyoDataBusMessageEnum["VehicleSocUpdateV1"] = "VehicleSocUpdateV1";
163
+ EnyoDataBusMessageEnum["StartCalibrationV1"] = "StartCalibrationV1";
164
+ EnyoDataBusMessageEnum["StopCalibrationV1"] = "StopCalibrationV1";
162
165
  })(EnyoDataBusMessageEnum || (EnyoDataBusMessageEnum = {}));
163
166
  /**
164
167
  * Possible answers an appliance can give when acknowledging a command.
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Types describing the SPINE feature/entity catalog advertised by a remote
3
+ * EEbus peer.
4
+ *
5
+ * The catalog is the **authoritative source of truth** for what a peer can
6
+ * actually do. It is derived from the lib's `RemoteDevice` view, which is
7
+ * itself kept in sync with `NodeManagement.DetailedDiscoveryData` replies
8
+ * and `NodeManagement.NotifyChange` events from the remote.
9
+ *
10
+ * Prefer feature/role gates based on this catalog over use-case gates from
11
+ * {@link EebusUseCaseSupport}: many non-certified peers and simulators
12
+ * implement working SPINE features (e.g. a `LoadControl` server with a
13
+ * `loadControlLimitDescriptionData` of `limitDirection: 'consume'`) without
14
+ * advertising the matching use case in `NodeManagement.UseCaseData`.
15
+ */
16
+ /**
17
+ * SPINE role under which a feature is advertised by the remote node.
18
+ *
19
+ * The set is intentionally widened with `string` so that lib upgrades that
20
+ * introduce new SPINE role variants do not break consumer code that
21
+ * pattern-matches on the role.
22
+ */
23
+ export type EebusFeatureRole = 'client' | 'server' | 'special' | string;
24
+ /**
25
+ * SPINE address triple identifying a feature within the EEbus topology.
26
+ *
27
+ * - {@link entity} addresses the entity within the remote node (e.g. `[1]`
28
+ * for a flat node, `[1, 1]` when the node nests sub-entities such as a
29
+ * compressor under a heat-pump appliance).
30
+ * - {@link feature} addresses the feature within that entity.
31
+ * - {@link device} optionally carries the remote node's SPINE
32
+ * `NetworkAddressDeviceID`. Usually omitted because the surrounding
33
+ * {@link EebusRemoteFeatureCatalog.deviceAddress} already provides it.
34
+ */
35
+ export interface EebusFeatureAddress {
36
+ /** SPINE entity address — a sequence of integers identifying the entity within the node */
37
+ entity: number[];
38
+ /** SPINE feature address within the entity */
39
+ feature: number;
40
+ /** Optional SPINE `NetworkAddressDeviceID` of the remote node */
41
+ device?: string;
42
+ }
43
+ /**
44
+ * A SPINE function the remote advertises as supported on a feature,
45
+ * together with the operations (read / write) the remote permits on it.
46
+ *
47
+ * The operation payloads are intentionally opaque (`object`) — SPINE
48
+ * permits per-function filters and bindings whose shape varies by
49
+ * function and is irrelevant to most callers. Pass them through verbatim
50
+ * when forwarding to {@link EebusSpineLowLevel}.
51
+ */
52
+ export interface EebusSupportedFunction {
53
+ /** SPINE function/data-set name (e.g. `'loadControlLimitListData'`, `'measurementListData'`) */
54
+ function: string;
55
+ /** Operations the remote permits on this function */
56
+ possibleOperations: {
57
+ /** Present when the remote permits reads; payload mirrors the SPINE `read` operation parameters */
58
+ read?: object;
59
+ /** Present when the remote permits writes; payload mirrors the SPINE `write` operation parameters */
60
+ write?: object;
61
+ };
62
+ }
63
+ /**
64
+ * A single SPINE feature advertised by a remote entity.
65
+ *
66
+ * The {@link type} is a wire string (e.g. `'LoadControl'`,
67
+ * `'Measurement'`, `'DeviceClassification'`) rather than a closed enum
68
+ * so that lib upgrades that introduce new SPINE feature types do not
69
+ * break existing packages — see {@link EebusSpineLowLevel} for the same
70
+ * rationale applied to the low-level escape hatch.
71
+ */
72
+ export interface EebusRemoteFeature {
73
+ /** SPINE address triple for this feature */
74
+ address: EebusFeatureAddress;
75
+ /** SPINE feature type wire string (e.g. `'LoadControl'`, `'Measurement'`) */
76
+ type: string;
77
+ /** SPINE role under which the feature is advertised */
78
+ role: EebusFeatureRole;
79
+ /** Functions the remote advertises as supported on this feature */
80
+ supportedFunctions: EebusSupportedFunction[];
81
+ /** Optional manufacturer-provided label */
82
+ label?: string;
83
+ /** Optional manufacturer-provided description */
84
+ description?: string;
85
+ }
86
+ /**
87
+ * A SPINE entity advertised by a remote node.
88
+ *
89
+ * A node usually exposes a `DeviceInformation` entity (the node itself)
90
+ * plus one or more application-specific entities (e.g. `EVSE`, `EV`,
91
+ * `HeatPumpAppliance`, `Compressor`). Sub-entities are flattened into
92
+ * this list with their full {@link address} path preserved (e.g. `[1, 1]`
93
+ * for a compressor under a heat-pump appliance), so consumers can
94
+ * reconstruct the hierarchy when needed.
95
+ */
96
+ export interface EebusRemoteEntity {
97
+ /** SPINE entity address — a sequence of integers identifying the entity (e.g. `[1]` or `[1, 1]`) */
98
+ address: number[];
99
+ /** SPINE entity type wire string (e.g. `'HeatPumpAppliance'`, `'Compressor'`, `'EVSE'`) */
100
+ type: string;
101
+ /** Optional manufacturer-provided label */
102
+ label?: string;
103
+ /** Optional manufacturer-provided description */
104
+ description?: string;
105
+ /** Features advertised on this entity */
106
+ features: EebusRemoteFeature[];
107
+ }
108
+ /**
109
+ * Snapshot of the full SPINE entity/feature catalog advertised by a
110
+ * remote EEbus peer.
111
+ *
112
+ * Returned by {@link EebusFeatureCatalog.get} and delivered to
113
+ * {@link EebusFeatureCatalog.onFeaturesChanged} listeners. The shape is
114
+ * intentionally identical between the two so that change subscribers can
115
+ * drop and replace their cached catalog on every event without diffing.
116
+ *
117
+ * When the peer identified by {@link ski} is not known (never paired or
118
+ * not currently connected), {@link found} is `false` and {@link entities}
119
+ * is an empty array — the call resolves cleanly rather than throwing, so
120
+ * packages can use the snapshot as a feature gate without try/catch.
121
+ */
122
+ export interface EebusRemoteFeatureCatalog {
123
+ /** Subject Key Identifier of the remote node this catalog describes */
124
+ ski: string;
125
+ /** Whether the peer is currently known to the SDK (paired AND reachable) */
126
+ found: boolean;
127
+ /** Remote node's SPINE `NetworkAddressDeviceID`, when known */
128
+ deviceAddress?: string;
129
+ /** SPINE entities advertised by the remote node, flattened with their address path preserved */
130
+ entities: EebusRemoteEntity[];
131
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Types describing the SPINE feature/entity catalog advertised by a remote
3
+ * EEbus peer.
4
+ *
5
+ * The catalog is the **authoritative source of truth** for what a peer can
6
+ * actually do. It is derived from the lib's `RemoteDevice` view, which is
7
+ * itself kept in sync with `NodeManagement.DetailedDiscoveryData` replies
8
+ * and `NodeManagement.NotifyChange` events from the remote.
9
+ *
10
+ * Prefer feature/role gates based on this catalog over use-case gates from
11
+ * {@link EebusUseCaseSupport}: many non-certified peers and simulators
12
+ * implement working SPINE features (e.g. a `LoadControl` server with a
13
+ * `loadControlLimitDescriptionData` of `limitDirection: 'consume'`) without
14
+ * advertising the matching use case in `NodeManagement.UseCaseData`.
15
+ */
16
+ export {};
package/dist/version.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "0.0.135";
8
+ export declare const SDK_VERSION = "0.0.137";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/dist/version.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export const SDK_VERSION = '0.0.135';
8
+ export const SDK_VERSION = '0.0.137';
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enyo-energy/energy-app-sdk",
3
- "version": "0.0.135",
3
+ "version": "0.0.137",
4
4
  "description": "enyo Energy App SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",