@enyo-energy/energy-app-sdk 1.20.0 → 1.22.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 +81 -0
- package/dist/cjs/energy-app-package-definition.cjs +19 -1
- package/dist/cjs/energy-app-package-definition.d.cts +37 -0
- package/dist/cjs/energy-app-permission.type.cjs +2 -0
- package/dist/cjs/energy-app-permission.type.d.cts +2 -0
- package/dist/cjs/energy-app.cjs +9 -0
- package/dist/cjs/energy-app.d.cts +8 -0
- package/dist/cjs/enyo-energy-app-sdk.d.cts +3 -0
- package/dist/cjs/implementations/firmware/firmware-validators.cjs +16 -2
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/packages/energy-app-modbus-rtu.d.cts +31 -2
- package/dist/cjs/packages/energy-app-weather-history.cjs +2 -0
- package/dist/cjs/packages/energy-app-weather-history.d.cts +138 -0
- package/dist/cjs/types/enyo-weather-history.cjs +43 -0
- package/dist/cjs/types/enyo-weather-history.d.cts +284 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/energy-app-package-definition.d.ts +37 -0
- package/dist/energy-app-package-definition.js +18 -0
- package/dist/energy-app-permission.type.d.ts +2 -0
- package/dist/energy-app-permission.type.js +2 -0
- package/dist/energy-app.d.ts +8 -0
- package/dist/energy-app.js +9 -0
- package/dist/enyo-energy-app-sdk.d.ts +3 -0
- package/dist/implementations/firmware/firmware-validators.js +16 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/packages/energy-app-modbus-rtu.d.ts +31 -2
- package/dist/packages/energy-app-weather-history.d.ts +138 -0
- package/dist/packages/energy-app-weather-history.js +1 -0
- package/dist/types/enyo-weather-history.d.ts +284 -0
- package/dist/types/enyo-weather-history.js +40 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EnergyAppPackageFirmwareModeEnum = exports.EnergyAppPackageCategory = void 0;
|
|
3
|
+
exports.EnergyAppPackageFirmwareModeEnum = exports.EnergyAppPackageCompatibilityStatus = exports.EnergyAppPackageCategory = void 0;
|
|
4
4
|
exports.defineEnergyAppPackage = defineEnergyAppPackage;
|
|
5
5
|
const version_js_1 = require("./version.cjs");
|
|
6
6
|
var EnergyAppPackageCategory;
|
|
@@ -27,6 +27,24 @@ var EnergyAppPackageCategory;
|
|
|
27
27
|
EnergyAppPackageCategory["Vehicle"] = "vehicle";
|
|
28
28
|
EnergyAppPackageCategory["Other"] = "other";
|
|
29
29
|
})(EnergyAppPackageCategory || (exports.EnergyAppPackageCategory = EnergyAppPackageCategory = {}));
|
|
30
|
+
/**
|
|
31
|
+
* Whether a declared compatibility entry means "this works" or "this is known
|
|
32
|
+
* not to work".
|
|
33
|
+
*
|
|
34
|
+
* Used by {@link EnergyAppPackageCompatibilityVendor.status} and
|
|
35
|
+
* {@link EnergyAppPackageCompatibilityModel.status} so a package can
|
|
36
|
+
* list a vendor or model it has explicitly tested and found unsupported,
|
|
37
|
+
* instead of silently leaving it out. The enyo Store and onboarding flows can
|
|
38
|
+
* then tell the user "this device is not supported by this app" rather than
|
|
39
|
+
* showing nothing at all.
|
|
40
|
+
*/
|
|
41
|
+
var EnergyAppPackageCompatibilityStatus;
|
|
42
|
+
(function (EnergyAppPackageCompatibilityStatus) {
|
|
43
|
+
/** The package supports this vendor or model. */
|
|
44
|
+
EnergyAppPackageCompatibilityStatus["Compatible"] = "compatible";
|
|
45
|
+
/** The package has been verified **not** to work with this vendor or model. */
|
|
46
|
+
EnergyAppPackageCompatibilityStatus["NotCompatible"] = "not-compatible";
|
|
47
|
+
})(EnergyAppPackageCompatibilityStatus || (exports.EnergyAppPackageCompatibilityStatus = EnergyAppPackageCompatibilityStatus = {}));
|
|
30
48
|
/**
|
|
31
49
|
* Enum form of {@link EnergyAppPackageFirmwareMode} for use in package
|
|
32
50
|
* definitions.
|
|
@@ -213,6 +213,23 @@ export interface EnergyAppPackagePermission {
|
|
|
213
213
|
/** Internal documentation describing what this permission is used for */
|
|
214
214
|
internalComment: string;
|
|
215
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Whether a declared compatibility entry means "this works" or "this is known
|
|
218
|
+
* not to work".
|
|
219
|
+
*
|
|
220
|
+
* Used by {@link EnergyAppPackageCompatibilityVendor.status} and
|
|
221
|
+
* {@link EnergyAppPackageCompatibilityModel.status} so a package can
|
|
222
|
+
* list a vendor or model it has explicitly tested and found unsupported,
|
|
223
|
+
* instead of silently leaving it out. The enyo Store and onboarding flows can
|
|
224
|
+
* then tell the user "this device is not supported by this app" rather than
|
|
225
|
+
* showing nothing at all.
|
|
226
|
+
*/
|
|
227
|
+
export declare enum EnergyAppPackageCompatibilityStatus {
|
|
228
|
+
/** The package supports this vendor or model. */
|
|
229
|
+
Compatible = "compatible",
|
|
230
|
+
/** The package has been verified **not** to work with this vendor or model. */
|
|
231
|
+
NotCompatible = "not-compatible"
|
|
232
|
+
}
|
|
216
233
|
/**
|
|
217
234
|
* A specific device model supported by an Energy App package.
|
|
218
235
|
* the concrete models the package has been verified to work with.
|
|
@@ -249,6 +266,16 @@ export interface EnergyAppPackageCompatibilityModel {
|
|
|
249
266
|
category?: EnergyAppPackageCategory;
|
|
250
267
|
/** Optional internal note explaining model-specific caveats or limitations */
|
|
251
268
|
internalComment?: string;
|
|
269
|
+
/**
|
|
270
|
+
* Whether this model is supported or explicitly unsupported.
|
|
271
|
+
*
|
|
272
|
+
* Defaults to {@link EnergyAppPackageCompatibilityStatus.Compatible} when
|
|
273
|
+
* omitted, so existing definitions keep their meaning. Set it to
|
|
274
|
+
* {@link EnergyAppPackageCompatibilityStatus.NotCompatible} to document a
|
|
275
|
+
* model you have tested and found not to work — use
|
|
276
|
+
* {@link internalComment} to say why.
|
|
277
|
+
*/
|
|
278
|
+
status?: EnergyAppPackageCompatibilityStatus;
|
|
252
279
|
/**
|
|
253
280
|
* Important capabilities this specific model supports (e.g. charging the
|
|
254
281
|
* battery from grid, limiting the charge, or forcing a heat pump DHW boost).
|
|
@@ -277,6 +304,16 @@ export interface EnergyAppPackageCompatibilityVendor {
|
|
|
277
304
|
* worse than listing none.
|
|
278
305
|
*/
|
|
279
306
|
models: EnergyAppPackageCompatibilityModel[];
|
|
307
|
+
/**
|
|
308
|
+
* Whether this vendor is supported or explicitly unsupported.
|
|
309
|
+
*
|
|
310
|
+
* Defaults to {@link EnergyAppPackageCompatibilityStatus.Compatible} when
|
|
311
|
+
* omitted. Set it to
|
|
312
|
+
* {@link EnergyAppPackageCompatibilityStatus.NotCompatible} to declare a
|
|
313
|
+
* brand the package is known not to work with; individual models may still
|
|
314
|
+
* override it with their own {@link EnergyAppPackageCompatibilityModel.status}.
|
|
315
|
+
*/
|
|
316
|
+
status?: EnergyAppPackageCompatibilityStatus;
|
|
280
317
|
/**
|
|
281
318
|
* Marks this package as the default Energy App for the vendor when no
|
|
282
319
|
* concrete model has been selected.
|
|
@@ -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",
|
package/dist/cjs/energy-app.cjs
CHANGED
|
@@ -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 */
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
24
|
exports.FirmwareRegistryValidationError = void 0;
|
|
25
25
|
exports.validateFirmwareRegistry = validateFirmwareRegistry;
|
|
26
26
|
exports.assertValidFirmwareRegistry = assertValidFirmwareRegistry;
|
|
27
|
+
const energy_app_package_definition_js_1 = require("../../energy-app-package-definition.cjs");
|
|
27
28
|
const energy_app_permission_type_js_1 = require("../../energy-app-permission.type.cjs");
|
|
28
29
|
const define_firmware_file_js_1 = require("./define-firmware-file.cjs");
|
|
29
30
|
/**
|
|
@@ -269,11 +270,12 @@ function findDanglingSources(files) {
|
|
|
269
270
|
}
|
|
270
271
|
/**
|
|
271
272
|
* Reports vendors and models referenced by firmware entries that the package
|
|
272
|
-
* does not declare in its `compatibility` list
|
|
273
|
+
* does not declare in its `compatibility` list, or that it declares as
|
|
274
|
+
* {@link EnergyAppPackageCompatibilityStatus.NotCompatible}.
|
|
273
275
|
*
|
|
274
276
|
* @param files - All declared firmware entries.
|
|
275
277
|
* @param compatibility - The package's declared vendors and models.
|
|
276
|
-
* @returns One warning per unknown vendor or model.
|
|
278
|
+
* @returns One warning per unknown or explicitly incompatible vendor or model.
|
|
277
279
|
*/
|
|
278
280
|
function findUnknownCompatibility(files, compatibility) {
|
|
279
281
|
const warnings = [];
|
|
@@ -281,15 +283,27 @@ function findUnknownCompatibility(files, compatibility) {
|
|
|
281
283
|
return warnings;
|
|
282
284
|
const vendors = new Set(compatibility.map(vendor => vendor.vendorName));
|
|
283
285
|
const models = new Set(compatibility.flatMap(vendor => vendor.models.map(model => model.modelName)));
|
|
286
|
+
const incompatibleVendors = new Set(compatibility
|
|
287
|
+
.filter(vendor => vendor.status === energy_app_package_definition_js_1.EnergyAppPackageCompatibilityStatus.NotCompatible)
|
|
288
|
+
.map(vendor => vendor.vendorName));
|
|
289
|
+
const incompatibleModels = new Set(compatibility.flatMap(vendor => vendor.models
|
|
290
|
+
.filter(model => model.status === energy_app_package_definition_js_1.EnergyAppPackageCompatibilityStatus.NotCompatible)
|
|
291
|
+
.map(model => model.modelName)));
|
|
284
292
|
for (const [index, file] of files.entries()) {
|
|
285
293
|
const at = describe(file, index);
|
|
286
294
|
if (file.vendorName && !vendors.has(file.vendorName)) {
|
|
287
295
|
warnings.push(`${at}: vendorName "${file.vendorName}" is not listed in compatibility.`);
|
|
288
296
|
}
|
|
297
|
+
else if (file.vendorName && incompatibleVendors.has(file.vendorName)) {
|
|
298
|
+
warnings.push(`${at}: vendorName "${file.vendorName}" is declared as not-compatible.`);
|
|
299
|
+
}
|
|
289
300
|
for (const model of file.modelNames ?? []) {
|
|
290
301
|
if (!models.has(model)) {
|
|
291
302
|
warnings.push(`${at}: modelName "${model}" is not listed in compatibility.`);
|
|
292
303
|
}
|
|
304
|
+
else if (incompatibleModels.has(model)) {
|
|
305
|
+
warnings.push(`${at}: modelName "${model}" is declared as not-compatible.`);
|
|
306
|
+
}
|
|
293
307
|
}
|
|
294
308
|
}
|
|
295
309
|
return warnings;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -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);
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -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';
|
|
@@ -28,6 +28,21 @@ export interface ModbusRtuOptions {
|
|
|
28
28
|
*/
|
|
29
29
|
waitBetweenMessagesMs?: number;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Which register bank an RTU read addresses, and therefore which Modbus
|
|
33
|
+
* function code goes on the wire.
|
|
34
|
+
*
|
|
35
|
+
* Holding and input registers are two separate address spaces: a device may
|
|
36
|
+
* answer register 30001 as an input register and hold something entirely
|
|
37
|
+
* different — or nothing at all — at the same address in the holding bank.
|
|
38
|
+
* Reading the wrong bank yields an illegal-data-address exception, not a
|
|
39
|
+
* timeout, so this is a correctness knob rather than a recovery one.
|
|
40
|
+
*/
|
|
41
|
+
export type ModbusRtuRegisterType =
|
|
42
|
+
/** Holding registers, read with function code 3 (`mbpoll -t 4`). */
|
|
43
|
+
'holding'
|
|
44
|
+
/** Input registers, read with function code 4 (`mbpoll -t 3`). */
|
|
45
|
+
| 'input';
|
|
31
46
|
/**
|
|
32
47
|
* Request parameters for reading Modbus RTU registers.
|
|
33
48
|
*/
|
|
@@ -38,6 +53,14 @@ export interface ModbusRtuReadRegistersRequest {
|
|
|
38
53
|
startRegister: number;
|
|
39
54
|
/** Number of consecutive registers to read */
|
|
40
55
|
count: number;
|
|
56
|
+
/**
|
|
57
|
+
* Which register bank to read from.
|
|
58
|
+
*
|
|
59
|
+
* `'holding'` issues function code 3 and `'input'` issues function code 4.
|
|
60
|
+
* Defaults to `'holding'` when omitted, which is what every existing caller
|
|
61
|
+
* gets today.
|
|
62
|
+
*/
|
|
63
|
+
registerType?: ModbusRtuRegisterType;
|
|
41
64
|
}
|
|
42
65
|
/**
|
|
43
66
|
* Response containing register values read from a Modbus RTU device.
|
|
@@ -63,9 +86,15 @@ export interface ModbusRtuWriteRegistersRequest {
|
|
|
63
86
|
* Provides methods for reading and writing registers over a serial connection.
|
|
64
87
|
*/
|
|
65
88
|
export interface EnergyAppModbusRtuInstance {
|
|
66
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Read register values from the connected Modbus RTU device.
|
|
91
|
+
*
|
|
92
|
+
* Reads holding registers (function code 3) unless the request sets
|
|
93
|
+
* {@link ModbusRtuReadRegistersRequest.registerType} to `'input'`, which
|
|
94
|
+
* reads input registers with function code 4 instead.
|
|
95
|
+
*/
|
|
67
96
|
readRegisters: (request: ModbusRtuReadRegistersRequest) => Promise<ModbusRtuReadRegistersResponse>;
|
|
68
|
-
/** Write register values to the connected Modbus RTU device */
|
|
97
|
+
/** Write register values to the connected Modbus RTU device (holding registers only) */
|
|
69
98
|
writeRegisters: (request: ModbusRtuWriteRegistersRequest) => Promise<void>;
|
|
70
99
|
}
|
|
71
100
|
/**
|
|
@@ -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 = {}));
|