@enyo-energy/energy-app-sdk 1.20.0 → 1.21.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
@@ -375,6 +375,7 @@ Energy Apps use a granular permissions system to control access to system resour
375
375
  - **`EnergyManager`**: Run as the active energy manager
376
376
  - **`EnergyManagerInfo`**: Read information about the active energy manager
377
377
  - **`WeatherForecastRegister`** / **`WeatherForecastUse`**: Publish / consume weather forecasts
378
+ - **`WeatherHistoryRegister`** / **`WeatherHistoryUse`**: Publish / consume observed (past) weather data
378
379
  - **`PvForecastRegister`** / **`PvForecastUse`**: Publish / consume PV forecasts
379
380
  - **`DynamicPriceForecastRegister`** / **`DynamicPriceForecastUse`**: Publish / consume dynamic-price forecasts
380
381
  - **`PvSystemRegister`** / **`PvSystemUse`**: Register / read PV system configuration
@@ -1769,6 +1770,86 @@ const byCoords = await weather.getWeatherForecastByCoordinates('wx-prod', 48.13,
1769
1770
 
1770
1771
  Publishers need `WeatherForecastRegister`; consumers need `WeatherForecastUse`.
1771
1772
 
1773
+ #### `useWeatherHistory(): EnergyAppWeatherHistory`
1774
+
1775
+ The backward-looking counterpart. Where forecasting says what the weather *will* do, this says what it
1776
+ *did* between two timestamps — temperature, wind, cloud cover and solar irradiance. That is what you
1777
+ need to correlate measured consumption with the weather that drove it, build heating-degree-day
1778
+ statistics, check measured PV production against the irradiance that was actually available, or train
1779
+ a consumption model on outdoor conditions.
1780
+
1781
+ ```typescript
1782
+ const weatherHistory = energyApp.useWeatherHistory();
1783
+
1784
+ await weatherHistory.registerHistory({
1785
+ historyId: 'dwd-archive',
1786
+ name: 'DWD Climate Archive',
1787
+ vendor: 'Deutscher Wetterdienst',
1788
+ availableHistoryDays: 730,
1789
+ availableMeasures: [
1790
+ WeatherHistoryMeasureEnum.OutdoorTemperature,
1791
+ WeatherHistoryMeasureEnum.WindSpeed,
1792
+ WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance,
1793
+ ],
1794
+ });
1795
+
1796
+ const temperatures = await weatherHistory.getOutdoorTemperature('dwd-archive', {
1797
+ fromIso: '2026-01-15T00:00:00Z',
1798
+ untilIso: '2026-01-16T00:00:00Z',
1799
+ resolution: WeatherHistoryResolutionEnum.OneHour, // optional, defaults to the provider's
1800
+ });
1801
+
1802
+ temperatures.averageCelsius; // time-weighted mean over the interval
1803
+ temperatures.minCelsius;
1804
+ temperatures.maxCelsius;
1805
+ temperatures.readings; // [{ timestampIso, outdoorTemperatureCelsius }, …]
1806
+ ```
1807
+
1808
+ The interval is half-open — `fromIso` included, `untilIso` excluded — so consecutive intervals line
1809
+ up without double-counting the boundary. A `resolution` finer than the provider's is filled by
1810
+ linear interpolation, a coarser one aggregated as a time-weighted average.
1811
+
1812
+ Reaching further back than the archive goes is **not** an error: you get the covered part plus
1813
+ `coveredFromIso` / `coveredUntilIso` telling you where the data actually began and ended, and an
1814
+ interval the provider holds nothing for returns empty `readings` with no aggregates.
1815
+
1816
+ No location is passed: the registered provider resolves the device's own location through
1817
+ `useLocation()`, so a consumer only states the interval it wants.
1818
+
1819
+ For anything beyond temperature — irradiance, wind, cloud cover — use `getWeatherHistory`, which
1820
+ returns every requested measure per bucket:
1821
+
1822
+ ```typescript
1823
+ const history = await weatherHistory.getWeatherHistory('open-meteo-archive', {
1824
+ fromIso: '2026-01-15T00:00:00Z',
1825
+ untilIso: '2026-01-16T00:00:00Z',
1826
+ resolution: WeatherHistoryResolutionEnum.OneHour,
1827
+ measures: [ // optional, defaults to everything held
1828
+ WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance,
1829
+ WeatherHistoryMeasureEnum.WindSpeed,
1830
+ WeatherHistoryMeasureEnum.CloudArea,
1831
+ ],
1832
+ });
1833
+
1834
+ history.measures; // what actually came back
1835
+ history.readings; // [{ timestampIso, globalHorizontalIrradiance, windSpeedMs, … }, …]
1836
+ history.statistics?.[WeatherHistoryMeasureEnum.WindSpeed]?.averageValue;
1837
+ ```
1838
+
1839
+ Field names and units mirror `WeatherForecastEntry` one to one — `outdoorTemperatureCelsius`,
1840
+ `windSpeedMs`, `cloudAreaPercent` (0–100), `symbol`, and `globalHorizontalIrradiance` /
1841
+ `directNormalIrradiance` / `diffuseHorizontalIrradiance` in W/m² — so an observed series and a
1842
+ forecast series concatenate into one timeline without translation. Every measure on a reading is
1843
+ optional: you get what the provider holds and you asked for, and a measure it does not hold is simply
1844
+ absent rather than an error.
1845
+
1846
+ Aggregates per measure live in `statistics`, keyed by `WeatherHistoryMeasureEnum`. `averageValue` is
1847
+ time-weighted; for the irradiance measures it is a mean power density in W/m², so multiply by the
1848
+ covered duration in hours to get received energy in Wh/m². `symbol` is categorical and therefore
1849
+ never appears in `statistics`.
1850
+
1851
+ Publishers need `WeatherHistoryRegister`; consumers need `WeatherHistoryUse`.
1852
+
1772
1853
  #### `usePvForecasting(): EnergyAppPvForecasting`
1773
1854
 
1774
1855
  Same shape as weather forecasting, but for PV production.
@@ -37,6 +37,8 @@ var EnergyAppPermissionTypeEnum;
37
37
  EnergyAppPermissionTypeEnum["EnergyPrices"] = "EnergyPrices";
38
38
  EnergyAppPermissionTypeEnum["WeatherForecastRegister"] = "WeatherForecastRegister";
39
39
  EnergyAppPermissionTypeEnum["WeatherForecastUse"] = "WeatherForecastUse";
40
+ EnergyAppPermissionTypeEnum["WeatherHistoryRegister"] = "WeatherHistoryRegister";
41
+ EnergyAppPermissionTypeEnum["WeatherHistoryUse"] = "WeatherHistoryUse";
40
42
  EnergyAppPermissionTypeEnum["PvForecastRegister"] = "PvForecastRegister";
41
43
  EnergyAppPermissionTypeEnum["PvForecastUse"] = "PvForecastUse";
42
44
  EnergyAppPermissionTypeEnum["DynamicPriceForecastRegister"] = "DynamicPriceForecastRegister";
@@ -33,6 +33,8 @@ export declare enum EnergyAppPermissionTypeEnum {
33
33
  EnergyPrices = "EnergyPrices",
34
34
  WeatherForecastRegister = "WeatherForecastRegister",
35
35
  WeatherForecastUse = "WeatherForecastUse",
36
+ WeatherHistoryRegister = "WeatherHistoryRegister",
37
+ WeatherHistoryUse = "WeatherHistoryUse",
36
38
  PvForecastRegister = "PvForecastRegister",
37
39
  PvForecastUse = "PvForecastUse",
38
40
  DynamicPriceForecastRegister = "DynamicPriceForecastRegister",
@@ -188,6 +188,15 @@ class EnergyApp {
188
188
  useWeatherForecasting() {
189
189
  return this.energyAppSdk.useWeatherForecasting();
190
190
  }
191
+ /**
192
+ * Gets the Weather History API for managing weather history providers and retrieving observed weather data.
193
+ * Provides methods to register/deregister weather history providers, list available providers,
194
+ * and fetch the outdoor temperature for a past time interval by zip code or coordinates.
195
+ * @returns The Weather History API instance
196
+ */
197
+ useWeatherHistory() {
198
+ return this.energyAppSdk.useWeatherHistory();
199
+ }
191
200
  /**
192
201
  * Gets the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts.
193
202
  * Provides methods to register/deregister PV forecast providers and fetch power production forecasts.
@@ -23,6 +23,7 @@ import { EnyoEnergyAppEnvironment } from "./enyo-energy-app-environment.cjs";
23
23
  import { EnergyAppEnergyManager } from "./packages/energy-app-energy-manager.cjs";
24
24
  import { EnergyAppElectricityTariff } from "./packages/energy-app-electricity-tariff.cjs";
25
25
  import { EnergyAppWeatherForecasting } from "./packages/energy-app-weather-forecasting.cjs";
26
+ import { EnergyAppWeatherHistory } from "./packages/energy-app-weather-history.cjs";
26
27
  import { EnergyAppPvForecasting } from "./packages/energy-app-pv-forecasting.cjs";
27
28
  import { EnergyAppDynamicPriceForecast } from "./packages/energy-app-dynamic-price-forecast.cjs";
28
29
  import { EnergyAppPvSystem } from "./packages/energy-app-pv-system.cjs";
@@ -161,6 +162,13 @@ export declare class EnergyApp implements EnyoEnergyAppSdk {
161
162
  * @returns The Weather Forecasting API instance
162
163
  */
163
164
  useWeatherForecasting(): EnergyAppWeatherForecasting;
165
+ /**
166
+ * Gets the Weather History API for managing weather history providers and retrieving observed weather data.
167
+ * Provides methods to register/deregister weather history providers, list available providers,
168
+ * and fetch the outdoor temperature for a past time interval by zip code or coordinates.
169
+ * @returns The Weather History API instance
170
+ */
171
+ useWeatherHistory(): EnergyAppWeatherHistory;
164
172
  /**
165
173
  * Gets the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts.
166
174
  * Provides methods to register/deregister PV forecast providers and fetch power production forecasts.
@@ -22,6 +22,7 @@ import { EnyoEnergyAppEnvironment } from "./enyo-energy-app-environment.cjs";
22
22
  import { EnergyAppEnergyManager } from "./packages/energy-app-energy-manager.cjs";
23
23
  import { EnergyAppElectricityTariff } from "./packages/energy-app-electricity-tariff.cjs";
24
24
  import { EnergyAppWeatherForecasting } from "./packages/energy-app-weather-forecasting.cjs";
25
+ import { EnergyAppWeatherHistory } from "./packages/energy-app-weather-history.cjs";
25
26
  import { EnergyAppPvForecasting } from "./packages/energy-app-pv-forecasting.cjs";
26
27
  import { EnergyAppDynamicPriceForecast } from "./packages/energy-app-dynamic-price-forecast.cjs";
27
28
  import { EnergyAppPvSystem } from "./packages/energy-app-pv-system.cjs";
@@ -126,6 +127,8 @@ export interface EnyoEnergyAppSdk {
126
127
  useElectricityTariff: () => EnergyAppElectricityTariff;
127
128
  /** Get the Weather Forecasting API for managing weather forecast providers and retrieving weather forecasts */
128
129
  useWeatherForecasting: () => EnergyAppWeatherForecasting;
130
+ /** Get the Weather History API for managing weather history providers and retrieving observed weather for a past interval */
131
+ useWeatherHistory: () => EnergyAppWeatherHistory;
129
132
  /** Get the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts */
130
133
  usePvForecasting: () => EnergyAppPvForecasting;
131
134
  /** Get the Dynamic Price Forecast API for publishing and consuming forward-looking electricity price forecasts */
@@ -49,6 +49,8 @@ __exportStar(require("./packages/energy-app-electricity-tariff.cjs"), exports);
49
49
  __exportStar(require("./types/enyo-pv-forecast.cjs"), exports);
50
50
  __exportStar(require("./types/enyo-forecasting.cjs"), exports);
51
51
  __exportStar(require("./packages/energy-app-weather-forecasting.cjs"), exports);
52
+ __exportStar(require("./types/enyo-weather-history.cjs"), exports);
53
+ __exportStar(require("./packages/energy-app-weather-history.cjs"), exports);
52
54
  __exportStar(require("./packages/energy-app-pv-forecasting.cjs"), exports);
53
55
  __exportStar(require("./packages/energy-app-dynamic-price-forecast.cjs"), exports);
54
56
  __exportStar(require("./types/enyo-pv-system.cjs"), exports);
@@ -33,6 +33,8 @@ export * from './packages/energy-app-electricity-tariff.cjs';
33
33
  export * from './types/enyo-pv-forecast.cjs';
34
34
  export * from './types/enyo-forecasting.cjs';
35
35
  export * from './packages/energy-app-weather-forecasting.cjs';
36
+ export * from './types/enyo-weather-history.cjs';
37
+ export * from './packages/energy-app-weather-history.cjs';
36
38
  export * from './packages/energy-app-pv-forecasting.cjs';
37
39
  export * from './packages/energy-app-dynamic-price-forecast.cjs';
38
40
  export * from './types/enyo-pv-system.cjs';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,138 @@
1
+ import { WeatherHistoryRegistration, WeatherHistoryInfo, OutdoorTemperatureHistoryRequest, OutdoorTemperatureHistory, WeatherHistoryRequest, WeatherHistory } from "../types/enyo-weather-history.cjs";
2
+ /**
3
+ * Interface for managing weather history providers and retrieving observed
4
+ * weather data for a past time interval.
5
+ *
6
+ * This is the backward-looking counterpart to `EnergyAppWeatherForecasting`:
7
+ * where the forecasting API answers "what will the weather do", this one
8
+ * answers "what was the weather between these two timestamps" — temperature,
9
+ * wind, cloud cover and solar irradiance. That is the input an app needs to
10
+ * correlate measured consumption with the weather that drove it, to build
11
+ * heating-degree-day statistics, to check measured PV production against the
12
+ * irradiance that was actually available, or to train a consumption model on
13
+ * outdoor conditions.
14
+ *
15
+ * Two queries are offered: {@link EnergyAppWeatherHistory.getWeatherHistory}
16
+ * returns every requested measure per bucket, while
17
+ * {@link EnergyAppWeatherHistory.getOutdoorTemperature} is the shorthand for
18
+ * the common temperature-only case. Neither takes a location — the registered
19
+ * provider resolves the device's own location via `energyApp.useLocation()`,
20
+ * so a consumer only ever states the interval it cares about.
21
+ *
22
+ * Like the forecasting API, data comes from registered providers; an app
23
+ * either registers one (wrapping an external archive) or consumes one that is
24
+ * already registered, or both.
25
+ */
26
+ export interface EnergyAppWeatherHistory {
27
+ /**
28
+ * Registers a new weather history provider or updates an existing one.
29
+ * Uses upsert logic based on historyId - if a provider with the same ID
30
+ * exists, it will be updated; otherwise, a new provider will be created.
31
+ *
32
+ * @param registration - The history provider registration data
33
+ * @returns Promise that resolves when the provider has been registered
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * await weatherHistory.registerHistory({
38
+ * historyId: 'dwd-archive',
39
+ * name: 'DWD Climate Archive',
40
+ * vendor: 'Deutscher Wetterdienst',
41
+ * availableHistoryDays: 730,
42
+ * availableMeasures: [WeatherHistoryMeasureEnum.OutdoorTemperature]
43
+ * });
44
+ * ```
45
+ */
46
+ registerHistory(registration: WeatherHistoryRegistration): Promise<void>;
47
+ /**
48
+ * Removes a registered weather history provider by its ID.
49
+ * If the provider does not exist, this operation is a no-op.
50
+ *
51
+ * @param historyId - The unique identifier of the history provider to remove
52
+ * @returns Promise that resolves when the provider has been removed
53
+ */
54
+ deregisterHistory(historyId: string): Promise<void>;
55
+ /**
56
+ * Retrieves all registered weather history providers.
57
+ *
58
+ * @returns Promise that resolves to an array of all registered weather history providers
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const providers = await weatherHistory.listHistories();
63
+ * providers.forEach(p => console.log(`${p.name} (${p.vendor})`));
64
+ * ```
65
+ */
66
+ listHistories(): Promise<WeatherHistoryInfo[]>;
67
+ /**
68
+ * Fetches the observed outdoor temperature for a time interval.
69
+ *
70
+ * The interval is half-open: `fromIso` is included and `untilIso` is not,
71
+ * so consecutive intervals can be requested back to back without the
72
+ * boundary timestamp being counted twice. Pass `resolution` to get a bucket
73
+ * size other than the provider's own — a finer resolution is filled by
74
+ * linear interpolation, a coarser one aggregated as a time-weighted
75
+ * average.
76
+ *
77
+ * An interval that reaches further back than the provider's archive, or
78
+ * forward past its most recent observation, is not an error: the covered
79
+ * part is returned and `coveredFromIso` / `coveredUntilIso` state where the
80
+ * data actually began and ended. An interval the provider holds no data for
81
+ * at all yields an empty `readings` array.
82
+ *
83
+ * @param historyId - The unique identifier of the history provider to use
84
+ * @param request - The requested interval and resolution
85
+ * @returns Promise that resolves to the observed temperatures for the interval
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const temperatures = await weatherHistory.getOutdoorTemperature('dwd-archive', {
90
+ * fromIso: '2026-01-15T00:00:00Z',
91
+ * untilIso: '2026-01-16T00:00:00Z',
92
+ * resolution: WeatherHistoryResolutionEnum.OneHour
93
+ * });
94
+ * console.log(`Average: ${temperatures.averageCelsius}°C`);
95
+ * temperatures.readings.forEach(r =>
96
+ * console.log(`${r.timestampIso}: ${r.outdoorTemperatureCelsius}°C`)
97
+ * );
98
+ * ```
99
+ */
100
+ getOutdoorTemperature(historyId: string, request: OutdoorTemperatureHistoryRequest): Promise<OutdoorTemperatureHistory>;
101
+ /**
102
+ * Fetches the observed weather for a time interval across every requested
103
+ * measure — temperature, wind speed, cloud cover and the three irradiance
104
+ * components.
105
+ *
106
+ * Interval, resolution and coverage behave exactly as described on
107
+ * {@link EnergyAppWeatherHistory.getOutdoorTemperature}. Narrow the result
108
+ * with `measures` when only some quantities are needed — archives are
109
+ * typically billed or rate-limited per quantity. Measures the provider does
110
+ * not hold are simply absent from the readings rather than reported as an
111
+ * error; `measures` on the result states what actually came back.
112
+ *
113
+ * @param historyId - The unique identifier of the history provider to use
114
+ * @param request - The requested interval, resolution and measures
115
+ * @returns Promise that resolves to the observed weather for the interval
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const history = await weatherHistory.getWeatherHistory('open-meteo-archive', {
120
+ * fromIso: '2026-01-15T00:00:00Z',
121
+ * untilIso: '2026-01-16T00:00:00Z',
122
+ * resolution: WeatherHistoryResolutionEnum.OneHour,
123
+ * measures: [
124
+ * WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance,
125
+ * WeatherHistoryMeasureEnum.WindSpeed,
126
+ * WeatherHistoryMeasureEnum.CloudArea
127
+ * ]
128
+ * });
129
+ *
130
+ * const ghi = history.statistics?.[WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance];
131
+ * console.log(`Mean irradiance: ${ghi?.averageValue} W/m²`);
132
+ * history.readings.forEach(r =>
133
+ * console.log(`${r.timestampIso}: ${r.globalHorizontalIrradiance} W/m², ${r.windSpeedMs} m/s`)
134
+ * );
135
+ * ```
136
+ */
137
+ getWeatherHistory(historyId: string, request: WeatherHistoryRequest): Promise<WeatherHistory>;
138
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WeatherHistoryMeasureEnum = exports.WeatherHistoryResolutionEnum = void 0;
4
+ /**
5
+ * Resolution of historical weather data entries.
6
+ *
7
+ * The values mirror {@link ForecastResolutionEnum} so a history series and a
8
+ * forecast series of the same resolution can be concatenated without
9
+ * translating between the two vocabularies.
10
+ */
11
+ var WeatherHistoryResolutionEnum;
12
+ (function (WeatherHistoryResolutionEnum) {
13
+ /** 1-minute intervals */
14
+ WeatherHistoryResolutionEnum["OneMinute"] = "1min";
15
+ /** 15-minute intervals */
16
+ WeatherHistoryResolutionEnum["FifteenMinutes"] = "15min";
17
+ /** 1-hour intervals */
18
+ WeatherHistoryResolutionEnum["OneHour"] = "1hr";
19
+ })(WeatherHistoryResolutionEnum || (exports.WeatherHistoryResolutionEnum = WeatherHistoryResolutionEnum = {}));
20
+ /**
21
+ * A weather quantity a history provider can serve.
22
+ *
23
+ * Used to narrow a request to the measures an app actually needs — archives
24
+ * are usually billed or rate-limited per quantity, so asking for irradiance
25
+ * when only wind is wanted is pure cost.
26
+ */
27
+ var WeatherHistoryMeasureEnum;
28
+ (function (WeatherHistoryMeasureEnum) {
29
+ /** Outdoor air temperature in degrees Celsius */
30
+ WeatherHistoryMeasureEnum["OutdoorTemperature"] = "outdoor-temperature";
31
+ /** Wind speed in meters per second */
32
+ WeatherHistoryMeasureEnum["WindSpeed"] = "wind-speed";
33
+ /** Cloud coverage area in percent */
34
+ WeatherHistoryMeasureEnum["CloudArea"] = "cloud-area";
35
+ /** Global horizontal irradiance in W/m² */
36
+ WeatherHistoryMeasureEnum["GlobalHorizontalIrradiance"] = "global-horizontal-irradiance";
37
+ /** Direct normal irradiance in W/m² */
38
+ WeatherHistoryMeasureEnum["DirectNormalIrradiance"] = "direct-normal-irradiance";
39
+ /** Diffuse horizontal irradiance in W/m² */
40
+ WeatherHistoryMeasureEnum["DiffuseHorizontalIrradiance"] = "diffuse-horizontal-irradiance";
41
+ /** Categorical weather symbol */
42
+ WeatherHistoryMeasureEnum["Symbol"] = "symbol";
43
+ })(WeatherHistoryMeasureEnum || (exports.WeatherHistoryMeasureEnum = WeatherHistoryMeasureEnum = {}));
@@ -0,0 +1,284 @@
1
+ import { EnyoWeatherSymbolEnum } from './enyo-forecasting.cjs';
2
+ /**
3
+ * Resolution of historical weather data entries.
4
+ *
5
+ * The values mirror {@link ForecastResolutionEnum} so a history series and a
6
+ * forecast series of the same resolution can be concatenated without
7
+ * translating between the two vocabularies.
8
+ */
9
+ export declare enum WeatherHistoryResolutionEnum {
10
+ /** 1-minute intervals */
11
+ OneMinute = "1min",
12
+ /** 15-minute intervals */
13
+ FifteenMinutes = "15min",
14
+ /** 1-hour intervals */
15
+ OneHour = "1hr"
16
+ }
17
+ /**
18
+ * Registration data for a weather history provider.
19
+ *
20
+ * A provider is not told which place to serve: it resolves the device's own
21
+ * location itself via `energyApp.useLocation()`, so nothing location-shaped
22
+ * travels through this API.
23
+ */
24
+ export interface WeatherHistoryRegistration {
25
+ /** Unique identifier for the weather history provider */
26
+ historyId: string;
27
+ /** Human-readable name of the history provider */
28
+ name: string;
29
+ /** Vendor or company providing the historical data */
30
+ vendor: string;
31
+ /**
32
+ * How far back the provider can serve data, in days. Informational — it
33
+ * lets a consumer size its request before issuing one that would only be
34
+ * partially covered.
35
+ */
36
+ availableHistoryDays?: number;
37
+ /**
38
+ * The measures this provider can serve. Informational — it lets a consumer
39
+ * pick a provider that holds the quantity it needs instead of discovering
40
+ * the gap from an empty result. When omitted, assume outdoor temperature
41
+ * only.
42
+ */
43
+ availableMeasures?: WeatherHistoryMeasureEnum[];
44
+ }
45
+ /**
46
+ * A registered weather history provider with metadata.
47
+ */
48
+ export interface WeatherHistoryInfo extends WeatherHistoryRegistration {
49
+ /** Timestamp when this history provider was registered in ISO format */
50
+ registeredAtIso: string;
51
+ }
52
+ /**
53
+ * Time interval and resolution shared by every weather history request.
54
+ *
55
+ * The interval is half-open — `fromIso` is included, `untilIso` is not — so
56
+ * consecutive intervals can be requested back to back without the boundary
57
+ * timestamp being counted twice.
58
+ */
59
+ export interface WeatherHistoryIntervalRequest {
60
+ /** Start of the requested interval in ISO format (inclusive) */
61
+ fromIso: string;
62
+ /** End of the requested interval in ISO format (exclusive) */
63
+ untilIso: string;
64
+ /**
65
+ * Desired resolution of the returned readings. When omitted, the
66
+ * provider's own resolution is used. A resolution finer than the
67
+ * provider's is filled by linear interpolation; a coarser one is
68
+ * aggregated as a time-weighted average.
69
+ */
70
+ resolution?: WeatherHistoryResolutionEnum;
71
+ }
72
+ /**
73
+ * Request parameters for fetching historical outdoor temperatures for a time
74
+ * interval — the interval and resolution, nothing else.
75
+ */
76
+ export type OutdoorTemperatureHistoryRequest = WeatherHistoryIntervalRequest;
77
+ /**
78
+ * A single observed outdoor temperature at a point in time.
79
+ */
80
+ export interface OutdoorTemperatureReading {
81
+ /** Start of the bucket this reading applies to, in ISO format */
82
+ timestampIso: string;
83
+ /** Observed outdoor temperature in degrees Celsius */
84
+ outdoorTemperatureCelsius: number;
85
+ }
86
+ /**
87
+ * Observed outdoor temperatures covering a requested time interval.
88
+ *
89
+ * `fromIso`, `untilIso` and `resolution` echo what was asked for, while
90
+ * {@link OutdoorTemperatureHistory.coveredFromIso} and
91
+ * {@link OutdoorTemperatureHistory.coveredUntilIso} state what the provider
92
+ * could actually deliver — these differ whenever the requested interval
93
+ * reaches further back than the provider's archive, or into the future.
94
+ */
95
+ export interface OutdoorTemperatureHistory {
96
+ /** Start of the requested interval in ISO format (inclusive) */
97
+ fromIso: string;
98
+ /** End of the requested interval in ISO format (exclusive) */
99
+ untilIso: string;
100
+ /** The resolution of the returned readings */
101
+ resolution: WeatherHistoryResolutionEnum;
102
+ /**
103
+ * Readings ordered by timestamp, one per bucket of
104
+ * {@link OutdoorTemperatureHistory.resolution}. Empty when the provider
105
+ * holds no data for the requested interval — this is a normal result, not
106
+ * an error.
107
+ */
108
+ readings: OutdoorTemperatureReading[];
109
+ /**
110
+ * Time-weighted mean temperature over the covered part of the interval, in
111
+ * degrees Celsius. Absent when {@link OutdoorTemperatureHistory.readings}
112
+ * is empty.
113
+ */
114
+ averageCelsius?: number;
115
+ /**
116
+ * Lowest temperature in degrees Celsius over the covered part of the
117
+ * interval. Absent when {@link OutdoorTemperatureHistory.readings} is
118
+ * empty.
119
+ */
120
+ minCelsius?: number;
121
+ /**
122
+ * Highest temperature in degrees Celsius over the covered part of the
123
+ * interval. Absent when {@link OutdoorTemperatureHistory.readings} is
124
+ * empty.
125
+ */
126
+ maxCelsius?: number;
127
+ /**
128
+ * Start of the part of the interval the provider could cover, in ISO
129
+ * format. Later than {@link OutdoorTemperatureHistory.fromIso} when the
130
+ * request reached further back than the archive goes. Absent when
131
+ * {@link OutdoorTemperatureHistory.readings} is empty.
132
+ */
133
+ coveredFromIso?: string;
134
+ /**
135
+ * End of the part of the interval the provider could cover, in ISO format.
136
+ * Earlier than {@link OutdoorTemperatureHistory.untilIso} when the request
137
+ * reached into the future or past the most recent observation. Absent when
138
+ * {@link OutdoorTemperatureHistory.readings} is empty.
139
+ */
140
+ coveredUntilIso?: string;
141
+ }
142
+ /**
143
+ * A weather quantity a history provider can serve.
144
+ *
145
+ * Used to narrow a request to the measures an app actually needs — archives
146
+ * are usually billed or rate-limited per quantity, so asking for irradiance
147
+ * when only wind is wanted is pure cost.
148
+ */
149
+ export declare enum WeatherHistoryMeasureEnum {
150
+ /** Outdoor air temperature in degrees Celsius */
151
+ OutdoorTemperature = "outdoor-temperature",
152
+ /** Wind speed in meters per second */
153
+ WindSpeed = "wind-speed",
154
+ /** Cloud coverage area in percent */
155
+ CloudArea = "cloud-area",
156
+ /** Global horizontal irradiance in W/m² */
157
+ GlobalHorizontalIrradiance = "global-horizontal-irradiance",
158
+ /** Direct normal irradiance in W/m² */
159
+ DirectNormalIrradiance = "direct-normal-irradiance",
160
+ /** Diffuse horizontal irradiance in W/m² */
161
+ DiffuseHorizontalIrradiance = "diffuse-horizontal-irradiance",
162
+ /** Categorical weather symbol */
163
+ Symbol = "symbol"
164
+ }
165
+ /**
166
+ * A single observed weather data point.
167
+ *
168
+ * Every measure is optional: a reading only carries the quantities the
169
+ * provider holds and the request asked for. The field names and units mirror
170
+ * `WeatherForecastEntry` exactly, so an observed series and a forecast series
171
+ * can be concatenated into one timeline without translating between them.
172
+ */
173
+ export interface WeatherHistoryReading {
174
+ /** Start of the bucket this reading applies to, in ISO format */
175
+ timestampIso: string;
176
+ /** Observed outdoor temperature in degrees Celsius */
177
+ outdoorTemperatureCelsius?: number;
178
+ /** Observed wind speed in meters per second */
179
+ windSpeedMs?: number;
180
+ /** Observed cloud coverage area as a percentage (0-100) */
181
+ cloudAreaPercent?: number;
182
+ /** Weather symbol describing the observed condition */
183
+ symbol?: EnyoWeatherSymbolEnum;
184
+ /**
185
+ * Global horizontal irradiance in W/m².
186
+ *
187
+ * Total shortwave radiation received by a horizontal surface — the sum of
188
+ * the diffuse part and the horizontal projection of the direct part
189
+ * (`GHI = DHI + DNI * cos(zenith)`). This is the quantity to correlate
190
+ * with measured PV production.
191
+ */
192
+ globalHorizontalIrradiance?: number;
193
+ /**
194
+ * Direct normal irradiance (DNI) in W/m².
195
+ *
196
+ * Beam radiation arriving from the direction of the sun, measured on a
197
+ * surface held perpendicular to the sun's rays. Together with
198
+ * {@link WeatherHistoryReading.diffuseHorizontalIrradiance} it allows
199
+ * transposing the observation onto an arbitrarily tilted plane (plane of
200
+ * array), which a single GHI value cannot do.
201
+ */
202
+ directNormalIrradiance?: number;
203
+ /**
204
+ * Diffuse horizontal irradiance (DHI) in W/m².
205
+ *
206
+ * The part of the radiation on a horizontal surface that has been
207
+ * scattered by the atmosphere and clouds, i.e. everything that did not
208
+ * arrive directly from the sun's disc. See
209
+ * {@link WeatherHistoryReading.directNormalIrradiance}.
210
+ */
211
+ diffuseHorizontalIrradiance?: number;
212
+ }
213
+ /**
214
+ * Aggregates of one numeric measure over the covered part of an interval.
215
+ */
216
+ export interface WeatherHistoryStatistics {
217
+ /**
218
+ * Time-weighted mean of the measure over the covered interval, in the
219
+ * measure's own unit.
220
+ *
221
+ * For the irradiance measures this is a mean power density in W/m²;
222
+ * multiply by the covered duration in hours to get the received energy in
223
+ * Wh/m².
224
+ */
225
+ averageValue: number;
226
+ /** Lowest observed value of the measure, in the measure's own unit */
227
+ minValue: number;
228
+ /** Highest observed value of the measure, in the measure's own unit */
229
+ maxValue: number;
230
+ }
231
+ /**
232
+ * Request parameters for fetching observed weather for a time interval.
233
+ */
234
+ export interface WeatherHistoryRequest extends WeatherHistoryIntervalRequest {
235
+ /**
236
+ * The measures to return. When omitted, the provider returns everything it
237
+ * holds for the interval.
238
+ */
239
+ measures?: WeatherHistoryMeasureEnum[];
240
+ }
241
+ /**
242
+ * Observed weather covering a requested time interval, across every requested
243
+ * measure.
244
+ *
245
+ * This is the general-purpose counterpart to {@link OutdoorTemperatureHistory}:
246
+ * same interval and coverage semantics, but each reading carries the full set
247
+ * of requested quantities instead of temperature alone.
248
+ */
249
+ export interface WeatherHistory {
250
+ /** Start of the requested interval in ISO format (inclusive) */
251
+ fromIso: string;
252
+ /** End of the requested interval in ISO format (exclusive) */
253
+ untilIso: string;
254
+ /** The resolution of the returned readings */
255
+ resolution: WeatherHistoryResolutionEnum;
256
+ /** The measures actually contained in the readings */
257
+ measures: WeatherHistoryMeasureEnum[];
258
+ /**
259
+ * Readings ordered by timestamp, one per bucket of
260
+ * {@link WeatherHistory.resolution}. Empty when the provider holds no data
261
+ * for the requested interval — this is a normal result, not an error.
262
+ */
263
+ readings: WeatherHistoryReading[];
264
+ /**
265
+ * Aggregates per numeric measure over the covered part of the interval.
266
+ * {@link WeatherHistoryMeasureEnum.Symbol} is categorical and therefore
267
+ * never present here. Absent when {@link WeatherHistory.readings} is empty.
268
+ */
269
+ statistics?: Partial<Record<WeatherHistoryMeasureEnum, WeatherHistoryStatistics>>;
270
+ /**
271
+ * Start of the part of the interval the provider could cover, in ISO
272
+ * format. Later than {@link WeatherHistory.fromIso} when the request
273
+ * reached further back than the archive goes. Absent when
274
+ * {@link WeatherHistory.readings} is empty.
275
+ */
276
+ coveredFromIso?: string;
277
+ /**
278
+ * End of the part of the interval the provider could cover, in ISO format.
279
+ * Earlier than {@link WeatherHistory.untilIso} when the request reached
280
+ * into the future or past the most recent observation. Absent when
281
+ * {@link WeatherHistory.readings} is empty.
282
+ */
283
+ coveredUntilIso?: string;
284
+ }
@@ -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.20.0';
12
+ exports.SDK_VERSION = '1.21.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.20.0";
8
+ export declare const SDK_VERSION = "1.21.0";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -33,6 +33,8 @@ export declare enum EnergyAppPermissionTypeEnum {
33
33
  EnergyPrices = "EnergyPrices",
34
34
  WeatherForecastRegister = "WeatherForecastRegister",
35
35
  WeatherForecastUse = "WeatherForecastUse",
36
+ WeatherHistoryRegister = "WeatherHistoryRegister",
37
+ WeatherHistoryUse = "WeatherHistoryUse",
36
38
  PvForecastRegister = "PvForecastRegister",
37
39
  PvForecastUse = "PvForecastUse",
38
40
  DynamicPriceForecastRegister = "DynamicPriceForecastRegister",
@@ -34,6 +34,8 @@ export var EnergyAppPermissionTypeEnum;
34
34
  EnergyAppPermissionTypeEnum["EnergyPrices"] = "EnergyPrices";
35
35
  EnergyAppPermissionTypeEnum["WeatherForecastRegister"] = "WeatherForecastRegister";
36
36
  EnergyAppPermissionTypeEnum["WeatherForecastUse"] = "WeatherForecastUse";
37
+ EnergyAppPermissionTypeEnum["WeatherHistoryRegister"] = "WeatherHistoryRegister";
38
+ EnergyAppPermissionTypeEnum["WeatherHistoryUse"] = "WeatherHistoryUse";
37
39
  EnergyAppPermissionTypeEnum["PvForecastRegister"] = "PvForecastRegister";
38
40
  EnergyAppPermissionTypeEnum["PvForecastUse"] = "PvForecastUse";
39
41
  EnergyAppPermissionTypeEnum["DynamicPriceForecastRegister"] = "DynamicPriceForecastRegister";
@@ -23,6 +23,7 @@ import { EnyoEnergyAppEnvironment } from "./enyo-energy-app-environment.js";
23
23
  import { EnergyAppEnergyManager } from "./packages/energy-app-energy-manager.js";
24
24
  import { EnergyAppElectricityTariff } from "./packages/energy-app-electricity-tariff.js";
25
25
  import { EnergyAppWeatherForecasting } from "./packages/energy-app-weather-forecasting.js";
26
+ import { EnergyAppWeatherHistory } from "./packages/energy-app-weather-history.js";
26
27
  import { EnergyAppPvForecasting } from "./packages/energy-app-pv-forecasting.js";
27
28
  import { EnergyAppDynamicPriceForecast } from "./packages/energy-app-dynamic-price-forecast.js";
28
29
  import { EnergyAppPvSystem } from "./packages/energy-app-pv-system.js";
@@ -161,6 +162,13 @@ export declare class EnergyApp implements EnyoEnergyAppSdk {
161
162
  * @returns The Weather Forecasting API instance
162
163
  */
163
164
  useWeatherForecasting(): EnergyAppWeatherForecasting;
165
+ /**
166
+ * Gets the Weather History API for managing weather history providers and retrieving observed weather data.
167
+ * Provides methods to register/deregister weather history providers, list available providers,
168
+ * and fetch the outdoor temperature for a past time interval by zip code or coordinates.
169
+ * @returns The Weather History API instance
170
+ */
171
+ useWeatherHistory(): EnergyAppWeatherHistory;
164
172
  /**
165
173
  * Gets the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts.
166
174
  * Provides methods to register/deregister PV forecast providers and fetch power production forecasts.
@@ -185,6 +185,15 @@ export class EnergyApp {
185
185
  useWeatherForecasting() {
186
186
  return this.energyAppSdk.useWeatherForecasting();
187
187
  }
188
+ /**
189
+ * Gets the Weather History API for managing weather history providers and retrieving observed weather data.
190
+ * Provides methods to register/deregister weather history providers, list available providers,
191
+ * and fetch the outdoor temperature for a past time interval by zip code or coordinates.
192
+ * @returns The Weather History API instance
193
+ */
194
+ useWeatherHistory() {
195
+ return this.energyAppSdk.useWeatherHistory();
196
+ }
188
197
  /**
189
198
  * Gets the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts.
190
199
  * Provides methods to register/deregister PV forecast providers and fetch power production forecasts.
@@ -22,6 +22,7 @@ import { EnyoEnergyAppEnvironment } from "./enyo-energy-app-environment.js";
22
22
  import { EnergyAppEnergyManager } from "./packages/energy-app-energy-manager.js";
23
23
  import { EnergyAppElectricityTariff } from "./packages/energy-app-electricity-tariff.js";
24
24
  import { EnergyAppWeatherForecasting } from "./packages/energy-app-weather-forecasting.js";
25
+ import { EnergyAppWeatherHistory } from "./packages/energy-app-weather-history.js";
25
26
  import { EnergyAppPvForecasting } from "./packages/energy-app-pv-forecasting.js";
26
27
  import { EnergyAppDynamicPriceForecast } from "./packages/energy-app-dynamic-price-forecast.js";
27
28
  import { EnergyAppPvSystem } from "./packages/energy-app-pv-system.js";
@@ -126,6 +127,8 @@ export interface EnyoEnergyAppSdk {
126
127
  useElectricityTariff: () => EnergyAppElectricityTariff;
127
128
  /** Get the Weather Forecasting API for managing weather forecast providers and retrieving weather forecasts */
128
129
  useWeatherForecasting: () => EnergyAppWeatherForecasting;
130
+ /** Get the Weather History API for managing weather history providers and retrieving observed weather for a past interval */
131
+ useWeatherHistory: () => EnergyAppWeatherHistory;
129
132
  /** Get the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts */
130
133
  usePvForecasting: () => EnergyAppPvForecasting;
131
134
  /** Get the Dynamic Price Forecast API for publishing and consuming forward-looking electricity price forecasts */
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export * from './packages/energy-app-electricity-tariff.js';
33
33
  export * from './types/enyo-pv-forecast.js';
34
34
  export * from './types/enyo-forecasting.js';
35
35
  export * from './packages/energy-app-weather-forecasting.js';
36
+ export * from './types/enyo-weather-history.js';
37
+ export * from './packages/energy-app-weather-history.js';
36
38
  export * from './packages/energy-app-pv-forecasting.js';
37
39
  export * from './packages/energy-app-dynamic-price-forecast.js';
38
40
  export * from './types/enyo-pv-system.js';
package/dist/index.js CHANGED
@@ -33,6 +33,8 @@ export * from './packages/energy-app-electricity-tariff.js';
33
33
  export * from './types/enyo-pv-forecast.js';
34
34
  export * from './types/enyo-forecasting.js';
35
35
  export * from './packages/energy-app-weather-forecasting.js';
36
+ export * from './types/enyo-weather-history.js';
37
+ export * from './packages/energy-app-weather-history.js';
36
38
  export * from './packages/energy-app-pv-forecasting.js';
37
39
  export * from './packages/energy-app-dynamic-price-forecast.js';
38
40
  export * from './types/enyo-pv-system.js';
@@ -0,0 +1,138 @@
1
+ import { WeatherHistoryRegistration, WeatherHistoryInfo, OutdoorTemperatureHistoryRequest, OutdoorTemperatureHistory, WeatherHistoryRequest, WeatherHistory } from "../types/enyo-weather-history.js";
2
+ /**
3
+ * Interface for managing weather history providers and retrieving observed
4
+ * weather data for a past time interval.
5
+ *
6
+ * This is the backward-looking counterpart to `EnergyAppWeatherForecasting`:
7
+ * where the forecasting API answers "what will the weather do", this one
8
+ * answers "what was the weather between these two timestamps" — temperature,
9
+ * wind, cloud cover and solar irradiance. That is the input an app needs to
10
+ * correlate measured consumption with the weather that drove it, to build
11
+ * heating-degree-day statistics, to check measured PV production against the
12
+ * irradiance that was actually available, or to train a consumption model on
13
+ * outdoor conditions.
14
+ *
15
+ * Two queries are offered: {@link EnergyAppWeatherHistory.getWeatherHistory}
16
+ * returns every requested measure per bucket, while
17
+ * {@link EnergyAppWeatherHistory.getOutdoorTemperature} is the shorthand for
18
+ * the common temperature-only case. Neither takes a location — the registered
19
+ * provider resolves the device's own location via `energyApp.useLocation()`,
20
+ * so a consumer only ever states the interval it cares about.
21
+ *
22
+ * Like the forecasting API, data comes from registered providers; an app
23
+ * either registers one (wrapping an external archive) or consumes one that is
24
+ * already registered, or both.
25
+ */
26
+ export interface EnergyAppWeatherHistory {
27
+ /**
28
+ * Registers a new weather history provider or updates an existing one.
29
+ * Uses upsert logic based on historyId - if a provider with the same ID
30
+ * exists, it will be updated; otherwise, a new provider will be created.
31
+ *
32
+ * @param registration - The history provider registration data
33
+ * @returns Promise that resolves when the provider has been registered
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * await weatherHistory.registerHistory({
38
+ * historyId: 'dwd-archive',
39
+ * name: 'DWD Climate Archive',
40
+ * vendor: 'Deutscher Wetterdienst',
41
+ * availableHistoryDays: 730,
42
+ * availableMeasures: [WeatherHistoryMeasureEnum.OutdoorTemperature]
43
+ * });
44
+ * ```
45
+ */
46
+ registerHistory(registration: WeatherHistoryRegistration): Promise<void>;
47
+ /**
48
+ * Removes a registered weather history provider by its ID.
49
+ * If the provider does not exist, this operation is a no-op.
50
+ *
51
+ * @param historyId - The unique identifier of the history provider to remove
52
+ * @returns Promise that resolves when the provider has been removed
53
+ */
54
+ deregisterHistory(historyId: string): Promise<void>;
55
+ /**
56
+ * Retrieves all registered weather history providers.
57
+ *
58
+ * @returns Promise that resolves to an array of all registered weather history providers
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const providers = await weatherHistory.listHistories();
63
+ * providers.forEach(p => console.log(`${p.name} (${p.vendor})`));
64
+ * ```
65
+ */
66
+ listHistories(): Promise<WeatherHistoryInfo[]>;
67
+ /**
68
+ * Fetches the observed outdoor temperature for a time interval.
69
+ *
70
+ * The interval is half-open: `fromIso` is included and `untilIso` is not,
71
+ * so consecutive intervals can be requested back to back without the
72
+ * boundary timestamp being counted twice. Pass `resolution` to get a bucket
73
+ * size other than the provider's own — a finer resolution is filled by
74
+ * linear interpolation, a coarser one aggregated as a time-weighted
75
+ * average.
76
+ *
77
+ * An interval that reaches further back than the provider's archive, or
78
+ * forward past its most recent observation, is not an error: the covered
79
+ * part is returned and `coveredFromIso` / `coveredUntilIso` state where the
80
+ * data actually began and ended. An interval the provider holds no data for
81
+ * at all yields an empty `readings` array.
82
+ *
83
+ * @param historyId - The unique identifier of the history provider to use
84
+ * @param request - The requested interval and resolution
85
+ * @returns Promise that resolves to the observed temperatures for the interval
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const temperatures = await weatherHistory.getOutdoorTemperature('dwd-archive', {
90
+ * fromIso: '2026-01-15T00:00:00Z',
91
+ * untilIso: '2026-01-16T00:00:00Z',
92
+ * resolution: WeatherHistoryResolutionEnum.OneHour
93
+ * });
94
+ * console.log(`Average: ${temperatures.averageCelsius}°C`);
95
+ * temperatures.readings.forEach(r =>
96
+ * console.log(`${r.timestampIso}: ${r.outdoorTemperatureCelsius}°C`)
97
+ * );
98
+ * ```
99
+ */
100
+ getOutdoorTemperature(historyId: string, request: OutdoorTemperatureHistoryRequest): Promise<OutdoorTemperatureHistory>;
101
+ /**
102
+ * Fetches the observed weather for a time interval across every requested
103
+ * measure — temperature, wind speed, cloud cover and the three irradiance
104
+ * components.
105
+ *
106
+ * Interval, resolution and coverage behave exactly as described on
107
+ * {@link EnergyAppWeatherHistory.getOutdoorTemperature}. Narrow the result
108
+ * with `measures` when only some quantities are needed — archives are
109
+ * typically billed or rate-limited per quantity. Measures the provider does
110
+ * not hold are simply absent from the readings rather than reported as an
111
+ * error; `measures` on the result states what actually came back.
112
+ *
113
+ * @param historyId - The unique identifier of the history provider to use
114
+ * @param request - The requested interval, resolution and measures
115
+ * @returns Promise that resolves to the observed weather for the interval
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const history = await weatherHistory.getWeatherHistory('open-meteo-archive', {
120
+ * fromIso: '2026-01-15T00:00:00Z',
121
+ * untilIso: '2026-01-16T00:00:00Z',
122
+ * resolution: WeatherHistoryResolutionEnum.OneHour,
123
+ * measures: [
124
+ * WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance,
125
+ * WeatherHistoryMeasureEnum.WindSpeed,
126
+ * WeatherHistoryMeasureEnum.CloudArea
127
+ * ]
128
+ * });
129
+ *
130
+ * const ghi = history.statistics?.[WeatherHistoryMeasureEnum.GlobalHorizontalIrradiance];
131
+ * console.log(`Mean irradiance: ${ghi?.averageValue} W/m²`);
132
+ * history.readings.forEach(r =>
133
+ * console.log(`${r.timestampIso}: ${r.globalHorizontalIrradiance} W/m², ${r.windSpeedMs} m/s`)
134
+ * );
135
+ * ```
136
+ */
137
+ getWeatherHistory(historyId: string, request: WeatherHistoryRequest): Promise<WeatherHistory>;
138
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,284 @@
1
+ import { EnyoWeatherSymbolEnum } from './enyo-forecasting.js';
2
+ /**
3
+ * Resolution of historical weather data entries.
4
+ *
5
+ * The values mirror {@link ForecastResolutionEnum} so a history series and a
6
+ * forecast series of the same resolution can be concatenated without
7
+ * translating between the two vocabularies.
8
+ */
9
+ export declare enum WeatherHistoryResolutionEnum {
10
+ /** 1-minute intervals */
11
+ OneMinute = "1min",
12
+ /** 15-minute intervals */
13
+ FifteenMinutes = "15min",
14
+ /** 1-hour intervals */
15
+ OneHour = "1hr"
16
+ }
17
+ /**
18
+ * Registration data for a weather history provider.
19
+ *
20
+ * A provider is not told which place to serve: it resolves the device's own
21
+ * location itself via `energyApp.useLocation()`, so nothing location-shaped
22
+ * travels through this API.
23
+ */
24
+ export interface WeatherHistoryRegistration {
25
+ /** Unique identifier for the weather history provider */
26
+ historyId: string;
27
+ /** Human-readable name of the history provider */
28
+ name: string;
29
+ /** Vendor or company providing the historical data */
30
+ vendor: string;
31
+ /**
32
+ * How far back the provider can serve data, in days. Informational — it
33
+ * lets a consumer size its request before issuing one that would only be
34
+ * partially covered.
35
+ */
36
+ availableHistoryDays?: number;
37
+ /**
38
+ * The measures this provider can serve. Informational — it lets a consumer
39
+ * pick a provider that holds the quantity it needs instead of discovering
40
+ * the gap from an empty result. When omitted, assume outdoor temperature
41
+ * only.
42
+ */
43
+ availableMeasures?: WeatherHistoryMeasureEnum[];
44
+ }
45
+ /**
46
+ * A registered weather history provider with metadata.
47
+ */
48
+ export interface WeatherHistoryInfo extends WeatherHistoryRegistration {
49
+ /** Timestamp when this history provider was registered in ISO format */
50
+ registeredAtIso: string;
51
+ }
52
+ /**
53
+ * Time interval and resolution shared by every weather history request.
54
+ *
55
+ * The interval is half-open — `fromIso` is included, `untilIso` is not — so
56
+ * consecutive intervals can be requested back to back without the boundary
57
+ * timestamp being counted twice.
58
+ */
59
+ export interface WeatherHistoryIntervalRequest {
60
+ /** Start of the requested interval in ISO format (inclusive) */
61
+ fromIso: string;
62
+ /** End of the requested interval in ISO format (exclusive) */
63
+ untilIso: string;
64
+ /**
65
+ * Desired resolution of the returned readings. When omitted, the
66
+ * provider's own resolution is used. A resolution finer than the
67
+ * provider's is filled by linear interpolation; a coarser one is
68
+ * aggregated as a time-weighted average.
69
+ */
70
+ resolution?: WeatherHistoryResolutionEnum;
71
+ }
72
+ /**
73
+ * Request parameters for fetching historical outdoor temperatures for a time
74
+ * interval — the interval and resolution, nothing else.
75
+ */
76
+ export type OutdoorTemperatureHistoryRequest = WeatherHistoryIntervalRequest;
77
+ /**
78
+ * A single observed outdoor temperature at a point in time.
79
+ */
80
+ export interface OutdoorTemperatureReading {
81
+ /** Start of the bucket this reading applies to, in ISO format */
82
+ timestampIso: string;
83
+ /** Observed outdoor temperature in degrees Celsius */
84
+ outdoorTemperatureCelsius: number;
85
+ }
86
+ /**
87
+ * Observed outdoor temperatures covering a requested time interval.
88
+ *
89
+ * `fromIso`, `untilIso` and `resolution` echo what was asked for, while
90
+ * {@link OutdoorTemperatureHistory.coveredFromIso} and
91
+ * {@link OutdoorTemperatureHistory.coveredUntilIso} state what the provider
92
+ * could actually deliver — these differ whenever the requested interval
93
+ * reaches further back than the provider's archive, or into the future.
94
+ */
95
+ export interface OutdoorTemperatureHistory {
96
+ /** Start of the requested interval in ISO format (inclusive) */
97
+ fromIso: string;
98
+ /** End of the requested interval in ISO format (exclusive) */
99
+ untilIso: string;
100
+ /** The resolution of the returned readings */
101
+ resolution: WeatherHistoryResolutionEnum;
102
+ /**
103
+ * Readings ordered by timestamp, one per bucket of
104
+ * {@link OutdoorTemperatureHistory.resolution}. Empty when the provider
105
+ * holds no data for the requested interval — this is a normal result, not
106
+ * an error.
107
+ */
108
+ readings: OutdoorTemperatureReading[];
109
+ /**
110
+ * Time-weighted mean temperature over the covered part of the interval, in
111
+ * degrees Celsius. Absent when {@link OutdoorTemperatureHistory.readings}
112
+ * is empty.
113
+ */
114
+ averageCelsius?: number;
115
+ /**
116
+ * Lowest temperature in degrees Celsius over the covered part of the
117
+ * interval. Absent when {@link OutdoorTemperatureHistory.readings} is
118
+ * empty.
119
+ */
120
+ minCelsius?: number;
121
+ /**
122
+ * Highest temperature in degrees Celsius over the covered part of the
123
+ * interval. Absent when {@link OutdoorTemperatureHistory.readings} is
124
+ * empty.
125
+ */
126
+ maxCelsius?: number;
127
+ /**
128
+ * Start of the part of the interval the provider could cover, in ISO
129
+ * format. Later than {@link OutdoorTemperatureHistory.fromIso} when the
130
+ * request reached further back than the archive goes. Absent when
131
+ * {@link OutdoorTemperatureHistory.readings} is empty.
132
+ */
133
+ coveredFromIso?: string;
134
+ /**
135
+ * End of the part of the interval the provider could cover, in ISO format.
136
+ * Earlier than {@link OutdoorTemperatureHistory.untilIso} when the request
137
+ * reached into the future or past the most recent observation. Absent when
138
+ * {@link OutdoorTemperatureHistory.readings} is empty.
139
+ */
140
+ coveredUntilIso?: string;
141
+ }
142
+ /**
143
+ * A weather quantity a history provider can serve.
144
+ *
145
+ * Used to narrow a request to the measures an app actually needs — archives
146
+ * are usually billed or rate-limited per quantity, so asking for irradiance
147
+ * when only wind is wanted is pure cost.
148
+ */
149
+ export declare enum WeatherHistoryMeasureEnum {
150
+ /** Outdoor air temperature in degrees Celsius */
151
+ OutdoorTemperature = "outdoor-temperature",
152
+ /** Wind speed in meters per second */
153
+ WindSpeed = "wind-speed",
154
+ /** Cloud coverage area in percent */
155
+ CloudArea = "cloud-area",
156
+ /** Global horizontal irradiance in W/m² */
157
+ GlobalHorizontalIrradiance = "global-horizontal-irradiance",
158
+ /** Direct normal irradiance in W/m² */
159
+ DirectNormalIrradiance = "direct-normal-irradiance",
160
+ /** Diffuse horizontal irradiance in W/m² */
161
+ DiffuseHorizontalIrradiance = "diffuse-horizontal-irradiance",
162
+ /** Categorical weather symbol */
163
+ Symbol = "symbol"
164
+ }
165
+ /**
166
+ * A single observed weather data point.
167
+ *
168
+ * Every measure is optional: a reading only carries the quantities the
169
+ * provider holds and the request asked for. The field names and units mirror
170
+ * `WeatherForecastEntry` exactly, so an observed series and a forecast series
171
+ * can be concatenated into one timeline without translating between them.
172
+ */
173
+ export interface WeatherHistoryReading {
174
+ /** Start of the bucket this reading applies to, in ISO format */
175
+ timestampIso: string;
176
+ /** Observed outdoor temperature in degrees Celsius */
177
+ outdoorTemperatureCelsius?: number;
178
+ /** Observed wind speed in meters per second */
179
+ windSpeedMs?: number;
180
+ /** Observed cloud coverage area as a percentage (0-100) */
181
+ cloudAreaPercent?: number;
182
+ /** Weather symbol describing the observed condition */
183
+ symbol?: EnyoWeatherSymbolEnum;
184
+ /**
185
+ * Global horizontal irradiance in W/m².
186
+ *
187
+ * Total shortwave radiation received by a horizontal surface — the sum of
188
+ * the diffuse part and the horizontal projection of the direct part
189
+ * (`GHI = DHI + DNI * cos(zenith)`). This is the quantity to correlate
190
+ * with measured PV production.
191
+ */
192
+ globalHorizontalIrradiance?: number;
193
+ /**
194
+ * Direct normal irradiance (DNI) in W/m².
195
+ *
196
+ * Beam radiation arriving from the direction of the sun, measured on a
197
+ * surface held perpendicular to the sun's rays. Together with
198
+ * {@link WeatherHistoryReading.diffuseHorizontalIrradiance} it allows
199
+ * transposing the observation onto an arbitrarily tilted plane (plane of
200
+ * array), which a single GHI value cannot do.
201
+ */
202
+ directNormalIrradiance?: number;
203
+ /**
204
+ * Diffuse horizontal irradiance (DHI) in W/m².
205
+ *
206
+ * The part of the radiation on a horizontal surface that has been
207
+ * scattered by the atmosphere and clouds, i.e. everything that did not
208
+ * arrive directly from the sun's disc. See
209
+ * {@link WeatherHistoryReading.directNormalIrradiance}.
210
+ */
211
+ diffuseHorizontalIrradiance?: number;
212
+ }
213
+ /**
214
+ * Aggregates of one numeric measure over the covered part of an interval.
215
+ */
216
+ export interface WeatherHistoryStatistics {
217
+ /**
218
+ * Time-weighted mean of the measure over the covered interval, in the
219
+ * measure's own unit.
220
+ *
221
+ * For the irradiance measures this is a mean power density in W/m²;
222
+ * multiply by the covered duration in hours to get the received energy in
223
+ * Wh/m².
224
+ */
225
+ averageValue: number;
226
+ /** Lowest observed value of the measure, in the measure's own unit */
227
+ minValue: number;
228
+ /** Highest observed value of the measure, in the measure's own unit */
229
+ maxValue: number;
230
+ }
231
+ /**
232
+ * Request parameters for fetching observed weather for a time interval.
233
+ */
234
+ export interface WeatherHistoryRequest extends WeatherHistoryIntervalRequest {
235
+ /**
236
+ * The measures to return. When omitted, the provider returns everything it
237
+ * holds for the interval.
238
+ */
239
+ measures?: WeatherHistoryMeasureEnum[];
240
+ }
241
+ /**
242
+ * Observed weather covering a requested time interval, across every requested
243
+ * measure.
244
+ *
245
+ * This is the general-purpose counterpart to {@link OutdoorTemperatureHistory}:
246
+ * same interval and coverage semantics, but each reading carries the full set
247
+ * of requested quantities instead of temperature alone.
248
+ */
249
+ export interface WeatherHistory {
250
+ /** Start of the requested interval in ISO format (inclusive) */
251
+ fromIso: string;
252
+ /** End of the requested interval in ISO format (exclusive) */
253
+ untilIso: string;
254
+ /** The resolution of the returned readings */
255
+ resolution: WeatherHistoryResolutionEnum;
256
+ /** The measures actually contained in the readings */
257
+ measures: WeatherHistoryMeasureEnum[];
258
+ /**
259
+ * Readings ordered by timestamp, one per bucket of
260
+ * {@link WeatherHistory.resolution}. Empty when the provider holds no data
261
+ * for the requested interval — this is a normal result, not an error.
262
+ */
263
+ readings: WeatherHistoryReading[];
264
+ /**
265
+ * Aggregates per numeric measure over the covered part of the interval.
266
+ * {@link WeatherHistoryMeasureEnum.Symbol} is categorical and therefore
267
+ * never present here. Absent when {@link WeatherHistory.readings} is empty.
268
+ */
269
+ statistics?: Partial<Record<WeatherHistoryMeasureEnum, WeatherHistoryStatistics>>;
270
+ /**
271
+ * Start of the part of the interval the provider could cover, in ISO
272
+ * format. Later than {@link WeatherHistory.fromIso} when the request
273
+ * reached further back than the archive goes. Absent when
274
+ * {@link WeatherHistory.readings} is empty.
275
+ */
276
+ coveredFromIso?: string;
277
+ /**
278
+ * End of the part of the interval the provider could cover, in ISO format.
279
+ * Earlier than {@link WeatherHistory.untilIso} when the request reached
280
+ * into the future or past the most recent observation. Absent when
281
+ * {@link WeatherHistory.readings} is empty.
282
+ */
283
+ coveredUntilIso?: string;
284
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Resolution of historical weather data entries.
3
+ *
4
+ * The values mirror {@link ForecastResolutionEnum} so a history series and a
5
+ * forecast series of the same resolution can be concatenated without
6
+ * translating between the two vocabularies.
7
+ */
8
+ export var WeatherHistoryResolutionEnum;
9
+ (function (WeatherHistoryResolutionEnum) {
10
+ /** 1-minute intervals */
11
+ WeatherHistoryResolutionEnum["OneMinute"] = "1min";
12
+ /** 15-minute intervals */
13
+ WeatherHistoryResolutionEnum["FifteenMinutes"] = "15min";
14
+ /** 1-hour intervals */
15
+ WeatherHistoryResolutionEnum["OneHour"] = "1hr";
16
+ })(WeatherHistoryResolutionEnum || (WeatherHistoryResolutionEnum = {}));
17
+ /**
18
+ * A weather quantity a history provider can serve.
19
+ *
20
+ * Used to narrow a request to the measures an app actually needs — archives
21
+ * are usually billed or rate-limited per quantity, so asking for irradiance
22
+ * when only wind is wanted is pure cost.
23
+ */
24
+ export var WeatherHistoryMeasureEnum;
25
+ (function (WeatherHistoryMeasureEnum) {
26
+ /** Outdoor air temperature in degrees Celsius */
27
+ WeatherHistoryMeasureEnum["OutdoorTemperature"] = "outdoor-temperature";
28
+ /** Wind speed in meters per second */
29
+ WeatherHistoryMeasureEnum["WindSpeed"] = "wind-speed";
30
+ /** Cloud coverage area in percent */
31
+ WeatherHistoryMeasureEnum["CloudArea"] = "cloud-area";
32
+ /** Global horizontal irradiance in W/m² */
33
+ WeatherHistoryMeasureEnum["GlobalHorizontalIrradiance"] = "global-horizontal-irradiance";
34
+ /** Direct normal irradiance in W/m² */
35
+ WeatherHistoryMeasureEnum["DirectNormalIrradiance"] = "direct-normal-irradiance";
36
+ /** Diffuse horizontal irradiance in W/m² */
37
+ WeatherHistoryMeasureEnum["DiffuseHorizontalIrradiance"] = "diffuse-horizontal-irradiance";
38
+ /** Categorical weather symbol */
39
+ WeatherHistoryMeasureEnum["Symbol"] = "symbol";
40
+ })(WeatherHistoryMeasureEnum || (WeatherHistoryMeasureEnum = {}));
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.20.0";
8
+ export declare const SDK_VERSION = "1.21.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.20.0';
8
+ export const SDK_VERSION = '1.21.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.20.0",
3
+ "version": "1.21.0",
4
4
  "description": "enyo Energy App SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",