@enyo-energy/sunspec-sdk 0.0.71 → 0.0.72

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 (34) hide show
  1. package/README.md +302 -0
  2. package/dist/cjs/index.cjs +30 -2
  3. package/dist/cjs/index.d.cts +6 -1
  4. package/dist/cjs/sunspec-battery-calibration-driver.cjs +158 -0
  5. package/dist/cjs/sunspec-battery-calibration-driver.d.cts +63 -0
  6. package/dist/cjs/sunspec-battery-feature-calibrator.cjs +350 -0
  7. package/dist/cjs/sunspec-battery-feature-calibrator.d.cts +89 -0
  8. package/dist/cjs/sunspec-battery-schedule-handler.cjs +92 -0
  9. package/dist/cjs/sunspec-battery-schedule-handler.d.cts +67 -0
  10. package/dist/cjs/sunspec-calibration-storage.cjs +47 -0
  11. package/dist/cjs/sunspec-calibration-storage.d.cts +24 -0
  12. package/dist/cjs/sunspec-devices.cjs +270 -215
  13. package/dist/cjs/sunspec-devices.d.cts +99 -19
  14. package/dist/cjs/sunspec-interfaces.cjs +42 -1
  15. package/dist/cjs/sunspec-interfaces.d.cts +66 -0
  16. package/dist/cjs/version.cjs +1 -1
  17. package/dist/cjs/version.d.cts +1 -1
  18. package/dist/index.d.ts +6 -1
  19. package/dist/index.js +12 -1
  20. package/dist/sunspec-battery-calibration-driver.d.ts +63 -0
  21. package/dist/sunspec-battery-calibration-driver.js +154 -0
  22. package/dist/sunspec-battery-feature-calibrator.d.ts +89 -0
  23. package/dist/sunspec-battery-feature-calibrator.js +345 -0
  24. package/dist/sunspec-battery-schedule-handler.d.ts +67 -0
  25. package/dist/sunspec-battery-schedule-handler.js +88 -0
  26. package/dist/sunspec-calibration-storage.d.ts +24 -0
  27. package/dist/sunspec-calibration-storage.js +42 -0
  28. package/dist/sunspec-devices.d.ts +99 -19
  29. package/dist/sunspec-devices.js +271 -216
  30. package/dist/sunspec-interfaces.d.ts +66 -0
  31. package/dist/sunspec-interfaces.js +41 -0
  32. package/dist/version.d.ts +1 -1
  33. package/dist/version.js +1 -1
  34. package/package.json +7 -3
@@ -1,11 +1,11 @@
1
- import { type IRetryConfig, type SunspecBatteryBaseData, SunspecBatteryCapability, type SunspecBatteryControls, type SunspecInverterData, SunspecInverterCapability, SunspecMeterCapability, SunspecStorageMode } from "./sunspec-interfaces.js";
1
+ import { type IRetryConfig, type SunspecBatteryBaseData, SunspecBatteryCapability, type SunspecBatteryControls, type SunspecBatteryFeatureMode, type SunspecInverterData, SunspecInverterCapability, SunspecMeterCapability, SunspecStorageMode } from "./sunspec-interfaces.js";
2
2
  import { ApplianceManager, EnergyApp } from "@enyo-energy/energy-app-sdk";
3
3
  import { type EnyoAppliance, type EnyoApplianceErrorCode, EnyoApplianceName } from "@enyo-energy/energy-app-sdk/dist/types/enyo-appliance.js";
4
4
  import { EnyoNetworkDevice } from "@enyo-energy/energy-app-sdk/dist/types/enyo-network-device.js";
5
5
  import { SunspecModbusClient } from "./sunspec-modbus-client.js";
6
6
  import { ConnectionRetryManager } from "./connection-retry-manager.js";
7
7
  import { EnyoCommandAcknowledgeAnswerEnum, EnyoDataBusMessage, EnyoDataBusMessageEnum, EnyoDataBusMessageResolution } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
8
- import { type CalibrationDeviceType, type CalibrationRestoreReason, type CalibrationSnapshot, CalibrationSnapshotService } from "./calibration-snapshot-service.js";
8
+ import { BatteryCalibrator, type BatteryCalibratorConfig, type CalibrationResultStore, type CalibrationSnapshot, type RestoreReason, SnapshotService } from "@enyo-energy/appliance-calibration";
9
9
  import { EnergyAppDataBus } from "@enyo-energy/energy-app-sdk/dist/packages/energy-app-data-bus.js";
10
10
  /**
11
11
  * Base abstract class for all Sunspec devices
@@ -26,7 +26,13 @@ export declare abstract class BaseSunspecDevice {
26
26
  protected dataBus?: EnergyAppDataBus;
27
27
  protected retryManager: ConnectionRetryManager;
28
28
  protected consecutiveReconnectFailures: number;
29
- protected calibrationService?: CalibrationSnapshotService;
29
+ /**
30
+ * Prefix used when persisting calibration snapshots via the library's
31
+ * {@link SnapshotService}. Kept identical to the key the SDK used before
32
+ * the migration to `@enyo-energy/appliance-calibration` so existing
33
+ * snapshots stored by older builds are still picked up on startup.
34
+ */
35
+ protected static readonly CALIBRATION_SNAPSHOT_KEY_PREFIX = "sunspec-calibration-snapshot-";
30
36
  constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, retryConfig?: IRetryConfig, appliance?: EnyoAppliance, useTls?: boolean | undefined);
31
37
  /**
32
38
  * Connect to the device and create/update the appliance
@@ -80,16 +86,11 @@ export declare abstract class BaseSunspecDevice {
80
86
  protected markOffline(): Promise<void>;
81
87
  protected sendCommandAcknowledge(messageId: string, acknowledgeMessage: EnyoDataBusMessageEnum | string, answer: EnyoCommandAcknowledgeAnswerEnum, rejectionReason?: string): void;
82
88
  /**
83
- * Lazily construct and initialize the per-appliance CalibrationSnapshotService. Reloads
84
- * any persisted snapshot from storage so an in-flight calibration survives restarts.
85
- * Idempotent subsequent calls are no-ops once the service exists.
86
- */
87
- protected initCalibrationService(deviceType: CalibrationDeviceType): Promise<void>;
88
- /**
89
- * Subclasses implement how to write the modified fields of a snapshot back to the device.
90
- * Called both on explicit StopCalibrationV1 and when the 5-minute auto-stop fires.
89
+ * Build a typed {@link SnapshotService} bound to this appliance's calibration storage,
90
+ * using the legacy SDK storage key prefix so prior installs upgrade seamlessly. Returns
91
+ * undefined if the appliance has not been registered yet.
91
92
  */
92
- protected restoreFromCalibrationSnapshot(_snapshot: CalibrationSnapshot, _reason: CalibrationRestoreReason): Promise<void>;
93
+ protected buildSnapshotService<T>(onRestore: (snapshot: CalibrationSnapshot<T>, reason: RestoreReason) => Promise<void>): SnapshotService<T> | undefined;
93
94
  }
94
95
  /**
95
96
  * Sunspec Inverter implementation using dynamic model discovery
@@ -100,6 +101,7 @@ export declare class SunspecInverter extends BaseSunspecDevice {
100
101
  private static readonly CONNECTION_FAULT_THRESHOLD;
101
102
  private storage?;
102
103
  private errorState;
104
+ private snapshotService?;
103
105
  constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecInverterCapability[], retryConfig?: IRetryConfig, appliance?: EnyoAppliance, useTls?: boolean);
104
106
  connect(): Promise<void>;
105
107
  disconnect(): Promise<void>;
@@ -169,16 +171,77 @@ export declare class SunspecInverter extends BaseSunspecDevice {
169
171
  stopDataBusListening(): void;
170
172
  private handleInverterCommand;
171
173
  private handleSetFeedInLimit;
174
+ /**
175
+ * Lazily construct the per-appliance {@link SnapshotService}. Reloads any
176
+ * persisted snapshot from storage so an in-flight calibration survives
177
+ * process restarts. Idempotent.
178
+ */
179
+ private initSnapshotService;
172
180
  private handleStartCalibration;
173
181
  private handleStopCalibration;
174
- protected restoreFromCalibrationSnapshot(snapshot: CalibrationSnapshot, reason: CalibrationRestoreReason): Promise<void>;
182
+ /**
183
+ * `onRestore` callback for the inverter's {@link SnapshotService}. Writes only the
184
+ * subset of writable inverter fields that other commands actually touched during the
185
+ * calibration. Catches and logs failures rather than throwing — the snapshot has
186
+ * already been removed from storage by the time this runs, so a throw is unrecoverable
187
+ * and is best logged for operator action.
188
+ */
189
+ private restoreInverterSnapshot;
175
190
  }
176
191
  /**
177
192
  * Sunspec Battery implementation
178
193
  */
