@enyo-energy/energy-app-sdk 0.0.174 → 0.0.176
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/dist/cjs/implementations/appliance-command-forecast/appliance-command-forecast-validators.cjs +47 -0
- package/dist/cjs/implementations/appliance-command-forecast/appliance-command-forecast-validators.d.cts +23 -1
- package/dist/cjs/implementations/appliances/appliance-manager.cjs +27 -0
- package/dist/cjs/implementations/appliances/appliance-manager.d.cts +15 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/packages/energy-app-appliance-energy-manager-forecast.d.cts +21 -1
- package/dist/cjs/packages/energy-app-appliance.d.cts +43 -2
- package/dist/cjs/types/enyo-appliance-command-forecast.d.cts +76 -0
- package/dist/cjs/types/enyo-data-bus-value.d.cts +6 -0
- package/dist/cjs/types/enyo-heatpump-appliance.cjs +11 -0
- package/dist/cjs/types/enyo-heatpump-appliance.d.cts +15 -1
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/implementations/appliance-command-forecast/appliance-command-forecast-validators.d.ts +23 -1
- package/dist/implementations/appliance-command-forecast/appliance-command-forecast-validators.js +44 -0
- package/dist/implementations/appliances/appliance-manager.d.ts +15 -0
- package/dist/implementations/appliances/appliance-manager.js +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/packages/energy-app-appliance-energy-manager-forecast.d.ts +21 -1
- package/dist/packages/energy-app-appliance.d.ts +43 -2
- package/dist/types/enyo-appliance-command-forecast.d.ts +76 -0
- package/dist/types/enyo-data-bus-value.d.ts +6 -0
- package/dist/types/enyo-heatpump-appliance.d.ts +15 -1
- package/dist/types/enyo-heatpump-appliance.js +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,9 @@ exports.validateChargerSchedule = validateChargerSchedule;
|
|
|
8
8
|
exports.validateBatterySchedule = validateBatterySchedule;
|
|
9
9
|
exports.validateHeatpumpSchedule = validateHeatpumpSchedule;
|
|
10
10
|
exports.validateHeatpumpScheduleEntry = validateHeatpumpScheduleEntry;
|
|
11
|
+
exports.validateHeatingRodForecast = validateHeatingRodForecast;
|
|
12
|
+
exports.validateHeatingRodSchedule = validateHeatingRodSchedule;
|
|
13
|
+
exports.validateHeatingRodScheduleEntry = validateHeatingRodScheduleEntry;
|
|
11
14
|
const enyo_appliance_command_forecast_js_1 = require("../../types/enyo-appliance-command-forecast.cjs");
|
|
12
15
|
const enyo_data_bus_value_js_1 = require("../../types/enyo-data-bus-value.cjs");
|
|
13
16
|
/**
|
|
@@ -172,6 +175,50 @@ function validateHeatpumpScheduleEntry(entry, fieldName) {
|
|
|
172
175
|
validateBooleanField(entry.bufferTankBoostActive, `${fieldName}.bufferTankBoostActive`);
|
|
173
176
|
validateBooleanField(entry.availablePowerActive, `${fieldName}.availablePowerActive`);
|
|
174
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Validates a {@link HeatingRodForecast}. Throws on the first violation —
|
|
180
|
+
* the error message names the offending field / index.
|
|
181
|
+
*
|
|
182
|
+
* The forecast carries a single relative schedule; every entry is
|
|
183
|
+
* validated by {@link validateHeatingRodScheduleEntry}.
|
|
184
|
+
*/
|
|
185
|
+
function validateHeatingRodForecast(forecast) {
|
|
186
|
+
if (!forecast || typeof forecast !== 'object') {
|
|
187
|
+
throw new ApplianceCommandForecastValidationError('HeatingRodForecast must be an object.');
|
|
188
|
+
}
|
|
189
|
+
validateMetadata(forecast);
|
|
190
|
+
validateHeatingRodSchedule(forecast.relativeSchedule, forecast.resolution);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Validates a heating rod relative schedule (the schedule used by
|
|
194
|
+
* {@link HeatingRodForecast.relativeSchedule}). Enforces that the
|
|
195
|
+
* schedule is non-empty, starts at `seconds = 0`, has entries spaced by
|
|
196
|
+
* exactly `resolution`, and that every per-entry value falls in the
|
|
197
|
+
* plausible range documented on {@link HeatingRodForecastScheduleEntry}.
|
|
198
|
+
*/
|
|
199
|
+
function validateHeatingRodSchedule(entries, resolution) {
|
|
200
|
+
const stepSeconds = resolveResolutionSeconds(resolution);
|
|
201
|
+
validateNonEmptySchedule(entries, 'relativeSchedule');
|
|
202
|
+
for (let i = 0; i < entries.length; i++) {
|
|
203
|
+
validateHeatingRodScheduleEntry(entries[i], `relativeSchedule[${i}]`);
|
|
204
|
+
}
|
|
205
|
+
validateFirstEntryStartsAtZero(entries[0].seconds, 'relativeSchedule');
|
|
206
|
+
validateSecondsMatchResolution(entries.map((e) => e.seconds), stepSeconds, 'relativeSchedule');
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Validates a single {@link HeatingRodForecastScheduleEntry}. Used by
|
|
210
|
+
* {@link validateHeatingRodSchedule} and exposed for callers that build
|
|
211
|
+
* entries incrementally.
|
|
212
|
+
*/
|
|
213
|
+
function validateHeatingRodScheduleEntry(entry, fieldName) {
|
|
214
|
+
validateSecondsField(entry.seconds, `${fieldName}.seconds`);
|
|
215
|
+
if (entry.powerW !== undefined) {
|
|
216
|
+
validatePowerW(entry.powerW, `${fieldName}.powerW`);
|
|
217
|
+
}
|
|
218
|
+
validateTemperatureField(entry.temperatureC, `${fieldName}.temperatureC`);
|
|
219
|
+
validateBooleanField(entry.heatingActive, `${fieldName}.heatingActive`);
|
|
220
|
+
validateBooleanField(entry.availablePowerActive, `${fieldName}.availablePowerActive`);
|
|
221
|
+
}
|
|
175
222
|
function validateMetadata(forecast) {
|
|
176
223
|
if (!(forecast.resolution in RESOLUTION_SECONDS)) {
|
|
177
224
|
throw new ApplianceCommandForecastValidationError(`resolution is invalid: ${forecast.resolution}. Allowed values: ${Object.values(enyo_appliance_command_forecast_js_1.ApplianceForecastResolutionEnum).join(', ')}.`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApplianceForecastResolutionEnum, BatteryCommandForecast, BatteryCommandForecastScheduleEntry, ChargerForecast, ChargerForecastScheduleEntry, HeatpumpForecast, HeatpumpForecastScheduleEntry } from '../../types/enyo-appliance-command-forecast.cjs';
|
|
1
|
+
import { ApplianceForecastResolutionEnum, BatteryCommandForecast, BatteryCommandForecastScheduleEntry, ChargerForecast, ChargerForecastScheduleEntry, HeatingRodForecast, HeatingRodForecastScheduleEntry, HeatpumpForecast, HeatpumpForecastScheduleEntry } from '../../types/enyo-appliance-command-forecast.cjs';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown when a forecast payload passed to one of the validators (or to
|
|
4
4
|
* {@link EnergyAppApplianceEnergyManagerForecast.publishChargerForecast}
|
|
@@ -65,3 +65,25 @@ export declare function validateHeatpumpSchedule(entries: HeatpumpForecastSchedu
|
|
|
65
65
|
* entries incrementally.
|
|
66
66
|
*/
|
|
67
67
|
export declare function validateHeatpumpScheduleEntry(entry: HeatpumpForecastScheduleEntry, fieldName: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Validates a {@link HeatingRodForecast}. Throws on the first violation —
|
|
70
|
+
* the error message names the offending field / index.
|
|
71
|
+
*
|
|
72
|
+
* The forecast carries a single relative schedule; every entry is
|
|
73
|
+
* validated by {@link validateHeatingRodScheduleEntry}.
|
|
74
|
+
*/
|
|
75
|
+
export declare function validateHeatingRodForecast(forecast: HeatingRodForecast): void;
|
|
76
|
+
/**
|
|
77
|
+
* Validates a heating rod relative schedule (the schedule used by
|
|
78
|
+
* {@link HeatingRodForecast.relativeSchedule}). Enforces that the
|
|
79
|
+
* schedule is non-empty, starts at `seconds = 0`, has entries spaced by
|
|
80
|
+
* exactly `resolution`, and that every per-entry value falls in the
|
|
81
|
+
* plausible range documented on {@link HeatingRodForecastScheduleEntry}.
|
|
82
|
+
*/
|
|
83
|
+
export declare function validateHeatingRodSchedule(entries: HeatingRodForecastScheduleEntry[], resolution: ApplianceForecastResolutionEnum): void;
|
|
84
|
+
/**
|
|
85
|
+
* Validates a single {@link HeatingRodForecastScheduleEntry}. Used by
|
|
86
|
+
* {@link validateHeatingRodSchedule} and exposed for callers that build
|
|
87
|
+
* entries incrementally.
|
|
88
|
+
*/
|
|
89
|
+
export declare function validateHeatingRodScheduleEntry(entry: HeatingRodForecastScheduleEntry, fieldName: string): void;
|
|
@@ -300,6 +300,33 @@ class ApplianceManager {
|
|
|
300
300
|
});
|
|
301
301
|
this.listenerIds.push(removedListenerId);
|
|
302
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Subscribes to newly-created appliances. Fires only when an appliance is
|
|
305
|
+
* first created, not on subsequent updates. The optional
|
|
306
|
+
* {@link EnyoApplianceCreatedFilter filter} controls scope (own package,
|
|
307
|
+
* all appliances, or only externally-created) and category — `scope: 'all'`
|
|
308
|
+
* and `scope: 'external'` require the `AllAppliances` permission.
|
|
309
|
+
*
|
|
310
|
+
* @param listener - Invoked with each newly-created appliance
|
|
311
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
312
|
+
* @returns An unsubscribe function. Any still-active subscription is also
|
|
313
|
+
* cleaned up automatically on {@link dispose}.
|
|
314
|
+
* @throws {ApplianceManagerDisposedError} when called after {@link dispose}
|
|
315
|
+
*/
|
|
316
|
+
onApplianceCreated(listener, filter) {
|
|
317
|
+
this.throwIfDisposed();
|
|
318
|
+
const applianceService = this.energyApp.useAppliances();
|
|
319
|
+
const listenerId = applianceService.listenForApplianceCreated((appliance) => {
|
|
320
|
+
if (this.disposed)
|
|
321
|
+
return;
|
|
322
|
+
return listener(appliance);
|
|
323
|
+
}, filter);
|
|
324
|
+
this.listenerIds.push(listenerId);
|
|
325
|
+
return () => {
|
|
326
|
+
applianceService.removeListener(listenerId);
|
|
327
|
+
this.listenerIds = this.listenerIds.filter(id => id !== listenerId);
|
|
328
|
+
};
|
|
329
|
+
}
|
|
303
330
|
/**
|
|
304
331
|
* Clears the internal cache without touching the SDK.
|
|
305
332
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EnergyApp } from "../../index.cjs";
|
|
2
2
|
import type { EnyoNetworkDevice } from "../../types/enyo-network-device.cjs";
|
|
3
3
|
import { EnyoAppliance, EnyoApplianceAvailableFeaturesEnum, EnyoApplianceConnectionType, EnyoApplianceMetadata, EnyoApplianceName, EnyoApplianceStateEnum, EnyoApplianceTopology, EnyoApplianceTypeEnum } from "../../types/enyo-appliance.cjs";
|
|
4
|
+
import type { EnyoApplianceCreatedFilter } from "../../packages/energy-app-appliance.cjs";
|
|
4
5
|
import type { EnyoChargerApplianceMetadata } from "../../types/enyo-charger-appliance.cjs";
|
|
5
6
|
import type { EnyoHeatpumpApplianceMetadata } from "../../types/enyo-heatpump-appliance.cjs";
|
|
6
7
|
import type { EnyoBatteryApplianceMetadata } from "../../types/enyo-battery-appliance.cjs";
|
|
@@ -203,6 +204,20 @@ export declare class ApplianceManager {
|
|
|
203
204
|
* Subscribes to appliance update and removal events to keep the cache in sync.
|
|
204
205
|
*/
|
|
205
206
|
private subscribeToEvents;
|
|
207
|
+
/**
|
|
208
|
+
* Subscribes to newly-created appliances. Fires only when an appliance is
|
|
209
|
+
* first created, not on subsequent updates. The optional
|
|
210
|
+
* {@link EnyoApplianceCreatedFilter filter} controls scope (own package,
|
|
211
|
+
* all appliances, or only externally-created) and category — `scope: 'all'`
|
|
212
|
+
* and `scope: 'external'` require the `AllAppliances` permission.
|
|
213
|
+
*
|
|
214
|
+
* @param listener - Invoked with each newly-created appliance
|
|
215
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
216
|
+
* @returns An unsubscribe function. Any still-active subscription is also
|
|
217
|
+
* cleaned up automatically on {@link dispose}.
|
|
218
|
+
* @throws {ApplianceManagerDisposedError} when called after {@link dispose}
|
|
219
|
+
*/
|
|
220
|
+
onApplianceCreated(listener: (appliance: EnyoAppliance) => void | Promise<void>, filter?: EnyoApplianceCreatedFilter): () => void;
|
|
206
221
|
/**
|
|
207
222
|
* Clears the internal cache without touching the SDK.
|
|
208
223
|
*/
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __exportStar(require("./types/enyo-energy-prices.cjs"), exports);
|
|
|
29
29
|
__exportStar(require("./types/enyo-notification.cjs"), exports);
|
|
30
30
|
__exportStar(require("./types/enyo-secret-manager.cjs"), exports);
|
|
31
31
|
__exportStar(require("./types/enyo-location.cjs"), exports);
|
|
32
|
+
__exportStar(require("./types/enyo-appliance.cjs"), exports);
|
|
33
|
+
__exportStar(require("./packages/energy-app-appliance.cjs"), exports);
|
|
32
34
|
__exportStar(require("./implementations/appliances/appliance-manager.cjs"), exports);
|
|
33
35
|
__exportStar(require("./implementations/appliances/identifier-strategies.cjs"), exports);
|
|
34
36
|
__exportStar(require("./implementations/network-devices/network-access-guard.cjs"), exports);
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -13,6 +13,8 @@ export * from './types/enyo-energy-prices.cjs';
|
|
|
13
13
|
export * from './types/enyo-notification.cjs';
|
|
14
14
|
export * from './types/enyo-secret-manager.cjs';
|
|
15
15
|
export * from './types/enyo-location.cjs';
|
|
16
|
+
export * from './types/enyo-appliance.cjs';
|
|
17
|
+
export * from './packages/energy-app-appliance.cjs';
|
|
16
18
|
export * from './implementations/appliances/appliance-manager.cjs';
|
|
17
19
|
export * from './implementations/appliances/identifier-strategies.cjs';
|
|
18
20
|
export * from './implementations/network-devices/network-access-guard.cjs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BatteryCommandForecast, ChargerForecast, HeatpumpForecast } from '../types/enyo-appliance-command-forecast.cjs';
|
|
1
|
+
import { BatteryCommandForecast, ChargerForecast, HeatingRodForecast, HeatpumpForecast } from '../types/enyo-appliance-command-forecast.cjs';
|
|
2
2
|
/**
|
|
3
3
|
* SDK accessor for the **Appliance Energy-Manager Forecast** package.
|
|
4
4
|
*
|
|
@@ -16,6 +16,10 @@ import { BatteryCommandForecast, ChargerForecast, HeatpumpForecast } from '../ty
|
|
|
16
16
|
* carry the forecasted DHW / room / buffer-tank temperatures together
|
|
17
17
|
* with planned boost / pre-heating flags and the available-power
|
|
18
18
|
* announcement at each slot ({@link HeatpumpForecast}).
|
|
19
|
+
* - **Heating rods** — a single relative schedule whose entries carry
|
|
20
|
+
* the forecasted target temperature together with the planned heating
|
|
21
|
+
* flag and the available-power announcement at each slot
|
|
22
|
+
* ({@link HeatingRodForecast}).
|
|
19
23
|
*
|
|
20
24
|
* Every forecast optionally carries
|
|
21
25
|
* {@link ApplianceForecastEstimatedSavings} so downstream consumers can
|
|
@@ -85,4 +89,20 @@ export interface EnergyAppApplianceEnergyManagerForecast {
|
|
|
85
89
|
* is malformed.
|
|
86
90
|
*/
|
|
87
91
|
publishHeatpumpForecast(applianceId: string, forecast: HeatpumpForecast): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Publishes the command-plan forecast for a heating rod (immersion
|
|
94
|
+
* element). The forecast carries a single relative schedule whose
|
|
95
|
+
* entries pack the forecasted target temperature together with the
|
|
96
|
+
* planned heating flag and the available-power announcement at each
|
|
97
|
+
* slot.
|
|
98
|
+
*
|
|
99
|
+
* Validates {@link forecast} against the invariants documented on
|
|
100
|
+
* {@link HeatingRodForecast}.
|
|
101
|
+
*
|
|
102
|
+
* @param applianceId - The heating rod appliance the forecast applies to.
|
|
103
|
+
* @param forecast - The command-plan forecast and its metadata.
|
|
104
|
+
* @throws {ApplianceCommandForecastValidationError} If the forecast
|
|
105
|
+
* is malformed.
|
|
106
|
+
*/
|
|
107
|
+
publishHeatingRodForecast(applianceId: string, forecast: HeatingRodForecast): Promise<void>;
|
|
88
108
|
}
|
|
@@ -1,4 +1,30 @@
|
|
|
1
|
-
import { EnyoAppliance } from "../types/enyo-appliance.cjs";
|
|
1
|
+
import { EnyoAppliance, EnyoApplianceTypeEnum } from "../types/enyo-appliance.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Ownership scope for an appliance-created subscription.
|
|
4
|
+
* - `'own'`: appliances created by your own package.
|
|
5
|
+
* - `'all'`: every appliance created system-wide.
|
|
6
|
+
* - `'external'`: only appliances created by *other* packages (all minus own).
|
|
7
|
+
*/
|
|
8
|
+
export type EnyoApplianceCreatedScope = 'own' | 'all' | 'external';
|
|
9
|
+
/**
|
|
10
|
+
* Optional filter controlling which appliance-created events a listener receives.
|
|
11
|
+
* When omitted, defaults to `scope: 'own'` and no category restriction.
|
|
12
|
+
*/
|
|
13
|
+
export interface EnyoApplianceCreatedFilter {
|
|
14
|
+
/**
|
|
15
|
+
* Ownership scope of the subscription:
|
|
16
|
+
* - `'own'` (default): appliances created by your own package.
|
|
17
|
+
* - `'all'`: every appliance created system-wide. Requires the `AllAppliances` permission.
|
|
18
|
+
* - `'external'`: only appliances created by *other* packages (all minus own). Requires the `AllAppliances` permission.
|
|
19
|
+
*/
|
|
20
|
+
scope?: EnyoApplianceCreatedScope;
|
|
21
|
+
/**
|
|
22
|
+
* When set, the listener only fires for appliances whose
|
|
23
|
+
* {@link EnyoApplianceTypeEnum category} is included in this list. When
|
|
24
|
+
* omitted, appliances of every category are delivered.
|
|
25
|
+
*/
|
|
26
|
+
types?: EnyoApplianceTypeEnum[];
|
|
27
|
+
}
|
|
2
28
|
/**
|
|
3
29
|
* Interface for managing appliances in enyo packages.
|
|
4
30
|
* Provides CRUD operations for appliance registration and management.
|
|
@@ -26,9 +52,24 @@ export interface EnergyAppAppliance {
|
|
|
26
52
|
* @returns A unique listener ID that can be used to remove the listener
|
|
27
53
|
*/
|
|
28
54
|
listenForApplianceRemoved: (listener: (applianceId: string) => void | Promise<void>) => string;
|
|
55
|
+
/**
|
|
56
|
+
* Listen for newly-created appliances. Fires only when an appliance is
|
|
57
|
+
* first created — not on subsequent updates (use
|
|
58
|
+
* {@link listenForApplianceUpdated} for those).
|
|
59
|
+
*
|
|
60
|
+
* The optional {@link EnyoApplianceCreatedFilter filter} controls scope and
|
|
61
|
+
* category: by default only your own package's creations are delivered;
|
|
62
|
+
* `scope: 'all'` and `scope: 'external'` observe appliances created by other
|
|
63
|
+
* packages and require the `AllAppliances` permission.
|
|
64
|
+
*
|
|
65
|
+
* @param listener - Callback invoked with each newly-created appliance
|
|
66
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
67
|
+
* @returns A unique listener ID that can be used to remove the listener
|
|
68
|
+
*/
|
|
69
|
+
listenForApplianceCreated: (listener: (appliance: EnyoAppliance) => void | Promise<void>, filter?: EnyoApplianceCreatedFilter) => string;
|
|
29
70
|
/**
|
|
30
71
|
* Removes a previously registered listener.
|
|
31
|
-
* @param listenerId - The ID returned by listenForApplianceUpdated or
|
|
72
|
+
* @param listenerId - The ID returned by listenForApplianceUpdated, listenForApplianceRemoved, or listenForApplianceCreated
|
|
32
73
|
*/
|
|
33
74
|
removeListener: (listenerId: string) => void;
|
|
34
75
|
}
|
|
@@ -354,3 +354,79 @@ export interface HeatpumpForecast extends ApplianceForecastMetadata {
|
|
|
354
354
|
*/
|
|
355
355
|
relativeSchedule: HeatpumpForecastScheduleEntry[];
|
|
356
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* One entry of a heating rod's relative schedule.
|
|
359
|
+
*
|
|
360
|
+
* The entry packs every per-slot piece of information the energy-manager
|
|
361
|
+
* forecast carries for a heating rod (immersion element): the forecasted
|
|
362
|
+
* target temperature, the planned heating flag, and the available-power
|
|
363
|
+
* announcement. The setpoint becomes active {@link seconds} after the
|
|
364
|
+
* forecast becomes effective and stays active until the next entry's
|
|
365
|
+
* `seconds` is reached.
|
|
366
|
+
*
|
|
367
|
+
* Every field other than {@link seconds} is optional — an entry may
|
|
368
|
+
* describe only the temperature, only the flag, only power, or any
|
|
369
|
+
* combination. A field that is omitted carries no information for that
|
|
370
|
+
* slot (it is **not** "set to zero / false"); the previous entry's value
|
|
371
|
+
* should be treated as still in effect.
|
|
372
|
+
*/
|
|
373
|
+
export interface HeatingRodForecastScheduleEntry {
|
|
374
|
+
/**
|
|
375
|
+
* Seconds from the moment the forecast becomes effective at which
|
|
376
|
+
* this entry becomes active. `0` for the first entry; subsequent
|
|
377
|
+
* entries must be strictly increasing.
|
|
378
|
+
*/
|
|
379
|
+
seconds: number;
|
|
380
|
+
/**
|
|
381
|
+
* Planned available electrical power in Watts the energy manager
|
|
382
|
+
* intends to make available to the heating rod during this slot. The
|
|
383
|
+
* heating rod is free to consume up to this value — and free to
|
|
384
|
+
* consume less if it cannot use it all. Non-negative when present.
|
|
385
|
+
*/
|
|
386
|
+
powerW?: number;
|
|
387
|
+
/**
|
|
388
|
+
* Forecasted target temperature in °C at this slot (the temperature
|
|
389
|
+
* the heating rod is driving its tank / buffer toward). Plausible
|
|
390
|
+
* range: [-50, 150].
|
|
391
|
+
*/
|
|
392
|
+
temperatureC?: number;
|
|
393
|
+
/**
|
|
394
|
+
* Whether the heating rod is planned to be actively heating during
|
|
395
|
+
* this slot — `true` while the publisher intends to drive the tank
|
|
396
|
+
* up, `false` (or omitted) otherwise.
|
|
397
|
+
*/
|
|
398
|
+
heatingActive?: boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Whether the publisher is announcing available power for this slot
|
|
401
|
+
* — `true` when the energy-manager decision for the slot is
|
|
402
|
+
* "available power", meaning {@link powerW} doubles as the
|
|
403
|
+
* available-power offer to the heating rod (the heating rod is free
|
|
404
|
+
* to consume up to that value), `false` (or omitted) otherwise.
|
|
405
|
+
*
|
|
406
|
+
* This flag is independent of {@link heatingActive} and may coexist
|
|
407
|
+
* with it when the publisher offers available power while a heating
|
|
408
|
+
* window is also planned.
|
|
409
|
+
*/
|
|
410
|
+
availablePowerActive?: boolean;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Forecasted command plan for a heating rod appliance, published via
|
|
414
|
+
* {@link EnergyAppApplianceEnergyManagerForecast.publishHeatingRodForecast}.
|
|
415
|
+
*
|
|
416
|
+
* A heating rod forecast is a **single** relative schedule whose entries
|
|
417
|
+
* carry every per-slot piece of information at once (forecasted target
|
|
418
|
+
* temperature, heating flag, available-power announcement). One entry per
|
|
419
|
+
* slot keeps the temperature trajectory and the heating decisions aligned
|
|
420
|
+
* by construction.
|
|
421
|
+
*
|
|
422
|
+
* The schedule must be sorted ascending by `seconds` and start at
|
|
423
|
+
* `seconds = 0` so the appliance has an authoritative "right now" entry.
|
|
424
|
+
*/
|
|
425
|
+
export interface HeatingRodForecast extends ApplianceForecastMetadata {
|
|
426
|
+
/**
|
|
427
|
+
* Relative schedule of forecast entries. Sorted ascending by
|
|
428
|
+
* `seconds`, starting at `seconds = 0`. Must contain at least one
|
|
429
|
+
* entry.
|
|
430
|
+
*/
|
|
431
|
+
relativeSchedule: HeatingRodForecastScheduleEntry[];
|
|
432
|
+
}
|
|
@@ -625,6 +625,12 @@ export interface EnyoDataBusAggregatedStateValuesV1 extends EnyoDataBusMessage {
|
|
|
625
625
|
gridPowerPhase2W?: number;
|
|
626
626
|
/** Grid power on phase L3 (in Watt). Negative: grid feed in, positive: grid consumption */
|
|
627
627
|
gridPowerPhase3W?: number;
|
|
628
|
+
/**
|
|
629
|
+
* Time resolution of the aggregated grid power values (e.g. the sampling
|
|
630
|
+
* interval the `gridPowerW` / `gridPowerPhaseXW` values were measured at).
|
|
631
|
+
* Use `'dynamic'` when the values are forwarded as events occur.
|
|
632
|
+
*/
|
|
633
|
+
gridPowerResolution: EnyoDataBusMessageResolution;
|
|
628
634
|
gridConsumptionW?: number;
|
|
629
635
|
gridFeedInW?: number;
|
|
630
636
|
homeConsumptionW?: number;
|
|
@@ -19,12 +19,23 @@ var EnyoHeatpumpApplianceAvailableFeaturesEnum;
|
|
|
19
19
|
EnyoHeatpumpApplianceAvailableFeaturesEnum["Power"] = "Power";
|
|
20
20
|
/** If the heatpump is ready for calibration (i.e. has all prerequisites in place to start a calibration run) */
|
|
21
21
|
EnyoHeatpumpApplianceAvailableFeaturesEnum["ReadyForCalibration"] = "ReadyForCalibration";
|
|
22
|
+
/** If the heatpump supports cooling (reversible heatpump) */
|
|
23
|
+
EnyoHeatpumpApplianceAvailableFeaturesEnum["Cooling"] = "Cooling";
|
|
22
24
|
})(EnyoHeatpumpApplianceAvailableFeaturesEnum || (exports.EnyoHeatpumpApplianceAvailableFeaturesEnum = EnyoHeatpumpApplianceAvailableFeaturesEnum = {}));
|
|
25
|
+
/**
|
|
26
|
+
* The current operating state of a heatpump.
|
|
27
|
+
*/
|
|
23
28
|
var EnyoHeatpumpApplianceModeEnum;
|
|
24
29
|
(function (EnyoHeatpumpApplianceModeEnum) {
|
|
30
|
+
/** The heatpump is idle (not actively heating, cooling, or producing hot water) */
|
|
25
31
|
EnyoHeatpumpApplianceModeEnum["Idle"] = "Idle";
|
|
32
|
+
/** The heatpump is actively heating */
|
|
26
33
|
EnyoHeatpumpApplianceModeEnum["Heating"] = "Heating";
|
|
34
|
+
/** The heatpump is actively cooling (reversible heatpumps only) */
|
|
35
|
+
EnyoHeatpumpApplianceModeEnum["Cooling"] = "Cooling";
|
|
36
|
+
/** The heatpump is actively producing domestic hot water */
|
|
27
37
|
EnyoHeatpumpApplianceModeEnum["DomesticHotWater"] = "DomesticHotWater";
|
|
38
|
+
/** The heatpump is running in emergency operation */
|
|
28
39
|
EnyoHeatpumpApplianceModeEnum["EmergencyOperation"] = "EmergencyOperation";
|
|
29
40
|
})(EnyoHeatpumpApplianceModeEnum || (exports.EnyoHeatpumpApplianceModeEnum = EnyoHeatpumpApplianceModeEnum = {}));
|
|
30
41
|
/**
|
|
@@ -14,12 +14,23 @@ export declare enum EnyoHeatpumpApplianceAvailableFeaturesEnum {
|
|
|
14
14
|
/** If the heatpump reports power values (e.g. electrical power consumption in watts) */
|
|
15
15
|
Power = "Power",
|
|
16
16
|
/** If the heatpump is ready for calibration (i.e. has all prerequisites in place to start a calibration run) */
|
|
17
|
-
ReadyForCalibration = "ReadyForCalibration"
|
|
17
|
+
ReadyForCalibration = "ReadyForCalibration",
|
|
18
|
+
/** If the heatpump supports cooling (reversible heatpump) */
|
|
19
|
+
Cooling = "Cooling"
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The current operating state of a heatpump.
|
|
23
|
+
*/
|
|
19
24
|
export declare enum EnyoHeatpumpApplianceModeEnum {
|
|
25
|
+
/** The heatpump is idle (not actively heating, cooling, or producing hot water) */
|
|
20
26
|
Idle = "Idle",
|
|
27
|
+
/** The heatpump is actively heating */
|
|
21
28
|
Heating = "Heating",
|
|
29
|
+
/** The heatpump is actively cooling (reversible heatpumps only) */
|
|
30
|
+
Cooling = "Cooling",
|
|
31
|
+
/** The heatpump is actively producing domestic hot water */
|
|
22
32
|
DomesticHotWater = "DomesticHotWater",
|
|
33
|
+
/** The heatpump is running in emergency operation */
|
|
23
34
|
EmergencyOperation = "EmergencyOperation"
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
@@ -51,7 +62,10 @@ export interface EnyoHeatpumpApplianceCompressor {
|
|
|
51
62
|
}
|
|
52
63
|
export interface EnyoHeatpumpApplianceHeatingCircuit {
|
|
53
64
|
index: number;
|
|
65
|
+
/** Target room temperature setpoint when heating (in °C) */
|
|
54
66
|
targetRoomTemperatureC?: number;
|
|
67
|
+
/** Target room temperature setpoint when cooling (in °C). Only meaningful for cooling-capable heatpumps. */
|
|
68
|
+
targetCoolingRoomTemperatureC?: number;
|
|
55
69
|
}
|
|
56
70
|
export interface EnyoHeatpumpApplianceMetadata {
|
|
57
71
|
availableFeatures: EnyoHeatpumpApplianceAvailableFeaturesEnum[];
|
package/dist/cjs/version.cjs
CHANGED
|
@@ -9,7 +9,7 @@ exports.getSdkVersion = getSdkVersion;
|
|
|
9
9
|
/**
|
|
10
10
|
* Current version of the enyo Energy App SDK.
|
|
11
11
|
*/
|
|
12
|
-
exports.SDK_VERSION = '0.0.
|
|
12
|
+
exports.SDK_VERSION = '0.0.176';
|
|
13
13
|
/**
|
|
14
14
|
* Gets the current SDK version.
|
|
15
15
|
* @returns The semantic version string of the SDK
|
package/dist/cjs/version.d.cts
CHANGED
package/dist/implementations/appliance-command-forecast/appliance-command-forecast-validators.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApplianceForecastResolutionEnum, BatteryCommandForecast, BatteryCommandForecastScheduleEntry, ChargerForecast, ChargerForecastScheduleEntry, HeatpumpForecast, HeatpumpForecastScheduleEntry } from '../../types/enyo-appliance-command-forecast.js';
|
|
1
|
+
import { ApplianceForecastResolutionEnum, BatteryCommandForecast, BatteryCommandForecastScheduleEntry, ChargerForecast, ChargerForecastScheduleEntry, HeatingRodForecast, HeatingRodForecastScheduleEntry, HeatpumpForecast, HeatpumpForecastScheduleEntry } from '../../types/enyo-appliance-command-forecast.js';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown when a forecast payload passed to one of the validators (or to
|
|
4
4
|
* {@link EnergyAppApplianceEnergyManagerForecast.publishChargerForecast}
|
|
@@ -65,3 +65,25 @@ export declare function validateHeatpumpSchedule(entries: HeatpumpForecastSchedu
|
|
|
65
65
|
* entries incrementally.
|
|
66
66
|
*/
|
|
67
67
|
export declare function validateHeatpumpScheduleEntry(entry: HeatpumpForecastScheduleEntry, fieldName: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Validates a {@link HeatingRodForecast}. Throws on the first violation —
|
|
70
|
+
* the error message names the offending field / index.
|
|
71
|
+
*
|
|
72
|
+
* The forecast carries a single relative schedule; every entry is
|
|
73
|
+
* validated by {@link validateHeatingRodScheduleEntry}.
|
|
74
|
+
*/
|
|
75
|
+
export declare function validateHeatingRodForecast(forecast: HeatingRodForecast): void;
|
|
76
|
+
/**
|
|
77
|
+
* Validates a heating rod relative schedule (the schedule used by
|
|
78
|
+
* {@link HeatingRodForecast.relativeSchedule}). Enforces that the
|
|
79
|
+
* schedule is non-empty, starts at `seconds = 0`, has entries spaced by
|
|
80
|
+
* exactly `resolution`, and that every per-entry value falls in the
|
|
81
|
+
* plausible range documented on {@link HeatingRodForecastScheduleEntry}.
|
|
82
|
+
*/
|
|
83
|
+
export declare function validateHeatingRodSchedule(entries: HeatingRodForecastScheduleEntry[], resolution: ApplianceForecastResolutionEnum): void;
|
|
84
|
+
/**
|
|
85
|
+
* Validates a single {@link HeatingRodForecastScheduleEntry}. Used by
|
|
86
|
+
* {@link validateHeatingRodSchedule} and exposed for callers that build
|
|
87
|
+
* entries incrementally.
|
|
88
|
+
*/
|
|
89
|
+
export declare function validateHeatingRodScheduleEntry(entry: HeatingRodForecastScheduleEntry, fieldName: string): void;
|
package/dist/implementations/appliance-command-forecast/appliance-command-forecast-validators.js
CHANGED
|
@@ -161,6 +161,50 @@ export function validateHeatpumpScheduleEntry(entry, fieldName) {
|
|
|
161
161
|
validateBooleanField(entry.bufferTankBoostActive, `${fieldName}.bufferTankBoostActive`);
|
|
162
162
|
validateBooleanField(entry.availablePowerActive, `${fieldName}.availablePowerActive`);
|
|
163
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Validates a {@link HeatingRodForecast}. Throws on the first violation —
|
|
166
|
+
* the error message names the offending field / index.
|
|
167
|
+
*
|
|
168
|
+
* The forecast carries a single relative schedule; every entry is
|
|
169
|
+
* validated by {@link validateHeatingRodScheduleEntry}.
|
|
170
|
+
*/
|
|
171
|
+
export function validateHeatingRodForecast(forecast) {
|
|
172
|
+
if (!forecast || typeof forecast !== 'object') {
|
|
173
|
+
throw new ApplianceCommandForecastValidationError('HeatingRodForecast must be an object.');
|
|
174
|
+
}
|
|
175
|
+
validateMetadata(forecast);
|
|
176
|
+
validateHeatingRodSchedule(forecast.relativeSchedule, forecast.resolution);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Validates a heating rod relative schedule (the schedule used by
|
|
180
|
+
* {@link HeatingRodForecast.relativeSchedule}). Enforces that the
|
|
181
|
+
* schedule is non-empty, starts at `seconds = 0`, has entries spaced by
|
|
182
|
+
* exactly `resolution`, and that every per-entry value falls in the
|
|
183
|
+
* plausible range documented on {@link HeatingRodForecastScheduleEntry}.
|
|
184
|
+
*/
|
|
185
|
+
export function validateHeatingRodSchedule(entries, resolution) {
|
|
186
|
+
const stepSeconds = resolveResolutionSeconds(resolution);
|
|
187
|
+
validateNonEmptySchedule(entries, 'relativeSchedule');
|
|
188
|
+
for (let i = 0; i < entries.length; i++) {
|
|
189
|
+
validateHeatingRodScheduleEntry(entries[i], `relativeSchedule[${i}]`);
|
|
190
|
+
}
|
|
191
|
+
validateFirstEntryStartsAtZero(entries[0].seconds, 'relativeSchedule');
|
|
192
|
+
validateSecondsMatchResolution(entries.map((e) => e.seconds), stepSeconds, 'relativeSchedule');
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Validates a single {@link HeatingRodForecastScheduleEntry}. Used by
|
|
196
|
+
* {@link validateHeatingRodSchedule} and exposed for callers that build
|
|
197
|
+
* entries incrementally.
|
|
198
|
+
*/
|
|
199
|
+
export function validateHeatingRodScheduleEntry(entry, fieldName) {
|
|
200
|
+
validateSecondsField(entry.seconds, `${fieldName}.seconds`);
|
|
201
|
+
if (entry.powerW !== undefined) {
|
|
202
|
+
validatePowerW(entry.powerW, `${fieldName}.powerW`);
|
|
203
|
+
}
|
|
204
|
+
validateTemperatureField(entry.temperatureC, `${fieldName}.temperatureC`);
|
|
205
|
+
validateBooleanField(entry.heatingActive, `${fieldName}.heatingActive`);
|
|
206
|
+
validateBooleanField(entry.availablePowerActive, `${fieldName}.availablePowerActive`);
|
|
207
|
+
}
|
|
164
208
|
function validateMetadata(forecast) {
|
|
165
209
|
if (!(forecast.resolution in RESOLUTION_SECONDS)) {
|
|
166
210
|
throw new ApplianceCommandForecastValidationError(`resolution is invalid: ${forecast.resolution}. Allowed values: ${Object.values(ApplianceForecastResolutionEnum).join(', ')}.`);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EnergyApp } from "../../index.js";
|
|
2
2
|
import type { EnyoNetworkDevice } from "../../types/enyo-network-device.js";
|
|
3
3
|
import { EnyoAppliance, EnyoApplianceAvailableFeaturesEnum, EnyoApplianceConnectionType, EnyoApplianceMetadata, EnyoApplianceName, EnyoApplianceStateEnum, EnyoApplianceTopology, EnyoApplianceTypeEnum } from "../../types/enyo-appliance.js";
|
|
4
|
+
import type { EnyoApplianceCreatedFilter } from "../../packages/energy-app-appliance.js";
|
|
4
5
|
import type { EnyoChargerApplianceMetadata } from "../../types/enyo-charger-appliance.js";
|
|
5
6
|
import type { EnyoHeatpumpApplianceMetadata } from "../../types/enyo-heatpump-appliance.js";
|
|
6
7
|
import type { EnyoBatteryApplianceMetadata } from "../../types/enyo-battery-appliance.js";
|
|
@@ -203,6 +204,20 @@ export declare class ApplianceManager {
|
|
|
203
204
|
* Subscribes to appliance update and removal events to keep the cache in sync.
|
|
204
205
|
*/
|
|
205
206
|
private subscribeToEvents;
|
|
207
|
+
/**
|
|
208
|
+
* Subscribes to newly-created appliances. Fires only when an appliance is
|
|
209
|
+
* first created, not on subsequent updates. The optional
|
|
210
|
+
* {@link EnyoApplianceCreatedFilter filter} controls scope (own package,
|
|
211
|
+
* all appliances, or only externally-created) and category — `scope: 'all'`
|
|
212
|
+
* and `scope: 'external'` require the `AllAppliances` permission.
|
|
213
|
+
*
|
|
214
|
+
* @param listener - Invoked with each newly-created appliance
|
|
215
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
216
|
+
* @returns An unsubscribe function. Any still-active subscription is also
|
|
217
|
+
* cleaned up automatically on {@link dispose}.
|
|
218
|
+
* @throws {ApplianceManagerDisposedError} when called after {@link dispose}
|
|
219
|
+
*/
|
|
220
|
+
onApplianceCreated(listener: (appliance: EnyoAppliance) => void | Promise<void>, filter?: EnyoApplianceCreatedFilter): () => void;
|
|
206
221
|
/**
|
|
207
222
|
* Clears the internal cache without touching the SDK.
|
|
208
223
|
*/
|
|
@@ -294,6 +294,33 @@ export class ApplianceManager {
|
|
|
294
294
|
});
|
|
295
295
|
this.listenerIds.push(removedListenerId);
|
|
296
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Subscribes to newly-created appliances. Fires only when an appliance is
|
|
299
|
+
* first created, not on subsequent updates. The optional
|
|
300
|
+
* {@link EnyoApplianceCreatedFilter filter} controls scope (own package,
|
|
301
|
+
* all appliances, or only externally-created) and category — `scope: 'all'`
|
|
302
|
+
* and `scope: 'external'` require the `AllAppliances` permission.
|
|
303
|
+
*
|
|
304
|
+
* @param listener - Invoked with each newly-created appliance
|
|
305
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
306
|
+
* @returns An unsubscribe function. Any still-active subscription is also
|
|
307
|
+
* cleaned up automatically on {@link dispose}.
|
|
308
|
+
* @throws {ApplianceManagerDisposedError} when called after {@link dispose}
|
|
309
|
+
*/
|
|
310
|
+
onApplianceCreated(listener, filter) {
|
|
311
|
+
this.throwIfDisposed();
|
|
312
|
+
const applianceService = this.energyApp.useAppliances();
|
|
313
|
+
const listenerId = applianceService.listenForApplianceCreated((appliance) => {
|
|
314
|
+
if (this.disposed)
|
|
315
|
+
return;
|
|
316
|
+
return listener(appliance);
|
|
317
|
+
}, filter);
|
|
318
|
+
this.listenerIds.push(listenerId);
|
|
319
|
+
return () => {
|
|
320
|
+
applianceService.removeListener(listenerId);
|
|
321
|
+
this.listenerIds = this.listenerIds.filter(id => id !== listenerId);
|
|
322
|
+
};
|
|
323
|
+
}
|
|
297
324
|
/**
|
|
298
325
|
* Clears the internal cache without touching the SDK.
|
|
299
326
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export * from './types/enyo-energy-prices.js';
|
|
|
13
13
|
export * from './types/enyo-notification.js';
|
|
14
14
|
export * from './types/enyo-secret-manager.js';
|
|
15
15
|
export * from './types/enyo-location.js';
|
|
16
|
+
export * from './types/enyo-appliance.js';
|
|
17
|
+
export * from './packages/energy-app-appliance.js';
|
|
16
18
|
export * from './implementations/appliances/appliance-manager.js';
|
|
17
19
|
export * from './implementations/appliances/identifier-strategies.js';
|
|
18
20
|
export * from './implementations/network-devices/network-access-guard.js';
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,8 @@ export * from './types/enyo-energy-prices.js';
|
|
|
13
13
|
export * from './types/enyo-notification.js';
|
|
14
14
|
export * from './types/enyo-secret-manager.js';
|
|
15
15
|
export * from './types/enyo-location.js';
|
|
16
|
+
export * from './types/enyo-appliance.js';
|
|
17
|
+
export * from './packages/energy-app-appliance.js';
|
|
16
18
|
export * from './implementations/appliances/appliance-manager.js';
|
|
17
19
|
export * from './implementations/appliances/identifier-strategies.js';
|
|
18
20
|
export * from './implementations/network-devices/network-access-guard.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BatteryCommandForecast, ChargerForecast, HeatpumpForecast } from '../types/enyo-appliance-command-forecast.js';
|
|
1
|
+
import { BatteryCommandForecast, ChargerForecast, HeatingRodForecast, HeatpumpForecast } from '../types/enyo-appliance-command-forecast.js';
|
|
2
2
|
/**
|
|
3
3
|
* SDK accessor for the **Appliance Energy-Manager Forecast** package.
|
|
4
4
|
*
|
|
@@ -16,6 +16,10 @@ import { BatteryCommandForecast, ChargerForecast, HeatpumpForecast } from '../ty
|
|
|
16
16
|
* carry the forecasted DHW / room / buffer-tank temperatures together
|
|
17
17
|
* with planned boost / pre-heating flags and the available-power
|
|
18
18
|
* announcement at each slot ({@link HeatpumpForecast}).
|
|
19
|
+
* - **Heating rods** — a single relative schedule whose entries carry
|
|
20
|
+
* the forecasted target temperature together with the planned heating
|
|
21
|
+
* flag and the available-power announcement at each slot
|
|
22
|
+
* ({@link HeatingRodForecast}).
|
|
19
23
|
*
|
|
20
24
|
* Every forecast optionally carries
|
|
21
25
|
* {@link ApplianceForecastEstimatedSavings} so downstream consumers can
|
|
@@ -85,4 +89,20 @@ export interface EnergyAppApplianceEnergyManagerForecast {
|
|
|
85
89
|
* is malformed.
|
|
86
90
|
*/
|
|
87
91
|
publishHeatpumpForecast(applianceId: string, forecast: HeatpumpForecast): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Publishes the command-plan forecast for a heating rod (immersion
|
|
94
|
+
* element). The forecast carries a single relative schedule whose
|
|
95
|
+
* entries pack the forecasted target temperature together with the
|
|
96
|
+
* planned heating flag and the available-power announcement at each
|
|
97
|
+
* slot.
|
|
98
|
+
*
|
|
99
|
+
* Validates {@link forecast} against the invariants documented on
|
|
100
|
+
* {@link HeatingRodForecast}.
|
|
101
|
+
*
|
|
102
|
+
* @param applianceId - The heating rod appliance the forecast applies to.
|
|
103
|
+
* @param forecast - The command-plan forecast and its metadata.
|
|
104
|
+
* @throws {ApplianceCommandForecastValidationError} If the forecast
|
|
105
|
+
* is malformed.
|
|
106
|
+
*/
|
|
107
|
+
publishHeatingRodForecast(applianceId: string, forecast: HeatingRodForecast): Promise<void>;
|
|
88
108
|
}
|
|
@@ -1,4 +1,30 @@
|
|
|
1
|
-
import { EnyoAppliance } from "../types/enyo-appliance.js";
|
|
1
|
+
import { EnyoAppliance, EnyoApplianceTypeEnum } from "../types/enyo-appliance.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ownership scope for an appliance-created subscription.
|
|
4
|
+
* - `'own'`: appliances created by your own package.
|
|
5
|
+
* - `'all'`: every appliance created system-wide.
|
|
6
|
+
* - `'external'`: only appliances created by *other* packages (all minus own).
|
|
7
|
+
*/
|
|
8
|
+
export type EnyoApplianceCreatedScope = 'own' | 'all' | 'external';
|
|
9
|
+
/**
|
|
10
|
+
* Optional filter controlling which appliance-created events a listener receives.
|
|
11
|
+
* When omitted, defaults to `scope: 'own'` and no category restriction.
|
|
12
|
+
*/
|
|
13
|
+
export interface EnyoApplianceCreatedFilter {
|
|
14
|
+
/**
|
|
15
|
+
* Ownership scope of the subscription:
|
|
16
|
+
* - `'own'` (default): appliances created by your own package.
|
|
17
|
+
* - `'all'`: every appliance created system-wide. Requires the `AllAppliances` permission.
|
|
18
|
+
* - `'external'`: only appliances created by *other* packages (all minus own). Requires the `AllAppliances` permission.
|
|
19
|
+
*/
|
|
20
|
+
scope?: EnyoApplianceCreatedScope;
|
|
21
|
+
/**
|
|
22
|
+
* When set, the listener only fires for appliances whose
|
|
23
|
+
* {@link EnyoApplianceTypeEnum category} is included in this list. When
|
|
24
|
+
* omitted, appliances of every category are delivered.
|
|
25
|
+
*/
|
|
26
|
+
types?: EnyoApplianceTypeEnum[];
|
|
27
|
+
}
|
|
2
28
|
/**
|
|
3
29
|
* Interface for managing appliances in enyo packages.
|
|
4
30
|
* Provides CRUD operations for appliance registration and management.
|
|
@@ -26,9 +52,24 @@ export interface EnergyAppAppliance {
|
|
|
26
52
|
* @returns A unique listener ID that can be used to remove the listener
|
|
27
53
|
*/
|
|
28
54
|
listenForApplianceRemoved: (listener: (applianceId: string) => void | Promise<void>) => string;
|
|
55
|
+
/**
|
|
56
|
+
* Listen for newly-created appliances. Fires only when an appliance is
|
|
57
|
+
* first created — not on subsequent updates (use
|
|
58
|
+
* {@link listenForApplianceUpdated} for those).
|
|
59
|
+
*
|
|
60
|
+
* The optional {@link EnyoApplianceCreatedFilter filter} controls scope and
|
|
61
|
+
* category: by default only your own package's creations are delivered;
|
|
62
|
+
* `scope: 'all'` and `scope: 'external'` observe appliances created by other
|
|
63
|
+
* packages and require the `AllAppliances` permission.
|
|
64
|
+
*
|
|
65
|
+
* @param listener - Callback invoked with each newly-created appliance
|
|
66
|
+
* @param filter - Optional scope/category filter; defaults to `{ scope: 'own' }`
|
|
67
|
+
* @returns A unique listener ID that can be used to remove the listener
|
|
68
|
+
*/
|
|
69
|
+
listenForApplianceCreated: (listener: (appliance: EnyoAppliance) => void | Promise<void>, filter?: EnyoApplianceCreatedFilter) => string;
|
|
29
70
|
/**
|
|
30
71
|
* Removes a previously registered listener.
|
|
31
|
-
* @param listenerId - The ID returned by listenForApplianceUpdated or
|
|
72
|
+
* @param listenerId - The ID returned by listenForApplianceUpdated, listenForApplianceRemoved, or listenForApplianceCreated
|
|
32
73
|
*/
|
|
33
74
|
removeListener: (listenerId: string) => void;
|
|
34
75
|
}
|
|
@@ -354,3 +354,79 @@ export interface HeatpumpForecast extends ApplianceForecastMetadata {
|
|
|
354
354
|
*/
|
|
355
355
|
relativeSchedule: HeatpumpForecastScheduleEntry[];
|
|
356
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* One entry of a heating rod's relative schedule.
|
|
359
|
+
*
|
|
360
|
+
* The entry packs every per-slot piece of information the energy-manager
|
|
361
|
+
* forecast carries for a heating rod (immersion element): the forecasted
|
|
362
|
+
* target temperature, the planned heating flag, and the available-power
|
|
363
|
+
* announcement. The setpoint becomes active {@link seconds} after the
|
|
364
|
+
* forecast becomes effective and stays active until the next entry's
|
|
365
|
+
* `seconds` is reached.
|
|
366
|
+
*
|
|
367
|
+
* Every field other than {@link seconds} is optional — an entry may
|
|
368
|
+
* describe only the temperature, only the flag, only power, or any
|
|
369
|
+
* combination. A field that is omitted carries no information for that
|
|
370
|
+
* slot (it is **not** "set to zero / false"); the previous entry's value
|
|
371
|
+
* should be treated as still in effect.
|
|
372
|
+
*/
|
|
373
|
+
export interface HeatingRodForecastScheduleEntry {
|
|
374
|
+
/**
|
|
375
|
+
* Seconds from the moment the forecast becomes effective at which
|
|
376
|
+
* this entry becomes active. `0` for the first entry; subsequent
|
|
377
|
+
* entries must be strictly increasing.
|
|
378
|
+
*/
|
|
379
|
+
seconds: number;
|
|
380
|
+
/**
|
|
381
|
+
* Planned available electrical power in Watts the energy manager
|
|
382
|
+
* intends to make available to the heating rod during this slot. The
|
|
383
|
+
* heating rod is free to consume up to this value — and free to
|
|
384
|
+
* consume less if it cannot use it all. Non-negative when present.
|
|
385
|
+
*/
|
|
386
|
+
powerW?: number;
|
|
387
|
+
/**
|
|
388
|
+
* Forecasted target temperature in °C at this slot (the temperature
|
|
389
|
+
* the heating rod is driving its tank / buffer toward). Plausible
|
|
390
|
+
* range: [-50, 150].
|
|
391
|
+
*/
|
|
392
|
+
temperatureC?: number;
|
|
393
|
+
/**
|
|
394
|
+
* Whether the heating rod is planned to be actively heating during
|
|
395
|
+
* this slot — `true` while the publisher intends to drive the tank
|
|
396
|
+
* up, `false` (or omitted) otherwise.
|
|
397
|
+
*/
|
|
398
|
+
heatingActive?: boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Whether the publisher is announcing available power for this slot
|
|
401
|
+
* — `true` when the energy-manager decision for the slot is
|
|
402
|
+
* "available power", meaning {@link powerW} doubles as the
|
|
403
|
+
* available-power offer to the heating rod (the heating rod is free
|
|
404
|
+
* to consume up to that value), `false` (or omitted) otherwise.
|
|
405
|
+
*
|
|
406
|
+
* This flag is independent of {@link heatingActive} and may coexist
|
|
407
|
+
* with it when the publisher offers available power while a heating
|
|
408
|
+
* window is also planned.
|
|
409
|
+
*/
|
|
410
|
+
availablePowerActive?: boolean;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Forecasted command plan for a heating rod appliance, published via
|
|
414
|
+
* {@link EnergyAppApplianceEnergyManagerForecast.publishHeatingRodForecast}.
|
|
415
|
+
*
|
|
416
|
+
* A heating rod forecast is a **single** relative schedule whose entries
|
|
417
|
+
* carry every per-slot piece of information at once (forecasted target
|
|
418
|
+
* temperature, heating flag, available-power announcement). One entry per
|
|
419
|
+
* slot keeps the temperature trajectory and the heating decisions aligned
|
|
420
|
+
* by construction.
|
|
421
|
+
*
|
|
422
|
+
* The schedule must be sorted ascending by `seconds` and start at
|
|
423
|
+
* `seconds = 0` so the appliance has an authoritative "right now" entry.
|
|
424
|
+
*/
|
|
425
|
+
export interface HeatingRodForecast extends ApplianceForecastMetadata {
|
|
426
|
+
/**
|
|
427
|
+
* Relative schedule of forecast entries. Sorted ascending by
|
|
428
|
+
* `seconds`, starting at `seconds = 0`. Must contain at least one
|
|
429
|
+
* entry.
|
|
430
|
+
*/
|
|
431
|
+
relativeSchedule: HeatingRodForecastScheduleEntry[];
|
|
432
|
+
}
|
|
@@ -625,6 +625,12 @@ export interface EnyoDataBusAggregatedStateValuesV1 extends EnyoDataBusMessage {
|
|
|
625
625
|
gridPowerPhase2W?: number;
|
|
626
626
|
/** Grid power on phase L3 (in Watt). Negative: grid feed in, positive: grid consumption */
|
|
627
627
|
gridPowerPhase3W?: number;
|
|
628
|
+
/**
|
|
629
|
+
* Time resolution of the aggregated grid power values (e.g. the sampling
|
|
630
|
+
* interval the `gridPowerW` / `gridPowerPhaseXW` values were measured at).
|
|
631
|
+
* Use `'dynamic'` when the values are forwarded as events occur.
|
|
632
|
+
*/
|
|
633
|
+
gridPowerResolution: EnyoDataBusMessageResolution;
|
|
628
634
|
gridConsumptionW?: number;
|
|
629
635
|
gridFeedInW?: number;
|
|
630
636
|
homeConsumptionW?: number;
|
|
@@ -14,12 +14,23 @@ export declare enum EnyoHeatpumpApplianceAvailableFeaturesEnum {
|
|
|
14
14
|
/** If the heatpump reports power values (e.g. electrical power consumption in watts) */
|
|
15
15
|
Power = "Power",
|
|
16
16
|
/** If the heatpump is ready for calibration (i.e. has all prerequisites in place to start a calibration run) */
|
|
17
|
-
ReadyForCalibration = "ReadyForCalibration"
|
|
17
|
+
ReadyForCalibration = "ReadyForCalibration",
|
|
18
|
+
/** If the heatpump supports cooling (reversible heatpump) */
|
|
19
|
+
Cooling = "Cooling"
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The current operating state of a heatpump.
|
|
23
|
+
*/
|
|
19
24
|
export declare enum EnyoHeatpumpApplianceModeEnum {
|
|
25
|
+
/** The heatpump is idle (not actively heating, cooling, or producing hot water) */
|
|
20
26
|
Idle = "Idle",
|
|
27
|
+
/** The heatpump is actively heating */
|
|
21
28
|
Heating = "Heating",
|
|
29
|
+
/** The heatpump is actively cooling (reversible heatpumps only) */
|
|
30
|
+
Cooling = "Cooling",
|
|
31
|
+
/** The heatpump is actively producing domestic hot water */
|
|
22
32
|
DomesticHotWater = "DomesticHotWater",
|
|
33
|
+
/** The heatpump is running in emergency operation */
|
|
23
34
|
EmergencyOperation = "EmergencyOperation"
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
@@ -51,7 +62,10 @@ export interface EnyoHeatpumpApplianceCompressor {
|
|
|
51
62
|
}
|
|
52
63
|
export interface EnyoHeatpumpApplianceHeatingCircuit {
|
|
53
64
|
index: number;
|
|
65
|
+
/** Target room temperature setpoint when heating (in °C) */
|
|
54
66
|
targetRoomTemperatureC?: number;
|
|
67
|
+
/** Target room temperature setpoint when cooling (in °C). Only meaningful for cooling-capable heatpumps. */
|
|
68
|
+
targetCoolingRoomTemperatureC?: number;
|
|
55
69
|
}
|
|
56
70
|
export interface EnyoHeatpumpApplianceMetadata {
|
|
57
71
|
availableFeatures: EnyoHeatpumpApplianceAvailableFeaturesEnum[];
|
|
@@ -16,12 +16,23 @@ export var EnyoHeatpumpApplianceAvailableFeaturesEnum;
|
|
|
16
16
|
EnyoHeatpumpApplianceAvailableFeaturesEnum["Power"] = "Power";
|
|
17
17
|
/** If the heatpump is ready for calibration (i.e. has all prerequisites in place to start a calibration run) */
|
|
18
18
|
EnyoHeatpumpApplianceAvailableFeaturesEnum["ReadyForCalibration"] = "ReadyForCalibration";
|
|
19
|
+
/** If the heatpump supports cooling (reversible heatpump) */
|
|
20
|
+
EnyoHeatpumpApplianceAvailableFeaturesEnum["Cooling"] = "Cooling";
|
|
19
21
|
})(EnyoHeatpumpApplianceAvailableFeaturesEnum || (EnyoHeatpumpApplianceAvailableFeaturesEnum = {}));
|
|
22
|
+
/**
|
|
23
|
+
* The current operating state of a heatpump.
|
|
24
|
+
*/
|
|
20
25
|
export var EnyoHeatpumpApplianceModeEnum;
|
|
21
26
|
(function (EnyoHeatpumpApplianceModeEnum) {
|
|
27
|
+
/** The heatpump is idle (not actively heating, cooling, or producing hot water) */
|
|
22
28
|
EnyoHeatpumpApplianceModeEnum["Idle"] = "Idle";
|
|
29
|
+
/** The heatpump is actively heating */
|
|
23
30
|
EnyoHeatpumpApplianceModeEnum["Heating"] = "Heating";
|
|
31
|
+
/** The heatpump is actively cooling (reversible heatpumps only) */
|
|
32
|
+
EnyoHeatpumpApplianceModeEnum["Cooling"] = "Cooling";
|
|
33
|
+
/** The heatpump is actively producing domestic hot water */
|
|
24
34
|
EnyoHeatpumpApplianceModeEnum["DomesticHotWater"] = "DomesticHotWater";
|
|
35
|
+
/** The heatpump is running in emergency operation */
|
|
25
36
|
EnyoHeatpumpApplianceModeEnum["EmergencyOperation"] = "EmergencyOperation";
|
|
26
37
|
})(EnyoHeatpumpApplianceModeEnum || (EnyoHeatpumpApplianceModeEnum = {}));
|
|
27
38
|
/**
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED