@enyo-energy/energy-app-sdk 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -1
- package/dist/cjs/energy-app-package-definition.cjs +1 -0
- package/dist/cjs/energy-app-package-definition.d.cts +1 -0
- package/dist/cjs/energy-app-permission.type.cjs +2 -0
- package/dist/cjs/energy-app-permission.type.d.cts +3 -1
- package/dist/cjs/energy-app.cjs +16 -0
- package/dist/cjs/energy-app.d.cts +15 -0
- package/dist/cjs/enyo-energy-app-sdk.d.cts +3 -0
- package/dist/cjs/implementations/pricing/compose-electricity-prices.cjs +218 -0
- package/dist/cjs/implementations/pricing/compose-electricity-prices.d.cts +100 -0
- package/dist/cjs/implementations/pricing/price-component-validators.cjs +295 -0
- package/dist/cjs/implementations/pricing/price-component-validators.d.cts +90 -0
- package/dist/cjs/implementations/pricing/price-schedule-resolver.cjs +182 -0
- package/dist/cjs/implementations/pricing/price-schedule-resolver.d.cts +95 -0
- package/dist/cjs/index.cjs +7 -0
- package/dist/cjs/index.d.cts +7 -0
- package/dist/cjs/packages/energy-app-electricity-tariff.d.cts +34 -1
- package/dist/cjs/packages/energy-app-grid-fee.cjs +2 -0
- package/dist/cjs/packages/energy-app-grid-fee.d.cts +181 -0
- package/dist/cjs/types/enyo-electricity-tariff.cjs +33 -1
- package/dist/cjs/types/enyo-electricity-tariff.d.cts +161 -4
- package/dist/cjs/types/enyo-grid-fee.cjs +15 -0
- package/dist/cjs/types/enyo-grid-fee.d.cts +129 -0
- package/dist/cjs/types/enyo-price-composition.cjs +15 -0
- package/dist/cjs/types/enyo-price-composition.d.cts +126 -0
- package/dist/cjs/types/enyo-price-schedule.cjs +45 -0
- package/dist/cjs/types/enyo-price-schedule.d.cts +137 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/energy-app-package-definition.d.ts +1 -0
- package/dist/energy-app-package-definition.js +1 -0
- package/dist/energy-app-permission.type.d.ts +3 -1
- package/dist/energy-app-permission.type.js +2 -0
- package/dist/energy-app.d.ts +15 -0
- package/dist/energy-app.js +16 -0
- package/dist/enyo-energy-app-sdk.d.ts +3 -0
- package/dist/implementations/pricing/compose-electricity-prices.d.ts +100 -0
- package/dist/implementations/pricing/compose-electricity-prices.js +212 -0
- package/dist/implementations/pricing/price-component-validators.d.ts +90 -0
- package/dist/implementations/pricing/price-component-validators.js +285 -0
- package/dist/implementations/pricing/price-schedule-resolver.d.ts +95 -0
- package/dist/implementations/pricing/price-schedule-resolver.js +175 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/packages/energy-app-electricity-tariff.d.ts +34 -1
- package/dist/packages/energy-app-grid-fee.d.ts +181 -0
- package/dist/packages/energy-app-grid-fee.js +1 -0
- package/dist/types/enyo-electricity-tariff.d.ts +161 -4
- package/dist/types/enyo-electricity-tariff.js +32 -0
- package/dist/types/enyo-grid-fee.d.ts +129 -0
- package/dist/types/enyo-grid-fee.js +12 -0
- package/dist/types/enyo-price-composition.d.ts +126 -0
- package/dist/types/enyo-price-composition.js +12 -0
- package/dist/types/enyo-price-schedule.d.ts +137 -0
- package/dist/types/enyo-price-schedule.js +42 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EnyoPriceAppliesToEnum, EnyoPriceSchedule } from './enyo-price-schedule.js';
|
|
1
2
|
/**
|
|
2
3
|
* Enum representing the type of electricity tariff pricing model
|
|
3
4
|
*/
|
|
@@ -9,10 +10,119 @@ export declare enum ElectricityTariffTypeEnum {
|
|
|
9
10
|
/** Price changes dynamically based on market conditions */
|
|
10
11
|
Dynamic = "dynamic"
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* How the grid fee (network charge) of a tariff is determined.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum GridFeeModeEnum {
|
|
17
|
+
/**
|
|
18
|
+
* A single constant fee per kWh, carried by the tariff itself
|
|
19
|
+
* (see {@link DynamicTariffData.gridFeePerKwh}).
|
|
20
|
+
*/
|
|
21
|
+
Static = "static",
|
|
22
|
+
/**
|
|
23
|
+
* A time-dependent fee, read from the grid fee API with
|
|
24
|
+
* `useGridFee().getDynamicGridFees()`. The tariff only declares *that* the
|
|
25
|
+
* fee is time-dependent — which fee applies is a property of the site's grid
|
|
26
|
+
* connection, not of the tariff.
|
|
27
|
+
*/
|
|
28
|
+
Dynamic = "dynamic"
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Declares how the grid fee (network charge) that applies alongside a tariff is
|
|
32
|
+
* determined.
|
|
33
|
+
*
|
|
34
|
+
* Mixed into every tariff pricing shape: a fixed energy price combined with
|
|
35
|
+
* time-variable network charges (e.g. §14a EnWG module 3) is just as real a
|
|
36
|
+
* product as a spot-market tariff, so the declaration is not exclusive to
|
|
37
|
+
* dynamic tariffs.
|
|
38
|
+
*
|
|
39
|
+
* A grid fee itself is **not** bound to a tariff — it belongs to the site's grid
|
|
40
|
+
* connection and is registered and resolved through `useGridFee()` independently.
|
|
41
|
+
* The tariff only says whether its grid fee is a constant it carries itself or a
|
|
42
|
+
* time-dependent one to be read from that API.
|
|
43
|
+
*
|
|
44
|
+
* The grid fee is never applied automatically. Energy apps read the fee and
|
|
45
|
+
* compose the effective price themselves — see `composeElectricityPrices()`.
|
|
46
|
+
*/
|
|
47
|
+
export interface TariffGridFeeConfig {
|
|
48
|
+
/**
|
|
49
|
+
* How the grid fee is determined. Defaults to {@link GridFeeModeEnum.Static}
|
|
50
|
+
* when omitted, so tariffs registered before this field existed keep their
|
|
51
|
+
* previous behaviour.
|
|
52
|
+
*
|
|
53
|
+
* {@link GridFeeModeEnum.Dynamic} must not be combined with
|
|
54
|
+
* `priceComposition.includesGridFee === true` — a fee already contained in
|
|
55
|
+
* the tariff's prices must not be added again.
|
|
56
|
+
*/
|
|
57
|
+
gridFeeMode?: GridFeeModeEnum;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Declares which cost components are **already contained** in the prices this
|
|
61
|
+
* tariff yields.
|
|
62
|
+
*
|
|
63
|
+
* Provider APIs differ: some return all-in prices with network charges, levies
|
|
64
|
+
* and taxes baked in, others return the pure energy price. Consumers must never
|
|
65
|
+
* add a component that is already included — this declaration is what makes the
|
|
66
|
+
* difference machine-readable instead of tribal knowledge.
|
|
67
|
+
*
|
|
68
|
+
* When omitted, prices are treated as **energy price only**.
|
|
69
|
+
*/
|
|
70
|
+
export interface TariffPriceCompositionInfo {
|
|
71
|
+
/** `true` when the tariff's prices already contain the grid fee. */
|
|
72
|
+
includesGridFee: boolean;
|
|
73
|
+
/** `true` when the tariff's prices already contain taxes and levies. */
|
|
74
|
+
includesTaxesAndLevies?: boolean;
|
|
75
|
+
/** `true` when the tariff's prices already have its bonuses applied. */
|
|
76
|
+
includesBonuses?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A time-dependent discount granted on top of a tariff, expressed in currency
|
|
80
|
+
* per kWh — for example "5 ct/kWh cheaper between 22:00 and 06:00" or a
|
|
81
|
+
* promotional rebate that runs for a fixed number of months.
|
|
82
|
+
*
|
|
83
|
+
* A tariff may carry several bonuses. Amounts in {@link schedule} are positive
|
|
84
|
+
* magnitudes and are **subtracted** from the price.
|
|
85
|
+
*
|
|
86
|
+
* Consumption-quota bonuses ("the first 100 kWh each month are free") are not
|
|
87
|
+
* expressible here — they require consumption accounting that this model
|
|
88
|
+
* deliberately does not carry.
|
|
89
|
+
*/
|
|
90
|
+
export interface EnyoTariffBonus {
|
|
91
|
+
/** Unique identifier of the bonus within its tariff. */
|
|
92
|
+
id: string;
|
|
93
|
+
/** Human-readable name shown to the user, e.g. `'Nachtbonus'`. */
|
|
94
|
+
name: string;
|
|
95
|
+
/**
|
|
96
|
+
* When and how much the discount is. Amounts are positive and subtracted
|
|
97
|
+
* from the price.
|
|
98
|
+
*/
|
|
99
|
+
schedule: EnyoPriceSchedule;
|
|
100
|
+
/**
|
|
101
|
+
* IANA time zone the schedule's wall-clock times are expressed in, e.g.
|
|
102
|
+
* `'Europe/Berlin'`.
|
|
103
|
+
*/
|
|
104
|
+
timezone: string;
|
|
105
|
+
/** Whether the bonus applies to consumption, feed-in, or both. */
|
|
106
|
+
appliesTo: EnyoPriceAppliesToEnum;
|
|
107
|
+
/** Optional start of the bonus's validity in ISO format (inclusive). */
|
|
108
|
+
validFromIso?: string;
|
|
109
|
+
/** Optional end of the bonus's validity in ISO format (exclusive). */
|
|
110
|
+
validUntilIso?: string;
|
|
111
|
+
/**
|
|
112
|
+
* When `true`, this bonus suppresses every lower-priority bonus in the
|
|
113
|
+
* intervals it covers instead of stacking with them.
|
|
114
|
+
*/
|
|
115
|
+
exclusive?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Ranking used to pick between competing exclusive bonuses — higher wins.
|
|
118
|
+
* Defaults to `0`.
|
|
119
|
+
*/
|
|
120
|
+
priority?: number;
|
|
121
|
+
}
|
|
12
122
|
/**
|
|
13
123
|
* Pricing data for a static (fixed-price) electricity tariff
|
|
14
124
|
*/
|
|
15
|
-
export interface StaticTariffData {
|
|
125
|
+
export interface StaticTariffData extends TariffGridFeeConfig {
|
|
16
126
|
/** Price per kWh for consumption */
|
|
17
127
|
pricePerKwh: number;
|
|
18
128
|
/** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
|
|
@@ -21,8 +131,15 @@ export interface StaticTariffData {
|
|
|
21
131
|
/**
|
|
22
132
|
* Pricing data for a dynamic electricity tariff
|
|
23
133
|
*/
|
|
24
|
-
export interface DynamicTariffData {
|
|
25
|
-
/**
|
|
134
|
+
export interface DynamicTariffData extends TariffGridFeeConfig {
|
|
135
|
+
/**
|
|
136
|
+
* Constant price per kWh for grid fees.
|
|
137
|
+
*
|
|
138
|
+
* @deprecated Set {@link TariffGridFeeConfig.gridFeeMode} to
|
|
139
|
+
* {@link GridFeeModeEnum.Dynamic} and read the fee from
|
|
140
|
+
* `useGridFee().getDynamicGridFees()` instead. Still honoured as the
|
|
141
|
+
* constant fallback while `gridFeeMode` is Static or omitted.
|
|
142
|
+
*/
|
|
26
143
|
gridFeePerKwh?: number;
|
|
27
144
|
/** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
|
|
28
145
|
currency: string;
|
|
@@ -39,7 +156,7 @@ export interface TimeVariableScheduleEntry {
|
|
|
39
156
|
/**
|
|
40
157
|
* Pricing data for a time-variable electricity tariff
|
|
41
158
|
*/
|
|
42
|
-
export interface TimeVariableTariffData {
|
|
159
|
+
export interface TimeVariableTariffData extends TariffGridFeeConfig {
|
|
43
160
|
/** Schedule of time-based price entries */
|
|
44
161
|
schedule: TimeVariableScheduleEntry[];
|
|
45
162
|
/** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
|
|
@@ -67,6 +184,17 @@ export interface EnyoElectricityTariff {
|
|
|
67
184
|
dynamicTariffData?: DynamicTariffData;
|
|
68
185
|
/** Optional external tariff id for easy identification */
|
|
69
186
|
externalTariffId?: string;
|
|
187
|
+
/**
|
|
188
|
+
* Optional declaration of which cost components the tariff's prices already
|
|
189
|
+
* contain. Omitted means "energy price only".
|
|
190
|
+
*/
|
|
191
|
+
priceComposition?: TariffPriceCompositionInfo;
|
|
192
|
+
/**
|
|
193
|
+
* Optional discounts granted on top of this tariff. Several bonuses may
|
|
194
|
+
* apply at the same time — overlapping bonuses stack additively unless one
|
|
195
|
+
* of them is {@link EnyoTariffBonus.exclusive}.
|
|
196
|
+
*/
|
|
197
|
+
bonuses?: EnyoTariffBonus[];
|
|
70
198
|
}
|
|
71
199
|
/**
|
|
72
200
|
* Tariff registration data extended with default indicator.
|
|
@@ -76,3 +204,32 @@ export interface EnyoElectricityTariffWithDefault extends EnyoElectricityTariff
|
|
|
76
204
|
/** Indicates whether this tariff is the system default */
|
|
77
205
|
defaultTariff: boolean;
|
|
78
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* What happened to a tariff registration.
|
|
209
|
+
*/
|
|
210
|
+
export declare enum EnyoTariffChangeTypeEnum {
|
|
211
|
+
/** A new tariff was registered. */
|
|
212
|
+
Registered = "registered",
|
|
213
|
+
/** An existing tariff's attributes, grid fee link or bonuses changed. */
|
|
214
|
+
Updated = "updated",
|
|
215
|
+
/** A tariff was removed. */
|
|
216
|
+
Removed = "removed",
|
|
217
|
+
/** A different tariff became the system default. */
|
|
218
|
+
DefaultChanged = "default-changed"
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Event delivered to listeners registered via
|
|
222
|
+
* {@link EnergyAppElectricityTariff.onTariffChanged}.
|
|
223
|
+
*/
|
|
224
|
+
export interface EnyoTariffChangeEvent {
|
|
225
|
+
/** What happened. */
|
|
226
|
+
changeType: EnyoTariffChangeTypeEnum;
|
|
227
|
+
/** Identifier of the affected tariff. */
|
|
228
|
+
tariffId: string;
|
|
229
|
+
/**
|
|
230
|
+
* The tariff after the change, or `null` when it was removed. For
|
|
231
|
+
* {@link EnyoTariffChangeTypeEnum.DefaultChanged} this is the tariff that
|
|
232
|
+
* became the new default.
|
|
233
|
+
*/
|
|
234
|
+
tariff: EnyoElectricityTariffWithDefault | null;
|
|
235
|
+
}
|
|
@@ -10,3 +10,35 @@ export var ElectricityTariffTypeEnum;
|
|
|
10
10
|
/** Price changes dynamically based on market conditions */
|
|
11
11
|
ElectricityTariffTypeEnum["Dynamic"] = "dynamic";
|
|
12
12
|
})(ElectricityTariffTypeEnum || (ElectricityTariffTypeEnum = {}));
|
|
13
|
+
/**
|
|
14
|
+
* How the grid fee (network charge) of a tariff is determined.
|
|
15
|
+
*/
|
|
16
|
+
export var GridFeeModeEnum;
|
|
17
|
+
(function (GridFeeModeEnum) {
|
|
18
|
+
/**
|
|
19
|
+
* A single constant fee per kWh, carried by the tariff itself
|
|
20
|
+
* (see {@link DynamicTariffData.gridFeePerKwh}).
|
|
21
|
+
*/
|
|
22
|
+
GridFeeModeEnum["Static"] = "static";
|
|
23
|
+
/**
|
|
24
|
+
* A time-dependent fee, read from the grid fee API with
|
|
25
|
+
* `useGridFee().getDynamicGridFees()`. The tariff only declares *that* the
|
|
26
|
+
* fee is time-dependent — which fee applies is a property of the site's grid
|
|
27
|
+
* connection, not of the tariff.
|
|
28
|
+
*/
|
|
29
|
+
GridFeeModeEnum["Dynamic"] = "dynamic";
|
|
30
|
+
})(GridFeeModeEnum || (GridFeeModeEnum = {}));
|
|
31
|
+
/**
|
|
32
|
+
* What happened to a tariff registration.
|
|
33
|
+
*/
|
|
34
|
+
export var EnyoTariffChangeTypeEnum;
|
|
35
|
+
(function (EnyoTariffChangeTypeEnum) {
|
|
36
|
+
/** A new tariff was registered. */
|
|
37
|
+
EnyoTariffChangeTypeEnum["Registered"] = "registered";
|
|
38
|
+
/** An existing tariff's attributes, grid fee link or bonuses changed. */
|
|
39
|
+
EnyoTariffChangeTypeEnum["Updated"] = "updated";
|
|
40
|
+
/** A tariff was removed. */
|
|
41
|
+
EnyoTariffChangeTypeEnum["Removed"] = "removed";
|
|
42
|
+
/** A different tariff became the system default. */
|
|
43
|
+
EnyoTariffChangeTypeEnum["DefaultChanged"] = "default-changed";
|
|
44
|
+
})(EnyoTariffChangeTypeEnum || (EnyoTariffChangeTypeEnum = {}));
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { EnyoCurrencyEnum } from './enyo-currency.js';
|
|
2
|
+
import { ForecastResolutionEnum } from './enyo-forecasting.js';
|
|
3
|
+
import { EnyoPriceAppliesToEnum, EnyoPriceSchedule } from './enyo-price-schedule.js';
|
|
4
|
+
/**
|
|
5
|
+
* A registered dynamic grid fee (network charge).
|
|
6
|
+
*
|
|
7
|
+
* A grid fee is the component of the electricity price the grid operator (DSO)
|
|
8
|
+
* charges for transporting the energy. Historically it was a single constant
|
|
9
|
+
* ct/kWh value; with time-variable network charges (e.g. §14a EnWG module 3 in
|
|
10
|
+
* Germany) it varies by time of day, weekday and season, and grid operators
|
|
11
|
+
* increasingly publish it as a dated series.
|
|
12
|
+
*
|
|
13
|
+
* A fee registered here is **not** automatically applied to any price. It is
|
|
14
|
+
* published so that energy apps can read it via
|
|
15
|
+
* {@link EnergyAppGridFee.getDynamicGridFees} and compose the effective
|
|
16
|
+
* electricity price themselves — see `composeElectricityPrices()`. This is
|
|
17
|
+
* deliberate: some tariff providers already return grid-fee-inclusive prices
|
|
18
|
+
* from their own API and must not add the fee a second time.
|
|
19
|
+
*/
|
|
20
|
+
export interface EnyoDynamicGridFee {
|
|
21
|
+
/** Unique identifier of this grid fee. */
|
|
22
|
+
id: string;
|
|
23
|
+
/** Human-readable name, e.g. `'Netzentgelt HT/NT 2026'`. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Name of the grid operator (DSO) that publishes this fee. */
|
|
26
|
+
gridOperator: string;
|
|
27
|
+
/** Currency of every amount in {@link schedule}. */
|
|
28
|
+
currency: EnyoCurrencyEnum;
|
|
29
|
+
/**
|
|
30
|
+
* IANA time zone the schedule's wall-clock times are expressed in, e.g.
|
|
31
|
+
* `'Europe/Berlin'`. Required — network charge windows are published in
|
|
32
|
+
* local time and must survive daylight-saving transitions.
|
|
33
|
+
*/
|
|
34
|
+
timezone: string;
|
|
35
|
+
/** Whether the fee applies to consumption, feed-in, or both. */
|
|
36
|
+
appliesTo: EnyoPriceAppliesToEnum;
|
|
37
|
+
/** When and how much the fee is. Amounts are positive and **added** to the energy price. */
|
|
38
|
+
schedule: EnyoPriceSchedule;
|
|
39
|
+
/** Optional start of the fee's validity in ISO format (inclusive). */
|
|
40
|
+
validFromIso?: string;
|
|
41
|
+
/** Optional end of the fee's validity in ISO format (exclusive). */
|
|
42
|
+
validUntilIso?: string;
|
|
43
|
+
/** Optional metering point this fee is bound to (e.g. a German Marktlokations-ID). */
|
|
44
|
+
meteringPointId?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Marks the fee as a time-variable network charge under §14a EnWG module 3.
|
|
47
|
+
* Purely informational — it does not change how the fee is resolved.
|
|
48
|
+
*/
|
|
49
|
+
moduleThreeCompliant?: boolean;
|
|
50
|
+
/** When the fee was last registered or updated, in ISO format. Set by the host. */
|
|
51
|
+
publishedAtIso?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Registration payload for {@link EnergyAppGridFee.registerGridFee}.
|
|
55
|
+
* `publishedAtIso` is assigned by the host and therefore not part of the input.
|
|
56
|
+
*/
|
|
57
|
+
export type EnyoDynamicGridFeeRegistration = Omit<EnyoDynamicGridFee, 'publishedAtIso'>;
|
|
58
|
+
/**
|
|
59
|
+
* One resolved 15-minute interval of a dynamic grid fee.
|
|
60
|
+
*/
|
|
61
|
+
export interface EnyoDynamicGridFeeEntry {
|
|
62
|
+
/** Start of the 15-minute interval in ISO format. */
|
|
63
|
+
timestampIso: string;
|
|
64
|
+
/**
|
|
65
|
+
* Grid fee per kWh for this interval, in the series' currency. Always
|
|
66
|
+
* `>= 0`; `0` for intervals no window covers.
|
|
67
|
+
*/
|
|
68
|
+
feePerKwh: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A dynamic grid fee resolved to a flat 15-minute series over a requested range.
|
|
72
|
+
*
|
|
73
|
+
* The resolution matches {@link EnergyAppEnergyPrices.getPrices}, so entries can
|
|
74
|
+
* be zipped with a price series index-by-index once both cover the same range.
|
|
75
|
+
*/
|
|
76
|
+
export interface EnyoDynamicGridFeeSeries {
|
|
77
|
+
/** Identifier of the grid fee this series was resolved from. */
|
|
78
|
+
gridFeeId: string;
|
|
79
|
+
/** Currency of every amount in {@link entries}. */
|
|
80
|
+
currency: EnyoCurrencyEnum;
|
|
81
|
+
/** Always {@link ForecastResolutionEnum.FifteenMinutes} — present for symmetry with other price APIs. */
|
|
82
|
+
resolution: ForecastResolutionEnum;
|
|
83
|
+
/** IANA time zone the underlying schedule was resolved in. */
|
|
84
|
+
timezone: string;
|
|
85
|
+
/** Direction the fee applies to. */
|
|
86
|
+
appliesTo: EnyoPriceAppliesToEnum;
|
|
87
|
+
/** Resolved entries sorted ascending by `timestampIso`, without gaps. */
|
|
88
|
+
entries: EnyoDynamicGridFeeEntry[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Selects which grid fee to resolve, and over which range.
|
|
92
|
+
*
|
|
93
|
+
* A grid fee belongs to the site's grid connection, not to a supplier contract —
|
|
94
|
+
* so there is deliberately no tariff selector here. With no selector at all, the
|
|
95
|
+
* grid fee that applies to this device is resolved.
|
|
96
|
+
*/
|
|
97
|
+
export interface EnyoDynamicGridFeeFilter {
|
|
98
|
+
/** Start of the requested range in ISO format (inclusive). */
|
|
99
|
+
fromIso: string;
|
|
100
|
+
/** End of the requested range in ISO format (exclusive). */
|
|
101
|
+
untilIso: string;
|
|
102
|
+
/** Resolve this specific grid fee. */
|
|
103
|
+
gridFeeId?: string;
|
|
104
|
+
/** Resolve the grid fee registered for this metering point. */
|
|
105
|
+
meteringPointId?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* What happened to a grid fee registration.
|
|
109
|
+
*/
|
|
110
|
+
export declare enum EnyoGridFeeChangeTypeEnum {
|
|
111
|
+
/** A new grid fee was registered. */
|
|
112
|
+
Registered = "registered",
|
|
113
|
+
/** An existing grid fee's attributes or schedule changed. */
|
|
114
|
+
Updated = "updated",
|
|
115
|
+
/** A grid fee was removed. */
|
|
116
|
+
Removed = "removed"
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Event delivered to listeners registered via
|
|
120
|
+
* {@link EnergyAppGridFee.onGridFeeChanged}.
|
|
121
|
+
*/
|
|
122
|
+
export interface EnyoGridFeeChangeEvent {
|
|
123
|
+
/** What happened. */
|
|
124
|
+
changeType: EnyoGridFeeChangeTypeEnum;
|
|
125
|
+
/** Identifier of the affected grid fee. */
|
|
126
|
+
gridFeeId: string;
|
|
127
|
+
/** The grid fee after the change, or `null` when it was removed. */
|
|
128
|
+
gridFee: EnyoDynamicGridFee | null;
|
|
129
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What happened to a grid fee registration.
|
|
3
|
+
*/
|
|
4
|
+
export var EnyoGridFeeChangeTypeEnum;
|
|
5
|
+
(function (EnyoGridFeeChangeTypeEnum) {
|
|
6
|
+
/** A new grid fee was registered. */
|
|
7
|
+
EnyoGridFeeChangeTypeEnum["Registered"] = "registered";
|
|
8
|
+
/** An existing grid fee's attributes or schedule changed. */
|
|
9
|
+
EnyoGridFeeChangeTypeEnum["Updated"] = "updated";
|
|
10
|
+
/** A grid fee was removed. */
|
|
11
|
+
EnyoGridFeeChangeTypeEnum["Removed"] = "removed";
|
|
12
|
+
})(EnyoGridFeeChangeTypeEnum || (EnyoGridFeeChangeTypeEnum = {}));
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { EnyoTariffBonus, TariffPriceCompositionInfo } from './enyo-electricity-tariff.js';
|
|
2
|
+
import { EnyoDynamicGridFeeSeries } from './enyo-grid-fee.js';
|
|
3
|
+
import { EnyoPriceAppliesToEnum } from './enyo-price-schedule.js';
|
|
4
|
+
/**
|
|
5
|
+
* Where a price component in a composed entry came from.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum EnyoPriceComponentOriginEnum {
|
|
8
|
+
/** The component was already contained in the energy price series. */
|
|
9
|
+
Included = "included",
|
|
10
|
+
/** The component was added by the composer on top of the energy price. */
|
|
11
|
+
Added = "added",
|
|
12
|
+
/** No such component applies to this interval. */
|
|
13
|
+
NotApplicable = "not-applicable"
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A single energy price point fed into
|
|
17
|
+
* {@link composeElectricityPrices}.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately minimal so any source can be used — spot prices from
|
|
20
|
+
* `useEpexSpotPrices()`, tariff prices from `useElectricityPrices()`, or a
|
|
21
|
+
* series fetched from the provider's own API. Use
|
|
22
|
+
* `fromEnergyPriceEntries()` / `fromEpexSpotEntries()` to adapt the SDK's own
|
|
23
|
+
* shapes.
|
|
24
|
+
*/
|
|
25
|
+
export interface EnyoComposableEnergyPriceEntry {
|
|
26
|
+
/** Start of the interval in ISO format. */
|
|
27
|
+
timestampIso: string;
|
|
28
|
+
/** Energy price per kWh for this interval, in the composition's currency. */
|
|
29
|
+
pricePerKwh: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Input for {@link composeElectricityPrices}.
|
|
33
|
+
*/
|
|
34
|
+
export interface EnyoComposeElectricityPricesInput {
|
|
35
|
+
/**
|
|
36
|
+
* The energy price series to compose on top of. Entries are matched to the
|
|
37
|
+
* grid fee and bonus series by `timestampIso`, so all inputs should cover
|
|
38
|
+
* the same range at 15-minute resolution.
|
|
39
|
+
*/
|
|
40
|
+
energyPrices: EnyoComposableEnergyPriceEntry[];
|
|
41
|
+
/**
|
|
42
|
+
* What the {@link energyPrices} already contain, taken from the tariff's
|
|
43
|
+
* `priceComposition`. Components flagged as included are reported in the
|
|
44
|
+
* result but **not added again**. Omitted means "energy price only".
|
|
45
|
+
*/
|
|
46
|
+
energyPriceComposition?: TariffPriceCompositionInfo;
|
|
47
|
+
/**
|
|
48
|
+
* The resolved dynamic grid fee series, e.g. from
|
|
49
|
+
* `useGridFee().getDynamicGridFees()`. Ignored when the energy prices
|
|
50
|
+
* already include the grid fee, and may be `null` or omitted when the
|
|
51
|
+
* tariff has no dynamic grid fee.
|
|
52
|
+
*/
|
|
53
|
+
gridFees?: EnyoDynamicGridFeeSeries | null;
|
|
54
|
+
/**
|
|
55
|
+
* A constant grid fee per kWh, used when the tariff carries one instead of
|
|
56
|
+
* referencing a dynamic fee. Ignored when {@link gridFees} is given or when
|
|
57
|
+
* the energy prices already include the grid fee.
|
|
58
|
+
*/
|
|
59
|
+
constantGridFeePerKwh?: number;
|
|
60
|
+
/**
|
|
61
|
+
* The tariff's bonuses. Overlapping bonuses stack additively unless one is
|
|
62
|
+
* {@link EnyoTariffBonus.exclusive}. Ignored when the energy prices already
|
|
63
|
+
* have bonuses applied.
|
|
64
|
+
*/
|
|
65
|
+
bonuses?: EnyoTariffBonus[];
|
|
66
|
+
/**
|
|
67
|
+
* Which direction to compose for. Components whose `appliesTo` does not
|
|
68
|
+
* match are skipped. Defaults to {@link EnyoPriceAppliesToEnum.Consumption}.
|
|
69
|
+
*/
|
|
70
|
+
appliesTo?: EnyoPriceAppliesToEnum;
|
|
71
|
+
/**
|
|
72
|
+
* Optional lower bound for {@link EnyoComposedElectricityPriceEntry.effectivePricePerKwh}.
|
|
73
|
+
* Left unset by default — effective prices may legitimately go negative,
|
|
74
|
+
* because wholesale prices do.
|
|
75
|
+
*/
|
|
76
|
+
minEffectivePricePerKwh?: number;
|
|
77
|
+
/** Currency code carried through to the result, e.g. `'EUR'`. */
|
|
78
|
+
currency?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* One fully composed 15-minute price interval, with every component reported
|
|
82
|
+
* separately so a UI can explain the number and an optimizer can reason about
|
|
83
|
+
* its parts.
|
|
84
|
+
*/
|
|
85
|
+
export interface EnyoComposedElectricityPriceEntry {
|
|
86
|
+
/** Start of the interval in ISO format. */
|
|
87
|
+
timestampIso: string;
|
|
88
|
+
/**
|
|
89
|
+
* The price taken from the source series for this interval. When the source
|
|
90
|
+
* was all-in, it already contains the components whose origin is
|
|
91
|
+
* `included`.
|
|
92
|
+
*/
|
|
93
|
+
energyPricePerKwh: number;
|
|
94
|
+
/**
|
|
95
|
+
* Grid fee per kWh attributable to this interval; `0` when none applies.
|
|
96
|
+
*
|
|
97
|
+
* Reported even when {@link gridFeeOrigin} is
|
|
98
|
+
* {@link EnyoPriceComponentOriginEnum.Included} — provided a fee series was
|
|
99
|
+
* passed in — so a UI can break down an all-in price without the composer
|
|
100
|
+
* adding the amount a second time.
|
|
101
|
+
*/
|
|
102
|
+
gridFeePerKwh: number;
|
|
103
|
+
/**
|
|
104
|
+
* Whether {@link gridFeePerKwh} was added by the composer, was already part
|
|
105
|
+
* of the energy price, or does not apply.
|
|
106
|
+
*/
|
|
107
|
+
gridFeeOrigin: EnyoPriceComponentOriginEnum;
|
|
108
|
+
/** Total discount per kWh applied to this interval; `0` when none applies. */
|
|
109
|
+
bonusPerKwh: number;
|
|
110
|
+
/**
|
|
111
|
+
* Whether {@link bonusPerKwh} was applied by the composer, was already part
|
|
112
|
+
* of the energy price, or does not apply.
|
|
113
|
+
*/
|
|
114
|
+
bonusOrigin: EnyoPriceComponentOriginEnum;
|
|
115
|
+
/** Ids of the bonuses that contributed to {@link bonusPerKwh}. */
|
|
116
|
+
appliedBonusIds: string[];
|
|
117
|
+
/**
|
|
118
|
+
* The final price per kWh for this interval:
|
|
119
|
+
* `energyPricePerKwh + gridFeePerKwh - bonusPerKwh`, with components whose
|
|
120
|
+
* origin is `included` already contained in `energyPricePerKwh` and
|
|
121
|
+
* therefore not counted twice.
|
|
122
|
+
*/
|
|
123
|
+
effectivePricePerKwh: number;
|
|
124
|
+
/** Currency of every amount in this entry, when known. */
|
|
125
|
+
currency?: string;
|
|
126
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a price component in a composed entry came from.
|
|
3
|
+
*/
|
|
4
|
+
export var EnyoPriceComponentOriginEnum;
|
|
5
|
+
(function (EnyoPriceComponentOriginEnum) {
|
|
6
|
+
/** The component was already contained in the energy price series. */
|
|
7
|
+
EnyoPriceComponentOriginEnum["Included"] = "included";
|
|
8
|
+
/** The component was added by the composer on top of the energy price. */
|
|
9
|
+
EnyoPriceComponentOriginEnum["Added"] = "added";
|
|
10
|
+
/** No such component applies to this interval. */
|
|
11
|
+
EnyoPriceComponentOriginEnum["NotApplicable"] = "not-applicable";
|
|
12
|
+
})(EnyoPriceComponentOriginEnum || (EnyoPriceComponentOriginEnum = {}));
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared scheduling primitives for time-dependent price components
|
|
3
|
+
* (dynamic grid fees and tariff bonuses).
|
|
4
|
+
*
|
|
5
|
+
* All amounts in this module are expressed **per kilowatt hour** and are always
|
|
6
|
+
* a positive magnitude — the direction is defined by the component that carries
|
|
7
|
+
* the schedule: a grid fee is *added* to the energy price, a tariff bonus is
|
|
8
|
+
* *subtracted* from it. Keeping magnitudes unsigned removes the single most
|
|
9
|
+
* common integration mistake (an inverted sign silently flipping an optimizer's
|
|
10
|
+
* decisions) and is enforced by the validators in
|
|
11
|
+
* `implementations/pricing/price-schedule-validators.ts`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The kind of schedule a price component follows.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum EnyoPriceScheduleTypeEnum {
|
|
17
|
+
/** One amount that applies at every point in time. */
|
|
18
|
+
Constant = "constant",
|
|
19
|
+
/**
|
|
20
|
+
* Calendar-recurring windows — used for high-tariff/low-tariff (HT/NT)
|
|
21
|
+
* network charges, seasonal charges, and weekday-dependent bonuses.
|
|
22
|
+
*/
|
|
23
|
+
Recurring = "recurring",
|
|
24
|
+
/**
|
|
25
|
+
* Explicit absolute time windows — used for grid fees or bonuses published
|
|
26
|
+
* as a dated series (e.g. a day-ahead publication by the grid operator).
|
|
27
|
+
*/
|
|
28
|
+
Absolute = "absolute"
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Which energy direction a price component applies to.
|
|
32
|
+
*/
|
|
33
|
+
export declare enum EnyoPriceAppliesToEnum {
|
|
34
|
+
/** Applies to energy drawn from the grid. */
|
|
35
|
+
Consumption = "consumption",
|
|
36
|
+
/** Applies to energy fed into the grid. */
|
|
37
|
+
FeedIn = "feed-in",
|
|
38
|
+
/** Applies to both directions. */
|
|
39
|
+
Both = "both"
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A calendar-recurring price window.
|
|
43
|
+
*
|
|
44
|
+
* Times are wall-clock times in the owning component's `timezone`, so a window
|
|
45
|
+
* survives daylight-saving transitions: `'22:00'` stays 22:00 local time all
|
|
46
|
+
* year round.
|
|
47
|
+
*/
|
|
48
|
+
export interface EnyoRecurringPriceWindow {
|
|
49
|
+
/**
|
|
50
|
+
* Inclusive start of the window as a local wall-clock time in `HH:mm`
|
|
51
|
+
* 24-hour notation, e.g. `'22:00'`.
|
|
52
|
+
*/
|
|
53
|
+
startTimeOfDay: string;
|
|
54
|
+
/**
|
|
55
|
+
* Exclusive end of the window as a local wall-clock time in `HH:mm`
|
|
56
|
+
* notation. May be **earlier** than `startTimeOfDay`, in which case the
|
|
57
|
+
* window wraps past midnight (e.g. `'22:00'` → `'06:00'`).
|
|
58
|
+
*/
|
|
59
|
+
endTimeOfDay: string;
|
|
60
|
+
/**
|
|
61
|
+
* Days of the week the window applies to, `0` = Sunday … `6` = Saturday.
|
|
62
|
+
* Omit for "every day".
|
|
63
|
+
*
|
|
64
|
+
* For a window that wraps past midnight the day is evaluated against the
|
|
65
|
+
* day the window **starts** — a Monday 22:00–06:00 window covers Monday
|
|
66
|
+
* evening and the early hours of Tuesday.
|
|
67
|
+
*/
|
|
68
|
+
daysOfWeek?: number[];
|
|
69
|
+
/**
|
|
70
|
+
* Months the window applies to, `1` = January … `12` = December. Omit for
|
|
71
|
+
* "every month". Evaluated against the day the window starts, exactly as
|
|
72
|
+
* {@link daysOfWeek}.
|
|
73
|
+
*/
|
|
74
|
+
months?: number[];
|
|
75
|
+
/** Positive amount per kWh that applies inside the window. */
|
|
76
|
+
amountPerKwh: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* An explicit, absolutely-dated price window.
|
|
80
|
+
*/
|
|
81
|
+
export interface EnyoAbsolutePriceWindow {
|
|
82
|
+
/** Inclusive start of the window in ISO format. */
|
|
83
|
+
startIso: string;
|
|
84
|
+
/** Exclusive end of the window in ISO format. */
|
|
85
|
+
endIso: string;
|
|
86
|
+
/** Positive amount per kWh that applies inside the window. */
|
|
87
|
+
amountPerKwh: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A single amount that applies at all times.
|
|
91
|
+
*/
|
|
92
|
+
export interface EnyoConstantPriceSchedule {
|
|
93
|
+
type: EnyoPriceScheduleTypeEnum.Constant;
|
|
94
|
+
/** Positive amount per kWh, applied to every interval. */
|
|
95
|
+
amountPerKwh: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* A set of calendar-recurring windows. Intervals not covered by any window
|
|
99
|
+
* resolve to `0`.
|
|
100
|
+
*/
|
|
101
|
+
export interface EnyoRecurringPriceSchedule {
|
|
102
|
+
type: EnyoPriceScheduleTypeEnum.Recurring;
|
|
103
|
+
/** The recurring windows. Must not overlap each other. */
|
|
104
|
+
windows: EnyoRecurringPriceWindow[];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A set of absolutely-dated windows. Intervals not covered by any window
|
|
108
|
+
* resolve to `0`.
|
|
109
|
+
*/
|
|
110
|
+
export interface EnyoAbsolutePriceSchedule {
|
|
111
|
+
type: EnyoPriceScheduleTypeEnum.Absolute;
|
|
112
|
+
/** The dated windows. Must not overlap each other. */
|
|
113
|
+
windows: EnyoAbsolutePriceWindow[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Any supported price component schedule, discriminated by `type`.
|
|
117
|
+
*/
|
|
118
|
+
export type EnyoPriceSchedule = EnyoConstantPriceSchedule | EnyoRecurringPriceSchedule | EnyoAbsolutePriceSchedule;
|
|
119
|
+
/**
|
|
120
|
+
* One resolved 15-minute interval produced by expanding an
|
|
121
|
+
* {@link EnyoPriceSchedule} over a time range.
|
|
122
|
+
*/
|
|
123
|
+
export interface EnyoResolvedPriceEntry {
|
|
124
|
+
/** Start of the 15-minute interval in ISO format. */
|
|
125
|
+
timestampIso: string;
|
|
126
|
+
/** Resolved positive amount per kWh for this interval; `0` when uncovered. */
|
|
127
|
+
amountPerKwh: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Restricts a price component query to a time range.
|
|
131
|
+
*/
|
|
132
|
+
export interface EnyoPriceRangeFilter {
|
|
133
|
+
/** Start of the requested range in ISO format (inclusive). */
|
|
134
|
+
fromIso: string;
|
|
135
|
+
/** End of the requested range in ISO format (exclusive). */
|
|
136
|
+
untilIso: string;
|
|
137
|
+
}
|