179
194
  export declare class SunspecBattery extends BaseSunspecDevice {
195
+ private readonly featureMode;
180
196
  private readonly capabilities;
181
- constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecBatteryCapability[], retryConfig?: IRetryConfig, appliance?: EnyoAppliance, useTls?: boolean);
197
+ private snapshotService?;
198
+ private calibrationDriver?;
199
+ private batteryCalibrator?;
200
+ private calibrationResultStore?;
201
+ private scheduleHandler;
202
+ /**
203
+ * Battery features that imply outbound control writes from the host action-taker.
204
+ * These are stripped from `appliance.battery.features` until the calibration result
205
+ * store says this battery has been successfully calibrated — see
206
+ * {@link computeAdvertisedFeatures}.
207
+ */
208
+ private static readonly CONTROLLABLE_FEATURES;
209
+ constructor(energyApp: EnergyApp, name: EnyoApplianceName[], networkDevice: EnyoNetworkDevice, sunspecClient: SunspecModbusClient, applianceManager: ApplianceManager, featureMode: SunspecBatteryFeatureMode, unitId?: number, port?: number, baseAddress?: number, capabilities?: SunspecBatteryCapability[], retryConfig?: IRetryConfig, appliance?: EnyoAppliance, useTls?: boolean);
210
+ /**
211
+ * Wire the battery into `@enyo-energy/appliance-calibration`'s
212
+ * `BatteryCalibrator` test-charge flow. Call once after {@link connect}.
213
+ *
214
+ * Consumers own the `CalibrationResultStore` (shared across appliances so
215
+ * the persisted result map doesn't get clobbered) and the
216
+ * `CalibrationTrigger` that drives `runCalibration()` on whatever schedule
217
+ * makes sense for the host. Pass overrides for the calibrator's defaults
218
+ * (`testPowerW`, response thresholds, etc.) via `opts.config`.
219
+ */
220
+ configureCalibration(opts: {
221
+ resultStore: CalibrationResultStore;
222
+ config?: Partial<BatteryCalibratorConfig>;
223
+ }): BatteryCalibrator<SunspecBatteryControls>;
224
+ /**
225
+ * Detect which battery features the device's registers expose. This is the
226
+ * raw, register-only view; the {@link featureMode} configured at
227
+ * construction decides what is actually published — see
228
+ * {@link resolveAdvertisedFeatures}.
229
+ */
230
+ private detectFromRegisters;
231
+ /**
232
+ * Resolve `appliance.battery.features` for the configured mode. Called on
233
+ * every connect() and readData() cycle so that, in calibration-based mode,
234
+ * the controllable features appear as soon as the calibrator flips
235
+ * `isCalibrated` (no synchronous push).
236
+ */
237
+ private resolveAdvertisedFeatures;
238
+ /**
239
+ * Returns the per-battery `BatteryCalibrator` created by
240
+ * {@link configureCalibration}, or `undefined` if calibration was never
241
+ * configured. Consumers register the returned instance with their own
242
+ * `CalibrationTrigger`.
243
+ */
244
+ getBatteryCalibrator(): BatteryCalibrator<SunspecBatteryControls> | undefined;
182
245
  /**
183
246
  * Connect to the battery and create/update the appliance
184
247
  */
@@ -300,13 +363,30 @@ export declare class SunspecBattery extends BaseSunspecDevice {
300
363
  */
301
364
  stopDataBusListening(): void;
302
365
  private handleStorageCommand;
303
- private handleStartGridCharge;
304
- private handleStopGridCharge;
305
- private handleSetDischargeLimit;
306
- private handleSetChargeLimit;
366
+ /**
367
+ * Acknowledge a SetStorageScheduleV1 message. The actual schedule application
368
+ * is owned by `this.scheduleHandler` (subscribed independently via its own
369
+ * data-bus listener registered in its constructor). The ack reports "received
370
+ * & queued" rather than "applied" — schedule entries play out over time, and
371
+ * per-entry write failures land in `console.error` via the handler's
372
+ * onChange wrapper.
373
+ */
374
+ private handleSetStorageScheduleAck;
375
+ /**
376
+ * Lazily construct the per-appliance {@link SnapshotService}. Reloads any
377
+ * persisted snapshot from storage so an in-flight calibration survives
378
+ * process restarts. Idempotent.
379
+ */
380
+ private initSnapshotService;
307
381
  private handleStartCalibration;
308
382
  private handleStopCalibration;
309
- protected restoreFromCalibrationSnapshot(snapshot: CalibrationSnapshot, reason: CalibrationRestoreReason): Promise<void>;
383
+ /**
384
+ * `onRestore` callback for the battery's {@link SnapshotService}. Writes only the
385
+ * subset of writable battery fields touched during the calibration. Errors are
386
+ * caught and logged — by the time this fires the snapshot is gone from storage,
387
+ * so a throw would just propagate into the void.
388
+ */
389
+ private restoreBatterySnapshot;
310
390
  }
311
391
  /**
312
392
  * Sunspec Meter implementation