nodejs-poolcontroller 7.6.1 → 8.0.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/.eslintrc.json +36 -45
- 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/CONTRIBUTING.md +74 -74
- package/Changelog +242 -215
- package/Dockerfile +17 -17
- package/Gruntfile.js +40 -40
- package/LICENSE +661 -661
- package/README.md +195 -191
- package/anslq25/MessagesMock.ts +218 -0
- package/anslq25/boards/MockBoardFactory.ts +50 -0
- package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
- package/anslq25/boards/MockSystemBoard.ts +217 -0
- package/anslq25/chemistry/MockChlorinator.ts +75 -0
- package/anslq25/pumps/MockPump.ts +84 -0
- package/app.ts +10 -14
- package/config/Config.ts +26 -8
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +59 -25
- package/controller/Equipment.ts +2667 -2459
- package/controller/Errors.ts +181 -180
- package/controller/Lockouts.ts +534 -436
- package/controller/State.ts +596 -77
- package/controller/boards/AquaLinkBoard.ts +1003 -0
- package/controller/boards/BoardFactory.ts +53 -45
- package/controller/boards/EasyTouchBoard.ts +3079 -2653
- package/controller/boards/IntelliCenterBoard.ts +3821 -4230
- package/controller/boards/IntelliComBoard.ts +69 -63
- package/controller/boards/IntelliTouchBoard.ts +384 -241
- package/controller/boards/NixieBoard.ts +1871 -1675
- package/controller/boards/SunTouchBoard.ts +393 -0
- package/controller/boards/SystemBoard.ts +5244 -4697
- package/controller/comms/Comms.ts +905 -541
- package/controller/comms/ScreenLogic.ts +1663 -0
- package/controller/comms/messages/Messages.ts +382 -54
- package/controller/comms/messages/config/ChlorinatorMessage.ts +8 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
- package/controller/comms/messages/config/CircuitMessage.ts +82 -13
- package/controller/comms/messages/config/ConfigMessage.ts +3 -1
- package/controller/comms/messages/config/CoverMessage.ts +2 -1
- package/controller/comms/messages/config/CustomNameMessage.ts +31 -30
- package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
- package/controller/comms/messages/config/ExternalMessage.ts +33 -3
- package/controller/comms/messages/config/FeatureMessage.ts +2 -1
- package/controller/comms/messages/config/GeneralMessage.ts +2 -1
- package/controller/comms/messages/config/HeaterMessage.ts +145 -11
- package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
- package/controller/comms/messages/config/OptionsMessage.ts +16 -27
- package/controller/comms/messages/config/PumpMessage.ts +62 -47
- package/controller/comms/messages/config/RemoteMessage.ts +80 -13
- package/controller/comms/messages/config/ScheduleMessage.ts +390 -347
- package/controller/comms/messages/config/SecurityMessage.ts +2 -1
- package/controller/comms/messages/config/ValveMessage.ts +44 -27
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +44 -91
- package/controller/comms/messages/status/EquipmentStateMessage.ts +139 -30
- package/controller/comms/messages/status/HeaterStateMessage.ts +135 -86
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -445
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -35
- package/controller/comms/messages/status/PumpStateMessage.ts +92 -2
- package/controller/comms/messages/status/VersionMessage.ts +2 -1
- package/controller/nixie/Nixie.ts +173 -162
- package/controller/nixie/NixieEquipment.ts +104 -103
- package/controller/nixie/bodies/Body.ts +120 -120
- package/controller/nixie/bodies/Filter.ts +135 -135
- package/controller/nixie/chemistry/ChemController.ts +2682 -2498
- package/controller/nixie/chemistry/ChemDoser.ts +806 -0
- package/controller/nixie/chemistry/Chlorinator.ts +367 -314
- package/controller/nixie/circuits/Circuit.ts +402 -248
- package/controller/nixie/heaters/Heater.ts +815 -649
- package/controller/nixie/pumps/Pump.ts +934 -661
- package/controller/nixie/schedules/Schedule.ts +319 -257
- package/controller/nixie/valves/Valve.ts +170 -170
- package/defaultConfig.json +346 -286
- package/logger/DataLogger.ts +448 -448
- package/logger/Logger.ts +38 -9
- package/package.json +60 -56
- package/tsconfig.json +25 -25
- package/web/Server.ts +275 -117
- package/web/bindings/aqualinkD.json +560 -0
- package/web/bindings/homeassistant.json +437 -0
- package/web/bindings/influxDB.json +1066 -1021
- package/web/bindings/mqtt.json +721 -654
- package/web/bindings/mqttAlt.json +746 -684
- package/web/bindings/rulesManager.json +54 -54
- package/web/bindings/smartThings-Hubitat.json +31 -31
- package/web/bindings/valveRelays.json +20 -20
- package/web/bindings/vera.json +25 -25
- package/web/interfaces/baseInterface.ts +188 -136
- package/web/interfaces/httpInterface.ts +148 -124
- package/web/interfaces/influxInterface.ts +283 -245
- package/web/interfaces/mqttInterface.ts +695 -475
- package/web/interfaces/ruleInterface.ts +87 -0
- package/web/services/config/Config.ts +177 -49
- package/web/services/config/ConfigSocket.ts +2 -1
- package/web/services/state/State.ts +154 -3
- package/web/services/state/StateSocket.ts +69 -18
- package/web/services/utilities/Utilities.ts +232 -42
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -42,6 +43,10 @@ import { TouchScheduleCommands } from "controller/boards/EasyTouchBoard";
|
|
|
42
43
|
import { IntelliValveStateMessage } from "./status/IntelliValveStateMessage";
|
|
43
44
|
import { IntelliChemStateMessage } from "./status/IntelliChemStateMessage";
|
|
44
45
|
import { OutboundMessageError } from "../../Errors";
|
|
46
|
+
import { conn } from "../Comms"
|
|
47
|
+
import extend = require("extend");
|
|
48
|
+
import { MessagesMock } from "../../../anslq25/MessagesMock";
|
|
49
|
+
|
|
45
50
|
export enum Direction {
|
|
46
51
|
In = 'in',
|
|
47
52
|
Out = 'out'
|
|
@@ -54,6 +59,8 @@ export enum Protocol {
|
|
|
54
59
|
IntelliChem = 'intellichem',
|
|
55
60
|
IntelliValve = 'intellivalve',
|
|
56
61
|
Heater = 'heater',
|
|
62
|
+
AquaLink = 'aqualink',
|
|
63
|
+
Hayward = 'hayward',
|
|
57
64
|
Unidentified = 'unidentified'
|
|
58
65
|
}
|
|
59
66
|
export class Message {
|
|
@@ -66,8 +73,11 @@ export class Message {
|
|
|
66
73
|
private _id: number = -1;
|
|
67
74
|
// Fields
|
|
68
75
|
private static _messageId: number = 0;
|
|
69
|
-
public static get nextMessageId(): number {
|
|
70
|
-
|
|
76
|
+
public static get nextMessageId(): number {
|
|
77
|
+
let i = this._messageId < 80000 ? ++this._messageId : this._messageId = 0;
|
|
78
|
+
logger.debug(`Assigning message id ${i}`)
|
|
79
|
+
return i; }
|
|
80
|
+
public portId = 0; // This will be the target or source port for the message. If this is from or to an Aux RS485 port the value will be > 0.
|
|
71
81
|
public timestamp: Date = new Date();
|
|
72
82
|
public direction: Direction = Direction.In;
|
|
73
83
|
public protocol: Protocol = Protocol.Unknown;
|
|
@@ -81,36 +91,62 @@ export class Message {
|
|
|
81
91
|
public set id(val: number) { this._id = val; }
|
|
82
92
|
public isValid: boolean = true;
|
|
83
93
|
public scope: string;
|
|
94
|
+
public isClone: boolean;
|
|
84
95
|
// Properties
|
|
85
96
|
public get isComplete(): boolean { return this._complete; }
|
|
86
97
|
public get sub(): number { return this.header.length > 1 ? this.header[1] : -1; }
|
|
87
98
|
public get dest(): number {
|
|
88
|
-
if (this.
|
|
89
|
-
|
|
99
|
+
if (this.header.length > 2) {
|
|
100
|
+
if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) {
|
|
101
|
+
return this.header.length > 2 ? (this.header[2] >= 80 ? this.header[2] : 0) : -1;
|
|
102
|
+
}
|
|
103
|
+
else if (this.protocol === Protocol.Hayward) {
|
|
104
|
+
// src act dest
|
|
105
|
+
//0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
|
|
106
|
+
return this.header.length > 4 ? this.header[2] : -1;
|
|
107
|
+
}
|
|
108
|
+
else return this.header.length > 2 ? this.header[2] : -1;
|
|
90
109
|
}
|
|
91
|
-
if (this.header.length > 2) return this.header[2];
|
|
92
110
|
else return -1;
|
|
93
111
|
}
|
|
94
112
|
public get source(): number {
|
|
95
113
|
if (this.protocol === Protocol.Chlorinator) {
|
|
96
|
-
return this.header[2] >= 80 ? 0 : 1;
|
|
114
|
+
return this.header.length > 2 ? (this.header[2] >= 80 ? 0 : this.header[2]) : -1;
|
|
97
115
|
// have to assume incoming packets with header[2] >= 80 (sent to a chlorinator)
|
|
98
116
|
// are from controller (0);
|
|
99
117
|
// likewise, if the destination is 0 (controller) we
|
|
100
118
|
// have to assume it was sent from the 1st chlorinator (1)
|
|
101
119
|
// until we learn otherwise.
|
|
102
120
|
}
|
|
121
|
+
else if (this.protocol === Protocol.AquaLink) {
|
|
122
|
+
// Once we decode the devices we will be able to tell where it came from based upon the commands.
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
else if (this.protocol === Protocol.Hayward) {
|
|
126
|
+
// src act dest
|
|
127
|
+
//0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
|
|
128
|
+
//0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
|
|
129
|
+
return this.header.length > 4 ? this.header[4] : -1;
|
|
130
|
+
}
|
|
103
131
|
if (this.header.length > 3) return this.header[3];
|
|
104
132
|
else return -1;
|
|
105
133
|
}
|
|
106
134
|
public get action(): number {
|
|
107
|
-
|
|
108
|
-
if (this.
|
|
135
|
+
// The action byte is actually the 4th byte in the header the destination address is the 5th byte.
|
|
136
|
+
if (this.protocol === Protocol.Chlorinator ||
|
|
137
|
+
this.protocol === Protocol.AquaLink) return this.header.length > 3 ? this.header[3] : -1;
|
|
138
|
+
else if (this.protocol === Protocol.Hayward) {
|
|
139
|
+
// src act dest
|
|
140
|
+
//0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
|
|
141
|
+
//0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
|
|
142
|
+
return this.header.length > 3 ? this.header[3] || this.header[2] : -1;
|
|
143
|
+
}
|
|
144
|
+
if (this.header.length > 4) return this.header[4];
|
|
109
145
|
else return -1;
|
|
110
146
|
}
|
|
111
|
-
public get datalen(): number { return this.protocol === Protocol.Chlorinator ? this.payload.length : this.header.length > 5 ? this.header[5] : -1; }
|
|
112
|
-
public get chkHi(): number { return this.protocol === Protocol.Chlorinator ? 0 : this.term.length > 0 ? this.term[0] : -1; }
|
|
113
|
-
public get chkLo(): number { return this.protocol === Protocol.Chlorinator ? this.term[0] : this.term[1]; }
|
|
147
|
+
public get datalen(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink || this.protocol === Protocol.Hayward ? this.payload.length : this.header.length > 5 ? this.header[5] : -1; }
|
|
148
|
+
public get chkHi(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink ? 0 : this.term.length > 0 ? this.term[0] : -1; }
|
|
149
|
+
public get chkLo(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink ? this.term[0] : this.term[1]; }
|
|
114
150
|
public get checksum(): number {
|
|
115
151
|
var sum = 0;
|
|
116
152
|
for (let i = 0; i < this.header.length; i++) sum += this.header[i];
|
|
@@ -136,7 +172,59 @@ export class Message {
|
|
|
136
172
|
return pkt;
|
|
137
173
|
}
|
|
138
174
|
public toLog(): string {
|
|
139
|
-
return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)}
|
|
175
|
+
return `{"port":${this.portId},"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)}, ${JSON.stringify(this.header)}, ${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts":"${Timestamp.toISOLocal(this.timestamp)}"}`;
|
|
176
|
+
}
|
|
177
|
+
public static convertOutboundToInbound(out: Outbound): Inbound {
|
|
178
|
+
let inbound = new Inbound();
|
|
179
|
+
inbound.portId = out.portId;
|
|
180
|
+
// inbound.id = Message.nextMessageId;
|
|
181
|
+
inbound.protocol = out.protocol;
|
|
182
|
+
inbound.scope = out.scope;
|
|
183
|
+
inbound.preamble = out.preamble;
|
|
184
|
+
inbound.padding = out.padding;
|
|
185
|
+
inbound.header = out.header;
|
|
186
|
+
inbound.payload = [...out.payload];
|
|
187
|
+
inbound.term = out.term;
|
|
188
|
+
inbound.portId = out.portId;
|
|
189
|
+
return inbound;
|
|
190
|
+
}
|
|
191
|
+
public static convertInboundToOutbound(inbound: Inbound): Outbound {
|
|
192
|
+
let out = new Outbound(
|
|
193
|
+
inbound.protocol,
|
|
194
|
+
inbound.source,
|
|
195
|
+
inbound.dest,
|
|
196
|
+
inbound.action,
|
|
197
|
+
inbound.payload,
|
|
198
|
+
);
|
|
199
|
+
out.scope = inbound.scope;
|
|
200
|
+
out.preamble = inbound.preamble;
|
|
201
|
+
out.padding = inbound.padding;
|
|
202
|
+
out.header = inbound.header;
|
|
203
|
+
out.term = inbound.term;
|
|
204
|
+
out.portId = inbound.portId;
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
public clone(): Inbound | Outbound {
|
|
208
|
+
let msg;
|
|
209
|
+
if (this instanceof Inbound) {
|
|
210
|
+
msg = new Inbound();
|
|
211
|
+
msg.id = Message.nextMessageId;
|
|
212
|
+
msg.scope = this.scope;
|
|
213
|
+
msg.preamble = this.preamble;
|
|
214
|
+
msg.padding = this.padding;
|
|
215
|
+
msg.payload = [...this.payload];
|
|
216
|
+
msg.header = this.header;
|
|
217
|
+
msg.term = this.term;
|
|
218
|
+
msg.portId = this.portId;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
msg = new Outbound(
|
|
222
|
+
this.protocol, this.source, this.dest, this.action, [...this.payload],
|
|
223
|
+
);
|
|
224
|
+
msg.portId = this.portId;
|
|
225
|
+
msg.scope = this.scope;
|
|
226
|
+
}
|
|
227
|
+
return msg;
|
|
140
228
|
}
|
|
141
229
|
}
|
|
142
230
|
export class Inbound extends Message {
|
|
@@ -158,26 +246,93 @@ export class Inbound extends Message {
|
|
|
158
246
|
public responseFor: number[] = [];
|
|
159
247
|
public isProcessed: boolean = false;
|
|
160
248
|
public collisions: number = 0;
|
|
249
|
+
public rewinds: number = 0;
|
|
161
250
|
// Private methods
|
|
162
251
|
private isValidChecksum(): boolean {
|
|
163
|
-
if (this.protocol === Protocol.Chlorinator) return this.checksum % 256 === this.chkLo;
|
|
252
|
+
if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) return this.checksum % 256 === this.chkLo;
|
|
164
253
|
return (this.chkHi * 256) + this.chkLo === this.checksum;
|
|
165
254
|
}
|
|
166
255
|
public toLog() {
|
|
167
256
|
if (this.responseFor.length > 0)
|
|
168
|
-
return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
|
|
169
|
-
return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
|
|
257
|
+
return `{"port":${this.portId || 0},"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
|
|
258
|
+
return `{"port":${this.portId || 0},"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
|
|
170
259
|
}
|
|
171
260
|
private testChlorHeader(bytes: number[], ndx: number): boolean {
|
|
172
261
|
// if packets have 16,2 (eg status=16,2,29) in them and they come as partial packets, they would have
|
|
173
262
|
// prev been detected as chlor packets;
|
|
174
263
|
// valid chlor packets should have 16,2,0 or 16,2,[80-96];
|
|
175
264
|
// this should reduce the number of false chlor packets
|
|
176
|
-
|
|
265
|
+
// For any of these 16,2 type headers we need at least 5 bytes to determine the routing.
|
|
266
|
+
//63,15,16,2,29,9,36,0,0,0,0,0,16,0,32,0,0,2,0,75,75,32,241,80,85,24,241,16,16,48,245,69,45,100,186,16,2,80,17,0,115,16,3
|
|
267
|
+
if (bytes.length > ndx + 4) {
|
|
268
|
+
if (bytes[ndx] === 16 && bytes[ndx + 1] === 2) {
|
|
269
|
+
let dst = bytes[ndx + 2];
|
|
270
|
+
let act = bytes[ndx + 3];
|
|
271
|
+
// For now the dst byte will always be 0 or 80.
|
|
272
|
+
if (![0, 16, 80, 81, 82, 83].includes(dst)) {
|
|
273
|
+
//logger.info(`Sensed chlorinator header but the dst byte is ${dst}`);
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
else if (dst === 0 && [1, 18, 3].includes(act))
|
|
277
|
+
return true;
|
|
278
|
+
else if (![0, 17, 19, 20, 21, 22].includes(act)) {
|
|
279
|
+
//logger.info(`Sensed out chlorinator header but the dst byte is ${dst} ${act} ${JSON.stringify(bytes)}`);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
private testAquaLinkHeader(bytes: number[], ndx: number): boolean {
|
|
288
|
+
if (bytes.length > ndx + 4 && sys.controllerType === 'aqualink') {
|
|
289
|
+
if (bytes[ndx] === 16 && bytes[ndx + 1] === 2) {
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
private testHaywardHeader(bytes: number[], ndx: number): boolean {
|
|
296
|
+
//0x10, 0x02, 0x0C, 0x01, 0x00, 0x2D, 0x00, 0x4C, 0x10, 0x03 -- Command to pump
|
|
297
|
+
//[16,2,12,1,0]
|
|
298
|
+
//0x10, 0x02, 0x0C, 0x01, 0x00, 0x2D, 0x00, 0x4C, 0x10, 0x03 -- Command to Filter Pump
|
|
299
|
+
//[16,2,12,1,0]
|
|
300
|
+
//0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
|
|
301
|
+
//[16,2,12,1,2]
|
|
302
|
+
// src act dest
|
|
303
|
+
//0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
|
|
304
|
+
//[16,2,0,12,0] --> Response
|
|
305
|
+
//[16,2,0,12,0]
|
|
306
|
+
if (bytes.length > ndx + 4) {
|
|
307
|
+
if (sys.controllerType === 'aqualink') return false;
|
|
308
|
+
if (bytes[ndx] === 16 && bytes[ndx + 1] === 2) {
|
|
309
|
+
let dst = bytes[ndx + 3];
|
|
310
|
+
let src = bytes[ndx + 2];
|
|
311
|
+
if (dst === 12 || src === 12) return true;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return false;
|
|
177
315
|
}
|
|
178
|
-
private testBroadcastHeader(bytes: number[], ndx: number): boolean {
|
|
179
|
-
|
|
180
|
-
|
|
316
|
+
private testBroadcastHeader(bytes: number[], ndx: number): boolean {
|
|
317
|
+
// We are looking for [255,0,255,165]
|
|
318
|
+
if (bytes.length > ndx + 3) {
|
|
319
|
+
if (bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] === 165) return true;
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
//return ndx < bytes.length - 3 && bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] === 165;
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
private testUnidentifiedHeader(bytes: number[], ndx: number): boolean {
|
|
326
|
+
if (bytes.length > ndx + 3) {
|
|
327
|
+
if (bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] !== 165) return true;
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
//return ndx < bytes.length - 3 && bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] !== 165;
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
private testChlorTerm(bytes: number[], ndx: number): boolean { return ndx + 2 < bytes.length && bytes[ndx + 1] === 16 && bytes[ndx + 2] === 3; }
|
|
334
|
+
private testAquaLinkTerm(bytes: number[], ndx: number): boolean { return ndx + 2 < bytes.length && bytes[ndx + 1] === 16 && bytes[ndx + 2] === 3; }
|
|
335
|
+
private testHaywardTerm(bytes: number[], ndx: number): boolean { return ndx + 3 < bytes.length && bytes[ndx + 2] === 16 && bytes[ndx + 3] === 3; }
|
|
181
336
|
private pushBytes(target: number[], bytes: number[], ndx: number, length: number): number {
|
|
182
337
|
let end = ndx + length;
|
|
183
338
|
while (ndx < bytes.length && ndx < end)
|
|
@@ -205,16 +360,18 @@ export class Inbound extends Message {
|
|
|
205
360
|
this.isValid = true;
|
|
206
361
|
|
|
207
362
|
this.collisions++;
|
|
363
|
+
this.rewinds++;
|
|
208
364
|
logger.info(`rewinding message collision ${this.collisions} ${ndx} ${bytes.length} ${JSON.stringify(buff)}`);
|
|
209
365
|
this.readPacket(buff);
|
|
210
366
|
return ndx;
|
|
211
367
|
//return this.padding.length + this.preamble.length;
|
|
212
368
|
}
|
|
213
369
|
public readPacket(bytes: number[]): number {
|
|
370
|
+
//logger.info(`BYTES: ${JSON.stringify(bytes)}`);
|
|
214
371
|
var ndx = this.readHeader(bytes, 0);
|
|
215
372
|
if (this.isValid && this.header.length > 0) ndx = this.readPayload(bytes, ndx);
|
|
216
373
|
if (this.isValid && this.header.length > 0) ndx = this.readChecksum(bytes, ndx);
|
|
217
|
-
|
|
374
|
+
if (this.isComplete && !this.isValid) return this.rewind(bytes, ndx);
|
|
218
375
|
return ndx;
|
|
219
376
|
}
|
|
220
377
|
public mergeBytes(bytes) {
|
|
@@ -227,22 +384,40 @@ export class Inbound extends Message {
|
|
|
227
384
|
}
|
|
228
385
|
public readHeader(bytes: number[], ndx: number): number {
|
|
229
386
|
// start over to include the padding bytes.
|
|
387
|
+
//if (this.protocol !== Protocol.Unknown) {
|
|
388
|
+
// logger.warn(`${this.protocol} resulted in an empty message header ${JSON.stringify(this.header)}`);
|
|
389
|
+
//}
|
|
230
390
|
let ndxStart = ndx;
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
391
|
+
// RKS: 05-30-22 -- OMG we have not been dealing with short headers. As a result it was restarting
|
|
392
|
+
// the header process even after it had identified it.
|
|
393
|
+
if (this.protocol === Protocol.Unknown) {
|
|
394
|
+
while (ndx < bytes.length) {
|
|
395
|
+
if (this.testBroadcastHeader(bytes, ndx)) {
|
|
396
|
+
this.protocol = Protocol.Broadcast;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
if (this.testUnidentifiedHeader(bytes, ndx)) {
|
|
400
|
+
this.protocol = Protocol.Unidentified;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
if (this.testChlorHeader(bytes, ndx)) {
|
|
404
|
+
this.protocol = Protocol.Chlorinator;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
if (this.testAquaLinkHeader(bytes, ndx)) {
|
|
408
|
+
this.protocol = Protocol.AquaLink;
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
if (this.testHaywardHeader(bytes, ndx)) {
|
|
412
|
+
this.protocol = Protocol.Hayward;
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
this.padding.push(bytes[ndx++]);
|
|
243
416
|
}
|
|
244
|
-
this.padding.push(bytes[ndx++]);
|
|
245
417
|
}
|
|
418
|
+
// When the code above finds a protocol, ndx will be at the start of that
|
|
419
|
+
// header. If it is not identified then it will rewind to the initial
|
|
420
|
+
// start position until we get more bytes. This is the default case below.
|
|
246
421
|
let ndxHeader = ndx;
|
|
247
422
|
switch (this.protocol) {
|
|
248
423
|
case Protocol.Pump:
|
|
@@ -257,11 +432,11 @@ export class Inbound extends Message {
|
|
|
257
432
|
// We actually don't have a complete header yet so just return.
|
|
258
433
|
// we will pick it up next go around.
|
|
259
434
|
// logger.debug(`We have an incoming message but the serial port hasn't given a complete header. [${this.padding}][${this.preamble}][${this.header}]`);
|
|
435
|
+
//logger.info(`We don't have a complete header ${JSON.stringify(this.header)}`);
|
|
260
436
|
this.preamble = [];
|
|
261
437
|
this.header = [];
|
|
262
438
|
return ndxHeader;
|
|
263
439
|
}
|
|
264
|
-
|
|
265
440
|
if (this.source >= 96 && this.source <= 111) this.protocol = Protocol.Pump;
|
|
266
441
|
else if (this.dest >= 96 && this.dest <= 111) this.protocol = Protocol.Pump;
|
|
267
442
|
else if (this.source >= 112 && this.source <= 127) this.protocol = Protocol.Heater;
|
|
@@ -271,12 +446,13 @@ export class Inbound extends Message {
|
|
|
271
446
|
else if (this.source == 12 || this.dest == 12) this.protocol = Protocol.IntelliValve;
|
|
272
447
|
if (this.datalen > 75) {
|
|
273
448
|
//this.isValid = false;
|
|
274
|
-
logger.debug(`Broadcast length ${this.datalen} exceeded
|
|
449
|
+
logger.debug(`Broadcast length ${this.datalen} exceeded 75 bytes for ${this.protocol} message. Message rewound ${this.header}`);
|
|
275
450
|
this.padding.push(...this.preamble);
|
|
276
451
|
this.padding.push(...this.header.slice(0, 1));
|
|
277
452
|
this.preamble = [];
|
|
278
453
|
this.header = [];
|
|
279
454
|
this.collisions++;
|
|
455
|
+
this.rewinds++;
|
|
280
456
|
return ndxHeader + 1;
|
|
281
457
|
}
|
|
282
458
|
break;
|
|
@@ -298,6 +474,28 @@ export class Inbound extends Message {
|
|
|
298
474
|
return ndxHeader;
|
|
299
475
|
}
|
|
300
476
|
break;
|
|
477
|
+
case Protocol.Hayward:
|
|
478
|
+
ndx = this.pushBytes(this.header, bytes, ndx, 5);
|
|
479
|
+
if (this.header.length < 4) {
|
|
480
|
+
// We actually don't have a complete header yet so just return.
|
|
481
|
+
// we will pick it up next go around.
|
|
482
|
+
logger.debug(`We have an incoming Hayward message but the serial port hasn't given a complete header. [${this.padding}][${this.preamble}][${this.header}]`);
|
|
483
|
+
this.preamble = [];
|
|
484
|
+
this.header = [];
|
|
485
|
+
return ndxHeader;
|
|
486
|
+
}
|
|
487
|
+
break;
|
|
488
|
+
case Protocol.AquaLink:
|
|
489
|
+
ndx = this.pushBytes(this.header, bytes, ndx, 5);
|
|
490
|
+
if (this.header.length < 5) {
|
|
491
|
+
// We actually don't have a complete header yet so just return.
|
|
492
|
+
// we will pick it up next go around.
|
|
493
|
+
logger.debug(`We have an incoming AquaLink message but the serial port hasn't given a complete header. [${this.padding}][${this.preamble}][${this.header}]`);
|
|
494
|
+
this.preamble = [];
|
|
495
|
+
this.header = [];
|
|
496
|
+
return ndxHeader;
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
301
499
|
default:
|
|
302
500
|
// We didn't get a message signature. don't do anything with it.
|
|
303
501
|
ndx = ndxStart;
|
|
@@ -326,7 +524,11 @@ export class Inbound extends Message {
|
|
|
326
524
|
case Protocol.IntelliValve:
|
|
327
525
|
case Protocol.Heater:
|
|
328
526
|
case Protocol.Unidentified:
|
|
329
|
-
if (this.datalen - this.payload.length <= 0)
|
|
527
|
+
if (this.datalen - this.payload.length <= 0) {
|
|
528
|
+
let buff = bytes.slice(ndx - 1);
|
|
529
|
+
//logger.info(`We don't need any more payload ${this.datalen - this.payload.length} ${ndx} ${JSON.stringify(buff)};`);
|
|
530
|
+
return ndx; // We don't need any more payload.
|
|
531
|
+
}
|
|
330
532
|
ndx = this.pushBytes(this.payload, bytes, ndx, this.datalen - this.payload.length);
|
|
331
533
|
break;
|
|
332
534
|
case Protocol.Chlorinator:
|
|
@@ -341,6 +543,31 @@ export class Inbound extends Message {
|
|
|
341
543
|
}
|
|
342
544
|
}
|
|
343
545
|
break;
|
|
546
|
+
case Protocol.AquaLink:
|
|
547
|
+
// We need to deal with AquaLink packets where the terminator is actually split meaning only the first byte or
|
|
548
|
+
// two of the total payload is provided for the term. We need at least 3 bytes to make this determination.
|
|
549
|
+
while (ndx + 3 <= bytes.length && !this.testAquaLinkTerm(bytes, ndx)) {
|
|
550
|
+
this.payload.push(bytes[ndx++]);
|
|
551
|
+
if (this.payload.length > 25) {
|
|
552
|
+
this.isValid = false; // We have a runaway packet. Some collision occurred so lets preserve future packets.
|
|
553
|
+
logger.debug(`AquaLink message marked as invalid after not finding 16,3 in payload after ${this.payload.length} bytes`);
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
break;
|
|
558
|
+
case Protocol.Hayward:
|
|
559
|
+
// We need to deal with AquaLink packets where the terminator is actually split meaning only the first byte or
|
|
560
|
+
// two of the total payload is provided for the term. We need at least 3 bytes to make this determination.
|
|
561
|
+
while (ndx + 4 <= bytes.length && !this.testHaywardTerm(bytes, ndx)) {
|
|
562
|
+
this.payload.push(bytes[ndx++]);
|
|
563
|
+
if (this.payload.length > 25) {
|
|
564
|
+
this.isValid = false; // We have a runaway packet. Some collision occurred so lets preserve future packets.
|
|
565
|
+
logger.debug(`Hayward message marked as invalid after not finding 16,3 in payload after ${this.payload.length} bytes`);
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
break;
|
|
570
|
+
|
|
344
571
|
}
|
|
345
572
|
return ndx;
|
|
346
573
|
}
|
|
@@ -369,6 +596,21 @@ export class Inbound extends Message {
|
|
|
369
596
|
this.isValid = this.isValidChecksum();
|
|
370
597
|
}
|
|
371
598
|
break;
|
|
599
|
+
case Protocol.AquaLink:
|
|
600
|
+
if (ndx + 3 <= bytes.length && this.testAquaLinkTerm(bytes, ndx)) {
|
|
601
|
+
this._complete = true;
|
|
602
|
+
ndx = this.pushBytes(this.term, bytes, ndx, 3);
|
|
603
|
+
this.isValid = this.isValidChecksum();
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
606
|
+
case Protocol.Hayward:
|
|
607
|
+
if (ndx + 4 <= bytes.length && this.testHaywardTerm(bytes, ndx)) {
|
|
608
|
+
this._complete = true;
|
|
609
|
+
ndx = this.pushBytes(this.term, bytes, ndx, 4);
|
|
610
|
+
this.isValid = this.isValidChecksum();
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
|
|
372
614
|
}
|
|
373
615
|
return ndx;
|
|
374
616
|
}
|
|
@@ -471,7 +713,16 @@ export class Inbound extends Message {
|
|
|
471
713
|
PumpMessage.process(this);
|
|
472
714
|
break;
|
|
473
715
|
case 30:
|
|
474
|
-
|
|
716
|
+
switch (sys.controllerType) {
|
|
717
|
+
case ControllerType.Unknown:
|
|
718
|
+
break;
|
|
719
|
+
case ControllerType.SunTouch:
|
|
720
|
+
ScheduleMessage.processSunTouch(this);
|
|
721
|
+
break;
|
|
722
|
+
default:
|
|
723
|
+
OptionsMessage.process(this);
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
475
726
|
break;
|
|
476
727
|
case 22:
|
|
477
728
|
case 32:
|
|
@@ -514,6 +765,9 @@ export class Inbound extends Message {
|
|
|
514
765
|
case 147:
|
|
515
766
|
IntellichemMessage.process(this);
|
|
516
767
|
break;
|
|
768
|
+
case 136:
|
|
769
|
+
ExternalMessage.processTouchSetHeatMode(this);
|
|
770
|
+
break;
|
|
517
771
|
default:
|
|
518
772
|
if (this.action === 109 && this.payload[1] === 3) break;
|
|
519
773
|
if (this.source === 17 && this.payload[0] === 109) break;
|
|
@@ -524,6 +778,13 @@ export class Inbound extends Message {
|
|
|
524
778
|
}
|
|
525
779
|
}
|
|
526
780
|
public process() {
|
|
781
|
+
let port = conn.findPortById(this.portId);
|
|
782
|
+
if (this.portId === sys.anslq25.portId) {
|
|
783
|
+
return MessagesMock.process(this);
|
|
784
|
+
}
|
|
785
|
+
if (port.mock && port.hasAssignedEquipment()){
|
|
786
|
+
return MessagesMock.process(this);
|
|
787
|
+
}
|
|
527
788
|
switch (this.protocol) {
|
|
528
789
|
case Protocol.Broadcast:
|
|
529
790
|
this.processBroadcast();
|
|
@@ -546,6 +807,9 @@ export class Inbound extends Message {
|
|
|
546
807
|
case Protocol.Chlorinator:
|
|
547
808
|
ChlorinatorStateMessage.process(this);
|
|
548
809
|
break;
|
|
810
|
+
case Protocol.Hayward:
|
|
811
|
+
PumpStateMessage.processHayward(this);
|
|
812
|
+
break;
|
|
549
813
|
default:
|
|
550
814
|
logger.debug(`Unprocessed Message ${this.toPacket()}`)
|
|
551
815
|
break;
|
|
@@ -553,15 +817,44 @@ export class Inbound extends Message {
|
|
|
553
817
|
}
|
|
554
818
|
}
|
|
555
819
|
class OutboundCommon extends Message {
|
|
556
|
-
public set sub(val: number) { if (this.protocol !== Protocol.Chlorinator) this.header[1] = val; }
|
|
820
|
+
public set sub(val: number) { if (this.protocol !== Protocol.Chlorinator && this.protocol !== Protocol.AquaLink) this.header[1] = val; }
|
|
557
821
|
public get sub() { return super.sub; }
|
|
558
|
-
public set dest(val: number) {
|
|
822
|
+
public set dest(val: number) {
|
|
823
|
+
if (this.protocol === Protocol.Chlorinator) this.header[2] = val;
|
|
824
|
+
else if (this.protocol === Protocol.Hayward) this.header[4] = val;
|
|
825
|
+
else this.header[2] = val;
|
|
826
|
+
}
|
|
559
827
|
public get dest() { return super.dest; }
|
|
560
|
-
public set source(val: number) {
|
|
828
|
+
public set source(val: number) {
|
|
829
|
+
switch (this.protocol) {
|
|
830
|
+
case Protocol.Chlorinator:
|
|
831
|
+
break;
|
|
832
|
+
case Protocol.Hayward:
|
|
833
|
+
this.header[3] = val;
|
|
834
|
+
break;
|
|
835
|
+
default:
|
|
836
|
+
this.header[3] = val;
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
//if (this.protocol === Protocol.Hayward) this.header[2] = val;
|
|
840
|
+
//else if (this.protocol !== Protocol.Chlorinator) this.header[3] = val;
|
|
841
|
+
}
|
|
561
842
|
public get source() { return super.source; }
|
|
562
|
-
public set action(val: number) {
|
|
843
|
+
public set action(val: number) {
|
|
844
|
+
switch (this.protocol) {
|
|
845
|
+
case Protocol.Chlorinator:
|
|
846
|
+
this.header[3] = val;
|
|
847
|
+
break;
|
|
848
|
+
case Protocol.Hayward:
|
|
849
|
+
this.header[2] = val;
|
|
850
|
+
break;
|
|
851
|
+
default:
|
|
852
|
+
this.header[4] = val;
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
563
856
|
public get action() { return super.action; }
|
|
564
|
-
public set datalen(val: number) { if (this.protocol !== Protocol.Chlorinator) this.header[5] = val; }
|
|
857
|
+
public set datalen(val: number) { if (this.protocol !== Protocol.Chlorinator && this.protocol !== Protocol.Hayward) this.header[5] = val; }
|
|
565
858
|
public get datalen() { return super.datalen; }
|
|
566
859
|
public set chkHi(val: number) { if (this.protocol !== Protocol.Chlorinator) this.term[0] = val; }
|
|
567
860
|
public get chkHi() { return super.chkHi; }
|
|
@@ -578,11 +871,13 @@ class OutboundCommon extends Message {
|
|
|
578
871
|
case Protocol.Unidentified:
|
|
579
872
|
case Protocol.IntelliChem:
|
|
580
873
|
case Protocol.Heater:
|
|
874
|
+
case Protocol.Hayward:
|
|
581
875
|
this.chkHi = Math.floor(sum / 256);
|
|
582
876
|
this.chkLo = (sum - (super.chkHi * 256));
|
|
583
877
|
break;
|
|
878
|
+
case Protocol.AquaLink:
|
|
584
879
|
case Protocol.Chlorinator:
|
|
585
|
-
this.term[0] = sum;
|
|
880
|
+
this.term[0] = sum % 256;
|
|
586
881
|
break;
|
|
587
882
|
}
|
|
588
883
|
}
|
|
@@ -598,7 +893,7 @@ export class Outbound extends OutboundCommon {
|
|
|
598
893
|
this.header.length = 0;
|
|
599
894
|
this.term.length = 0;
|
|
600
895
|
this.payload.length = 0;
|
|
601
|
-
if (proto === Protocol.Chlorinator) {
|
|
896
|
+
if (proto === Protocol.Chlorinator || proto === Protocol.AquaLink) {
|
|
602
897
|
this.header.push.apply(this.header, [16, 2, 0, 0]);
|
|
603
898
|
this.term.push.apply(this.term, [0, 16, 3]);
|
|
604
899
|
}
|
|
@@ -612,6 +907,10 @@ export class Outbound extends OutboundCommon {
|
|
|
612
907
|
this.header.push.apply(this.header, [165, 0, 15, Message.pluginAddress, 0, 0]);
|
|
613
908
|
this.term.push.apply(this.term, [0, 0]);
|
|
614
909
|
}
|
|
910
|
+
else if (proto === Protocol.Hayward) {
|
|
911
|
+
this.header.push.apply(this.header, [16, 2, 0, 0, 0]);
|
|
912
|
+
this.term.push.apply(this.term, [0, 0, 16, 3]);
|
|
913
|
+
}
|
|
615
914
|
this.scope = scope;
|
|
616
915
|
this.source = source;
|
|
617
916
|
this.dest = dest;
|
|
@@ -625,8 +924,19 @@ export class Outbound extends OutboundCommon {
|
|
|
625
924
|
}
|
|
626
925
|
// Factory
|
|
627
926
|
public static create(obj?: any) {
|
|
628
|
-
let
|
|
629
|
-
|
|
927
|
+
let o = extend({
|
|
928
|
+
protocol: Protocol.Broadcast,
|
|
929
|
+
source: sys.board.commandSourceAddress || Message.pluginAddress,
|
|
930
|
+
dest: sys.board.commandDestAddress || 16,
|
|
931
|
+
action: 0,
|
|
932
|
+
payload: [],
|
|
933
|
+
retries: 0,
|
|
934
|
+
response: false,
|
|
935
|
+
}, obj, true);
|
|
936
|
+
let out = new Outbound(o.protocol, o.source, o.dest, o.action, o.payload, o.retries, o.response, o.scope);
|
|
937
|
+
//let out = new Outbound(obj.protocol || Protocol.Broadcast,
|
|
938
|
+
// obj.source || sys.board.commandSourceAddress || Message.pluginAddress, obj.dest || sys.board.commandDestAddress || 16, obj.action || 0, obj.payload || [], obj.retries || 0, obj.response || false, obj.scope || undefined);
|
|
939
|
+
out.portId = obj.portId || 0;
|
|
630
940
|
out.onComplete = obj.onComplete;
|
|
631
941
|
out.onAbort = obj.onAbort;
|
|
632
942
|
out.timeout = obj.timeout;
|
|
@@ -643,7 +953,9 @@ export class Outbound extends OutboundCommon {
|
|
|
643
953
|
public static createMessage(action: number, payload: number[], retries?: number, response?: Response | boolean): Outbound {
|
|
644
954
|
return new Outbound(Protocol.Broadcast, sys.board.commandSourceAddress || Message.pluginAddress, sys.board.commandDestAddress || 16, action, payload, retries, response);
|
|
645
955
|
}
|
|
646
|
-
|
|
956
|
+
public async sendAsync() {
|
|
957
|
+
return conn.queueSendMessageAsync(this);
|
|
958
|
+
}
|
|
647
959
|
// Fields
|
|
648
960
|
public retries: number = 0;
|
|
649
961
|
public tries: number = 0;
|
|
@@ -659,7 +971,6 @@ export class Outbound extends OutboundCommon {
|
|
|
659
971
|
return false;
|
|
660
972
|
}
|
|
661
973
|
public get remainingTries(): number { return this.retries - this.tries + 1; } // Always allow 1 try.
|
|
662
|
-
|
|
663
974
|
public setPayloadByte(ndx: number, value: number, def?: number) {
|
|
664
975
|
if (typeof value === 'undefined' || isNaN(value)) value = def;
|
|
665
976
|
if (ndx < this.payload.length) this.payload[ndx] = value;
|
|
@@ -737,11 +1048,11 @@ export class Outbound extends OutboundCommon {
|
|
|
737
1048
|
if (typeof s === 'undefined') s = def;
|
|
738
1049
|
let l = typeof len === 'undefined' ? s.length : len;
|
|
739
1050
|
let buf = [];
|
|
740
|
-
for (let i = 0; i < l;
|
|
741
|
-
if (i <
|
|
742
|
-
else buf.push(
|
|
1051
|
+
for (let i = 0; i < l; i++) {
|
|
1052
|
+
if (i < s.length) buf.push(s.charCodeAt(i));
|
|
1053
|
+
else buf.push(0);
|
|
743
1054
|
}
|
|
744
|
-
this.payload.splice(start,
|
|
1055
|
+
this.payload.splice(start, l, ...buf);
|
|
745
1056
|
return this;
|
|
746
1057
|
}
|
|
747
1058
|
public toPacket(): number[] {
|
|
@@ -754,6 +1065,20 @@ export class Outbound extends OutboundCommon {
|
|
|
754
1065
|
pkt.push.apply(pkt, this.term);
|
|
755
1066
|
return pkt;
|
|
756
1067
|
}
|
|
1068
|
+
public processMock(){
|
|
1069
|
+
// When the port is a mock port, we are no longer sending an
|
|
1070
|
+
// outbound message but converting it to an inbound and
|
|
1071
|
+
// skipping the actual send/receive part of the comms.
|
|
1072
|
+
let inbound = Message.convertOutboundToInbound(this);
|
|
1073
|
+
let port = conn.findPortById(this.portId);
|
|
1074
|
+
if (port.hasAssignedEquipment() || this.portId === sys.anslq25.portId){
|
|
1075
|
+
MessagesMock.process(inbound);
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
inbound.process();
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
}
|
|
757
1082
|
}
|
|
758
1083
|
export class Ack extends Outbound {
|
|
759
1084
|
constructor(byte: number) {
|
|
@@ -805,7 +1130,10 @@ export class Response extends OutboundCommon {
|
|
|
805
1130
|
try {
|
|
806
1131
|
if (typeof this.responseBool === 'boolean' && this.responseBool) bresp = this.evalResponse(msgIn, msgOut);
|
|
807
1132
|
else return bresp;
|
|
808
|
-
if (bresp === true && typeof msgOut !== 'undefined')
|
|
1133
|
+
if (bresp === true && typeof msgOut !== 'undefined') {
|
|
1134
|
+
msgIn.responseFor.push(msgOut.id);
|
|
1135
|
+
logger.silly(`Message in ${msgIn.id} is a response for message out ${msgOut.id}`);
|
|
1136
|
+
}
|
|
809
1137
|
return bresp;
|
|
810
1138
|
}
|
|
811
1139
|
catch (err) { }
|