@enyo-energy/energy-app-sdk 1.24.0 → 1.25.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 +15 -2
- package/dist/cjs/implementations/onboarding-v2/define-onboarding-guide-v2.cjs +9 -3
- package/dist/cjs/implementations/onboarding-v2/define-onboarding-guide-v2.d.cts +9 -3
- package/dist/cjs/implementations/onboarding-v2/onboarding-v2-validators.cjs +7 -3
- package/dist/cjs/packages/energy-app-grid-connection-point.d.cts +6 -1
- package/dist/cjs/types/enyo-charger-appliance.cjs +6 -0
- package/dist/cjs/types/enyo-charger-appliance.d.cts +7 -1
- package/dist/cjs/types/enyo-eebus.d.cts +13 -0
- package/dist/cjs/types/enyo-electricity-tariff.d.cts +9 -0
- package/dist/cjs/types/enyo-grid-connection-point.cjs +8 -0
- package/dist/cjs/types/enyo-grid-connection-point.d.cts +21 -0
- package/dist/cjs/types/enyo-onboarding-v2-eebus-device-select.d.cts +13 -1
- package/dist/cjs/types/enyo-onboarding-v2.d.cts +25 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/implementations/onboarding-v2/define-onboarding-guide-v2.d.ts +9 -3
- package/dist/implementations/onboarding-v2/define-onboarding-guide-v2.js +9 -3
- package/dist/implementations/onboarding-v2/onboarding-v2-validators.js +7 -3
- package/dist/packages/energy-app-grid-connection-point.d.ts +6 -1
- package/dist/types/enyo-charger-appliance.d.ts +7 -1
- package/dist/types/enyo-charger-appliance.js +6 -0
- package/dist/types/enyo-eebus.d.ts +13 -0
- package/dist/types/enyo-electricity-tariff.d.ts +9 -0
- package/dist/types/enyo-grid-connection-point.d.ts +21 -0
- package/dist/types/enyo-grid-connection-point.js +7 -1
- package/dist/types/enyo-onboarding-v2-eebus-device-select.d.ts +13 -1
- package/dist/types/enyo-onboarding-v2.d.ts +25 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ The SDK exposes several layered building blocks. Pick the one that matches the k
|
|
|
184
184
|
| List known WiFi SSIDs in range | [`useWifi()`](#usewifi-energyappwifi) |
|
|
185
185
|
| Query historical timeseries (PV, battery, meter, …) | [`useTimeseries()`](#usetimeseries-energyapptimeseries) |
|
|
186
186
|
| Read site location (zip or coordinates) | [`useLocation()`](#uselocation-energyapplocation) |
|
|
187
|
-
| Read grid connection point (fuse, phases, max power) | [`useGridConnectionPoint()`](#usegridconnectionpoint-energyappgridconnectionpoint) |
|
|
187
|
+
| Read grid connection point (fuse, phases, max power, charger limit) | [`useGridConnectionPoint()`](#usegridconnectionpoint-energyappgridconnectionpoint) |
|
|
188
188
|
| Retrieve secrets from the developer org secret store | [`useSecretManager()`](#usesecretmanager-energyappsecretmanager) |
|
|
189
189
|
| Submit energy-manager diagnostics | [`useDiagnostics()`](#usediagnostics-energyappdiagnostics) |
|
|
190
190
|
| Register a weather / PV / dynamic-price forecast provider | [`useWeatherForecasting()`](#useweatherforecasting-energyappweatherforecasting) / [`usePvForecasting()`](#usepvforecasting-energyapppvforecasting) / [`useDynamicPriceForecast()`](#usedynamicpriceforecast-energyappdynamicpriceforecast) |
|
|
@@ -1592,13 +1592,18 @@ if (full) console.log(`lat=${full.latitude} lon=${full.longitude}`);
|
|
|
1592
1592
|
|
|
1593
1593
|
#### `useGridConnectionPoint(): EnergyAppGridConnectionPoint`
|
|
1594
1594
|
|
|
1595
|
-
Read the site's grid connection details — main fuse rating, number of phases,
|
|
1595
|
+
Read the site's grid connection details — main fuse rating, number of phases, the maximum allowed grid power, and the total power that load balancing may allocate to EV chargers. Use this to size dispatch envelopes and avoid violating the contractual cap.
|
|
1596
|
+
|
|
1597
|
+
`chargerLimitW` is optional: when it is not configured, load balancing falls back to `DEFAULT_CHARGER_LIMIT_W` (11 kW).
|
|
1596
1598
|
|
|
1597
1599
|
```typescript
|
|
1600
|
+
import {DEFAULT_CHARGER_LIMIT_W} from "@enyo-energy/energy-app-sdk";
|
|
1601
|
+
|
|
1598
1602
|
const gcp = energyApp.useGridConnectionPoint();
|
|
1599
1603
|
const point = await gcp.getGridConnectionPoint();
|
|
1600
1604
|
if (point) {
|
|
1601
1605
|
console.log(`Fuse ${point.fuseAmpere}A across ${point.numberOfPhases} phases`);
|
|
1606
|
+
console.log(`Charger limit ${point.chargerLimitW ?? DEFAULT_CHARGER_LIMIT_W} W`);
|
|
1602
1607
|
}
|
|
1603
1608
|
```
|
|
1604
1609
|
|
|
@@ -1725,6 +1730,14 @@ await tariffs.publishPrices(EnyoTariffDirectionEnum.Consumption, {
|
|
|
1725
1730
|
});
|
|
1726
1731
|
```
|
|
1727
1732
|
|
|
1733
|
+
An entry may carry an optional `gridFeeGrossPerKwh`: the gross grid fee **contained in**
|
|
1734
|
+
`pricePerKwh`, in currency units per kWh. It is a breakdown only — `pricePerKwh` is always the
|
|
1735
|
+
total, so never compute `pricePerKwh + gridFeeGrossPerKwh`.
|
|
1736
|
+
|
|
1737
|
+
```typescript
|
|
1738
|
+
entries.push({ timestampIso: '2026-05-23T10:00:00Z', pricePerKwh: 0.31, gridFeeGrossPerKwh: 0.09 });
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1728
1741
|
**Calling `setTariff` is the activation signal.** Return `AuthenticationRequired` or
|
|
1729
1742
|
`OnboardingRequired` from the handler to have the host send the user somewhere, and carry the
|
|
1730
1743
|
`authenticationUrl` / `onboardingGuideId` that makes it actionable; when that flow later completes,
|
|
@@ -306,7 +306,11 @@ exports.onboardingV2Block = {
|
|
|
306
306
|
* Filter it. `deviceTypes` is what turns this from "here are the six EEBUS
|
|
307
307
|
* devices in the house" into "here is your heat pump", and with one match it
|
|
308
308
|
* skips the screen entirely instead of asking a question with one possible
|
|
309
|
-
* answer.
|
|
309
|
+
* answer. `vendors` narrows it further, by the `brand` a peer announces —
|
|
310
|
+
* use it where the device type cannot separate the candidates (two EEBUS
|
|
311
|
+
* heat pumps in one house), or where the guide is written for one
|
|
312
|
+
* manufacturer and must not offer a competitor's device. The two filters are
|
|
313
|
+
* conjunctive: a peer must satisfy both to be offered.
|
|
310
314
|
*
|
|
311
315
|
* The picker is drawn from what mDNS discovery found, so the guide must have
|
|
312
316
|
* scanned — keep {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its
|
|
@@ -327,8 +331,9 @@ exports.onboardingV2Block = {
|
|
|
327
331
|
* paired peer into appliances.
|
|
328
332
|
*
|
|
329
333
|
* @param id - Stable block id, unique within the guide.
|
|
330
|
-
* @param options - Screen wording, optional `deviceTypes`
|
|
331
|
-
* behaviour, and the `paired` / `not-found` / `failure`
|
|
334
|
+
* @param options - Screen wording, optional `deviceTypes` and `vendors`
|
|
335
|
+
* filters, skip behaviour, and the `paired` / `not-found` / `failure`
|
|
336
|
+
* routing handles.
|
|
332
337
|
* @returns The EEBUS device-select block.
|
|
333
338
|
*
|
|
334
339
|
* @example
|
|
@@ -336,6 +341,7 @@ exports.onboardingV2Block = {
|
|
|
336
341
|
* onboardingV2Block.eebusDeviceSelect('pair', {
|
|
337
342
|
* headline: t('Wärmepumpe auswählen', 'Select the heat pump'),
|
|
338
343
|
* deviceTypes: [EnyoEebusDeviceTypeEnum.HeatPumpAppliance],
|
|
344
|
+
* vendors: ['Vaillant'],
|
|
339
345
|
* outcomes: [
|
|
340
346
|
* {id: 'ok', value: EnyoOnboardingV2EebusPairOutcome.Paired, label: t('Gekoppelt', 'Paired')},
|
|
341
347
|
* {id: 'none', value: EnyoOnboardingV2EebusPairOutcome.NotFound, label: t('Nichts gefunden', 'Nothing found')},
|
|
@@ -254,7 +254,11 @@ export declare const onboardingV2Block: {
|
|
|
254
254
|
* Filter it. `deviceTypes` is what turns this from "here are the six EEBUS
|
|
255
255
|
* devices in the house" into "here is your heat pump", and with one match it
|
|
256
256
|
* skips the screen entirely instead of asking a question with one possible
|
|
257
|
-
* answer.
|
|
257
|
+
* answer. `vendors` narrows it further, by the `brand` a peer announces —
|
|
258
|
+
* use it where the device type cannot separate the candidates (two EEBUS
|
|
259
|
+
* heat pumps in one house), or where the guide is written for one
|
|
260
|
+
* manufacturer and must not offer a competitor's device. The two filters are
|
|
261
|
+
* conjunctive: a peer must satisfy both to be offered.
|
|
258
262
|
*
|
|
259
263
|
* The picker is drawn from what mDNS discovery found, so the guide must have
|
|
260
264
|
* scanned — keep {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its
|
|
@@ -275,8 +279,9 @@ export declare const onboardingV2Block: {
|
|
|
275
279
|
* paired peer into appliances.
|
|
276
280
|
*
|
|
277
281
|
* @param id - Stable block id, unique within the guide.
|
|
278
|
-
* @param options - Screen wording, optional `deviceTypes`
|
|
279
|
-
* behaviour, and the `paired` / `not-found` / `failure`
|
|
282
|
+
* @param options - Screen wording, optional `deviceTypes` and `vendors`
|
|
283
|
+
* filters, skip behaviour, and the `paired` / `not-found` / `failure`
|
|
284
|
+
* routing handles.
|
|
280
285
|
* @returns The EEBUS device-select block.
|
|
281
286
|
*
|
|
282
287
|
* @example
|
|
@@ -284,6 +289,7 @@ export declare const onboardingV2Block: {
|
|
|
284
289
|
* onboardingV2Block.eebusDeviceSelect('pair', {
|
|
285
290
|
* headline: t('Wärmepumpe auswählen', 'Select the heat pump'),
|
|
286
291
|
* deviceTypes: [EnyoEebusDeviceTypeEnum.HeatPumpAppliance],
|
|
292
|
+
* vendors: ['Vaillant'],
|
|
287
293
|
* outcomes: [
|
|
288
294
|
* {id: 'ok', value: EnyoOnboardingV2EebusPairOutcome.Paired, label: t('Gekoppelt', 'Paired')},
|
|
289
295
|
* {id: 'none', value: EnyoOnboardingV2EebusPairOutcome.NotFound, label: t('Nichts gefunden', 'Nothing found')},
|
|
@@ -614,9 +614,9 @@ function isPickerBlock(block) {
|
|
|
614
614
|
* it would either be skipped along with it or offer a way past the pick. Both
|
|
615
615
|
* are errors rather than warnings, because there is no reading of the step
|
|
616
616
|
* that behaves sensibly.
|
|
617
|
-
* - **An empty filter is not a filter.** `detectedAt: []` / `deviceTypes: []`
|
|
618
|
-
* match nothing, so the picker can only ever reach its
|
|
619
|
-
* Omitting the property is how "no filter" is expressed.
|
|
617
|
+
* - **An empty filter is not a filter.** `detectedAt: []` / `deviceTypes: []` /
|
|
618
|
+
* `vendors: []` match nothing, so the picker can only ever reach its
|
|
619
|
+
* `not-found` branch. Omitting the property is how "no filter" is expressed.
|
|
620
620
|
* - **A picker that renders should say something.** With neither a headline of
|
|
621
621
|
* its own nor a step title, the installer gets a bare list — a warning, since
|
|
622
622
|
* the host has a default caption.
|
|
@@ -655,6 +655,10 @@ function validatePickerBlocks(step, at, errors, warnings) {
|
|
|
655
655
|
errors.push(`${at}: ${label(block)} has an empty \`deviceTypes\` filter, which matches no peer — ` +
|
|
656
656
|
'omit the property to offer every discovered peer.');
|
|
657
657
|
}
|
|
658
|
+
if (block.vendors && block.vendors.length === 0) {
|
|
659
|
+
errors.push(`${at}: ${label(block)} has an empty \`vendors\` filter, which matches no peer — ` +
|
|
660
|
+
'omit the property to offer peers of every vendor.');
|
|
661
|
+
}
|
|
658
662
|
}
|
|
659
663
|
if (!block.headline?.length && !step.title?.length) {
|
|
660
664
|
warnings.push(`${at}: ${label(block)} has no headline and sits on a step with no title — ` +
|
|
@@ -4,7 +4,8 @@ import { EnyoGridConnectionPoint } from "../types/enyo-grid-connection-point.cjs
|
|
|
4
4
|
*
|
|
5
5
|
* The grid connection point describes the physical interface between the
|
|
6
6
|
* local electrical installation and the public grid, including the main
|
|
7
|
-
* fuse rating, the number of phases,
|
|
7
|
+
* fuse rating, the number of phases, the maximum allowed grid power, and the
|
|
8
|
+
* total power that load balancing may allocate to EV chargers.
|
|
8
9
|
* Energy apps consume this information to size grid-import/export budgets,
|
|
9
10
|
* enforce per-phase current limits, and respect contractual or regulatory
|
|
10
11
|
* power caps.
|
|
@@ -21,12 +22,16 @@ export interface EnergyAppGridConnectionPoint {
|
|
|
21
22
|
*
|
|
22
23
|
* @example
|
|
23
24
|
* ```typescript
|
|
25
|
+
* import {DEFAULT_CHARGER_LIMIT_W} from "@enyo-energy/energy-app-sdk";
|
|
26
|
+
*
|
|
24
27
|
* const gridConnectionPoint = energyApp.useGridConnectionPoint();
|
|
25
28
|
* const details = await gridConnectionPoint.getGridConnectionPoint();
|
|
26
29
|
* if (details) {
|
|
27
30
|
* console.log(`Fuse: ${details.fuseAmpere} A`);
|
|
28
31
|
* console.log(`Phases: ${details.numberOfPhases}`);
|
|
29
32
|
* console.log(`Power limit: ${details.powerLimitW} W`);
|
|
33
|
+
* const chargerLimitW = details.chargerLimitW ?? DEFAULT_CHARGER_LIMIT_W;
|
|
34
|
+
* console.log(`Charger limit: ${chargerLimitW} W`);
|
|
30
35
|
* }
|
|
31
36
|
* ```
|
|
32
37
|
*/
|
|
@@ -69,4 +69,10 @@ var EnyoChargerApplianceAvailableFeaturesEnum;
|
|
|
69
69
|
EnyoChargerApplianceAvailableFeaturesEnum["PvSurplusMode"] = "PvSurplusMode";
|
|
70
70
|
/** If the charger supports switching between three-phase and one-phase charging */
|
|
71
71
|
EnyoChargerApplianceAvailableFeaturesEnum["ThreeToOnePhaseSwitch"] = "ThreeToOnePhaseSwitch";
|
|
72
|
+
/**
|
|
73
|
+
* If the charger requires the vehicle to be disconnected before a new charge can be started.
|
|
74
|
+
* Once the charger is in {@link EnyoChargerApplianceStatusEnum.Finishing}, no new charge can be
|
|
75
|
+
* started remotely; the customer has to unplug the vehicle and plug it in again.
|
|
76
|
+
*/
|
|
77
|
+
EnyoChargerApplianceAvailableFeaturesEnum["DisconnectToRestartCharge"] = "DisconnectToRestartCharge";
|
|
72
78
|
})(EnyoChargerApplianceAvailableFeaturesEnum || (exports.EnyoChargerApplianceAvailableFeaturesEnum = EnyoChargerApplianceAvailableFeaturesEnum = {}));
|
|
@@ -82,7 +82,13 @@ export declare enum EnyoChargerApplianceAvailableFeaturesEnum {
|
|
|
82
82
|
/** If the Charger supprots a pv surplus mode */
|
|
83
83
|
PvSurplusMode = "PvSurplusMode",
|
|
84
84
|
/** If the charger supports switching between three-phase and one-phase charging */
|
|
85
|
-
ThreeToOnePhaseSwitch = "ThreeToOnePhaseSwitch"
|
|
85
|
+
ThreeToOnePhaseSwitch = "ThreeToOnePhaseSwitch",
|
|
86
|
+
/**
|
|
87
|
+
* If the charger requires the vehicle to be disconnected before a new charge can be started.
|
|
88
|
+
* Once the charger is in {@link EnyoChargerApplianceStatusEnum.Finishing}, no new charge can be
|
|
89
|
+
* started remotely; the customer has to unplug the vehicle and plug it in again.
|
|
90
|
+
*/
|
|
91
|
+
DisconnectToRestartCharge = "DisconnectToRestartCharge"
|
|
86
92
|
}
|
|
87
93
|
/**
|
|
88
94
|
* Phase configurations a charger can operate in.
|
|
@@ -80,6 +80,19 @@ export interface EebusDiscoveredDevice {
|
|
|
80
80
|
ski: string;
|
|
81
81
|
/** Human-readable device name advertised during discovery */
|
|
82
82
|
deviceName?: string;
|
|
83
|
+
/**
|
|
84
|
+
* The vendor the peer announced in its SHIP record (the `brand` TXT key),
|
|
85
|
+
* verbatim and untranslated — e.g. `Vaillant`, `KEBA`, `Viessmann`.
|
|
86
|
+
*
|
|
87
|
+
* The peer's own claim, made before anything is paired, which is what makes
|
|
88
|
+
* it usable as a discovery filter next to {@link deviceType}: see
|
|
89
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors}. Spelling and case
|
|
90
|
+
* are whatever the firmware ships, so compare case-insensitively rather
|
|
91
|
+
* than with `===`.
|
|
92
|
+
*
|
|
93
|
+
* Absent when the peer advertises no `brand`.
|
|
94
|
+
*/
|
|
95
|
+
brand?: string;
|
|
83
96
|
/** IP address or hostname of the device */
|
|
84
97
|
host: string;
|
|
85
98
|
/** Port number for the SHIP connection */
|
|
@@ -180,6 +180,15 @@ export interface EnyoTariffPriceEntry {
|
|
|
180
180
|
timestampIso: string;
|
|
181
181
|
/** Price per kWh for this interval, in the tariff's currency. */
|
|
182
182
|
pricePerKwh: number;
|
|
183
|
+
/**
|
|
184
|
+
* Optional gross grid fee per kWh contained in {@link pricePerKwh}, in the
|
|
185
|
+
* tariff's currency (not cent).
|
|
186
|
+
*
|
|
187
|
+
* Informational only: it breaks down the price, it is **never added** to it.
|
|
188
|
+
* {@link pricePerKwh} is always the total price. Only meaningful when the
|
|
189
|
+
* series declares {@link EnyoPriceComponentEnum.GridFee} in its `includes`.
|
|
190
|
+
*/
|
|
191
|
+
gridFeeGrossPerKwh?: number;
|
|
183
192
|
}
|
|
184
193
|
/**
|
|
185
194
|
* Prices for one direction over a requested range.
|
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_CHARGER_LIMIT_W = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Default total charger power limit, in watts (W), applied by load balancing
|
|
6
|
+
* when {@link EnyoGridConnectionPoint.chargerLimitW} is not configured.
|
|
7
|
+
*
|
|
8
|
+
* 11 kW corresponds to the common three-phase 16 A wallbox rating.
|
|
9
|
+
*/
|
|
10
|
+
exports.DEFAULT_CHARGER_LIMIT_W = 11000;
|
|
@@ -52,4 +52,25 @@ export interface EnyoGridConnectionPoint {
|
|
|
52
52
|
* `powerLimitW` applies.
|
|
53
53
|
*/
|
|
54
54
|
desiredKwLimit?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Maximum active power, in watts (W), that the load balancing may allocate
|
|
57
|
+
* to EV chargers in total at this grid connection point.
|
|
58
|
+
*
|
|
59
|
+
* This caps the charging power distributed across all connected wallboxes,
|
|
60
|
+
* independently of what the grid connection as a whole could deliver: it
|
|
61
|
+
* lets an installer keep headroom for the rest of the household, or honour
|
|
62
|
+
* a charger-specific limit agreed with the grid operator (e.g. §14a EnWG
|
|
63
|
+
* style restrictions).
|
|
64
|
+
*
|
|
65
|
+
* Optional. When `undefined`, load balancing assumes the default of
|
|
66
|
+
* {@link DEFAULT_CHARGER_LIMIT_W} (11 kW).
|
|
67
|
+
*/
|
|
68
|
+
chargerLimitW?: number;
|
|
55
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Default total charger power limit, in watts (W), applied by load balancing
|
|
72
|
+
* when {@link EnyoGridConnectionPoint.chargerLimitW} is not configured.
|
|
73
|
+
*
|
|
74
|
+
* 11 kW corresponds to the common three-phase 16 A wallbox rating.
|
|
75
|
+
*/
|
|
76
|
+
export declare const DEFAULT_CHARGER_LIMIT_W = 11000;
|
|
@@ -47,6 +47,17 @@ export interface EnyoOnboardingV2EebusPeer {
|
|
|
47
47
|
deviceName?: string;
|
|
48
48
|
/** Brand or model the peer advertised, if any. */
|
|
49
49
|
deviceModel?: string;
|
|
50
|
+
/**
|
|
51
|
+
* The vendor the peer announced during discovery (the SHIP `brand` TXT
|
|
52
|
+
* key), verbatim and untranslated, if any.
|
|
53
|
+
*
|
|
54
|
+
* The same claim {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors}
|
|
55
|
+
* filters the picker by, passed on so a handler that serves several
|
|
56
|
+
* manufacturers can pick the right appliance shape without re-reading
|
|
57
|
+
* discovery. Case and spelling are the firmware's — compare
|
|
58
|
+
* case-insensitively. Absent means the peer announced no vendor.
|
|
59
|
+
*/
|
|
60
|
+
brand?: string;
|
|
50
61
|
/**
|
|
51
62
|
* The device type the peer announced, when it announced one this SDK knows.
|
|
52
63
|
*
|
|
@@ -118,7 +129,8 @@ export interface EnyoOnboardingV2EebusDeviceSelectRequest {
|
|
|
118
129
|
/**
|
|
119
130
|
* `true` when the host paired on the installer's behalf because exactly one
|
|
120
131
|
* peer matched the block's
|
|
121
|
-
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.deviceTypes}
|
|
132
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.deviceTypes} and
|
|
133
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors} filters and
|
|
122
134
|
* {@link EnyoOnboardingV2PickerBlockBase.autoSelectSingleMatch} was left on —
|
|
123
135
|
* the screen was never rendered.
|
|
124
136
|
*
|
|
@@ -679,6 +679,31 @@ export interface EnyoOnboardingV2EebusDeviceSelectBlock extends EnyoOnboardingV2
|
|
|
679
679
|
* is a validation error.
|
|
680
680
|
*/
|
|
681
681
|
deviceTypes?: EnyoEebusDeviceTypeEnum[];
|
|
682
|
+
/**
|
|
683
|
+
* Offer only peers announcing one of these vendors; everything else is left
|
|
684
|
+
* out of the list and does not count towards
|
|
685
|
+
* {@link EnyoOnboardingV2PickerBlockBase.autoSelectSingleMatch}.
|
|
686
|
+
*
|
|
687
|
+
* The companion of {@link deviceTypes} for the case that filter cannot
|
|
688
|
+
* separate: a house with two EEBUS heat pumps, or a guide that is written
|
|
689
|
+
* for one manufacturer's device and would otherwise offer a competitor's as
|
|
690
|
+
* a candidate for its own pairing flow. Both filters are **conjunctive** —
|
|
691
|
+
* a peer must satisfy every filter present to be offered.
|
|
692
|
+
*
|
|
693
|
+
* Matched against the vendor the peer announced
|
|
694
|
+
* ({@link EebusDiscoveredDevice.brand}, the SHIP `brand` TXT key),
|
|
695
|
+
* **case-insensitively and ignoring surrounding whitespace**, since the
|
|
696
|
+
* spelling is whatever the firmware ships. It is otherwise an exact match,
|
|
697
|
+
* not a substring one: `KEBA` does not match `KEBA AG`, so list the
|
|
698
|
+
* spellings a vendor is known to announce rather than hoping for one.
|
|
699
|
+
*
|
|
700
|
+
* A peer that announces no vendor is treated the same way an unknown device
|
|
701
|
+
* type is: it survives an omitted filter and is excluded by any filter
|
|
702
|
+
* present, so a guide can never pair something it did not ask for. Omit the
|
|
703
|
+
* property to offer peers of every vendor; an **empty array** filters
|
|
704
|
+
* everything out and is a validation error.
|
|
705
|
+
*/
|
|
706
|
+
vendors?: string[];
|
|
682
707
|
}
|
|
683
708
|
/**
|
|
684
709
|
* A fixed URL the installer opens or copies — a vendor portal, a manual, a
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -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 = '1.
|
|
12
|
+
exports.SDK_VERSION = '1.25.0';
|
|
13
13
|
/**
|
|
14
14
|
* Gets the current SDK version.
|
|
15
15
|
* @returns The semantic version string of the SDK
|
package/dist/cjs/version.d.cts
CHANGED
|
@@ -254,7 +254,11 @@ export declare const onboardingV2Block: {
|
|
|
254
254
|
* Filter it. `deviceTypes` is what turns this from "here are the six EEBUS
|
|
255
255
|
* devices in the house" into "here is your heat pump", and with one match it
|
|
256
256
|
* skips the screen entirely instead of asking a question with one possible
|
|
257
|
-
* answer.
|
|
257
|
+
* answer. `vendors` narrows it further, by the `brand` a peer announces —
|
|
258
|
+
* use it where the device type cannot separate the candidates (two EEBUS
|
|
259
|
+
* heat pumps in one house), or where the guide is written for one
|
|
260
|
+
* manufacturer and must not offer a competitor's device. The two filters are
|
|
261
|
+
* conjunctive: a peer must satisfy both to be offered.
|
|
258
262
|
*
|
|
259
263
|
* The picker is drawn from what mDNS discovery found, so the guide must have
|
|
260
264
|
* scanned — keep {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its
|
|
@@ -275,8 +279,9 @@ export declare const onboardingV2Block: {
|
|
|
275
279
|
* paired peer into appliances.
|
|
276
280
|
*
|
|
277
281
|
* @param id - Stable block id, unique within the guide.
|
|
278
|
-
* @param options - Screen wording, optional `deviceTypes`
|
|
279
|
-
* behaviour, and the `paired` / `not-found` / `failure`
|
|
282
|
+
* @param options - Screen wording, optional `deviceTypes` and `vendors`
|
|
283
|
+
* filters, skip behaviour, and the `paired` / `not-found` / `failure`
|
|
284
|
+
* routing handles.
|
|
280
285
|
* @returns The EEBUS device-select block.
|
|
281
286
|
*
|
|
282
287
|
* @example
|
|
@@ -284,6 +289,7 @@ export declare const onboardingV2Block: {
|
|
|
284
289
|
* onboardingV2Block.eebusDeviceSelect('pair', {
|
|
285
290
|
* headline: t('Wärmepumpe auswählen', 'Select the heat pump'),
|
|
286
291
|
* deviceTypes: [EnyoEebusDeviceTypeEnum.HeatPumpAppliance],
|
|
292
|
+
* vendors: ['Vaillant'],
|
|
287
293
|
* outcomes: [
|
|
288
294
|
* {id: 'ok', value: EnyoOnboardingV2EebusPairOutcome.Paired, label: t('Gekoppelt', 'Paired')},
|
|
289
295
|
* {id: 'none', value: EnyoOnboardingV2EebusPairOutcome.NotFound, label: t('Nichts gefunden', 'Nothing found')},
|
|
@@ -298,7 +298,11 @@ export const onboardingV2Block = {
|
|
|
298
298
|
* Filter it. `deviceTypes` is what turns this from "here are the six EEBUS
|
|
299
299
|
* devices in the house" into "here is your heat pump", and with one match it
|
|
300
300
|
* skips the screen entirely instead of asking a question with one possible
|
|
301
|
-
* answer.
|
|
301
|
+
* answer. `vendors` narrows it further, by the `brand` a peer announces —
|
|
302
|
+
* use it where the device type cannot separate the candidates (two EEBUS
|
|
303
|
+
* heat pumps in one house), or where the guide is written for one
|
|
304
|
+
* manufacturer and must not offer a competitor's device. The two filters are
|
|
305
|
+
* conjunctive: a peer must satisfy both to be offered.
|
|
302
306
|
*
|
|
303
307
|
* The picker is drawn from what mDNS discovery found, so the guide must have
|
|
304
308
|
* scanned — keep {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its
|
|
@@ -319,8 +323,9 @@ export const onboardingV2Block = {
|
|
|
319
323
|
* paired peer into appliances.
|
|
320
324
|
*
|
|
321
325
|
* @param id - Stable block id, unique within the guide.
|
|
322
|
-
* @param options - Screen wording, optional `deviceTypes`
|
|
323
|
-
* behaviour, and the `paired` / `not-found` / `failure`
|
|
326
|
+
* @param options - Screen wording, optional `deviceTypes` and `vendors`
|
|
327
|
+
* filters, skip behaviour, and the `paired` / `not-found` / `failure`
|
|
328
|
+
* routing handles.
|
|
324
329
|
* @returns The EEBUS device-select block.
|
|
325
330
|
*
|
|
326
331
|
* @example
|
|
@@ -328,6 +333,7 @@ export const onboardingV2Block = {
|
|
|
328
333
|
* onboardingV2Block.eebusDeviceSelect('pair', {
|
|
329
334
|
* headline: t('Wärmepumpe auswählen', 'Select the heat pump'),
|
|
330
335
|
* deviceTypes: [EnyoEebusDeviceTypeEnum.HeatPumpAppliance],
|
|
336
|
+
* vendors: ['Vaillant'],
|
|
331
337
|
* outcomes: [
|
|
332
338
|
* {id: 'ok', value: EnyoOnboardingV2EebusPairOutcome.Paired, label: t('Gekoppelt', 'Paired')},
|
|
333
339
|
* {id: 'none', value: EnyoOnboardingV2EebusPairOutcome.NotFound, label: t('Nichts gefunden', 'Nothing found')},
|
|
@@ -608,9 +608,9 @@ function isPickerBlock(block) {
|
|
|
608
608
|
* it would either be skipped along with it or offer a way past the pick. Both
|
|
609
609
|
* are errors rather than warnings, because there is no reading of the step
|
|
610
610
|
* that behaves sensibly.
|
|
611
|
-
* - **An empty filter is not a filter.** `detectedAt: []` / `deviceTypes: []`
|
|
612
|
-
* match nothing, so the picker can only ever reach its
|
|
613
|
-
* Omitting the property is how "no filter" is expressed.
|
|
611
|
+
* - **An empty filter is not a filter.** `detectedAt: []` / `deviceTypes: []` /
|
|
612
|
+
* `vendors: []` match nothing, so the picker can only ever reach its
|
|
613
|
+
* `not-found` branch. Omitting the property is how "no filter" is expressed.
|
|
614
614
|
* - **A picker that renders should say something.** With neither a headline of
|
|
615
615
|
* its own nor a step title, the installer gets a bare list — a warning, since
|
|
616
616
|
* the host has a default caption.
|
|
@@ -649,6 +649,10 @@ function validatePickerBlocks(step, at, errors, warnings) {
|
|
|
649
649
|
errors.push(`${at}: ${label(block)} has an empty \`deviceTypes\` filter, which matches no peer — ` +
|
|
650
650
|
'omit the property to offer every discovered peer.');
|
|
651
651
|
}
|
|
652
|
+
if (block.vendors && block.vendors.length === 0) {
|
|
653
|
+
errors.push(`${at}: ${label(block)} has an empty \`vendors\` filter, which matches no peer — ` +
|
|
654
|
+
'omit the property to offer peers of every vendor.');
|
|
655
|
+
}
|
|
652
656
|
}
|
|
653
657
|
if (!block.headline?.length && !step.title?.length) {
|
|
654
658
|
warnings.push(`${at}: ${label(block)} has no headline and sits on a step with no title — ` +
|
|
@@ -4,7 +4,8 @@ import { EnyoGridConnectionPoint } from "../types/enyo-grid-connection-point.js"
|
|
|
4
4
|
*
|
|
5
5
|
* The grid connection point describes the physical interface between the
|
|
6
6
|
* local electrical installation and the public grid, including the main
|
|
7
|
-
* fuse rating, the number of phases,
|
|
7
|
+
* fuse rating, the number of phases, the maximum allowed grid power, and the
|
|
8
|
+
* total power that load balancing may allocate to EV chargers.
|
|
8
9
|
* Energy apps consume this information to size grid-import/export budgets,
|
|
9
10
|
* enforce per-phase current limits, and respect contractual or regulatory
|
|
10
11
|
* power caps.
|
|
@@ -21,12 +22,16 @@ export interface EnergyAppGridConnectionPoint {
|
|
|
21
22
|
*
|
|
22
23
|
* @example
|
|
23
24
|
* ```typescript
|
|
25
|
+
* import {DEFAULT_CHARGER_LIMIT_W} from "@enyo-energy/energy-app-sdk";
|
|
26
|
+
*
|
|
24
27
|
* const gridConnectionPoint = energyApp.useGridConnectionPoint();
|
|
25
28
|
* const details = await gridConnectionPoint.getGridConnectionPoint();
|
|
26
29
|
* if (details) {
|
|
27
30
|
* console.log(`Fuse: ${details.fuseAmpere} A`);
|
|
28
31
|
* console.log(`Phases: ${details.numberOfPhases}`);
|
|
29
32
|
* console.log(`Power limit: ${details.powerLimitW} W`);
|
|
33
|
+
* const chargerLimitW = details.chargerLimitW ?? DEFAULT_CHARGER_LIMIT_W;
|
|
34
|
+
* console.log(`Charger limit: ${chargerLimitW} W`);
|
|
30
35
|
* }
|
|
31
36
|
* ```
|
|
32
37
|
*/
|
|
@@ -82,7 +82,13 @@ export declare enum EnyoChargerApplianceAvailableFeaturesEnum {
|
|
|
82
82
|
/** If the Charger supprots a pv surplus mode */
|
|
83
83
|
PvSurplusMode = "PvSurplusMode",
|
|
84
84
|
/** If the charger supports switching between three-phase and one-phase charging */
|
|
85
|
-
ThreeToOnePhaseSwitch = "ThreeToOnePhaseSwitch"
|
|
85
|
+
ThreeToOnePhaseSwitch = "ThreeToOnePhaseSwitch",
|
|
86
|
+
/**
|
|
87
|
+
* If the charger requires the vehicle to be disconnected before a new charge can be started.
|
|
88
|
+
* Once the charger is in {@link EnyoChargerApplianceStatusEnum.Finishing}, no new charge can be
|
|
89
|
+
* started remotely; the customer has to unplug the vehicle and plug it in again.
|
|
90
|
+
*/
|
|
91
|
+
DisconnectToRestartCharge = "DisconnectToRestartCharge"
|
|
86
92
|
}
|
|
87
93
|
/**
|
|
88
94
|
* Phase configurations a charger can operate in.
|
|
@@ -66,4 +66,10 @@ export var EnyoChargerApplianceAvailableFeaturesEnum;
|
|
|
66
66
|
EnyoChargerApplianceAvailableFeaturesEnum["PvSurplusMode"] = "PvSurplusMode";
|
|
67
67
|
/** If the charger supports switching between three-phase and one-phase charging */
|
|
68
68
|
EnyoChargerApplianceAvailableFeaturesEnum["ThreeToOnePhaseSwitch"] = "ThreeToOnePhaseSwitch";
|
|
69
|
+
/**
|
|
70
|
+
* If the charger requires the vehicle to be disconnected before a new charge can be started.
|
|
71
|
+
* Once the charger is in {@link EnyoChargerApplianceStatusEnum.Finishing}, no new charge can be
|
|
72
|
+
* started remotely; the customer has to unplug the vehicle and plug it in again.
|
|
73
|
+
*/
|
|
74
|
+
EnyoChargerApplianceAvailableFeaturesEnum["DisconnectToRestartCharge"] = "DisconnectToRestartCharge";
|
|
69
75
|
})(EnyoChargerApplianceAvailableFeaturesEnum || (EnyoChargerApplianceAvailableFeaturesEnum = {}));
|
|
@@ -80,6 +80,19 @@ export interface EebusDiscoveredDevice {
|
|
|
80
80
|
ski: string;
|
|
81
81
|
/** Human-readable device name advertised during discovery */
|
|
82
82
|
deviceName?: string;
|
|
83
|
+
/**
|
|
84
|
+
* The vendor the peer announced in its SHIP record (the `brand` TXT key),
|
|
85
|
+
* verbatim and untranslated — e.g. `Vaillant`, `KEBA`, `Viessmann`.
|
|
86
|
+
*
|
|
87
|
+
* The peer's own claim, made before anything is paired, which is what makes
|
|
88
|
+
* it usable as a discovery filter next to {@link deviceType}: see
|
|
89
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors}. Spelling and case
|
|
90
|
+
* are whatever the firmware ships, so compare case-insensitively rather
|
|
91
|
+
* than with `===`.
|
|
92
|
+
*
|
|
93
|
+
* Absent when the peer advertises no `brand`.
|
|
94
|
+
*/
|
|
95
|
+
brand?: string;
|
|
83
96
|
/** IP address or hostname of the device */
|
|
84
97
|
host: string;
|
|
85
98
|
/** Port number for the SHIP connection */
|
|
@@ -180,6 +180,15 @@ export interface EnyoTariffPriceEntry {
|
|
|
180
180
|
timestampIso: string;
|
|
181
181
|
/** Price per kWh for this interval, in the tariff's currency. */
|
|
182
182
|
pricePerKwh: number;
|
|
183
|
+
/**
|
|
184
|
+
* Optional gross grid fee per kWh contained in {@link pricePerKwh}, in the
|
|
185
|
+
* tariff's currency (not cent).
|
|
186
|
+
*
|
|
187
|
+
* Informational only: it breaks down the price, it is **never added** to it.
|
|
188
|
+
* {@link pricePerKwh} is always the total price. Only meaningful when the
|
|
189
|
+
* series declares {@link EnyoPriceComponentEnum.GridFee} in its `includes`.
|
|
190
|
+
*/
|
|
191
|
+
gridFeeGrossPerKwh?: number;
|
|
183
192
|
}
|
|
184
193
|
/**
|
|
185
194
|
* Prices for one direction over a requested range.
|
|
@@ -52,4 +52,25 @@ export interface EnyoGridConnectionPoint {
|
|
|
52
52
|
* `powerLimitW` applies.
|
|
53
53
|
*/
|
|
54
54
|
desiredKwLimit?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Maximum active power, in watts (W), that the load balancing may allocate
|
|
57
|
+
* to EV chargers in total at this grid connection point.
|
|
58
|
+
*
|
|
59
|
+
* This caps the charging power distributed across all connected wallboxes,
|
|
60
|
+
* independently of what the grid connection as a whole could deliver: it
|
|
61
|
+
* lets an installer keep headroom for the rest of the household, or honour
|
|
62
|
+
* a charger-specific limit agreed with the grid operator (e.g. §14a EnWG
|
|
63
|
+
* style restrictions).
|
|
64
|
+
*
|
|
65
|
+
* Optional. When `undefined`, load balancing assumes the default of
|
|
66
|
+
* {@link DEFAULT_CHARGER_LIMIT_W} (11 kW).
|
|
67
|
+
*/
|
|
68
|
+
chargerLimitW?: number;
|
|
55
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Default total charger power limit, in watts (W), applied by load balancing
|
|
72
|
+
* when {@link EnyoGridConnectionPoint.chargerLimitW} is not configured.
|
|
73
|
+
*
|
|
74
|
+
* 11 kW corresponds to the common three-phase 16 A wallbox rating.
|
|
75
|
+
*/
|
|
76
|
+
export declare const DEFAULT_CHARGER_LIMIT_W = 11000;
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Default total charger power limit, in watts (W), applied by load balancing
|
|
3
|
+
* when {@link EnyoGridConnectionPoint.chargerLimitW} is not configured.
|
|
4
|
+
*
|
|
5
|
+
* 11 kW corresponds to the common three-phase 16 A wallbox rating.
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_CHARGER_LIMIT_W = 11000;
|
|
@@ -47,6 +47,17 @@ export interface EnyoOnboardingV2EebusPeer {
|
|
|
47
47
|
deviceName?: string;
|
|
48
48
|
/** Brand or model the peer advertised, if any. */
|
|
49
49
|
deviceModel?: string;
|
|
50
|
+
/**
|
|
51
|
+
* The vendor the peer announced during discovery (the SHIP `brand` TXT
|
|
52
|
+
* key), verbatim and untranslated, if any.
|
|
53
|
+
*
|
|
54
|
+
* The same claim {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors}
|
|
55
|
+
* filters the picker by, passed on so a handler that serves several
|
|
56
|
+
* manufacturers can pick the right appliance shape without re-reading
|
|
57
|
+
* discovery. Case and spelling are the firmware's — compare
|
|
58
|
+
* case-insensitively. Absent means the peer announced no vendor.
|
|
59
|
+
*/
|
|
60
|
+
brand?: string;
|
|
50
61
|
/**
|
|
51
62
|
* The device type the peer announced, when it announced one this SDK knows.
|
|
52
63
|
*
|
|
@@ -118,7 +129,8 @@ export interface EnyoOnboardingV2EebusDeviceSelectRequest {
|
|
|
118
129
|
/**
|
|
119
130
|
* `true` when the host paired on the installer's behalf because exactly one
|
|
120
131
|
* peer matched the block's
|
|
121
|
-
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.deviceTypes}
|
|
132
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.deviceTypes} and
|
|
133
|
+
* {@link EnyoOnboardingV2EebusDeviceSelectBlock.vendors} filters and
|
|
122
134
|
* {@link EnyoOnboardingV2PickerBlockBase.autoSelectSingleMatch} was left on —
|
|
123
135
|
* the screen was never rendered.
|
|
124
136
|
*
|
|
@@ -679,6 +679,31 @@ export interface EnyoOnboardingV2EebusDeviceSelectBlock extends EnyoOnboardingV2
|
|
|
679
679
|
* is a validation error.
|
|
680
680
|
*/
|
|
681
681
|
deviceTypes?: EnyoEebusDeviceTypeEnum[];
|
|
682
|
+
/**
|
|
683
|
+
* Offer only peers announcing one of these vendors; everything else is left
|
|
684
|
+
* out of the list and does not count towards
|
|
685
|
+
* {@link EnyoOnboardingV2PickerBlockBase.autoSelectSingleMatch}.
|
|
686
|
+
*
|
|
687
|
+
* The companion of {@link deviceTypes} for the case that filter cannot
|
|
688
|
+
* separate: a house with two EEBUS heat pumps, or a guide that is written
|
|
689
|
+
* for one manufacturer's device and would otherwise offer a competitor's as
|
|
690
|
+
* a candidate for its own pairing flow. Both filters are **conjunctive** —
|
|
691
|
+
* a peer must satisfy every filter present to be offered.
|
|
692
|
+
*
|
|
693
|
+
* Matched against the vendor the peer announced
|
|
694
|
+
* ({@link EebusDiscoveredDevice.brand}, the SHIP `brand` TXT key),
|
|
695
|
+
* **case-insensitively and ignoring surrounding whitespace**, since the
|
|
696
|
+
* spelling is whatever the firmware ships. It is otherwise an exact match,
|
|
697
|
+
* not a substring one: `KEBA` does not match `KEBA AG`, so list the
|
|
698
|
+
* spellings a vendor is known to announce rather than hoping for one.
|
|
699
|
+
*
|
|
700
|
+
* A peer that announces no vendor is treated the same way an unknown device
|
|
701
|
+
* type is: it survives an omitted filter and is excluded by any filter
|
|
702
|
+
* present, so a guide can never pair something it did not ask for. Omit the
|
|
703
|
+
* property to offer peers of every vendor; an **empty array** filters
|
|
704
|
+
* everything out and is a validation error.
|
|
705
|
+
*/
|
|
706
|
+
vendors?: string[];
|
|
682
707
|
}
|
|
683
708
|
/**
|
|
684
709
|
* A fixed URL the installer opens or copies — a vendor portal, a manual, a
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED