@enyo-energy/energy-app-sdk 0.0.193 → 0.0.194

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 (26) hide show
  1. package/README.md +10 -0
  2. package/dist/cjs/energy-app-package-definition.d.cts +12 -0
  3. package/dist/cjs/implementations/onboarding-v2/define-onboarding-guide-v2.cjs +31 -0
  4. package/dist/cjs/implementations/onboarding-v2/define-onboarding-guide-v2.d.cts +25 -0
  5. package/dist/cjs/implementations/onboarding-v2/onboarding-v2-validators.cjs +57 -2
  6. package/dist/cjs/integrations/wallbox-integration-energy-app.cjs +34 -0
  7. package/dist/cjs/integrations/wallbox-integration-energy-app.d.cts +23 -1
  8. package/dist/cjs/types/enyo-data-bus-value.cjs +21 -1
  9. package/dist/cjs/types/enyo-data-bus-value.d.cts +155 -1
  10. package/dist/cjs/types/enyo-onboarding-v2.cjs +51 -1
  11. package/dist/cjs/types/enyo-onboarding-v2.d.cts +53 -2
  12. package/dist/cjs/version.cjs +1 -1
  13. package/dist/cjs/version.d.cts +1 -1
  14. package/dist/energy-app-package-definition.d.ts +12 -0
  15. package/dist/implementations/onboarding-v2/define-onboarding-guide-v2.d.ts +25 -0
  16. package/dist/implementations/onboarding-v2/define-onboarding-guide-v2.js +31 -0
  17. package/dist/implementations/onboarding-v2/onboarding-v2-validators.js +58 -3
  18. package/dist/integrations/wallbox-integration-energy-app.d.ts +23 -1
  19. package/dist/integrations/wallbox-integration-energy-app.js +34 -0
  20. package/dist/types/enyo-data-bus-value.d.ts +155 -1
  21. package/dist/types/enyo-data-bus-value.js +20 -0
  22. package/dist/types/enyo-onboarding-v2.d.ts +53 -2
  23. package/dist/types/enyo-onboarding-v2.js +50 -0
  24. package/dist/version.d.ts +1 -1
  25. package/dist/version.js +1 -1
  26. package/package.json +1 -1
package/README.md CHANGED
@@ -2054,6 +2054,16 @@ Drives an EV wallbox / charger. Has the richest command surface of all integrati
2054
2054
  - `publishChargingMeterValues(applianceId, data)` — periodic meter values during a session.
2055
2055
  - `publishMaxChargingPowerChanged(applianceId, maxChargingPowerKw)` — e.g. on thermal derating.
2056
2056
  - `publishChargerStatusChanged(applianceId, data)` — OCPP-style status changes.
2057
+ - `publishEnergyManagementChargingState(applianceId, data)` — the app's own continuously
2058
+ updated state for the energy manager. Facts only: `activePhases` (the phase count in
2059
+ force), `phaseSwitching` (`supported` / `available` right now, `availableFromIso` when
2060
+ it is barred until a known time, `inProgress`), `appliedCurrentLimitA` and the
2061
+ `appliedPowerW` it implies, `lastLimitRequest` (`accepted` \| `clamped` \| `rejected`,
2062
+ with what was requested), and `measuredAtIso` — when the reading was taken, as opposed
2063
+ to when the message was sent. No recommended minimum power, no suggested setpoint,
2064
+ nothing derived from the manager's own plan; static nameplate data stays in the
2065
+ appliance metadata. Republish the **complete** payload on every change and periodically
2066
+ as a heartbeat — an omitted field means "unknown", never "unchanged".
2057
2067
 
