@enyo-energy/energy-app-sdk 0.0.109 → 0.0.111

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.
Files changed (82) hide show
  1. package/README.md +374 -0
  2. package/dist/cjs/energy-app.cjs +240 -0
  3. package/dist/cjs/energy-app.d.cts +177 -0
  4. package/dist/cjs/implementations/forecasts/battery-forecast.cjs +238 -0
  5. package/dist/cjs/implementations/forecasts/battery-forecast.d.cts +88 -0
  6. package/dist/cjs/implementations/forecasts/ev-charging-forecast.cjs +215 -0
  7. package/dist/cjs/implementations/forecasts/ev-charging-forecast.d.cts +74 -0
  8. package/dist/cjs/implementations/forecasts/forecast-types.cjs +43 -0
  9. package/dist/cjs/implementations/forecasts/forecast-types.d.cts +120 -0
  10. package/dist/cjs/implementations/forecasts/forecast-utils.cjs +303 -0
  11. package/dist/cjs/implementations/forecasts/forecast-utils.d.cts +159 -0
  12. package/dist/cjs/implementations/forecasts/heatpump-consumption-forecast.cjs +216 -0
  13. package/dist/cjs/implementations/forecasts/heatpump-consumption-forecast.d.cts +75 -0
  14. package/dist/cjs/implementations/forecasts/heatpump-dhw-temperature-forecast.cjs +225 -0
  15. package/dist/cjs/implementations/forecasts/heatpump-dhw-temperature-forecast.d.cts +92 -0
  16. package/dist/cjs/implementations/forecasts/home-consumption-forecast.cjs +186 -0
  17. package/dist/cjs/implementations/forecasts/home-consumption-forecast.d.cts +69 -0
  18. package/dist/cjs/implementations/forecasts/pv-production-forecast.cjs +198 -0
  19. package/dist/cjs/implementations/forecasts/pv-production-forecast.d.cts +83 -0
  20. package/dist/cjs/index.cjs +17 -221
  21. package/dist/cjs/index.d.cts +17 -160
  22. package/dist/cjs/integrations/air-conditioning-integration-energy-app.cjs +62 -0
  23. package/dist/cjs/integrations/air-conditioning-integration-energy-app.d.cts +44 -0
  24. package/dist/cjs/integrations/energy-manager-energy-app.cjs +206 -0
  25. package/dist/cjs/integrations/energy-manager-energy-app.d.cts +121 -0
  26. package/dist/cjs/integrations/heatpump-integration-energy-app.cjs +93 -0
  27. package/dist/cjs/integrations/heatpump-integration-energy-app.d.cts +88 -0
  28. package/dist/cjs/integrations/integration-energy-app.cjs +266 -0
  29. package/dist/cjs/integrations/integration-energy-app.d.cts +151 -0
  30. package/dist/cjs/integrations/integration-types.cjs +2 -0
  31. package/dist/cjs/integrations/integration-types.d.cts +73 -0
  32. package/dist/cjs/integrations/inverter-integration-energy-app.cjs +44 -0
  33. package/dist/cjs/integrations/inverter-integration-energy-app.d.cts +34 -0
  34. package/dist/cjs/integrations/storage-integration-energy-app.cjs +64 -0
  35. package/dist/cjs/integrations/storage-integration-energy-app.d.cts +49 -0
  36. package/dist/cjs/integrations/wallbox-integration-energy-app.cjs +136 -0
  37. package/dist/cjs/integrations/wallbox-integration-energy-app.d.cts +113 -0
  38. package/dist/cjs/packages/energy-app-timeseries.d.cts +28 -1
  39. package/dist/cjs/types/enyo-timeseries.d.cts +45 -0
  40. package/dist/cjs/version.cjs +1 -1
  41. package/dist/cjs/version.d.cts +1 -1
  42. package/dist/energy-app.d.ts +177 -0
  43. package/dist/energy-app.js +236 -0
  44. package/dist/implementations/forecasts/battery-forecast.d.ts +88 -0
  45. package/dist/implementations/forecasts/battery-forecast.js +234 -0
  46. package/dist/implementations/forecasts/ev-charging-forecast.d.ts +74 -0
  47. package/dist/implementations/forecasts/ev-charging-forecast.js +211 -0
  48. package/dist/implementations/forecasts/forecast-types.d.ts +120 -0
  49. package/dist/implementations/forecasts/forecast-types.js +39 -0
  50. package/dist/implementations/forecasts/forecast-utils.d.ts +159 -0
  51. package/dist/implementations/forecasts/forecast-utils.js +284 -0
  52. package/dist/implementations/forecasts/heatpump-consumption-forecast.d.ts +75 -0
  53. package/dist/implementations/forecasts/heatpump-consumption-forecast.js +212 -0
  54. package/dist/implementations/forecasts/heatpump-dhw-temperature-forecast.d.ts +92 -0
  55. package/dist/implementations/forecasts/heatpump-dhw-temperature-forecast.js +221 -0
  56. package/dist/implementations/forecasts/home-consumption-forecast.d.ts +69 -0
  57. package/dist/implementations/forecasts/home-consumption-forecast.js +182 -0
  58. package/dist/implementations/forecasts/pv-production-forecast.d.ts +83 -0
  59. package/dist/implementations/forecasts/pv-production-forecast.js +194 -0
  60. package/dist/index.d.ts +17 -160
  61. package/dist/index.js +17 -219
  62. package/dist/integrations/air-conditioning-integration-energy-app.d.ts +44 -0
  63. package/dist/integrations/air-conditioning-integration-energy-app.js +58 -0
  64. package/dist/integrations/energy-manager-energy-app.d.ts +121 -0
  65. package/dist/integrations/energy-manager-energy-app.js +202 -0
  66. package/dist/integrations/heatpump-integration-energy-app.d.ts +88 -0
  67. package/dist/integrations/heatpump-integration-energy-app.js +89 -0
  68. package/dist/integrations/integration-energy-app.d.ts +151 -0
  69. package/dist/integrations/integration-energy-app.js +262 -0
  70. package/dist/integrations/integration-types.d.ts +73 -0
  71. package/dist/integrations/integration-types.js +1 -0
  72. package/dist/integrations/inverter-integration-energy-app.d.ts +34 -0
  73. package/dist/integrations/inverter-integration-energy-app.js +40 -0
  74. package/dist/integrations/storage-integration-energy-app.d.ts +49 -0
  75. package/dist/integrations/storage-integration-energy-app.js +60 -0
  76. package/dist/integrations/wallbox-integration-energy-app.d.ts +113 -0
  77. package/dist/integrations/wallbox-integration-energy-app.js +132 -0
  78. package/dist/packages/energy-app-timeseries.d.ts +28 -1
  79. package/dist/types/enyo-timeseries.d.ts +45 -0
  80. package/dist/version.d.ts +1 -1
  81. package/dist/version.js +1 -1
  82. package/package.json +1 -1
package/README.md CHANGED
@@ -9,6 +9,7 @@ The official TypeScript SDK for building Energy Apps on the enyo platform. Creat
9
9
 
10
10
  - [Installation](#installation)
11
11
  - [Quick Start](#quick-start)
12
+ - [Choosing the Right API](#choosing-the-right-api)
12
13
  - [Core Concepts](#core-concepts)
13
14
  - [Energy App Lifecycle](#energy-app-lifecycle)
14
15
  - [Package Definition](#package-definition)
@@ -22,6 +23,22 @@ The official TypeScript SDK for building Energy Apps on the enyo platform. Creat
22
23
  - [User Features](#user-features)
23
24
  - [App Intelligence](#app-intelligence)
24
25
  - [Advanced Modbus Integration](#advanced-modbus-integration)
26
+ - [Device Integrations](#device-integrations)
27
+ - [IntegrationEnergyApp (Base Class)](#integrationenergyapp-base-class)
28
+ - [HeatpumpIntegrationEnergyApp](#heatpumpintegrationenergyapp)
29
+ - [WallboxIntegrationEnergyApp](#wallboxintegrationenergyapp)
30
+ - [StorageIntegrationEnergyApp](#storageintegrationenergyapp)
31
+ - [InverterIntegrationEnergyApp](#inverterintegrationenergyapp)
32
+ - [AirConditioningIntegrationEnergyApp](#airconditioningintegrationenergyapp)
33
+ - [EnergyManagerEnergyApp](#energymanagerenergyapp)
34
+ - [Forecasting](#forecasting)
35
+ - [ForecastConfig](#forecastconfig)
36
+ - [PvProductionForecast](#pvproductionforecast)
37
+ - [BatteryForecast](#batteryforecast)
38
+ - [HomeConsumptionForecast](#homeconsumptionforecast)
39
+ - [EvChargingForecast](#evchargingforecast)
40
+ - [HeatpumpConsumptionForecast](#heatpumpconsumptionforecast)
41
+ - [HeatpumpDhwTemperatureForecast](#heatpumpdhwtemperatureforecast)
25
42
  - [Examples](#examples)
26
43
  - [Basic Energy App](#basic-energy-app)
27
44
  - [Device Integration](#device-integration)
@@ -76,6 +93,36 @@ async function startApp() {
76
93
  }
77
94
  ```
78
95
 
96
+ ## Choosing the Right API
97
+
98
+ The SDK exposes several layered building blocks. Pick the one that matches the kind of app you are building before diving into the API reference:
99
+
100
+ - **Core SDK (`EnergyApp`)** — the always-present facade for system lifecycle, storage, data bus, settings, notifications, and HTTP. Every Energy App uses it.
101
+ - **Modbus helpers (`EnergyAppModbusInverter` / `Battery` / `Meter`)** — vendor-agnostic, configuration-driven Modbus access for raw register polling.
102
+ - **Device Integrations (`*IntegrationEnergyApp`)** — *inbound* abstractions for apps that **drive a real device** (heatpump, wallbox, inverter, storage, air conditioning). They subscribe to the right data-bus commands, dispatch them to your handlers, auto-acknowledge, and expose typed `publish*` helpers for status updates.
103
+ - **Forecasting (`*Forecast`, `EnergyManagerEnergyApp`)** — *outbound* abstractions for apps that **predict** future PV production, consumption, battery state, EV charging load, heatpump load, or DHW tank temperature using historical timeseries plus live data-bus updates.
104
+
105
+ ### Decision Matrix
106
+
107
+ | If you want to… | Use |
108
+ |---|---|
109
+ | React to system lifecycle, store data, send notifications | [`EnergyApp`](#api-reference) |
110
+ | Talk to a Modbus device through configuration only | [`EnergyAppModbusInverter` / `Battery` / `Meter`](#advanced-modbus-integration) |
111
+ | Build a **device integration** for a heatpump | [`HeatpumpIntegrationEnergyApp`](#heatpumpintegrationenergyapp) |
112
+ | Build a **device integration** for an EV wallbox | [`WallboxIntegrationEnergyApp`](#wallboxintegrationenergyapp) |
113
+ | Build a **device integration** for a battery / storage system | [`StorageIntegrationEnergyApp`](#storageintegrationenergyapp) |
114
+ | Build a **device integration** for a PV inverter | [`InverterIntegrationEnergyApp`](#inverterintegrationenergyapp) |
115
+ | Build a **device integration** for an air-conditioning unit | [`AirConditioningIntegrationEnergyApp`](#airconditioningintegrationenergyapp) |
116
+ | Build an **energy manager** that orchestrates many forecasters | [`EnergyManagerEnergyApp`](#energymanagerenergyapp) |
117
+ | Forecast PV production for a single inverter | [`PvProductionForecast`](#pvproductionforecast) |
118
+ | Forecast battery state-of-charge | [`BatteryForecast`](#batteryforecast) |
119
+ | Forecast total household consumption | [`HomeConsumptionForecast`](#homeconsumptionforecast) |
120
+ | Forecast EV charging demand | [`EvChargingForecast`](#evchargingforecast) |
121
+ | Forecast heatpump electrical consumption | [`HeatpumpConsumptionForecast`](#heatpumpconsumptionforecast) |
122
+ | Forecast heatpump DHW tank temperature | [`HeatpumpDhwTemperatureForecast`](#heatpumpdhwtemperatureforecast) |
123
+
124
+ > **Rule of thumb:** if your app *receives* commands and drives hardware, you want an **Integration**. If your app *produces* predictions, you want a **Forecast** (and likely an `EnergyManagerEnergyApp` to wire several together).
125
+
79
126
  ## Core Concepts
80
127
 
81
128
  ### Energy App Lifecycle
@@ -859,6 +906,333 @@ The Modbus implementation follows a clean, modular architecture:
859
906
 
860
907
  This modular design ensures maintainability, testability, and extensibility for future enhancements.
861
908
 
909
+ ## Device Integrations
910
+
911
+ Device Integrations are the high-level building blocks for apps that **drive a real device** — a heatpump, EV wallbox, PV inverter, battery storage system, or air-conditioning unit. Each integration class hides the data-bus plumbing for its appliance type so you only implement the business logic that physically controls the device.
912
+
913
+ ### ✨ What the integration framework does for you
914
+
915
+ - **Subscribes** to the relevant `*CommandV1` data-bus messages for the appliance type.
916
+ - **Dispatches** each command to the async handler you register.
917
+ - **Auto-acknowledges** every command via a `CommandAcknowledgeV1` response containing your `Accepted` / `Rejected` / `NotSupported` answer.
918
+ - **Handles broadcast `GridOperatorPowerLimitationV1`** (§14a EnWG) and routes it once per managed appliance.
919
+ - **Manages lifecycle** — auto-starts on construction and auto-stops on shutdown by default.
920
+ - **Exposes typed `publish*` helpers** so your handler implementations can broadcast status updates back to the system without hand-building messages.
921
+
922
+ ### 🚀 Quick Start
923
+
924
+ ```typescript
925
+ import {
926
+ HeatpumpIntegrationEnergyApp,
927
+ EnyoSourceEnum,
928
+ EnyoCommandAcknowledgeAnswerEnum,
929
+ ApplianceManager,
930
+ } from '@enyo-energy/energy-app-sdk';
931
+
932
+ class MyHeatpumpApp extends HeatpumpIntegrationEnergyApp {
933
+ constructor(applianceManager: ApplianceManager) {
934
+ super({ source: EnyoSourceEnum.Device, applianceManager });
935
+ }
936
+
937
+ protected async handleHeatpumpOverheating(message) {
938
+ await driveOverheating(message.data);
939
+ return { answer: EnyoCommandAcknowledgeAnswerEnum.Accepted };
940
+ }
941
+
942
+ protected async handleHeatpumpAvailablePowerAnnouncement(message) {
943
+ await scaleHeatpumpToEnvelope(message.data);
944
+ return { answer: EnyoCommandAcknowledgeAnswerEnum.Accepted };
945
+ }
946
+
947
+ protected async handleGridOperatorPowerLimitation(message, applianceId) {
948
+ await applyGridLimit(applianceId, message.data);
949
+ return { applianceId, answer: EnyoCommandAcknowledgeAnswerEnum.Accepted };
950
+ }
951
+ }
952
+ ```
953
+
954
+ ### IntegrationEnergyApp (Base Class)
955
+
956
+ `IntegrationEnergyApp` is the abstract base every device integration extends. It owns the data-bus subscription/acknowledgment loop and the broadcast routing so subclasses only declare *what* commands they care about and *how* to fulfil them.
957
+
958
+ **Constructor options (`IntegrationEnergyAppOptions`)**
959
+
960
+ | Field | Type | Default | Purpose |
961
+ |---|---|---|---|
962
+ | `source` | `EnyoSourceEnum` | required | Source identifier for outbound messages (typically `Device`). |
963
+ | `applianceManager` | `ApplianceManager` | optional | Lookup all appliances of the integration's `managedApplianceType`. |
964
+ | `applianceIds` | `string[]` | optional | Explicit list of appliance IDs to manage. Overrides the manager-based lookup. |
965
+ | `autoStart` | `boolean` | `true` | Subscribe to the data bus immediately after construction. |
966
+ | `autoStopOnShutdown` | `boolean` | `true` | Register an SDK shutdown hook to release listeners. |
967
+
968
+ **Lifecycle**
969
+
970
+ - `start(): void` — idempotent; registers all command handlers via the subclass's `registerHandlers()`.
971
+ - `stop(): void` — releases listeners and disposes the outbound command handler.
972
+
973
+ **For subclass authors**
974
+
975
+ - `protected abstract registerHandlers(): void` — call `registerCommandHandler(messageType, handler)` for each command you want to receive.
976
+ - `protected abstract handleGridOperatorPowerLimitation(message, applianceId)` — handle the §14a EnWG broadcast per managed appliance.
977
+ - `protected abstract get managedApplianceType(): EnyoApplianceTypeEnum` — used to resolve appliance IDs when no explicit list is given.
978
+
979
+ ### HeatpumpIntegrationEnergyApp
980
+
981
+ Drives a heatpump. Manages building / DHW overheating commands and grid-power-availability announcements.
982
+
983
+ - **Subscribed commands:** `HeatpumpOverheatingV1`, `HeatpumpAvailablePowerAnnouncementV1`, `GridOperatorPowerLimitationV1` (broadcast)
984
+ - **Implement:** `handleHeatpumpOverheating`, `handleHeatpumpAvailablePowerAnnouncement`, `handleGridOperatorPowerLimitation`
985
+ - **Publish helpers:**
986
+ - `publishHeatpumpValuesUpdate(applianceId, values)` — operation mode, electrical and thermal power, energies.
987
+ - `publishHeatpumpTemperatures(applianceId, temperatures)` — outdoor, flow, return, DHW tanks, heating circuits, buffer tank.
988
+
989
+ ### WallboxIntegrationEnergyApp
990
+
991
+ Drives an EV wallbox / charger. Has the richest command surface of all integrations.
992
+
993
+ - **Subscribed commands:** `StartChargeV1`, `StopChargeV1`, `PauseChargingV1`, `ResumeChargingV1`, `ChangeChargingPowerV1`, `SetChargingScheduleV1`, `ResetChargerV1`, `RebootChargerV1`, `RequestChargerLogsV1`, `ClearChargingProfilesV1`, `GridOperatorPowerLimitationV1` (broadcast)
994
+ - **Implement:** one `handle*` method per command listed above plus `handleGridOperatorPowerLimitation`.
995
+ - **Publish helpers:**
996
+ - `publishChargingStarted(applianceId, data)` / `publishChargingStopped(applianceId, data)`
997
+ - `publishChargingMeterValues(applianceId, data)` — periodic meter values during a session.
998
+ - `publishMaxChargingPowerChanged(applianceId, maxChargingPowerKw)` — e.g. on thermal derating.
999
+ - `publishChargerStatusChanged(applianceId, data)` — OCPP-style status changes.
1000
+
1001
+ ```typescript
1002
+ class MyWallbox extends WallboxIntegrationEnergyApp {
1003
+ constructor(applianceManager: ApplianceManager) {
1004
+ super({ source: EnyoSourceEnum.Device, applianceManager });
1005
+ }
1006
+
1007
+ protected async handleStartCharge(message) {
1008
+ const txId = await this.driver.start(message.data);
1009
+ this.publishChargingStarted(message.applianceId, { transactionId: txId });
1010
+ return { answer: EnyoCommandAcknowledgeAnswerEnum.Accepted };
1011
+ }
1012
+ // ... other handlers
1013
+ }
1014
+ ```
1015
+
1016
+ ### StorageIntegrationEnergyApp
1017
+
1018
+ Drives a battery / storage system. Controls grid-charging windows and discharge limits.
1019
+
1020
+ - **Subscribed commands:** `StartStorageGridChargeV1`, `StopStorageGridChargeV1`, `SetStorageDischargeLimitV1`, `GridOperatorPowerLimitationV1` (broadcast)
1021
+ - **Implement:** `handleStartStorageGridCharge`, `handleStopStorageGridCharge`, `handleSetStorageDischargeLimit`, `handleGridOperatorPowerLimitation`.
1022
+ - **Publish helpers:**
1023
+ - `publishBatteryValuesUpdate(applianceId, data)` — state, power, SoC.
1024
+ - `publishMaxDischargePowerChanged(applianceId, maxDischargePowerKw)` — discharge-limit changes.
1025
+
1026
+ ### InverterIntegrationEnergyApp
1027
+
1028
+ Drives a PV inverter. Controls grid feed-in limits and publishes electrical metrics.
1029
+
1030
+ - **Subscribed commands:** `SetInverterFeedInLimitV1`, `GridOperatorPowerLimitationV1` (broadcast)
1031
+ - **Implement:** `handleSetInverterFeedInLimit` (`data.feedInLimitW` may be `null` to clear), `handleGridOperatorPowerLimitation`.
1032
+ - **Publish helpers:**
1033
+ - `publishInverterValuesUpdate(applianceId, data)` — DC strings, AC voltages, total PV power, operating state.
1034
+
1035
+ ### AirConditioningIntegrationEnergyApp
1036
+
1037
+ Drives an air-conditioning unit. Starts and stops heating or cooling modes.
1038
+
1039
+ - **Subscribed commands:** `StartAirConditioningV1`, `StopAirConditioningV1`, `GridOperatorPowerLimitationV1` (broadcast)
1040
+ - **Implement:** `handleStartAirConditioning` (mode is `Heating` or `Cooling`), `handleStopAirConditioning`, `handleGridOperatorPowerLimitation`.
1041
+ - **Publish helpers:**
1042
+ - `publishAirConditioningValues(applianceId, values)` — current operation mode and electrical consumption.
1043
+ - `publishAirConditioningTemperatures(applianceId, data)` — current and target temperatures per room.
1044
+
1045
+ ### EnergyManagerEnergyApp
1046
+
1047
+ `EnergyManagerEnergyApp` is the **counterpart** to the device integrations: instead of receiving commands, it produces forecasts. It is the recommended entry point when your app needs **multiple forecasters** wired together — it lazily creates each forecaster on first request, caches it, and disposes them all on shutdown.
1048
+
1049
+ **Constructor**
1050
+
1051
+ ```typescript
1052
+ new EnergyManagerEnergyApp({
1053
+ source: EnyoSourceEnum.Device,
1054
+ forecastConfig?: ForecastConfig, // applied to every forecaster unless overridden per call
1055
+ autoStopOnShutdown?: boolean, // default true
1056
+ });
1057
+ ```
1058
+
1059
+ **Lazy forecaster factories** — each returns a ready-to-use forecaster (history loaded, live listeners attached):
1060
+
1061
+ - `getPvProductionForecast(applianceId, config?)`
1062
+ - `getBatteryForecast(applianceId, config?)`
1063
+ - `getHomeConsumptionForecast(config?)` — system-wide, no appliance ID
1064
+ - `getEvChargingForecast(applianceId, config?)`
1065
+ - `getHeatpumpConsumptionForecast(applianceId, config?)`
1066
+ - `getHeatpumpDhwTemperatureForecast(applianceId, config?)`
1067
+
1068
+ **Lifecycle**
1069
+
1070
+ - `stop(): void` — disposes every cached forecaster.
1071
+
1072
+ ```typescript
1073
+ const manager = new EnergyManagerEnergyApp({ source: EnyoSourceEnum.Device });
1074
+
1075
+ const pv = await manager.getPvProductionForecast('inverter-1');
1076
+ const battery = await manager.getBatteryForecast('battery-1');
1077
+
1078
+ const pvForecast = pv.getForecast();
1079
+ const batteryForecast = battery.getForecast();
1080
+ ```
1081
+
1082
+ ## Forecasting
1083
+
1084
+ The forecasting module provides 24-hour predictions across the energy domains the SDK already understands (PV, battery, home consumption, EV charging, heatpump consumption, DHW temperature). Every forecaster follows the same lifecycle and shares the same configuration shape, so once you've used one you've used them all.
1085
+
1086
+ ### ✨ Common pattern
1087
+
1088
+ 1. Construct the forecaster with the SDK app, the appliance ID (where applicable), and an optional `ForecastConfig`.
1089
+ 2. `await initialize()` — pulls historical timeseries and subscribes to live data-bus updates.
1090
+ 3. Call `getForecast()` whenever you need a fresh prediction (cheap; uses in-memory state).
1091
+ 4. Optionally call `publishForecast()` to manually push to the data bus (or rely on auto-publish).
1092
+ 5. `dispose()` to release listeners on shutdown.
1093
+
1094
+ All forecasters compute **same-weekday recency-weighted averages** at 15-minute resolution and optionally smooth the first ~2 hours toward recent actuals. `PvProductionForecast` is the exception — sun position is weekday-independent, so it weights all days equally.
1095
+
1096
+ ### ForecastConfig
1097
+
1098
+ The shared configuration applied to every forecaster.
1099
+
1100
+ | Field | Type | Default | Purpose |
1101
+ |---|---|---|---|
1102
+ | `historyDays` | `number` | `7` | Lookback window for historical timeseries. |
1103
+ | `resolution` | `'1m' \| '15m'` | `'15m'` | Slot granularity for both history and forecast. |
1104
+ | `horizonHours` | `number` | `24` | How far ahead to forecast. |
1105
+ | `alignToRecentActuals` | `boolean` | `true` | Smoothly join the first ~2 forecast hours to recent observations. |
1106
+ | `publishToBus` | `boolean` | `true` | Auto-publish to the data bus on every refresh. |
1107
+
1108
+ > **Per-forecaster overrides:** `PvProductionForecast` defaults to **4 days** (sun-driven, recency matters most). `BatteryForecast`, `EvChargingForecast`, and `HomeConsumptionForecast` default to **14 days** (strongly weekday-cyclic).
1109
+
1110
+ All forecasters return a `BaseForecast<D>`-shaped object:
1111
+
1112
+ ```typescript
1113
+ {
1114
+ generatedAtIso: string; // ISO timestamp of computation
1115
+ data: {
1116
+ resolution: '1m' | '15m';
1117
+ entries: Array<{ startIso: string; /* per-class fields */ }>;
1118
+ };
1119
+ }
1120
+ ```
1121
+
1122
+ ### PvProductionForecast
1123
+
1124
+ Forecasts the AC power output of a single PV inverter.
1125
+
1126
+ ```typescript
1127
+ new PvProductionForecast(app, applianceId, { source: EnyoSourceEnum.Device, config? });
1128
+ ```
1129
+
1130
+ - **Output per slot:** `{ powerW: number; powerWh: number }`
1131
+ - **History default:** 4 days, all-day weighting.
1132
+ - **Live source:** `InverterValuesUpdateV1`.
1133
+
1134
+ ### BatteryForecast
1135
+
1136
+ Forecasts state-of-charge (and derived stored energy) for a single battery.
1137
+
1138
+ ```typescript
1139
+ new BatteryForecast(app, applianceId, {
1140
+ source: EnyoSourceEnum.Device,
1141
+ config?: { ratedCapacityWh?: number, ...ForecastConfig }
1142
+ });
1143
+ ```
1144
+
1145
+ - **Output per slot:** `{ socPercent: number; capacityWh: number }` (SoC clamped to `[0, 100]`).
1146
+ - **History default:** 14 days.
1147
+ - **Notable config:** `ratedCapacityWh` is auto-loaded from the appliance metadata if omitted.
1148
+ - **Live source:** `BatteryValuesUpdateV1`.
1149
+
1150
+ ### HomeConsumptionForecast
1151
+
1152
+ Forecasts total household electrical consumption — system-wide, no appliance ID.
1153
+
1154
+ ```typescript
1155
+ new HomeConsumptionForecast(app, { source: EnyoSourceEnum.Device, config? });
1156
+ ```
1157
+
1158
+ - **Output per slot:** `{ powerW: number; powerWh: number }`
1159
+ - **History default:** 14 days (household routines are strongly weekday-cyclic).
1160
+ - **Live source:** `AggregatedStateUpdateV1`.
1161
+
1162
+ ### EvChargingForecast
1163
+
1164
+ Forecasts EV charging power for a single charger.
1165
+
1166
+ ```typescript
1167
+ new EvChargingForecast(app, applianceId, { source: EnyoSourceEnum.Device, config? });
1168
+ ```
1169
+
1170
+ - **Output per slot:** `{ powerW: number; powerWh: number }`
1171
+ - **History default:** 14 days.
1172
+ - **Live source:** `ChargingMeterValuesUpdateV1`.
1173
+
1174
+ ### HeatpumpConsumptionForecast
1175
+
1176
+ Forecasts the electrical consumption of a heatpump (heating + cooling combined).
1177
+
1178
+ ```typescript
1179
+ new HeatpumpConsumptionForecast(app, applianceId, { source: EnyoSourceEnum.Device, config? });
1180
+ ```
1181
+
1182
+ - **Output per slot:** `{ powerW: number; powerWh: number }`
1183
+ - **History default:** 7 days.
1184
+ - **Live source:** `HeatpumpValuesUpdateV1`.
1185
+ - **Note:** does not adjust for forecasted weather; layer COP-based correction on top if you need that.
1186
+
1187
+ ### HeatpumpDhwTemperatureForecast
1188
+
1189
+ Forecasts the temperature of a heatpump's domestic-hot-water tank.
1190
+
1191
+ ```typescript
1192
+ new HeatpumpDhwTemperatureForecast(app, applianceId, {
1193
+ source: EnyoSourceEnum.Device,
1194
+ config?: { dhwTankIndex?: number, ...ForecastConfig }
1195
+ });
1196
+ ```
1197
+
1198
+ - **Output per slot:** `{ temperatureC: number }` (rounded to 0.1 °C).
1199
+ - **History default:** 7 days.
1200
+ - **Notable config:** `dhwTankIndex` selects a specific tank (zero-based); omit to average across all tanks.
1201
+ - **Live source:** heatpump temperature timeseries / live updates.
1202
+
1203
+ ### 🚀 Common usage example
1204
+
1205
+ ```typescript
1206
+ import {
1207
+ PvProductionForecast,
1208
+ BatteryForecast,
1209
+ EnyoSourceEnum,
1210
+ } from '@enyo-energy/energy-app-sdk';
1211
+
1212
+ const pv = new PvProductionForecast(energyApp, 'inverter-1', {
1213
+ source: EnyoSourceEnum.Device,
1214
+ });
1215
+ const battery = new BatteryForecast(energyApp, 'battery-1', {
1216
+ source: EnyoSourceEnum.Device,
1217
+ config: { ratedCapacityWh: 10_000 },
1218
+ });
1219
+
1220
+ await Promise.all([pv.initialize(), battery.initialize()]);
1221
+
1222
+ energyApp.useInterval().createInterval('15m', () => {
1223
+ const pvNext24h = pv.getForecast();
1224
+ const batteryNext24h = battery.getForecast();
1225
+ runDispatch(pvNext24h, batteryNext24h);
1226
+ });
1227
+
1228
+ energyApp.onShutdown(async () => {
1229
+ pv.dispose();
1230
+ battery.dispose();
1231
+ });
1232
+ ```
1233
+
1234
+ > **Tip:** if your app needs more than one forecaster, prefer [`EnergyManagerEnergyApp`](#energymanagerenergyapp) — it manages construction, caching, and disposal for you.
1235
+
862
1236
  ## Examples
863
1237
 
864
1238
  ### Basic Energy App
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnergyApp = void 0;
4
+ const version_js_1 = require("./version.cjs");
5
+ /**
6
+ * Concrete implementation of {@link EnyoEnergyAppSdk} that delegates every call
7
+ * to the runtime-provided `energyAppSdkInstance` global.
8
+ *
9
+ * This class is the canonical entry point for an energy app: an integrator
10
+ * instantiates one `EnergyApp`, then either consumes its `use*()` accessors
11
+ * directly or extends one of the specialized abstract integration classes
12
+ * (e.g. `HeatpumpIntegrationEnergyApp`) which build on top of this class.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const app = new EnergyApp();
17
+ * app.register((packageName, version, channel, deviceId) => {
18
+ * // perform initialization
19
+ * });
20
+ * ```
21
+ */
22
+ class EnergyApp {
23
+ energyAppSdk;
24
+ constructor() {
25
+ // in our runtime, there is an instance of energyAppSdk available which needs to be used here
26
+ // if the energyAppSdk is not available, instantiate a mocked version for local development
27
+ // @ts-ignore
28
+ if (energyAppSdkInstance === undefined || energyAppSdkInstance === null) {
29
+ throw new Error('Missing energyAppSdk instance');
30
+ }
31
+ else {
32
+ // @ts-ignore
33
+ this.energyAppSdk = energyAppSdkInstance;
34
+ }
35
+ }
36
+ isSystemOnline() {
37
+ return this.energyAppSdk.isSystemOnline();
38
+ }
39
+ /**
40
+ * Registers a listener that gets called when the network status changes.
41
+ * @param listener - Callback invoked with `true` when the system goes online, `false` when it goes offline
42
+ * @returns A unique listener ID that can be used to remove the listener
43
+ */
44
+ onNetworkStatusChanged(listener) {
45
+ return this.energyAppSdk.onNetworkStatusChanged(listener);
46
+ }
47
+ updateEnergyAppState(state) {
48
+ this.energyAppSdk.updateEnergyAppState(state);
49
+ }
50
+ register(callback) {
51
+ // This registers the package with the enyo system
52
+ this.energyAppSdk.register(callback);
53
+ }
54
+ onShutdown(callback) {
55
+ process.on('beforeExit', async (code) => {
56
+ await callback();
57
+ });
58
+ process.on('exit', async (code) => {
59
+ await callback();
60
+ });
61
+ }
62
+ useFetch() {
63
+ return this.energyAppSdk.useFetch();
64
+ }
65
+ useInterval() {
66
+ return this.energyAppSdk.useInterval();
67
+ }
68
+ useModbus() {
69
+ return this.energyAppSdk.useModbus();
70
+ }
71
+ useNetworkDevices() {
72
+ return this.energyAppSdk.useNetworkDevices();
73
+ }
74
+ useStorage() {
75
+ return this.energyAppSdk.useStorage();
76
+ }
77
+ useAppliances() {
78
+ return this.energyAppSdk.useAppliances();
79
+ }
80
+ useDataBus() {
81
+ return this.energyAppSdk.useDataBus();
82
+ }
83
+ useOcpp() {
84
+ return this.energyAppSdk.useOcpp();
85
+ }
86
+ useVehicle() {
87
+ return this.energyAppSdk.useVehicle();
88
+ }
89
+ useChargingCard() {
90
+ return this.energyAppSdk.useChargingCard();
91
+ }
92
+ useCharge() {
93
+ return this.energyAppSdk.useCharge();
94
+ }
95
+ useAuthentication() {
96
+ return this.energyAppSdk.useAuthentication();
97
+ }
98
+ useSettings() {
99
+ return this.energyAppSdk.useSettings();
100
+ }
101
+ useElectricityPrices() {
102
+ return this.energyAppSdk.useElectricityPrices();
103
+ }
104
+ useNotification() {
105
+ return this.energyAppSdk.useNotification();
106
+ }
107
+ useOnboarding() {
108
+ return this.energyAppSdk.useOnboarding();
109
+ }
110
+ /**
111
+ * Gets the Secret Manager API for retrieving secrets from the developer organization.
112
+ * Provides methods to fetch secrets that have been configured in the developer org's secret store.
113
+ * @returns The Secret Manager API instance
114
+ */
115
+ useSecretManager() {
116
+ return this.energyAppSdk.useSecretManager();
117
+ }
118
+ /**
119
+ * Gets the Location API for retrieving device location information.
120
+ * Provides methods to fetch location with varying levels of detail based on permissions.
121
+ * @returns The Location API instance
122
+ */
123
+ useLocation() {
124
+ return this.energyAppSdk.useLocation();
125
+ }
126
+ /**
127
+ * Gets the Timeseries API for querying historical energy data.
128
+ * Provides methods to retrieve aggregated timeseries data with 15-minute bucket granularity
129
+ * for various energy metrics including PV production, battery state, meter values, and grid power.
130
+ * @returns The Timeseries API instance
131
+ */
132
+ useTimeseries() {
133
+ return this.energyAppSdk.useTimeseries();
134
+ }
135
+ /**
136
+ * Gets the Energy Manager API for retrieving information about the active energy manager.
137
+ * Provides methods to check the current energy manager and its supported features.
138
+ * @returns The Energy Manager API instance
139
+ */
140
+ useEnergyManager() {
141
+ return this.energyAppSdk.useEnergyManager();
142
+ }
143
+ /**
144
+ * Gets the Electricity Tariff API for managing electricity tariffs.
145
+ * Provides methods to register, retrieve, and remove electricity tariffs
146
+ * used for energy pricing and consumption calculations.
147
+ * @returns The Electricity Tariff API instance
148
+ */
149
+ useElectricityTariff() {
150
+ return this.energyAppSdk.useElectricityTariff();
151
+ }
152
+ /**
153
+ * Gets the Weather Forecasting API for managing weather forecast providers and retrieving weather forecasts.
154
+ * Provides methods to register/deregister weather forecast providers, list available providers,
155
+ * and fetch weather forecasts by zip code or coordinates.
156
+ * @returns The Weather Forecasting API instance
157
+ */
158
+ useWeatherForecasting() {
159
+ return this.energyAppSdk.useWeatherForecasting();
160
+ }
161
+ /**
162
+ * Gets the PV Forecasting API for managing PV forecast providers and retrieving PV forecasts.
163
+ * Provides methods to register/deregister PV forecast providers and fetch power production forecasts.
164
+ * @returns The PV Forecasting API instance
165
+ */
166
+ usePvForecasting() {
167
+ return this.energyAppSdk.usePvForecasting();
168
+ }
169
+ /**
170
+ * Gets the PV System API for managing PV system registrations and configurations.
171
+ * Provides methods to register, retrieve, update, and remove PV systems
172
+ * including DC string orientations, peak power, associated appliances, and feature flags.
173
+ * @returns The PV System API instance
174
+ */
175
+ usePvSystem() {
176
+ return this.energyAppSdk.usePvSystem();
177
+ }
178
+ /**
179
+ * Gets the Sequence Generator API for generating unique sequential numbers per named sequence.
180
+ * Each sequence is identified by a string name and maintains its own independent counter.
181
+ * @returns The Sequence Generator API instance
182
+ */
183
+ useSequenceGenerator() {
184
+ return this.energyAppSdk.useSequenceGenerator();
185
+ }
186
+ /**
187
+ * Gets the Modbus RTU serial communication API.
188
+ * Provides methods to connect to Modbus RTU devices over serial ports
189
+ * and read/write registers using slave IDs.
190
+ * @returns The Modbus RTU API instance
191
+ */
192
+ useModbusRtu() {
193
+ return this.energyAppSdk.useModbusRtu();
194
+ }
195
+ /**
196
+ * Gets the EEbus API for SHIP/SPINE device communication.
197
+ * Provides device pairing and discovery, low-level SPINE data access,
198
+ * and high-level convenience methods for power management and device classification.
199
+ * Supports both appliance and energy manager roles for bidirectional communication.
200
+ * @returns The EEbus API instance
201
+ */
202
+ useEebus() {
203
+ return this.energyAppSdk.useEebus();
204
+ }
205
+ /**
206
+ * Gets the MQTT communication API.
207
+ * Provides methods to connect to the SDK-provided internal MQTT broker
208
+ * or external custom brokers for publishing and subscribing to topics.
209
+ * @returns The MQTT API instance
210
+ */
211
+ useMqtt() {
212
+ return this.energyAppSdk.useMqtt();
213
+ }
214
+ /**
215
+ * Gets the Diagnostics API for submitting energy manager diagnostics data.
216
+ * Allows energy managers to report current state, forecast, and control plan
217
+ * for internal processing and analysis.
218
+ * @returns The Diagnostics API instance
219
+ */
220
+ useDiagnostics() {
221
+ return this.energyAppSdk.useDiagnostics();
222
+ }
223
+ /**
224
+ * Gets the Learning Phase API for registering and tracking learning phases.
225
+ * Provides methods to register new learning phases, check their status,
226
+ * and retrieve learning phase history for the package or specific appliances.
227
+ * @returns The Learning Phase API instance
228
+ */
229
+ useLearningPhase() {
230
+ return this.energyAppSdk.useLearningPhase();
231
+ }
232
+ /**
233
+ * Gets the current SDK version.
234
+ * @returns The semantic version string of the SDK
235
+ */
236
+ getSdkVersion() {
237
+ return (0, version_js_1.getSdkVersion)();
238
+ }
239
+ }
240
+ exports.EnergyApp = EnergyApp;