nodejs-poolcontroller 7.3.0 → 7.6.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Changelog +23 -0
- package/README.md +5 -5
- package/app.ts +2 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +88 -0
- package/controller/Equipment.ts +246 -66
- package/controller/Errors.ts +24 -1
- package/controller/Lockouts.ts +423 -0
- package/controller/State.ts +314 -54
- package/controller/boards/EasyTouchBoard.ts +107 -59
- package/controller/boards/IntelliCenterBoard.ts +186 -125
- package/controller/boards/IntelliTouchBoard.ts +104 -30
- package/controller/boards/NixieBoard.ts +721 -159
- package/controller/boards/SystemBoard.ts +2370 -1108
- package/controller/comms/Comms.ts +85 -10
- package/controller/comms/messages/Messages.ts +10 -4
- package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
- package/controller/comms/messages/config/CoverMessage.ts +1 -0
- package/controller/comms/messages/config/EquipmentMessage.ts +4 -0
- package/controller/comms/messages/config/ExternalMessage.ts +44 -26
- package/controller/comms/messages/config/FeatureMessage.ts +8 -1
- package/controller/comms/messages/config/GeneralMessage.ts +8 -0
- package/controller/comms/messages/config/HeaterMessage.ts +15 -9
- package/controller/comms/messages/config/IntellichemMessage.ts +4 -1
- package/controller/comms/messages/config/OptionsMessage.ts +13 -1
- package/controller/comms/messages/config/PumpMessage.ts +4 -20
- package/controller/comms/messages/config/RemoteMessage.ts +4 -0
- package/controller/comms/messages/config/ScheduleMessage.ts +11 -0
- package/controller/comms/messages/config/SecurityMessage.ts +1 -0
- package/controller/comms/messages/config/ValveMessage.ts +13 -3
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +78 -24
- package/controller/comms/messages/status/HeaterStateMessage.ts +42 -9
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +37 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/bodies/Body.ts +4 -1
- package/controller/nixie/chemistry/ChemController.ts +80 -77
- package/controller/nixie/chemistry/Chlorinator.ts +9 -8
- package/controller/nixie/circuits/Circuit.ts +55 -6
- package/controller/nixie/heaters/Heater.ts +192 -32
- package/controller/nixie/pumps/Pump.ts +146 -84
- package/controller/nixie/schedules/Schedule.ts +3 -2
- package/controller/nixie/valves/Valve.ts +1 -1
- package/defaultConfig.json +32 -1
- package/issue_template.md +1 -1
- package/logger/DataLogger.ts +37 -22
- package/package.json +20 -18
- package/web/Server.ts +520 -29
- package/web/bindings/influxDB.json +96 -8
- package/web/bindings/mqtt.json +151 -40
- package/web/bindings/mqttAlt.json +114 -4
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +36 -19
- package/web/interfaces/mqttInterface.ts +14 -3
- package/web/services/config/Config.ts +171 -44
- package/web/services/state/State.ts +49 -5
- package/web/services/state/StateSocket.ts +18 -1
|
@@ -38,33 +38,39 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
38
38
|
this.equipmentIds.features.start = 129;
|
|
39
39
|
this.equipmentIds.circuitGroups.start = 193;
|
|
40
40
|
this.equipmentIds.virtualCircuits.start = 237;
|
|
41
|
+
this.valueMaps.panelModes = new byteValueMap([
|
|
42
|
+
[0, { val: 0, name: 'auto', desc: 'Auto' }],
|
|
43
|
+
[1, { val: 1, name: 'service', desc: 'Service' }],
|
|
44
|
+
[8, { val: 8, name: 'freeze', desc: 'Freeze' }],
|
|
45
|
+
[255, { name: 'error', desc: 'System Error' }]
|
|
46
|
+
]);
|
|
41
47
|
this.valueMaps.circuitFunctions = new byteValueMap([
|
|
42
48
|
[0, { name: 'generic', desc: 'Generic' }],
|
|
43
49
|
[1, { name: 'spillway', desc: 'Spillway' }],
|
|
44
|
-
[2, { name: 'mastercleaner', desc: 'Master Cleaner' }],
|
|
50
|
+
[2, { name: 'mastercleaner', desc: 'Master Cleaner', body: 1 }],
|
|
45
51
|
[3, { name: 'chemrelay', desc: 'Chem Relay' }],
|
|
46
52
|
[4, { name: 'light', desc: 'Light', isLight: true }],
|
|
47
|
-
[5, { name: 'intellibrite', desc: 'Intellibrite', isLight: true }],
|
|
48
|
-
[6, { name: 'globrite', desc: 'GloBrite', isLight: true }],
|
|
53
|
+
[5, { name: 'intellibrite', desc: 'Intellibrite', isLight: true, theme: 'intellibrite' }],
|
|
54
|
+
[6, { name: 'globrite', desc: 'GloBrite', isLight: true, themes: 'intellibrite' }],
|
|
49
55
|
[7, { name: 'globritewhite', desc: 'GloBrite White', isLight: true }],
|
|
50
|
-
[8, { name: 'magicstream', desc: 'Magicstream', isLight: true }],
|
|
56
|
+
[8, { name: 'magicstream', desc: 'Magicstream', isLight: true, theme: 'intellibrite' }],
|
|
51
57
|
[9, { name: 'dimmer', desc: 'Dimmer', isLight: true }],
|
|
52
|
-
[10, { name: 'colorcascade', desc: 'ColorCascade', isLight: true }],
|
|
53
|
-
[11, { name: 'mastercleaner2', desc: 'Master Cleaner 2' }],
|
|
54
|
-
[12, { name: 'pool', desc: 'Pool', hasHeatSource: true }],
|
|
55
|
-
[13, { name: 'spa', desc: 'Spa', hasHeatSource: true }]
|
|
58
|
+
[10, { name: 'colorcascade', desc: 'ColorCascade', isLight: true, theme: 'intellibrite' }],
|
|
59
|
+
[11, { name: 'mastercleaner2', desc: 'Master Cleaner 2', body: 2 }],
|
|
60
|
+
[12, { name: 'pool', desc: 'Pool', hasHeatSource: true, body: 1 }],
|
|
61
|
+
[13, { name: 'spa', desc: 'Spa', hasHeatSource: true, body: 2 }]
|
|
56
62
|
]);
|
|
57
63
|
this.valueMaps.pumpTypes = new byteValueMap([
|
|
58
64
|
[1, { name: 'ss', desc: 'Single Speed', maxCircuits: 0, hasAddress: false, hasBody:true }],
|
|
59
65
|
[2, { name: 'ds', desc: 'Two Speed', maxCircuits: 8, hasAddress: false, hasBody:true }],
|
|
60
66
|
[3, { name: 'vs', desc: 'Intelliflo VS', maxPrimingTime: 6, minSpeed: 450, maxSpeed: 3450, maxCircuits: 8, hasAddress: true }],
|
|
61
67
|
[4, { name: 'vsf', desc: 'Intelliflo VSF', minSpeed: 450, maxSpeed: 3450, minFlow: 15, maxFlow: 130, maxCircuits: 8, hasAddress: true }],
|
|
62
|
-
[5, { name: 'vf', desc: 'Intelliflo VF', minFlow: 15, maxFlow: 130, maxCircuits: 8, hasAddress: true }],
|
|
68
|
+
[5, { name: 'vf', desc: 'Intelliflo VF', maxPrimingTime: 6, minFlow: 15, maxFlow: 130, maxCircuits: 8, hasAddress: true }],
|
|
63
69
|
[100, {name: 'sf', desc: 'SuperFlo VS', hasAddress: false, maxCircuits: 8, maxRelays: 4, equipmentMaster: 1}]
|
|
64
70
|
]);
|
|
65
71
|
// RSG - same as systemBoard definition; can delete.
|
|
66
72
|
this.valueMaps.heatModes = new byteValueMap([
|
|
67
|
-
[
|
|
73
|
+
[1, { name: 'off', desc: 'Off' }],
|
|
68
74
|
[3, { name: 'heater', desc: 'Heater' }],
|
|
69
75
|
[5, { name: 'solar', desc: 'Solar Only' }],
|
|
70
76
|
[12, { name: 'solarpref', desc: 'Solar Preferred' }]
|
|
@@ -89,8 +95,8 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
89
95
|
[3, { name: 'heatpump', desc: 'Heat Pump', hasAddress: true }],
|
|
90
96
|
[4, { name: 'ultratemp', desc: 'UltraTemp', hasAddress: true, hasCoolSetpoint: true }],
|
|
91
97
|
[5, { name: 'hybrid', desc: 'Hybrid', hasAddress: true }],
|
|
92
|
-
[6, { name: '
|
|
93
|
-
[7, { name: '
|
|
98
|
+
[6, { name: 'mastertemp', desc: 'MasterTemp', hasAddress: true }],
|
|
99
|
+
[7, { name: 'maxetherm', desc: 'Max-E-Therm', hasAddress: true }],
|
|
94
100
|
]);
|
|
95
101
|
|
|
96
102
|
|
|
@@ -129,8 +135,8 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
129
135
|
[6, { name: 'i10x', part: '522997Z', desc: 'i10x Expansion Module', circuits: 10 }],
|
|
130
136
|
[7, { name: 'i10D', part: '523029Z', desc: 'i10D Personality Card', bodies: 2, valves: 2, circuits: 11, shared: false, dual: true, chlorinators: 1, chemControllers: 1 }], // We have witnessed this in the wild
|
|
131
137
|
[8, { name: 'Valve Exp', part: '522440', desc: 'Valve Expansion Module', valves: 6 }],
|
|
132
|
-
[9, { name: '
|
|
133
|
-
[10, { name: '
|
|
138
|
+
[9, { name: 'A/D Module', part: '522039', desc: 'A/D Cover Module', covers: 2 }], // Finally have a user with one of these
|
|
139
|
+
[10, { name: 'iChlor Mux', part: '522719', desc: 'iChlor MUX Card', chlorinators: 3 }], // This is a guess
|
|
134
140
|
[255, {name: 'i5x', part: '522033', desc: 'i5x Expansion Module', circuits: 5}] // This does not actually map to a known value at this point but we do know it will be > 6.
|
|
135
141
|
]);
|
|
136
142
|
|
|
@@ -167,18 +173,18 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
167
173
|
[2, { name: 'sunset', desc: 'Sunset' }]
|
|
168
174
|
]);
|
|
169
175
|
this.valueMaps.lightThemes = new byteValueMap([
|
|
170
|
-
[0, { name: 'white', desc: 'White', sequence: 11 }],
|
|
171
|
-
[1, { name: 'green', desc: 'Green', sequence: 9 }],
|
|
172
|
-
[2, { name: 'blue', desc: 'Blue', sequence: 8 }],
|
|
173
|
-
[3, { name: 'magenta', desc: 'Magenta', sequence: 12 }],
|
|
174
|
-
[4, { name: 'red', desc: 'Red', sequence: 10 }],
|
|
175
|
-
[5, { name: 'sam', desc: 'SAm Mode', sequence: 1 }],
|
|
176
|
-
[6, { name: 'party', desc: 'Party', sequence: 2 }],
|
|
177
|
-
[7, { name: 'romance', desc: 'Romance', sequence: 3 }],
|
|
178
|
-
[8, { name: 'caribbean', desc: 'Caribbean', sequence: 4 }],
|
|
179
|
-
[9, { name: 'american', desc: 'American', sequence: 5 }],
|
|
180
|
-
[10, { name: 'sunset', desc: 'Sunset', sequence: 6 }],
|
|
181
|
-
[11, { name: 'royal', desc: 'Royal', sequence: 7 }],
|
|
176
|
+
[0, { name: 'white', desc: 'White', sequence: 11, types:['intellibrite', 'magicstream'] }],
|
|
177
|
+
[1, { name: 'green', desc: 'Green', sequence: 9, types: ['intellibrite', 'magicstream'] }],
|
|
178
|
+
[2, { name: 'blue', desc: 'Blue', sequence: 8, types: ['intellibrite', 'magicstream'] }],
|
|
179
|
+
[3, { name: 'magenta', desc: 'Magenta', sequence: 12, types: ['intellibrite', 'magicstream'] }],
|
|
180
|
+
[4, { name: 'red', desc: 'Red', sequence: 10, types: ['intellibrite', 'magicstream'] }],
|
|
181
|
+
[5, { name: 'sam', desc: 'SAm Mode', sequence: 1, types: ['intellibrite', 'magicstream'] }],
|
|
182
|
+
[6, { name: 'party', desc: 'Party', sequence: 2, types: ['intellibrite', 'magicstream'] }],
|
|
183
|
+
[7, { name: 'romance', desc: 'Romance', sequence: 3, types: ['intellibrite', 'magicstream'] }],
|
|
184
|
+
[8, { name: 'caribbean', desc: 'Caribbean', sequence: 4, types: ['intellibrite', 'magicstream'] }],
|
|
185
|
+
[9, { name: 'american', desc: 'American', sequence: 5, types: ['intellibrite', 'magicstream'] }],
|
|
186
|
+
[10, { name: 'sunset', desc: 'Sunset', sequence: 6, types: ['intellibrite', 'magicstream'] }],
|
|
187
|
+
[11, { name: 'royal', desc: 'Royal', sequence: 7, types: ['intellibrite', 'magicstream'] }],
|
|
182
188
|
[255, { name: 'none', desc: 'None' }]
|
|
183
189
|
]);
|
|
184
190
|
this.valueMaps.lightColors = new byteValueMap([
|
|
@@ -207,8 +213,9 @@ export class IntelliCenterBoard extends SystemBoard {
|
|
|
207
213
|
[1, { name: 'heater', desc: 'Heater' }],
|
|
208
214
|
[2, { name: 'solar', desc: 'Solar' }],
|
|
209
215
|
[3, { name: 'cooling', desc: 'Cooling' }],
|
|
216
|
+
[6, { name: 'mtheat', desc: 'Heater' }],
|
|
210
217
|
[4, { name: 'hpheat', desc: 'Heating' }],
|
|
211
|
-
[8, { name: 'hpcool', desc: 'Cooling'}]
|
|
218
|
+
[8, { name: 'hpcool', desc: 'Cooling' }]
|
|
212
219
|
]);
|
|
213
220
|
this.valueMaps.scheduleTypes = new byteValueMap([
|
|
214
221
|
[0, { name: 'runonce', desc: 'Run Once', startDate: true, startTime: true, endTime: true, days: false, heatSource: true, heatSetpoint: true }],
|
|
@@ -572,7 +579,7 @@ class IntelliCenterConfigRequest extends ConfigRequest {
|
|
|
572
579
|
if (typeof items !== 'undefined') this.items.push(...items);
|
|
573
580
|
this.oncomplete = oncomplete;
|
|
574
581
|
}
|
|
575
|
-
|
|
582
|
+
declare category: ConfigCategories;
|
|
576
583
|
}
|
|
577
584
|
class IntelliCenterConfigQueue extends ConfigQueue {
|
|
578
585
|
public _processing: boolean = false;
|
|
@@ -1285,7 +1292,7 @@ class IntelliCenterSystemCommands extends SystemCommands {
|
|
|
1285
1292
|
let out = Outbound.create({
|
|
1286
1293
|
action: 168,
|
|
1287
1294
|
retries: 5,
|
|
1288
|
-
payload: [12, 0,
|
|
1295
|
+
payload: [12, 0, 13, parseInt(obj.timeZone, 10)],
|
|
1289
1296
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
1290
1297
|
onComplete: (err, msg) => {
|
|
1291
1298
|
if (err) reject(err);
|
|
@@ -1388,7 +1395,20 @@ class IntelliCenterSystemCommands extends SystemCommands {
|
|
|
1388
1395
|
}
|
|
1389
1396
|
}
|
|
1390
1397
|
class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
1391
|
-
|
|
1398
|
+
declare board: IntelliCenterBoard;
|
|
1399
|
+
// Need to override this as IntelliCenter manages all the egg timers for all circuit types.
|
|
1400
|
+
public async checkEggTimerExpirationAsync() {
|
|
1401
|
+
try {
|
|
1402
|
+
for (let i = 0; i < sys.circuits.length; i++) {
|
|
1403
|
+
let c = sys.circuits.getItemByIndex(i);
|
|
1404
|
+
let cstate = state.circuits.getItemByIndex(i);
|
|
1405
|
+
if (!cstate.isActive || !cstate.isOn) continue;
|
|
1406
|
+
if (c.master === 1) {
|
|
1407
|
+
await ncp.circuits.checkCircuitEggTimerExpirationAsync(cstate);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
} catch (err) { logger.error(`checkEggTimerExpiration: Error synchronizing circuit relays ${err.message}`); }
|
|
1411
|
+
}
|
|
1392
1412
|
public async setCircuitAsync(data: any): Promise<ICircuit> {
|
|
1393
1413
|
let id = parseInt(data.id, 10);
|
|
1394
1414
|
let circuit = sys.circuits.getItemById(id, false);
|
|
@@ -1405,7 +1425,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
1405
1425
|
let eggHrs = Math.floor(eggTimer / 60);
|
|
1406
1426
|
let eggMins = eggTimer - (eggHrs * 60);
|
|
1407
1427
|
let type = typeof data.type !== 'undefined' ? parseInt(data.type, 10) : circuit.type;
|
|
1408
|
-
let theme = typeof data.lightingTheme !== 'undefined' ? data.
|
|
1428
|
+
let theme = typeof data.lightingTheme !== 'undefined' ? data.lightingTheme : circuit.lightingTheme;
|
|
1409
1429
|
if (circuit.type === 9) theme = typeof data.level !== 'undefined' ? data.level : circuit.level;
|
|
1410
1430
|
if (typeof theme === 'undefined') theme = 0;
|
|
1411
1431
|
let out = Outbound.create({
|
|
@@ -1419,14 +1439,24 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
1419
1439
|
onComplete: (err, msg) => {
|
|
1420
1440
|
if (err) reject(err);
|
|
1421
1441
|
else {
|
|
1442
|
+
let scircuit = state.circuits.getItemById(circuit.id, true);
|
|
1422
1443
|
circuit.eggTimer = eggTimer;
|
|
1423
1444
|
circuit.dontStop = data.dontStop;
|
|
1424
1445
|
circuit.freeze = (typeof data.freeze !== 'undefined' ? utils.makeBool(data.freeze) : circuit.freeze);
|
|
1425
1446
|
circuit.showInFeatures = (typeof data.showInFeatures !== 'undefined' ? utils.makeBool(data.showInFeatures) : circuit.showInFeatures);
|
|
1426
|
-
if (type === 9) circuit.level = theme;
|
|
1427
|
-
else
|
|
1428
|
-
|
|
1429
|
-
|
|
1447
|
+
if (type === 9) scircuit.level = circuit.level = theme;
|
|
1448
|
+
else {
|
|
1449
|
+
let t = sys.board.valueMaps.circuitFunctions.transform(type);
|
|
1450
|
+
if (t.isLight == true) scircuit.lightingTheme = circuit.lightingTheme = theme;
|
|
1451
|
+
else {
|
|
1452
|
+
scircuit.lightingTheme = undefined;
|
|
1453
|
+
circuit.lightingTheme = 0;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
scircuit.name = circuit.name = typeof data.name !== 'undefined' ? data.name.toString().substring(0, 16) : circuit.name;
|
|
1457
|
+
scircuit.type = circuit.type = type;
|
|
1458
|
+
scircuit.isActive = circuit.isActive = true;
|
|
1459
|
+
circuit.master = 0;
|
|
1430
1460
|
resolve(circuit);
|
|
1431
1461
|
}
|
|
1432
1462
|
}
|
|
@@ -1972,17 +2002,18 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
1972
2002
|
}
|
|
1973
2003
|
return Promise.resolve(sgroup);
|
|
1974
2004
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
}
|
|
2005
|
+
// 12-01-21 RKS: This has been deprecated. This allows for multiple vendor light themes driven by the metadata on the valuemaps.
|
|
2006
|
+
//public getLightThemes(type: number): any[] {
|
|
2007
|
+
// switch (type) {
|
|
2008
|
+
// case 5: // Intellibrite
|
|
2009
|
+
// case 6: // Globrite
|
|
2010
|
+
// case 8: // Magicstream
|
|
2011
|
+
// case 10: // ColorCascade
|
|
2012
|
+
// return sys.board.valueMaps.lightThemes.toArray();
|
|
2013
|
+
// default:
|
|
2014
|
+
// return [];
|
|
2015
|
+
// }
|
|
2016
|
+
//}
|
|
1986
2017
|
private async verifyVersionAsync(): Promise<boolean> {
|
|
1987
2018
|
return new Promise<boolean>((resolve, reject) => {
|
|
1988
2019
|
let out = Outbound.create({
|
|
@@ -2042,7 +2073,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2042
2073
|
conn.queueSendMessage(out);
|
|
2043
2074
|
});
|
|
2044
2075
|
}
|
|
2045
|
-
public async setCircuitStateAsync(id: number, val: boolean): Promise<ICircuitState> {
|
|
2076
|
+
public async setCircuitStateAsync(id: number, val: boolean, ignoreDelays?: boolean): Promise<ICircuitState> {
|
|
2046
2077
|
let c = sys.circuits.getInterfaceById(id);
|
|
2047
2078
|
if (c.master !== 0) return await super.setCircuitStateAsync(id, val);
|
|
2048
2079
|
// As of 1.047 there is a sequence to this.
|
|
@@ -2055,6 +2086,14 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2055
2086
|
// NOT SURE IF COINCIDENTAL: The ICP seems to respond immediately after action 2.
|
|
2056
2087
|
// 7. ICP Sends 168[15,0,... new options, 0,0,0,0]
|
|
2057
2088
|
// 8. OCP responds ACK(168)
|
|
2089
|
+
// i10D turn on pool
|
|
2090
|
+
// OCP
|
|
2091
|
+
// Schedule on
|
|
2092
|
+
// [255, 0, 255][165, 1, 15, 16, 168, 36][15, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 1][5, 226]
|
|
2093
|
+
// No schedules
|
|
2094
|
+
// [255, 0, 255][165, 1, 15, 16, 168, 36][15, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 1, 0][5, 195]
|
|
2095
|
+
// njsPC
|
|
2096
|
+
// [255, 0, 255][165, 1, 15, 33, 168, 36][15, 0, 0, 33, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0][5, 216]
|
|
2058
2097
|
|
|
2059
2098
|
// The previous sequence is just additional noise on the bus. There is no need for it. We just
|
|
2060
2099
|
// need to send the set circuit message. It will reliably work 100% of the time but the ICP
|
|
@@ -2064,6 +2103,9 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2064
2103
|
//if (b) b = await this.getConfigAsync([15, 0]);
|
|
2065
2104
|
return new Promise<ICircuitState>((resolve, reject) => {
|
|
2066
2105
|
let out = this.createCircuitStateMessage(id, val);
|
|
2106
|
+
//if (sys.equipment.dual && id === 6) out.setPayloadByte(35, 1);
|
|
2107
|
+
out.setPayloadByte(34, 1);
|
|
2108
|
+
out.source = 16;
|
|
2067
2109
|
out.onComplete = async (err, msg: Inbound) => {
|
|
2068
2110
|
if (err) reject(err);
|
|
2069
2111
|
else {
|
|
@@ -2297,7 +2339,19 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2297
2339
|
let ndx = Math.floor(ordinal / 8);
|
|
2298
2340
|
let byte = out.payload[ndx + 15];
|
|
2299
2341
|
let bit = ordinal - (ndx * 8);
|
|
2300
|
-
|
|
2342
|
+
// Lets determine if this schedule should be on.
|
|
2343
|
+
if (sched.circuit === id) {
|
|
2344
|
+
if (isOn) {
|
|
2345
|
+
let dt = state.time.toDate();
|
|
2346
|
+
let dow = dt.getDay();
|
|
2347
|
+
// Convert the dow to the bit value.
|
|
2348
|
+
let sd = sys.board.valueMaps.scheduleDays.toArray().find(elem => elem.dow === dow);
|
|
2349
|
+
let dayVal = sd.bitVal || sd.val; // The bitval allows mask overrides.
|
|
2350
|
+
let ts = dt.getHours() * 60 + dt.getMinutes();
|
|
2351
|
+
if ((sched.scheduleDays & dayVal) > 0 && ts >= sched.startTime && ts <= sched.endTime) byte = byte | (1 << bit);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
else if (sched.isOn) byte = byte | (1 << bit);
|
|
2301
2355
|
out.payload[ndx + 15] = byte;
|
|
2302
2356
|
}
|
|
2303
2357
|
return out;
|
|
@@ -2340,7 +2394,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2340
2394
|
}
|
|
2341
2395
|
}
|
|
2342
2396
|
class IntelliCenterFeatureCommands extends FeatureCommands {
|
|
2343
|
-
|
|
2397
|
+
declare board: IntelliCenterBoard;
|
|
2344
2398
|
public async setFeatureStateAsync(id, val): Promise<ICircuitState> { return sys.board.circuits.setCircuitStateAsync(id, val); }
|
|
2345
2399
|
public async toggleFeatureStateAsync(id): Promise<ICircuitState> { return sys.board.circuits.toggleCircuitStateAsync(id); }
|
|
2346
2400
|
public syncGroupStates() { } // Do nothing and let IntelliCenter do it.
|
|
@@ -2427,12 +2481,10 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2427
2481
|
public async setChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
2428
2482
|
let id = parseInt(obj.id, 10);
|
|
2429
2483
|
let isAdd = false;
|
|
2430
|
-
let isVirtual = false;
|
|
2431
|
-
if (id <= 0 || isNaN(id)) id = 1;
|
|
2432
2484
|
let chlor = sys.chlorinators.getItemById(id);
|
|
2433
|
-
if (id
|
|
2485
|
+
if (id <= 0 || isNaN(id)) {
|
|
2434
2486
|
isAdd = true;
|
|
2435
|
-
chlor.master = utils.makeBool(obj.
|
|
2487
|
+
chlor.master = utils.makeBool(obj.master) ? 1 : 0;
|
|
2436
2488
|
// Calculate an id for the chlorinator. The messed up part is that if a chlorinator is not attached to the OCP, its address
|
|
2437
2489
|
// cannot be set by the MUX. This will have to wait.
|
|
2438
2490
|
id = 1;
|
|
@@ -2441,14 +2493,20 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2441
2493
|
//let chlor = extend(true, {}, sys.chlorinators.getItemById(id).get(), obj);
|
|
2442
2494
|
// If this is a virtual chlorinator then go to the base class and handle it from there.
|
|
2443
2495
|
if (chlor.master === 1) return super.setChlorAsync(obj);
|
|
2496
|
+
if (typeof chlor.master === 'undefined') chlor.master = 0;
|
|
2444
2497
|
let name = obj.name || chlor.name || 'IntelliChlor' + id;
|
|
2445
|
-
let poolSetpoint = parseInt(obj.poolSetpoint, 10);
|
|
2446
|
-
let spaSetpoint = parseInt(obj.spaSetpoint, 10);
|
|
2447
2498
|
let superChlorHours = parseInt(obj.superChlorHours, 10);
|
|
2448
2499
|
if (typeof obj.superChlorinate !== 'undefined') obj.superChlor = utils.makeBool(obj.superChlorinate);
|
|
2449
2500
|
let superChlorinate = typeof obj.superChlor === 'undefined' ? undefined : utils.makeBool(obj.superChlor);
|
|
2450
|
-
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
2451
2501
|
let isDosing = typeof obj.isDosing !== 'undefined' ? utils.makeBool(obj.isDosing) : chlor.isDosing;
|
|
2502
|
+
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
2503
|
+
// This should never never never modify the setpoints based upon the disabled or isDosing flags.
|
|
2504
|
+
//let poolSetpoint = isDosing ? 100 : disabled ? 0 : parseInt(obj.poolSetpoint, 10);
|
|
2505
|
+
//let spaSetpoint = isDosing ? 100 : disabled ? 0 : parseInt(obj.spaSetpoint, 10);
|
|
2506
|
+
let poolSetpoint = typeof obj.poolSetpoint !== 'undefined' ? parseInt(obj.poolSetpoint, 10) : chlor.poolSetpoint;
|
|
2507
|
+
let spaSetpoint = typeof obj.spaSetpoint !== 'undefined' ? parseInt(obj.spaSetpoint, 10) : chlor.spaSetpoint;
|
|
2508
|
+
if (poolSetpoint === 0) console.log(obj);
|
|
2509
|
+
|
|
2452
2510
|
let model = typeof obj.model !== 'undefined' ? obj.model : chlor.model;
|
|
2453
2511
|
let chlorType = typeof obj.type !== 'undefined' ? sys.board.valueMaps.chlorinatorType.encode(obj.type) : chlor.type || 0;
|
|
2454
2512
|
if (isAdd) {
|
|
@@ -2466,7 +2524,7 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2466
2524
|
if (typeof obj.disabled !== 'undefined') chlor.disabled = utils.makeBool(obj.disabled);
|
|
2467
2525
|
if (typeof chlor.body === 'undefined') chlor.body = obj.body || 32;
|
|
2468
2526
|
// Verify the data.
|
|
2469
|
-
let body = sys.board.bodies.mapBodyAssociation(chlor.body);
|
|
2527
|
+
let body = sys.board.bodies.mapBodyAssociation(typeof obj.body === 'undefined' ? chlor.body || 0 : obj.body);
|
|
2470
2528
|
if (typeof body === 'undefined') return Promise.reject(new InvalidEquipmentDataError(`Chlorinator body association is not valid: ${chlor.body}`, 'chlorinator', chlor.body));
|
|
2471
2529
|
if (poolSetpoint > 100 || poolSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator poolSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.poolSetpoint));
|
|
2472
2530
|
if (spaSetpoint > 100 || spaSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator spaSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.spaSetpoint));
|
|
@@ -2474,7 +2532,10 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2474
2532
|
return new Promise<ChlorinatorState>((resolve, reject) => {
|
|
2475
2533
|
let out = Outbound.create({
|
|
2476
2534
|
action: 168,
|
|
2477
|
-
payload: [7, 0, id - 1, body.val, 1,
|
|
2535
|
+
payload: [7, 0, id - 1, body.val, 1,
|
|
2536
|
+
disabled ? 0 : isDosing ? 100 : poolSetpoint,
|
|
2537
|
+
disabled ? 0 : isDosing ? 100 : spaSetpoint,
|
|
2538
|
+
superChlorinate ? 1 : 0, superChlorHours, 0, 1],
|
|
2478
2539
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
2479
2540
|
retries: 5,
|
|
2480
2541
|
onComplete: (err, msg) => {
|
|
@@ -2482,6 +2543,7 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2482
2543
|
else {
|
|
2483
2544
|
let schlor = state.chlorinators.getItemById(id, true);
|
|
2484
2545
|
let cchlor = sys.chlorinators.getItemById(id, true);
|
|
2546
|
+
schlor.body = chlor.body = body.val;
|
|
2485
2547
|
chlor.disabled = disabled;
|
|
2486
2548
|
chlor.model = model;
|
|
2487
2549
|
schlor.type = chlor.type = chlorType;
|
|
@@ -2502,21 +2564,22 @@ class IntelliCenterChlorinatorCommands extends ChlorinatorCommands {
|
|
|
2502
2564
|
}
|
|
2503
2565
|
public async deleteChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
2504
2566
|
let id = parseInt(obj.id, 10);
|
|
2505
|
-
if (isNaN(id)) obj.id
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
let
|
|
2567
|
+
if (isNaN(id)) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator id is not valid: ${obj.id}`, 'chlorinator', obj.id));
|
|
2568
|
+
let chlor = sys.chlorinators.getItemById(id);
|
|
2569
|
+
if (chlor.master === 1) return await super.deleteChlorAsync(obj);
|
|
2570
|
+
let schlor = state.chlorinators.getItemById(id);
|
|
2509
2571
|
// Verify the data.
|
|
2510
2572
|
return new Promise<ChlorinatorState>((resolve, reject) => {
|
|
2511
2573
|
let out = Outbound.create({
|
|
2512
2574
|
action: 168,
|
|
2513
|
-
payload: [7, 0, id - 1,
|
|
2575
|
+
payload: [7, 0, id - 1, schlor.body || 0, 0, schlor.poolSetpoint || 0, schlor.spaSetpoint || 0, 0, schlor.superChlorHours || 0, 0, 0],
|
|
2514
2576
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
2515
2577
|
retries: 5,
|
|
2516
2578
|
onComplete: (err, msg) => {
|
|
2517
2579
|
if (err) reject(err);
|
|
2518
2580
|
else {
|
|
2519
|
-
|
|
2581
|
+
ncp.chlorinators.deleteChlorinatorAsync(id).then(()=>{});
|
|
2582
|
+
schlor = state.chlorinators.getItemById(id, true);
|
|
2520
2583
|
state.chlorinators.removeItemById(id);
|
|
2521
2584
|
sys.chlorinators.removeItemById(id);
|
|
2522
2585
|
resolve(schlor);
|
|
@@ -2605,7 +2668,7 @@ class IntelliCenterPumpCommands extends PumpCommands {
|
|
|
2605
2668
|
let id = (typeof data.id === 'undefined' || data.id <= 0) ? sys.pumps.getNextEquipmentId(sys.board.equipmentIds.pumps) : parseInt(data.id, 10);
|
|
2606
2669
|
if (isNaN(id)) return Promise.reject(new Error(`Invalid pump id: ${data.id}`));
|
|
2607
2670
|
let pump = sys.pumps.getItemById(id, false);
|
|
2608
|
-
if (data.master > 0 || pump.master > 0
|
|
2671
|
+
if (data.master > 0 || pump.master > 0) return await super.setPumpAsync(data);
|
|
2609
2672
|
|
|
2610
2673
|
// 0 6 10 11 12 15
|
|
2611
2674
|
//[255, 0, 255][165, 63, 15, 16, 168, 34][4, 0, 0, 3, 0, 96, 194, 1, 122, 13, 15, 130, 1, 196, 9, 128, 2, 255, 5, 0, 251, 128, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0][11, 218]
|
|
@@ -2959,11 +3022,22 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2959
3022
|
public async setHeatModeAsync(body: Body, mode: number): Promise<BodyTempState> {
|
|
2960
3023
|
return new Promise<BodyTempState>((resolve, reject) => {
|
|
2961
3024
|
const self = this;
|
|
2962
|
-
let byte2 =
|
|
2963
|
-
let
|
|
2964
|
-
let
|
|
2965
|
-
|
|
2966
|
-
let
|
|
3025
|
+
let byte2 = 22;
|
|
3026
|
+
let body1 = sys.bodies.getItemById(1);
|
|
3027
|
+
let body2 = sys.bodies.getItemById(2);
|
|
3028
|
+
|
|
3029
|
+
let heat1 = body1.heatSetpoint || 78;
|
|
3030
|
+
let cool1 = body1.coolSetpoint || 100;
|
|
3031
|
+
let heat2 = body2.heatSetpoint || 78;
|
|
3032
|
+
let cool2 = body2.coolSetpoint || 103;
|
|
3033
|
+
|
|
3034
|
+
let mode1 = body1.heatMode || 1;
|
|
3035
|
+
let mode2 = body2.heatMode || 1;
|
|
3036
|
+
let bitopts = 0;
|
|
3037
|
+
if (sys.general.options.clockSource) bitopts += 32;
|
|
3038
|
+
if (sys.general.options.clockMode === 24) bitopts += 64;
|
|
3039
|
+
if (sys.general.options.adjustDST) bitopts += 128;
|
|
3040
|
+
|
|
2967
3041
|
switch (body.id) {
|
|
2968
3042
|
case 1:
|
|
2969
3043
|
byte2 = 22;
|
|
@@ -2973,19 +3047,12 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2973
3047
|
byte2 = 23;
|
|
2974
3048
|
mode2 = mode;
|
|
2975
3049
|
break;
|
|
2976
|
-
case 3:
|
|
2977
|
-
byte2 = 24;
|
|
2978
|
-
mode3 = mode;
|
|
2979
|
-
break;
|
|
2980
|
-
case 4:
|
|
2981
|
-
byte2 = 25;
|
|
2982
|
-
mode4 = mode;
|
|
2983
|
-
break;
|
|
2984
3050
|
}
|
|
2985
3051
|
let out = Outbound.create({
|
|
2986
3052
|
action: 168,
|
|
2987
|
-
payload: [0, 0, byte2, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0,
|
|
2988
|
-
,
|
|
3053
|
+
payload: [0, 0, byte2, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, bitopts, 89, 27, 110, 3, 0, 0,
|
|
3054
|
+
heat1, cool1, heat2, cool2, mode1, mode2, 0, 0, 15,
|
|
3055
|
+
sys.general.options.pumpDelay ? 1 : 0, sys.general.options.cooldownDelay ? 1 : 0, 0, 100, 0, 0, 0, 0, sys.general.options.manualPriority ? 1 : 0, sys.general.options.manualHeat ? 1 : 0, 0],
|
|
2989
3056
|
retries: 5,
|
|
2990
3057
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
2991
3058
|
onComplete: (err, msg) => {
|
|
@@ -3006,31 +3073,25 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3006
3073
|
let byte2 = 18;
|
|
3007
3074
|
let body1 = sys.bodies.getItemById(1);
|
|
3008
3075
|
let body2 = sys.bodies.getItemById(2);
|
|
3009
|
-
let body3 = sys.bodies.getItemById(3);
|
|
3010
|
-
let body4 = sys.bodies.getItemById(4);
|
|
3011
3076
|
|
|
3012
|
-
let
|
|
3013
|
-
let
|
|
3014
|
-
let
|
|
3015
|
-
let
|
|
3077
|
+
let heat1 = body1.heatSetpoint || 78;
|
|
3078
|
+
let cool1 = body1.coolSetpoint || 100;
|
|
3079
|
+
let heat2 = body2.heatSetpoint || 78;
|
|
3080
|
+
let cool2 = body2.coolSetpoint || 103;
|
|
3016
3081
|
switch (body.id) {
|
|
3017
3082
|
case 1:
|
|
3018
3083
|
byte2 = 18;
|
|
3019
|
-
|
|
3084
|
+
heat1 = setPoint;
|
|
3020
3085
|
break;
|
|
3021
3086
|
case 2:
|
|
3022
3087
|
byte2 = 20;
|
|
3023
|
-
|
|
3024
|
-
break;
|
|
3025
|
-
case 3:
|
|
3026
|
-
byte2 = 19;
|
|
3027
|
-
temp3 = setPoint;
|
|
3028
|
-
break;
|
|
3029
|
-
case 4:
|
|
3030
|
-
byte2 = 21;
|
|
3031
|
-
temp4 = setPoint;
|
|
3088
|
+
heat2 = setPoint;
|
|
3032
3089
|
break;
|
|
3033
3090
|
}
|
|
3091
|
+
let bitopts = 0;
|
|
3092
|
+
if (sys.general.options.clockSource) bitopts += 32;
|
|
3093
|
+
if (sys.general.options.clockMode === 24) bitopts += 64;
|
|
3094
|
+
if (sys.general.options.adjustDST) bitopts += 128;
|
|
3034
3095
|
// 6 15 17 18 21 22 24 25
|
|
3035
3096
|
//[255, 0, 255][165, 63, 15, 16, 168, 41][0, 0, 18, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 176, 89, 27, 110, 3, 0, 0, 89, 100, 98, 100, 0, 0, 0, 0, 15, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0][5, 243]
|
|
3036
3097
|
//[255, 0, 255][165, 63, 15, 16, 168, 41][0, 0, 18, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 235, 27, 167, 1, 0, 0, 89, 81, 98, 103, 5, 0, 0, 0, 15, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0][6, 48]
|
|
@@ -3038,8 +3099,8 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3038
3099
|
action: 168,
|
|
3039
3100
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
3040
3101
|
retries: 5,
|
|
3041
|
-
payload: [0, 0, byte2, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0,
|
|
3042
|
-
|
|
3102
|
+
payload: [0, 0, byte2, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, bitopts, 89, 27, 110, 3, 0, 0,
|
|
3103
|
+
heat1, cool1, heat2, cool2, body1.heatMode || 1, body2.heatMode || 1, 0, 0, 15,
|
|
3043
3104
|
sys.general.options.pumpDelay ? 1 : 0, sys.general.options.cooldownDelay ? 1 : 0, 0, 100, 0, 0, 0, 0, sys.general.options.manualPriority ? 1 : 0, sys.general.options.manualHeat ? 1 : 0, 0]
|
|
3044
3105
|
});
|
|
3045
3106
|
return new Promise<BodyTempState>((resolve, reject) => {
|
|
@@ -3055,23 +3116,14 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3055
3116
|
});
|
|
3056
3117
|
}
|
|
3057
3118
|
public async setCoolSetpointAsync(body: Body, setPoint: number): Promise<BodyTempState> {
|
|
3058
|
-
|
|
3059
|
-
let byte2 = 19;
|
|
3119
|
+
let byte2 = 18;
|
|
3060
3120
|
let body1 = sys.bodies.getItemById(1);
|
|
3061
3121
|
let body2 = sys.bodies.getItemById(2);
|
|
3062
|
-
let body3 = sys.bodies.getItemById(3);
|
|
3063
|
-
let body4 = sys.bodies.getItemById(3);
|
|
3064
3122
|
|
|
3065
|
-
let
|
|
3066
|
-
let cool1 =
|
|
3067
|
-
let
|
|
3068
|
-
let cool2 =
|
|
3069
|
-
|
|
3070
|
-
//Them
|
|
3071
|
-
//[165, 63, 15, 16, 168, 41][0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 59, 30, 5, 5, 0, 0, 90, 102, 98, 81, 3, 1, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][4, 129]
|
|
3072
|
-
//Us
|
|
3073
|
-
//[165, 63, 15, 33, 168, 40][0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 89, 27, 5, 5, 0, 0, 90, 103, 98, 81, 3, 1, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][5, 249]
|
|
3074
|
-
//[165, 63, 15, 33, 168, 40][0, 0, 19, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 176, 89, 27, 110, 3, 0, 0, 90, 103, 98, 81, 3, 1, 0, 0, 15, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0][5, 249]
|
|
3123
|
+
let heat1 = body1.heatSetpoint || 78;
|
|
3124
|
+
let cool1 = body1.coolSetpoint || 100;
|
|
3125
|
+
let heat2 = body2.heatSetpoint || 78;
|
|
3126
|
+
let cool2 = body2.coolSetpoint || 103;
|
|
3075
3127
|
switch (body.id) {
|
|
3076
3128
|
case 1:
|
|
3077
3129
|
byte2 = 19;
|
|
@@ -3082,6 +3134,10 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3082
3134
|
cool2 = setPoint;
|
|
3083
3135
|
break;
|
|
3084
3136
|
}
|
|
3137
|
+
let bitopts = 0;
|
|
3138
|
+
if (sys.general.options.clockSource) bitopts += 32;
|
|
3139
|
+
if (sys.general.options.clockMode === 24) bitopts += 64;
|
|
3140
|
+
if (sys.general.options.adjustDST) bitopts += 128;
|
|
3085
3141
|
// 6 15 17 18 21 22 24 25
|
|
3086
3142
|
//[255, 0, 255][165, 63, 15, 16, 168, 41][0, 0, 18, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 176, 89, 27, 110, 3, 0, 0, 89, 100, 98, 100, 0, 0, 0, 0, 15, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0][5, 243]
|
|
3087
3143
|
//[255, 0, 255][165, 63, 15, 16, 168, 41][0, 0, 18, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 235, 27, 167, 1, 0, 0, 89, 81, 98, 103, 5, 0, 0, 0, 15, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0][6, 48]
|
|
@@ -3089,8 +3145,8 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3089
3145
|
action: 168,
|
|
3090
3146
|
response: IntelliCenterBoard.getAckResponse(168),
|
|
3091
3147
|
retries: 5,
|
|
3092
|
-
payload: [0, 0, byte2, 1, 0, 0,
|
|
3093
|
-
|
|
3148
|
+
payload: [0, 0, byte2, 1, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, bitopts, 89, 27, 110, 3, 0, 0,
|
|
3149
|
+
heat1, cool1, heat2, cool2, body1.heatMode || 1, body2.heatMode || 1, 0, 0, 15,
|
|
3094
3150
|
sys.general.options.pumpDelay ? 1 : 0, sys.general.options.cooldownDelay ? 1 : 0, 0, 100, 0, 0, 0, 0, sys.general.options.manualPriority ? 1 : 0, sys.general.options.manualHeat ? 1 : 0, 0]
|
|
3095
3151
|
});
|
|
3096
3152
|
return new Promise<BodyTempState>((resolve, reject) => {
|
|
@@ -3098,7 +3154,7 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
3098
3154
|
if (err) reject(err);
|
|
3099
3155
|
else {
|
|
3100
3156
|
let bstate = state.temps.bodies.getItemById(body.id);
|
|
3101
|
-
body.
|
|
3157
|
+
body.heatSetpoint = bstate.heatSetpoint = setPoint;
|
|
3102
3158
|
resolve(bstate);
|
|
3103
3159
|
}
|
|
3104
3160
|
};
|
|
@@ -3184,6 +3240,8 @@ class IntelliCenterScheduleCommands extends ScheduleCommands {
|
|
|
3184
3240
|
out.retries = 5;
|
|
3185
3241
|
out.onComplete = (err, msg) => {
|
|
3186
3242
|
if (!err) {
|
|
3243
|
+
sched = sys.schedules.getItemById(id, true);
|
|
3244
|
+
ssched = state.schedules.getItemById(id, true);
|
|
3187
3245
|
sched.circuit = ssched.circuit = circuit;
|
|
3188
3246
|
sched.scheduleDays = ssched.scheduleDays = schedDays;
|
|
3189
3247
|
sched.scheduleType = ssched.scheduleType = schedType;
|
|
@@ -3280,14 +3338,14 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3280
3338
|
conn.queueSendMessage(out);
|
|
3281
3339
|
}
|
|
3282
3340
|
public async setHeaterAsync(obj: any): Promise<Heater> {
|
|
3283
|
-
if (
|
|
3341
|
+
if (obj.master === 1 || parseInt(obj.id, 10) > 255) return super.setHeaterAsync(obj);
|
|
3284
3342
|
return new Promise<Heater>((resolve, reject) => {
|
|
3285
3343
|
let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10);
|
|
3286
3344
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater'));
|
|
3287
3345
|
let heater: Heater;
|
|
3288
3346
|
if (id <= 0) {
|
|
3289
3347
|
// We are adding a heater. In this case all heaters are virtual.
|
|
3290
|
-
let vheaters = sys.heaters.filter(h => h.
|
|
3348
|
+
let vheaters = sys.heaters.filter(h => h.master === 1);
|
|
3291
3349
|
id = vheaters.length + 1;
|
|
3292
3350
|
}
|
|
3293
3351
|
heater = sys.heaters.getItemById(id, false);
|
|
@@ -3395,7 +3453,6 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3395
3453
|
heater.economyTime = economyTime;
|
|
3396
3454
|
heater.startTempDelta = startTempDelta;
|
|
3397
3455
|
heater.stopTempDelta = stopTempDelta;
|
|
3398
|
-
//hstate.isVirtual = heater.isVirtual = false;
|
|
3399
3456
|
heater.cooldownDelay = cooldownDelay;
|
|
3400
3457
|
sys.board.heaters.updateHeaterServices();
|
|
3401
3458
|
sys.board.heaters.syncHeaterStates();
|
|
@@ -3408,7 +3465,7 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3408
3465
|
});
|
|
3409
3466
|
}
|
|
3410
3467
|
public async deleteHeaterAsync(obj): Promise<Heater> {
|
|
3411
|
-
if (
|
|
3468
|
+
if (obj.master === 1 || parseInt(obj.id, 10) > 255) return await super.deleteHeaterAsync(obj);
|
|
3412
3469
|
return new Promise<Heater>((resolve, reject) => {
|
|
3413
3470
|
let id = parseInt(obj.id, 10);
|
|
3414
3471
|
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Cannot delete. Heater Id is not valid.', obj.id, 'Heater'));
|
|
@@ -3450,6 +3507,8 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3450
3507
|
let heatPumpInstalled = htypes.heatpump > 0;
|
|
3451
3508
|
let gasHeaterInstalled = htypes.gas > 0;
|
|
3452
3509
|
let ultratempInstalled = htypes.ultratemp > 0;
|
|
3510
|
+
let mastertempInstalled = htypes.mastertemp > 0;
|
|
3511
|
+
|
|
3453
3512
|
|
|
3454
3513
|
// RKS: 09-26-20 This is a hack to maintain backward compatability with fw versions 1.04 and below. Ultratemp is not
|
|
3455
3514
|
// supported on 1.04 and below.
|
|
@@ -3473,9 +3532,10 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3473
3532
|
// 3 = Solar Heater
|
|
3474
3533
|
// 4 = Solar Preferred
|
|
3475
3534
|
// 5 = Heat Pump
|
|
3476
|
-
|
|
3535
|
+
|
|
3477
3536
|
if (sys.heaters.length > 0) sys.board.valueMaps.heatSources = new byteValueMap([[1, { name: 'off', desc: 'Off' }]]);
|
|
3478
3537
|
if (gasHeaterInstalled) sys.board.valueMaps.heatSources.merge([[2, { name: 'heater', desc: 'Heater' }]]);
|
|
3538
|
+
if (mastertempInstalled) sys.board.valueMaps.heatSources.merge([[11, { name: 'mtheater', desc: 'MasterTemp' }]]);
|
|
3479
3539
|
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 }]]);
|
|
3480
3540
|
else if (solarInstalled) sys.board.valueMaps.heatSources.merge([[3, { name: 'solar', desc: 'Solar', hasCoolsetpoint: htypes.hasCoolSetpoint }]]);
|
|
3481
3541
|
if (heatPumpInstalled && (gasHeaterInstalled || solarInstalled)) sys.board.valueMaps.heatSources.merge([[9, { name: 'heatpump', desc: 'Heatpump Only' }], [25, { name: 'heatpumppref', desc: 'Heat Pump Pref' }]]);
|
|
@@ -3486,11 +3546,12 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3486
3546
|
|
|
3487
3547
|
sys.board.valueMaps.heatModes = new byteValueMap([[1, { name: 'off', desc: 'Off' }]]);
|
|
3488
3548
|
if (gasHeaterInstalled) sys.board.valueMaps.heatModes.merge([[2, { name: 'heater', desc: 'Heater' }]]);
|
|
3489
|
-
if (
|
|
3549
|
+
if (mastertempInstalled) sys.board.valueMaps.heatModes.merge([[11, { name: 'mtheater', desc: 'MasterTemp' }]]);
|
|
3550
|
+
if (solarInstalled && (gasHeaterInstalled || heatPumpInstalled || mastertempInstalled)) sys.board.valueMaps.heatModes.merge([[3, { name: 'solar', desc: 'Solar Only' }], [4, { name: 'solarpref', desc: 'Solar Preferred' }]]);
|
|
3490
3551
|
else if (solarInstalled) sys.board.valueMaps.heatModes.merge([[3, { name: 'solar', desc: 'Solar' }]]);
|
|
3491
|
-
if (ultratempInstalled && (gasHeaterInstalled || heatPumpInstalled)) sys.board.valueMaps.heatModes.merge([[5, { name: 'ultratemp', desc: 'UltraTemp Only'}], [6, { name: 'ultratemppref', desc: 'UltraTemp Pref' }]]);
|
|
3552
|
+
if (ultratempInstalled && (gasHeaterInstalled || heatPumpInstalled || mastertempInstalled)) sys.board.valueMaps.heatModes.merge([[5, { name: 'ultratemp', desc: 'UltraTemp Only' }], [6, { name: 'ultratemppref', desc: 'UltraTemp Pref' }]]);
|
|
3492
3553
|
else if (ultratempInstalled) sys.board.valueMaps.heatModes.merge([[5, { name: 'ultratemp', desc: 'UltraTemp' }]]);
|
|
3493
|
-
if (heatPumpInstalled && (gasHeaterInstalled || solarInstalled)) sys.board.valueMaps.heatModes.merge([[9, { name: 'heatpump', desc: 'Heatpump Only' }], [25, { name: 'heatpumppref', desc: 'Heat Pump Preferred' }]]);
|
|
3554
|
+
if (heatPumpInstalled && (gasHeaterInstalled || solarInstalled || mastertempInstalled)) sys.board.valueMaps.heatModes.merge([[9, { name: 'heatpump', desc: 'Heatpump Only' }], [25, { name: 'heatpumppref', desc: 'Heat Pump Preferred' }]]);
|
|
3494
3555
|
else if (heatPumpInstalled) sys.board.valueMaps.heatModes.merge([[9, { name: 'heatpump', desc: 'Heat Pump' }]]);
|
|
3495
3556
|
}
|
|
3496
3557
|
else {
|
|
@@ -3522,7 +3583,7 @@ class IntelliCenterHeaterCommands extends HeaterCommands {
|
|
|
3522
3583
|
}
|
|
3523
3584
|
class IntelliCenterValveCommands extends ValveCommands {
|
|
3524
3585
|
public async setValveAsync(obj?: any): Promise<Valve> {
|
|
3525
|
-
if (obj.
|
|
3586
|
+
if (obj.master === 1) return super.setValveAsync(obj);
|
|
3526
3587
|
let id = parseInt(obj.id, 10);
|
|
3527
3588
|
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Valve Id has not been defined', obj.id, 'Valve'));
|
|
3528
3589
|
let valve = sys.valves.getItemById(id);
|
|
@@ -3572,7 +3633,7 @@ export class IntelliCenterChemControllerCommands extends ChemControllerCommands
|
|
|
3572
3633
|
// Now lets do all our validation to the incoming chem controller data.
|
|
3573
3634
|
let name = typeof data.name !== 'undefined' ? data.name : chem.name || `IntelliChem - ${address - 143}`;
|
|
3574
3635
|
let type = sys.board.valueMaps.chemControllerTypes.transformByName('intellichem');
|
|
3575
|
-
// So now we are down to the nitty gritty setting the data for the REM
|
|
3636
|
+
// So now we are down to the nitty gritty setting the data for the REM Chem controller.
|
|
3576
3637
|
let calciumHardness = typeof data.calciumHardness !== 'undefined' ? parseInt(data.calciumHardness, 10) : chem.calciumHardness;
|
|
3577
3638
|
let cyanuricAcid = typeof data.cyanuricAcid !== 'undefined' ? parseInt(data.cyanuricAcid, 10) : chem.cyanuricAcid;
|
|
3578
3639
|
let alkalinity = typeof data.alkalinity !== 'undefined' ? parseInt(data.alkalinity, 10) : chem.alkalinity;
|