@enyo-energy/energy-app-sdk 1.10.0 → 1.12.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 CHANGED
@@ -84,6 +84,7 @@ The official TypeScript SDK for building Energy Apps on the enyo platform. Creat
84
84
  - [Basic Energy App](#basic-energy-app)
85
85
  - [Device Integration](#device-integration)
86
86
  - [Data Bus Messaging](#data-bus-messaging)
87
+ - [Announcing Appliance Flexibility](#announcing-appliance-flexibility)
87
88
  - [Settings Management](#settings-management)
88
89
  - [Troubleshooting](#troubleshooting)
89
90
  - [External Libraries](#external-libraries)
@@ -1494,7 +1495,7 @@ Publishers need `PvSystemRegister`; consumers need `PvSystemUse`.
1494
1495
 
1495
1496
  #### `useTimeseries(): EnergyAppTimeseries`
1496
1497
 
1497
- Query historical 15-minute aggregated data across the energy domain (PV production, battery SoC / power, meter values, grid power, home consumption, heatpump electrical / thermal, air-conditioning, temperature sensors). Some endpoints also support 1-minute resolution.
1498
+ Query historical 15-minute aggregated data across the energy domain (PV production, battery SoC / power, meter values, grid power, home consumption, heatpump electrical / thermal, air-conditioning, temperature sensors, smart plugs). Some endpoints also support 1-minute resolution.
1498
1499
 
1499
1500
  ```typescript
1500
1501
  const ts = energyApp.useTimeseries();
@@ -3529,6 +3530,79 @@ energyApp.register(async (packageName, version) => {
3529
3530
  });
3530
3531
  ```
3531
3532
 
3533
+ #### Announcing Appliance Flexibility
3534
+
3535
+ An appliance tells the rest of the system how much energy it can shift, and
3536
+ until when, with `ApplianceFlexibilityAnnouncementV1`. Optionally it can also say
3537
+ **how much watt for what** — which part of the system the energy would go into —
3538
+ so the consumer of the announcement can reason about the demand behind the number
3539
+ instead of treating it as one opaque block.
3540
+
3541
+ The breakdown is a list of `EnyoFlexibilityTargetPower` entries under
3542
+ `data.flexibility.context.targets`. Each entry names a `EnyoFlexibilityTargetEnum`
3543
+ target, the power that share would draw in Watts, and optionally the share of the
3544
+ announced energy in kWh.
3545
+
3546
+ `EnyoFlexibilityTargetEnum` is an open vocabulary. Today it covers
3547
+ `domesticHotWater`, `bufferTank`, and `heating`, since thermal appliances are the
3548
+ first to split their draw — but it is not limited to thermal targets, and further
3549
+ members may describe non-thermal ones. Treat an unknown value as "some other
3550
+ target" rather than assuming it is a heat sink.
3551
+
3552
+ ```typescript
3553
+ import {
3554
+ EnergyApp,
3555
+ EnyoFlexibilityTargetEnum,
3556
+ } from '@enyo-energy/energy-app-sdk';
3557
+
3558
+ const energyApp = new EnergyApp();
3559
+ const dataBus = energyApp.useDataBus();
3560
+
3561
+ dataBus.sendMessage([{
3562
+ type: 'message',
3563
+ message: 'ApplianceFlexibilityAnnouncementV1',
3564
+ applianceId: 'heatpump-1',
3565
+ data: {
3566
+ flexibility: {
3567
+ // Authoritative total: 4 kWh can be shifted until 14:00.
3568
+ kWh: 4,
3569
+ availableUntilIsoTimestamp: '2025-10-01T14:00:00Z',
3570
+ // Optional: what those 4 kWh are for, and at which power.
3571
+ context: {
3572
+ targets: [
3573
+ {
3574
+ target: EnyoFlexibilityTargetEnum.DomesticHotWater,
3575
+ powerW: 1500,
3576
+ kWh: 2.5,
3577
+ },
3578
+ {
3579
+ target: EnyoFlexibilityTargetEnum.BufferTank,
3580
+ powerW: 800,
3581
+ kWh: 1.5,
3582
+ },
3583
+ ],
3584
+ },
3585
+ },
3586
+ },
3587
+ }]);
3588
+ ```
3589
+
3590
+ Notes:
3591
+
3592
+ - `context` is entirely optional — existing publishers that only send `kWh` and
3593
+ `availableUntilIsoTimestamp` stay valid.
3594
+ - The breakdown may be **partial**: its entries do not have to sum to `kWh` or to
3595
+ the appliance's full draw. Only `kWh` is authoritative.
3596
+ - A given target should appear at most once per breakdown.
3597
+ - The same breakdown is available on category-level announcements via
3598
+ `context.targets` on `EnyoFlexibilityAnnouncementContext`, so the
3599
+ per-appliance and aggregated surfaces stay in step.
3600
+ - The V2 available-power commands carry the same breakdown in the other
3601
+ direction: `targets` on `EnyoAvailablePowerCommandData` lets the energy manager
3602
+ say what the granted envelope is meant for, using the same vocabulary, so a
3603
+ grant can be read against the announcement it answers. It is advisory — the
3604
+ command's `powerW` remains the only limit.
3605
+
3532
3606
  ### Settings Management
3533
3607
 
3534
3608
  Dynamic configuration with user interface:
@@ -1,4 +1,4 @@
1
- import { DataBusMessageQueryRequest, DataBusMessageQueryResponse, PvProductionTimeseriesRequest, PvProductionTimeseriesResponse, BatterySocTimeseriesRequest, BatterySocTimeseriesResponse, BatteryPowerTimeseriesRequest, BatteryPowerTimeseriesResponse, MeterValuesTimeseriesRequest, MeterValuesTimeseriesResponse, GridPowerTimeseriesRequest, GridPowerTimeseriesResponse, HomeConsumptionTimeseriesRequest, HomeConsumptionTimeseriesResponse, HeatpumpTemperatureTimeseriesRequest, HeatpumpTemperatureTimeseriesResponse, HeatpumpPowerTimeseriesRequest, HeatpumpPowerTimeseriesResponse, TemperatureSensorTimeseriesRequest, TemperatureSensorTimeseriesResponse, AirConditioningPowerTimeseriesRequest, AirConditioningPowerTimeseriesResponse, AirConditioningTemperatureTimeseriesRequest, AirConditioningTemperatureTimeseriesResponse } from "../types/enyo-timeseries.cjs";
1
+ import { DataBusMessageQueryRequest, DataBusMessageQueryResponse, PvProductionTimeseriesRequest, PvProductionTimeseriesResponse, BatterySocTimeseriesRequest, BatterySocTimeseriesResponse, BatteryPowerTimeseriesRequest, BatteryPowerTimeseriesResponse, MeterValuesTimeseriesRequest, MeterValuesTimeseriesResponse, GridPowerTimeseriesRequest, GridPowerTimeseriesResponse, HomeConsumptionTimeseriesRequest, HomeConsumptionTimeseriesResponse, HeatpumpTemperatureTimeseriesRequest, HeatpumpTemperatureTimeseriesResponse, HeatpumpPowerTimeseriesRequest, HeatpumpPowerTimeseriesResponse, TemperatureSensorTimeseriesRequest, TemperatureSensorTimeseriesResponse, AirConditioningPowerTimeseriesRequest, AirConditioningPowerTimeseriesResponse, AirConditioningTemperatureTimeseriesRequest, AirConditioningTemperatureTimeseriesResponse, SmartPlugTimeseriesRequest, SmartPlugTimeseriesResponse } from "../types/enyo-timeseries.cjs";
2
2
  /**
3
3
  * Interface for querying historical energy data with configurable bucket granularity.
4
4
  * Provides methods to retrieve aggregated timeseries data for various energy metrics
@@ -253,4 +253,33 @@ export interface EnergyAppTimeseries {
253
253
  * ```
254
254
  */
255
255
  getAirConditioningTemperatureTimeseries(request: AirConditioningTemperatureTimeseriesRequest): Promise<AirConditioningTemperatureTimeseriesResponse>;
256
+ /**
257
+ * Retrieves smart plug timeseries data aggregated in time buckets.
258
+ *
259
+ * Every bucket carries the aggregate across all included plugs
260
+ * (`smartPlugPowerW` / `Wh`) plus a per-plug breakdown, since a plug measures
261
+ * an arbitrary load and the total alone does not say which load ran. The
262
+ * response additionally summarises each plug across the full period.
263
+ *
264
+ * Per-plug fields are optional because plug capabilities differ: a
265
+ * measure-only plug reports power but no runtime, a switch-only plug reports
266
+ * runtime (`onDurationMinutes`, `switchCount`) but no power.
267
+ *
268
+ * @param request - The query parameters including date range and optional appliance filter
269
+ * @returns Promise resolving to smart plug entries with the total and per-plug summaries
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const response = await timeseries.getSmartPlugTimeseries({
274
+ * startDateIso: '2024-01-01T00:00:00Z',
275
+ * endDateIso: '2024-01-02T00:00:00Z'
276
+ * });
277
+ * console.log(`Total plug consumption: ${response.totalSmartPlugPowerWh} Wh`);
278
+ * response.plugs.forEach(plug => {
279
+ * console.log(`${plug.applianceId}: ${plug.totalPowerWh ?? 0} Wh, ` +
280
+ * `on for ${plug.totalOnDurationMinutes ?? 0} min`);
281
+ * });
282
+ * ```
283
+ */
284
+ getSmartPlugTimeseries(request: SmartPlugTimeseriesRequest): Promise<SmartPlugTimeseriesResponse>;
256
285
  }
@@ -7,6 +7,7 @@ import { PreviewChargingSchedule, PreviewChargingScheduleCostComparison, Preview
7
7
  import { EnyoEnergyPrices } from "./enyo-energy-prices.cjs";
8
8
  import { EnyoCurrencyEnum } from "./enyo-currency.cjs";
9
9
  import { EnyoHeatpumpApplianceModeEnum } from "./enyo-heatpump-appliance.cjs";
10
+ import type { EnyoFlexibilityTargetPower } from "./enyo-flexibility-announcement.cjs";
10
11
  import { EnyoSmartPlugApplianceStateEnum } from "./enyo-smart-plug-appliance.cjs";
11
12
  import { EnyoAirConditioningApplianceModeEnum, EnyoAirConditioningOptimizationModeEnum } from "./enyo-air-conditioning-appliance.cjs";
12
13
  import { EnergyAppPackageCategory } from "../energy-app-package-definition.cjs";
@@ -579,6 +580,36 @@ export interface EnyoDataBusInverterValuesV1 extends EnyoDataBusMessage {
579
580
  gridOperatorLimit?: EnyoGridOperatorLimit;
580
581
  };
581
582
  }
583
+ /**
584
+ * An appliance announces how much energy it can shift, and until when.
585
+ *
586
+ * Optionally it can also say *what the energy is for and at which power* via
587
+ * `data.flexibility.context.targets` — e.g. a heat pump splitting its draw
588
+ * between the domestic hot water tank, the heating buffer tank, and the space
589
+ * heating circuit. That breakdown is additive context for the decision maker;
590
+ * `kWh` remains the authoritative total.
591
+ *
592
+ * @example
593
+ * ```typescript
594
+ * dataBus.sendMessage([{
595
+ * type: 'message',
596
+ * message: EnyoDataBusMessageEnum.ApplianceFlexibilityAnnouncementV1,
597
+ * applianceId: 'heatpump-1',
598
+ * data: {
599
+ * flexibility: {
600
+ * kWh: 4,
601
+ * availableUntilIsoTimestamp: '2025-10-01T14:00:00Z',
602
+ * context: {
603
+ * targets: [
604
+ * {target: EnyoFlexibilityTargetEnum.DomesticHotWater, powerW: 1500, kWh: 2.5},
605
+ * {target: EnyoFlexibilityTargetEnum.BufferTank, powerW: 800, kWh: 1.5},
606
+ * ],
607
+ * },
608
+ * },
609
+ * },
610
+ * }]);
611
+ * ```
612
+ */
582
613
  export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataBusMessage {
583
614
  type: 'message';
584
615
  message: EnyoDataBusMessageEnum.ApplianceFlexibilityAnnouncementV1;
@@ -589,6 +620,19 @@ export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataB
589
620
  kWh: number;
590
621
  /** Defines until the kWh flexibility can be shifted. If for Example 10 kWh can be shifted until 2025-10-01T14:00:00 (current time 2025-10-01T10:00:00), the control can shift the 10 kWh in the next 4 hours */
591
622
  availableUntilIsoTimestamp: string;
623
+ /**
624
+ * Optional extra context for the consumer of this announcement.
625
+ * Nested so further context keys can be added without changing the
626
+ * message shape again.
627
+ */
628
+ context?: {
629
+ /**
630
+ * Breakdown of what the announced flexibility is for and at which
631
+ * power. May be partial — entries need not sum to the appliance's
632
+ * full draw — and a given target SHOULD appear at most once.
633
+ */
634
+ targets: EnyoFlexibilityTargetPower[];
635
+ };
592
636
  };
593
637
  };
594
638
  }
@@ -867,6 +911,20 @@ export interface EnyoAvailablePowerCommandData {
867
911
  * Must be non-negative. The appliance must not exceed this envelope.
868
912
  */
869
913
  powerW: number;
914
+ /**
915
+ * Optional breakdown of what the granted envelope is meant for and at which
916
+ * power — the same "how much watt for what" vocabulary an appliance uses to
917
+ * announce its flexibility
918
+ * ({@link EnyoDataBusApplianceFlexibilityAnnouncementV1}), so a grant can be
919
+ * read against the announcement it answers.
920
+ *
921
+ * Advisory, and never a second limit: `powerW` alone bounds what the
922
+ * appliance may draw. The shares SHOULD NOT exceed `powerW` in sum, may be
923
+ * partial, and a given target SHOULD appear at most once. An appliance that
924
+ * does not understand a target should fall back to spending the envelope as
925
+ * it sees fit rather than refusing it.
926
+ */
927
+ targets?: EnyoFlexibilityTargetPower[];
870
928
  /** Optional reason why this command was issued */
871
929
  reason?: EnyoDataBusCommandReason;
872
930
  }
@@ -2243,7 +2301,8 @@ export interface EnyoPowerSourceShare {
2243
2301
  /**
2244
2302
  * V2 command announcing the available / maximum active-power envelope (in
2245
2303
  * Watts) a heatpump may draw, together with optional context describing what
2246
- * the power should be used for ({@link EnyoHeatpumpControlPurposeEnum}) and
2304
+ * the power should be used for ({@link EnyoHeatpumpControlPurposeEnum}), how it
2305
+ * splits across targets ({@link EnyoAvailablePowerCommandData.targets}), and
2247
2306
  * where it comes from ({@link EnyoPowerSourceShare}). Supersedes the deprecated
2248
2307
  * {@link EnyoDataBusHeatpumpAvailablePowerAnnouncementV1}.
2249
2308
  *
@@ -2260,6 +2319,14 @@ export interface EnyoDataBusSetHeatpumpAvailablePowerV2 extends EnyoDataBusMessa
2260
2319
  /**
2261
2320
  * What the heatpump should use the announced power for (e.g. DHW boost,
2262
2321
  * pre-heating). Advisory — the appliance may still apply its own logic.
2322
+ *
2323
+ * This names a single intent for the whole envelope, and covers intents
2324
+ * that are not a heat sink at all ({@link
2325
+ * EnyoHeatpumpControlPurposeEnum.PreHeating}). To instead split the
2326
+ * envelope across sinks — "1500 W for hot water, 800 W for the buffer
2327
+ * tank" — use {@link EnyoAvailablePowerCommandData.targets}. The two may
2328
+ * be sent together; they are separate vocabularies and neither is derived
2329
+ * from the other.
2263
2330
  */
2264
2331
  purpose?: EnyoHeatpumpControlPurposeEnum;
2265
2332
  /**
@@ -14,7 +14,7 @@
14
14
  // deliberately uses TS enums — the values below are the exact on-the-wire
15
15
  // strings, so the enums stay wire-compatible while giving callers named members.
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.EnyoCategoryFlexibilityGrantStatusEnum = exports.EnyoFlexibilityOptimizationModeEnum = exports.EnyoFlexibilityTimingTargetEnum = exports.EnyoFlexibilityAirConditioningTargetTypeEnum = exports.EnyoFlexibilityHeatpumpTargetTypeEnum = exports.EnyoFlexibilityAnnouncementTypeEnum = void 0;
17
+ exports.EnyoCategoryFlexibilityGrantStatusEnum = exports.EnyoFlexibilityOptimizationModeEnum = exports.EnyoFlexibilityTimingTargetEnum = exports.EnyoFlexibilityAirConditioningTargetTypeEnum = exports.EnyoFlexibilityTargetEnum = exports.EnyoFlexibilityHeatpumpTargetTypeEnum = exports.EnyoFlexibilityAnnouncementTypeEnum = void 0;
18
18
  // ─── Vocabulary enums ───────────────────────────────────────
19
19
  /** Discriminant tag for the four flexibility-announcement variants. */
20
20
  var EnyoFlexibilityAnnouncementTypeEnum;
@@ -32,6 +32,13 @@ var EnyoFlexibilityAnnouncementTypeEnum;
32
32
  * What a heat pump's flexibility is aimed at — gives the decision maker extra
33
33
  * context on the demand behind a heat-pump announcement. `Cooling` is reserved
34
34
  * for a future cooling mode and is not emitted yet.
35
+ *
36
+ * This enum describes the *mode* a heat pump runs in. To say what the announced
37
+ * energy is for — and how much power goes to each target — use
38
+ * {@link EnyoFlexibilityTargetEnum} together with
39
+ * {@link EnyoFlexibilityTargetPower}. The overlap between the two
40
+ * (`heating` / `dhw`) is intentional: both vocabularies stay wire-stable on
41
+ * their own.
35
42
  */
36
43
  var EnyoFlexibilityHeatpumpTargetTypeEnum;
37
44
  (function (EnyoFlexibilityHeatpumpTargetTypeEnum) {
@@ -39,6 +46,39 @@ var EnyoFlexibilityHeatpumpTargetTypeEnum;
39
46
  EnyoFlexibilityHeatpumpTargetTypeEnum["Cooling"] = "cooling";
40
47
  EnyoFlexibilityHeatpumpTargetTypeEnum["Dhw"] = "dhw";
41
48
  })(EnyoFlexibilityHeatpumpTargetTypeEnum || (exports.EnyoFlexibilityHeatpumpTargetTypeEnum = EnyoFlexibilityHeatpumpTargetTypeEnum = {}));
49
+ /**
50
+ * What a share of power is physically aimed at — the open vocabulary behind the
51
+ * "how much watt for what" breakdown carried by
52
+ * {@link EnyoFlexibilityTargetPower}, on flexibility announcements and on the
53
+ * available-power commands that answer them alike.
54
+ *
55
+ * The members present today all describe heat sinks, because thermal appliances
56
+ * are the first ones to split their draw. The enum is deliberately **not**
57
+ * scoped to thermal loads though: further members may describe non-thermal
58
+ * targets (a vehicle battery, a stationary storage, a dedicated household
59
+ * circuit) as other appliance types start announcing a breakdown. Consumers
60
+ * should therefore treat an unknown value as "some other target" rather than
61
+ * assuming every value maps to a heat sink.
62
+ *
63
+ * Broader than {@link EnyoFlexibilityHeatpumpTargetTypeEnum}, which names the
64
+ * *mode* a heat pump runs in: this enum adds the heating buffer tank, is not
65
+ * heat-pump specific (a heating rod announces against the same sinks), and
66
+ * carries no `cooling` member — cooling is a run mode, not a target.
67
+ *
68
+ * Values match the vocabulary used elsewhere in the SDK for the same physical
69
+ * parts (e.g. `domesticHotWater` and `bufferTank...` in the timeseries types),
70
+ * so a consumer can correlate an announcement with measured values without a
71
+ * mapping table.
72
+ */
73
+ var EnyoFlexibilityTargetEnum;
74
+ (function (EnyoFlexibilityTargetEnum) {
75
+ /** Domestic hot water tank. */
76
+ EnyoFlexibilityTargetEnum["DomesticHotWater"] = "domesticHotWater";
77
+ /** Heating buffer / storage tank. */
78
+ EnyoFlexibilityTargetEnum["BufferTank"] = "bufferTank";
79
+ /** Space heating circuit. */
80
+ EnyoFlexibilityTargetEnum["Heating"] = "heating";
81
+ })(EnyoFlexibilityTargetEnum || (exports.EnyoFlexibilityTargetEnum = EnyoFlexibilityTargetEnum = {}));
42
82
  /**
43
83
  * What an air-conditioning unit's flexibility is aimed at — extra context for
44
84
  * the decision maker. Cooling-only today; a heating variant may follow.
@@ -24,12 +24,51 @@ export declare enum EnyoFlexibilityAnnouncementTypeEnum {
24
24
  * What a heat pump's flexibility is aimed at — gives the decision maker extra
25
25
  * context on the demand behind a heat-pump announcement. `Cooling` is reserved
26
26
  * for a future cooling mode and is not emitted yet.
27
+ *
28
+ * This enum describes the *mode* a heat pump runs in. To say what the announced
29
+ * energy is for — and how much power goes to each target — use
30
+ * {@link EnyoFlexibilityTargetEnum} together with
31
+ * {@link EnyoFlexibilityTargetPower}. The overlap between the two
32
+ * (`heating` / `dhw`) is intentional: both vocabularies stay wire-stable on
33
+ * their own.
27
34
  */
28
35
  export declare enum EnyoFlexibilityHeatpumpTargetTypeEnum {
29
36
  Heating = "heating",
30
37
  Cooling = "cooling",
31
38
  Dhw = "dhw"
32
39
  }
40
+ /**
41
+ * What a share of power is physically aimed at — the open vocabulary behind the
42
+ * "how much watt for what" breakdown carried by
43
+ * {@link EnyoFlexibilityTargetPower}, on flexibility announcements and on the
44
+ * available-power commands that answer them alike.
45
+ *
46
+ * The members present today all describe heat sinks, because thermal appliances
47
+ * are the first ones to split their draw. The enum is deliberately **not**
48
+ * scoped to thermal loads though: further members may describe non-thermal
49
+ * targets (a vehicle battery, a stationary storage, a dedicated household
50
+ * circuit) as other appliance types start announcing a breakdown. Consumers
51
+ * should therefore treat an unknown value as "some other target" rather than
52
+ * assuming every value maps to a heat sink.
53
+ *
54
+ * Broader than {@link EnyoFlexibilityHeatpumpTargetTypeEnum}, which names the
55
+ * *mode* a heat pump runs in: this enum adds the heating buffer tank, is not
56
+ * heat-pump specific (a heating rod announces against the same sinks), and
57
+ * carries no `cooling` member — cooling is a run mode, not a target.
58
+ *
59
+ * Values match the vocabulary used elsewhere in the SDK for the same physical
60
+ * parts (e.g. `domesticHotWater` and `bufferTank...` in the timeseries types),
61
+ * so a consumer can correlate an announcement with measured values without a
62
+ * mapping table.
63
+ */
64
+ export declare enum EnyoFlexibilityTargetEnum {
65
+ /** Domestic hot water tank. */
66
+ DomesticHotWater = "domesticHotWater",
67
+ /** Heating buffer / storage tank. */
68
+ BufferTank = "bufferTank",
69
+ /** Space heating circuit. */
70
+ Heating = "heating"
71
+ }
33
72
  /**
34
73
  * What an air-conditioning unit's flexibility is aimed at — extra context for
35
74
  * the decision maker. Cooling-only today; a heating variant may follow.
@@ -60,6 +99,44 @@ export declare enum EnyoFlexibilityOptimizationModeEnum {
60
99
  PvSurplusPreferred = "pv-surplus-preferred",
61
100
  PriceLimit = "price-limit"
62
101
  }
102
+ /**
103
+ * How much power is meant for one target — one entry of the "how much watt for
104
+ * what" breakdown.
105
+ *
106
+ * Used in both directions, with the same shape and the same vocabulary so the
107
+ * two can be read against each other:
108
+ *
109
+ * - **Appliance → manager**, on a flexibility announcement: what the announced
110
+ * flexibility would be spent on.
111
+ * - **Manager → appliance**, on an available-power command
112
+ * (`EnyoAvailablePowerCommandData.targets`): what the granted envelope is
113
+ * meant for.
114
+ *
115
+ * Informational in both cases — the carrying message's own energy or power
116
+ * figure stays authoritative, and this breakdown never acts as a second limit. A
117
+ * breakdown may be partial, and a given {@link target} SHOULD appear at most
118
+ * once per breakdown.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // A heat pump that would put 1500 W into the DHW tank and 800 W into heating
123
+ * const targets: EnyoFlexibilityTargetPower[] = [
124
+ * {target: EnyoFlexibilityTargetEnum.DomesticHotWater, powerW: 1500, kWh: 2.5},
125
+ * {target: EnyoFlexibilityTargetEnum.Heating, powerW: 800},
126
+ * ];
127
+ * ```
128
+ */
129
+ export interface EnyoFlexibilityTargetPower {
130
+ /** What this share is for. */
131
+ target: EnyoFlexibilityTargetEnum;
132
+ /** Electrical power this share would draw, in Watts. Non-negative. */
133
+ powerW: number;
134
+ /**
135
+ * Share of the announced energy attributable to this target, in kWh.
136
+ * Optional — omit when only the power split is known.
137
+ */
138
+ kWh?: number;
139
+ }
63
140
  /** Discrete power band the solver may pick from: [minWatt, maxWatt] in stepWatt steps. */
64
141
  export interface EnyoFlexibilityPowerBand {
65
142
  /** Lower bound of the band, in Watts. Non-negative. */
@@ -125,6 +202,13 @@ export interface EnyoFlexibilityAnnouncementContext {
125
202
  heatpumpTargetType?: EnyoFlexibilityHeatpumpTargetTypeEnum;
126
203
  /** For air-conditioning announcements: what the flexibility is aimed at. */
127
204
  airConditioningTargetType?: EnyoFlexibilityAirConditioningTargetTypeEnum;
205
+ /**
206
+ * How much power the announced flexibility would draw per target — "how much
207
+ * watt for what". Keeps the category surface in step with the per-appliance
208
+ * announcement, which carries the same breakdown under
209
+ * `data.flexibility.context.targets`.
210
+ */
211
+ targets?: EnyoFlexibilityTargetPower[];
128
212
  /**
129
213
  * For storage announcements: the round-trip cost of cycling the battery, in
130
214
  * EUR per kWh. The floor a discharge has to beat to be worth licensing.
@@ -538,3 +538,94 @@ export interface AirConditioningTemperatureTimeseriesResponse extends Timeseries
538
538
  /** Array of air conditioning temperature entries, one per time bucket */
539
539
  entries: AirConditioningTemperatureTimeseriesEntry[];
540
540
  }
541
+ /**
542
+ * Power and runtime figures for a single smart plug within one time bucket.
543
+ *
544
+ * A smart plug measures an arbitrary load, so the per-plug breakdown matters
545
+ * more here than for other appliance types: summing several plugs gives the
546
+ * total switchable load, but only the per-plug values say *which* load ran.
547
+ *
548
+ * Every field other than the identity is optional, because plug capabilities
549
+ * differ (see {@link EnyoSmartPlugApplianceAvailableFeaturesEnum}): a
550
+ * switch-only plug reports runtime but no power, a measure-only plug reports
551
+ * power but no runtime.
552
+ */
553
+ export interface SmartPlugTimeseriesPlugValues {
554
+ /** ID of the smart plug appliance these values belong to */
555
+ applianceId: string;
556
+ /**
557
+ * Time-weighted average power drawn by the connected load in Watts for this
558
+ * bucket. Omitted for plugs that cannot measure power — this is not the same
559
+ * as `0`, which means "measured, nothing drawing".
560
+ */
561
+ averagePowerW?: number;
562
+ /** Cumulative energy drawn by the connected load in Watt-hours for this bucket */
563
+ powerWh?: number;
564
+ /** Lowest power in Watts observed in this bucket */
565
+ minPowerW?: number;
566
+ /** Highest power in Watts observed in this bucket */
567
+ maxPowerW?: number;
568
+ /**
569
+ * Minutes the relay was on within this bucket, for plugs that report their
570
+ * state. `0` means the plug was known to be off for the whole bucket; the
571
+ * value never exceeds the bucket length.
572
+ */
573
+ onDurationMinutes?: number;
574
+ /**
575
+ * Number of relay state changes observed in this bucket. Useful for spotting
576
+ * short-cycling of the connected load.
577
+ */
578
+ switchCount?: number;
579
+ }
580
+ /**
581
+ * A single entry in the smart plug timeseries.
582
+ *
583
+ * Carries the aggregate across every included plug plus the per-plug breakdown
584
+ * for the same bucket, so a consumer can chart the total switchable load and
585
+ * the individual loads from one response.
586
+ */
587
+ export interface SmartPlugTimeseriesEntry extends TimeseriesEntryBase {
588
+ /** Time-weighted average power across all included plugs in Watts for this bucket */
589
+ smartPlugPowerW: number;
590
+ /** Cumulative energy across all included plugs in Watt-hours for this bucket */
591
+ smartPlugPowerWh: number;
592
+ /** Per-plug values for this bucket, one entry per included plug */
593
+ plugs: SmartPlugTimeseriesPlugValues[];
594
+ }
595
+ /**
596
+ * Request parameters for querying smart plug timeseries data.
597
+ *
598
+ * Pass `applianceIds` to restrict the query to specific plugs; omit it to
599
+ * include every smart plug of the device.
600
+ */
601
+ export interface SmartPlugTimeseriesRequest extends TimeseriesRequestBase {
602
+ }
603
+ /**
604
+ * Per-plug summary across the full queried period.
605
+ *
606
+ * Mirrors the optionality of {@link SmartPlugTimeseriesPlugValues}: a field is
607
+ * only present when the plug reported the underlying values.
608
+ */
609
+ export interface SmartPlugTimeseriesPlugSummary {
610
+ /** ID of the smart plug appliance this summary belongs to */
611
+ applianceId: string;
612
+ /** Total energy drawn by the connected load in Watt-hours across all buckets */
613
+ totalPowerWh?: number;
614
+ /** Time-weighted average power in Watts across the full period */
615
+ averagePowerW?: number;
616
+ /** Total minutes the relay was on across the full period */
617
+ totalOnDurationMinutes?: number;
618
+ /** Total number of relay state changes across the full period */
619
+ totalSwitchCount?: number;
620
+ }
621
+ /**
622
+ * Response containing smart plug timeseries data.
623
+ */
624
+ export interface SmartPlugTimeseriesResponse extends TimeseriesResponseBase {
625
+ /** Array of smart plug entries, one per time bucket */
626
+ entries: SmartPlugTimeseriesEntry[];
627
+ /** Total energy across all included plugs in Watt-hours across all buckets */
628
+ totalSmartPlugPowerWh: number;
629
+ /** Per-plug summaries across the full queried period */
630
+ plugs: SmartPlugTimeseriesPlugSummary[];
631
+ }
@@ -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.10.0';
12
+ exports.SDK_VERSION = '1.12.0';
13
13
  /**
14
14
  * Gets the current SDK version.
15
15
  * @returns The semantic version string of the SDK
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "1.10.0";
8
+ export declare const SDK_VERSION = "1.12.0";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -1,4 +1,4 @@
1
- import { DataBusMessageQueryRequest, DataBusMessageQueryResponse, PvProductionTimeseriesRequest, PvProductionTimeseriesResponse, BatterySocTimeseriesRequest, BatterySocTimeseriesResponse, BatteryPowerTimeseriesRequest, BatteryPowerTimeseriesResponse, MeterValuesTimeseriesRequest, MeterValuesTimeseriesResponse, GridPowerTimeseriesRequest, GridPowerTimeseriesResponse, HomeConsumptionTimeseriesRequest, HomeConsumptionTimeseriesResponse, HeatpumpTemperatureTimeseriesRequest, HeatpumpTemperatureTimeseriesResponse, HeatpumpPowerTimeseriesRequest, HeatpumpPowerTimeseriesResponse, TemperatureSensorTimeseriesRequest, TemperatureSensorTimeseriesResponse, AirConditioningPowerTimeseriesRequest, AirConditioningPowerTimeseriesResponse, AirConditioningTemperatureTimeseriesRequest, AirConditioningTemperatureTimeseriesResponse } from "../types/enyo-timeseries.js";
1
+ import { DataBusMessageQueryRequest, DataBusMessageQueryResponse, PvProductionTimeseriesRequest, PvProductionTimeseriesResponse, BatterySocTimeseriesRequest, BatterySocTimeseriesResponse, BatteryPowerTimeseriesRequest, BatteryPowerTimeseriesResponse, MeterValuesTimeseriesRequest, MeterValuesTimeseriesResponse, GridPowerTimeseriesRequest, GridPowerTimeseriesResponse, HomeConsumptionTimeseriesRequest, HomeConsumptionTimeseriesResponse, HeatpumpTemperatureTimeseriesRequest, HeatpumpTemperatureTimeseriesResponse, HeatpumpPowerTimeseriesRequest, HeatpumpPowerTimeseriesResponse, TemperatureSensorTimeseriesRequest, TemperatureSensorTimeseriesResponse, AirConditioningPowerTimeseriesRequest, AirConditioningPowerTimeseriesResponse, AirConditioningTemperatureTimeseriesRequest, AirConditioningTemperatureTimeseriesResponse, SmartPlugTimeseriesRequest, SmartPlugTimeseriesResponse } from "../types/enyo-timeseries.js";
2
2
  /**
3
3
  * Interface for querying historical energy data with configurable bucket granularity.
4
4
  * Provides methods to retrieve aggregated timeseries data for various energy metrics
@@ -253,4 +253,33 @@ export interface EnergyAppTimeseries {
253
253
  * ```
254
254
  */
255
255
  getAirConditioningTemperatureTimeseries(request: AirConditioningTemperatureTimeseriesRequest): Promise<AirConditioningTemperatureTimeseriesResponse>;
256
+ /**
257
+ * Retrieves smart plug timeseries data aggregated in time buckets.
258
+ *
259
+ * Every bucket carries the aggregate across all included plugs
260
+ * (`smartPlugPowerW` / `Wh`) plus a per-plug breakdown, since a plug measures
261
+ * an arbitrary load and the total alone does not say which load ran. The
262
+ * response additionally summarises each plug across the full period.
263
+ *
264
+ * Per-plug fields are optional because plug capabilities differ: a
265
+ * measure-only plug reports power but no runtime, a switch-only plug reports
266
+ * runtime (`onDurationMinutes`, `switchCount`) but no power.
267
+ *
268
+ * @param request - The query parameters including date range and optional appliance filter
269
+ * @returns Promise resolving to smart plug entries with the total and per-plug summaries
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const response = await timeseries.getSmartPlugTimeseries({
274
+ * startDateIso: '2024-01-01T00:00:00Z',
275
+ * endDateIso: '2024-01-02T00:00:00Z'
276
+ * });
277
+ * console.log(`Total plug consumption: ${response.totalSmartPlugPowerWh} Wh`);
278
+ * response.plugs.forEach(plug => {
279
+ * console.log(`${plug.applianceId}: ${plug.totalPowerWh ?? 0} Wh, ` +
280
+ * `on for ${plug.totalOnDurationMinutes ?? 0} min`);
281
+ * });
282
+ * ```
283
+ */
284
+ getSmartPlugTimeseries(request: SmartPlugTimeseriesRequest): Promise<SmartPlugTimeseriesResponse>;
256
285
  }
@@ -7,6 +7,7 @@ import { PreviewChargingSchedule, PreviewChargingScheduleCostComparison, Preview
7
7
  import { EnyoEnergyPrices } from "./enyo-energy-prices.js";
8
8
  import { EnyoCurrencyEnum } from "./enyo-currency.js";
9
9
  import { EnyoHeatpumpApplianceModeEnum } from "./enyo-heatpump-appliance.js";
10
+ import type { EnyoFlexibilityTargetPower } from "./enyo-flexibility-announcement.js";
10
11
  import { EnyoSmartPlugApplianceStateEnum } from "./enyo-smart-plug-appliance.js";
11
12
  import { EnyoAirConditioningApplianceModeEnum, EnyoAirConditioningOptimizationModeEnum } from "./enyo-air-conditioning-appliance.js";
12
13
  import { EnergyAppPackageCategory } from "../energy-app-package-definition.js";
@@ -579,6 +580,36 @@ export interface EnyoDataBusInverterValuesV1 extends EnyoDataBusMessage {
579
580
  gridOperatorLimit?: EnyoGridOperatorLimit;
580
581
  };
581
582
  }
583
+ /**
584
+ * An appliance announces how much energy it can shift, and until when.
585
+ *
586
+ * Optionally it can also say *what the energy is for and at which power* via
587
+ * `data.flexibility.context.targets` — e.g. a heat pump splitting its draw
588
+ * between the domestic hot water tank, the heating buffer tank, and the space
589
+ * heating circuit. That breakdown is additive context for the decision maker;
590
+ * `kWh` remains the authoritative total.
591
+ *
592
+ * @example
593
+ * ```typescript
594
+ * dataBus.sendMessage([{
595
+ * type: 'message',
596
+ * message: EnyoDataBusMessageEnum.ApplianceFlexibilityAnnouncementV1,
597
+ * applianceId: 'heatpump-1',
598
+ * data: {
599
+ * flexibility: {
600
+ * kWh: 4,
601
+ * availableUntilIsoTimestamp: '2025-10-01T14:00:00Z',
602
+ * context: {
603
+ * targets: [
604
+ * {target: EnyoFlexibilityTargetEnum.DomesticHotWater, powerW: 1500, kWh: 2.5},
605
+ * {target: EnyoFlexibilityTargetEnum.BufferTank, powerW: 800, kWh: 1.5},
606
+ * ],
607
+ * },
608
+ * },
609
+ * },
610
+ * }]);
611
+ * ```
612
+ */
582
613
  export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataBusMessage {
583
614
  type: 'message';
584
615
  message: EnyoDataBusMessageEnum.ApplianceFlexibilityAnnouncementV1;
@@ -589,6 +620,19 @@ export interface EnyoDataBusApplianceFlexibilityAnnouncementV1 extends EnyoDataB
589
620
  kWh: number;
590
621
  /** Defines until the kWh flexibility can be shifted. If for Example 10 kWh can be shifted until 2025-10-01T14:00:00 (current time 2025-10-01T10:00:00), the control can shift the 10 kWh in the next 4 hours */
591
622
  availableUntilIsoTimestamp: string;
623
+ /**
624
+ * Optional extra context for the consumer of this announcement.
625
+ * Nested so further context keys can be added without changing the
626
+ * message shape again.
627
+ */
628
+ context?: {
629
+ /**
630
+ * Breakdown of what the announced flexibility is for and at which
631
+ * power. May be partial — entries need not sum to the appliance's
632
+ * full draw — and a given target SHOULD appear at most once.
633
+ */
634
+ targets: EnyoFlexibilityTargetPower[];
635
+ };
592
636
  };
593
637
  };
594
638
  }
@@ -867,6 +911,20 @@ export interface EnyoAvailablePowerCommandData {
867
911
  * Must be non-negative. The appliance must not exceed this envelope.
868
912
  */
869
913
  powerW: number;
914
+ /**
915
+ * Optional breakdown of what the granted envelope is meant for and at which
916
+ * power — the same "how much watt for what" vocabulary an appliance uses to
917
+ * announce its flexibility
918
+ * ({@link EnyoDataBusApplianceFlexibilityAnnouncementV1}), so a grant can be
919
+ * read against the announcement it answers.
920
+ *
921
+ * Advisory, and never a second limit: `powerW` alone bounds what the
922
+ * appliance may draw. The shares SHOULD NOT exceed `powerW` in sum, may be
923
+ * partial, and a given target SHOULD appear at most once. An appliance that
924
+ * does not understand a target should fall back to spending the envelope as
925
+ * it sees fit rather than refusing it.
926
+ */
927
+ targets?: EnyoFlexibilityTargetPower[];
870
928
  /** Optional reason why this command was issued */
871
929
  reason?: EnyoDataBusCommandReason;
872
930
  }
@@ -2243,7 +2301,8 @@ export interface EnyoPowerSourceShare {
2243
2301
  /**
2244
2302
  * V2 command announcing the available / maximum active-power envelope (in
2245
2303
  * Watts) a heatpump may draw, together with optional context describing what
2246
- * the power should be used for ({@link EnyoHeatpumpControlPurposeEnum}) and
2304
+ * the power should be used for ({@link EnyoHeatpumpControlPurposeEnum}), how it
2305
+ * splits across targets ({@link EnyoAvailablePowerCommandData.targets}), and
2247
2306
  * where it comes from ({@link EnyoPowerSourceShare}). Supersedes the deprecated
2248
2307
  * {@link EnyoDataBusHeatpumpAvailablePowerAnnouncementV1}.
2249
2308
  *
@@ -2260,6 +2319,14 @@ export interface EnyoDataBusSetHeatpumpAvailablePowerV2 extends EnyoDataBusMessa
2260
2319
  /**
2261
2320
  * What the heatpump should use the announced power for (e.g. DHW boost,
2262
2321
  * pre-heating). Advisory — the appliance may still apply its own logic.
2322
+ *
2323
+ * This names a single intent for the whole envelope, and covers intents
2324
+ * that are not a heat sink at all ({@link
2325
+ * EnyoHeatpumpControlPurposeEnum.PreHeating}). To instead split the
2326
+ * envelope across sinks — "1500 W for hot water, 800 W for the buffer
2327
+ * tank" — use {@link EnyoAvailablePowerCommandData.targets}. The two may
2328
+ * be sent together; they are separate vocabularies and neither is derived
2329
+ * from the other.
2263
2330
  */
2264
2331
  purpose?: EnyoHeatpumpControlPurposeEnum;
2265
2332
  /**
@@ -24,12 +24,51 @@ export declare enum EnyoFlexibilityAnnouncementTypeEnum {
24
24
  * What a heat pump's flexibility is aimed at — gives the decision maker extra
25
25
  * context on the demand behind a heat-pump announcement. `Cooling` is reserved
26
26
  * for a future cooling mode and is not emitted yet.
27
+ *
28
+ * This enum describes the *mode* a heat pump runs in. To say what the announced
29
+ * energy is for — and how much power goes to each target — use
30
+ * {@link EnyoFlexibilityTargetEnum} together with
31
+ * {@link EnyoFlexibilityTargetPower}. The overlap between the two
32
+ * (`heating` / `dhw`) is intentional: both vocabularies stay wire-stable on
33
+ * their own.
27
34
  */
28
35
  export declare enum EnyoFlexibilityHeatpumpTargetTypeEnum {
29
36
  Heating = "heating",
30
37
  Cooling = "cooling",
31
38
  Dhw = "dhw"
32
39
  }
40
+ /**
41
+ * What a share of power is physically aimed at — the open vocabulary behind the
42
+ * "how much watt for what" breakdown carried by
43
+ * {@link EnyoFlexibilityTargetPower}, on flexibility announcements and on the
44
+ * available-power commands that answer them alike.
45
+ *
46
+ * The members present today all describe heat sinks, because thermal appliances
47
+ * are the first ones to split their draw. The enum is deliberately **not**
48
+ * scoped to thermal loads though: further members may describe non-thermal
49
+ * targets (a vehicle battery, a stationary storage, a dedicated household
50
+ * circuit) as other appliance types start announcing a breakdown. Consumers
51
+ * should therefore treat an unknown value as "some other target" rather than
52
+ * assuming every value maps to a heat sink.
53
+ *
54
+ * Broader than {@link EnyoFlexibilityHeatpumpTargetTypeEnum}, which names the
55
+ * *mode* a heat pump runs in: this enum adds the heating buffer tank, is not
56
+ * heat-pump specific (a heating rod announces against the same sinks), and
57
+ * carries no `cooling` member — cooling is a run mode, not a target.
58
+ *
59
+ * Values match the vocabulary used elsewhere in the SDK for the same physical
60
+ * parts (e.g. `domesticHotWater` and `bufferTank...` in the timeseries types),
61
+ * so a consumer can correlate an announcement with measured values without a
62
+ * mapping table.
63
+ */
64
+ export declare enum EnyoFlexibilityTargetEnum {
65
+ /** Domestic hot water tank. */
66
+ DomesticHotWater = "domesticHotWater",
67
+ /** Heating buffer / storage tank. */
68
+ BufferTank = "bufferTank",
69
+ /** Space heating circuit. */
70
+ Heating = "heating"
71
+ }
33
72
  /**
34
73
  * What an air-conditioning unit's flexibility is aimed at — extra context for
35
74
  * the decision maker. Cooling-only today; a heating variant may follow.
@@ -60,6 +99,44 @@ export declare enum EnyoFlexibilityOptimizationModeEnum {
60
99
  PvSurplusPreferred = "pv-surplus-preferred",
61
100
  PriceLimit = "price-limit"
62
101
  }
102
+ /**
103
+ * How much power is meant for one target — one entry of the "how much watt for
104
+ * what" breakdown.
105
+ *
106
+ * Used in both directions, with the same shape and the same vocabulary so the
107
+ * two can be read against each other:
108
+ *
109
+ * - **Appliance → manager**, on a flexibility announcement: what the announced
110
+ * flexibility would be spent on.
111
+ * - **Manager → appliance**, on an available-power command
112
+ * (`EnyoAvailablePowerCommandData.targets`): what the granted envelope is
113
+ * meant for.
114
+ *
115
+ * Informational in both cases — the carrying message's own energy or power
116
+ * figure stays authoritative, and this breakdown never acts as a second limit. A
117
+ * breakdown may be partial, and a given {@link target} SHOULD appear at most
118
+ * once per breakdown.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // A heat pump that would put 1500 W into the DHW tank and 800 W into heating
123
+ * const targets: EnyoFlexibilityTargetPower[] = [
124
+ * {target: EnyoFlexibilityTargetEnum.DomesticHotWater, powerW: 1500, kWh: 2.5},
125
+ * {target: EnyoFlexibilityTargetEnum.Heating, powerW: 800},
126
+ * ];
127
+ * ```
128
+ */
129
+ export interface EnyoFlexibilityTargetPower {
130
+ /** What this share is for. */
131
+ target: EnyoFlexibilityTargetEnum;
132
+ /** Electrical power this share would draw, in Watts. Non-negative. */
133
+ powerW: number;
134
+ /**
135
+ * Share of the announced energy attributable to this target, in kWh.
136
+ * Optional — omit when only the power split is known.
137
+ */
138
+ kWh?: number;
139
+ }
63
140
  /** Discrete power band the solver may pick from: [minWatt, maxWatt] in stepWatt steps. */
64
141
  export interface EnyoFlexibilityPowerBand {
65
142
  /** Lower bound of the band, in Watts. Non-negative. */
@@ -125,6 +202,13 @@ export interface EnyoFlexibilityAnnouncementContext {
125
202
  heatpumpTargetType?: EnyoFlexibilityHeatpumpTargetTypeEnum;
126
203
  /** For air-conditioning announcements: what the flexibility is aimed at. */
127
204
  airConditioningTargetType?: EnyoFlexibilityAirConditioningTargetTypeEnum;
205
+ /**
206
+ * How much power the announced flexibility would draw per target — "how much
207
+ * watt for what". Keeps the category surface in step with the per-appliance
208
+ * announcement, which carries the same breakdown under
209
+ * `data.flexibility.context.targets`.
210
+ */
211
+ targets?: EnyoFlexibilityTargetPower[];
128
212
  /**
129
213
  * For storage announcements: the round-trip cost of cycling the battery, in
130
214
  * EUR per kWh. The floor a discharge has to beat to be worth licensing.
@@ -29,6 +29,13 @@ export var EnyoFlexibilityAnnouncementTypeEnum;
29
29
  * What a heat pump's flexibility is aimed at — gives the decision maker extra
30
30
  * context on the demand behind a heat-pump announcement. `Cooling` is reserved
31
31
  * for a future cooling mode and is not emitted yet.
32
+ *
33
+ * This enum describes the *mode* a heat pump runs in. To say what the announced
34
+ * energy is for — and how much power goes to each target — use
35
+ * {@link EnyoFlexibilityTargetEnum} together with
36
+ * {@link EnyoFlexibilityTargetPower}. The overlap between the two
37
+ * (`heating` / `dhw`) is intentional: both vocabularies stay wire-stable on
38
+ * their own.
32
39
  */
33
40
  export var EnyoFlexibilityHeatpumpTargetTypeEnum;
34
41
  (function (EnyoFlexibilityHeatpumpTargetTypeEnum) {
@@ -36,6 +43,39 @@ export var EnyoFlexibilityHeatpumpTargetTypeEnum;
36
43
  EnyoFlexibilityHeatpumpTargetTypeEnum["Cooling"] = "cooling";
37
44
  EnyoFlexibilityHeatpumpTargetTypeEnum["Dhw"] = "dhw";
38
45
  })(EnyoFlexibilityHeatpumpTargetTypeEnum || (EnyoFlexibilityHeatpumpTargetTypeEnum = {}));
46
+ /**
47
+ * What a share of power is physically aimed at — the open vocabulary behind the
48
+ * "how much watt for what" breakdown carried by
49
+ * {@link EnyoFlexibilityTargetPower}, on flexibility announcements and on the
50
+ * available-power commands that answer them alike.
51
+ *
52
+ * The members present today all describe heat sinks, because thermal appliances
53
+ * are the first ones to split their draw. The enum is deliberately **not**
54
+ * scoped to thermal loads though: further members may describe non-thermal
55
+ * targets (a vehicle battery, a stationary storage, a dedicated household
56
+ * circuit) as other appliance types start announcing a breakdown. Consumers
57
+ * should therefore treat an unknown value as "some other target" rather than
58
+ * assuming every value maps to a heat sink.
59
+ *
60
+ * Broader than {@link EnyoFlexibilityHeatpumpTargetTypeEnum}, which names the
61
+ * *mode* a heat pump runs in: this enum adds the heating buffer tank, is not
62
+ * heat-pump specific (a heating rod announces against the same sinks), and
63
+ * carries no `cooling` member — cooling is a run mode, not a target.
64
+ *
65
+ * Values match the vocabulary used elsewhere in the SDK for the same physical
66
+ * parts (e.g. `domesticHotWater` and `bufferTank...` in the timeseries types),
67
+ * so a consumer can correlate an announcement with measured values without a
68
+ * mapping table.
69
+ */
70
+ export var EnyoFlexibilityTargetEnum;
71
+ (function (EnyoFlexibilityTargetEnum) {
72
+ /** Domestic hot water tank. */
73
+ EnyoFlexibilityTargetEnum["DomesticHotWater"] = "domesticHotWater";
74
+ /** Heating buffer / storage tank. */
75
+ EnyoFlexibilityTargetEnum["BufferTank"] = "bufferTank";
76
+ /** Space heating circuit. */
77
+ EnyoFlexibilityTargetEnum["Heating"] = "heating";
78
+ })(EnyoFlexibilityTargetEnum || (EnyoFlexibilityTargetEnum = {}));
39
79
  /**
40
80
  * What an air-conditioning unit's flexibility is aimed at — extra context for
41
81
  * the decision maker. Cooling-only today; a heating variant may follow.
@@ -538,3 +538,94 @@ export interface AirConditioningTemperatureTimeseriesResponse extends Timeseries
538
538
  /** Array of air conditioning temperature entries, one per time bucket */
539
539
  entries: AirConditioningTemperatureTimeseriesEntry[];
540
540
  }
541
+ /**
542
+ * Power and runtime figures for a single smart plug within one time bucket.
543
+ *
544
+ * A smart plug measures an arbitrary load, so the per-plug breakdown matters
545
+ * more here than for other appliance types: summing several plugs gives the
546
+ * total switchable load, but only the per-plug values say *which* load ran.
547
+ *
548
+ * Every field other than the identity is optional, because plug capabilities
549
+ * differ (see {@link EnyoSmartPlugApplianceAvailableFeaturesEnum}): a
550
+ * switch-only plug reports runtime but no power, a measure-only plug reports
551
+ * power but no runtime.
552
+ */
553
+ export interface SmartPlugTimeseriesPlugValues {
554
+ /** ID of the smart plug appliance these values belong to */
555
+ applianceId: string;
556
+ /**
557
+ * Time-weighted average power drawn by the connected load in Watts for this
558
+ * bucket. Omitted for plugs that cannot measure power — this is not the same
559
+ * as `0`, which means "measured, nothing drawing".
560
+ */
561
+ averagePowerW?: number;
562
+ /** Cumulative energy drawn by the connected load in Watt-hours for this bucket */
563
+ powerWh?: number;
564
+ /** Lowest power in Watts observed in this bucket */
565
+ minPowerW?: number;
566
+ /** Highest power in Watts observed in this bucket */
567
+ maxPowerW?: number;
568
+ /**
569
+ * Minutes the relay was on within this bucket, for plugs that report their
570
+ * state. `0` means the plug was known to be off for the whole bucket; the
571
+ * value never exceeds the bucket length.
572
+ */
573
+ onDurationMinutes?: number;
574
+ /**
575
+ * Number of relay state changes observed in this bucket. Useful for spotting
576
+ * short-cycling of the connected load.
577
+ */
578
+ switchCount?: number;
579
+ }
580
+ /**
581
+ * A single entry in the smart plug timeseries.
582
+ *
583
+ * Carries the aggregate across every included plug plus the per-plug breakdown
584
+ * for the same bucket, so a consumer can chart the total switchable load and
585
+ * the individual loads from one response.
586
+ */
587
+ export interface SmartPlugTimeseriesEntry extends TimeseriesEntryBase {
588
+ /** Time-weighted average power across all included plugs in Watts for this bucket */
589
+ smartPlugPowerW: number;
590
+ /** Cumulative energy across all included plugs in Watt-hours for this bucket */
591
+ smartPlugPowerWh: number;
592
+ /** Per-plug values for this bucket, one entry per included plug */
593
+ plugs: SmartPlugTimeseriesPlugValues[];
594
+ }
595
+ /**
596
+ * Request parameters for querying smart plug timeseries data.
597
+ *
598
+ * Pass `applianceIds` to restrict the query to specific plugs; omit it to
599
+ * include every smart plug of the device.
600
+ */
601
+ export interface SmartPlugTimeseriesRequest extends TimeseriesRequestBase {
602
+ }
603
+ /**
604
+ * Per-plug summary across the full queried period.
605
+ *
606
+ * Mirrors the optionality of {@link SmartPlugTimeseriesPlugValues}: a field is
607
+ * only present when the plug reported the underlying values.
608
+ */
609
+ export interface SmartPlugTimeseriesPlugSummary {
610
+ /** ID of the smart plug appliance this summary belongs to */
611
+ applianceId: string;
612
+ /** Total energy drawn by the connected load in Watt-hours across all buckets */
613
+ totalPowerWh?: number;
614
+ /** Time-weighted average power in Watts across the full period */
615
+ averagePowerW?: number;
616
+ /** Total minutes the relay was on across the full period */
617
+ totalOnDurationMinutes?: number;
618
+ /** Total number of relay state changes across the full period */
619
+ totalSwitchCount?: number;
620
+ }
621
+ /**
622
+ * Response containing smart plug timeseries data.
623
+ */
624
+ export interface SmartPlugTimeseriesResponse extends TimeseriesResponseBase {
625
+ /** Array of smart plug entries, one per time bucket */
626
+ entries: SmartPlugTimeseriesEntry[];
627
+ /** Total energy across all included plugs in Watt-hours across all buckets */
628
+ totalSmartPlugPowerWh: number;
629
+ /** Per-plug summaries across the full queried period */
630
+ plugs: SmartPlugTimeseriesPlugSummary[];
631
+ }
package/dist/version.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "1.10.0";
8
+ export declare const SDK_VERSION = "1.12.0";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/dist/version.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export const SDK_VERSION = '1.10.0';
8
+ export const SDK_VERSION = '1.12.0';
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enyo-energy/energy-app-sdk",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "enyo Energy App SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",