@enyo-energy/sunspec-sdk 0.0.70 → 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 (38) hide show
  1. package/README.md +302 -0
  2. package/dist/calibration-snapshot-service.d.ts +67 -0
  3. package/dist/calibration-snapshot-service.js +160 -0
  4. package/dist/cjs/calibration-snapshot-service.cjs +164 -0
  5. package/dist/cjs/calibration-snapshot-service.d.cts +67 -0
  6. package/dist/cjs/index.cjs +30 -1
  7. package/dist/cjs/index.d.cts +6 -0
  8. package/dist/cjs/sunspec-battery-calibration-driver.cjs +158 -0
  9. package/dist/cjs/sunspec-battery-calibration-driver.d.cts +63 -0
  10. package/dist/cjs/sunspec-battery-feature-calibrator.cjs +350 -0
  11. package/dist/cjs/sunspec-battery-feature-calibrator.d.cts +89 -0
  12. package/dist/cjs/sunspec-battery-schedule-handler.cjs +92 -0
  13. package/dist/cjs/sunspec-battery-schedule-handler.d.cts +67 -0
  14. package/dist/cjs/sunspec-calibration-storage.cjs +47 -0
  15. package/dist/cjs/sunspec-calibration-storage.d.cts +24 -0
  16. package/dist/cjs/sunspec-devices.cjs +407 -104
  17. package/dist/cjs/sunspec-devices.d.cts +112 -6
  18. package/dist/cjs/sunspec-interfaces.cjs +42 -1
  19. package/dist/cjs/sunspec-interfaces.d.cts +66 -0
  20. package/dist/cjs/version.cjs +1 -1
  21. package/dist/cjs/version.d.cts +1 -1
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.js +12 -0
  24. package/dist/sunspec-battery-calibration-driver.d.ts +63 -0
  25. package/dist/sunspec-battery-calibration-driver.js +154 -0
  26. package/dist/sunspec-battery-feature-calibrator.d.ts +89 -0
  27. package/dist/sunspec-battery-feature-calibrator.js +345 -0
  28. package/dist/sunspec-battery-schedule-handler.d.ts +67 -0
  29. package/dist/sunspec-battery-schedule-handler.js +88 -0
  30. package/dist/sunspec-calibration-storage.d.ts +24 -0
  31. package/dist/sunspec-calibration-storage.js +42 -0
  32. package/dist/sunspec-devices.d.ts +112 -6
  33. package/dist/sunspec-devices.js +408 -105
  34. package/dist/sunspec-interfaces.d.ts +66 -0
  35. package/dist/sunspec-interfaces.js +41 -0
  36. package/dist/version.d.ts +1 -1
  37. package/dist/version.js +1 -1
  38. package/package.json +7 -3
@@ -1,10 +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 { BatteryCalibrator, type BatteryCalibratorConfig, type CalibrationResultStore, type CalibrationSnapshot, type RestoreReason, SnapshotService } from "@enyo-energy/appliance-calibration";
8
9
  import { EnergyAppDataBus } from "@enyo-energy/energy-app-sdk/dist/packages/energy-app-data-bus.js";
9
10
  /**
10
11
  * Base abstract class for all Sunspec devices
@@ -25,6 +26,13 @@ export declare abstract class BaseSunspecDevice {
25
26
  protected dataBus?: EnergyAppDataBus;
26
27
  protected retryManager: ConnectionRetryManager;
27
28
  protected consecutiveReconnectFailures: number;
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-";
28
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);
29
37
  /**
30
38
  * Connect to the device and create/update the appliance
@@ -77,6 +85,12 @@ export declare abstract class BaseSunspecDevice {
77
85
  */
78
86
  protected markOffline(): Promise<void>;
79
87
  protected sendCommandAcknowledge(messageId: string, acknowledgeMessage: EnyoDataBusMessageEnum | string, answer: EnyoCommandAcknowledgeAnswerEnum, rejectionReason?: string): void;
88
+ /**
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.
92
+ */
93
+ protected buildSnapshotService<T>(onRestore: (snapshot: CalibrationSnapshot<T>, reason: RestoreReason) => Promise<void>): SnapshotService<T> | undefined;
80
94
  }
81
95
  /**
82
96
  * Sunspec Inverter implementation using dynamic model discovery
@@ -87,6 +101,7 @@ export declare class SunspecInverter extends BaseSunspecDevice {
87
101
  private static readonly CONNECTION_FAULT_THRESHOLD;
88
102
  private storage?;
89
103
  private errorState;
104
+ private snapshotService?;
90
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);
91
106
  connect(): Promise<void>;
92
107
  disconnect(): Promise<void>;
@@ -156,13 +171,77 @@ export declare class SunspecInverter extends BaseSunspecDevice {
156
171
  stopDataBusListening(): void;
157
172
  private handleInverterCommand;
158
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;
180
+ private handleStartCalibration;
181
+ private handleStopCalibration;
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;
159
190
  }
160
191
  /**
161
192
  * Sunspec Battery implementation
162
193
  */
163
194
  export declare class SunspecBattery extends BaseSunspecDevice {
195
+ private readonly featureMode;
164
196
  private readonly capabilities;
165
- 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;
166
245
  /**
167
246
  * Connect to the battery and create/update the appliance
168
247
  */
@@ -284,10 +363,30 @@ export declare class SunspecBattery extends BaseSunspecDevice {
284
363
  */
285
364
  stopDataBusListening(): void;
286
365
  private handleStorageCommand;
287
- private handleStartGridCharge;
288
- private handleStopGridCharge;
289
- private handleSetDischargeLimit;
290
- 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;
381
+ private handleStartCalibration;
382
+ private handleStopCalibration;
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;
291
390
  }
292
391
  /**
293
392
  * Sunspec Meter implementation
@@ -303,6 +402,13 @@ export declare class SunspecMeter extends BaseSunspecDevice {
303
402
  * Disconnect from the meter and update appliance state
304
403
  */
305
404
  disconnect(): Promise<void>;
405
+ /**
406
+ * Meter does not implement calibration; it only subscribes to Start/StopCalibrationV1 to
407
+ * answer NotSupported (per the data-bus contract that every command must be acknowledged).
408
+ */
409
+ startDataBusListening(): void;
410
+ stopDataBusListening(): void;
411
+ private handleMeterCommand;
306
412
  /**
307
413
  * Update meter data and return data bus messages
308
414
  */