@enyo-energy/energy-app-sdk 0.0.158 → 0.0.160

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.
@@ -1,4 +1,4 @@
1
- import { EnyoCharge, EnyoChargeFilter } from "../types/enyo-charge.cjs";
1
+ import { EnyoCharge, EnyoChargeFilter, EnyoDefaultChargeMode } from "../types/enyo-charge.cjs";
2
2
  /**
3
3
  * Interface for managing charging sessions in enyo packages.
4
4
  * Provides operations for charge session tracking and management.
@@ -14,4 +14,24 @@ export interface EnergyAppCharge {
14
14
  findActiveCharge: (applianceId: string) => Promise<EnyoCharge | null>;
15
15
  /** Find the currently active charge by appliance ID and transaction ID */
16
16
  findActiveChargeByTransactionId: (applianceId: string, transactionId: string) => Promise<EnyoCharge | null>;
17
+ /**
18
+ * Sets the default charging mode for a specific appliance, optionally
19
+ * with a target completion time and its timezone.
20
+ *
21
+ * **Required permission:** `EnergyManager`.
22
+ *
23
+ * @param applianceId - The appliance (charger) the default charge mode applies to.
24
+ * @param defaultChargeMode - The default charge mode configuration to apply.
25
+ * @returns Promise that resolves once the default charge mode is stored.
26
+ */
27
+ setDefaultChargeMode: (applianceId: string, defaultChargeMode: EnyoDefaultChargeMode) => Promise<void>;
28
+ /**
29
+ * Retrieves the currently configured default charging mode for a specific appliance.
30
+ *
31
+ * No permission is required to read the default charge mode.
32
+ *
33
+ * @param applianceId - The appliance (charger) to read the default charge mode for.
34
+ * @returns Promise resolving to the configured default charge mode
35
+ */
36
+ getDefaultChargeMode: (applianceId: string) => Promise<EnyoDefaultChargeMode>;
17
37
  }
@@ -1,2 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnergyAppUdpBindError = void 0;
4
+ /**
5
+ * Thrown by {@link EnergyAppUdp.bind} when the underlying socket cannot be
6
+ * bound — for example `EADDRINUSE`, an invalid multicast group address
7
+ * supplied via {@link UdpBindOptions.multicastGroups}, or a failure to join
8
+ * one of the requested groups after the socket starts listening.
9
+ *
10
+ * Implementations should wrap the originating `Error` and preserve its
11
+ * `message` so callers can `instanceof`-check this class while still
12
+ * surfacing the root cause in logs.
13
+ */
14
+ class EnergyAppUdpBindError extends Error {
15
+ /**
16
+ * Create a new `EnergyAppUdpBindError`.
17
+ *
18
+ * @param message - Human-readable description of the bind failure. Should
19
+ * include the root cause (e.g. the originating `Error`'s
20
+ * `message`) so it is preserved for logging.
21
+ */
22
+ constructor(message) {
23
+ super(message);
24
+ this.name = 'EnergyAppUdpBindError';
25
+ }
26
+ }
27
+ exports.EnergyAppUdpBindError = EnergyAppUdpBindError;
@@ -9,9 +9,37 @@ export interface UdpBindOptions {
9
9
  * sockets may bind to the same address/port. Maps to the `reuseAddr`
10
10
  * option of `node:dgram`'s `createSocket`.
11
11
  *
12
+ * Particularly useful in combination with {@link multicastGroups} so
13
+ * that multiple processes on the same host can receive the same
14
+ * multicast stream.
15
+ *
12
16
  * Defaults to `false`.
13
17
  */
14
18
  reuseAddr?: boolean;
19
+ /**
20
+ * IPv4 multicast group addresses to join after the socket is bound.
21
+ *
22
+ * Each entry must be a dotted-quad IPv4 address in the multicast range
23
+ * `224.0.0.0/4` (i.e. first octet 224–239). The runtime joins every
24
+ * listed group on the socket once the `listening` event fires; if any
25
+ * join fails or any entry is not a valid multicast address, the socket
26
+ * is closed and {@link EnergyAppUdp.bind} rejects with
27
+ * {@link EnergyAppUdpBindError}.
28
+ *
29
+ * Typical use: SMA Speedwire receivers join `239.12.255.254`.
30
+ *
31
+ * Defaults to `undefined` (no multicast membership — unicast bind only).
32
+ */
33
+ multicastGroups?: string[];
34
+ /**
35
+ * Optional local interface address (IPv4 dotted-quad) to bind the
36
+ * multicast membership(s) to. When omitted, the operating system
37
+ * selects an interface — usually the one carrying the default route.
38
+ *
39
+ * Only meaningful in combination with {@link multicastGroups}. Most
40
+ * callers should leave this `undefined`.
41
+ */
42
+ multicastInterface?: string;
15
43
  }
16
44
  /**
17
45
  * A single inbound datagram delivered to a handler registered with
@@ -84,6 +112,31 @@ export interface EnergyAppUdpSocket {
84
112
  * its `close` event.
85
113
  */
86
114
  close(): Promise<void>;
115
+ /**
116
+ * Join an additional IPv4 multicast group on this already-bound socket.
117
+ *
118
+ * The address must be a dotted-quad in the multicast range
119
+ * `224.0.0.0/4`. Implementations forward to the underlying
120
+ * `dgram.Socket.addMembership` call.
121
+ *
122
+ * @param group - IPv4 multicast group address to join.
123
+ * @param interfaceAddress - Optional local interface (IPv4 dotted-quad)
124
+ * to bind the membership to. When omitted,
125
+ * the operating system selects an interface.
126
+ * @throws If the address is not a valid multicast address, the socket
127
+ * has been closed, or the underlying join fails.
128
+ */
129
+ addMembership(group: string, interfaceAddress?: string): void;
130
+ /**
131
+ * Leave a previously joined IPv4 multicast group.
132
+ *
133
+ * @param group - IPv4 multicast group address to leave.
134
+ * @param interfaceAddress - Optional local interface (IPv4 dotted-quad)
135
+ * the membership was originally bound to.
136
+ * @throws If the address is not a valid multicast address, the socket
137
+ * has been closed, or no matching membership exists.
138
+ */
139
+ dropMembership(group: string, interfaceAddress?: string): void;
87
140
  }
