nodejs-poolcontroller 7.5.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.
- package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -0
- package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
- package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/Changelog +19 -0
- package/Dockerfile +3 -3
- package/README.md +13 -8
- package/app.ts +1 -1
- package/config/Config.ts +38 -2
- package/config/VersionCheck.ts +27 -12
- package/controller/Constants.ts +2 -1
- package/controller/Equipment.ts +193 -9
- package/controller/Errors.ts +10 -0
- package/controller/Lockouts.ts +503 -0
- package/controller/State.ts +269 -64
- package/controller/boards/AquaLinkBoard.ts +1000 -0
- package/controller/boards/BoardFactory.ts +4 -0
- package/controller/boards/EasyTouchBoard.ts +468 -144
- package/controller/boards/IntelliCenterBoard.ts +466 -307
- package/controller/boards/IntelliTouchBoard.ts +37 -5
- package/controller/boards/NixieBoard.ts +671 -141
- package/controller/boards/SystemBoard.ts +1397 -641
- package/controller/comms/Comms.ts +462 -362
- package/controller/comms/messages/Messages.ts +174 -30
- package/controller/comms/messages/config/ChlorinatorMessage.ts +6 -3
- package/controller/comms/messages/config/CircuitMessage.ts +1 -0
- package/controller/comms/messages/config/ExternalMessage.ts +10 -8
- package/controller/comms/messages/config/HeaterMessage.ts +141 -29
- package/controller/comms/messages/config/OptionsMessage.ts +9 -2
- package/controller/comms/messages/config/PumpMessage.ts +53 -35
- package/controller/comms/messages/config/ScheduleMessage.ts +33 -25
- package/controller/comms/messages/config/ValveMessage.ts +2 -2
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
- package/controller/comms/messages/status/EquipmentStateMessage.ts +59 -23
- package/controller/comms/messages/status/HeaterStateMessage.ts +57 -3
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +56 -8
- package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
- package/controller/nixie/Nixie.ts +1 -1
- package/controller/nixie/bodies/Body.ts +3 -0
- package/controller/nixie/chemistry/ChemController.ts +164 -51
- package/controller/nixie/chemistry/Chlorinator.ts +137 -88
- package/controller/nixie/circuits/Circuit.ts +51 -19
- package/controller/nixie/heaters/Heater.ts +241 -31
- package/controller/nixie/pumps/Pump.ts +488 -206
- package/controller/nixie/schedules/Schedule.ts +91 -35
- package/controller/nixie/valves/Valve.ts +1 -1
- package/defaultConfig.json +20 -0
- package/package.json +21 -21
- package/web/Server.ts +94 -49
- package/web/bindings/aqualinkD.json +505 -0
- package/web/bindings/influxDB.json +71 -1
- package/web/bindings/mqtt.json +98 -39
- package/web/bindings/mqttAlt.json +59 -1
- package/web/interfaces/baseInterface.ts +1 -0
- package/web/interfaces/httpInterface.ts +23 -2
- package/web/interfaces/influxInterface.ts +45 -10
- package/web/interfaces/mqttInterface.ts +114 -54
- package/web/services/config/Config.ts +55 -132
- package/web/services/state/State.ts +81 -4
- package/web/services/state/StateSocket.ts +4 -4
- package/web/services/utilities/Utilities.ts +8 -6
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
|
@@ -64,6 +64,7 @@ export class HeaterMessage {
|
|
|
64
64
|
case ControllerType.IntelliTouch:
|
|
65
65
|
case ControllerType.EasyTouch:
|
|
66
66
|
HeaterMessage.processIntelliTouch(msg);
|
|
67
|
+
break;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
private static processIntelliTouch(msg: Inbound) {
|
|
@@ -71,8 +72,22 @@ export class HeaterMessage {
|
|
|
71
72
|
// Gas heater setup in EquipmentStateMessage upon *Touch discovery
|
|
72
73
|
switch (msg.action) {
|
|
73
74
|
// 1 = gas heater, 2 = solar, 3 = heat pump
|
|
74
|
-
case 34:
|
|
75
|
-
case 162:
|
|
75
|
+
case 34: // Somebody requested the configuration
|
|
76
|
+
case 162: // Somebody set the configuration
|
|
77
|
+
// Release any heaters that are tied to Nixie that should not be.
|
|
78
|
+
for (let i = sys.heaters.length - 1; i >= 0; i--) {
|
|
79
|
+
let heater = sys.heaters.getItemByIndex(i);
|
|
80
|
+
if (heater.id <= 4 && heater.master === 1) {
|
|
81
|
+
// Return the heater control back to Touch
|
|
82
|
+
(async function () {
|
|
83
|
+
try {
|
|
84
|
+
await ncp.heaters.deleteHeaterAsync(heater.id);
|
|
85
|
+
logger.debug(`${heater.name} control returned to OCP.`);
|
|
86
|
+
}
|
|
87
|
+
catch (err) { logger.error(`Error with OCP reclaiming control over gas ${heater.name}: ${err}`) }
|
|
88
|
+
})();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
76
91
|
// byte 0
|
|
77
92
|
// 21 = solar or heat pump disabled
|
|
78
93
|
// 23 = solar or heat pump enabled
|
|
@@ -94,6 +109,121 @@ export class HeaterMessage {
|
|
|
94
109
|
// on/off (16) = solar as a heat pump
|
|
95
110
|
// bits 7,8 = stop temp delta
|
|
96
111
|
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
// Determine what type of heater should be in id number 1. If this is a hybrid heater
|
|
115
|
+
// we will be installing it in id 1 although it will perform dual purpose.
|
|
116
|
+
let hasHeater = (msg.extractPayloadByte(0) & 0x01) === 0x01 || true;
|
|
117
|
+
let hasSolar = (msg.extractPayloadByte(0) & 0x02) === 0x02;
|
|
118
|
+
let hasHeatpump = (msg.extractPayloadByte(1) & 0x20) === 0x20;
|
|
119
|
+
let hasHybrid = !hasHeatpump && (msg.extractPayloadByte(1) & 0x10) === 0x10;
|
|
120
|
+
|
|
121
|
+
// Ok so it appears that the heater ids are as follows.
|
|
122
|
+
// 1 = Gas Heater
|
|
123
|
+
// 2 = Solar
|
|
124
|
+
// 3 = UltraTemp (HEATPUMPCOM)
|
|
125
|
+
// 4 = UltraTemp ETi (Hybrid)
|
|
126
|
+
// If an UltraTemp ETi is installed, no other heaters can be installed so they should be removed. This is not
|
|
127
|
+
// an available option for IntelliTouch i10D so it does not apply to it.
|
|
128
|
+
if (!hasHeater) {
|
|
129
|
+
sys.heaters.removeItemById(1);
|
|
130
|
+
state.heaters.removeItemById(1);
|
|
131
|
+
sys.heaters.removeItemById(2);
|
|
132
|
+
state.heaters.removeItemById(2);
|
|
133
|
+
sys.heaters.removeItemById(3);
|
|
134
|
+
state.heaters.removeItemById(3);
|
|
135
|
+
sys.heaters.removeItemById(4);
|
|
136
|
+
state.heaters.removeItemById(4);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (hasHybrid) {
|
|
140
|
+
sys.heaters.removeItemById(1);
|
|
141
|
+
state.heaters.removeItemById(1);
|
|
142
|
+
sys.heaters.removeItemById(2);
|
|
143
|
+
state.heaters.removeItemById(2);
|
|
144
|
+
sys.heaters.removeItemById(3);
|
|
145
|
+
state.heaters.removeItemById(3);
|
|
146
|
+
let hybrid = sys.heaters.getItemById(4, true);
|
|
147
|
+
let shybrid = state.heaters.getItemById(4, true);
|
|
148
|
+
// [5, { name: 'hybrid', desc: 'Hybrid', hasAddress: true }],
|
|
149
|
+
shybrid.type = hybrid.type = 5;
|
|
150
|
+
hybrid.address = 112; // Touch only supports address 1.
|
|
151
|
+
hybrid.isActive = true;
|
|
152
|
+
hybrid.master = 0;
|
|
153
|
+
hybrid.body = sys.equipment.shared ? 32 : 0;
|
|
154
|
+
if (typeof hybrid.name === 'undefined') shybrid.name = hybrid.name = 'UltraTemp ETi';
|
|
155
|
+
// The following 2 values need to come from somewhere.
|
|
156
|
+
if (typeof hybrid.economyTime === 'undefined') hybrid.economyTime = 1;
|
|
157
|
+
if (typeof hybrid.maxBoostTemp === 'undefined') hybrid.maxBoostTemp = 5;
|
|
158
|
+
hasHeatpump = false; // You cannot have a heatpump and a hybrid heater.
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Hybrid heaters and gas heaters cannot co-exist but it appears you cannot disable the gas
|
|
162
|
+
// heater on the touch panels.
|
|
163
|
+
sys.heaters.removeItemById(4);
|
|
164
|
+
state.heaters.removeItemById(4);
|
|
165
|
+
let heater = sys.heaters.getItemById(1, true);
|
|
166
|
+
let hstate = state.heaters.getItemById(1, true);
|
|
167
|
+
heater.body = sys.equipment.shared ? 32 : 0;
|
|
168
|
+
// [1, { name: 'gas', desc: 'Gas Heater', hasAddress: false }],
|
|
169
|
+
heater.type = hstate.type = 1;
|
|
170
|
+
heater.isActive = true;
|
|
171
|
+
heater.master = 0;
|
|
172
|
+
if (typeof heater.name === 'undefined') heater.name = hstate.name = 'Gas Heater';
|
|
173
|
+
if (typeof heater.cooldownDelay === 'undefined') heater.cooldownDelay = 5;
|
|
174
|
+
}
|
|
175
|
+
// Check to see if a heatpump is installed. This will replace the solar heater so they cannot coexist.
|
|
176
|
+
if (hasHeatpump) {
|
|
177
|
+
// Remove the solar heater. This will be replaced with the heatpump.
|
|
178
|
+
sys.heaters.removeItemById(2);
|
|
179
|
+
state.heaters.removeItemById(2);
|
|
180
|
+
let heatpump = sys.heaters.getItemById(3, true);
|
|
181
|
+
let sheatpump = state.heaters.getItemById(3, true);
|
|
182
|
+
// [3, { name: 'heatpump', desc: 'Heat Pump', hasAddress: true, hasPreference: true }],
|
|
183
|
+
heatpump.type = sheatpump.type = 3;
|
|
184
|
+
heatpump.body = sys.equipment.shared ? 32 : 0;
|
|
185
|
+
heatpump.isActive = true;
|
|
186
|
+
heatpump.master = 0;
|
|
187
|
+
|
|
188
|
+
if (typeof heatpump.name === 'undefined') sheatpump.name = heatpump.name = 'UltraTemp';
|
|
189
|
+
heatpump.heatingEnabled = (msg.extractPayloadByte(1) & 0x01) === 1;
|
|
190
|
+
heatpump.coolingEnabled = (msg.extractPayloadByte(1) & 0x02) === 2;
|
|
191
|
+
sys.board.equipmentIds.invalidIds.add(20); // exclude Aux Extra
|
|
192
|
+
}
|
|
193
|
+
else if (hasSolar) {
|
|
194
|
+
sys.heaters.removeItemById(3);
|
|
195
|
+
state.heaters.removeItemById(3);
|
|
196
|
+
let solar = sys.heaters.getItemById(2, true);
|
|
197
|
+
let ssolar = sys.heaters.getItemById(2, true);
|
|
198
|
+
// [2, { name: 'solar', desc: 'Solar Heater', hasAddress: false, hasPreference: true }],
|
|
199
|
+
solar.type = ssolar.type = 2;
|
|
200
|
+
solar.body = sys.equipment.shared ? 32 : 0;
|
|
201
|
+
solar.isActive = true;
|
|
202
|
+
solar.master = 0;
|
|
203
|
+
if (typeof solar.name === 'undefined') solar.name = ssolar.name = 'Solar Heater';
|
|
204
|
+
solar.freeze = (msg.extractPayloadByte(1) & 0x80) >> 7 === 1;
|
|
205
|
+
solar.coolingEnabled = (msg.extractPayloadByte(1) & 0x20) >> 5 === 1;
|
|
206
|
+
solar.startTempDelta = ((msg.extractPayloadByte(2) & 0xE) >> 1) + 3;
|
|
207
|
+
solar.stopTempDelta = ((msg.extractPayloadByte(2) & 0xC0) >> 6) + 2;
|
|
208
|
+
sys.board.equipmentIds.invalidIds.add(20); // exclude Aux Extra
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
sys.board.equipmentIds.invalidIds.remove(20); // Allow access to Aux Extra
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
sys.board.heaters.updateHeaterServices();
|
|
215
|
+
for (let i = 0; i < sys.bodies.length; i++) {
|
|
216
|
+
let body = sys.bodies.getItemByIndex(i);
|
|
217
|
+
let btemp = state.temps.bodies.getItemById(body.id, body.isActive !== false);
|
|
218
|
+
let opts = sys.board.heaters.getInstalledHeaterTypes(body.id);
|
|
219
|
+
btemp.heaterOptions = opts;
|
|
220
|
+
}
|
|
221
|
+
sys.board.heaters.syncHeaterStates();
|
|
222
|
+
sys.equipment.setEquipmentIds();
|
|
223
|
+
msg.isProcessed = true;
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
/*
|
|
97
227
|
// gas heater only; solar/heatpump/ultratemp disabled
|
|
98
228
|
if ((msg.extractPayloadByte(0) & 0x2) === 0) {
|
|
99
229
|
let heater = sys.heaters.getItemById(1);
|
|
@@ -112,14 +242,14 @@ export class HeaterMessage {
|
|
|
112
242
|
sys.heaters.getItemById(3).isActive = false;
|
|
113
243
|
sys.heaters.getItemById(4).isActive = false;
|
|
114
244
|
sys.board.equipmentIds.invalidIds.remove(20); // include Aux Extra
|
|
115
|
-
|
|
116
|
-
for (let i = 0; i < sys.bodies.length; i++) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
return;
|
|
245
|
+
//sys.equipment.setEquipmentIds();
|
|
246
|
+
//for (let i = 0; i < sys.bodies.length; i++) {
|
|
247
|
+
// let body = sys.bodies.getItemByIndex(i);
|
|
248
|
+
// let btemp = state.temps.bodies.getItemById(body.id, body.isActive !== false);
|
|
249
|
+
// let opts = sys.board.heaters.getInstalledHeaterTypes(body.id);
|
|
250
|
+
// btemp.heaterOptions = opts;
|
|
251
|
+
//}
|
|
252
|
+
return;
|
|
123
253
|
}
|
|
124
254
|
// Ultratemp (+ cooling?);
|
|
125
255
|
else if ((msg.extractPayloadByte(2) & 0x30) === 0x30) {
|
|
@@ -220,27 +350,9 @@ export class HeaterMessage {
|
|
|
220
350
|
sys.board.heaters.syncHeaterStates();
|
|
221
351
|
sys.equipment.setEquipmentIds();
|
|
222
352
|
msg.isProcessed = true;
|
|
353
|
+
*/
|
|
223
354
|
break;
|
|
224
|
-
case 168:
|
|
225
|
-
{
|
|
226
|
-
// IntelliChem Installed
|
|
227
|
-
if ((msg.extractPayloadByte(3) & 0x01) === 1) {
|
|
228
|
-
// only support for 1 ic with EasyTouch
|
|
229
|
-
let chem = sys.chemControllers.getItemByAddress(144, true);
|
|
230
|
-
let schem = state.chemControllers.getItemById(chem.id, true);
|
|
231
|
-
chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
|
|
232
|
-
chem.ph.tank.units = chem.orp.tank.units = '';
|
|
233
355
|
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
let chem = sys.chemControllers.getItemByAddress(144);
|
|
237
|
-
state.chemControllers.removeItemById(chem.id);
|
|
238
|
-
sys.chemControllers.removeItemById(chem.id);
|
|
239
|
-
}
|
|
240
|
-
// Spa Manual Heat on/off
|
|
241
|
-
sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1 ? true : false;
|
|
242
|
-
msg.isProcessed = true;
|
|
243
|
-
}
|
|
244
356
|
}
|
|
245
357
|
}
|
|
246
358
|
private static processCooldownDelay(msg: Inbound) {
|
|
@@ -139,16 +139,22 @@ export class OptionsMessage {
|
|
|
139
139
|
break;
|
|
140
140
|
}
|
|
141
141
|
case 40:
|
|
142
|
+
case 168:
|
|
143
|
+
{
|
|
144
|
+
|
|
142
145
|
// [165,33,16,34,168,10],[0,0,0,254,0,0,0,0,0,0],[2,168 = manual heat mode off
|
|
143
146
|
// [165,33,16,34,168,10],[0,0,0,254,1,0,0,0,0,0],[2,169] = manual heat mode on
|
|
144
147
|
sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1;
|
|
148
|
+
// From https://github.com/tagyoureit/nodejs-poolController/issues/362 = Intellitouch
|
|
149
|
+
// [0,0,0,0,1,x,0,0,0,0] x=0 Manual OP heat Off; x=1 Manual OP heat On
|
|
150
|
+
sys.general.options.manualPriority = msg.extractPayloadByte(5) === 1;
|
|
145
151
|
if ((msg.extractPayloadByte(3) & 0x01) === 1) {
|
|
146
152
|
// only support for 1 ic with EasyTouch
|
|
147
153
|
let chem = sys.chemControllers.getItemByAddress(144, true);
|
|
148
|
-
let schem = state.chemControllers.getItemById(chem.id, true);
|
|
154
|
+
//let schem = state.chemControllers.getItemById(chem.id, true);
|
|
149
155
|
chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
|
|
150
156
|
chem.ph.tank.units = chem.orp.tank.units = '';
|
|
151
|
-
|
|
157
|
+
|
|
152
158
|
}
|
|
153
159
|
else {
|
|
154
160
|
let chem = sys.chemControllers.getItemByAddress(144);
|
|
@@ -157,6 +163,7 @@ export class OptionsMessage {
|
|
|
157
163
|
}
|
|
158
164
|
msg.isProcessed = true;
|
|
159
165
|
break;
|
|
166
|
+
}
|
|
160
167
|
}
|
|
161
168
|
}
|
|
162
169
|
}
|
|
@@ -36,43 +36,60 @@ export class PumpMessage {
|
|
|
36
36
|
// packet 24/27/152/155 - Pump Config: IntelliTouch
|
|
37
37
|
const pumpId = msg.extractPayloadByte(0);
|
|
38
38
|
let type = msg.extractPayloadByte(1); // Avoid setting this then setting it back if we are mapping to a different value.
|
|
39
|
+
let isActive = type !== 0 && pumpId <= sys.equipment.maxPumps;
|
|
39
40
|
// RKS: 04-14-21 - Only create the pump if it is available. If the pump was previously defined as another type
|
|
40
41
|
// then it will be removed and recreated.
|
|
41
|
-
let pump: Pump = sys.pumps.getItemById(pumpId,
|
|
42
|
-
if
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
pump
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
42
|
+
let pump: Pump = sys.pumps.getItemById(pumpId, isActive);
|
|
43
|
+
if(isActive) {
|
|
44
|
+
// Remap the combination pump types.
|
|
45
|
+
switch (type) {
|
|
46
|
+
case 0:
|
|
47
|
+
case 64:
|
|
48
|
+
case 169:
|
|
49
|
+
break;
|
|
50
|
+
case 255:
|
|
51
|
+
case 128:
|
|
52
|
+
case 134:
|
|
53
|
+
type = 128;
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
type = 1;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
if (pump.type !== type) {
|
|
60
|
+
sys.pumps.removeItemById(pumpId);
|
|
61
|
+
pump = sys.pumps.getItemById(pumpId, isActive);
|
|
62
|
+
}
|
|
63
|
+
pump.address = pumpId + 95;
|
|
64
|
+
pump.master = 0;
|
|
65
|
+
switch (type) {
|
|
66
|
+
case 0: // none
|
|
67
|
+
pump.type = 0;
|
|
68
|
+
pump.isActive = false;
|
|
69
|
+
break;
|
|
70
|
+
case 64: // vsf
|
|
71
|
+
pump.type = type;
|
|
72
|
+
pump.isActive = true;
|
|
73
|
+
PumpMessage.processVSF_IT(msg);
|
|
74
|
+
break;
|
|
75
|
+
case 255: // vs 3050 on old panels.
|
|
76
|
+
case 128: // vs
|
|
77
|
+
case 134: // vs Ultra Efficiency
|
|
78
|
+
pump.type = 128;
|
|
79
|
+
pump.isActive = true;
|
|
80
|
+
PumpMessage.processVS_IT(msg);
|
|
81
|
+
break;
|
|
82
|
+
case 169: // vs+svrs
|
|
83
|
+
pump.type = 169;
|
|
84
|
+
pump.isActive = true;
|
|
85
|
+
PumpMessage.processVS_IT(msg);
|
|
86
|
+
break;
|
|
87
|
+
default: // vf - type is the background circuit
|
|
88
|
+
pump.type = 1; // force to type 1?
|
|
89
|
+
pump.isActive = true;
|
|
90
|
+
PumpMessage.processVF_IT(msg);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
76
93
|
if (typeof pump.name === 'undefined') pump.name = sys.board.valueMaps.pumpTypes.get(pump.type).desc;
|
|
77
94
|
const spump = state.pumps.getItemById(pump.id, true);
|
|
78
95
|
spump.name = pump.name;
|
|
@@ -224,6 +241,7 @@ export class PumpMessage {
|
|
|
224
241
|
}
|
|
225
242
|
if (typeof pump.model === 'undefined') pump.model = 0;
|
|
226
243
|
pump.type = type;
|
|
244
|
+
pump.master = 0;
|
|
227
245
|
let spump = state.pumps.getItemById(pump.id, true);
|
|
228
246
|
spump.type = pump.type;
|
|
229
247
|
spump.isActive = pump.isActive = true;
|
|
@@ -48,10 +48,10 @@ export class ScheduleMessage {
|
|
|
48
48
|
case 6:
|
|
49
49
|
ScheduleMessage.processCircuit(msg);
|
|
50
50
|
break;
|
|
51
|
-
case 8: //
|
|
51
|
+
case 8: // Schedule Type
|
|
52
52
|
case 9:
|
|
53
53
|
case 10:
|
|
54
|
-
ScheduleMessage.
|
|
54
|
+
ScheduleMessage.processScheduleType(msg);
|
|
55
55
|
break;
|
|
56
56
|
case 11:
|
|
57
57
|
case 12:
|
|
@@ -127,6 +127,7 @@ export class ScheduleMessage {
|
|
|
127
127
|
const schedule: Schedule = sys.schedules.getItemByIndex(i);
|
|
128
128
|
if (schedule.scheduleType === sys.board.valueMaps.scheduleTypes.getValue('runonce') && schedule.circuit === eggTimer.circuit){
|
|
129
129
|
const sstate = state.schedules.getItemById(schedule.id);
|
|
130
|
+
schedule.master = 0;
|
|
130
131
|
sstate.endTime = schedule.endTime = (schedule.startTime + eggTimer.runTime) % 1440; // remove days if we go past midnight
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -150,6 +151,7 @@ export class ScheduleMessage {
|
|
|
150
151
|
if (sys.circuits.getItemById(schedule.circuit).hasHeatSource && typeof schedule.heatSource === 'undefined') schedule.heatSource = sys.board.valueMaps.heatSources.getValue('nochange');
|
|
151
152
|
// todo: add to base sched item
|
|
152
153
|
// (msg.extractPayloadByte(1) & 128) === 1 ? schedule.smartStart = 1 : schedule.smartStart = 0;
|
|
154
|
+
schedule.master = 0;
|
|
153
155
|
if (schedule.isActive) {
|
|
154
156
|
const sstate = state.schedules.getItemById(schedule.id, true);
|
|
155
157
|
sstate.circuit = schedule.circuit;
|
|
@@ -191,7 +193,7 @@ export class ScheduleMessage {
|
|
|
191
193
|
}
|
|
192
194
|
private static processStartDay(msg: Inbound) {
|
|
193
195
|
let schedId = (msg.extractPayloadByte(1) - 17) * 40 + 1;
|
|
194
|
-
for (let i = 1; i < msg.payload.length; i++) {
|
|
196
|
+
for (let i = 1; i < msg.payload.length && schedId <= ScheduleMessage._maxSchedId; i++) {
|
|
195
197
|
const schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
196
198
|
if (schedule.isActive !== false) {
|
|
197
199
|
schedule.startDay = msg.extractPayloadByte(i + 1);
|
|
@@ -203,7 +205,7 @@ export class ScheduleMessage {
|
|
|
203
205
|
}
|
|
204
206
|
private static processStartYear(msg: Inbound) {
|
|
205
207
|
let schedId = (msg.extractPayloadByte(1) - 20) * 40 + 1;
|
|
206
|
-
for (let i = 1; i < msg.payload.length; i++) {
|
|
208
|
+
for (let i = 1; i < msg.payload.length && schedId <= ScheduleMessage._maxSchedId; i++) {
|
|
207
209
|
const schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
208
210
|
if (schedule.isActive !== false) {
|
|
209
211
|
schedule.startYear = msg.extractPayloadByte(i + 1);
|
|
@@ -213,22 +215,15 @@ export class ScheduleMessage {
|
|
|
213
215
|
}
|
|
214
216
|
private static processStartTimes(msg: Inbound) {
|
|
215
217
|
let schedId = msg.extractPayloadByte(1) * 20 + 1;
|
|
216
|
-
for (let i = 1; i < msg.payload.length - 1;) {
|
|
217
|
-
let
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
schedule.startTime = time;
|
|
221
|
-
schedule.isActive = schedule.startTime !== 0;
|
|
218
|
+
for (let i = 1; i < msg.payload.length - 1 && schedId <= ScheduleMessage._maxSchedId;) {
|
|
219
|
+
let schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
220
|
+
if (schedule.isActive) {
|
|
221
|
+
schedule.startTime = msg.extractPayloadInt(i + 1);
|
|
222
222
|
let csched = state.schedules.getItemById(schedule.id, true);
|
|
223
223
|
csched.startTime = schedule.startTime;
|
|
224
224
|
}
|
|
225
|
-
else {
|
|
226
|
-
state.schedules.removeItemById(schedule.id);
|
|
227
|
-
sys.schedules.removeItemById(schedule.id);
|
|
228
|
-
}
|
|
229
225
|
i += 2;
|
|
230
226
|
}
|
|
231
|
-
ScheduleMessage._maxSchedId = sys.schedules.getMaxId(true, 0);
|
|
232
227
|
msg.isProcessed = true;
|
|
233
228
|
}
|
|
234
229
|
private static processEndTimes(msg: Inbound) {
|
|
@@ -238,7 +233,7 @@ export class ScheduleMessage {
|
|
|
238
233
|
const schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
239
234
|
if (schedule.isActive !== false) {
|
|
240
235
|
schedule.endTime = time;
|
|
241
|
-
let csched = state.schedules.getItemById(schedule.id);
|
|
236
|
+
let csched = state.schedules.getItemById(schedule.id, true);
|
|
242
237
|
csched.endTime = schedule.endTime;
|
|
243
238
|
}
|
|
244
239
|
i += 2;
|
|
@@ -250,11 +245,10 @@ export class ScheduleMessage {
|
|
|
250
245
|
for (let i = 1; i < msg.payload.length && schedId <= ScheduleMessage._maxSchedId; i++) {
|
|
251
246
|
let schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
252
247
|
if (schedule.isActive) {
|
|
253
|
-
let csched = state.schedules.getItemById(schedule.id);
|
|
248
|
+
let csched = state.schedules.getItemById(schedule.id, true);
|
|
254
249
|
schedule.circuit = msg.extractPayloadByte(i + 1) + 1;
|
|
255
250
|
if (schedule.circuit === 256 || schedule.circuit === 0) {
|
|
256
|
-
// This is some of the IntelliCenter craziness where the schedule
|
|
257
|
-
// the circuit is undefined.
|
|
251
|
+
// This is some of the IntelliCenter craziness where the schedule is marked as active but the circuit is not defined.
|
|
258
252
|
csched.isActive = false;
|
|
259
253
|
state.schedules.removeItemById(schedule.id);
|
|
260
254
|
sys.schedules.removeItemById(schedule.id);
|
|
@@ -265,13 +259,16 @@ export class ScheduleMessage {
|
|
|
265
259
|
}
|
|
266
260
|
msg.isProcessed = true;
|
|
267
261
|
}
|
|
268
|
-
private static
|
|
262
|
+
private static processScheduleType(msg: Inbound) {
|
|
269
263
|
let schedId = (msg.extractPayloadByte(1) - 8) * 40 + 1;
|
|
270
|
-
for (let i = 1; i < msg.payload.length
|
|
271
|
-
let
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// schedule.
|
|
264
|
+
for (let i = 1; i < msg.payload.length; i++) {
|
|
265
|
+
let byte = msg.extractPayloadByte(i + 1);
|
|
266
|
+
let schedule: Schedule = sys.schedules.getItemById(schedId++, (byte & 128) === 128);
|
|
267
|
+
if ((byte & 128) === 128) {
|
|
268
|
+
// If bit 8 is set on the time type then this indicates whether the schedule is active. If it is not
|
|
269
|
+
// active then we will be removing it.
|
|
270
|
+
schedule.isActive = true;
|
|
271
|
+
schedule.master = 0;
|
|
275
272
|
schedule.scheduleType = (byte & 1 & 0xFF) === 1 ? 0 : 128;
|
|
276
273
|
if ((byte & 4 & 0xFF) === 4) schedule.startTimeType = 1;
|
|
277
274
|
else if ((byte & 8 & 0xFF) === 8) schedule.startTimeType = 2;
|
|
@@ -281,11 +278,22 @@ export class ScheduleMessage {
|
|
|
281
278
|
else if ((byte & 32 & 0xFF) === 32) schedule.endTimeType = 2;
|
|
282
279
|
else schedule.endTimeType = 0;
|
|
283
280
|
let csched = state.schedules.getItemById(schedule.id);
|
|
281
|
+
csched.isActive = true;
|
|
284
282
|
csched.startTimeType = schedule.startTimeType;
|
|
285
283
|
csched.endTimeType = schedule.endTimeType;
|
|
286
284
|
csched.scheduleType = schedule.scheduleType;
|
|
287
285
|
}
|
|
286
|
+
else {
|
|
287
|
+
// Now we need to remove this pig because this is not an active schedule.
|
|
288
|
+
sys.schedules.removeItemById(schedule.id);
|
|
289
|
+
if (schedule.isActive) {
|
|
290
|
+
let csched = state.schedules.getItemById(schedule.id);
|
|
291
|
+
schedule.isActive = csched.isActive = false;
|
|
292
|
+
}
|
|
293
|
+
state.schedules.removeItemById(schedule.id);
|
|
294
|
+
}
|
|
288
295
|
}
|
|
296
|
+
ScheduleMessage._maxSchedId = sys.schedules.getMaxId(true, 0);
|
|
289
297
|
msg.isProcessed = true;
|
|
290
298
|
}
|
|
291
299
|
private static processDays(msg: Inbound) {
|
|
@@ -131,7 +131,7 @@ export class ValveMessage {
|
|
|
131
131
|
// there is no circuit. The circuitry for the valve always exists although I am not sure
|
|
132
132
|
// how the valve expansion is represented.
|
|
133
133
|
valve.isActive = true;
|
|
134
|
-
valve.isReturn = false;
|
|
134
|
+
valve.isReturn = false;
|
|
135
135
|
valve.isIntake = false;
|
|
136
136
|
valve.type = 0;
|
|
137
137
|
// Allow users to name the valve whatever they want. *Touch apparently only allows the valve to be named the same
|
|
@@ -174,7 +174,7 @@ export class ValveMessage {
|
|
|
174
174
|
// for i10d.
|
|
175
175
|
let ndx: number = 2;
|
|
176
176
|
let id = 1;
|
|
177
|
-
for (let i = 0; i < sys.equipment.maxValves
|
|
177
|
+
for (let i = 0; i < sys.equipment.maxValves; i++) {
|
|
178
178
|
if (id === 3 && !sys.equipment.shared) {
|
|
179
179
|
// The intake/return valves are skipped for non-shared systems.
|
|
180
180
|
sys.valves.removeItemById(3);
|