@enyo-energy/sunspec-sdk 0.0.73 → 0.0.74

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/README.md CHANGED
@@ -332,7 +332,11 @@ See [`@enyo-energy/appliance-calibration`'s README](https://www.npmjs.com/packag
332
332
  3. Activates the first entry immediately, then advances to subsequent entries as their `seconds` offsets elapse on a 1-second tick (driven by `EnergyApp.useInterval()`).
333
333
  4. Each `Charge` entry writes `chaGriSet=GRID`, `inWRte = powerW / installedWChaMax × 100`, `storCtlMod=CHARGE`.
334
334
  5. Each `Discharge` entry writes `chaGriSet=PV`, `outWRte = powerW / installedWChaMax × 100`, `storCtlMod=DISCHARGE`.
335
- 6. On `mode: auto`, a replacement schedule, `disconnect()`, or process restart with an active schedule still persisted, the SDK restores the snapshotted pre-schedule registers via `onRollback`.
335
+ 6. Restores the snapshotted pre-schedule registers (`storCtlMod`, `chaGriSet`, `wChaMax`, `inWRte`, `outWRte`) **only on `mode: auto`, `disconnect()`, or process-restart recovery** not when one `mode: schedule` is replaced by another. Schedule-to-schedule replacement keeps the device on the active register set and lets the new schedule's first entry take over directly, so consecutive schedules don't leak a `storCtlMod=AUTO` (`0x3`) write between them. The pre-schedule snapshot stays sticky across every replacement until one of the three terminal events fires.
336
+
337
+ ### Register write order
338
+
339
+ `writeBatteryControls` issues each register write sequentially in this order so the device never sees a stale-parameter window when the control mode changes: `chaGriSet → wChaMax → inWRte → outWRte → minRsvPct → storCtlMod`. Source pin and the limit/rate parameters land first; the control mode is written last so the device only "starts acting" once every governing value is fresh.
336
340
 
337
341
  ### Power cap
338
342
 
@@ -18,6 +18,23 @@ class SunspecBatteryScheduleHandler extends storage_schedule_handler_js_1.Storag
18
18
  getSnapshotService;
19
19
  onErrorCallback;
20
20
  installedWChaMax;
21
+ /**
22
+ * Sticky pre-schedule snapshot, captured once on the first `onInit` and
23
+ * held across every subsequent schedule-to-schedule replacement. Cleared
24
+ * only when a real rollback fires (`mode: auto` from the data bus or
25
+ * `dispose`). Lets the eventual restore write the *true* baseline rather
26
+ * than the last-active-entry register set that the device happens to be
27
+ * in at the moment of replacement.
28
+ */
29
+ originalBaseline;
30
+ /**
31
+ * Set inside the overridden `applyMessage` when an incoming
32
+ * `mode: schedule` message would replace an already-running schedule.
33
+ * Consumed (and reset) inside `onRollback` so the base library's
34
+ * automatic `doReleaseSchedule → onRollback` step does not actually
35
+ * write the snapshot back during a replacement.
36
+ */
37
+ suppressNextRollbackWrite = false;
21
38
  constructor(opts) {
22
39
  super(opts);
23
40
  this.sunspecClient = opts.sunspecClient;
@@ -26,19 +43,53 @@ class SunspecBatteryScheduleHandler extends storage_schedule_handler_js_1.Storag
26
43
  this.getSnapshotService = opts.getSnapshotService;
27
44
  this.onErrorCallback = opts.onErrorCallback;
28
45
  }
46
+ /**
47
+ * Override the base-class data-bus router so a schedule-to-schedule
48
+ * replacement marks the next `onRollback` as "skip the write". The base
49
+ * library still owns the actual schedule lifecycle — we just steer one
50
+ * decision inside `onRollback`. `mode: auto` and any path that does not
51
+ * have an active schedule fall through unchanged, so the rollback fires
52
+ * normally there.
53
+ */
54
+ async applyMessage(msg) {
55
+ if (msg.applianceId === this.applianceIdForLog
56
+ && msg.data.mode === enyo_data_bus_value_js_1.EnyoStorageScheduleModeEnum.Schedule
57
+ && this.getActiveEntry() !== undefined) {
58
+ this.suppressNextRollbackWrite = true;
59
+ }
60
+ try {
61
+ await super.applyMessage(msg);
62
+ }
63
+ finally {
64
+ // Defence in depth: if the base class skipped the rollback for
65
+ // any reason (validation error, disposed, etc.), the flag would
66
+ // otherwise stay set and silently swallow the next real rollback.
67
+ this.suppressNextRollbackWrite = false;
68
+ }
69
+ }
29
70
  async onInit(_active) {
71
+ if (this.originalBaseline !== undefined) {
72
+ // Replacement install: keep handing the library the sticky
73
+ // baseline so the persisted snapshot continues to point at the
74
+ // original pre-schedule state. The library will overwrite its
75
+ // storage row with the same value — harmless.
76
+ this.installedWChaMax = this.originalBaseline.wChaMax;
77
+ return { ...this.originalBaseline };
78
+ }
30
79
  const controls = await this.sunspecClient.readBatteryControls(this.unitId);
31
80
  if (!controls) {
32
81
  throw new Error(`SunspecBatteryScheduleHandler ${this.applianceIdForLog}: failed to read pre-schedule controls`);
33
82
  }
34
- this.installedWChaMax = controls.wChaMax;
35
- return {
83
+ const baseline = {
36
84
  storCtlMod: controls.storCtlMod,
37
85
  chaGriSet: controls.chaGriSet,
38
86
  wChaMax: controls.wChaMax,
39
87
  inWRte: controls.inWRte,
40
88
  outWRte: controls.outWRte,
41
89
  };
90
+ this.originalBaseline = baseline;
91
+ this.installedWChaMax = baseline.wChaMax;
92
+ return { ...baseline };
42
93
  }
43
94
  onChange(active, _previous) {
44
95
  void this.applyEntry(active).catch(err => {
@@ -46,6 +97,25 @@ class SunspecBatteryScheduleHandler extends storage_schedule_handler_js_1.Storag
46
97
  });
47
98
  }
48
99
  onRollback(registers) {
100
+ if (this.suppressNextRollbackWrite) {
101
+ // Schedule-to-schedule replacement. Do NOT write the snapshot
102
+ // back; the new schedule's first `onChange` will own the
103
+ // register state. `installedWChaMax` stays valid (set in
104
+ // onInit) so the very next applyEntry has a baseline to divide
105
+ // against — this is the fix for the
106
+ // "no usable wChaMax baseline (installedWChaMax=undefined)"
107
+ // race seen in production logs.
108
+ this.suppressNextRollbackWrite = false;
109
+ return;
110
+ }
111
+ // Real rollback (mode: auto, dispose, restart recovery). Clear the
112
+ // sticky baseline so the next `onInit` re-reads the device state.
113
+ // Important: clear synchronously here — NOT in the async finally
114
+ // that follows — so a concurrent `onInit` queued behind this one
115
+ // (impossible today, but defensive) cannot observe a half-cleared
116
+ // state.
117
+ this.originalBaseline = undefined;
118
+ this.installedWChaMax = undefined;
49
119
  void (async () => {
50
120
  try {
51
121
  await this.sunspecClient.writeBatteryControls(this.unitId, registers);
@@ -56,9 +126,6 @@ class SunspecBatteryScheduleHandler extends storage_schedule_handler_js_1.Storag
56
126
  catch (err) {
57
127
  console.error(`SunspecBatteryScheduleHandler ${this.applianceIdForLog}: onRollback failed: ${err}`);
58
128
  }
59
- finally {
60
- this.installedWChaMax = undefined;
61
- }
62
129
  })();
63
130
  }
64
131
  onError(err) {
@@ -1,4 +1,5 @@
1
1
  import { StorageScheduleHandler, type ActiveStorageScheduleEntry, type StorageScheduleHandlerOptions } from "@enyo-energy/energy-app-sdk/dist/implementations/storage/storage-schedule-handler.js";
2
+ import { type EnyoDataBusSetStorageScheduleV1 } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
2
3
  import { type SnapshotService } from "@enyo-energy/appliance-calibration";
3
4
  import { type SunspecBatteryControls } from "./sunspec-interfaces.cjs";
4
5
  /**
@@ -58,7 +59,33 @@ export declare class SunspecBatteryScheduleHandler extends StorageScheduleHandle
58
59
  private readonly getSnapshotService;
59
60
  private readonly onErrorCallback?;
60
61
  private installedWChaMax;
62
+ /**
63
+ * Sticky pre-schedule snapshot, captured once on the first `onInit` and
64
+ * held across every subsequent schedule-to-schedule replacement. Cleared
65
+ * only when a real rollback fires (`mode: auto` from the data bus or
66
+ * `dispose`). Lets the eventual restore write the *true* baseline rather
67
+ * than the last-active-entry register set that the device happens to be
68
+ * in at the moment of replacement.
69
+ */
70
+ private originalBaseline?;
71
+ /**
72
+ * Set inside the overridden `applyMessage` when an incoming
73
+ * `mode: schedule` message would replace an already-running schedule.
74
+ * Consumed (and reset) inside `onRollback` so the base library's
75
+ * automatic `doReleaseSchedule → onRollback` step does not actually
76
+ * write the snapshot back during a replacement.
77
+ */
78
+ private suppressNextRollbackWrite;
61
79
  constructor(opts: SunspecBatteryScheduleHandlerOptions);
80
+ /**
81
+ * Override the base-class data-bus router so a schedule-to-schedule
82
+ * replacement marks the next `onRollback` as "skip the write". The base
83
+ * library still owns the actual schedule lifecycle — we just steer one
84
+ * decision inside `onRollback`. `mode: auto` and any path that does not
85
+ * have an active schedule fall through unchanged, so the rollback fires
86
+ * normally there.
87
+ */
88
+ applyMessage(msg: EnyoDataBusSetStorageScheduleV1): Promise<void>;
62
89
  protected onInit(_active: ActiveStorageScheduleEntry): Promise<SunspecScheduleRegisters>;
63
90
  protected onChange(active: ActiveStorageScheduleEntry, _previous: ActiveStorageScheduleEntry | undefined): void;
64
91
  protected onRollback(registers: SunspecScheduleRegisters): void;
@@ -1666,11 +1666,11 @@ class SunspecModbusClient {
1666
1666
  const baseAddr = model.address;
1667
1667
  console.log(`Writing Battery Controls to Model 124 at base address: ${baseAddr} (unit ${unitId})`);
1668
1668
  try {
1669
- // Write storage control mode (Register 5)
1670
- if (controls.storCtlMod !== undefined) {
1671
- await this.writeRegisterValue(unitId, baseAddr + 5, controls.storCtlMod, 'uint16');
1672
- console.log(`Set storage control mode to 0x${controls.storCtlMod.toString(16)}`);
1673
- }
1669
+ // Write order: source pin and parameter writes land BEFORE the
1670
+ // control mode so the device only "starts acting" once every
1671
+ // value that governs the action is fresh. The reverse order
1672
+ // leaks a Modbus RTT-sized window where storCtlMod sees stale
1673
+ // chaGriSet / wChaMax / inWRte / outWRte.
1674
1674
  // Write charge source setting (Register 17)
1675
1675
  if (controls.chaGriSet !== undefined) {
1676
1676
  await this.writeRegisterValue(unitId, baseAddr + 17, controls.chaGriSet, 'uint16');
@@ -1708,6 +1708,13 @@ class SunspecModbusClient {
1708
1708
  await this.writeRegisterValue(unitId, baseAddr + 7, scaledValue, 'uint16');
1709
1709
  console.log(`Set minimum reserve to ${controls.minRsvPct}% (scaled: ${scaledValue})`);
1710
1710
  }
1711
+ // Storage control mode (Register 5) — written LAST so all
1712
+ // governing parameters are already in place when the device
1713
+ // transitions into the new mode.
1714
+ if (controls.storCtlMod !== undefined) {
1715
+ await this.writeRegisterValue(unitId, baseAddr + 5, controls.storCtlMod, 'uint16');
1716
+ console.log(`Set storage control mode to 0x${controls.storCtlMod.toString(16)}`);
1717
+ }
1711
1718
  console.log('Battery controls written successfully');
1712
1719
  return true;
1713
1720
  }
@@ -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.73';
12
+ exports.SDK_VERSION = '0.0.74';
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.73";
8
+ export declare const SDK_VERSION = "0.0.74";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
@@ -1,4 +1,5 @@
1
1
  import { StorageScheduleHandler, type ActiveStorageScheduleEntry, type StorageScheduleHandlerOptions } from "@enyo-energy/energy-app-sdk/dist/implementations/storage/storage-schedule-handler.js";
2
+ import { type EnyoDataBusSetStorageScheduleV1 } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
2
3
  import { type SnapshotService } from "@enyo-energy/appliance-calibration";
3
4
  import { type SunspecBatteryControls } from "./sunspec-interfaces.js";
4
5
  /**
@@ -58,7 +59,33 @@ export declare class SunspecBatteryScheduleHandler extends StorageScheduleHandle
58
59
  private readonly getSnapshotService;
59
60
  private readonly onErrorCallback?;
60
61
  private installedWChaMax;
62
+ /**
63
+ * Sticky pre-schedule snapshot, captured once on the first `onInit` and
64
+ * held across every subsequent schedule-to-schedule replacement. Cleared
65
+ * only when a real rollback fires (`mode: auto` from the data bus or
66
+ * `dispose`). Lets the eventual restore write the *true* baseline rather
67
+ * than the last-active-entry register set that the device happens to be
68
+ * in at the moment of replacement.
69
+ */
70
+ private originalBaseline?;
71
+ /**
72
+ * Set inside the overridden `applyMessage` when an incoming
73
+ * `mode: schedule` message would replace an already-running schedule.
74
+ * Consumed (and reset) inside `onRollback` so the base library's
75
+ * automatic `doReleaseSchedule → onRollback` step does not actually
76
+ * write the snapshot back during a replacement.
77
+ */
78
+ private suppressNextRollbackWrite;
61
79
  constructor(opts: SunspecBatteryScheduleHandlerOptions);
80
+ /**
81
+ * Override the base-class data-bus router so a schedule-to-schedule
82
+ * replacement marks the next `onRollback` as "skip the write". The base
83
+ * library still owns the actual schedule lifecycle — we just steer one
84
+ * decision inside `onRollback`. `mode: auto` and any path that does not
85
+ * have an active schedule fall through unchanged, so the rollback fires
86
+ * normally there.
87
+ */
88
+ applyMessage(msg: EnyoDataBusSetStorageScheduleV1): Promise<void>;
62
89
  protected onInit(_active: ActiveStorageScheduleEntry): Promise<SunspecScheduleRegisters>;
63
90
  protected onChange(active: ActiveStorageScheduleEntry, _previous: ActiveStorageScheduleEntry | undefined): void;
64
91
  protected onRollback(registers: SunspecScheduleRegisters): void;
@@ -1,5 +1,5 @@
1
1
  import { StorageScheduleHandler, } from "@enyo-energy/energy-app-sdk/dist/implementations/storage/storage-schedule-handler.js";
2
- import { EnyoStorageScheduleDirectionEnum } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
2
+ import { EnyoStorageScheduleDirectionEnum, EnyoStorageScheduleModeEnum, } from "@enyo-energy/energy-app-sdk/dist/types/enyo-data-bus-value.js";
3
3
  import { SunspecChargeSource, SunspecStorageControlMode, } from "./sunspec-interfaces.js";
4
4
  /**
5
5
  * Concrete `StorageScheduleHandler` for SunSpec Model 124 batteries. The base
@@ -15,6 +15,23 @@ export class SunspecBatteryScheduleHandler extends StorageScheduleHandler {
15
15
  getSnapshotService;
16
16
  onErrorCallback;
17
17
  installedWChaMax;
18
+ /**
19
+ * Sticky pre-schedule snapshot, captured once on the first `onInit` and
20
+ * held across every subsequent schedule-to-schedule replacement. Cleared
21
+ * only when a real rollback fires (`mode: auto` from the data bus or
22
+ * `dispose`). Lets the eventual restore write the *true* baseline rather
23
+ * than the last-active-entry register set that the device happens to be
24
+ * in at the moment of replacement.
25
+ */
26
+ originalBaseline;
27
+ /**
28
+ * Set inside the overridden `applyMessage` when an incoming
29
+ * `mode: schedule` message would replace an already-running schedule.
30
+ * Consumed (and reset) inside `onRollback` so the base library's
31
+ * automatic `doReleaseSchedule → onRollback` step does not actually
32
+ * write the snapshot back during a replacement.
33
+ */
34
+ suppressNextRollbackWrite = false;
18
35
  constructor(opts) {
19
36
  super(opts);
20
37
  this.sunspecClient = opts.sunspecClient;
@@ -23,19 +40,53 @@ export class SunspecBatteryScheduleHandler extends StorageScheduleHandler {
23
40
  this.getSnapshotService = opts.getSnapshotService;
24
41
  this.onErrorCallback = opts.onErrorCallback;
25
42
  }
43
+ /**
44
+ * Override the base-class data-bus router so a schedule-to-schedule
45
+ * replacement marks the next `onRollback` as "skip the write". The base
46
+ * library still owns the actual schedule lifecycle — we just steer one
47
+ * decision inside `onRollback`. `mode: auto` and any path that does not
48
+ * have an active schedule fall through unchanged, so the rollback fires
49
+ * normally there.
50
+ */
51
+ async applyMessage(msg) {
52
+ if (msg.applianceId === this.applianceIdForLog
53
+ && msg.data.mode === EnyoStorageScheduleModeEnum.Schedule
54
+ && this.getActiveEntry() !== undefined) {
55
+ this.suppressNextRollbackWrite = true;
56
+ }
57
+ try {
58
+ await super.applyMessage(msg);
59
+ }
60
+ finally {
61
+ // Defence in depth: if the base class skipped the rollback for
62
+ // any reason (validation error, disposed, etc.), the flag would
63
+ // otherwise stay set and silently swallow the next real rollback.
64
+ this.suppressNextRollbackWrite = false;
65
+ }
66
+ }
26
67
  async onInit(_active) {
68
+ if (this.originalBaseline !== undefined) {
69
+ // Replacement install: keep handing the library the sticky
70
+ // baseline so the persisted snapshot continues to point at the
71
+ // original pre-schedule state. The library will overwrite its
72
+ // storage row with the same value — harmless.
73
+ this.installedWChaMax = this.originalBaseline.wChaMax;
74
+ return { ...this.originalBaseline };
75
+ }
27
76
  const controls = await this.sunspecClient.readBatteryControls(this.unitId);
28
77
  if (!controls) {
29
78
  throw new Error(`SunspecBatteryScheduleHandler ${this.applianceIdForLog}: failed to read pre-schedule controls`);
30
79
  }
31
- this.installedWChaMax = controls.wChaMax;
32
- return {
80
+ const baseline = {
33
81
  storCtlMod: controls.storCtlMod,
34
82
  chaGriSet: controls.chaGriSet,
35
83
  wChaMax: controls.wChaMax,
36
84
  inWRte: controls.inWRte,
37
85
  outWRte: controls.outWRte,
38
86
  };
87
+ this.originalBaseline = baseline;
88
+ this.installedWChaMax = baseline.wChaMax;
89
+ return { ...baseline };
39
90
  }
40
91
  onChange(active, _previous) {
41
92
  void this.applyEntry(active).catch(err => {
@@ -43,6 +94,25 @@ export class SunspecBatteryScheduleHandler extends StorageScheduleHandler {
43
94
  });
44
95
  }
45
96
  onRollback(registers) {
97
+ if (this.suppressNextRollbackWrite) {
98
+ // Schedule-to-schedule replacement. Do NOT write the snapshot
99
+ // back; the new schedule's first `onChange` will own the
100
+ // register state. `installedWChaMax` stays valid (set in
101
+ // onInit) so the very next applyEntry has a baseline to divide
102
+ // against — this is the fix for the
103
+ // "no usable wChaMax baseline (installedWChaMax=undefined)"
104
+ // race seen in production logs.
105
+ this.suppressNextRollbackWrite = false;
106
+ return;
107
+ }
108
+ // Real rollback (mode: auto, dispose, restart recovery). Clear the
109
+ // sticky baseline so the next `onInit` re-reads the device state.
110
+ // Important: clear synchronously here — NOT in the async finally
111
+ // that follows — so a concurrent `onInit` queued behind this one
112
+ // (impossible today, but defensive) cannot observe a half-cleared
113
+ // state.
114
+ this.originalBaseline = undefined;
115
+ this.installedWChaMax = undefined;
46
116
  void (async () => {
47
117
  try {
48
118
  await this.sunspecClient.writeBatteryControls(this.unitId, registers);
@@ -53,9 +123,6 @@ export class SunspecBatteryScheduleHandler extends StorageScheduleHandler {
53
123
  catch (err) {
54
124
  console.error(`SunspecBatteryScheduleHandler ${this.applianceIdForLog}: onRollback failed: ${err}`);
55
125
  }
56
- finally {
57
- this.installedWChaMax = undefined;
58
- }
59
126
  })();
60
127
  }
61
128
  onError(err) {
@@ -1661,11 +1661,11 @@ export class SunspecModbusClient {
1661
1661
  const baseAddr = model.address;
1662
1662
  console.log(`Writing Battery Controls to Model 124 at base address: ${baseAddr} (unit ${unitId})`);
1663
1663
  try {
1664
- // Write storage control mode (Register 5)
1665
- if (controls.storCtlMod !== undefined) {
1666
- await this.writeRegisterValue(unitId, baseAddr + 5, controls.storCtlMod, 'uint16');
1667
- console.log(`Set storage control mode to 0x${controls.storCtlMod.toString(16)}`);
1668
- }
1664
+ // Write order: source pin and parameter writes land BEFORE the
1665
+ // control mode so the device only "starts acting" once every
1666
+ // value that governs the action is fresh. The reverse order
1667
+ // leaks a Modbus RTT-sized window where storCtlMod sees stale
1668
+ // chaGriSet / wChaMax / inWRte / outWRte.
1669
1669
  // Write charge source setting (Register 17)
1670
1670
  if (controls.chaGriSet !== undefined) {
1671
1671
  await this.writeRegisterValue(unitId, baseAddr + 17, controls.chaGriSet, 'uint16');
@@ -1703,6 +1703,13 @@ export class SunspecModbusClient {
1703
1703
  await this.writeRegisterValue(unitId, baseAddr + 7, scaledValue, 'uint16');
1704
1704
  console.log(`Set minimum reserve to ${controls.minRsvPct}% (scaled: ${scaledValue})`);
1705
1705
  }
1706
+ // Storage control mode (Register 5) — written LAST so all
1707
+ // governing parameters are already in place when the device
1708
+ // transitions into the new mode.
1709
+ if (controls.storCtlMod !== undefined) {
1710
+ await this.writeRegisterValue(unitId, baseAddr + 5, controls.storCtlMod, 'uint16');
1711
+ console.log(`Set storage control mode to 0x${controls.storCtlMod.toString(16)}`);
1712
+ }
1706
1713
  console.log('Battery controls written successfully');
1707
1714
  return true;
1708
1715
  }
package/dist/version.d.ts CHANGED
@@ -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.73";
8
+ export declare const SDK_VERSION = "0.0.74";
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/dist/version.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Current version of the enyo Energy App SDK.
7
7
  */
8
- export const SDK_VERSION = '0.0.73';
8
+ export const SDK_VERSION = '0.0.74';
9
9
  /**
10
10
  * Gets the current SDK version.
11
11
  * @returns The semantic version string of the SDK
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enyo-energy/sunspec-sdk",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "description": "enyo Energy Sunspec SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",