88
141
  /**
89
142
  * Interface for raw UDP communication in enyo packages.
@@ -102,17 +155,54 @@ export interface EnergyAppUdpSocket {
102
155
  * socket.off(handlerId);
103
156
  * await socket.close();
104
157
  * ```
158
+ *
159
+ * @example Multicast receiver (SMA Speedwire)
160
+ * ```typescript
161
+ * const udp = energyApp.useUdp();
162
+ * const socket = await udp.bind({
163
+ * port: 9522,
164
+ * reuseAddr: true,
165
+ * multicastGroups: ['239.12.255.254'],
166
+ * });
167
+ * socket.onMessage((msg) => {
168
+ * // Inbound SMA Speedwire datagram on 239.12.255.254:9522
169
+ * });
170
+ * ```
105
171
  */
106
172
  export interface EnergyAppUdp {
107
173
  /**
108
174
  * Bind a UDP socket on the requested host/port.
109
175
  *
110
176
  * Resolves once the underlying socket has emitted its `listening` event.
177
+ * When {@link UdpBindOptions.multicastGroups} is provided, the runtime
178
+ * also joins each listed group before the returned promise resolves.
111
179
  *
112
180
  * @param options - Bind configuration (see {@link UdpBindOptions}).
113
181
  * @returns A bound socket ready to send and receive datagrams.
114
182
  * @throws {EnergyAppUdpBindError} If the requested port is already in use
115
- * (EADDRINUSE). Other errors propagate as their original Error.
183
+ * (EADDRINUSE), any entry in {@link UdpBindOptions.multicastGroups}
184
+ * is not a valid IPv4 multicast address, or joining a requested
185
+ * group fails. Other errors propagate as their original Error.
116
186
  */
117
187
  bind(options: UdpBindOptions): Promise<EnergyAppUdpSocket>;
118
188
  }
189
+ /**
190
+ * Thrown by {@link EnergyAppUdp.bind} when the underlying socket cannot be
191
+ * bound — for example `EADDRINUSE`, an invalid multicast group address
192
+ * supplied via {@link UdpBindOptions.multicastGroups}, or a failure to join
193
+ * one of the requested groups after the socket starts listening.
194
+ *
195
+ * Implementations should wrap the originating `Error` and preserve its
196
+ * `message` so callers can `instanceof`-check this class while still
197
+ * surfacing the root cause in logs.
198
+ */
199
+ export declare class EnergyAppUdpBindError extends Error {
200
+ /**
201
+ * Create a new `EnergyAppUdpBindError`.
202
+ *
203
+ * @param message - Human-readable description of the bind failure. Should
204
+ * include the root cause (e.g. the originating `Error`'s
205
+ * `message`) so it is preserved for logging.
206
+ */
207
+ constructor(message: string);
208
+ }
@@ -83,6 +83,27 @@ export interface EnyoChargeScheduleEntry {
83
83
  /** Current limit in Ampere for this schedule period */
84
84
  limitAmpere: number;
85
85
  }
86
+ /**
87
+ * Default charging preference applied to charging sessions when no
88
+ * per-session mode is explicitly provided.
89
+ */
90
+ export interface EnyoDefaultChargeMode {
91
+ /** The default charging mode (e.g. immediate, cost-optimized, price-limit) */
92
+ chargeMode: EnyoChargeModeEnum;
93
+ /**
94
+ * Optional target completion time as a wall-clock time in the
95
+ * accompanying {@link EnyoDefaultChargeMode.timezone} (e.g. `"07:30"`).
96
+ * When set, optimized modes plan the session to finish by this time.
97
+ */
98
+ completeAtTime?: string;
99
+ /**
100
+ * IANA timezone the {@link EnyoDefaultChargeMode.completeAtTime} is
101
+ * expressed in (e.g. `"Europe/Berlin"`). Should be provided whenever
102
+ * `completeAtTime` is set so the wall-clock time can be resolved
103
+ * unambiguously.
104
+ */
105
+ timezone?: string;
106
+ }
86
107
  export interface EnyoChargeFilter {
87
108
  /** Filter by specific appliance ID */
88
109
  applianceId?: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EnyoChargingProfileTypeEnum = exports.EnyoCommandAcknowledgeAnswerEnum = exports.EnyoStorageScheduleDirectionEnum = exports.EnyoStorageScheduleModeEnum = exports.EnyoDataBusMessageEnum = exports.EnyoChargeModeEnum = exports.EnyoChargingStopReason = exports.EnyoChargingMeterValueContext = exports.EnyoStringStateEnum = exports.EnyoInverterStateEnum = exports.EnyoBatteryStateEnum = exports.EnyoDataBusCommandReasonTypeEnum = void 0;
3
+ exports.EnyoChargingProfileTypeEnum = exports.EnyoCommandAcknowledgeAnswerEnum = exports.EnyoStorageScheduleDirectionEnum = exports.EnyoStorageScheduleModeEnum = exports.EnyoDataBusMessageEnum = exports.EnyoChargeInitiatorEnum = exports.EnyoChargeModeEnum = exports.EnyoChargingStopReason = exports.EnyoChargingMeterValueContext = exports.EnyoStringStateEnum = exports.EnyoInverterStateEnum = exports.EnyoBatteryStateEnum = exports.EnyoDataBusCommandReasonCategoryEnum = exports.EnyoDataBusCommandReasonTypeEnum = void 0;
4
4
  /**
5
5
  * Enum representing the reason type for why a data bus command was issued.
6
6
  * Used to attach context to commands for logging, debugging, and UI display.
@@ -23,7 +23,51 @@ var EnyoDataBusCommandReasonTypeEnum;
23
23
  EnyoDataBusCommandReasonTypeEnum["GridOperatorPowerLimitationActive"] = "grid-operator-power-limitation-active";
24
24
  /** Command issued because a grid operator power limitation is inactive */
25
25
  EnyoDataBusCommandReasonTypeEnum["GridOperatorPowerLimitationInactive"] = "grid-operator-power-limitation-inactive";
26
+ /** Command issued because the battery state of charge is low */
27
+ EnyoDataBusCommandReasonTypeEnum["BatterySoCLow"] = "battery-soc-low";
28
+ /** Command issued because the battery state of charge is high */
29
+ EnyoDataBusCommandReasonTypeEnum["BatterySoCHigh"] = "battery-soc-high";
30
+ /** Command issued to follow the planned EV charging schedule */
31
+ EnyoDataBusCommandReasonTypeEnum["EvChargingSchedule"] = "ev-charging-schedule";
32
+ /** Command issued as part of a planned/scheduled optimization */
33
+ EnyoDataBusCommandReasonTypeEnum["ScheduledOptimization"] = "scheduled-optimization";
34
+ /** Command issued because the user explicitly requested it */
35
+ EnyoDataBusCommandReasonTypeEnum["UserRequest"] = "user-request";
36
+ /** Command issued to protect the device (e.g. overheating or safety limit) */
37
+ EnyoDataBusCommandReasonTypeEnum["DeviceProtection"] = "device-protection";
38
+ /** Command issued because home consumption is high */
39
+ EnyoDataBusCommandReasonTypeEnum["HomeConsumptionHigh"] = "home-consumption-high";
40
+ /** Command issued to optimize self-consumption */
41
+ EnyoDataBusCommandReasonTypeEnum["SelfConsumptionOptimization"] = "self-consumption-optimization";
26
42
  })(EnyoDataBusCommandReasonTypeEnum || (exports.EnyoDataBusCommandReasonTypeEnum = EnyoDataBusCommandReasonTypeEnum = {}));
