nodejs-poolcontroller 8.0.0 → 8.0.2

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 (47) hide show
  1. package/.docker/Dockerfile.armv6 +29 -0
  2. package/.docker/Dockerfile.armv7 +29 -0
  3. package/.docker/Dockerfile.linux +62 -0
  4. package/.docker/Dockerfile.windows +43 -0
  5. package/.docker/docker-compose.yml +47 -0
  6. package/.docker/ecosystem.config.js +35 -0
  7. package/.github/workflows/docker-publish-njsPC-linux.yml +81 -0
  8. package/.github/workflows/docker-publish-njsPC-windows.yml +41 -0
  9. package/Dockerfile +4 -3
  10. package/README.md +4 -1
  11. package/config/Config.ts +1 -1
  12. package/controller/Constants.ts +164 -67
  13. package/controller/Equipment.ts +79 -18
  14. package/controller/Lockouts.ts +15 -0
  15. package/controller/State.ts +280 -7
  16. package/controller/boards/EasyTouchBoard.ts +226 -102
  17. package/controller/boards/IntelliCenterBoard.ts +67 -18
  18. package/controller/boards/IntelliTouchBoard.ts +2 -4
  19. package/controller/boards/NixieBoard.ts +84 -27
  20. package/controller/boards/SunTouchBoard.ts +8 -2
  21. package/controller/boards/SystemBoard.ts +3259 -3242
  22. package/controller/comms/ScreenLogic.ts +60 -57
  23. package/controller/comms/messages/Messages.ts +4 -4
  24. package/controller/comms/messages/config/ChlorinatorMessage.ts +10 -3
  25. package/controller/comms/messages/config/ExternalMessage.ts +4 -1
  26. package/controller/comms/messages/config/PumpMessage.ts +8 -7
  27. package/controller/comms/messages/config/RemoteMessage.ts +48 -43
  28. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +8 -2
  29. package/controller/comms/messages/status/EquipmentStateMessage.ts +9 -4
  30. package/controller/nixie/NixieEquipment.ts +1 -1
  31. package/controller/nixie/bodies/Body.ts +1 -1
  32. package/controller/nixie/chemistry/ChemController.ts +37 -28
  33. package/controller/nixie/circuits/Circuit.ts +36 -0
  34. package/controller/nixie/heaters/Heater.ts +24 -5
  35. package/controller/nixie/pumps/Pump.ts +155 -97
  36. package/controller/nixie/schedules/Schedule.ts +207 -126
  37. package/defaultConfig.json +4 -3
  38. package/logger/DataLogger.ts +7 -7
  39. package/package.json +3 -3
  40. package/sendSocket.js +32 -0
  41. package/web/Server.ts +17 -11
  42. package/web/bindings/homeassistant.json +2 -2
  43. package/web/interfaces/mqttInterface.ts +18 -18
  44. package/web/services/config/Config.ts +34 -1
  45. package/web/services/state/State.ts +10 -3
  46. package/web/services/state/StateSocket.ts +7 -3
  47. package/web/services/utilities/Utilities.ts +3 -3
@@ -65,7 +65,8 @@ export class NixiePumpCollection extends NixieEquipmentCollection<NixiePump> {
65
65
  for (let i = 0; i < pumps.length; i++) {
66
66
  let pump = pumps.getItemByIndex(i);
67
67
  if (pump.master === 1) {
68
- if (typeof this.find(elem => elem.id === pump.id) === 'undefined') {
68
+ let p: NixiePump = this.find(elem => elem.id === pump.id) as NixiePump;
69
+ if (typeof p === 'undefined') {
69
70
  let type = sys.board.valueMaps.pumpTypes.getName(pump.type);
70
71
  let npump = this.pumpFactory(pump);
71
72
  logger.info(`Initializing Nixie Pump ${npump.id}-${pump.name}`);
@@ -81,7 +82,9 @@ export class NixiePumpCollection extends NixieEquipmentCollection<NixiePump> {
81
82
  try {
82
83
  for (let i = this.length - 1; i >= 0; i--) {
83
84
  try {
84
- await this[i].closeAsync();
85
+ try {
86
+ await this[i].closeAsync();
87
+ } catch (err) { logger.error(`Error attempting to close pump ${this[i].id}`); }
85
88
  this.splice(i, 1);
86
89
  } catch (err) { logger.error(`Error stopping Nixie Pump ${err}`); }
87
90
  }
@@ -101,14 +104,16 @@ export class NixiePumpCollection extends NixieEquipmentCollection<NixiePump> {
101
104
  try {
102
105
  let c: NixiePump = this.find(elem => elem.id === pump.id) as NixiePump;
103
106
  if (pump.master === 1) {
104
- // if pump exists, close it so we can re-init
107
+ // if pump exists, close it so we can re-init
105
108
  // (EG if pump type changes, we need to setup a new instance of the pump)
106
109
  if (typeof c !== 'undefined' && c.pump.type !== pump.type) {
107
110
  await c.closeAsync();
111
+ await this.deletePumpAsync(pump.id);
108
112
  c = this.pumpFactory(pump);
113
+ this.push(c);
109
114
  }
110
- logger.info(`Initializing Nixie Pump ${c.id}-${pump.name}`);
111
- this.push(c);
115
+ logger.info(`Initializing Existing Nixie Pump ${c.id}-${pump.name}`);
116
+
112
117
  }
113
118
  return c;
114
119
  } catch (err) { return Promise.reject(logger.error(`Nixie Controller: initPumpAsync Error: ${err.message}`)); }
@@ -140,13 +145,21 @@ export class NixiePumpCollection extends NixieEquipmentCollection<NixiePump> {
140
145
  // loop through all pumps and update rates based on circuit changes
141
146
  // this would happen in <2s anyway based on pollAsync but this is immediate.
142
147
  for (let i = this.length - 1; i >= 0; i--) {
148
+ let pump = this[i] as NixiePump;
149
+ if (!pump.suspendPolling) setTimeoutSync(async () => { await pump.pollEquipmentAsync(); }, 100);
150
+ else {
151
+ pump.setTargetSpeed(state.pumps.getItemById(pump.id));
152
+ }
153
+ // RKS: 05-16-23 - Below backs up the processing.
154
+ /*
155
+
143
156
  setTimeoutSync(async () => {
144
157
  let pump = this[i] as NixiePump;
145
158
  try {
146
159
  if (!pump.closing) await pump.pollEquipmentAsync();
147
160
  } catch (err) { }
148
161
  }, 100);
149
-
162
+ */
150
163
  }
151
164
  }
152
165
  }
@@ -157,7 +170,10 @@ export class NixiePump extends NixieEquipment {
157
170
  protected _targetSpeed: number;
158
171
  protected _suspendPolling = 0;
159
172
  public get suspendPolling(): boolean { return this._suspendPolling > 0; }
160
- public set suspendPolling(val: boolean) { this._suspendPolling = Math.max(0, this._suspendPolling + (val ? 1 : -1)); }
173
+ public set suspendPolling(val: boolean) {
174
+ this._suspendPolling = Math.max(0, this._suspendPolling + (val ? 1 : -1));
175
+ if (this._suspendPolling > 1) console.log(`Suspend Polling ${this._suspendPolling}`);
176
+ }
161
177
  public closing = false;
162
178
  public async setServiceModeAsync() {
163
179
  let pstate = state.pumps.getItemById(this.pump.id);
@@ -192,7 +208,6 @@ export class NixiePump extends NixieEquipment {
192
208
  }
193
209
  public async setPumpAsync(data: any): Promise<InterfaceServerResponse> {
194
210
  try {
195
-
196
211
  this.pump.master = 1;
197
212
  // if (typeof data.isVirtual !== 'undefined') this.pump.isVirtual = data.isVirtual;
198
213
  this.pump.isActive = true;
@@ -226,7 +241,7 @@ export class NixiePump extends NixieEquipment {
226
241
  case 'ds':
227
242
  case 'sf':
228
243
  case 'hwrly':
229
- c.units = 'undefined';
244
+ c.units = undefined;
230
245
  break;
231
246
  }
232
247
  if (isNaN(units)) units = typeof cd !== 'undefined' ? cd.units : sys.board.valueMaps.pumpUnits.getValue('rpm');
@@ -245,6 +260,7 @@ export class NixiePump extends NixieEquipment {
245
260
  c.relay = relay;
246
261
  }
247
262
  }
263
+ else data.circuits = [];
248
264
  this.pump.set(data); // Sets all the data back to the pump. This also sets the relays should it exist on the data.
249
265
  let spump = state.pumps.getItemById(this.pump.id, true);
250
266
  spump.name = this.pump.name;
@@ -264,16 +280,19 @@ export class NixiePump extends NixieEquipment {
264
280
  // RSG 8-2022. Refactored to add initasync. With this.pollEquipmentAsync inside the
265
281
  // constructor we could get here before the pump is initialized. The added check
266
282
  // for the 112 address prevented that previously, but now is just a final fail safe.
267
- if (this.suspendPolling || this.closing || this.pump.address > 112) return;
268
283
  if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
269
284
  this._pollTimer = null;
270
- // let success = false;
285
+ if (this.suspendPolling || this.closing || this.pump.address > 112) {
286
+ if (this.suspendPolling) logger.info(`Pump ${this.id} Polling Suspended`);
287
+ if (this.closing) logger.info(`Pump ${this.id} is closing`);
288
+ return;
289
+ }
271
290
  let pstate = state.pumps.getItemById(this.pump.id);
272
291
  this.setTargetSpeed(pstate);
273
292
  await this.setPumpStateAsync(pstate);
274
293
  }
275
294
  catch (err) { logger.error(`Nixie Error running pump sequence - ${err}`); }
276
- finally { if (!this.closing) this._pollTimer = setTimeoutSync(async () => await self.pollEquipmentAsync(), this.pollingInterval || 2000); }
295
+ finally { if (!self.closing) this._pollTimer = setTimeoutSync(async () => await self.pollEquipmentAsync(), self.pollingInterval || 2000); }
277
296
  }
278
297
  private async checkHardwareStatusAsync(connectionId: string, deviceBinding: string) {
279
298
  try {
@@ -304,7 +323,7 @@ export class NixiePump extends NixieEquipment {
304
323
  catch (err) { logger.error(`Nixie Pump closeAsync: ${err.message}`); return Promise.reject(err); }
305
324
  }
306
325
  public logData(filename: string, data: any) { this.controlPanel.logData(filename, data); }
307
- protected setTargetSpeed(pstate: PumpState) { };
326
+ public setTargetSpeed(pstate: PumpState) { };
308
327
  protected isBodyOn(bodyCode: number) {
309
328
  let assoc = sys.board.valueMaps.pumpBodies.transform(bodyCode);
310
329
  switch (assoc.name) {
@@ -555,27 +574,29 @@ export class NixiePumpRS485 extends NixiePump {
555
574
  finally { this.suspendPolling = false; }
556
575
  };
557
576
  protected async setDriveStateAsync(running: boolean = true) {
558
- if (conn.isPortEnabled(this.pump.portId || 0)) {
559
- let out = Outbound.create({
560
- portId: this.pump.portId || 0,
561
- protocol: Protocol.Pump,
562
- dest: this.pump.address,
563
- action: 6,
564
- payload: running && this._targetSpeed > 0 ? [10] : [4],
565
- retries: 1,
566
- response: true
567
- });
568
- try {
569
- await out.sendAsync();
577
+ try {
578
+ if (conn.isPortEnabled(this.pump.portId || 0)) {
579
+ let out = Outbound.create({
580
+ portId: this.pump.portId || 0,
581
+ protocol: Protocol.Pump,
582
+ dest: this.pump.address,
583
+ action: 6,
584
+ payload: running && this._targetSpeed > 0 ? [10] : [4],
585
+ retries: 1,
586
+ response: true
587
+ });
588
+ try {
589
+ await out.sendAsync();
590
+ }
591
+ catch (err) {
592
+ logger.error(`Error sending setDriveState for ${this.pump.name}: ${err.message}`);
593
+ }
570
594
  }
571
- catch (err) {
572
- logger.error(`Error sending setDriveState for ${this.pump.name}: ${err.message}`);
595
+ else {
596
+ let pstate = state.pumps.getItemById(this.pump.id);
597
+ pstate.command = pstate.rpm > 0 || pstate.flow > 0 ? 10 : 0;
573
598
  }
574
- }
575
- else {
576
- let pstate = state.pumps.getItemById(this.pump.id);
577
- pstate.command = pstate.rpm > 0 || pstate.flow > 0 ? 10 : 0;
578
- }
599
+ } catch (err) { logger.error(`Error setting driveState for ${this.pump.name}: ${err.message}`); }
579
600
  };
580
601
  protected async requestPumpStatusAsync() {
581
602
  if (conn.isPortEnabled(this.pump.portId || 0)) {
@@ -597,44 +618,48 @@ export class NixiePumpRS485 extends NixiePump {
597
618
  }
598
619
  };
599
620
  protected async setPumpToRemoteControlAsync(running: boolean = true) {
600
- if (conn.isPortEnabled(this.pump.portId || 0)) {
601
- let out = Outbound.create({
602
- portId: this.pump.portId || 0,
603
- protocol: Protocol.Pump,
604
- dest: this.pump.address,
605
- action: 4,
606
- payload: running ? [255] : [0], // when stopAsync is called, pass false to return control to pump panel
607
- retries: 1,
608
- response: true
609
- });
610
- try {
611
- await out.sendAsync();
612
- }
613
- catch (err) {
614
- logger.error(`Error sending setPumpToRemoteControl for ${this.pump.name}: ${err.message}`);
621
+ try {
622
+ if (conn.isPortEnabled(this.pump.portId || 0)) {
623
+ let out = Outbound.create({
624
+ portId: this.pump.portId || 0,
625
+ protocol: Protocol.Pump,
626
+ dest: this.pump.address,
627
+ action: 4,
628
+ payload: running ? [255] : [0], // when stopAsync is called, pass false to return control to pump panel
629
+ retries: 1,
630
+ response: true
631
+ });
632
+ try {
633
+ await out.sendAsync();
634
+ }
635
+ catch (err) {
636
+ logger.error(`Error sending setPumpToRemoteControl for ${this.pump.name}: ${err.message}`);
637
+ }
615
638
  }
616
- }
639
+ } catch (err) { logger.error(`Error setting pump to Remote Control for ${this.pump.name}: ${err.message}`); }
617
640
  }
618
641
  protected async setPumpFeatureAsync(feature?: number) {
619
642
  // empty payload (possibly 0?, too) is no feature
620
643
  // 6: Feature 1
621
- if (conn.isPortEnabled(this.pump.portId || 0)) {
622
- let out = Outbound.create({
623
- portId: this.pump.portId || 0,
624
- protocol: Protocol.Pump,
625
- dest: this.pump.address,
626
- action: 5,
627
- payload: typeof feature === 'undefined' ? [] : [feature],
628
- retries: 2,
629
- response: true
630
- });
631
- try {
632
- await out.sendAsync();
633
- }
634
- catch (err) {
635
- logger.error(`Error sending setPumpFeature for ${this.pump.name}: ${err.message}`);
644
+ try {
645
+ if (conn.isPortEnabled(this.pump.portId || 0)) {
646
+ let out = Outbound.create({
647
+ portId: this.pump.portId || 0,
648
+ protocol: Protocol.Pump,
649
+ dest: this.pump.address,
650
+ action: 5,
651
+ payload: typeof feature === 'undefined' ? [] : [feature],
652
+ retries: 2,
653
+ response: true
654
+ });
655
+ try {
656
+ await out.sendAsync();
657
+ }
658
+ catch (err) {
659
+ logger.error(`Error sending setPumpFeature for ${this.pump.name}: ${err.message}`);
660
+ }
636
661
  }
637
- }
662
+ } catch (err) { logger.error(`Error setting pump feature for ${this.pump.name}: ${err.message}`); }
638
663
  };
639
664
  protected async setPumpRPMAsync() {
640
665
  if (conn.isPortEnabled(this.pump.portId || 0)) {
@@ -691,7 +716,7 @@ export class NixiePumpRS485 extends NixiePump {
691
716
  //await this.setPumpFeature();
692
717
  //await this.setDriveStateAsync(false);
693
718
  await this.setPumpToRemoteControlAsync(false);
694
- // Make sure the polling timer is dead after we have closted this all off. That way we do not
719
+ // Make sure the polling timer is dead after we have closed this all off. That way we do not
695
720
  // have another process that revives it from the dead.
696
721
  if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
697
722
  this._pollTimer = null;
@@ -735,14 +760,38 @@ export class NixiePumpVF extends NixiePumpRS485 {
735
760
  if (this._targetSpeed !== 0) Math.min(Math.max(this.pump.minFlow, this._targetSpeed), this.pump.maxFlow);
736
761
  if (this._targetSpeed !== _newSpeed) logger.info(`NCP: Setting Pump ${this.pump.name} to ${_newSpeed} GPM.`);
737
762
  }
763
+ public async setPumpStateAsync(pstate: PumpState) {
764
+ // Don't poll while we are seting the state.
765
+ this.suspendPolling = true;
766
+ try {
767
+ let pt = sys.board.valueMaps.pumpTypes.get(this.pump.type);
768
+ if (state.mode === 0) {
769
+ // Since these process are async the closing flag can be set
770
+ // between calls. We need to check it in between each call. // 4, 6, 5, 7
771
+ // When we are 0 then it sends 4[255], 6[4], 5[6]
772
+ // When we are not 0 then it sends 4[255], 6[10], 5[6], 1[flow]
773
+ if (!this.closing) await this.setPumpToRemoteControlAsync(); // Action 4
774
+ if (!this.closing) await this.setDriveStateAsync(); // Action 6
775
+ if (!this.closing) await this.setPumpFeatureAsync(this._targetSpeed > 0 ? 6 : undefined); // Action 5
776
+ if (!this.closing && this._targetSpeed > 0) await this.setPumpGPMAsync(); // Action 1
777
+ if (!this.closing) await setTimeout(200);
778
+ if (!this.closing) await this.requestPumpStatusAsync(); // Action 7
779
+ }
780
+ return new InterfaceServerResponse(200, 'Success');
781
+ }
782
+ catch (err) {
783
+ logger.error(`Error running pump sequence for ${this.pump.name}: ${err.message}`);
784
+ return Promise.reject(err);
785
+ }
786
+ finally { this.suspendPolling = false; }
787
+ };
738
788
  }
739
789
  export class NixiePumpVSF extends NixiePumpRS485 {
740
790
  public setTargetSpeed(pState: PumpState) {
741
791
  let _newSpeed = 0;
742
792
  let maxRPM = 0;
743
793
  let maxGPM = 0;
744
- let flows = 0;
745
- let speeds = 0;
794
+ let useFlow = false;
746
795
  if (!pState.pumpOnDelay) {
747
796
  let pumpCircuits = this.pump.circuits.get();
748
797
  let pt = sys.board.valueMaps.pumpTypes.get(this.pump.type);
@@ -750,13 +799,19 @@ export class NixiePumpVSF extends NixiePumpRS485 {
750
799
  // if there is a mix in the circuit array then they will not work. In IntelliCenter if there is an RPM setting in the mix it will use RPM by converting
751
800
  // the GPM to RPM but if there is none then it will use GPM.
752
801
  let toRPM = (flowRate: number, minSpeed: number = 450, maxSpeed: number = 3450) => {
802
+ // eff = 114.4365
803
+ // gpm = 80
804
+ // speed = 2412
753
805
  let eff = .03317 * maxSpeed;
754
- let rpm = Math.min((flowRate * maxSpeed) / eff, maxSpeed);
806
+ let rpm = Math.min(Math.round((flowRate * maxSpeed) / eff), maxSpeed);
755
807
  return rpm > 0 ? Math.max(rpm, minSpeed) : 0;
756
808
  };
757
809
  let toGPM = (speed: number, maxSpeed: number = 3450, minFlow: number = 15, maxFlow: number = 140) => {
810
+ // eff = 114.4365
811
+ // speed = 1100
812
+ // gpm = (114.4365 * 1100)/3450 = 36
758
813
  let eff = .03317 * maxSpeed;
759
- let gpm = Math.min((eff * speed) / maxSpeed, maxFlow);
814
+ let gpm = Math.min(Math.round((eff * speed) / maxSpeed), maxFlow);
760
815
  return gpm > 0 ? Math.max(gpm, minFlow) : 0;
761
816
  }
762
817
  for (let i = 0; i < pumpCircuits.length; i++) {
@@ -764,23 +819,24 @@ export class NixiePumpVSF extends NixiePumpRS485 {
764
819
  let pc = pumpCircuits[i];
765
820
  if (circ.isOn) {
766
821
  if (pc.units > 0) {
822
+ let rpm = toRPM(pc.flow, pt.minSpeed, pt.MaxSpeed);
823
+ if (rpm > maxRPM) useFlow = true;
767
824
  maxGPM = Math.max(maxGPM, pc.flow);
768
- // Calculate an RPM from this flow.
769
- maxRPM = Math.max(maxGPM, toRPM(pc.flow, pt.minSpeed, pt.maxSpeed));
770
- flows++;
825
+ rpm = Math.max(maxRPM, rpm);
771
826
  }
772
827
  else {
828
+ let gpm = toGPM(pc.speed, pt.maxSpeed, pt.minFlow, pt.maxFlow);
829
+ if (gpm > maxGPM) useFlow = false;
773
830
  maxRPM = Math.max(maxRPM, pc.speed);
774
- maxGPM = Math.max(maxGPM, toGPM(pc.speed, pt.maxSpeed, pt.minFlow, pt.maxFlow));
775
- speeds++;
831
+ maxGPM = Math.max(maxGPM, gpm);
776
832
  }
777
833
  }
778
834
  }
779
- _newSpeed = speeds > 0 || flows === 0 ? maxRPM : maxGPM;
835
+ _newSpeed = useFlow ? maxGPM : maxRPM;
780
836
  }
781
837
  if (isNaN(_newSpeed)) _newSpeed = 0;
782
838
  // Send the flow message if it is flow and the rpm message if it is rpm.
783
- if (this._targetSpeed !== _newSpeed) logger.info(`NCP: Setting Pump ${this.pump.name} to ${_newSpeed} ${flows > 0 ? 'GPM' : 'RPM'}.`);
839
+ if (this._targetSpeed !== _newSpeed) logger.info(`NCP: Setting Pump ${this.pump.name} to ${_newSpeed} ${useFlow ? 'GPM' : 'RPM'}.`);
784
840
  this._targetSpeed = _newSpeed;
785
841
  }
786
842
  protected async setPumpRPMAsync() {
@@ -846,7 +902,7 @@ export class NixiePumpHWVS extends NixiePumpRS485 {
846
902
  this._targetSpeed = 0;
847
903
  await this.setPumpRPMAsync();
848
904
  }
849
- public async setDriveStateAsync(running: boolean = false) { }
905
+ public async setDriveStateAsync(running: boolean = false) { return Promise.resolve(); }
850
906
  public async setPumpStateAsync(pstate: PumpState) {
851
907
  // Don't poll while we are seting the state.
852
908
  this.suspendPolling = true;
@@ -865,29 +921,31 @@ export class NixiePumpHWVS extends NixiePumpRS485 {
865
921
  protected async requestPumpStatusAsync() { return Promise.resolve(); };
866
922
  protected setPumpFeatureAsync(feature?: number) { return Promise.resolve(); }
867
923
  protected async setPumpToRemoteControlAsync(running: boolean = true) {
868
- // We do nothing on this pump to set it to remote control. That is unless we are turning it off.
869
- if (conn.isPortEnabled(this.pump.portId || 0)) {
870
- if (!running) {
871
- let out = Outbound.create({
872
- portId: this.pump.portId || 0,
873
- protocol: Protocol.Hayward,
874
- source: 12, // Use the broadcast address
875
- dest: this.pump.address,
876
- action: 1,
877
- payload: [0], // when stopAsync is called, pass false to return control to pump panel
878
- // payload: spump.virtualControllerStatus === sys.board.valueMaps.virtualControllerStatus.getValue('running') ? [255] : [0],
879
- retries: 1,
880
- response: Response.create({ protocol: Protocol.Hayward, action: 12, source: this.pump.address - 96 })
881
- });
882
- try {
883
- await out.sendAsync();
884
- }
885
- catch (err) {
886
- logger.error(`Error sending setPumpToRemoteControl for ${this.pump.name}: ${err.message}`);
924
+ try {
925
+ // We do nothing on this pump to set it to remote control. That is unless we are turning it off.
926
+ if (conn.isPortEnabled(this.pump.portId || 0)) {
927
+ if (!running) {
928
+ let out = Outbound.create({
929
+ portId: this.pump.portId || 0,
930
+ protocol: Protocol.Hayward,
931
+ source: 12, // Use the broadcast address
932
+ dest: this.pump.address,
933
+ action: 1,
934
+ payload: [0], // when stopAsync is called, pass false to return control to pump panel
935
+ // payload: spump.virtualControllerStatus === sys.board.valueMaps.virtualControllerStatus.getValue('running') ? [255] : [0],
936
+ retries: 1,
937
+ response: Response.create({ protocol: Protocol.Hayward, action: 12, source: this.pump.address - 96 })
938
+ });
939
+ try {
940
+ await out.sendAsync();
941
+ }
942
+ catch (err) {
943
+ logger.error(`Error sending setPumpToRemoteControl for ${this.pump.name}: ${err.message}`);
887
944
 
945
+ }
888
946
  }
889
947
  }
890
- }
948
+ } catch(err) { `Error sending setPumpToRemoteControl message for ${this.pump.name}: ${err.message}` };
891
949
  }
892
950
  protected async setPumpRPMAsync() {
893
951
  // Address 1