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.
- package/.docker/Dockerfile.armv6 +29 -0
- package/.docker/Dockerfile.armv7 +29 -0
- package/.docker/Dockerfile.linux +62 -0
- package/.docker/Dockerfile.windows +43 -0
- package/.docker/docker-compose.yml +47 -0
- package/.docker/ecosystem.config.js +35 -0
- package/.github/workflows/docker-publish-njsPC-linux.yml +81 -0
- package/.github/workflows/docker-publish-njsPC-windows.yml +41 -0
- package/Dockerfile +4 -3
- package/README.md +4 -1
- package/config/Config.ts +1 -1
- package/controller/Constants.ts +164 -67
- package/controller/Equipment.ts +79 -18
- package/controller/Lockouts.ts +15 -0
- package/controller/State.ts +280 -7
- package/controller/boards/EasyTouchBoard.ts +226 -102
- package/controller/boards/IntelliCenterBoard.ts +67 -18
- package/controller/boards/IntelliTouchBoard.ts +2 -4
- package/controller/boards/NixieBoard.ts +84 -27
- package/controller/boards/SunTouchBoard.ts +8 -2
- package/controller/boards/SystemBoard.ts +3259 -3242
- package/controller/comms/ScreenLogic.ts +60 -57
- package/controller/comms/messages/Messages.ts +4 -4
- package/controller/comms/messages/config/ChlorinatorMessage.ts +10 -3
- package/controller/comms/messages/config/ExternalMessage.ts +4 -1
- package/controller/comms/messages/config/PumpMessage.ts +8 -7
- package/controller/comms/messages/config/RemoteMessage.ts +48 -43
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +8 -2
- package/controller/comms/messages/status/EquipmentStateMessage.ts +9 -4
- package/controller/nixie/NixieEquipment.ts +1 -1
- package/controller/nixie/bodies/Body.ts +1 -1
- package/controller/nixie/chemistry/ChemController.ts +37 -28
- package/controller/nixie/circuits/Circuit.ts +36 -0
- package/controller/nixie/heaters/Heater.ts +24 -5
- package/controller/nixie/pumps/Pump.ts +155 -97
- package/controller/nixie/schedules/Schedule.ts +207 -126
- package/defaultConfig.json +4 -3
- package/logger/DataLogger.ts +7 -7
- package/package.json +3 -3
- package/sendSocket.js +32 -0
- package/web/Server.ts +17 -11
- package/web/bindings/homeassistant.json +2 -2
- package/web/interfaces/mqttInterface.ts +18 -18
- package/web/services/config/Config.ts +34 -1
- package/web/services/state/State.ts +10 -3
- package/web/services/state/StateSocket.ts +7 -3
- package/web/services/utilities/Utilities.ts +3 -3
|
@@ -26,6 +26,7 @@ import { state, ChlorinatorState, LightGroupState, VirtualCircuitState, ICircuit
|
|
|
26
26
|
import { utils } from '../../controller/Constants';
|
|
27
27
|
import { InvalidEquipmentIdError, InvalidEquipmentDataError, EquipmentNotFoundError, MessageError, InvalidOperationError } from '../Errors';
|
|
28
28
|
import { ncp } from '../nixie/Nixie';
|
|
29
|
+
import { Timestamp } from "../Constants"
|
|
29
30
|
export class IntelliCenterBoard extends SystemBoard {
|
|
30
31
|
public needsConfigChanges: boolean = false;
|
|
31
32
|
constructor(system: PoolSystem) {
|
|
@@ -389,6 +390,10 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
389
390
|
for (let i = 0; i < sys.circuits.length; i++) {
|
|
390
391
|
let c = sys.circuits.getItemByIndex(i);
|
|
391
392
|
if (c.id <= 40) c.master = 0;
|
|
393
|
+
if (typeof sys.board.valueMaps.circuitFunctions.get(c.type).isLight) {
|
|
394
|
+
let s = state.circuits.getItemById(c.id);
|
|
395
|
+
if (s.action !== 0) s.action = 0;
|
|
396
|
+
}
|
|
392
397
|
}
|
|
393
398
|
for (let i = 0; i < sys.valves.length; i++) {
|
|
394
399
|
let v = sys.valves.getItemByIndex(i);
|
|
@@ -2258,9 +2263,9 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2258
2263
|
let dow = dt.getDay();
|
|
2259
2264
|
// Convert the dow to the bit value.
|
|
2260
2265
|
let sd = sys.board.valueMaps.scheduleDays.toArray().find(elem => elem.dow === dow);
|
|
2261
|
-
let dayVal = sd.bitVal || sd.val; // The bitval allows mask overrides.
|
|
2266
|
+
//let dayVal = sd.bitVal || sd.val; // The bitval allows mask overrides.
|
|
2262
2267
|
let ts = dt.getHours() * 60 + dt.getMinutes();
|
|
2263
|
-
if ((sched.scheduleDays &
|
|
2268
|
+
if ((sched.scheduleDays & sd.bitval) > 0 && ts >= sched.startTime && ts <= sched.endTime) byte = byte | (1 << bit);
|
|
2264
2269
|
}
|
|
2265
2270
|
}
|
|
2266
2271
|
else if (sched.isOn) byte = byte | (1 << bit);
|
|
@@ -2862,21 +2867,28 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2862
2867
|
retries: 2,
|
|
2863
2868
|
response: IntelliCenterBoard.getAckResponse(168)
|
|
2864
2869
|
});
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2870
|
+
try {
|
|
2871
|
+
await out.sendAsync();
|
|
2872
|
+
let body1 = sys.bodies.getItemById(1);
|
|
2873
|
+
let sbody1 = state.temps.bodies.getItemById(1);
|
|
2874
|
+
body1.heatMode = sbody1.heatMode = bhs.body1.heatMode;
|
|
2875
|
+
body1.heatSetpoint = sbody1.heatSetpoint = bhs.body1.heatSetpoint;
|
|
2876
|
+
body1.coolSetpoint = sbody1.coolSetpoint = bhs.body1.coolSetpoint;
|
|
2877
|
+
if (sys.equipment.dual || sys.equipment.shared) {
|
|
2878
|
+
let body2 = sys.bodies.getItemById(2);
|
|
2879
|
+
let sbody2 = state.temps.bodies.getItemById(2);
|
|
2880
|
+
body2.heatMode = sbody2.heatMode = bhs.body2.heatMode;
|
|
2881
|
+
body2.heatSetpoint = sbody2.heatSetpoint = bhs.body2.heatSetpoint;
|
|
2882
|
+
body2.coolSetpoint = sbody2.coolSetpoint = bhs.body2.coolSetpoint;
|
|
2883
|
+
}
|
|
2884
|
+
state.emitEquipmentChanges();
|
|
2885
|
+
} catch (err) {
|
|
2886
|
+
bhs.processing = false;
|
|
2887
|
+
throw (err);
|
|
2888
|
+
}
|
|
2889
|
+
finally {
|
|
2890
|
+
bhs.processing = false;
|
|
2891
|
+
}
|
|
2880
2892
|
return true;
|
|
2881
2893
|
}
|
|
2882
2894
|
else {
|
|
@@ -3119,6 +3131,7 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3119
3131
|
}
|
|
3120
3132
|
}
|
|
3121
3133
|
class IntelliCenterScheduleCommands extends ScheduleCommands {
|
|
3134
|
+
_lastScheduleCheck: number = 0;
|
|
3122
3135
|
public async setScheduleAsync(data: any): Promise<Schedule> {
|
|
3123
3136
|
if (typeof data.id !== 'undefined') {
|
|
3124
3137
|
let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10);
|
|
@@ -3141,6 +3154,8 @@ class IntelliCenterScheduleCommands extends ScheduleCommands {
|
|
|
3141
3154
|
let endTime = typeof data.endTime !== 'undefined' ? data.endTime : sched.endTime;
|
|
3142
3155
|
let schedDays = sys.board.schedules.transformDays(typeof data.scheduleDays !== 'undefined' ? data.scheduleDays : sched.scheduleDays);
|
|
3143
3156
|
let display = typeof data.display !== 'undefined' ? data.display : sched.display || 0;
|
|
3157
|
+
let endTimeOffset = typeof data.endTimeOffset !== 'undefined' ? data.endTimeOffset : sched.endTimeOffset;
|
|
3158
|
+
let startTimeOffset = typeof data.startTimeOffset !== 'undefined' ? data.startTimeOffset : sched.startTimeOffset;
|
|
3144
3159
|
|
|
3145
3160
|
// Ensure all the defaults.
|
|
3146
3161
|
if (isNaN(startDate.getTime())) startDate = new Date();
|
|
@@ -3216,11 +3231,45 @@ class IntelliCenterScheduleCommands extends ScheduleCommands {
|
|
|
3216
3231
|
ssched.isActive = sched.isActive = true;
|
|
3217
3232
|
ssched.display = sched.display = display;
|
|
3218
3233
|
ssched.emitEquipmentChange();
|
|
3234
|
+
ssched.startTimeOffset = sched.startTimeOffset = startTimeOffset;
|
|
3235
|
+
ssched.endTimeOffset = sched.endTimeOffset = endTimeOffset;
|
|
3219
3236
|
return sched;
|
|
3220
3237
|
}
|
|
3221
3238
|
else
|
|
3222
3239
|
return Promise.reject(new InvalidEquipmentIdError('No schedule information provided', undefined, 'Schedule'));
|
|
3223
3240
|
}
|
|
3241
|
+
public syncScheduleStates() {
|
|
3242
|
+
// This is triggered from the 204 message in IntelliCenter. We will
|
|
3243
|
+
// be checking to ensure it does not load the server so we only do this every 10 seconds.
|
|
3244
|
+
if (this._lastScheduleCheck > new Date().getTime() - 10000) return;
|
|
3245
|
+
try {
|
|
3246
|
+
// The call below also calculates the schedule window either the current or next.
|
|
3247
|
+
ncp.schedules.triggerSchedules(); // At this point we are not adding Nixie schedules to IntelliCenter but this will trigger
|
|
3248
|
+
// the proper time windows if they exist.
|
|
3249
|
+
// Check each running circuit/feature to see when it will be going off.
|
|
3250
|
+
let scheds = state.schedules.getActiveSchedules();
|
|
3251
|
+
let circs: { state: ICircuitState, endTime: number }[] = [];
|
|
3252
|
+
for (let i = 0; i < scheds.length; i++) {
|
|
3253
|
+
let ssched = scheds[i];
|
|
3254
|
+
if (!ssched.isOn || ssched.disabled || !ssched.isActive) continue;
|
|
3255
|
+
let c = circs.find(x => x.state.id === ssched.circuit);
|
|
3256
|
+
if (typeof c === 'undefined') {
|
|
3257
|
+
let cstate = state.circuits.getInterfaceById(ssched.circuit);
|
|
3258
|
+
c = { state: cstate, endTime: ssched.scheduleTime.endTime.getTime() };
|
|
3259
|
+
circs.push;
|
|
3260
|
+
}
|
|
3261
|
+
if (c.endTime < ssched.scheduleTime.endTime.getTime()) c.endTime = ssched.scheduleTime.endTime.getTime();
|
|
3262
|
+
}
|
|
3263
|
+
for (let i = 0; i < circs.length; i++) {
|
|
3264
|
+
let c = circs[i];
|
|
3265
|
+
if (c.state.endTime.getTime() !== c.endTime) {
|
|
3266
|
+
c.state.endTime = new Timestamp(new Date(c.endTime));
|
|
3267
|
+
c.state.emitEquipmentChange();
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
this._lastScheduleCheck = new Date().getTime();
|
|
3271
|
+
} catch (err) { logger.error(`Error synchronizing schedule states`); }
|
|
3272
|
+
}
|
|
3224
3273
|
public async deleteScheduleAsync(data: any): Promise<Schedule> {
|
|
3225
3274
|
if (typeof data.id !== 'undefined') {
|
|
3226
3275
|
let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10);
|
|
@@ -3484,7 +3533,7 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3484
3533
|
if (gasHeaterInstalled) sys.board.valueMaps.heatSources.merge([[2, { name: 'heater', desc: 'Heater' }]]);
|
|
3485
3534
|
if (mastertempInstalled) sys.board.valueMaps.heatSources.merge([[11, { name: 'mtheater', desc: 'MasterTemp' }]]);
|
|
3486
3535
|
if (solarInstalled && (gasHeaterInstalled || heatPumpInstalled)) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar Only', hasCoolSetpoint: htypes.hasCoolSetpoint }], [4, { name: 'solarpref', desc: 'Solar Preferred', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
3487
|
-
else if (solarInstalled) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar',
|
|
3536
|
+
else if (solarInstalled) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
3488
3537
|
if (heatPumpInstalled && (gasHeaterInstalled || solarInstalled)) sys.board.valueMaps.heatSources.merge([[9, { name: 'heatpump', desc: 'Heatpump Only' }], [25, { name: 'heatpumppref', desc: 'Heat Pump Pref' }]]);
|
|
3489
3538
|
else if (heatPumpInstalled) sys.board.valueMaps.heatSources.merge([[9, { name: 'heatpump', desc: 'Heat Pump' }]]);
|
|
3490
3539
|
if (ultratempInstalled && (gasHeaterInstalled || heatPumpInstalled)) sys.board.valueMaps.heatSources.merge([[5, { name: 'ultratemp', desc: 'UltraTemp Only', hasCoolSetpoint: htypes.hasCoolSetpoint }], [6, { name: 'ultratemppref', desc: 'UltraTemp Pref', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
@@ -86,7 +86,7 @@ export class IntelliTouchBoard extends EasyTouchBoard {
|
|
|
86
86
|
|
|
87
87
|
}
|
|
88
88
|
if (typeof sys.valves.find((v) => v.id === 2) === 'undefined') {
|
|
89
|
-
let valve = sys.valves.getItemById(
|
|
89
|
+
let valve = sys.valves.getItemById(2, true);
|
|
90
90
|
valve.isIntake = false;
|
|
91
91
|
valve.isReturn = false;
|
|
92
92
|
valve.type = 0;
|
|
@@ -360,9 +360,7 @@ class ITTouchConfigQueue extends TouchConfigQueue {
|
|
|
360
360
|
this.queueItems(GetTouchConfigCategories.highSpeedCircuits, [0]);
|
|
361
361
|
this.queueRange(GetTouchConfigCategories.pumpConfig, 1, sys.equipment.maxPumps);
|
|
362
362
|
this.queueRange(GetTouchConfigCategories.circuitGroups, 0, sys.equipment.maxFeatures - 1);
|
|
363
|
-
|
|
364
|
-
if (sys.chlorinators.getItemById(1).isActive)
|
|
365
|
-
this.queueItems(GetTouchConfigCategories.intellichlor, [0]);
|
|
363
|
+
this.queueItems(GetTouchConfigCategories.intellichlor, [0]);
|
|
366
364
|
if (this.remainingItems > 0) {
|
|
367
365
|
var self = this;
|
|
368
366
|
setTimeout(() => { self.processNext(); }, 50);
|
|
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
import * as extend from 'extend';
|
|
19
19
|
import { ncp } from "../nixie/Nixie";
|
|
20
20
|
import { NixieHeaterBase } from "../nixie/heaters/Heater";
|
|
21
|
-
import { utils } from '../Constants';
|
|
21
|
+
import { Timestamp, utils } from '../Constants';
|
|
22
22
|
import {SystemBoard, byteValueMap, BodyCommands, FilterCommands, PumpCommands, SystemCommands, CircuitCommands, FeatureCommands, ValveCommands, HeaterCommands, ChlorinatorCommands, ChemControllerCommands, EquipmentIdRange} from './SystemBoard';
|
|
23
23
|
import { logger } from '../../logger/Logger';
|
|
24
24
|
import { state, CircuitState, ICircuitState, ICircuitGroupState, LightGroupState, ValveState, FilterState, BodyTempState, FeatureState } from '../State';
|
|
@@ -221,6 +221,21 @@ export class NixieBoard extends SystemBoard {
|
|
|
221
221
|
[53, { name: 'greenblue', desc: 'Green-Blue', types: ['pooltone'], sequence: 14 }],
|
|
222
222
|
[54, { name: 'redgreen', desc: 'Red-Green', types: ['pooltone'], sequence: 15 }],
|
|
223
223
|
[55, { name: 'bluered', desc: 'Blue-red', types: ['pooltone'], sequence: 16 }],
|
|
224
|
+
// Jandy Pro Series WaterColors Themes
|
|
225
|
+
[56, { name: 'alpinewhite', desc: 'Alpine White', types: ['watercolors'], sequence: 1 }],
|
|
226
|
+
[57, { name: 'skyblue', desc: 'Sky Blue', types: ['watercolors'], sequence: 2 }],
|
|
227
|
+
[58, { name: 'cobaltblue', desc: 'Cobalt Blue', types: ['watercolors'], sequence: 3 }],
|
|
228
|
+
[59, { name: 'caribbeanblue', desc: 'Caribbean Blue', types: ['watercolors'], sequence: 4 }],
|
|
229
|
+
[60, { name: 'springgreen', desc: 'Spring Green', types: ['watercolors'], sequence: 5 }],
|
|
230
|
+
[61, { name: 'emeraldgreen', desc: 'Emerald Green', types: ['watercolors'], sequence: 6 }],
|
|
231
|
+
[62, { name: 'emeraldrose', desc: 'Emerald Rose', types: ['watercolors'], sequence: 7 }],
|
|
232
|
+
[63, { name: 'magenta', desc: 'Magenta', types: ['watercolors'], sequence: 8 }],
|
|
233
|
+
[64, { name: 'violet', desc: 'Violet', types: ['watercolors'], sequence: 9 }],
|
|
234
|
+
[65, { name: 'slowcolorsplash', desc: 'Slow Color Splash', types: ['watercolors'], sequence: 10 }],
|
|
235
|
+
[66, { name: 'fastcolorsplash', desc: 'Fast Color Splash', types: ['watercolors'], sequence: 11 }],
|
|
236
|
+
[67, { name: 'americathebeautiful', desc: 'America the Beautiful', types: ['watercolors'], sequence: 12 }],
|
|
237
|
+
[68, { name: 'fattuesday', desc: 'Fat Tuesday', types: ['watercolors'], sequence: 13 }],
|
|
238
|
+
[69, { name: 'discotech', desc: 'Disco Tech', types: ['watercolors'], sequence: 14 }],
|
|
224
239
|
[255, { name: 'none', desc: 'None' }]
|
|
225
240
|
]);
|
|
226
241
|
this.valueMaps.lightColors = new byteValueMap([
|
|
@@ -266,9 +281,35 @@ export class NixieBoard extends SystemBoard {
|
|
|
266
281
|
[4, { name: 'spaCommand', desc: 'Spa Command', maxButtons: 10 }]
|
|
267
282
|
]);
|
|
268
283
|
}
|
|
284
|
+
public async closeAsync() {
|
|
285
|
+
logger.info(`Closing Nixie Board`);
|
|
286
|
+
await ncp.closeAsync();
|
|
287
|
+
}
|
|
269
288
|
public async checkConfiguration() {
|
|
270
289
|
state.status = sys.board.valueMaps.controllerStatus.transform(0, 0);
|
|
271
290
|
state.emitControllerChange();
|
|
291
|
+
// Set all the schedule data based upon the config.
|
|
292
|
+
for (let i = 0; i < sys.schedules.length; i++) {
|
|
293
|
+
let sched = sys.schedules.getItemByIndex(i);
|
|
294
|
+
let ssched = state.schedules.getItemById(sched.id, true);
|
|
295
|
+
ssched.circuit = sched.circuit;
|
|
296
|
+
ssched.scheduleDays = sched.scheduleDays;
|
|
297
|
+
ssched.scheduleType = sched.scheduleType;
|
|
298
|
+
ssched.changeHeatSetpoint = sched.changeHeatSetpoint;
|
|
299
|
+
ssched.heatSetpoint = sched.heatSetpoint;
|
|
300
|
+
ssched.coolSetpoint = sched.coolSetpoint;
|
|
301
|
+
ssched.heatSource = sched.heatSource;
|
|
302
|
+
ssched.startTime = sched.startTime;
|
|
303
|
+
ssched.endTime = sched.endTime;
|
|
304
|
+
ssched.startTimeType = sched.startTimeType;
|
|
305
|
+
ssched.endTimeType = sched.endTimeType;
|
|
306
|
+
ssched.startDate = sched.startDate;
|
|
307
|
+
ssched.isActive = sched.isActive = true;
|
|
308
|
+
sched.disabled = sched.disabled;
|
|
309
|
+
ssched.display = sched.display;
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
272
313
|
state.status = sys.board.valueMaps.controllerStatus.transform(1, 100);
|
|
273
314
|
state.emitControllerChange();
|
|
274
315
|
}
|
|
@@ -390,7 +431,7 @@ export class NixieBoard extends SystemBoard {
|
|
|
390
431
|
sys.circuits.removeItemById(6);
|
|
391
432
|
state.circuits.removeItemById(6);
|
|
392
433
|
}
|
|
393
|
-
|
|
434
|
+
|
|
394
435
|
sys.equipment.setEquipmentIds();
|
|
395
436
|
sys.board.bodies.initFilters();
|
|
396
437
|
state.status = sys.board.valueMaps.controllerStatus.transform(2, 0);
|
|
@@ -411,10 +452,11 @@ export class NixieBoard extends SystemBoard {
|
|
|
411
452
|
sys.board.heaters.updateHeaterServices();
|
|
412
453
|
state.cleanupState();
|
|
413
454
|
logger.info(`${sys.equipment.model} control board initialized`);
|
|
414
|
-
state.status = sys.board.valueMaps.controllerStatus.transform(1, 100);
|
|
455
|
+
//state.status = sys.board.valueMaps.controllerStatus.transform(1, 100);
|
|
415
456
|
state.mode = sys.board.valueMaps.panelModes.encode('auto');
|
|
416
457
|
// At this point we should have the start of a board so lets check to see if we are ready or if we are stuck initializing.
|
|
417
458
|
await setTimeout(5000);
|
|
459
|
+
state.status = sys.board.valueMaps.controllerStatus.transform(1, 100);
|
|
418
460
|
await self.processStatusAsync();
|
|
419
461
|
} catch (err) { state.status = 255; logger.error(`Error Initializing Nixie Control Panel ${err.message}`); }
|
|
420
462
|
}
|
|
@@ -529,11 +571,11 @@ export class NixieSystemCommands extends SystemCommands {
|
|
|
529
571
|
state.delay = sys.board.valueMaps.delay.getValue('nodelay');
|
|
530
572
|
return Promise.resolve(state.data.delay);
|
|
531
573
|
}
|
|
532
|
-
public setManualOperationPriority(id: number): Promise<any> {
|
|
574
|
+
public setManualOperationPriority(id: number): Promise<any> {
|
|
533
575
|
let cstate = state.circuits.getInterfaceById(id);
|
|
534
576
|
delayMgr.setManualPriorityDelay(cstate);
|
|
535
|
-
return Promise.resolve(cstate);
|
|
536
|
-
|
|
577
|
+
return Promise.resolve(cstate);
|
|
578
|
+
}
|
|
537
579
|
public setDateTimeAsync(obj: any): Promise<any> { return Promise.resolve(); }
|
|
538
580
|
public getDOW() { return this.board.valueMaps.scheduleDays.toArray(); }
|
|
539
581
|
public async setGeneralAsync(obj: any): Promise<General> {
|
|
@@ -669,7 +711,6 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
669
711
|
break;
|
|
670
712
|
default:
|
|
671
713
|
await ncp.circuits.setCircuitStateAsync(circ, newState);
|
|
672
|
-
await sys.board.processStatusAsync();
|
|
673
714
|
break;
|
|
674
715
|
}
|
|
675
716
|
// Let the main nixie controller set the circuit state and affect the relays if it needs to.
|
|
@@ -680,6 +721,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
680
721
|
state.emitEquipmentChanges();
|
|
681
722
|
ncp.pumps.syncPumpStates();
|
|
682
723
|
sys.board.suspendStatus(false);
|
|
724
|
+
await sys.board.processStatusAsync();
|
|
683
725
|
}
|
|
684
726
|
}
|
|
685
727
|
protected async setCleanerCircuitStateAsync(id: number, val: boolean, ignoreDelays?: boolean): Promise<ICircuitState> {
|
|
@@ -742,8 +784,9 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
742
784
|
}
|
|
743
785
|
if (sys.general.options.cleanerStartDelay && sys.general.options.cleanerStartDelayTime) {
|
|
744
786
|
let bcstate = state.circuits.getItemById(bstate.circuit);
|
|
787
|
+
let stime = typeof bcstate.startTime === 'undefined' ? dtNow : (dtNow - bcstate.startTime.getTime());
|
|
745
788
|
// So we should be started. Lets determine whethere there should be any delay.
|
|
746
|
-
delayTime = Math.max(Math.round(((sys.general.options.cleanerStartDelayTime * 1000) -
|
|
789
|
+
delayTime = Math.max(Math.round(((sys.general.options.cleanerStartDelayTime * 1000) - stime) / 1000), delayTime);
|
|
747
790
|
logger.info(`Cleaner delay time calculated to ${delayTime}`);
|
|
748
791
|
}
|
|
749
792
|
}
|
|
@@ -864,6 +907,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
864
907
|
// circuit is already under delay it should have been processed out earlier.
|
|
865
908
|
delayMgr.cancelPumpValveDelays();
|
|
866
909
|
delayMgr.cancelHeaterStartupDelays();
|
|
910
|
+
sys.board.heaters.clearPrevHeaterOffTemp();
|
|
867
911
|
if (cstate.startDelay) delayMgr.clearBodyStartupDelay(bstate);
|
|
868
912
|
await this.turnOffCleanerCircuits(bstate);
|
|
869
913
|
if (sys.equipment.shared && bstate.id === 2) await this.turnOffDrainCircuits(ignoreDelays);
|
|
@@ -967,7 +1011,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
967
1011
|
return cstate;
|
|
968
1012
|
} catch (err) { logger.error(`Nixie: Error setDrainCircuitStateAsync ${err.message}`); return Promise.reject(new BoardProcessError(`Nixie: Error setDrainCircuitStateAsync ${err.message}`, 'setDrainCircuitStateAsync')); }
|
|
969
1013
|
}
|
|
970
|
-
|
|
1014
|
+
|
|
971
1015
|
public toggleCircuitStateAsync(id: number): Promise<ICircuitState> {
|
|
972
1016
|
let circ = state.circuits.getInterfaceById(id);
|
|
973
1017
|
return this.setCircuitStateAsync(id, !(circ.isOn || false));
|
|
@@ -1112,7 +1156,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
1112
1156
|
if (typeof obj.eggTimer !== 'undefined') group.eggTimer = Math.min(Math.max(parseInt(obj.eggTimer, 10), 0), 1440);
|
|
1113
1157
|
if (typeof obj.showInFeatures !== 'undefined') sgroup.showInFeatures = group.showInFeatures = utils.makeBool(obj.showInFeatures);
|
|
1114
1158
|
sgroup.type = group.type;
|
|
1115
|
-
|
|
1159
|
+
|
|
1116
1160
|
group.dontStop = group.eggTimer === 1440;
|
|
1117
1161
|
group.isActive = sgroup.isActive = true;
|
|
1118
1162
|
|
|
@@ -1179,7 +1223,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
1179
1223
|
// group.circuits.length = obj.circuits.length; // RSG - removed as this will delete circuits that were not changed
|
|
1180
1224
|
group.circuits.length = obj.circuits.length;
|
|
1181
1225
|
sgroup.emitEquipmentChange();
|
|
1182
|
-
|
|
1226
|
+
|
|
1183
1227
|
}
|
|
1184
1228
|
resolve(group);
|
|
1185
1229
|
});
|
|
@@ -1266,7 +1310,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
1266
1310
|
//grp.lightingTheme = sgrp.lightingTheme = theme;
|
|
1267
1311
|
let thm = sys.board.valueMaps.lightThemes.transform(theme);
|
|
1268
1312
|
sgrp.action = sys.board.valueMaps.circuitActions.getValue('lighttheme');
|
|
1269
|
-
|
|
1313
|
+
|
|
1270
1314
|
try {
|
|
1271
1315
|
// Go through and set the theme for all lights in the group.
|
|
1272
1316
|
for (let i = 0; i < grp.circuits.length; i++) {
|
|
@@ -1380,7 +1424,7 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
1380
1424
|
else if (circuit.desiredState === 5){
|
|
1381
1425
|
// off/ignore
|
|
1382
1426
|
if (val) cval = false;
|
|
1383
|
-
else continue;
|
|
1427
|
+
else continue;
|
|
1384
1428
|
}
|
|
1385
1429
|
await sys.board.circuits.setCircuitStateAsync(circuit.circuit, cval);
|
|
1386
1430
|
//arr.push(sys.board.circuits.setCircuitStateAsync(circuit.circuit, cval));
|
|
@@ -1402,13 +1446,23 @@ export class NixieCircuitCommands extends CircuitCommands {
|
|
|
1402
1446
|
let arr = [];
|
|
1403
1447
|
for (let i = 0; i < circuits.length; i++) {
|
|
1404
1448
|
let circuit = circuits[i];
|
|
1405
|
-
|
|
1449
|
+
// RSG 4/3/24 - This function was executing and returing the results to the array; not pushing the fn to the array.
|
|
1450
|
+
//arr.push(sys.board.circuits.setCircuitStateAsync(circuit.circuit, val));
|
|
1451
|
+
arr.push(async () => { await sys.board.circuits.setCircuitStateAsync(circuit.circuit, val) });
|
|
1406
1452
|
}
|
|
1453
|
+
// return new Promise<ICircuitGroupState>(async (resolve, reject) => {
|
|
1454
|
+
// await Promise.all(arr).catch((err) => { reject(err) });
|
|
1455
|
+
// resolve(gstate);
|
|
1456
|
+
// });
|
|
1407
1457
|
return new Promise<ICircuitGroupState>(async (resolve, reject) => {
|
|
1408
|
-
|
|
1409
|
-
|
|
1458
|
+
try {
|
|
1459
|
+
Promise.all(arr.map(async func => await func()));
|
|
1460
|
+
resolve(gstate);
|
|
1461
|
+
} catch (err) {
|
|
1462
|
+
reject(err);
|
|
1463
|
+
};
|
|
1410
1464
|
});
|
|
1411
|
-
|
|
1465
|
+
};
|
|
1412
1466
|
}
|
|
1413
1467
|
export class NixieFeatureCommands extends FeatureCommands {
|
|
1414
1468
|
public async setFeatureAsync(obj: any): Promise<Feature> {
|
|
@@ -1484,7 +1538,7 @@ export class NixieFeatureCommands extends FeatureCommands {
|
|
|
1484
1538
|
if (!val){
|
|
1485
1539
|
if (fstate.manualPriorityActive) delayMgr.cancelManualPriorityDelay(fstate.id);
|
|
1486
1540
|
fstate.manualPriorityActive = false; // if the delay was previously cancelled, still need to turn this off
|
|
1487
|
-
}
|
|
1541
|
+
}
|
|
1488
1542
|
state.emitEquipmentChanges();
|
|
1489
1543
|
return fstate;
|
|
1490
1544
|
} catch (err) { return Promise.reject(new Error(`Error setting feature state ${err.message}`)); }
|
|
@@ -1572,7 +1626,7 @@ export class NixieFeatureCommands extends FeatureCommands {
|
|
|
1572
1626
|
let circuit: CircuitGroupCircuit = grp.circuits.getItemByIndex(j);
|
|
1573
1627
|
let cstate = state.circuits.getInterfaceById(circuit.circuit);
|
|
1574
1628
|
// RSG: desiredState for Nixie is 1=on, 2=off, 3=ignore
|
|
1575
|
-
if (circuit.desiredState === 1 || circuit.desiredState === 4) {
|
|
1629
|
+
if (circuit.desiredState === 1 || circuit.desiredState === 4) {
|
|
1576
1630
|
// The circuit should be on if the value is 1.
|
|
1577
1631
|
// If we are on 'ignore' we should still only treat the circuit as
|
|
1578
1632
|
// desiredstate = 1.
|
|
@@ -1583,12 +1637,15 @@ export class NixieFeatureCommands extends FeatureCommands {
|
|
|
1583
1637
|
}
|
|
1584
1638
|
}
|
|
1585
1639
|
let sgrp = state.circuitGroups.getItemById(grp.id);
|
|
1640
|
+
if (bIsOn && typeof sgrp.endTime === 'undefined') {
|
|
1641
|
+
sys.board.circuits.setEndTime(grp, sgrp, bIsOn, true);
|
|
1642
|
+
}
|
|
1586
1643
|
sgrp.isOn = bIsOn;
|
|
1587
|
-
|
|
1644
|
+
|
|
1588
1645
|
if (!sgrp.isOn && sgrp.manualPriorityActive){
|
|
1589
1646
|
delayMgr.cancelManualPriorityDelays();
|
|
1590
1647
|
sgrp.manualPriorityActive = false; // if the delay was previously cancelled, still need to turn this off
|
|
1591
|
-
}
|
|
1648
|
+
}
|
|
1592
1649
|
}
|
|
1593
1650
|
sys.board.valves.syncValveStates();
|
|
1594
1651
|
}
|
|
@@ -1610,9 +1667,9 @@ export class NixieFeatureCommands extends FeatureCommands {
|
|
|
1610
1667
|
if (!sgrp.isOn && sgrp.manualPriorityActive){
|
|
1611
1668
|
delayMgr.cancelManualPriorityDelay(grp.id);
|
|
1612
1669
|
sgrp.manualPriorityActive = false; // if the delay was previously cancelled, still need to turn this off
|
|
1613
|
-
}
|
|
1670
|
+
}
|
|
1614
1671
|
}
|
|
1615
|
-
|
|
1672
|
+
|
|
1616
1673
|
sys.board.valves.syncValveStates();
|
|
1617
1674
|
}
|
|
1618
1675
|
state.emitEquipmentChanges();
|
|
@@ -1644,8 +1701,8 @@ export class NixiePumpCommands extends PumpCommands {
|
|
|
1644
1701
|
// to bodies.
|
|
1645
1702
|
console.log(`Body: ${pump.body} Pump: ${pump.name} Pool: ${circuitIds.includes(6)} `);
|
|
1646
1703
|
if ((pump.body === 255 && (circuitIds.includes(6) || circuitIds.includes(1))) ||
|
|
1647
|
-
|
|
1648
|
-
|
|
1704
|
+
(pump.body === 0 && circuitIds.includes(6)) ||
|
|
1705
|
+
(pump.body === 101 && circuitIds.includes(1))) {
|
|
1649
1706
|
delayMgr.setPumpValveDelay(pstate);
|
|
1650
1707
|
}
|
|
1651
1708
|
break;
|
|
@@ -1817,14 +1874,14 @@ export class NixieHeaterCommands extends HeaterCommands {
|
|
|
1817
1874
|
if (gasHeaterInstalled) sys.board.valueMaps.heatSources.merge([[2, { name: 'heater', desc: 'Heater' }]]);
|
|
1818
1875
|
if (mastertempInstalled) sys.board.valueMaps.heatSources.merge([[11, { name: 'mtheater', desc: 'MasterTemp' }]]);
|
|
1819
1876
|
if (solarInstalled && (gasHeaterInstalled || heatPumpInstalled)) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar Only', hasCoolSetpoint: htypes.hasCoolSetpoint }], [4, { name: 'solarpref', desc: 'Solar Preferred', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
1820
|
-
else if (solarInstalled) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar',
|
|
1877
|
+
else if (solarInstalled) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
1821
1878
|
if (heatPumpInstalled && (gasHeaterInstalled || solarInstalled)) sys.board.valueMaps.heatSources.merge([[9, { name: 'heatpump', desc: 'Heatpump Only' }], [25, { name: 'heatpumppref', desc: 'Heat Pump Pref' }]]);
|
|
1822
1879
|
else if (heatPumpInstalled) sys.board.valueMaps.heatSources.merge([[9, { name: 'heatpump', desc: 'Heat Pump' }]]);
|
|
1823
1880
|
if (ultratempInstalled && (gasHeaterInstalled || heatPumpInstalled)) sys.board.valueMaps.heatSources.merge([[5, { name: 'ultratemp', desc: 'UltraTemp Only', hasCoolSetpoint: htypes.hasCoolSetpoint }], [6, { name: 'ultratemppref', desc: 'UltraTemp Pref', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
1824
1881
|
else if (ultratempInstalled) sys.board.valueMaps.heatSources.merge([[5, { name: 'ultratemp', desc: 'UltraTemp', hasCoolSetpoint: htypes.hasCoolSetpoint }]]);
|
|
1825
1882
|
sys.board.valueMaps.heatSources.merge([[0, { name: 'nochange', desc: 'No Change' }]]);
|
|
1826
1883
|
|
|
1827
|
-
|
|
1884
|
+
|
|
1828
1885
|
if (gasHeaterInstalled) sys.board.valueMaps.heatModes.merge([[2, { name: 'heater', desc: 'Heater' }]]);
|
|
1829
1886
|
if (mastertempInstalled) sys.board.valueMaps.heatModes.merge([[11, { name: 'mtheater', desc: 'MasterTemp' }]]);
|
|
1830
1887
|
if (solarInstalled && (gasHeaterInstalled || heatPumpInstalled || mastertempInstalled)) sys.board.valueMaps.heatModes.merge([[3, { name: 'solar', desc: 'Solar Only' }], [4, { name: 'solarpref', desc: 'Solar Preferred' }]]);
|
|
@@ -31,7 +31,7 @@ export class SunTouchBoard extends EasyTouchBoard {
|
|
|
31
31
|
constructor(system: PoolSystem) {
|
|
32
32
|
super(system); // graph chain to EasyTouchBoard constructor.
|
|
33
33
|
this.valueMaps.expansionBoards = new byteValueMap([
|
|
34
|
-
[41, { name: '
|
|
34
|
+
[41, { name: 'stshared', part: '520820', desc: 'Pool and Spa controller', bodies: 2, valves: 4, circuits: 5, single: false, shared: true, dual: false, features: 4, chlorinators: 1, chemControllers: 1 }],
|
|
35
35
|
[40, { name: 'stsingle', part: '520819', desc: 'Pool or Spa controller', bodies: 2, valves: 4, circuits: 5, single: true, shared: true, dual: false, features: 4, chlorinators: 1, chemControllers: 1 }]
|
|
36
36
|
]);
|
|
37
37
|
this._statusInterval = -1;
|
|
@@ -222,8 +222,10 @@ class SunTouchConfigQueue extends TouchConfigQueue {
|
|
|
222
222
|
// 196 - [0-2]
|
|
223
223
|
// 198 - [0-2]
|
|
224
224
|
// 199 - [0-2]
|
|
225
|
+
// 200 - Heat/Temperature Status
|
|
225
226
|
// 201 - [0-2]
|
|
226
227
|
// 202 - [0-2] - Custom Names
|
|
228
|
+
// 203 - Circuit Functions
|
|
227
229
|
// 204 - [0-2]
|
|
228
230
|
// 205 - [0-2]
|
|
229
231
|
// 206 - [0-2]
|
|
@@ -238,13 +240,16 @@ class SunTouchConfigQueue extends TouchConfigQueue {
|
|
|
238
240
|
// 218 - [0-2]
|
|
239
241
|
// 219 - [0-2]
|
|
240
242
|
// 220 - [0-2]
|
|
243
|
+
// 221 - Valve Assignments
|
|
241
244
|
// 223 - [0-2]
|
|
242
245
|
// 224 - [1-2]
|
|
243
|
-
//
|
|
246
|
+
// 225 - Spa side remote
|
|
247
|
+
// 226 - [0] - Solar/HeatPump config
|
|
244
248
|
// 228 - [0-2]
|
|
245
249
|
// 229 - [0-2]
|
|
246
250
|
// 230 - [0-2]
|
|
247
251
|
// 231 - [0-2]
|
|
252
|
+
// 232 - Settings (Amazed that there is none of this)
|
|
248
253
|
// 233 - [0-2]
|
|
249
254
|
// 234 - [0-2]
|
|
250
255
|
// 235 - [0-2]
|
|
@@ -264,6 +269,7 @@ class SunTouchConfigQueue extends TouchConfigQueue {
|
|
|
264
269
|
// 249 - [0-2]
|
|
265
270
|
// 250 - [0-2]
|
|
266
271
|
// 251 - [0-2]
|
|
272
|
+
// 253 - Software Version
|
|
267
273
|
|
|
268
274
|
this.queueItems(GetTouchConfigCategories.version); // 252
|
|
269
275
|
this.queueItems(GetTouchConfigCategories.dateTime, [0]); //197
|