43
+ /**
44
+ * Coarse, machine-readable grouping of why a data bus command was issued.
45
+ * Intended for filtering, iconography, and analytics. The human-readable,
46
+ * end-user explanation lives in {@link EnyoDataBusCommandReason.translation}.
47
+ */
48
+ var EnyoDataBusCommandReasonCategoryEnum;
49
+ (function (EnyoDataBusCommandReasonCategoryEnum) {
50
+ /** Driven by the electricity price (cheap/expensive). */
51
+ EnyoDataBusCommandReasonCategoryEnum["EnergyPrice"] = "energy-price";
52
+ /** Driven by available/unavailable PV surplus. */
53
+ EnyoDataBusCommandReasonCategoryEnum["PvSurplus"] = "pv-surplus";
54
+ /** Driven by battery capacity or state of charge. */
55
+ EnyoDataBusCommandReasonCategoryEnum["BatteryState"] = "battery-state";
56
+ /** Driven by a grid operator power limitation. */
57
+ EnyoDataBusCommandReasonCategoryEnum["GridLimitation"] = "grid-limitation";
58
+ /** Driven by following a planned schedule. */
59
+ EnyoDataBusCommandReasonCategoryEnum["Schedule"] = "schedule";
60
+ /** Driven by an explicit user request. */
61
+ EnyoDataBusCommandReasonCategoryEnum["UserRequest"] = "user-request";
62
+ /** Driven by device protection / safety (e.g. overheating). */
63
+ EnyoDataBusCommandReasonCategoryEnum["DeviceProtection"] = "device-protection";
64
+ /** Driven by a temperature condition (e.g. heatpump thermal control). */
65
+ EnyoDataBusCommandReasonCategoryEnum["Temperature"] = "temperature";
66
+ /** Driven by self-consumption optimization. */
67
+ EnyoDataBusCommandReasonCategoryEnum["SelfConsumptionOptimization"] = "self-consumption-optimization";
68
+ /** Any reason not covered by the categories above. */
69
+ EnyoDataBusCommandReasonCategoryEnum["Other"] = "other";
70
+ })(EnyoDataBusCommandReasonCategoryEnum || (exports.EnyoDataBusCommandReasonCategoryEnum = EnyoDataBusCommandReasonCategoryEnum = {}));
27
71
  var EnyoBatteryStateEnum;
28
72
  (function (EnyoBatteryStateEnum) {
29
73
  EnyoBatteryStateEnum["Off"] = "off";
@@ -107,6 +151,16 @@ var EnyoChargeModeEnum;
107
151
  /** Optimize charging schedule for a maximum price limit, for example 7 ct grid or pv production */
108
152
  EnyoChargeModeEnum["PriceLimit"] = "price-limit";
109
153
  })(EnyoChargeModeEnum || (exports.EnyoChargeModeEnum = EnyoChargeModeEnum = {}));
154
+ /**
155
+ * Identifies who initiated a charging session.
156
+ */
157
+ var EnyoChargeInitiatorEnum;
158
+ (function (EnyoChargeInitiatorEnum) {
159
+ /** Session was started from the enyo app (remote/user-driven start) */
160
+ EnyoChargeInitiatorEnum["App"] = "app";
161
+ /** Session was started directly at the charger (e.g. plug-and-charge or local autostart) */
162
+ EnyoChargeInitiatorEnum["Charger"] = "charger";
163
+ })(EnyoChargeInitiatorEnum || (exports.EnyoChargeInitiatorEnum = EnyoChargeInitiatorEnum = {}));
110
164
  var EnyoDataBusMessageEnum;