2058
2068
  ```typescript
2059
2069
  class MyWallbox extends WallboxIntegrationEnergyApp {
@@ -228,6 +228,18 @@ export interface EnergyAppPackageCompatibilityModel {
228
228
  * upgrade graph in {@link EnergyAppPackageDefinition.firmware} instead.
229
229
  */
230
230
  minimumFirmwareVersion?: string;
231
+ /**
232
+ * Optional device category of this concrete model (e.g. `Inverter`,
233
+ * `BatteryStorage`).
234
+ *
235
+ * Packages can support models of different kinds — a hybrid inverter plus a
236
+ * matching battery, for example — while
237
+ * {@link EnergyAppPackageDefinition.categories} only describes the package
238
+ * as a whole. Declaring the category per model lets the enyo Store and
239
+ * onboarding flows group and filter individual models correctly. Omit when
240
+ * the package-level categories are precise enough.
241
+ */
242
+ category?: EnergyAppPackageCategory;
231
243
  /** Optional internal note explaining model-specific caveats or limitations */
232
244
  internalComment?: string;
233
245
  /**
@@ -158,6 +158,37 @@ exports.onboardingV2Block = {
158
158
  label,
159
159
  outcomes,
160
160
  }),
161
+ /**
162
+ * An EEBUS-pair action block: the installer picks one of the discovered
163
+ * EEBUS peers and the host trusts its SKI.
164
+ *
165
+ * A convenience wrapper over {@link onboardingV2Block.action} that pins the
166
+ * action kind. The picker is drawn from what mDNS discovery found, so the
167
+ * guide must have scanned — keep
168
+ * {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its default or place
169
+ * a {@link EnyoOnboardingV2ActionKind.NetworkScan} block ahead of this one.
170
+ *
171
+ * Most EEBUS devices only announce themselves once pairing is enabled in
172
+ * their own menu or portal, and many ask for a confirmation there while the
173
+ * handshake runs, so put that instruction in a text/hint block on the
174
+ * preceding step — the app cannot do it for the installer.
175
+ *
176
+ * Outcome `value`s must be {@link EnyoOnboardingV2EebusPairOutcome} members;
177
+ * route `not-found` to troubleshooting and `failure` to a step describing
178
+ * the confirmation on the device. A retry must lead into a *second* pairing
179
+ * step: a back-edge onto the same step reads as a loop and ends the run.
180
+ *
181
+ * @param id - Stable block id, unique within the guide.
182
+ * @param label - Translated trigger button text (de/en).
183
+ * @param outcomes - The `paired` / `not-found` / `failure` results; each is a routing handle.
184
+ */
185
+ eebusPair: (id, label, outcomes) => ({
186
+ id,
187
+ type: enyo_onboarding_v2_js_1.EnyoOnboardingV2BlockType.Action,
188
+ action: enyo_onboarding_v2_js_1.EnyoOnboardingV2ActionKind.EebusPair,
189
+ label,
190
+ outcomes,
191
+ }),
161
192
  /**
162
193
  * An auth block: the installer signs into the energy app's own account
163
194
  * system (OAuth / vendor portal).
@@ -117,6 +117,31 @@ export declare const onboardingV2Block: {
117
117
  * @param outcomes - The `connected` / `timeout` results; each is a routing handle.
118
118
  */
119
119
  ocppConnect: (id: string, label: EnyoOnboardingTranslatedContent[], outcomes: EnyoOnboardingV2ActionOutcome[]) => EnyoOnboardingV2Block;
120
+ /**
121
+ * An EEBUS-pair action block: the installer picks one of the discovered
122
+ * EEBUS peers and the host trusts its SKI.
123
+ *
124
+ * A convenience wrapper over {@link onboardingV2Block.action} that pins the
125
+ * action kind. The picker is drawn from what mDNS discovery found, so the
126
+ * guide must have scanned — keep
127
+ * {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its default or place
128
+ * a {@link EnyoOnboardingV2ActionKind.NetworkScan} block ahead of this one.
129
+ *
130
+ * Most EEBUS devices only announce themselves once pairing is enabled in
131
+ * their own menu or portal, and many ask for a confirmation there while the
132
+ * handshake runs, so put that instruction in a text/hint block on the
133
+ * preceding step — the app cannot do it for the installer.
134
+ *
135
+ * Outcome `value`s must be {@link EnyoOnboardingV2EebusPairOutcome} members;
136
+ * route `not-found` to troubleshooting and `failure` to a step describing
137
+ * the confirmation on the device. A retry must lead into a *second* pairing
138
+ * step: a back-edge onto the same step reads as a loop and ends the run.
139
+ *
140
+ * @param id - Stable block id, unique within the guide.
141
+ * @param label - Translated trigger button text (de/en).
142
+ * @param outcomes - The `paired` / `not-found` / `failure` results; each is a routing handle.
143
+ */
144
+ eebusPair: (id: string, label: EnyoOnboardingTranslatedContent[], outcomes: EnyoOnboardingV2ActionOutcome[]) => EnyoOnboardingV2Block;
120
145
  /**
121
146
  * An auth block: the installer signs into the energy app's own account
122
147
  * system (OAuth / vendor portal).
@@ -178,6 +178,9 @@ function validateActionBlocks(step, at, errors, warnings) {
178
178
  if (block.action === enyo_onboarding_v2_js_1.EnyoOnboardingV2ActionKind.OcppConnect) {
179
179
  validateOcppConnectOutcomes(block, at, errors);
180
180
  }
181
+ if (block.action === enyo_onboarding_v2_js_1.EnyoOnboardingV2ActionKind.EebusPair) {
182
+ validateEebusPairOutcomes(block, at, errors, warnings);
183
+ }
181
184
  continue;
182
185
  }
183
186
  const values = new Set();
@@ -233,8 +236,17 @@ function validateLinkBlocks(step, at, errors, warnings) {
233
236
  }
234
237
  /** Every valid {@link EnyoOnboardingV2InputValueType} value. */
235
238
  const INPUT_VALUE_TYPES = new Set(Object.values(enyo_onboarding_v2_js_1.EnyoOnboardingV2InputValueType));
236
- /** Outcome values the host treats as "the check succeeded". */
237
- const POSITIVE_INPUT_OUTCOMES = new Set(['reachable', 'success', 'found']);
239
+ /**
240
+ * Outcome values the host treats as "the check succeeded" — mirrors the
241
+ * runtime's own positive-outcome set, `paired` included, so an eebus-pair
242
+ * result is not read as a failure.
243
+ */
244
+ const POSITIVE_INPUT_OUTCOMES = new Set([
245
+ 'reachable',
246
+ 'success',
247
+ 'found',
248
+ enyo_onboarding_v2_js_1.EnyoOnboardingV2EebusPairOutcome.Paired,
249
+ ]);
238
250
  /**
239
251
  * The {@link EnyoDeviceTestOutcomeEnum} verdicts that collapse onto a positive
240
252
  * input outcome; every other verdict collapses onto a negative one.
@@ -341,6 +353,42 @@ function validateOcppConnectOutcomes(block, at, errors) {
341
353
  }
342
354
  }
343
355
  }
356
+ /** Every {@link EnyoOnboardingV2EebusPairOutcome} value. */
357
+ const EEBUS_PAIR_OUTCOMES = new Set(Object.values(enyo_onboarding_v2_js_1.EnyoOnboardingV2EebusPairOutcome));
358
+ /**
359
+ * Validates the outcomes of an {@link EnyoOnboardingV2ActionKind.EebusPair}
360
+ * block.
361
+ *
362
+ * The block reports one of three things — a peer was picked and the SHIP
363
+ * handshake came up, discovery found nothing, or the handshake failed — so its
364
+ * outcome `value`s are closed over {@link EnyoOnboardingV2EebusPairOutcome}.
365
+ * Anything else is an outcome that can never fire.
366
+ *
367
+ * The missing `paired` branch is a warning rather than an error: it strands
368
+ * every successful pairing, but an author staging a guide step by step may
369
+ * legitimately not have wired it yet.
370
+ *
371
+ * @param block - The eebus-pair action block being checked.
372
+ * @param at - Human-readable location prefix for messages.
373
+ * @param errors - Collector for blocking problems.
374
+ * @param warnings - Collector for advisory problems.
375
+ */
376
+ function validateEebusPairOutcomes(block, at, errors, warnings) {
377
+ const values = new Set();
378
+ for (const outcome of block.outcomes ?? []) {
379
+ if (!EEBUS_PAIR_OUTCOMES.has(outcome.value)) {
380
+ errors.push(`${at}: eebus-pair block "${block.id}" has outcome value "${outcome.value}", which is not an EnyoOnboardingV2EebusPairOutcome member.`);
381
+ }
382
+ else if (values.has(outcome.value)) {
383
+ errors.push(`${at}: eebus-pair block "${block.id}" wires outcome value "${outcome.value}" more than once.`);
384
+ }
385
+ values.add(outcome.value);
386
+ }
387
+ if (!values.has(enyo_onboarding_v2_js_1.EnyoOnboardingV2EebusPairOutcome.Paired)) {
388
+ warnings.push(`${at}: eebus-pair block "${block.id}" has no "${enyo_onboarding_v2_js_1.EnyoOnboardingV2EebusPairOutcome.Paired}" outcome — ` +
389
+ 'a successful pairing would have nowhere to go.');
390
+ }
391
+ }
344
392
  /**
345
393
  * Validates the auth blocks of a step.
346
394
  *
@@ -410,6 +458,13 @@ function validateNetworkScanFlag(guide, warnings) {
410
458
  'nothing was scanned, so it has nothing to test. Use deviceSelection "current", or run a ' +
411
459
  'network-scan action inside the guide.');
412
460
  }
461
+ const pairsEebus = blocks.some((b) => b.type === enyo_onboarding_v2_js_1.EnyoOnboardingV2BlockType.Action &&
462
+ b.action === enyo_onboarding_v2_js_1.EnyoOnboardingV2ActionKind.EebusPair);
463
+ if (pairsEebus) {
464
+ warnings.push('requiresNetworkScan is false, but an eebus-pair block asks the installer to pick a ' +
465
+ 'discovered EEBUS peer — nothing was scanned, so the picker would open on an empty ' +
466
+ 'list. Run a network-scan action inside the guide ahead of it.');
467
+ }
413
468
  }
414
469
  /**
415
470
  * The set of routing-handle keys a step must wire exactly once: one per
@@ -117,6 +117,40 @@ class WallboxIntegrationEnergyApp extends integration_energy_app_js_1.Integratio
117
117
  };
118
118
  this.useDataBus().sendMessage([msg]);
119
119
  }
120
+ /**
121
+ * Publishes an `EnergyManagementChargingStateV1` message: the app's own
122
+ * state — the phase count in force, whether a phase switch is possible
123
+ * right now, the limit actually applied and the verdict on the last
124
+ * request — reported to the energy manager.
125
+ *
126
+ * This is a continuously updated state, not an event. Call it whenever
127
+ * anything in the payload changes (a phase switch starts or finishes, a
128
+ * cool-down expires, a new limit is applied) and periodically as a
129
+ * heartbeat, always passing the **complete** picture: an omitted field
130
+ * means "unknown", never "unchanged".
131
+ *
132
+ * Report facts, never advice: the phase count, the applied limit and the
133
+ * power it implies, the request verdict, the measurement timestamp — no
134
+ * recommended minimum power, no suggested setpoint, nothing derived from
135
+ * the energy manager's own plan.
136
+ *
137
+ * @param applianceId - The charger appliance the state describes.
138
+ * @param data - The full charging state; see
139
+ * {@link EnyoDataBusEnergyManagementChargingStateV1}.
140
+ */
141
+ publishEnergyManagementChargingState(applianceId, data) {
142
+ const msg = {
143
+ id: this.generateMessageId(),
144
+ type: 'message',
145
+ message: enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.EnergyManagementChargingStateV1,
146
+ source: this.source,
147
+ applianceId,
148
+ timestampIso: new Date().toISOString(),
149
+ resolution: 'dynamic',
150
+ data
151
+ };
152
+ this.useDataBus().sendMessage([msg]);
153
+ }
120
154
  /**
121
155
  * Publishes a `ChargerStatusChangedV1` message reporting the current OCPP
122
156
  * status (Available, Preparing, Charging, …).
@@ -1,7 +1,7 @@
1
1
  import { IntegrationEnergyApp } from "./integration-energy-app.cjs";
2
2
  import { IntegrationCommandResponse, IntegrationEnergyAppOptions } from "./integration-types.cjs";
3
3
  import { EnyoApplianceTypeEnum } from "../types/enyo-appliance.cjs";
4
- import { EnyoDataBusChangeChargingPowerV1, EnyoDataBusChargerStatusChangedV1, EnyoDataBusChargingMeterValuesV1, EnyoDataBusChargingStartedV1, EnyoDataBusChargingStoppedV1, EnyoDataBusClearChargingProfilesV1, EnyoDataBusGridOperatorPowerLimitationV1, EnyoDataBusMessage, EnyoDataBusPauseChargingV1, EnyoDataBusRebootChargerV1, EnyoDataBusRequestChargerLogsV1, EnyoDataBusResetChargerV1, EnyoDataBusResumeChargingV1, EnyoDataBusSetChargerAvailablePowerV2, EnyoDataBusSetChargingScheduleV1, EnyoDataBusStartChargeV1, EnyoDataBusStopChargeV1 } from "../types/enyo-data-bus-value.cjs";
4
+ import { EnyoDataBusChangeChargingPowerV1, EnyoDataBusChargerStatusChangedV1, EnyoDataBusChargingMeterValuesV1, EnyoDataBusChargingStartedV1, EnyoDataBusChargingStoppedV1, EnyoDataBusClearChargingProfilesV1, EnyoDataBusEnergyManagementChargingStateV1, EnyoDataBusGridOperatorPowerLimitationV1, EnyoDataBusMessage, EnyoDataBusPauseChargingV1, EnyoDataBusRebootChargerV1, EnyoDataBusRequestChargerLogsV1, EnyoDataBusResetChargerV1, EnyoDataBusResumeChargingV1, EnyoDataBusSetChargerAvailablePowerV2, EnyoDataBusSetChargingScheduleV1, EnyoDataBusStartChargeV1, EnyoDataBusStopChargeV1 } from "../types/enyo-data-bus-value.cjs";
5
5
  /**
6
6
  * Abstract base class for wallbox / charger integrations.
7
7
  *
@@ -122,6 +122,28 @@ export declare abstract class WallboxIntegrationEnergyApp extends IntegrationEne
122
122
  * charger's max charging power has changed (e.g. due to thermal derating).
123
123
  */
124
124
  publishMaxChargingPowerChanged(applianceId: string, maxChargingPowerKw: number): void;
125
+ /**
126
+ * Publishes an `EnergyManagementChargingStateV1` message: the app's own
127
+ * state — the phase count in force, whether a phase switch is possible
128
+ * right now, the limit actually applied and the verdict on the last
129
+ * request — reported to the energy manager.
130
+ *
131
+ * This is a continuously updated state, not an event. Call it whenever
132
+ * anything in the payload changes (a phase switch starts or finishes, a
133
+ * cool-down expires, a new limit is applied) and periodically as a
134
+ * heartbeat, always passing the **complete** picture: an omitted field
135
+ * means "unknown", never "unchanged".
136
+ *
137
+ * Report facts, never advice: the phase count, the applied limit and the
138
+ * power it implies, the request verdict, the measurement timestamp — no
139
+ * recommended minimum power, no suggested setpoint, nothing derived from
140
+ * the energy manager's own plan.
141
+ *
142
+ * @param applianceId - The charger appliance the state describes.
143
+ * @param data - The full charging state; see
144
+ * {@link EnyoDataBusEnergyManagementChargingStateV1}.
145
+ */
146
+ publishEnergyManagementChargingState(applianceId: string, data: EnyoDataBusEnergyManagementChargingStateV1['data']): void;
125
147
  /**
126
148
  * Publishes a `ChargerStatusChangedV1` message reporting the current OCPP
127
149
  * status (Available, Preparing, Charging, …).
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EnyoPowerSourceEnum = exports.EnyoHeatpumpControlPurposeEnum = exports.EnyoChargingProfileTypeEnum = exports.EnyoCommandAcknowledgeAnswerEnum = exports.EnyoStorageControlDirectionEnum = exports.EnyoStorageControlModeEnum = exports.EnyoStorageScheduleDirectionEnum = exports.EnyoStorageScheduleModeEnum = exports.EnyoDataBusMessageEnum = exports.EnyoChargeInitiatorEnum = exports.EnyoChargeModeEnum = exports.EnyoChargingStopReason = exports.EnyoChargingMeterValueContext = exports.EnyoStringStateEnum = exports.EnyoHeatingRodStateEnum = exports.EnyoInverterStateEnum = exports.EnyoBatteryStateEnum = exports.EnyoGridOperatorLimitTypeEnum = exports.EnyoDataBusCommandReasonCategoryEnum = exports.EnyoDataBusCommandReasonTypeEnum = void 0;
3
+ exports.EnyoPowerSourceEnum = exports.EnyoHeatpumpControlPurposeEnum = exports.EnyoChargingProfileTypeEnum = exports.EnyoCommandAcknowledgeAnswerEnum = exports.EnyoStorageControlDirectionEnum = exports.EnyoStorageControlModeEnum = exports.EnyoStorageScheduleDirectionEnum = exports.EnyoStorageScheduleModeEnum = exports.EnyoChargingLimitRequestResultEnum = exports.EnyoDataBusMessageEnum = exports.EnyoChargeInitiatorEnum = exports.EnyoChargeModeEnum = exports.EnyoChargingStopReason = exports.EnyoChargingMeterValueContext = exports.EnyoStringStateEnum = exports.EnyoHeatingRodStateEnum = exports.EnyoInverterStateEnum = exports.EnyoBatteryStateEnum = exports.EnyoGridOperatorLimitTypeEnum = exports.EnyoDataBusCommandReasonCategoryEnum = exports.EnyoDataBusCommandReasonTypeEnum = void 0;
4
4
  /**
5
5
  * Enum representing the reason type for why a data bus command was issued.
6
6
  * Used to attach context to commands for logging, debugging, and UI display.
@@ -222,6 +222,8 @@ var EnyoDataBusMessageEnum;
222
222
  EnyoDataBusMessageEnum["EnergyTariffUpdateV1"] = "EnergyTariffUpdateV1";
223
223
  EnyoDataBusMessageEnum["ChargeFinishedV1"] = "ChargeFinishedV1";
224
224
  EnyoDataBusMessageEnum["ChargerStatusChangedV1"] = "ChargerStatusChangedV1";
225
+ /** Recurring state of the charging energy app (phases in force, phase-switch availability, applied limit, last request's verdict) reported to the energy manager. */
226
+ EnyoDataBusMessageEnum["EnergyManagementChargingStateV1"] = "EnergyManagementChargingStateV1";
225
227
  EnyoDataBusMessageEnum["RequestPreviewChargingScheduleV1"] = "RequestPreviewChargingScheduleV1";
226
228
  EnyoDataBusMessageEnum["PreviewChargingScheduleResponseV1"] = "PreviewChargingScheduleResponseV1";
227
229
  EnyoDataBusMessageEnum["PvForecastV1"] = "PvForecastV1";
@@ -280,6 +282,24 @@ var EnyoDataBusMessageEnum;
280
282
  EnyoDataBusMessageEnum["SetStorageControlV2"] = "SetStorageControlV2";
281
283
  EnyoDataBusMessageEnum["EnergyAppStartedV1"] = "EnergyAppStartedV1";
282
284
  })(EnyoDataBusMessageEnum || (exports.EnyoDataBusMessageEnum = EnyoDataBusMessageEnum = {}));
285
+ /**
286
+ * What became of the last power/current limit the energy manager asked this
287
+ * charging app for.
288
+ *
289
+ * A request is not the same as a limit in force: chargers round to their
290
+ * ampere step, refuse values below their minimum current, and cap at their
291
+ * nameplate. Reporting the verdict closes the loop — without it the energy
292
+ * manager cannot tell a limit it set from a limit the charger quietly changed.
293
+ */
294
+ var EnyoChargingLimitRequestResultEnum;
295
+ (function (EnyoChargingLimitRequestResultEnum) {
296
+ /** Applied as requested. */
297
+ EnyoChargingLimitRequestResultEnum["Accepted"] = "accepted";
298
+ /** Applied, but at a different value than requested (rounded, floored, capped). */
299
+ EnyoChargingLimitRequestResultEnum["Clamped"] = "clamped";
300
+ /** Not applied at all; the previous limit stayed in force. */
301
+ EnyoChargingLimitRequestResultEnum["Rejected"] = "rejected";
302
+ })(EnyoChargingLimitRequestResultEnum || (exports.EnyoChargingLimitRequestResultEnum = EnyoChargingLimitRequestResultEnum = {}));
283
303
  /**
284
304
  * Storage control mode carried by {@link EnyoDataBusSetStorageScheduleV1}.
285
305
  *
@@ -2,7 +2,7 @@ import { EnyoApplianceErrorCode, EnyoApplianceStateEnum, EnyoApplianceStatusEnum
2
2
  import type { EnyoAutomationTriggerData } from "./enyo-automation.cjs";
3
3
  import { EnyoSourceEnum } from "./enyo-source.enum.cjs";
4
4
  import { EnyoOcppRelativeSchedule } from "./enyo-ocpp.cjs";
5
- import { EnyoChargerApplianceStatusEnum, EnyoChargerApplianceSuspendedReasonEnum } from "./enyo-charger-appliance.cjs";
5
+ import { EnyoChargerAppliancePhase, EnyoChargerApplianceStatusEnum, EnyoChargerApplianceSuspendedReasonEnum } from "./enyo-charger-appliance.cjs";
6
6
  import { PreviewChargingSchedule, PreviewChargingScheduleCostComparison, PreviewChargingScheduleUnavailableReasonEnum } from "./enyo-energy-manager.cjs";
7
7
  import { EnyoEnergyPrices } from "./enyo-energy-prices.cjs";
8
8
  import { EnyoCurrencyEnum } from "./enyo-currency.cjs";
@@ -286,6 +286,8 @@ export declare enum EnyoDataBusMessageEnum {
286
286
  EnergyTariffUpdateV1 = "EnergyTariffUpdateV1",
287
287
  ChargeFinishedV1 = "ChargeFinishedV1",
288
288
  ChargerStatusChangedV1 = "ChargerStatusChangedV1",
289
+ /** Recurring state of the charging energy app (phases in force, phase-switch availability, applied limit, last request's verdict) reported to the energy manager. */
290
+ EnergyManagementChargingStateV1 = "EnergyManagementChargingStateV1",
289
291
  RequestPreviewChargingScheduleV1 = "RequestPreviewChargingScheduleV1",
290
292
  PreviewChargingScheduleResponseV1 = "PreviewChargingScheduleResponseV1",
291
293
  PvForecastV1 = "PvForecastV1",
@@ -997,6 +999,158 @@ export interface EnyoDataBusChargerStatusChangedV1 extends EnyoDataBusMessage {
997
999
  suspendedReason?: EnyoChargerApplianceSuspendedReasonEnum;
998
1000
  };
999
1001
  }
1002
+ /**
1003
+ * What became of the last power/current limit the energy manager asked this
1004
+ * charging app for.
1005
+ *
1006
+ * A request is not the same as a limit in force: chargers round to their
1007
+ * ampere step, refuse values below their minimum current, and cap at their
1008
+ * nameplate. Reporting the verdict closes the loop — without it the energy
1009
+ * manager cannot tell a limit it set from a limit the charger quietly changed.
1010
+ */
1011
+ export declare enum EnyoChargingLimitRequestResultEnum {
1012
+ /** Applied as requested. */
1013
+ Accepted = "accepted",
1014
+ /** Applied, but at a different value than requested (rounded, floored, capped). */
1015
+ Clamped = "clamped",
1016
+ /** Not applied at all; the previous limit stayed in force. */
1017
+ Rejected = "rejected"
1018
+ }
1019
+ /**
1020
+ * The verdict on the last limit request, as a fact about what happened.
1021
+ *
1022
+ * Carries what was asked for and what the app did with it. The value actually
1023
+ * in force afterwards is not repeated here — it is
1024
+ * {@link EnyoDataBusEnergyManagementChargingStateV1.data.appliedCurrentLimitA}
1025
+ * in the same message.
1026
+ */
1027
+ export interface EnyoChargingLimitRequestOutcome {
1028
+ /**
1029
+ * `id` of the {@link EnyoDataBusSetChargerAvailablePowerV2} (or other limit
1030
+ * command) this verdict belongs to, when the app tracked it. Lets the energy
1031
+ * manager match the verdict to its own request instead of guessing by time.
1032
+ */
1033
+ requestMessageId?: string;
1034
+ /** What the app did with the request. */
1035
+ result: EnyoChargingLimitRequestResultEnum;
1036
+ /** The active power that was requested, in Watts, as received. */
1037
+ requestedPowerW?: number;
1038
+ /** The current per phase that was requested, in Amperes, when the request was expressed that way. */
1039
+ requestedCurrentA?: number;
1040
+ /** ISO 8601 timestamp at which the app handled the request. */
1041
+ handledAtIso: string;
1042
+ /**
1043
+ * Short machine-readable cause when the request was clamped or rejected,
1044
+ * e.g. `below-minimum-current`, `above-nameplate`, `charger-offline`,
1045
+ * `ampere-step-rounding`. Never shown to end users verbatim.
1046
+ */
1047
+ reason?: string;
1048
+ }
1049
+ /**
1050
+ * Whether this charger can change its phase count right now, and if not, until
1051
+ * when.
1052
+ *
1053
+ * Two different facts: {@link supported} is about the hardware and the wiring
1054
+ * and does not change during operation; {@link available} is about this moment —
1055
+ * a contactor switch interrupts the session, so apps bar the next switch for a
1056
+ * cool-down after the last one, and refuse it outright while the charger is in
1057
+ * certain states.
1058
+ */
1059
+ export interface EnyoChargingPhaseSwitchingState {
1060
+ /** Whether the charger can switch between one- and three-phase charging at all. */
1061
+ supported: boolean;
1062
+ /** Whether a phase switch can be performed right now. */
1063
+ available: boolean;
1064
+ /**
1065
+ * ISO 8601 timestamp from which switching becomes available again. Set when
1066
+ * {@link available} is `false` **and** the app knows the deadline — a
1067
+ * cool-down expiry, typically. Omitted when the block has no known end (the
1068
+ * charger is offline, switching is unsupported).
1069
+ */
1070
+ availableFromIso?: string;
1071
+ /** Whether a phase switch is in progress at this moment. */
1072
+ inProgress: boolean;
1073
+ /**
1074
+ * The phase count a switch in progress is heading for. Only present while
1075
+ * {@link inProgress} is `true`.
1076
+ */
1077
+ targetPhases?: EnyoChargerAppliancePhase;
1078
+ /** ISO 8601 timestamp of the last completed phase switch, when the app knows it. */
1079
+ lastSwitchedAtIso?: string;
1080
+ /**
1081
+ * Short machine-readable cause when {@link available} is `false`, e.g.
1082
+ * `cool-down`, `vehicle-charging`, `charger-error`, `user-pinned-phases`.
1083
+ * Never shown to end users verbatim.
1084
+ */
1085
+ unavailableReason?: string;
1086
+ }
1087
+ /**
1088
+ * The charging energy app's own state, reported to the energy manager.
1089
+ *
1090
+ * One **continuously updated state**, not an event: the app republishes the
1091
+ * complete picture whenever something in it changes (a phase switch starts or
1092
+ * finishes, a cool-down expires, a limit is applied) and periodically as a
1093
+ * heartbeat, so a manager that just started up or missed a message converges on
1094
+ * the current truth from the next one. Every message carries the full payload —
1095
+ * a field is omitted to mean "unknown", never "unchanged".
1096
+ *
1097
+ * The payload is **facts about the charger, never advice about what to do with
1098
+ * it**. It reports the phase count in force, whether a phase switch is possible
1099
+ * right now and until when it is not, the limit actually applied and the power
1100
+ * that limit implies, the verdict on the last request, and when all of this was
1101
+ * observed. It deliberately carries no recommended minimum power, no suggested
1102
+ * setpoint and nothing derived from the energy manager's own plan: the manager
1103
+ * owns the planning, and a second opinion travelling with the measurements only
1104
+ * competes with it. Static nameplate data (supported phase configurations,
1105
+ * ampere step, nameplate power) stays where it already lives, in
1106
+ * {@link EnyoChargerApplianceMetadata}.
1107
+ *
1108
+ * Publish it with `resolution: 'dynamic'`.
1109
+ */
1110
+ export interface EnyoDataBusEnergyManagementChargingStateV1 extends EnyoDataBusMessage {
1111
+ type: 'message';
1112
+ message: EnyoDataBusMessageEnum.EnergyManagementChargingStateV1;
1113
+ /** ID of the charger appliance this state describes */
1114
+ applianceId: string;
1115
+ data: {
1116
+ /**
1117
+ * ISO 8601 timestamp at which this state was observed on the charger.
1118
+ * Distinct from {@link EnyoDataBusMessage.timestampIso}, which is when
1119
+ * the message was sent: a value polled from a charger every 30 s is
1120
+ * already that old when it is published, and the energy manager must be
1121
+ * able to tell a fresh reading from a stale one.
1122
+ */
1123
+ measuredAtIso: string;
1124
+ /**
1125
+ * The phase configuration in force right now — `1` or `3` while the
1126
+ * charger is drawing, `0` when it is not drawing at all.
1127
+ */
1128
+ activePhases: number;
1129
+ /** Whether a phase switch is possible right now, and if not, until when. */
1130
+ phaseSwitching: EnyoChargingPhaseSwitchingState;
1131
+ /**
1132
+ * The current limit per phase actually in force on the charger, in
1133
+ * Amperes — the value the charger is running with, not the one that was
1134
+ * asked for. Omitted when the app cannot read it back.
1135
+ */
1136
+ appliedCurrentLimitA?: number;
1137
+ /**
1138
+ * The active power {@link appliedCurrentLimitA} implies at the phase
1139
+ * count in force, in Watts. Reported alongside the current because the
1140
+ * conversion depends on {@link activePhases} and the mains voltage the
1141
+ * app measured — facts the energy manager would otherwise have to
1142
+ * assume.
1143
+ */
1144
+ appliedPowerW?: number;
1145
+ /**
1146
+ * What became of the last limit request the app received. Omitted when
1147
+ * it has not handled one in this session.
1148
+ */
1149
+ lastLimitRequest?: EnyoChargingLimitRequestOutcome;
1150
+ /** Connector ID on the charge point (optional, for multi-connector chargers) */
1151
+ connectorId?: number;
1152
+ };
1153
+ }
1000
1154
  /**
1001
1155
  * Request message to get a preview of the optimized charging schedule.
1002
1156
  * Sent when user wants to see the charging plan before starting.
@@ -22,7 +22,7 @@
22
22
  * before publishing.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.EnyoOnboardingV2TargetType = exports.EnyoOnboardingV2TransitionSourceKind = exports.EnyoOnboardingV2BlockType = exports.EnyoOnboardingV2ChoiceLayout = exports.EnyoOnboardingV2IconKey = exports.EnyoOnboardingV2DeviceSelection = exports.EnyoOnboardingV2InputValueType = exports.EnyoOnboardingV2OcppConnectOutcome = exports.EnyoOnboardingV2ActionKind = exports.EnyoOnboardingV2DynamicKind = exports.EnyoOnboardingV2HintVariant = exports.EnyoOnboardingV2PauseReason = exports.EnyoOnboardingV2StartVariant = void 0;
25
+ exports.EnyoOnboardingV2TargetType = exports.EnyoOnboardingV2TransitionSourceKind = exports.EnyoOnboardingV2BlockType = exports.EnyoOnboardingV2ChoiceLayout = exports.EnyoOnboardingV2IconKey = exports.EnyoOnboardingV2DeviceSelection = exports.EnyoOnboardingV2InputValueType = exports.EnyoOnboardingV2OcppConnectOutcome = exports.EnyoOnboardingV2EebusPairOutcome = exports.EnyoOnboardingV2ActionKind = exports.EnyoOnboardingV2DynamicKind = exports.EnyoOnboardingV2HintVariant = exports.EnyoOnboardingV2PauseReason = exports.EnyoOnboardingV2StartVariant = void 0;
26
26
  // ---------------------------------------------------------------------------
27
27
  // Enumerable string enums
28
28
  // ---------------------------------------------------------------------------
@@ -118,7 +118,57 @@ var EnyoOnboardingV2ActionKind;
118
118
  * is the common case, not an edge case.
119
119
  */
120
120
  EnyoOnboardingV2ActionKind["OcppConnect"] = "ocpp-connect";
121
+ /**
122
+ * Let the installer pick one of the EEBUS peers discovered on the local
123
+ * network and trust its SKI.
124
+ *
125
+ * EEBUS is the third way a device reaches us: it is neither typed in as an
126
+ * IP address ({@link EnyoOnboardingV2InputValueType.IpAddress}) nor dialling
127
+ * out to our CSMS ({@link OcppConnect}). Heat pumps and wallboxes announce
128
+ * themselves over mDNS/SHIP and are addressed by their **SKI**, so pairing
129
+ * means *choosing one of the announced peers* — a decision only the
130
+ * installer standing in front of the device can make, since two identical
131
+ * heat pumps in one house differ only by manufacturer, model and the last
132
+ * bytes of their SKI.
133
+ *
134
+ * The host app renders the picker from the peers the hub discovered; the
135
+ * guide contributes the trigger label and the branches. Because the list
136
+ * comes from discovery, the guide must have scanned: either it keeps
137
+ * {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its default, or it
138
+ * carries a {@link NetworkScan} block ahead of the pairing block —
139
+ * otherwise the picker opens on an empty list.
140
+ *
141
+ * Outcome `value`s MUST be {@link EnyoOnboardingV2EebusPairOutcome}
142
+ * members. The SKI the installer picked is recorded as the block's input
143
+ * value, so a finished run says *which* peer was paired, and later steps —
144
+ * a {@link DeviceTest}, for instance — can read it back under the block's
145
+ * id.
146
+ */
147
+ EnyoOnboardingV2ActionKind["EebusPair"] = "eebus-pair";
121
148
  })(EnyoOnboardingV2ActionKind || (exports.EnyoOnboardingV2ActionKind = EnyoOnboardingV2ActionKind = {}));
149
+ /**
150
+ * The possible results of an {@link EnyoOnboardingV2ActionKind.EebusPair}
151
+ * block.
152
+ *
153
+ * Three, not two: the two ways pairing fails need different guidance. Nothing
154
+ * was discovered at all is a different conversation from "you picked the right
155
+ * device but the handshake never came up".
156
+ */
157
+ var EnyoOnboardingV2EebusPairOutcome;
158
+ (function (EnyoOnboardingV2EebusPairOutcome) {
159
+ /** The installer picked a peer and the SHIP connection came up. */
160
+ EnyoOnboardingV2EebusPairOutcome["Paired"] = "paired";
161
+ /**
162
+ * Discovery turned up no EEBUS peer — the device is off, on another subnet,
163
+ * or EEBUS is not enabled in its menu.
164
+ */
165
+ EnyoOnboardingV2EebusPairOutcome["NotFound"] = "not-found";
166
+ /**
167
+ * A peer was picked but the SHIP handshake did not complete — the pairing
168
+ * was not confirmed on the device, or a PIN was rejected.
169
+ */
170
+ EnyoOnboardingV2EebusPairOutcome["Failure"] = "failure";
171
+ })(EnyoOnboardingV2EebusPairOutcome || (exports.EnyoOnboardingV2EebusPairOutcome = EnyoOnboardingV2EebusPairOutcome = {}));
122
172
  /**
123
173
  * The possible results of an {@link EnyoOnboardingV2ActionKind.OcppConnect}
124
174
  * block. Deliberately binary: either the charger reached our CSMS or it did not.
@@ -107,7 +107,56 @@ export declare enum EnyoOnboardingV2ActionKind {
107
107
  * members, and both of them must be wired — a charger that never calls home
108
108
  * is the common case, not an edge case.
109
109
  */
110
- OcppConnect = "ocpp-connect"
110
+ OcppConnect = "ocpp-connect",
111
+ /**
112
+ * Let the installer pick one of the EEBUS peers discovered on the local
113
+ * network and trust its SKI.
114
+ *
115
+ * EEBUS is the third way a device reaches us: it is neither typed in as an
116
+ * IP address ({@link EnyoOnboardingV2InputValueType.IpAddress}) nor dialling
117
+ * out to our CSMS ({@link OcppConnect}). Heat pumps and wallboxes announce
118
+ * themselves over mDNS/SHIP and are addressed by their **SKI**, so pairing
119
+ * means *choosing one of the announced peers* — a decision only the
120
+ * installer standing in front of the device can make, since two identical
121
+ * heat pumps in one house differ only by manufacturer, model and the last
122
+ * bytes of their SKI.
123
+ *
124
+ * The host app renders the picker from the peers the hub discovered; the
125
+ * guide contributes the trigger label and the branches. Because the list
126
+ * comes from discovery, the guide must have scanned: either it keeps
127
+ * {@link EnyoOnboardingV2Guide.requiresNetworkScan} at its default, or it
128
+ * carries a {@link NetworkScan} block ahead of the pairing block —
129
+ * otherwise the picker opens on an empty list.
130
+ *
131
+ * Outcome `value`s MUST be {@link EnyoOnboardingV2EebusPairOutcome}
132
+ * members. The SKI the installer picked is recorded as the block's input
133
+ * value, so a finished run says *which* peer was paired, and later steps —
134
+ * a {@link DeviceTest}, for instance — can read it back under the block's
135
+ * id.
136
+ */
137
+ EebusPair = "eebus-pair"
138
+ }
139
+ /**
140
+ * The possible results of an {@link EnyoOnboardingV2ActionKind.EebusPair}
141
+ * block.
142
+ *
143
+ * Three, not two: the two ways pairing fails need different guidance. Nothing
144
+ * was discovered at all is a different conversation from "you picked the right
145
+ * device but the handshake never came up".
146
+ */
147
+ export declare enum EnyoOnboardingV2EebusPairOutcome {
148
+ /** The installer picked a peer and the SHIP connection came up. */
149
+ Paired = "paired",
150
+ /**
151
+ * Discovery turned up no EEBUS peer — the device is off, on another subnet,
152
+ * or EEBUS is not enabled in its menu.
153
+ */
154
+ NotFound = "not-found",
155
+ /**
156
+ * A peer was picked but the SHIP handshake did not complete — the pairing
157
+ * was not confirmed on the device, or a PIN was rejected.
158
+ */
159
+ Failure = "failure"
111
160
  }
112
161
  /**
113
162
  * The possible results of an {@link EnyoOnboardingV2ActionKind.OcppConnect}
@@ -565,7 +614,9 @@ export interface EnyoOnboardingV2Guide {
565
614
  * A guide that opts out cannot rely on scan results, so
566
615
  * {@link EnyoOnboardingV2DeviceSelection.Detected} has nothing to select from
567
616
  * unless the guide runs its own
568
- * {@link EnyoOnboardingV2ActionKind.NetworkScan} block first.
617
+ * {@link EnyoOnboardingV2ActionKind.NetworkScan} block first, and an
618
+ * {@link EnyoOnboardingV2ActionKind.EebusPair} block would offer the
619
+ * installer an empty list of peers.
569
620
  */
570
621
  requiresNetworkScan?: boolean;
571
622
  /** Optional translated summary shown in the library (de/en). */
@@ -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.193';
12
+ exports.SDK_VERSION = '0.0.194';
13
13
  /**
14
14
  * Gets the current SDK version.
15
15
  * @returns The semantic version string of the SDK
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export declare const SDK_VERSION = "0.0.193";
8
+ export declare const SDK_VERSION = "0.0.194";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK