nodejs-poolcontroller 7.6.1 → 7.7.0

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 (91) hide show
  1. package/.eslintrc.json +44 -44
  2. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -0
  3. package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
  4. package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. package/CONTRIBUTING.md +74 -74
  7. package/Changelog +220 -215
  8. package/Dockerfile +17 -17
  9. package/Gruntfile.js +40 -40
  10. package/LICENSE +661 -661
  11. package/README.md +191 -191
  12. package/app.ts +1 -1
  13. package/config/Config.ts +14 -0
  14. package/config/VersionCheck.ts +2 -2
  15. package/controller/Constants.ts +2 -1
  16. package/controller/Equipment.ts +2484 -2459
  17. package/controller/Errors.ts +180 -180
  18. package/controller/Lockouts.ts +502 -436
  19. package/controller/State.ts +106 -30
  20. package/controller/boards/AquaLinkBoard.ts +1000 -0
  21. package/controller/boards/BoardFactory.ts +49 -45
  22. package/controller/boards/EasyTouchBoard.ts +2859 -2653
  23. package/controller/boards/IntelliCenterBoard.ts +4198 -4230
  24. package/controller/boards/IntelliComBoard.ts +63 -63
  25. package/controller/boards/IntelliTouchBoard.ts +273 -241
  26. package/controller/boards/NixieBoard.ts +1728 -1675
  27. package/controller/boards/SystemBoard.ts +4925 -4697
  28. package/controller/comms/Comms.ts +442 -479
  29. package/controller/comms/messages/Messages.ts +171 -25
  30. package/controller/comms/messages/config/ChlorinatorMessage.ts +5 -2
  31. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  32. package/controller/comms/messages/config/CircuitMessage.ts +1 -0
  33. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  34. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  35. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  36. package/controller/comms/messages/config/EquipmentMessage.ts +0 -0
  37. package/controller/comms/messages/config/ExternalMessage.ts +0 -0
  38. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  39. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  40. package/controller/comms/messages/config/HeaterMessage.ts +142 -10
  41. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  42. package/controller/comms/messages/config/OptionsMessage.ts +4 -21
  43. package/controller/comms/messages/config/PumpMessage.ts +53 -35
  44. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  45. package/controller/comms/messages/config/ScheduleMessage.ts +350 -347
  46. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  47. package/controller/comms/messages/config/ValveMessage.ts +1 -1
  48. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
  49. package/controller/comms/messages/status/EquipmentStateMessage.ts +58 -22
  50. package/controller/comms/messages/status/HeaterStateMessage.ts +116 -86
  51. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -445
  52. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  53. package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
  54. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  55. package/controller/nixie/Nixie.ts +162 -162
  56. package/controller/nixie/NixieEquipment.ts +103 -103
  57. package/controller/nixie/bodies/Body.ts +120 -120
  58. package/controller/nixie/bodies/Filter.ts +135 -135
  59. package/controller/nixie/chemistry/ChemController.ts +2511 -2498
  60. package/controller/nixie/chemistry/Chlorinator.ts +363 -314
  61. package/controller/nixie/circuits/Circuit.ts +261 -248
  62. package/controller/nixie/heaters/Heater.ts +650 -648
  63. package/controller/nixie/pumps/Pump.ts +906 -661
  64. package/controller/nixie/schedules/Schedule.ts +313 -257
  65. package/controller/nixie/valves/Valve.ts +170 -170
  66. package/defaultConfig.json +306 -286
  67. package/logger/DataLogger.ts +448 -448
  68. package/logger/Logger.ts +0 -0
  69. package/package.json +56 -56
  70. package/tsconfig.json +25 -25
  71. package/web/Server.ts +92 -47
  72. package/web/bindings/aqualinkD.json +505 -0
  73. package/web/bindings/influxDB.json +1051 -1021
  74. package/web/bindings/mqtt.json +702 -654
  75. package/web/bindings/mqttAlt.json +731 -684
  76. package/web/bindings/rulesManager.json +54 -54
  77. package/web/bindings/smartThings-Hubitat.json +31 -31
  78. package/web/bindings/valveRelays.json +20 -20
  79. package/web/bindings/vera.json +25 -25
  80. package/web/interfaces/baseInterface.ts +137 -136
  81. package/web/interfaces/httpInterface.ts +145 -124
  82. package/web/interfaces/influxInterface.ts +276 -245
  83. package/web/interfaces/mqttInterface.ts +535 -475
  84. package/web/services/config/Config.ts +39 -18
  85. package/web/services/config/ConfigSocket.ts +0 -0
  86. package/web/services/state/State.ts +10 -0
  87. package/web/services/state/StateSocket.ts +4 -4
  88. package/web/services/utilities/Utilities.ts +44 -42
  89. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
  90. package/config copy.json +0 -300
  91. package/issue_template.md +0 -52
