@enyo-energy/sunspec-sdk 0.0.73 → 0.0.75
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 +5 -1
- package/dist/cjs/sunspec-battery-schedule-handler.cjs +72 -5
- package/dist/cjs/sunspec-battery-schedule-handler.d.cts +27 -0
- package/dist/cjs/sunspec-devices.cjs +4 -138
- package/dist/cjs/sunspec-devices.d.cts +0 -11
- package/dist/cjs/sunspec-modbus-client.cjs +64 -38
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/sunspec-battery-schedule-handler.d.ts +27 -0
- package/dist/sunspec-battery-schedule-handler.js +73 -6
- package/dist/sunspec-devices.d.ts +0 -11
- package/dist/sunspec-devices.js +4 -138
- package/dist/sunspec-modbus-client.js +64 -38
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
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.
|
|
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
|
-
|
|
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;
|
|
@@ -711,8 +711,6 @@ class SunspecInverter extends BaseSunspecDevice {
|
|
|
711
711
|
this.dataBus = this.energyApp.useDataBus();
|
|
712
712
|
this.dataBusListenerId = this.dataBus.listenForMessages([
|
|
713
713
|
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.SetInverterFeedInLimitV1,
|
|
714
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StartCalibrationV1,
|
|
715
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StopCalibrationV1,
|
|
716
714
|
], (entry) => this.handleInverterCommand(entry));
|
|
717
715
|
console.log(`Inverter ${this.applianceId}: started data bus listening (listener ${this.dataBusListenerId})`);
|
|
718
716
|
}
|
|
@@ -737,12 +735,6 @@ class SunspecInverter extends BaseSunspecDevice {
|
|
|
737
735
|
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.SetInverterFeedInLimitV1:
|
|
738
736
|
await this.handleSetFeedInLimit(entry);
|
|
739
737
|
break;
|
|
740
|
-
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StartCalibrationV1:
|
|
741
|
-
await this.handleStartCalibration(entry);
|
|
742
|
-
break;
|
|
743
|
-
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StopCalibrationV1:
|
|
744
|
-
await this.handleStopCalibration(entry);
|
|
745
|
-
break;
|
|
746
738
|
}
|
|
747
739
|
}
|
|
748
740
|
catch (error) {
|
|
@@ -788,51 +780,6 @@ class SunspecInverter extends BaseSunspecDevice {
|
|
|
788
780
|
await this.snapshotService.initialize();
|
|
789
781
|
console.log(`Inverter ${this.applianceId}: snapshot service initialized`);
|
|
790
782
|
}
|
|
791
|
-
async handleStartCalibration(msg) {
|
|
792
|
-
if (!this.isConnected() || !this.applianceId) {
|
|
793
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Not connected');
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
if (!this.snapshotService) {
|
|
797
|
-
await this.initSnapshotService();
|
|
798
|
-
}
|
|
799
|
-
if (!this.snapshotService) {
|
|
800
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Snapshot service unavailable');
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
if (this.snapshotService.isCalibrating()) {
|
|
804
|
-
console.log(`Inverter ${this.applianceId}: calibration already active — ack idempotently`);
|
|
805
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
806
|
-
return;
|
|
807
|
-
}
|
|
808
|
-
console.log(`Inverter ${this.applianceId}: handling StartCalibrationV1`);
|
|
809
|
-
const controls = await this.sunspecClient.readInverterControls(this.unitId);
|
|
810
|
-
if (!controls) {
|
|
811
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Failed to read inverter controls for snapshot');
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
try {
|
|
815
|
-
await this.snapshotService.startCalibration(controls);
|
|
816
|
-
}
|
|
817
|
-
catch (error) {
|
|
818
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, `Failed to persist snapshot: ${error}`);
|
|
819
|
-
return;
|
|
820
|
-
}
|
|
821
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
822
|
-
}
|
|
823
|
-
async handleStopCalibration(msg) {
|
|
824
|
-
if (!this.applianceId) {
|
|
825
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Not initialized');
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
console.log(`Inverter ${this.applianceId}: handling StopCalibrationV1`);
|
|
829
|
-
// SnapshotService.stopCalibration fires `restoreInverterSnapshot` internally with
|
|
830
|
-
// reason="stop" before returning. Any restore failure is logged by the callback
|
|
831
|
-
// (the persisted snapshot is already gone by then — see library notes) so we
|
|
832
|
-
// always ack Accepted from here.
|
|
833
|
-
await this.snapshotService?.stopCalibration();
|
|
834
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
835
|
-
}
|
|
836
783
|
/**
|
|
837
784
|
* `onRestore` callback for the inverter's {@link SnapshotService}. Writes only the
|
|
838
785
|
* subset of writable inverter fields that other commands actually touched during the
|
|
@@ -1371,7 +1318,10 @@ class SunspecBattery extends BaseSunspecDevice {
|
|
|
1371
1318
|
console.error('Battery not connected');
|
|
1372
1319
|
return false;
|
|
1373
1320
|
}
|
|
1374
|
-
|
|
1321
|
+
// Redundant with the modbus client's own per-write debug trace. Keep at debug
|
|
1322
|
+
// so the high-level info logs (setStorageMode / enableGridCharging / etc.) stay
|
|
1323
|
+
// the only info-level signal per battery-control action.
|
|
1324
|
+
console.debug('Writing battery controls:', controls);
|
|
1375
1325
|
return this.sunspecClient.writeBatteryControls(this.unitId, controls);
|
|
1376
1326
|
}
|
|
1377
1327
|
mapToEnyoStorageMode(storageMode) {
|
|
@@ -1469,8 +1419,6 @@ class SunspecBattery extends BaseSunspecDevice {
|
|
|
1469
1419
|
this.dataBus = this.energyApp.useDataBus();
|
|
1470
1420
|
this.dataBusListenerId = this.dataBus.listenForMessages([
|
|
1471
1421
|
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.SetStorageScheduleV1,
|
|
1472
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StartCalibrationV1,
|
|
1473
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StopCalibrationV1,
|
|
1474
1422
|
], (entry) => this.handleStorageCommand(entry));
|
|
1475
1423
|
if (!this.applianceId) {
|
|
1476
1424
|
throw new Error("SunspecBattery.startDataBusListening: applianceId required — call connect() first.");
|
|
@@ -1509,12 +1457,6 @@ class SunspecBattery extends BaseSunspecDevice {
|
|
|
1509
1457
|
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.SetStorageScheduleV1:
|
|
1510
1458
|
this.handleSetStorageScheduleAck(entry);
|
|
1511
1459
|
break;
|
|
1512
|
-
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StartCalibrationV1:
|
|
1513
|
-
await this.handleStartCalibration(entry);
|
|
1514
|
-
break;
|
|
1515
|
-
case enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StopCalibrationV1:
|
|
1516
|
-
await this.handleStopCalibration(entry);
|
|
1517
|
-
break;
|
|
1518
1460
|
}
|
|
1519
1461
|
}
|
|
1520
1462
|
catch (error) {
|
|
@@ -1554,51 +1496,6 @@ class SunspecBattery extends BaseSunspecDevice {
|
|
|
1554
1496
|
await this.snapshotService.initialize();
|
|
1555
1497
|
console.log(`Battery ${this.applianceId}: snapshot service initialized`);
|
|
1556
1498
|
}
|
|
1557
|
-
async handleStartCalibration(msg) {
|
|
1558
|
-
if (!this.isConnected() || !this.applianceId) {
|
|
1559
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Not connected');
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
if (!this.snapshotService) {
|
|
1563
|
-
await this.initSnapshotService();
|
|
1564
|
-
}
|
|
1565
|
-
if (!this.snapshotService) {
|
|
1566
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Snapshot service unavailable');
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
if (this.snapshotService.isCalibrating()) {
|
|
1570
|
-
console.log(`Battery ${this.applianceId}: calibration already active — ack idempotently`);
|
|
1571
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
1572
|
-
return;
|
|
1573
|
-
}
|
|
1574
|
-
console.log(`Battery ${this.applianceId}: handling StartCalibrationV1`);
|
|
1575
|
-
const controls = await this.sunspecClient.readBatteryControls(this.unitId);
|
|
1576
|
-
if (!controls) {
|
|
1577
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Failed to read battery controls for snapshot');
|
|
1578
|
-
return;
|
|
1579
|
-
}
|
|
1580
|
-
try {
|
|
1581
|
-
await this.snapshotService.startCalibration(controls);
|
|
1582
|
-
}
|
|
1583
|
-
catch (error) {
|
|
1584
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, `Failed to persist snapshot: ${error}`);
|
|
1585
|
-
return;
|
|
1586
|
-
}
|
|
1587
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
1588
|
-
}
|
|
1589
|
-
async handleStopCalibration(msg) {
|
|
1590
|
-
if (!this.applianceId) {
|
|
1591
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Rejected, 'Not initialized');
|
|
1592
|
-
return;
|
|
1593
|
-
}
|
|
1594
|
-
console.log(`Battery ${this.applianceId}: handling StopCalibrationV1`);
|
|
1595
|
-
// SnapshotService.stopCalibration fires `restoreBatterySnapshot` internally
|
|
1596
|
-
// with reason="stop" before returning. Failures from the restore callback are
|
|
1597
|
-
// logged inside the callback (the persisted snapshot is already gone — see
|
|
1598
|
-
// library notes) so we always ack Accepted here.
|
|
1599
|
-
await this.snapshotService?.stopCalibration();
|
|
1600
|
-
this.sendCommandAcknowledge(msg.id, msg.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.Accepted);
|
|
1601
|
-
}
|
|
1602
1499
|
/**
|
|
1603
1500
|
* `onRestore` callback for the battery's {@link SnapshotService}. Writes only the
|
|
1604
1501
|
* subset of writable battery fields touched during the calibration. Errors are
|
|
@@ -1704,13 +1601,11 @@ class SunspecMeter extends BaseSunspecDevice {
|
|
|
1704
1601
|
console.error(`Failed to update meter appliance: ${error}`);
|
|
1705
1602
|
}
|
|
1706
1603
|
}
|
|
1707
|
-
this.startDataBusListening();
|
|
1708
1604
|
}
|
|
1709
1605
|
/**
|
|
1710
1606
|
* Disconnect from the meter and update appliance state
|
|
1711
1607
|
*/
|
|
1712
1608
|
async disconnect() {
|
|
1713
|
-
this.stopDataBusListening();
|
|
1714
1609
|
if (this.applianceId) {
|
|
1715
1610
|
try {
|
|
1716
1611
|
await this.applianceManager.updateApplianceState(this.applianceId, enyo_appliance_js_1.EnyoApplianceConnectionType.Connector, enyo_appliance_js_1.EnyoApplianceStateEnum.Offline);
|
|
@@ -1722,35 +1617,6 @@ class SunspecMeter extends BaseSunspecDevice {
|
|
|
1722
1617
|
// Close just this meter's unit; other devices on the same network device stay open.
|
|
1723
1618
|
await this.sunspecClient.disconnectUnit(this.unitId);
|
|
1724
1619
|
}
|
|
1725
|
-
/**
|
|
1726
|
-
* Meter does not implement calibration; it only subscribes to Start/StopCalibrationV1 to
|
|
1727
|
-
* answer NotSupported (per the data-bus contract that every command must be acknowledged).
|
|
1728
|
-
*/
|
|
1729
|
-
startDataBusListening() {
|
|
1730
|
-
if (this.dataBusListenerId) {
|
|
1731
|
-
return;
|
|
1732
|
-
}
|
|
1733
|
-
this.dataBus = this.energyApp.useDataBus();
|
|
1734
|
-
this.dataBusListenerId = this.dataBus.listenForMessages([
|
|
1735
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StartCalibrationV1,
|
|
1736
|
-
enyo_data_bus_value_js_1.EnyoDataBusMessageEnum.StopCalibrationV1,
|
|
1737
|
-
], (entry) => this.handleMeterCommand(entry));
|
|
1738
|
-
console.log(`Meter ${this.applianceId}: started data bus listening (listener ${this.dataBusListenerId})`);
|
|
1739
|
-
}
|
|
1740
|
-
stopDataBusListening() {
|
|
1741
|
-
if (this.dataBusListenerId && this.dataBus) {
|
|
1742
|
-
this.dataBus.unsubscribe(this.dataBusListenerId);
|
|
1743
|
-
console.log(`Meter ${this.applianceId}: stopped data bus listening (listener ${this.dataBusListenerId})`);
|
|
1744
|
-
}
|
|
1745
|
-
this.dataBusListenerId = undefined;
|
|
1746
|
-
this.dataBus = undefined;
|
|
1747
|
-
}
|
|
1748
|
-
handleMeterCommand(entry) {
|
|
1749
|
-
if (entry.applianceId !== this.applianceId) {
|
|
1750
|
-
return;
|
|
1751
|
-
}
|
|
1752
|
-
this.sendCommandAcknowledge(entry.id, entry.message, enyo_data_bus_value_js_1.EnyoCommandAcknowledgeAnswerEnum.NotSupported, 'Meter does not support calibration');
|
|
1753
|
-
}
|
|
1754
1620
|
/**
|
|
1755
1621
|
* Update meter data and return data bus messages
|
|
1756
1622
|
*/
|
|
@@ -178,8 +178,6 @@ export declare class SunspecInverter extends BaseSunspecDevice {
|
|
|
178
178
|
* process restarts. Idempotent.
|
|
179
179
|
*/
|
|
180
180
|
private initSnapshotService;
|
|
181
|
-
private handleStartCalibration;
|
|
182
|
-
private handleStopCalibration;
|
|
183
181
|
/**
|
|
184
182
|
* `onRestore` callback for the inverter's {@link SnapshotService}. Writes only the
|
|
185
183
|
* subset of writable inverter fields that other commands actually touched during the
|
|
@@ -408,8 +406,6 @@ export declare class SunspecBattery extends BaseSunspecDevice {
|
|
|
408
406
|
* process restarts. Idempotent.
|
|
409
407
|
*/
|
|
410
408
|
private initSnapshotService;
|
|
411
|
-
private handleStartCalibration;
|
|
412
|
-
private handleStopCalibration;
|
|
413
409
|
/**
|
|
414
410
|
* `onRestore` callback for the battery's {@link SnapshotService}. Writes only the
|
|
415
411
|
* subset of writable battery fields touched during the calibration. Errors are
|
|
@@ -432,13 +428,6 @@ export declare class SunspecMeter extends BaseSunspecDevice {
|
|
|
432
428
|
* Disconnect from the meter and update appliance state
|
|
433
429
|
*/
|
|
434
430
|
disconnect(): Promise<void>;
|
|
435
|
-
/**
|
|
436
|
-
* Meter does not implement calibration; it only subscribes to Start/StopCalibrationV1 to
|
|
437
|
-
* answer NotSupported (per the data-bus contract that every command must be acknowledged).
|
|
438
|
-
*/
|
|
439
|
-
startDataBusListening(): void;
|
|
440
|
-
stopDataBusListening(): void;
|
|
441
|
-
private handleMeterCommand;
|
|
442
431
|
/**
|
|
443
432
|
* Update meter data and return data bus messages
|
|
444
433
|
*/
|