@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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { EnyoCurrencyEnum } from './enyo-currency.cjs';
|
|
2
|
+
import { ForecastResolutionEnum } from './enyo-forecasting.cjs';
|
|
3
|
+
import { EnyoPriceAppliesToEnum, EnyoPriceSchedule } from './enyo-price-schedule.cjs';
|
|
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,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EnyoPriceComponentOriginEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Where a price component in a composed entry came from.
|
|
6
|
+
*/
|
|
7
|
+
var EnyoPriceComponentOriginEnum;
|
|
8
|
+
(function (EnyoPriceComponentOriginEnum) {
|
|
9
|
+
/** The component was already contained in the energy price series. */
|
|
10
|
+
EnyoPriceComponentOriginEnum["Included"] = "included";
|
|
11
|
+
/** The component was added by the composer on top of the energy price. */
|
|
12
|
+
EnyoPriceComponentOriginEnum["Added"] = "added";
|
|
13
|
+
/** No such component applies to this interval. */
|
|
14
|
+
EnyoPriceComponentOriginEnum["NotApplicable"] = "not-applicable";
|
|
15
|
+
})(EnyoPriceComponentOriginEnum || (exports.EnyoPriceComponentOriginEnum = EnyoPriceComponentOriginEnum = {}));
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { EnyoTariffBonus, TariffPriceCompositionInfo } from './enyo-electricity-tariff.cjs';
|
|
2
|
+
import { EnyoDynamicGridFeeSeries } from './enyo-grid-fee.cjs';
|
|
3
|
+
import { EnyoPriceAppliesToEnum } from './enyo-price-schedule.cjs';
|
|
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,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared scheduling primitives for time-dependent price components
|
|
4
|
+
* (dynamic grid fees and tariff bonuses).
|
|
5
|
+
*
|
|
6
|
+
* All amounts in this module are expressed **per kilowatt hour** and are always
|
|
7
|
+
* a positive magnitude — the direction is defined by the component that carries
|
|
8
|
+
* the schedule: a grid fee is *added* to the energy price, a tariff bonus is
|
|
9
|
+
* *subtracted* from it. Keeping magnitudes unsigned removes the single most
|
|
10
|
+
* common integration mistake (an inverted sign silently flipping an optimizer's
|
|
11
|
+
* decisions) and is enforced by the validators in
|
|
12
|
+
* `implementations/pricing/price-schedule-validators.ts`.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.EnyoPriceAppliesToEnum = exports.EnyoPriceScheduleTypeEnum = void 0;
|
|
16
|
+
/**
|
|
17
|
+
* The kind of schedule a price component follows.
|
|
18
|
+
*/
|
|
19
|
+
var EnyoPriceScheduleTypeEnum;
|
|
20
|
+
(function (EnyoPriceScheduleTypeEnum) {
|
|
21
|
+
/** One amount that applies at every point in time. */
|
|
22
|
+
EnyoPriceScheduleTypeEnum["Constant"] = "constant";
|
|
23
|
+
/**
|
|
24
|
+
* Calendar-recurring windows — used for high-tariff/low-tariff (HT/NT)
|
|
25
|
+
* network charges, seasonal charges, and weekday-dependent bonuses.
|
|
26
|
+
*/
|
|
27
|
+
EnyoPriceScheduleTypeEnum["Recurring"] = "recurring";
|
|
28
|
+
/**
|
|
29
|
+
* Explicit absolute time windows — used for grid fees or bonuses published
|
|
30
|
+
* as a dated series (e.g. a day-ahead publication by the grid operator).
|
|
31
|
+
*/
|
|
32
|
+
EnyoPriceScheduleTypeEnum["Absolute"] = "absolute";
|
|
33
|
+
})(EnyoPriceScheduleTypeEnum || (exports.EnyoPriceScheduleTypeEnum = EnyoPriceScheduleTypeEnum = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Which energy direction a price component applies to.
|
|
36
|
+
*/
|
|
37
|
+
var EnyoPriceAppliesToEnum;
|
|
38
|
+
(function (EnyoPriceAppliesToEnum) {
|
|
39
|
+
/** Applies to energy drawn from the grid. */
|
|
40
|
+
EnyoPriceAppliesToEnum["Consumption"] = "consumption";
|
|
41
|
+
/** Applies to energy fed into the grid. */
|
|
42
|
+
EnyoPriceAppliesToEnum["FeedIn"] = "feed-in";
|
|
43
|
+
/** Applies to both directions. */
|
|
44
|
+
EnyoPriceAppliesToEnum["Both"] = "both";
|
|
45
|
+
})(EnyoPriceAppliesToEnum || (exports.EnyoPriceAppliesToEnum = EnyoPriceAppliesToEnum = {}));
|
|
@@ -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
|
+
}
|
package/dist/cjs/version.cjs
CHANGED
package/dist/cjs/version.d.cts
CHANGED
|
@@ -14,6 +14,7 @@ export var EnergyAppPackageCategory;
|
|
|
14
14
|
EnergyAppPackageCategory["TemperatureSensor"] = "temperature-sensor";
|
|
15
15
|
EnergyAppPackageCategory["SmartPlug"] = "smart-plug";
|
|
16
16
|
EnergyAppPackageCategory["HeatingRod"] = "heating-rod";
|
|
17
|
+
EnergyAppPackageCategory["GridOperator"] = "grid-operator";
|
|
17
18
|
EnergyAppPackageCategory["Other"] = "other";
|
|
18
19
|
})(EnergyAppPackageCategory || (EnergyAppPackageCategory = {}));
|
|
19
20
|
/**
|
|
@@ -55,7 +55,9 @@ export declare enum EnergyAppPermissionTypeEnum {
|
|
|
55
55
|
Automation = "Automation",
|
|
56
56
|
Savings = "Savings",
|
|
57
57
|
EpexSpotPrices = "EpexSpotPrices",
|
|
58
|
-
FirmwareRegistry = "FirmwareRegistry"
|
|
58
|
+
FirmwareRegistry = "FirmwareRegistry",
|
|
59
|
+
GridFeeRegister = "GridFeeRegister",
|
|
60
|
+
GridFeeUse = "GridFeeUse"
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
61
63
|
* String union of every permission name, derived from
|
|
@@ -57,4 +57,6 @@ export var EnergyAppPermissionTypeEnum;
|
|
|
57
57
|
EnergyAppPermissionTypeEnum["Savings"] = "Savings";
|
|
58
58
|
EnergyAppPermissionTypeEnum["EpexSpotPrices"] = "EpexSpotPrices";
|
|
59
59
|
EnergyAppPermissionTypeEnum["FirmwareRegistry"] = "FirmwareRegistry";
|
|
60
|
+
EnergyAppPermissionTypeEnum["GridFeeRegister"] = "GridFeeRegister";
|
|
61
|
+
EnergyAppPermissionTypeEnum["GridFeeUse"] = "GridFeeUse";
|
|
60
62
|
})(EnergyAppPermissionTypeEnum || (EnergyAppPermissionTypeEnum = {}));
|
package/dist/energy-app.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ import { EnergyAppAutomation } from "./packages/energy-app-automation.js";
|
|
|
45
45
|
import { EnergyAppSavings } from "./packages/energy-app-savings.js";
|
|
46
46
|
import { EnergyAppDeviceTest } from "./packages/energy-app-device-test.js";
|
|
47
47
|
import { EnergyAppEpexSpotPrice } from "./packages/energy-app-epex-spot-price.js";
|
|
48
|
+
import { EnergyAppGridFee } from "./packages/energy-app-grid-fee.js";
|
|
48
49
|
import { UseFetchOptions } from "./types/enyo-fetch.js";
|
|
49
50
|
/**
|
|
50
51
|
* Concrete implementation of {@link EnyoEnergyAppSdk} that delegates every call
|
|
@@ -366,6 +367,20 @@ export declare class EnergyApp implements EnyoEnergyAppSdk {
|
|
|
366
367
|
* permission is not granted.
|
|
367
368
|
*/
|
|
368
369
|
useEpexSpotPrices(): EnergyAppEpexSpotPrice;
|
|
370
|
+
/**
|
|
371
|
+
* Gets the Grid Fee API for publishing time-dependent grid fees (network
|
|
372
|
+
* charges) and resolving them to a 15-minute series.
|
|
373
|
+
*
|
|
374
|
+
* Nothing published here is folded into a price automatically — provider
|
|
375
|
+
* APIs differ in whether their prices already contain the network charge, so
|
|
376
|
+
* the app that owns the tariff declares that via the tariff's
|
|
377
|
+
* `priceComposition` and composes the effective price itself with
|
|
378
|
+
* `composeElectricityPrices()`.
|
|
379
|
+
* @returns The Grid Fee API instance
|
|
380
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `GridFeeRegister` or
|
|
381
|
+
* `GridFeeUse` permission required by the called method is not granted.
|
|
382
|
+
*/
|
|
383
|
+
useGridFee(): EnergyAppGridFee;
|
|
369
384
|
/**
|
|
370
385
|
* Gets the current SDK version.
|
|
371
386
|
* @returns The semantic version string of the SDK
|
package/dist/energy-app.js
CHANGED
|
@@ -440,6 +440,22 @@ export class EnergyApp {
|
|
|
440
440
|
useEpexSpotPrices() {
|
|
441
441
|
return this.energyAppSdk.useEpexSpotPrices();
|
|
442
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Gets the Grid Fee API for publishing time-dependent grid fees (network
|
|
445
|
+
* charges) and resolving them to a 15-minute series.
|
|
446
|
+
*
|
|
447
|
+
* Nothing published here is folded into a price automatically — provider
|
|
448
|
+
* APIs differ in whether their prices already contain the network charge, so
|
|
449
|
+
* the app that owns the tariff declares that via the tariff's
|
|
450
|
+
* `priceComposition` and composes the effective price itself with
|
|
451
|
+
* `composeElectricityPrices()`.
|
|
452
|
+
* @returns The Grid Fee API instance
|
|
453
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `GridFeeRegister` or
|
|
454
|
+
* `GridFeeUse` permission required by the called method is not granted.
|
|
455
|
+
*/
|
|
456
|
+
useGridFee() {
|
|
457
|
+
return this.energyAppSdk.useGridFee();
|
|
458
|
+
}
|
|
443
459
|
/**
|
|
444
460
|
* Gets the current SDK version.
|
|
445
461
|
* @returns The semantic version string of the SDK
|
|
@@ -44,6 +44,7 @@ import { EnergyAppAutomation } from "./packages/energy-app-automation.js";
|
|
|
44
44
|
import { EnergyAppSavings } from "./packages/energy-app-savings.js";
|
|
45
45
|
import { EnergyAppDeviceTest } from "./packages/energy-app-device-test.js";
|
|
46
46
|
import { EnergyAppEpexSpotPrice } from "./packages/energy-app-epex-spot-price.js";
|
|
47
|
+
import { EnergyAppGridFee } from "./packages/energy-app-grid-fee.js";
|
|
47
48
|
import { UseFetchOptions } from "./types/enyo-fetch.js";
|
|
48
49
|
export declare enum EnergyAppStateEnum {
|
|
49
50
|
Launching = "launching",
|
|
@@ -163,4 +164,6 @@ export interface EnyoEnergyAppSdk {
|
|
|
163
164
|
useDeviceTest: () => EnergyAppDeviceTest;
|
|
164
165
|
/** Get the EPEX SPOT Price API for reading the cleared day-ahead wholesale electricity prices that apply to this device */
|
|
165
166
|
useEpexSpotPrices: () => EnergyAppEpexSpotPrice;
|
|
167
|
+
/** Get the Grid Fee API for publishing time-dependent network charges and resolving them to a 15-minute series */
|
|
168
|
+
useGridFee: () => EnergyAppGridFee;
|
|
166
169
|
}
|