@@ -505,6 +505,8 @@ export interface ICircuitState {
505
505
  isActive?: boolean;
506
506
  startDelay?: boolean;
507
507
  stopDelay?: boolean;
508
+ manualPriorityActive?: boolean;
509
+ dataName?: string;
508
510
  }
509
511
 
510
512
  interface IEqStateCreator<T> { ctor(data: any, name: string, parent?): T; }
@@ -913,6 +915,8 @@ export class PumpState extends EqState {
913
915
  public set rpm(val: number) { this.setDataVal('rpm', val, this.exceedsThreshold(this.data.rpm, val)); }
914
916
  public get relay(): number { return this.data.relay; }
915
917
  public set relay(val: number) { this.setDataVal('relay', val); }
918
+ public get program(): number { return this.data.program; }
919
+ public set program(val: number) { this.setDataVal('program', val); }
916
920
  public get watts(): number { return this.data.watts; }
917
921
  public set watts(val: number) { this.setDataVal('watts', val, this.exceedsThreshold(this.data.watts, val)); }
918
922
  public get flow(): number { return this.data.flow; }
@@ -985,23 +989,43 @@ export class PumpState extends EqState {
985
989
  pump.speedStepSize = cpump.speedStepSize;
986
990
  pump.flowStepSize = cpump.flowStepSize;
987
991
  pump.circuits = [];
988
- for (let i = 0; i < 8; i++) {
992
+ for (let i = 0; i < cpump.circuits.length; i++) {
989
993
  let c = cpump.circuits.getItemByIndex(i).get(true);
990
994
  c.circuit = state.circuits.getInterfaceById(c.circuit).get(true);
991
- if (typeof c.circuit.id === 'undefined' || typeof c.circuit.name === 'undefined') {
992
- // return "blank" circuit if none defined
993
- c.circuit.id = 0;
994
- c.circuit.name = 'Not Used';
995
- if (sys.board.valueMaps.pumpTypes.getName(cpump.type) === 'vf') {
996
- c.units = sys.board.valueMaps.pumpUnits.getValue('gpm');
997
- c.circuit.flow = 0;
998
- }
999
- else {
1000
- c.units = sys.board.valueMaps.pumpUnits.getValue('rpm');
1001
- c.circuit.speed = 0;
1002
- }
995
+ switch (pump.type.name) {
996
+ case 'vf':
997
+ c.units = sys.board.valueMaps.pumpUnits.transformByName('gpm');
998
+ break;
999
+ case 'hwvs':
1000
+ case 'vssvrs':
1001
+ case 'vs':
1002
+ c.units = sys.board.valueMaps.pumpUnits.transformByName('rpm');
1003
+ break;
1004
+ case 'ss':
1005
+ case 'ds':
1006
+ case 'sf':
1007
+ case 'hwrly':
1008
+ c.units = 'undefined';
1009
+ break;
1010
+ default:
1011
+ c.units = sys.board.valueMaps.pumpUnits.transform(c.units || 0);
1012
+ break;
1003
1013
  }
1004
- c.units = sys.board.valueMaps.pumpUnits.transform(c.units);
1014
+ // RKS: 04-08-22 - This is just wrong. If the user did not define circuits then they should not be sent down and it creates a whole host of issues.
1015
+ //if (typeof c.circuit.id === 'undefined' || typeof c.circuit.name === 'undefined') {
1016
+ // // return "blank" circuit if none defined
1017
+ // c.circuit.id = 0;
1018
+ // c.circuit.name = 'Not Used';
1019
+ // if (sys.board.valueMaps.pumpTypes.getName(cpump.type) === 'vf') {
1020
+ // c.units = sys.board.valueMaps.pumpUnits.getValue('gpm');
1021
+ // c.circuit.flow = 0;
1022
+ // }
1023
+ // else {
1024
+ // c.units = sys.board.valueMaps.pumpUnits.getValue('rpm');
1025
+ // c.circuit.speed = 0;
1026
+ // }
1027
+ //}
1028
+ //c.units = sys.board.valueMaps.pumpUnits.transform(c.units);
1005
1029
  pump.circuits.push(c);
1006
1030
  }
1007
1031
  pump.circuits.sort((a, b) => { return a.id > b.id ? 1 : -1; });
@@ -1046,6 +1070,8 @@ export class ScheduleState extends EqState {
1046
1070
  public set endTime(val: number) { this.setDataVal('endTime', val); }
1047
1071
  public get circuit(): number { return this.data.circuit; }
1048
1072
  public set circuit(val: number) { this.setDataVal('circuit', val); }
1073
+ public get disabled(): boolean { return this.data.disabled; }
1074
+ public set disabled(val: boolean) { this.setDataVal('disabled', val); }
1049
1075
  public get scheduleType(): number { return typeof (this.data.scheduleType) !== 'undefined' ? this.data.scheduleType.val : undefined; }
1050
1076
  public set scheduleType(val: number) {
1051
1077
  if (this.scheduleType !== val) {
@@ -1097,6 +1123,8 @@ export class ScheduleState extends EqState {
1097
1123
  public set coolSetpoint(val: number) { this.setDataVal('coolSetpoint', val); }
1098
1124
  public get isOn(): boolean { return this.data.isOn; }
1099
1125
  public set isOn(val: boolean) { this.setDataVal('isOn', val); }
1126
+ public get manualPriorityActive(): boolean { return this.data.manualPriorityActive; }
1127
+ public set manualPriorityActive(val: boolean) { this.setDataVal('manualPriorityActive', val); }
1100
1128
  public getExtended() {
1101
1129
  let sched = this.get(true); // Always operate on a copy.
1102
1130
  //if (typeof this.circuit !== 'undefined')
@@ -1124,6 +1152,7 @@ export interface ICircuitGroupState {
1124
1152
  dataName: string;
1125
1153
  lightingTheme?: number;
1126
1154
  showInFeatures?: boolean;
1155
+ manualPriorityActive?: boolean;
1127
1156
  get(bCopy?: boolean);
1128
1157
  emitEquipmentChange();
1129
1158
  }
@@ -1180,6 +1209,8 @@ export class CircuitGroupState extends EqState implements ICircuitGroupState, IC
1180
1209
  public set isActive(val: boolean) { this.setDataVal('isActive', val); }
1181
1210
  public get showInFeatures(): boolean { return typeof this.data.showInFeatures === 'undefined' ? true : this.data.showInFeatures; }
1182
1211
  public set showInFeatures(val: boolean) { this.setDataVal('showInFeatures', val); }
1212
+ public get manualPriorityActive(): boolean { return this.data.manualPriorityActive; }
1213
+ public set manualPriorityActive(val: boolean) { this.setDataVal('manualPriorityActive', val); }
1183
1214
  public getExtended() {
1184
1215
  let sgrp = this.get(true); // Always operate on a copy.
1185
1216
  if (typeof sgrp.showInFeatures === 'undefined') sgrp.showInFeatures = true;
@@ -1264,6 +1295,8 @@ export class LightGroupState extends EqState implements ICircuitGroupState, ICir
1264
1295
  public set isOn(val: boolean) { this.setDataVal('isOn', val); }
1265
1296
  public get isActive(): boolean { return this.data.isActive; }
1266
1297
  public set isActive(val: boolean) { this.setDataVal('isActive', val); }
1298
+ public get manualPriorityActive(): boolean { return this.data.manualPriorityActive; }
1299
+ public set manualPriorityActive(val: boolean) { this.setDataVal('manualPriorityActive', val); }
1267
1300
  public async setThemeAsync(val: number) { return sys.board.circuits.setLightThemeAsync; }
1268
1301
  public getExtended() {
1269
1302
  let sgrp = this.get(true); // Always operate on a copy.
@@ -1334,6 +1367,7 @@ export class BodyTempState extends EqState {
1334
1367
  if (typeof this.heaterCooldownDelay === 'undefined') this.data.heaterCooldownDelay = false;
1335
1368
  if (typeof this.data.startDelay === 'undefined') this.data.startDelay = false;
1336
1369
  if (typeof this.data.stopDelay === 'undefined') this.data.stopDelay = false;
1370
+ if (typeof this.data.showInDashboard === 'undefined') this.data.showInDashboard = true;
1337
1371
  }
1338
1372
  public get id(): number { return this.data.id; }
1339
1373
  public set id(val: number) { this.setDataVal('id', val); }
@@ -1376,6 +1410,8 @@ export class BodyTempState extends EqState {
1376
1410
  public set startDelay(val: boolean) { this.setDataVal('startDelay', val); }
1377
1411
  public get stopDelay(): boolean { return this.data.stopDelay; }
1378
1412
  public set stopDelay(val: boolean) { this.setDataVal('stopDelay', val); }
1413
+ public get showInDashboard(): boolean { return this.data.showInDashboard; }
1414
+ public set showInDashboard(val: boolean) { this.setDataVal('showInDashboard', val); }
1379
1415
 
1380
1416
  public get isCovered(): boolean { return this.data.isCovered; }
1381
1417
  public set isCovered(val: boolean) { this.setDataVal('isCovered', val); }
@@ -1578,6 +1614,8 @@ export class FeatureState extends EqState implements ICircuitState {
1578
1614
  public set freezeProtect(val: boolean) { this.setDataVal('freezeProtect', val); }
1579
1615
  public get isActive(): boolean { return this.data.isActive; }
1580
1616
  public set isActive(val: boolean) { this.setDataVal('isActive', val); }
1617
+ public get manualPriorityActive(): boolean { return this.data.manualPriorityActive; }
1618
+ public set manualPriorityActive(val: boolean) { this.setDataVal('manualPriorityActive', val); }
1581
1619
  }
1582
1620
  export class VirtualCircuitState extends EqState implements ICircuitState {
1583
1621
  public dataName: string = 'virtualCircuit';
@@ -1724,6 +1762,8 @@ export class CircuitState extends EqState implements ICircuitState {
1724
1762
  public set lockoutOn(val: boolean) { this.setDataVal('lockoutOn', val); }
1725
1763
  public get lockoutOff(): boolean { return this.data.lockoutOff; }
1726
1764
  public set lockoutOff(val: boolean) { this.setDataVal('lockoutOff', val); }
1765
+ public get manualPriorityActive(): boolean { return this.data.manualPriorityActive; }
1766
+ public set manualPriorityActive(val: boolean) { this.setDataVal('manualPriorityActive', val); }
1727
1767
  }
1728
1768
  export class ValveStateCollection extends EqStateCollection<ValveState> {
1729
1769
  public createItem(data: any): ValveState { return new ValveState(data); }
@@ -1800,9 +1840,16 @@ export class CoverState extends EqState {
1800
1840
  public set isClosed(val: boolean) { this.setDataVal('isClosed', val); }
1801
1841
  }
1802
1842
  export class ChlorinatorStateCollection extends EqStateCollection<ChlorinatorState> {
1843
+ public superChlor: { id:number, lastDispatch: number, reference: number }[] = [];
1844
+ public getSuperChlor(id: number): { id: number, lastDispatch: number, reference: number } {
1845
+ let sc = this.superChlor.find(elem => id === elem.id);
1846
+ if (typeof sc === 'undefined') {
1847
+ sc = { id: id, lastDispatch: 0, reference: 0 };
1848
+ this.superChlor.push(sc);
1849
+ }
1850
+ return sc;
1851
+ }
1803
1852
  public createItem(data: any): ChlorinatorState { return new ChlorinatorState(data); }
1804
- public superChlorReference: number = 0;
1805
- public lastDispatchSuperChlor: number = 0;
1806
1853
  public cleanupState() {
1807
1854
  for (let i = this.data.length - 1; i >= 0; i--) {
1808
1855
  if (isNaN(this.data[i].id)) this.data.splice(i, 1);
@@ -1815,10 +1862,10 @@ export class ChlorinatorStateCollection extends EqStateCollection<ChlorinatorSta
1815
1862
  let c = cfg[i];
1816
1863
  let s = this.getItemById(cfg[i].id, true);
1817
1864
  s.type = c.type;
1865
+ s.model = c.model;
1818
1866
  s.name = c.name;
1819
1867
  s.isActive = c.isActive;
1820
1868
  }
1821
-
1822
1869
  }
1823
1870
  }
1824
1871
  export class ChlorinatorState extends EqState {
@@ -1868,6 +1915,13 @@ export class ChlorinatorState extends EqState {
1868
1915
  this.hasChanged = true;
1869
1916
  }
1870
1917
  }
1918
+ public get model(): number { return typeof (this.data.model) !== 'undefined' ? this.data.model.val : 0; }
1919
+ public set model(val: number) {
1920
+ if (this.model !== val) {
1921
+ this.data.model = sys.board.valueMaps.chlorinatorModel.transform(val);
1922
+ this.hasChanged = true;
1923
+ }
1924
+ }
1871
1925
  public get body(): number { return typeof (this.data.body) !== 'undefined' ? this.data.body.val : -1; }
1872
1926
  public set body(val: number) {
1873
1927
  if (this.body !== val) {
@@ -1915,37 +1969,59 @@ export class ChlorinatorState extends EqState {
1915
1969
  }
1916
1970
  public get superChlorRemaining(): number { return this.data.superChlorRemaining || 0; }
1917
1971
  public set superChlorRemaining(val: number) {
1972
+ if (val === this.data.superChlorRemaining) return;
1918
1973
  let remaining: number;
1919
- if (sys.controllerType === 'nixie') {
1920
- remaining = Math.max(0, val);
1974
+ let sc = state.chlorinators.getSuperChlor(this.id);
1975
+ let chlor = sys.chlorinators.getItemById(this.id);
1976
+ if (chlor.master === 1) {
1977
+ // If we are 10 seconds different then we need to send it off and save the data.
1978
+ if (Math.floor(val / 10) !== Math.floor(this.superChlorRemaining / 10)) {
1979
+ this.hasChanged = true;
1980
+ remaining = val;
1981
+ sc.reference = Math.floor(new Date().getTime() / 1000);
1982
+ this.setDataVal('superChlorRemaining', remaining);
1983
+ }
1984
+ else if (val <= 0)
1985
+ remaining = 0;
1986
+ else
1987
+ remaining = this.superChlorRemaining;
1988
+ }
1989
+ else if (chlor.master === 2) {
1990
+ // If we are 10 seconds different then we need to send it off and save the data.
1991
+ if (Math.floor(val / 10) !== Math.floor(this.superChlorRemaining / 10)) {
1992
+ this.hasChanged = true;
1993
+ remaining = val;
1994
+ sc.reference = Math.floor(new Date().getTime() / 1000);
1995
+ this.setDataVal('superChlorRemaining', remaining);
1996
+ }
1921
1997
  }
1922
1998
  else if (sys.controllerType === 'intellicenter') {
1923
1999
  // Trim the seconds off both of these as we will be keeping the seconds separately since this
1924
2000
  // only reports in minutes. That way our seconds become self healing.
1925
2001
  if (Math.ceil(this.superChlorRemaining / 60) * 60 !== val) {
1926
- state.chlorinators.superChlorReference = Math.floor(new Date().getTime() / 1000); // Get the epoc and strip the milliseconds.
2002
+ sc.reference = Math.floor(new Date().getTime() / 1000); // Get the epoc and strip the milliseconds.
1927
2003
  this.hasChanged = true;
1928
2004
  }
1929
- let secs = Math.floor(new Date().getTime() / 1000) - state.chlorinators.superChlorReference;
2005
+ let secs = Math.floor(new Date().getTime() / 1000) - sc.reference;
1930
2006
  remaining = Math.max(0, val - Math.min(secs, 60));
2007
+ if (sc.lastDispatch - 5 > remaining) this.hasChanged = true;
2008
+ this.data.superChlorRemaining = remaining;
1931
2009
  }
1932
2010
  else {
1933
2011
  // *Touch only reports superchlor hours remaining.
1934
2012
  // If we have the same hours as existing, retain the mins + secs
1935
2013
  if (Math.ceil(this.superChlorRemaining / 3600) * 60 !== val / 60) {
1936
- state.chlorinators.superChlorReference = Math.floor(new Date().getTime() / 1000); // Get the epoc and strip the milliseconds.
2014
+ sc.reference = Math.floor(new Date().getTime() / 1000); // Get the epoc and strip the milliseconds.
1937
2015
  this.hasChanged = true;
1938
2016
  }
1939
- let secs = Math.floor(new Date().getTime() / 1000) - state.chlorinators.superChlorReference;
2017
+ let secs = Math.floor(new Date().getTime() / 1000) - sc.reference;
1940
2018
  remaining = Math.max(0, val - Math.min(secs, 3600));
2019
+ if (sc.lastDispatch - 5 > remaining) this.hasChanged = true;
2020
+ this.data.superChlorRemaining = remaining;
1941
2021
  }
1942
- if (state.chlorinators.lastDispatchSuperChlor - 5 > remaining) this.hasChanged = true;
1943
- if (this.hasChanged) state.chlorinators.lastDispatchSuperChlor = remaining;
1944
- this.data.superChlorRemaining = remaining;
1945
- if (remaining > 0)
1946
- this.setDataVal('superChlor', true);
1947
- else
1948
- this.setDataVal('superChlor', false);
2022
+ if (this.hasChanged) sc.lastDispatch = remaining;
2023
+ this.setDataVal('superChlor', remaining > 0);
2024
+ chlor.superChlor = remaining > 0;
1949
2025
  }
1950
2026
  public getExtended(): any {
1951
2027
  let schlor = this.get(true);