111
165
  (function (EnyoDataBusMessageEnum) {
112
166
  EnyoDataBusMessageEnum["InverterValuesUpdateV1"] = "InverterValuesUpdateV1";
@@ -8,6 +8,7 @@ import { EnyoCurrencyEnum } from "./enyo-currency.cjs";
8
8
  import { EnyoHeatpumpApplianceModeEnum } from "./enyo-heatpump-appliance.cjs";
9
9
  import { EnyoAirConditioningApplianceModeEnum } from "./enyo-air-conditioning-appliance.cjs";
10
10
  import { EnergyAppPackageCategory } from "../energy-app-package-definition.cjs";
11
+ import { EnyoPackageConfigurationTranslatedValue } from "./enyo-settings.cjs";
11
12
  /**
12
13
  * Enum representing the reason type for why a data bus command was issued.
13
14
  * Used to attach context to commands for logging, debugging, and UI display.
@@ -28,7 +29,50 @@ export declare enum EnyoDataBusCommandReasonTypeEnum {
28
29
  /** Command issued because a grid operator power limitation is active */
29
30
  GridOperatorPowerLimitationActive = "grid-operator-power-limitation-active",
30
31
  /** Command issued because a grid operator power limitation is inactive */
31
- GridOperatorPowerLimitationInactive = "grid-operator-power-limitation-inactive"
32
+ GridOperatorPowerLimitationInactive = "grid-operator-power-limitation-inactive",
33
+ /** Command issued because the battery state of charge is low */
34
+ BatterySoCLow = "battery-soc-low",
35
+ /** Command issued because the battery state of charge is high */
36
+ BatterySoCHigh = "battery-soc-high",
37
+ /** Command issued to follow the planned EV charging schedule */
38
+ EvChargingSchedule = "ev-charging-schedule",
39
+ /** Command issued as part of a planned/scheduled optimization */
40
+ ScheduledOptimization = "scheduled-optimization",
41
+ /** Command issued because the user explicitly requested it */
42
+ UserRequest = "user-request",
43
+ /** Command issued to protect the device (e.g. overheating or safety limit) */
44
+ DeviceProtection = "device-protection",
45
+ /** Command issued because home consumption is high */
46
+ HomeConsumptionHigh = "home-consumption-high",
47
+ /** Command issued to optimize self-consumption */
48
+ SelfConsumptionOptimization = "self-consumption-optimization"
49
+ }
50
+ /**
51
+ * Coarse, machine-readable grouping of why a data bus command was issued.
52
+ * Intended for filtering, iconography, and analytics. The human-readable,
53
+ * end-user explanation lives in {@link EnyoDataBusCommandReason.translation}.
54
+ */
55
+ export declare enum EnyoDataBusCommandReasonCategoryEnum {
56
+ /** Driven by the electricity price (cheap/expensive). */
57
+ EnergyPrice = "energy-price",
58
+ /** Driven by available/unavailable PV surplus. */
59
+ PvSurplus = "pv-surplus",
60
+ /** Driven by battery capacity or state of charge. */
61
+ BatteryState = "battery-state",
62
+ /** Driven by a grid operator power limitation. */
63
+ GridLimitation = "grid-limitation",
64
+ /** Driven by following a planned schedule. */
65
+ Schedule = "schedule",
66
+ /** Driven by an explicit user request. */
67
+ UserRequest = "user-request",
68
+ /** Driven by device protection / safety (e.g. overheating). */
69
+ DeviceProtection = "device-protection",
70
+ /** Driven by a temperature condition (e.g. heatpump thermal control). */
71
+ Temperature = "temperature",
72
+ /** Driven by self-consumption optimization. */
73
+ SelfConsumptionOptimization = "self-consumption-optimization",
74
+ /** Any reason not covered by the categories above. */
75
+ Other = "other"
32
76
  }
33
77
  /**
34
78
  * Interface describing the reason why a data bus command was issued.
@@ -37,6 +81,10 @@ export declare enum EnyoDataBusCommandReasonTypeEnum {
37
81
  export interface EnyoDataBusCommandReason {
38
82
  /** The reason type indicating why this command was issued */
39
83
  type: EnyoDataBusCommandReasonTypeEnum;
84
+ /** Coarse category for grouping, iconography, and analytics */
85
+ category?: EnyoDataBusCommandReasonCategoryEnum;
86
+ /** Per-language, end-user-facing explanation of this reason */
87
+ translation?: EnyoPackageConfigurationTranslatedValue[];
40
88
  /** Electricity price per kWh that triggered this command */
41
89
  electricityPricePerKwh?: number;
42
90
  /** Currency of the electricity price */
@@ -47,6 +95,10 @@ export interface EnyoDataBusCommandReason {
47
95
  powerW?: number;
48
96
  /** Relevant energy in Watt hours */
49
97
  powerWh?: number;
98
+ /** Relevant temperature in Celsius (e.g. heatpump-driven reasons) */
99
+ temperatureC?: number;
100
+ /** Relevant state of charge as a percentage (battery-driven reasons) */
101
+ socPercent?: number;
50
102
  }
51
103
  export declare enum EnyoBatteryStateEnum {
52
104
  Off = "off",
@@ -125,6 +177,15 @@ export declare enum EnyoChargeModeEnum {
125
177
  /** Optimize charging schedule for a maximum price limit, for example 7 ct grid or pv production */
126
178
  PriceLimit = "price-limit"
127
179
  }
180
+ /**
181
+ * Identifies who initiated a charging session.
182
+ */
183
+ export declare enum EnyoChargeInitiatorEnum {
184
+ /** Session was started from the enyo app (remote/user-driven start) */
185
+ App = "app",
186
+ /** Session was started directly at the charger (e.g. plug-and-charge or local autostart) */
187
+ Charger = "charger"
188
+ }
128
189
  export interface EnyoAggregatedStateApplianceValues {
129
190
  powerW?: number;
130
191
  batterySoC?: number;
@@ -440,6 +501,8 @@ export interface EnyoDataBusChargingStartedV1 extends EnyoDataBusMessage {
440
501
  transactionId: string;
441
502
  /** used charging card */
442
503
  chargingCardId?: string;
504
+ /** Who initiated the charging session — the enyo app or the charger itself */
505
+ initiator: EnyoChargeInitiatorEnum;
443
506
  /** The charge mode of the started charge. If initiated by wallbox, use either user settings or immediate as default */
444
507
  chargeMode: EnyoChargeModeEnum;
445
508
  /** ISO timestamp for target completion time (optional) */
@@ -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.158';
12
+ exports.SDK_VERSION = '0.0.160';
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.158";
8
+ export declare const SDK_VERSION = "0.0.160";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -1,4 +1,4 @@
1
- import { EnyoCharge, EnyoChargeFilter } from "../types/enyo-charge.js";
1
+ import { EnyoCharge, EnyoChargeFilter, EnyoDefaultChargeMode } from "../types/enyo-charge.js";
2
2
  /**
3
3
  * Interface for managing charging sessions in enyo packages.
4
4
  * Provides operations for charge session tracking and management.
@@ -14,4 +14,24 @@ export interface EnergyAppCharge {
14
14
  findActiveCharge: (applianceId: string) => Promise<EnyoCharge | null>;
15
15
  /** Find the currently active charge by appliance ID and transaction ID */
16
16
  findActiveChargeByTransactionId: (applianceId: string, transactionId: string) => Promise<EnyoCharge | null>;
17
+ /**
18
+ * Sets the default charging mode for a specific appliance, optionally
19
+ * with a target completion time and its timezone.
20
+ *
21
+ * **Required permission:** `EnergyManager`.
22
+ *
23
+ * @param applianceId - The appliance (charger) the default charge mode applies to.
24
+ * @param defaultChargeMode - The default charge mode configuration to apply.
25
+ * @returns Promise that resolves once the default charge mode is stored.
26
+ */
27
+ setDefaultChargeMode: (applianceId: string, defaultChargeMode: EnyoDefaultChargeMode) => Promise<void>;
28
+ /**
29
+ * Retrieves the currently configured default charging mode for a specific appliance.
30
+ *
31
+ * No permission is required to read the default charge mode.
32
+ *
33
+ * @param applianceId - The appliance (charger) to read the default charge mode for.
34
+ * @returns Promise resolving to the configured default charge mode
35
+ */
36
+ getDefaultChargeMode: (applianceId: string) => Promise<EnyoDefaultChargeMode>;
17
37
  }
@@ -9,9 +9,37 @@ export interface UdpBindOptions {
9
9
  * sockets may bind to the same address/port. Maps to the `reuseAddr`
10
10
  * option of `node:dgram`'s `createSocket`.
11
11
  *
12
+ * Particularly useful in combination with {@link multicastGroups} so
13
+ * that multiple processes on the same host can receive the same
14
+ * multicast stream.
15
+ *
12
16
  * Defaults to `false`.
13
17
  */
14
18
  reuseAddr?: boolean;
19
+ /**
20
+ * IPv4 multicast group addresses to join after the socket is bound.
21
+ *
22
+ * Each entry must be a dotted-quad IPv4 address in the multicast range
23
+ * `224.0.0.0/4` (i.e. first octet 224–239). The runtime joins every
24
+ * listed group on the socket once the `listening` event fires; if any
25
+ * join fails or any entry is not a valid multicast address, the socket
26
+ * is closed and {@link EnergyAppUdp.bind} rejects with
27
+ * {@link EnergyAppUdpBindError}.
28
+ *
29
+ * Typical use: SMA Speedwire receivers join `239.12.255.254`.
30
+ *
31
+ * Defaults to `undefined` (no multicast membership — unicast bind only).
32
+ */
33
+ multicastGroups?: string[];
34
+ /**
35
+ * Optional local interface address (IPv4 dotted-quad) to bind the
36
+ * multicast membership(s) to. When omitted, the operating system
37
+ * selects an interface — usually the one carrying the default route.
38
+ *
39
+ * Only meaningful in combination with {@link multicastGroups}. Most
40
+ * callers should leave this `undefined`.
41
+ */
42
+ multicastInterface?: string;
15
43
  }
16
44
  /**
17
45
  * A single inbound datagram delivered to a handler registered with
@@ -84,6 +112,31 @@ export interface EnergyAppUdpSocket {
84
112
  * its `close` event.
85
113
  */
86
114
  close(): Promise<void>;
115
+ /**
116
+ * Join an additional IPv4 multicast group on this already-bound socket.
117
+ *
118
+ * The address must be a dotted-quad in the multicast range
119
+ * `224.0.0.0/4`. Implementations forward to the underlying
120
+ * `dgram.Socket.addMembership` call.
121
+ *
122
+ * @param group - IPv4 multicast group address to join.
123
+ * @param interfaceAddress - Optional local interface (IPv4 dotted-quad)
124
+ * to bind the membership to. When omitted,
125
+ * the operating system selects an interface.
126
+ * @throws If the address is not a valid multicast address, the socket
127
+ * has been closed, or the underlying join fails.
128
+ */
129
+ addMembership(group: string, interfaceAddress?: string): void;
130
+ /**
131
+ * Leave a previously joined IPv4 multicast group.
132
+ *
133
+ * @param group - IPv4 multicast group address to leave.
134
+ * @param interfaceAddress - Optional local interface (IPv4 dotted-quad)
135
+ * the membership was originally bound to.
136
+ * @throws If the address is not a valid multicast address, the socket
137
+ * has been closed, or no matching membership exists.
138
+ */
139
+ dropMembership(group: string, interfaceAddress?: string): void;
87
140
  }
88
141
  /**
89
142
  * Interface for raw UDP communication in enyo packages.
@@ -102,17 +155,54 @@ export interface EnergyAppUdpSocket {
102
155
  * socket.off(handlerId);
103
156
  * await socket.close();
104
157
  * ```
158
+ *
159
+ * @example Multicast receiver (SMA Speedwire)
160
+ * ```typescript
161
+ * const udp = energyApp.useUdp();
162
+ * const socket = await udp.bind({
163
+ * port: 9522,
164
+ * reuseAddr: true,
165
+ * multicastGroups: ['239.12.255.254'],
166
+ * });
167
+ * socket.onMessage((msg) => {
168
+ * // Inbound SMA Speedwire datagram on 239.12.255.254:9522
169
+ * });
170
+ * ```
105
171
  */
106
172
  export interface EnergyAppUdp {
107
173
  /**
108
174
  * Bind a UDP socket on the requested host/port.
109
175
  *
110
176
  * Resolves once the underlying socket has emitted its `listening` event.
177
+ * When {@link UdpBindOptions.multicastGroups} is provided, the runtime
178
+ * also joins each listed group before the returned promise resolves.
111
179
  *
112
180
  * @param options - Bind configuration (see {@link UdpBindOptions}).
113
181
  * @returns A bound socket ready to send and receive datagrams.
114
182
  * @throws {EnergyAppUdpBindError} If the requested port is already in use
115
- * (EADDRINUSE). Other errors propagate as their original Error.
183
+ * (EADDRINUSE), any entry in {@link UdpBindOptions.multicastGroups}
184
+ * is not a valid IPv4 multicast address, or joining a requested
185
+ * group fails. Other errors propagate as their original Error.
116
186
  */
117
187
  bind(options: UdpBindOptions): Promise<EnergyAppUdpSocket>;
118
188
  }
189
+ /**
190
+ * Thrown by {@link EnergyAppUdp.bind} when the underlying socket cannot be
191
+ * bound — for example `EADDRINUSE`, an invalid multicast group address
192
+ * supplied via {@link UdpBindOptions.multicastGroups}, or a failure to join
193
+ * one of the requested groups after the socket starts listening.
194
+ *
195
+ * Implementations should wrap the originating `Error` and preserve its
196
+ * `message` so callers can `instanceof`-check this class while still
197
+ * surfacing the root cause in logs.
198
+ */
199
+ export declare class EnergyAppUdpBindError extends Error {
200
+ /**
201
+ * Create a new `EnergyAppUdpBindError`.
202
+ *
203
+ * @param message - Human-readable description of the bind failure. Should
204
+ * include the root cause (e.g. the originating `Error`'s
205
+ * `message`) so it is preserved for logging.
206
+ */
207
+ constructor(message: string);
208
+ }
@@ -1 +1,23 @@
1
- export {};
1
+ /**
2
+ * Thrown by {@link EnergyAppUdp.bind} when the underlying socket cannot be
3
+ * bound — for example `EADDRINUSE`, an invalid multicast group address
4
+ * supplied via {@link UdpBindOptions.multicastGroups}, or a failure to join
5
+ * one of the requested groups after the socket starts listening.
6
+ *
7
+ * Implementations should wrap the originating `Error` and preserve its
8
+ * `message` so callers can `instanceof`-check this class while still
9
+ * surfacing the root cause in logs.
10
+ */
11
+ export class EnergyAppUdpBindError extends Error {
12
+ /**
13
+ * Create a new `EnergyAppUdpBindError`.
14
+ *
15
+ * @param message - Human-readable description of the bind failure. Should
16
+ * include the root cause (e.g. the originating `Error`'s
17
+ * `message`) so it is preserved for logging.
18
+ */
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = 'EnergyAppUdpBindError';
22
+ }
23
+ }
@@ -83,6 +83,27 @@ export interface EnyoChargeScheduleEntry {
83
83
  /** Current limit in Ampere for this schedule period */
84
84
  limitAmpere: number;
85
85
  }
86
+ /**
87
+ * Default charging preference applied to charging sessions when no
88
+ * per-session mode is explicitly provided.
89
+ */
90
+ export interface EnyoDefaultChargeMode {
91
+ /** The default charging mode (e.g. immediate, cost-optimized, price-limit) */
92
+ chargeMode: EnyoChargeModeEnum;
93
+ /**
94
+ * Optional target completion time as a wall-clock time in the
95
+ * accompanying {@link EnyoDefaultChargeMode.timezone} (e.g. `"07:30"`).
96
+ * When set, optimized modes plan the session to finish by this time.
97
+ */
98
+ completeAtTime?: string;
99
+ /**
100
+ * IANA timezone the {@link EnyoDefaultChargeMode.completeAtTime} is
101
+ * expressed in (e.g. `"Europe/Berlin"`). Should be provided whenever
102
+ * `completeAtTime` is set so the wall-clock time can be resolved
103
+ * unambiguously.
104
+ */
105
+ timezone?: string;
106
+ }
86
107
  export interface EnyoChargeFilter {
87
108
  /** Filter by specific appliance ID */
88
109
  applianceId?: string;
@@ -8,6 +8,7 @@ import { EnyoCurrencyEnum } from "./enyo-currency.js";
8
8
  import { EnyoHeatpumpApplianceModeEnum } from "./enyo-heatpump-appliance.js";
9
9
  import { EnyoAirConditioningApplianceModeEnum } from "./enyo-air-conditioning-appliance.js";
10
10
  import { EnergyAppPackageCategory } from "../energy-app-package-definition.js";
11
+ import { EnyoPackageConfigurationTranslatedValue } from "./enyo-settings.js";
11
12
  /**
12
13
  * Enum representing the reason type for why a data bus command was issued.
13
14
  * Used to attach context to commands for logging, debugging, and UI display.
@@ -28,7 +29,50 @@ export declare enum EnyoDataBusCommandReasonTypeEnum {
28
29
  /** Command issued because a grid operator power limitation is active */
29
30
  GridOperatorPowerLimitationActive = "grid-operator-power-limitation-active",
30
31
  /** Command issued because a grid operator power limitation is inactive */
31
- GridOperatorPowerLimitationInactive = "grid-operator-power-limitation-inactive"
32
+ GridOperatorPowerLimitationInactive = "grid-operator-power-limitation-inactive",
33
+ /** Command issued because the battery state of charge is low */
34
+ BatterySoCLow = "battery-soc-low",
35
+ /** Command issued because the battery state of charge is high */
36
+ BatterySoCHigh = "battery-soc-high",
37
+ /** Command issued to follow the planned EV charging schedule */
38
+ EvChargingSchedule = "ev-charging-schedule",
39
+ /** Command issued as part of a planned/scheduled optimization */
40
+ ScheduledOptimization = "scheduled-optimization",
41
+ /** Command issued because the user explicitly requested it */
42
+ UserRequest = "user-request",
43
+ /** Command issued to protect the device (e.g. overheating or safety limit) */
44
+ DeviceProtection = "device-protection",
45
+ /** Command issued because home consumption is high */
46
+ HomeConsumptionHigh = "home-consumption-high",
47
+ /** Command issued to optimize self-consumption */
48
+ SelfConsumptionOptimization = "self-consumption-optimization"
49
+ }
50
+ /**
51
+ * Coarse, machine-readable grouping of why a data bus command was issued.
52
+ * Intended for filtering, iconography, and analytics. The human-readable,
53
+ * end-user explanation lives in {@link EnyoDataBusCommandReason.translation}.
54
+ */
55
+ export declare enum EnyoDataBusCommandReasonCategoryEnum {
56
+ /** Driven by the electricity price (cheap/expensive). */
57
+ EnergyPrice = "energy-price",
58
+ /** Driven by available/unavailable PV surplus. */
59
+ PvSurplus = "pv-surplus",
60
+ /** Driven by battery capacity or state of charge. */
61
+ BatteryState = "battery-state",
62
+ /** Driven by a grid operator power limitation. */
63
+ GridLimitation = "grid-limitation",
64
+ /** Driven by following a planned schedule. */
65
+ Schedule = "schedule",
66
+ /** Driven by an explicit user request. */
67
+ UserRequest = "user-request",
68
+ /** Driven by device protection / safety (e.g. overheating). */
69
+ DeviceProtection = "device-protection",
70
+ /** Driven by a temperature condition (e.g. heatpump thermal control). */
71
+ Temperature = "temperature",
72
+ /** Driven by self-consumption optimization. */
73
+ SelfConsumptionOptimization = "self-consumption-optimization",
74
+ /** Any reason not covered by the categories above. */
75
+ Other = "other"
32
76
  }
33
77
  /**
34
78
  * Interface describing the reason why a data bus command was issued.
@@ -37,6 +81,10 @@ export declare enum EnyoDataBusCommandReasonTypeEnum {
37
81
  export interface EnyoDataBusCommandReason {
38
82
  /** The reason type indicating why this command was issued */
39
83
  type: EnyoDataBusCommandReasonTypeEnum;
84
+ /** Coarse category for grouping, iconography, and analytics */
85
+ category?: EnyoDataBusCommandReasonCategoryEnum;
86
+ /** Per-language, end-user-facing explanation of this reason */
87
+ translation?: EnyoPackageConfigurationTranslatedValue[];
40
88
  /** Electricity price per kWh that triggered this command */
41
89
  electricityPricePerKwh?: number;
42
90
  /** Currency of the electricity price */
@@ -47,6 +95,10 @@ export interface EnyoDataBusCommandReason {
47
95
  powerW?: number;
48
96
  /** Relevant energy in Watt hours */
49
97
  powerWh?: number;
98
+ /** Relevant temperature in Celsius (e.g. heatpump-driven reasons) */
99
+ temperatureC?: number;
100
+ /** Relevant state of charge as a percentage (battery-driven reasons) */
101
+ socPercent?: number;
50
102
  }
51
103
  export declare enum EnyoBatteryStateEnum {
52
104
  Off = "off",
@@ -125,6 +177,15 @@ export declare enum EnyoChargeModeEnum {
125
177
  /** Optimize charging schedule for a maximum price limit, for example 7 ct grid or pv production */
126
178
  PriceLimit = "price-limit"
127
179
  }
180
+ /**
181
+ * Identifies who initiated a charging session.
182
+ */
183
+ export declare enum EnyoChargeInitiatorEnum {
184
+ /** Session was started from the enyo app (remote/user-driven start) */
185
+ App = "app",
186
+ /** Session was started directly at the charger (e.g. plug-and-charge or local autostart) */
187
+ Charger = "charger"
188
+ }
128
189
  export interface EnyoAggregatedStateApplianceValues {
129
190
  powerW?: number;
130
191
  batterySoC?: number;
@@ -440,6 +501,8 @@ export interface EnyoDataBusChargingStartedV1 extends EnyoDataBusMessage {
440
501
  transactionId: string;
441
502
  /** used charging card */
442
503
  chargingCardId?: string;
504
+ /** Who initiated the charging session — the enyo app or the charger itself */
505
+ initiator: EnyoChargeInitiatorEnum;
443
506
  /** The charge mode of the started charge. If initiated by wallbox, use either user settings or immediate as default */
444
507
  chargeMode: EnyoChargeModeEnum;
445
508
  /** ISO timestamp for target completion time (optional) */
@@ -20,7 +20,51 @@ export var EnyoDataBusCommandReasonTypeEnum;
20
20
  EnyoDataBusCommandReasonTypeEnum["GridOperatorPowerLimitationActive"] = "grid-operator-power-limitation-active";
21
21
  /** Command issued because a grid operator power limitation is inactive */
22
22
  EnyoDataBusCommandReasonTypeEnum["GridOperatorPowerLimitationInactive"] = "grid-operator-power-limitation-inactive";
23
+ /** Command issued because the battery state of charge is low */
24
+ EnyoDataBusCommandReasonTypeEnum["BatterySoCLow"] = "battery-soc-low";
25
+ /** Command issued because the battery state of charge is high */
26
+ EnyoDataBusCommandReasonTypeEnum["BatterySoCHigh"] = "battery-soc-high";
27
+ /** Command issued to follow the planned EV charging schedule */
28
+ EnyoDataBusCommandReasonTypeEnum["EvChargingSchedule"] = "ev-charging-schedule";
29
+ /** Command issued as part of a planned/scheduled optimization */
30
+ EnyoDataBusCommandReasonTypeEnum["ScheduledOptimization"] = "scheduled-optimization";
31
+ /** Command issued because the user explicitly requested it */
32
+ EnyoDataBusCommandReasonTypeEnum["UserRequest"] = "user-request";
33
+ /** Command issued to protect the device (e.g. overheating or safety limit) */
34
+ EnyoDataBusCommandReasonTypeEnum["DeviceProtection"] = "device-protection";
35
+ /** Command issued because home consumption is high */
36
+ EnyoDataBusCommandReasonTypeEnum["HomeConsumptionHigh"] = "home-consumption-high";
37
+ /** Command issued to optimize self-consumption */
38
+ EnyoDataBusCommandReasonTypeEnum["SelfConsumptionOptimization"] = "self-consumption-optimization";
23
39
  })(EnyoDataBusCommandReasonTypeEnum || (EnyoDataBusCommandReasonTypeEnum = {}));
40
+ /**
41
+ * Coarse, machine-readable grouping of why a data bus command was issued.
42
+ * Intended for filtering, iconography, and analytics. The human-readable,
43
+ * end-user explanation lives in {@link EnyoDataBusCommandReason.translation}.
44
+ */
45
+ export var EnyoDataBusCommandReasonCategoryEnum;
46
+ (function (EnyoDataBusCommandReasonCategoryEnum) {
47
+ /** Driven by the electricity price (cheap/expensive). */
48
+ EnyoDataBusCommandReasonCategoryEnum["EnergyPrice"] = "energy-price";
49
+ /** Driven by available/unavailable PV surplus. */
50
+ EnyoDataBusCommandReasonCategoryEnum["PvSurplus"] = "pv-surplus";
51
+ /** Driven by battery capacity or state of charge. */
52
+ EnyoDataBusCommandReasonCategoryEnum["BatteryState"] = "battery-state";
53
+ /** Driven by a grid operator power limitation. */
54
+ EnyoDataBusCommandReasonCategoryEnum["GridLimitation"] = "grid-limitation";
55
+ /** Driven by following a planned schedule. */
56
+ EnyoDataBusCommandReasonCategoryEnum["Schedule"] = "schedule";
57
+ /** Driven by an explicit user request. */
58
+ EnyoDataBusCommandReasonCategoryEnum["UserRequest"] = "user-request";
59
+ /** Driven by device protection / safety (e.g. overheating). */
60
+ EnyoDataBusCommandReasonCategoryEnum["DeviceProtection"] = "device-protection";
61
+ /** Driven by a temperature condition (e.g. heatpump thermal control). */
62
+ EnyoDataBusCommandReasonCategoryEnum["Temperature"] = "temperature";
63
+ /** Driven by self-consumption optimization. */
64
+ EnyoDataBusCommandReasonCategoryEnum["SelfConsumptionOptimization"] = "self-consumption-optimization";
65
+ /** Any reason not covered by the categories above. */
66
+ EnyoDataBusCommandReasonCategoryEnum["Other"] = "other";
67
+ })(EnyoDataBusCommandReasonCategoryEnum || (EnyoDataBusCommandReasonCategoryEnum = {}));
24
68
  export var EnyoBatteryStateEnum;
25
69
  (function (EnyoBatteryStateEnum) {
26
70
  EnyoBatteryStateEnum["Off"] = "off";
@@ -104,6 +148,16 @@ export var EnyoChargeModeEnum;
104
148
  /** Optimize charging schedule for a maximum price limit, for example 7 ct grid or pv production */
105
149
  EnyoChargeModeEnum["PriceLimit"] = "price-limit";
106
150
  })(EnyoChargeModeEnum || (EnyoChargeModeEnum = {}));
151
+ /**
152
+ * Identifies who initiated a charging session.
153
+ */
154
+ export var EnyoChargeInitiatorEnum;
155
+ (function (EnyoChargeInitiatorEnum) {
156
+ /** Session was started from the enyo app (remote/user-driven start) */
157
+ EnyoChargeInitiatorEnum["App"] = "app";
158
+ /** Session was started directly at the charger (e.g. plug-and-charge or local autostart) */
159
+ EnyoChargeInitiatorEnum["Charger"] = "charger";
160
+ })(EnyoChargeInitiatorEnum || (EnyoChargeInitiatorEnum = {}));
107
161
  export var EnyoDataBusMessageEnum;
108
162
  (function (EnyoDataBusMessageEnum) {
109
163
  EnyoDataBusMessageEnum["InverterValuesUpdateV1"] = "InverterValuesUpdateV1";
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.158";
8
+ export declare const SDK_VERSION = "0.0.160";
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.158';
8
+ export const SDK_VERSION = '0.0.160';
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.158",
3
+ "version": "0.0.160",
4
4
  "description": "enyo Energy App SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",