homebridge-adt-pulse 3.0.0-beta.3 → 3.0.0-beta.5
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/build/config.schema.json +237 -0
- package/build/src/index.js +6 -0
- package/build/src/index.js.map +1 -0
- package/build/src/lib/accessory.js +216 -0
- package/build/src/lib/accessory.js.map +1 -0
- package/build/src/lib/api.js +1876 -0
- package/build/src/lib/api.js.map +1 -0
- package/build/src/lib/detect.js +443 -0
- package/build/src/lib/detect.js.map +1 -0
- package/build/src/lib/platform.js +419 -0
- package/build/src/lib/platform.js.map +1 -0
- package/{src/lib/regex.ts → build/src/lib/regex.js} +1 -143
- package/build/src/lib/regex.js.map +1 -0
- package/build/src/lib/schema.js +29 -0
- package/build/src/lib/schema.js.map +1 -0
- package/build/src/lib/utility.js +434 -0
- package/build/src/lib/utility.js.map +1 -0
- package/build/src/scripts/repl.js +173 -0
- package/build/src/scripts/repl.js.map +1 -0
- package/build/src/scripts/test-api.js +171 -0
- package/build/src/scripts/test-api.js.map +1 -0
- package/package.json +4 -4
- package/src/index.ts +0 -18
- package/src/lib/accessory.ts +0 -405
- package/src/lib/api.ts +0 -3483
- package/src/lib/detect.ts +0 -728
- package/src/lib/platform.ts +0 -890
- package/src/lib/schema.ts +0 -34
- package/src/lib/utility.ts +0 -933
- package/src/scripts/repl.ts +0 -300
- package/src/scripts/test-api.ts +0 -278
- package/src/types/constant.d.ts +0 -308
- package/src/types/index.d.ts +0 -1472
- package/src/types/shared.d.ts +0 -517
|
@@ -0,0 +1,1876 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { wrapper } from 'axios-cookiejar-support';
|
|
3
|
+
import { JSDOM } from 'jsdom';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { serializeError } from 'serialize-error';
|
|
6
|
+
import { CookieJar } from 'tough-cookie';
|
|
7
|
+
import { detectedNewDoSubmitHandlers, detectedNewGatewayInformation, detectedNewOrbSecurityButtons, detectedNewPanelInformation, detectedNewPanelStatus, detectedNewPortalVersion, detectedNewSensorsInformation, detectedNewSensorsStatus, } from './detect.js';
|
|
8
|
+
import { paramNetworkId, paramSat, requestPathAccessSignIn, requestPathAccessSignInENsPartnerAdt, requestPathAccessSignInNetworkIdXxPartnerAdt, requestPathAjaxSyncCheckServTXx, requestPathKeepAlive, requestPathMfaMfaSignInWorkflowChallenge, requestPathQuickControlArmDisarm, requestPathQuickControlServRunRraCommand, requestPathSummarySummary, requestPathSystemDeviceId1, requestPathSystemGateway, requestPathSystemSystem, textPanelEmergencyKeys, } from './regex.js';
|
|
9
|
+
import { debugLog, fetchErrorMessage, fetchMissingSatCode, fetchTableCells, findNullKeys, generateDynatracePCHeaderValue, generateHash, isPortalSyncCode, parseArmDisarmMessage, parseDoSubmitHandlers, parseOrbSecurityButtons, parseOrbSensors, parseOrbTextSummary, parseSensorsTable, sleep, stackTracer, } from './utility.js';
|
|
10
|
+
export class ADTPulse {
|
|
11
|
+
#credentials;
|
|
12
|
+
#internal;
|
|
13
|
+
#session;
|
|
14
|
+
constructor(config, internalConfig) {
|
|
15
|
+
this.#credentials = {
|
|
16
|
+
fingerprint: config.fingerprint,
|
|
17
|
+
password: config.password,
|
|
18
|
+
subdomain: config.subdomain,
|
|
19
|
+
username: config.username,
|
|
20
|
+
};
|
|
21
|
+
this.#internal = {
|
|
22
|
+
baseUrl: internalConfig.baseUrl ?? `https://${this.#credentials.subdomain}.adtpulse.com`,
|
|
23
|
+
debug: internalConfig.debug ?? false,
|
|
24
|
+
logger: internalConfig.logger ?? null,
|
|
25
|
+
reportedHashes: [],
|
|
26
|
+
testMode: {
|
|
27
|
+
enabled: internalConfig.testMode?.enabled ?? false,
|
|
28
|
+
isDisarmChecked: internalConfig.testMode?.isDisarmChecked ?? false,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
this.#session = {
|
|
32
|
+
backupSatCode: null,
|
|
33
|
+
httpClient: wrapper(axios.create({
|
|
34
|
+
jar: new CookieJar(),
|
|
35
|
+
})),
|
|
36
|
+
isAuthenticated: false,
|
|
37
|
+
isCleanState: true,
|
|
38
|
+
networkId: null,
|
|
39
|
+
portalVersion: null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async login() {
|
|
43
|
+
let errorObject;
|
|
44
|
+
if (this.#internal.debug) {
|
|
45
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Attempting to login to "${this.#internal.baseUrl}"`);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const internet = await this.isPortalAccessible();
|
|
49
|
+
const sessions = {};
|
|
50
|
+
if (!internet.success) {
|
|
51
|
+
return {
|
|
52
|
+
action: 'LOGIN',
|
|
53
|
+
success: false,
|
|
54
|
+
info: internet.info,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (this.isAuthenticated()) {
|
|
58
|
+
if (this.#internal.debug) {
|
|
59
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', [
|
|
60
|
+
'Already logged in',
|
|
61
|
+
[
|
|
62
|
+
'(',
|
|
63
|
+
[
|
|
64
|
+
`backup sat code: ${this.#session.backupSatCode}`,
|
|
65
|
+
`network id: ${this.#session.networkId}`,
|
|
66
|
+
`portal version: ${this.#session.portalVersion}`,
|
|
67
|
+
].join(', '),
|
|
68
|
+
')',
|
|
69
|
+
].join(''),
|
|
70
|
+
].join(' '));
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
action: 'LOGIN',
|
|
74
|
+
success: true,
|
|
75
|
+
info: {
|
|
76
|
+
backupSatCode: this.#session.backupSatCode,
|
|
77
|
+
networkId: this.#session.networkId,
|
|
78
|
+
portalVersion: this.#session.portalVersion,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
sessions.axiosIndex = await this.#session.httpClient.get(`${this.#internal.baseUrl}/`, this.getRequestConfig());
|
|
83
|
+
if (typeof sessions.axiosIndex?.request === 'undefined') {
|
|
84
|
+
if (this.#internal.debug) {
|
|
85
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', 'The HTTP client responded without the "request" object');
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
action: 'LOGIN',
|
|
89
|
+
success: false,
|
|
90
|
+
info: {
|
|
91
|
+
message: 'The HTTP client responded without the "request" object',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const axiosIndexRequestPath = sessions.axiosIndex.request.path;
|
|
96
|
+
const axiosIndexRequestPathValid = requestPathAccessSignIn.test(axiosIndexRequestPath);
|
|
97
|
+
if (this.#internal.debug) {
|
|
98
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Request path ➜ ${axiosIndexRequestPath}`);
|
|
99
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Request path valid ➜ ${axiosIndexRequestPathValid}`);
|
|
100
|
+
}
|
|
101
|
+
if (!axiosIndexRequestPathValid) {
|
|
102
|
+
if (this.#internal.debug) {
|
|
103
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', `"${axiosIndexRequestPath} is not the sign-in page`);
|
|
104
|
+
}
|
|
105
|
+
this.handleLoginFailure(axiosIndexRequestPath, sessions.axiosIndex);
|
|
106
|
+
return {
|
|
107
|
+
action: 'LOGIN',
|
|
108
|
+
success: false,
|
|
109
|
+
info: {
|
|
110
|
+
message: `"${axiosIndexRequestPath} is not the sign-in page`,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const loginForm = new URLSearchParams();
|
|
115
|
+
loginForm.append('usernameForm', this.#credentials.username);
|
|
116
|
+
loginForm.append('passwordForm', this.#credentials.password);
|
|
117
|
+
loginForm.append('sun', 'yes');
|
|
118
|
+
loginForm.append('networkid', '');
|
|
119
|
+
loginForm.append('fingerprint', this.#credentials.fingerprint);
|
|
120
|
+
this.#session.portalVersion = axiosIndexRequestPath.replace(requestPathAccessSignIn, '$2');
|
|
121
|
+
await this.newInformationDispatcher('portal-version', { version: this.#session.portalVersion });
|
|
122
|
+
sessions.axiosSignin = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/signin.jsp?e=ns&partner=adt`, loginForm, this.getRequestConfig({
|
|
123
|
+
headers: {
|
|
124
|
+
'Cache-Control': 'max-age=0',
|
|
125
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
126
|
+
Origin: this.#internal.baseUrl,
|
|
127
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/signin.jsp?e=ns&partner=adt`,
|
|
128
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
129
|
+
},
|
|
130
|
+
}));
|
|
131
|
+
if (typeof sessions.axiosSignin?.request === 'undefined') {
|
|
132
|
+
if (this.#internal.debug) {
|
|
133
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', 'The HTTP client responded without the "request" object');
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
action: 'LOGIN',
|
|
137
|
+
success: false,
|
|
138
|
+
info: {
|
|
139
|
+
message: 'The HTTP client responded without the "request" object',
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const axiosSigninRequestPath = sessions.axiosSignin.request.path;
|
|
144
|
+
const axiosSigninRequestPathValid = requestPathSummarySummary.test(axiosSigninRequestPath);
|
|
145
|
+
if (this.#internal.debug) {
|
|
146
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Request path ➜ ${axiosSigninRequestPath}`);
|
|
147
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Request path valid ➜ ${axiosSigninRequestPathValid}`);
|
|
148
|
+
}
|
|
149
|
+
if (!axiosSigninRequestPathValid) {
|
|
150
|
+
if (this.#internal.debug) {
|
|
151
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', `"${axiosSigninRequestPath}" is not the summary page`);
|
|
152
|
+
}
|
|
153
|
+
this.handleLoginFailure(axiosSigninRequestPath, sessions.axiosSignin);
|
|
154
|
+
return {
|
|
155
|
+
action: 'LOGIN',
|
|
156
|
+
success: false,
|
|
157
|
+
info: {
|
|
158
|
+
message: `"${axiosSigninRequestPath}" is not the summary page`,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (typeof sessions.axiosSignin.data !== 'string') {
|
|
163
|
+
if (this.#internal.debug) {
|
|
164
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', 'The response body of the summary page is not of type "string"');
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
action: 'LOGIN',
|
|
168
|
+
success: false,
|
|
169
|
+
info: {
|
|
170
|
+
message: 'The response body of the summary page is not of type "string"',
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const matchNetworkId = sessions.axiosSignin.data.match(paramNetworkId);
|
|
175
|
+
this.#session.networkId = (matchNetworkId !== null && matchNetworkId.length >= 2) ? matchNetworkId[1] : null;
|
|
176
|
+
const matchSatCode = sessions.axiosSignin.data.match(paramSat);
|
|
177
|
+
this.#session.backupSatCode = (matchSatCode !== null && matchSatCode.length >= 2) ? matchSatCode[1] : null;
|
|
178
|
+
if (this.#session.backupSatCode === null && this.#internal.debug) {
|
|
179
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'warn', 'Unable to backup sat code, will try again when system becomes available');
|
|
180
|
+
}
|
|
181
|
+
this.#session.isAuthenticated = true;
|
|
182
|
+
if (this.#internal.debug) {
|
|
183
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'success', [
|
|
184
|
+
'Login successful',
|
|
185
|
+
[
|
|
186
|
+
'(',
|
|
187
|
+
[
|
|
188
|
+
`backup sat code: ${this.#session.backupSatCode}`,
|
|
189
|
+
`network id: ${this.#session.networkId}`,
|
|
190
|
+
`portal version: ${this.#session.portalVersion}`,
|
|
191
|
+
].join(', '),
|
|
192
|
+
')',
|
|
193
|
+
].join(''),
|
|
194
|
+
].join(' '));
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
action: 'LOGIN',
|
|
198
|
+
success: true,
|
|
199
|
+
info: {
|
|
200
|
+
backupSatCode: this.#session.backupSatCode,
|
|
201
|
+
networkId: this.#session.networkId,
|
|
202
|
+
portalVersion: this.#session.portalVersion,
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
errorObject = serializeError(error);
|
|
208
|
+
}
|
|
209
|
+
if (this.#internal.debug) {
|
|
210
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'error', 'Method encountered an error during execution');
|
|
211
|
+
stackTracer('serialize-error', errorObject);
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
action: 'LOGIN',
|
|
215
|
+
success: false,
|
|
216
|
+
info: {
|
|
217
|
+
error: errorObject,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
async logout() {
|
|
222
|
+
let errorObject;
|
|
223
|
+
if (this.#internal.debug) {
|
|
224
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', `Attempting to logout of "${this.#internal.baseUrl}"`);
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
const internet = await this.isPortalAccessible();
|
|
228
|
+
const sessions = {};
|
|
229
|
+
if (!internet.success) {
|
|
230
|
+
return {
|
|
231
|
+
action: 'LOGOUT',
|
|
232
|
+
success: false,
|
|
233
|
+
info: internet.info,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (!this.isAuthenticated()) {
|
|
237
|
+
if (this.#internal.debug) {
|
|
238
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', [
|
|
239
|
+
'Already logged out',
|
|
240
|
+
[
|
|
241
|
+
'(',
|
|
242
|
+
[
|
|
243
|
+
`backup sat code: ${this.#session.backupSatCode}`,
|
|
244
|
+
`network id: ${this.#session.networkId}`,
|
|
245
|
+
`portal version: ${this.#session.portalVersion}`,
|
|
246
|
+
].join(', '),
|
|
247
|
+
')',
|
|
248
|
+
].join(''),
|
|
249
|
+
].join(' '));
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
action: 'LOGOUT',
|
|
253
|
+
success: true,
|
|
254
|
+
info: {
|
|
255
|
+
backupSatCode: this.#session.backupSatCode,
|
|
256
|
+
networkId: this.#session.networkId,
|
|
257
|
+
portalVersion: this.#session.portalVersion,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
sessions.axiosSignout = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/signout.jsp?networkid=${this.#session.networkId}&partner=adt`, this.getRequestConfig({
|
|
262
|
+
headers: {
|
|
263
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
264
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
265
|
+
},
|
|
266
|
+
}));
|
|
267
|
+
if (typeof sessions.axiosSignout?.request === 'undefined') {
|
|
268
|
+
if (this.#internal.debug) {
|
|
269
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'error', 'The HTTP client responded without the "request" object');
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
action: 'LOGOUT',
|
|
273
|
+
success: false,
|
|
274
|
+
info: {
|
|
275
|
+
message: 'The HTTP client responded without the "request" object',
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
const axiosSignoutRequestPath = sessions.axiosSignout.request.path;
|
|
280
|
+
const axiosSignoutRequestPathValid = requestPathAccessSignInNetworkIdXxPartnerAdt.test(axiosSignoutRequestPath);
|
|
281
|
+
if (this.#internal.debug) {
|
|
282
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', `Request path ➜ ${axiosSignoutRequestPath}`);
|
|
283
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', `Request path valid ➜ ${axiosSignoutRequestPathValid}`);
|
|
284
|
+
}
|
|
285
|
+
if (!axiosSignoutRequestPathValid) {
|
|
286
|
+
if (this.#internal.debug) {
|
|
287
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'error', `"${axiosSignoutRequestPath}" is not the sign-in page with "networkid" and "partner=adt" parameters`);
|
|
288
|
+
}
|
|
289
|
+
this.handleLoginFailure(axiosSignoutRequestPath, sessions.axiosSignout);
|
|
290
|
+
return {
|
|
291
|
+
action: 'LOGOUT',
|
|
292
|
+
success: false,
|
|
293
|
+
info: {
|
|
294
|
+
message: `"${axiosSignoutRequestPath}" is not the sign-in page with "networkid" and "partner=adt" parameters`,
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
this.resetSession();
|
|
299
|
+
if (this.#internal.debug) {
|
|
300
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'success', [
|
|
301
|
+
'Logout successful',
|
|
302
|
+
[
|
|
303
|
+
'(',
|
|
304
|
+
[
|
|
305
|
+
`backup sat code: ${this.#session.backupSatCode}`,
|
|
306
|
+
`network id: ${this.#session.networkId}`,
|
|
307
|
+
`portal version: ${this.#session.portalVersion}`,
|
|
308
|
+
].join(', '),
|
|
309
|
+
')',
|
|
310
|
+
].join(''),
|
|
311
|
+
].join(' '));
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
action: 'LOGOUT',
|
|
315
|
+
success: true,
|
|
316
|
+
info: {
|
|
317
|
+
backupSatCode: this.#session.backupSatCode,
|
|
318
|
+
networkId: this.#session.networkId,
|
|
319
|
+
portalVersion: this.#session.portalVersion,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
errorObject = serializeError(error);
|
|
325
|
+
}
|
|
326
|
+
if (this.#internal.debug) {
|
|
327
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'error', 'Method encountered an error during execution');
|
|
328
|
+
stackTracer('serialize-error', errorObject);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
action: 'LOGOUT',
|
|
332
|
+
success: false,
|
|
333
|
+
info: {
|
|
334
|
+
error: errorObject,
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async getGatewayInformation() {
|
|
339
|
+
let errorObject;
|
|
340
|
+
if (this.#internal.debug) {
|
|
341
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'info', `Attempting to retrieve gateway information from "${this.#internal.baseUrl}"`);
|
|
342
|
+
}
|
|
343
|
+
try {
|
|
344
|
+
const internet = await this.isPortalAccessible();
|
|
345
|
+
const sessions = {};
|
|
346
|
+
if (!internet.success) {
|
|
347
|
+
return {
|
|
348
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
349
|
+
success: false,
|
|
350
|
+
info: internet.info,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
sessions.axiosSystemGateway = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/gateway.jsp`, this.getRequestConfig({
|
|
354
|
+
headers: {
|
|
355
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`,
|
|
356
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
357
|
+
'Sec-Fetch-User': undefined,
|
|
358
|
+
},
|
|
359
|
+
}));
|
|
360
|
+
if (typeof sessions.axiosSystemGateway?.request === 'undefined') {
|
|
361
|
+
if (this.#internal.debug) {
|
|
362
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'error', 'The HTTP client responded without the "request" object');
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
366
|
+
success: false,
|
|
367
|
+
info: {
|
|
368
|
+
message: 'The HTTP client responded without the "request" object',
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
const axiosSystemGatewayRequestPath = sessions.axiosSystemGateway.request.path;
|
|
373
|
+
const axiosSystemGatewayRequestPathValid = requestPathSystemGateway.test(axiosSystemGatewayRequestPath);
|
|
374
|
+
if (this.#internal.debug) {
|
|
375
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'info', `Request path ➜ ${axiosSystemGatewayRequestPath}`);
|
|
376
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'info', `Request path valid ➜ ${axiosSystemGatewayRequestPathValid}`);
|
|
377
|
+
}
|
|
378
|
+
if (!axiosSystemGatewayRequestPathValid) {
|
|
379
|
+
if (this.#internal.debug) {
|
|
380
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'error', `"${axiosSystemGatewayRequestPath}" is not the system gateway page`);
|
|
381
|
+
}
|
|
382
|
+
this.handleLoginFailure(axiosSystemGatewayRequestPath, sessions.axiosSystemGateway);
|
|
383
|
+
return {
|
|
384
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
385
|
+
success: false,
|
|
386
|
+
info: {
|
|
387
|
+
message: `"${axiosSystemGatewayRequestPath}" is not the system gateway page`,
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
if (typeof sessions.axiosSystemGateway.data !== 'string') {
|
|
392
|
+
if (this.#internal.debug) {
|
|
393
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'error', 'The response body of the system gateway page is not of type "string"');
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
397
|
+
success: false,
|
|
398
|
+
info: {
|
|
399
|
+
message: 'The response body of the system gateway page is not of type "string"',
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
sessions.jsdomSystemGateway = new JSDOM(sessions.axiosSystemGateway.data, {
|
|
404
|
+
url: sessions.axiosSystemGateway.config.url,
|
|
405
|
+
referrer: sessions.axiosSystemGateway.config.headers.Referer,
|
|
406
|
+
contentType: 'text/html',
|
|
407
|
+
pretendToBeVisual: true,
|
|
408
|
+
});
|
|
409
|
+
const jsdomSystemGatewayTableCells = sessions.jsdomSystemGateway.window.document.querySelectorAll('td');
|
|
410
|
+
const fetchedTableCells = fetchTableCells(jsdomSystemGatewayTableCells, [
|
|
411
|
+
'Broadband Connection Status:',
|
|
412
|
+
'Broadband LAN IP Address:',
|
|
413
|
+
'Broadband LAN MAC:',
|
|
414
|
+
'Cellular Connection Status:',
|
|
415
|
+
'Cellular Signal Strength:',
|
|
416
|
+
'Device LAN IP Address:',
|
|
417
|
+
'Device LAN MAC:',
|
|
418
|
+
'Firmware Version:',
|
|
419
|
+
'Hardware Version:',
|
|
420
|
+
'Last Update:',
|
|
421
|
+
'Manufacturer:',
|
|
422
|
+
'Model:',
|
|
423
|
+
'Next Update:',
|
|
424
|
+
'Primary Connection Type:',
|
|
425
|
+
'Router LAN IP Address:',
|
|
426
|
+
'Router WAN IP Address:',
|
|
427
|
+
'Serial Number:',
|
|
428
|
+
'Status:',
|
|
429
|
+
], 1, 1);
|
|
430
|
+
const gatewayInformation = {
|
|
431
|
+
communication: {
|
|
432
|
+
primaryConnectionType: _.get(fetchedTableCells, ['Primary Connection Type:', 0], null),
|
|
433
|
+
broadbandConnectionStatus: _.get(fetchedTableCells, ['Broadband Connection Status:', 0], null),
|
|
434
|
+
cellularConnectionStatus: _.get(fetchedTableCells, ['Cellular Connection Status:', 0], null),
|
|
435
|
+
cellularSignalStrength: _.get(fetchedTableCells, ['Cellular Signal Strength:', 0], null),
|
|
436
|
+
},
|
|
437
|
+
manufacturer: _.get(fetchedTableCells, ['Manufacturer:', 0], null),
|
|
438
|
+
model: _.get(fetchedTableCells, ['Model:', 0], null),
|
|
439
|
+
network: {
|
|
440
|
+
broadband: {
|
|
441
|
+
ip: _.get(fetchedTableCells, ['Broadband LAN IP Address:', 0], null),
|
|
442
|
+
mac: _.get(fetchedTableCells, ['Broadband LAN MAC:', 0], null),
|
|
443
|
+
},
|
|
444
|
+
device: {
|
|
445
|
+
ip: _.get(fetchedTableCells, ['Device LAN IP Address:', 0], null),
|
|
446
|
+
mac: _.get(fetchedTableCells, ['Device LAN MAC:', 0], null),
|
|
447
|
+
},
|
|
448
|
+
router: {
|
|
449
|
+
lanIp: _.get(fetchedTableCells, ['Router LAN IP Address:', 0], null),
|
|
450
|
+
wanIp: _.get(fetchedTableCells, ['Router WAN IP Address:', 0], null),
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
serialNumber: _.get(fetchedTableCells, ['Serial Number:', 0], null),
|
|
454
|
+
status: _.get(fetchedTableCells, ['Status:', 0], null),
|
|
455
|
+
update: {
|
|
456
|
+
last: _.get(fetchedTableCells, ['Last Update:', 0], null),
|
|
457
|
+
next: _.get(fetchedTableCells, ['Next Update:', 0], null),
|
|
458
|
+
},
|
|
459
|
+
versions: {
|
|
460
|
+
firmware: _.get(fetchedTableCells, ['Firmware Version:', 0], null),
|
|
461
|
+
hardware: _.get(fetchedTableCells, ['Hardware Version:', 0], null),
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
await this.newInformationDispatcher('gateway-information', gatewayInformation);
|
|
465
|
+
if (this.#internal.debug) {
|
|
466
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'success', `Successfully retrieved gateway information from "${this.#internal.baseUrl}"`);
|
|
467
|
+
}
|
|
468
|
+
return {
|
|
469
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
470
|
+
success: true,
|
|
471
|
+
info: gatewayInformation,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
errorObject = serializeError(error);
|
|
476
|
+
}
|
|
477
|
+
if (this.#internal.debug) {
|
|
478
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'error', 'Method encountered an error during execution');
|
|
479
|
+
stackTracer('serialize-error', errorObject);
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
action: 'GET_GATEWAY_INFORMATION',
|
|
483
|
+
success: false,
|
|
484
|
+
info: {
|
|
485
|
+
error: errorObject,
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
async getPanelInformation() {
|
|
490
|
+
let errorObject;
|
|
491
|
+
if (this.#internal.debug) {
|
|
492
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'info', `Attempting to retrieve panel information from "${this.#internal.baseUrl}"`);
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
const internet = await this.isPortalAccessible();
|
|
496
|
+
const sessions = {};
|
|
497
|
+
if (!internet.success) {
|
|
498
|
+
return {
|
|
499
|
+
action: 'GET_PANEL_INFORMATION',
|
|
500
|
+
success: false,
|
|
501
|
+
info: internet.info,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
sessions.axiosSystemDeviceId1 = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/device.jsp?id=1`, this.getRequestConfig({
|
|
505
|
+
headers: {
|
|
506
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`,
|
|
507
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
508
|
+
},
|
|
509
|
+
}));
|
|
510
|
+
if (typeof sessions.axiosSystemDeviceId1?.request === 'undefined') {
|
|
511
|
+
if (this.#internal.debug) {
|
|
512
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'error', 'The HTTP client responded without the "request" object');
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
action: 'GET_PANEL_INFORMATION',
|
|
516
|
+
success: false,
|
|
517
|
+
info: {
|
|
518
|
+
message: 'The HTTP client responded without the "request" object',
|
|
519
|
+
},
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
const axiosSystemDeviceId1RequestPath = sessions.axiosSystemDeviceId1.request.path;
|
|
523
|
+
const axiosSystemDeviceId1RequestPathValid = requestPathSystemDeviceId1.test(axiosSystemDeviceId1RequestPath);
|
|
524
|
+
if (this.#internal.debug) {
|
|
525
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'info', `Request path ➜ ${axiosSystemDeviceId1RequestPath}`);
|
|
526
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'info', `Request path valid ➜ ${axiosSystemDeviceId1RequestPathValid}`);
|
|
527
|
+
}
|
|
528
|
+
if (!axiosSystemDeviceId1RequestPathValid) {
|
|
529
|
+
if (this.#internal.debug) {
|
|
530
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'error', `"${axiosSystemDeviceId1RequestPath}" is not the system device id 1 page`);
|
|
531
|
+
}
|
|
532
|
+
this.handleLoginFailure(axiosSystemDeviceId1RequestPath, sessions.axiosSystemDeviceId1);
|
|
533
|
+
return {
|
|
534
|
+
action: 'GET_PANEL_INFORMATION',
|
|
535
|
+
success: false,
|
|
536
|
+
info: {
|
|
537
|
+
message: `"${axiosSystemDeviceId1RequestPath}" is not the system device id 1 page`,
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
if (typeof sessions.axiosSystemDeviceId1.data !== 'string') {
|
|
542
|
+
if (this.#internal.debug) {
|
|
543
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'error', 'The response body of the system device id 1 page is not of type "string"');
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
action: 'GET_PANEL_INFORMATION',
|
|
547
|
+
success: false,
|
|
548
|
+
info: {
|
|
549
|
+
message: 'The response body of the system device id 1 page is not of type "string"',
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
sessions.jsdomSystemDeviceId1 = new JSDOM(sessions.axiosSystemDeviceId1.data, {
|
|
554
|
+
url: sessions.axiosSystemDeviceId1.config.url,
|
|
555
|
+
referrer: sessions.axiosSystemDeviceId1.config.headers.Referer,
|
|
556
|
+
contentType: 'text/html',
|
|
557
|
+
pretendToBeVisual: true,
|
|
558
|
+
});
|
|
559
|
+
const jsdomSystemDeviceId1TableCells = sessions.jsdomSystemDeviceId1.window.document.querySelectorAll('td');
|
|
560
|
+
const fetchedTableCells = fetchTableCells(jsdomSystemDeviceId1TableCells, [
|
|
561
|
+
'Emergency Keys:',
|
|
562
|
+
'Manufacturer/Provider:',
|
|
563
|
+
'Security Panel Master Code:',
|
|
564
|
+
'Status:',
|
|
565
|
+
'Type/Model:',
|
|
566
|
+
], 1, 1);
|
|
567
|
+
const emergencyKeys = _.get(fetchedTableCells, ['Emergency Keys:', 0], null);
|
|
568
|
+
const parsedEmergencyKeys = (typeof emergencyKeys === 'string') ? emergencyKeys.match(textPanelEmergencyKeys) : null;
|
|
569
|
+
const manufacturerProvider = _.get(fetchedTableCells, ['Manufacturer/Provider:', 0], null);
|
|
570
|
+
const parsedManufacturer = (typeof manufacturerProvider === 'string') ? manufacturerProvider.split(' - ')[0] ?? null : null;
|
|
571
|
+
const parsedProvider = (typeof manufacturerProvider === 'string') ? manufacturerProvider.split(' - ')[1] ?? null : null;
|
|
572
|
+
const typeModel = _.get(fetchedTableCells, ['Type/Model:', 0], null);
|
|
573
|
+
const parsedType = (typeof typeModel === 'string') ? typeModel.split(' - ')[0] ?? null : null;
|
|
574
|
+
const parsedModel = (typeof typeModel === 'string') ? typeModel.split(' - ')[1] ?? null : null;
|
|
575
|
+
const panelInformation = {
|
|
576
|
+
emergencyKeys: parsedEmergencyKeys,
|
|
577
|
+
manufacturer: parsedManufacturer,
|
|
578
|
+
masterCode: _.get(fetchedTableCells, ['Security Panel Master Code:', 0], null),
|
|
579
|
+
provider: parsedProvider,
|
|
580
|
+
type: parsedType,
|
|
581
|
+
model: parsedModel,
|
|
582
|
+
status: _.get(fetchedTableCells, ['Status:', 0], null),
|
|
583
|
+
};
|
|
584
|
+
await this.newInformationDispatcher('panel-information', panelInformation);
|
|
585
|
+
if (this.#internal.debug) {
|
|
586
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'success', `Successfully retrieved panel information from "${this.#internal.baseUrl}"`);
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
action: 'GET_PANEL_INFORMATION',
|
|
590
|
+
success: true,
|
|
591
|
+
info: panelInformation,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
catch (error) {
|
|
595
|
+
errorObject = serializeError(error);
|
|
596
|
+
}
|
|
597
|
+
if (this.#internal.debug) {
|
|
598
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'error', 'Method encountered an error during execution');
|
|
599
|
+
stackTracer('serialize-error', errorObject);
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
action: 'GET_PANEL_INFORMATION',
|
|
603
|
+
success: false,
|
|
604
|
+
info: {
|
|
605
|
+
error: errorObject,
|
|
606
|
+
},
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
async getPanelStatus() {
|
|
610
|
+
let errorObject;
|
|
611
|
+
if (this.#internal.debug) {
|
|
612
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'info', `Attempting to retrieve panel status from "${this.#internal.baseUrl}"`);
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
const internet = await this.isPortalAccessible();
|
|
616
|
+
const sessions = {};
|
|
617
|
+
if (!internet.success) {
|
|
618
|
+
return {
|
|
619
|
+
action: 'GET_PANEL_STATUS',
|
|
620
|
+
success: false,
|
|
621
|
+
info: internet.info,
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
625
|
+
headers: {
|
|
626
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
627
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
628
|
+
},
|
|
629
|
+
}));
|
|
630
|
+
if (typeof sessions.axiosSummary?.request === 'undefined') {
|
|
631
|
+
if (this.#internal.debug) {
|
|
632
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'error', 'The HTTP client responded without the "request" object');
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
action: 'GET_PANEL_STATUS',
|
|
636
|
+
success: false,
|
|
637
|
+
info: {
|
|
638
|
+
message: 'The HTTP client responded without the "request" object',
|
|
639
|
+
},
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
const axiosSummaryRequestPath = sessions.axiosSummary.request.path;
|
|
643
|
+
const axiosSummaryRequestPathValid = requestPathSummarySummary.test(axiosSummaryRequestPath);
|
|
644
|
+
if (this.#internal.debug) {
|
|
645
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'info', `Request path ➜ ${axiosSummaryRequestPath}`);
|
|
646
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'info', `Request path valid ➜ ${axiosSummaryRequestPathValid}`);
|
|
647
|
+
}
|
|
648
|
+
if (!axiosSummaryRequestPathValid) {
|
|
649
|
+
if (this.#internal.debug) {
|
|
650
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'error', `"${axiosSummaryRequestPath}" is not the summary page`);
|
|
651
|
+
}
|
|
652
|
+
this.handleLoginFailure(axiosSummaryRequestPath, sessions.axiosSummary);
|
|
653
|
+
return {
|
|
654
|
+
action: 'GET_PANEL_STATUS',
|
|
655
|
+
success: false,
|
|
656
|
+
info: {
|
|
657
|
+
message: `"${axiosSummaryRequestPath}" is not the summary page`,
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
if (typeof sessions.axiosSummary.data !== 'string') {
|
|
662
|
+
if (this.#internal.debug) {
|
|
663
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'error', 'The response body of the summary page is not of type "string"');
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
action: 'GET_PANEL_STATUS',
|
|
667
|
+
success: false,
|
|
668
|
+
info: {
|
|
669
|
+
message: 'The response body of the summary page is not of type "string"',
|
|
670
|
+
},
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
if (this.#session.backupSatCode === null) {
|
|
674
|
+
const missingSatCode = fetchMissingSatCode(sessions.axiosSummary);
|
|
675
|
+
if (missingSatCode !== null) {
|
|
676
|
+
if (this.#internal.debug) {
|
|
677
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'success', 'Backup sat code was successfully recovered from previous failed retrieval');
|
|
678
|
+
}
|
|
679
|
+
this.#session.backupSatCode = missingSatCode;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
sessions.jsdomSummary = new JSDOM(sessions.axiosSummary.data, {
|
|
683
|
+
url: sessions.axiosSummary.config.url,
|
|
684
|
+
referrer: sessions.axiosSummary.config.headers.Referer,
|
|
685
|
+
contentType: 'text/html',
|
|
686
|
+
pretendToBeVisual: true,
|
|
687
|
+
});
|
|
688
|
+
const jsdomSummaryOrbTextSummary = sessions.jsdomSummary.window.document.querySelector('#divOrbTextSummary');
|
|
689
|
+
const parsedOrbTextSummary = parseOrbTextSummary(jsdomSummaryOrbTextSummary);
|
|
690
|
+
await this.newInformationDispatcher('panel-status', parsedOrbTextSummary);
|
|
691
|
+
if (this.#internal.debug) {
|
|
692
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'success', `Successfully retrieved panel status from "${this.#internal.baseUrl}"`);
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
action: 'GET_PANEL_STATUS',
|
|
696
|
+
success: true,
|
|
697
|
+
info: parsedOrbTextSummary,
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
errorObject = serializeError(error);
|
|
702
|
+
}
|
|
703
|
+
if (this.#internal.debug) {
|
|
704
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'error', 'Method encountered an error during execution');
|
|
705
|
+
stackTracer('serialize-error', errorObject);
|
|
706
|
+
}
|
|
707
|
+
return {
|
|
708
|
+
action: 'GET_PANEL_STATUS',
|
|
709
|
+
success: false,
|
|
710
|
+
info: {
|
|
711
|
+
error: errorObject,
|
|
712
|
+
},
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
async setPanelStatus(armTo) {
|
|
716
|
+
let errorObject;
|
|
717
|
+
if (this.#internal.debug) {
|
|
718
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'info', `Attempting to update panel status to "${armTo}" at "${this.#internal.baseUrl}"`);
|
|
719
|
+
}
|
|
720
|
+
if (armTo !== 'away'
|
|
721
|
+
&& armTo !== 'night'
|
|
722
|
+
&& armTo !== 'off'
|
|
723
|
+
&& armTo !== 'stay') {
|
|
724
|
+
return {
|
|
725
|
+
action: 'SET_PANEL_STATUS',
|
|
726
|
+
success: false,
|
|
727
|
+
info: {
|
|
728
|
+
message: `"${armTo}" is an invalid arm to state`,
|
|
729
|
+
},
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
try {
|
|
733
|
+
const internet = await this.isPortalAccessible();
|
|
734
|
+
const sessions = {};
|
|
735
|
+
if (!internet.success) {
|
|
736
|
+
return {
|
|
737
|
+
action: 'SET_PANEL_STATUS',
|
|
738
|
+
success: false,
|
|
739
|
+
info: internet.info,
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
743
|
+
headers: {
|
|
744
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
745
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
746
|
+
},
|
|
747
|
+
}));
|
|
748
|
+
if (typeof sessions.axiosSummary?.request === 'undefined') {
|
|
749
|
+
if (this.#internal.debug) {
|
|
750
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'The HTTP client responded without the "request" object');
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
action: 'SET_PANEL_STATUS',
|
|
754
|
+
success: false,
|
|
755
|
+
info: {
|
|
756
|
+
message: 'The HTTP client responded without the "request" object',
|
|
757
|
+
},
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
const axiosSummaryRequestPath = sessions.axiosSummary.request.path;
|
|
761
|
+
const axiosSummaryRequestPathValid = requestPathSummarySummary.test(axiosSummaryRequestPath);
|
|
762
|
+
if (this.#internal.debug) {
|
|
763
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'info', `Request path ➜ ${axiosSummaryRequestPath}`);
|
|
764
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'info', `Request path valid ➜ ${axiosSummaryRequestPathValid}`);
|
|
765
|
+
}
|
|
766
|
+
if (!axiosSummaryRequestPathValid) {
|
|
767
|
+
if (this.#internal.debug) {
|
|
768
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', `"${axiosSummaryRequestPath}" is not the summary page`);
|
|
769
|
+
}
|
|
770
|
+
this.handleLoginFailure(axiosSummaryRequestPath, sessions.axiosSummary);
|
|
771
|
+
return {
|
|
772
|
+
action: 'SET_PANEL_STATUS',
|
|
773
|
+
success: false,
|
|
774
|
+
info: {
|
|
775
|
+
message: `"${axiosSummaryRequestPath}" is not the summary page`,
|
|
776
|
+
},
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
if (typeof sessions.axiosSummary.data !== 'string') {
|
|
780
|
+
if (this.#internal.debug) {
|
|
781
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'The response body of the summary page is not of type "string"');
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
action: 'SET_PANEL_STATUS',
|
|
785
|
+
success: false,
|
|
786
|
+
info: {
|
|
787
|
+
message: 'The response body of the summary page is not of type "string"',
|
|
788
|
+
},
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
if (this.#session.backupSatCode === null) {
|
|
792
|
+
const missingSatCode = fetchMissingSatCode(sessions.axiosSummary);
|
|
793
|
+
if (missingSatCode !== null) {
|
|
794
|
+
if (this.#internal.debug) {
|
|
795
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'success', 'Backup sat code was successfully recovered from previous failed retrieval');
|
|
796
|
+
}
|
|
797
|
+
this.#session.backupSatCode = missingSatCode;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
sessions.jsdomSummary = new JSDOM(sessions.axiosSummary.data, {
|
|
801
|
+
url: sessions.axiosSummary.config.url,
|
|
802
|
+
referrer: sessions.axiosSummary.config.headers.Referer,
|
|
803
|
+
contentType: 'text/html',
|
|
804
|
+
pretendToBeVisual: true,
|
|
805
|
+
});
|
|
806
|
+
const jsdomSummaryOrbSecurityButtons = sessions.jsdomSummary.window.document.querySelectorAll('#divOrbSecurityButtons input');
|
|
807
|
+
const parsedOrbSecurityButtons = parseOrbSecurityButtons(jsdomSummaryOrbSecurityButtons);
|
|
808
|
+
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
|
|
809
|
+
const armingNightButtonIndex = parsedOrbSecurityButtons.findIndex((parsedOrbSecurityButton) => {
|
|
810
|
+
const parsedOrbSecurityButtonButtonDisabled = parsedOrbSecurityButton.buttonDisabled;
|
|
811
|
+
const parsedOrbSecurityButtonButtonText = parsedOrbSecurityButton.buttonText;
|
|
812
|
+
return (parsedOrbSecurityButtonButtonDisabled && parsedOrbSecurityButtonButtonText === 'Arming Night');
|
|
813
|
+
});
|
|
814
|
+
if (this.#session.backupSatCode !== null
|
|
815
|
+
&& armingNightButtonIndex >= 0) {
|
|
816
|
+
if (this.#internal.debug) {
|
|
817
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', 'Replacing the stuck "Arming Night" button with a fake "Disarm" button');
|
|
818
|
+
}
|
|
819
|
+
parsedOrbSecurityButtons[armingNightButtonIndex] = {
|
|
820
|
+
buttonDisabled: false,
|
|
821
|
+
buttonId: 'security_button_0',
|
|
822
|
+
buttonIndex: 0,
|
|
823
|
+
buttonText: 'Disarm',
|
|
824
|
+
changeAccessCode: false,
|
|
825
|
+
loadingText: 'Disarming',
|
|
826
|
+
relativeUrl: 'quickcontrol/armDisarm.jsp',
|
|
827
|
+
totalButtons: 1,
|
|
828
|
+
urlParams: {
|
|
829
|
+
arm: 'off',
|
|
830
|
+
armState: (this.#session.isCleanState) ? 'night' : 'night+stay',
|
|
831
|
+
href: 'rest/adt/ui/client/security/setArmState',
|
|
832
|
+
sat: this.#session.backupSatCode,
|
|
833
|
+
},
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton) => !parsedOrbSecurityButton.buttonDisabled);
|
|
837
|
+
if (readyButtons.length < 1) {
|
|
838
|
+
if (this.#internal.debug) {
|
|
839
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Security buttons are not found on the summary page');
|
|
840
|
+
}
|
|
841
|
+
return {
|
|
842
|
+
action: 'SET_PANEL_STATUS',
|
|
843
|
+
success: false,
|
|
844
|
+
info: {
|
|
845
|
+
message: 'Security buttons are not found on the summary page',
|
|
846
|
+
},
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
if (this.#internal.testMode.enabled
|
|
850
|
+
&& !this.#internal.testMode.isDisarmChecked) {
|
|
851
|
+
if (!['off', 'disarmed'].includes(readyButtons[0].urlParams.armState)) {
|
|
852
|
+
if (this.#internal.debug) {
|
|
853
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Test mode is active and system is not disarmed');
|
|
854
|
+
}
|
|
855
|
+
return {
|
|
856
|
+
action: 'SET_PANEL_STATUS',
|
|
857
|
+
success: false,
|
|
858
|
+
info: {
|
|
859
|
+
message: 'Test mode is active and system is not disarmed',
|
|
860
|
+
},
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
this.#internal.testMode.isDisarmChecked = true;
|
|
864
|
+
}
|
|
865
|
+
while (!['off', 'disarmed'].includes(readyButtons[0].urlParams.armState)) {
|
|
866
|
+
const armDisarmResponse = await this.armDisarmHandler(readyButtons[0].relativeUrl, readyButtons[0].urlParams.href, readyButtons[0].urlParams.armState, 'off', readyButtons[0].urlParams.sat);
|
|
867
|
+
if (!armDisarmResponse.success) {
|
|
868
|
+
if (this.#internal.debug) {
|
|
869
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'An error occurred in the arm disarm handler (while disarming)');
|
|
870
|
+
}
|
|
871
|
+
return {
|
|
872
|
+
action: 'SET_PANEL_STATUS',
|
|
873
|
+
success: false,
|
|
874
|
+
info: armDisarmResponse.info,
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
if (armDisarmResponse.info.readyButtons.length < 1) {
|
|
878
|
+
if (this.#internal.debug) {
|
|
879
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Arm disarm handler failed to find new security buttons');
|
|
880
|
+
}
|
|
881
|
+
return {
|
|
882
|
+
action: 'SET_PANEL_STATUS',
|
|
883
|
+
success: false,
|
|
884
|
+
info: {
|
|
885
|
+
message: 'Arm disarm handler failed to find new security buttons',
|
|
886
|
+
},
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
readyButtons = armDisarmResponse.info.readyButtons;
|
|
890
|
+
}
|
|
891
|
+
let forceArmRequired = false;
|
|
892
|
+
if (armTo !== 'off') {
|
|
893
|
+
const armDisarmResponse = await this.armDisarmHandler(readyButtons[0].relativeUrl, readyButtons[0].urlParams.href, readyButtons[0].urlParams.armState, armTo, readyButtons[0].urlParams.sat);
|
|
894
|
+
if (!armDisarmResponse.success) {
|
|
895
|
+
if (this.#internal.debug) {
|
|
896
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'An error occurred in the arm disarm handler (while arming)');
|
|
897
|
+
}
|
|
898
|
+
return {
|
|
899
|
+
action: 'SET_PANEL_STATUS',
|
|
900
|
+
success: false,
|
|
901
|
+
info: armDisarmResponse.info,
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
forceArmRequired = armDisarmResponse.info.forceArmRequired;
|
|
905
|
+
}
|
|
906
|
+
if (this.#internal.debug) {
|
|
907
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'success', `Successfully updated panel status to "${armTo}" at "${this.#internal.baseUrl}"`);
|
|
908
|
+
}
|
|
909
|
+
return {
|
|
910
|
+
action: 'SET_PANEL_STATUS',
|
|
911
|
+
success: true,
|
|
912
|
+
info: {
|
|
913
|
+
forceArmRequired,
|
|
914
|
+
},
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
catch (error) {
|
|
918
|
+
errorObject = serializeError(error);
|
|
919
|
+
}
|
|
920
|
+
if (this.#internal.debug) {
|
|
921
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Method encountered an error during execution');
|
|
922
|
+
stackTracer('serialize-error', errorObject);
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
action: 'SET_PANEL_STATUS',
|
|
926
|
+
success: false,
|
|
927
|
+
info: {
|
|
928
|
+
error: errorObject,
|
|
929
|
+
},
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
async getSensorsInformation() {
|
|
933
|
+
let errorObject;
|
|
934
|
+
if (this.#internal.debug) {
|
|
935
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'info', `Attempting to retrieve sensors information from "${this.#internal.baseUrl}"`);
|
|
936
|
+
}
|
|
937
|
+
try {
|
|
938
|
+
const internet = await this.isPortalAccessible();
|
|
939
|
+
const sessions = {};
|
|
940
|
+
if (!internet.success) {
|
|
941
|
+
return {
|
|
942
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
943
|
+
success: false,
|
|
944
|
+
info: internet.info,
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
sessions.axiosSystem = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`, this.getRequestConfig({
|
|
948
|
+
headers: {
|
|
949
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
950
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
951
|
+
},
|
|
952
|
+
}));
|
|
953
|
+
if (typeof sessions.axiosSystem?.request === 'undefined') {
|
|
954
|
+
if (this.#internal.debug) {
|
|
955
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'error', 'The HTTP client responded without the "request" object');
|
|
956
|
+
}
|
|
957
|
+
return {
|
|
958
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
959
|
+
success: false,
|
|
960
|
+
info: {
|
|
961
|
+
message: 'The HTTP client responded without the "request" object',
|
|
962
|
+
},
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
const axiosSystemRequestPath = sessions.axiosSystem.request.path;
|
|
966
|
+
const axiosSystemRequestPathValid = requestPathSystemSystem.test(axiosSystemRequestPath);
|
|
967
|
+
if (this.#internal.debug) {
|
|
968
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'info', `Request path ➜ ${axiosSystemRequestPath}`);
|
|
969
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'info', `Request path valid ➜ ${axiosSystemRequestPathValid}`);
|
|
970
|
+
}
|
|
971
|
+
if (!axiosSystemRequestPathValid) {
|
|
972
|
+
if (this.#internal.debug) {
|
|
973
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'error', `"${axiosSystemRequestPath}" is not the system page`);
|
|
974
|
+
}
|
|
975
|
+
this.handleLoginFailure(axiosSystemRequestPath, sessions.axiosSystem);
|
|
976
|
+
return {
|
|
977
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
978
|
+
success: false,
|
|
979
|
+
info: {
|
|
980
|
+
message: `"${axiosSystemRequestPath}" is not the system page`,
|
|
981
|
+
},
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
if (typeof sessions.axiosSystem.data !== 'string') {
|
|
985
|
+
if (this.#internal.debug) {
|
|
986
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'error', 'The response body of the system page is not of type "string"');
|
|
987
|
+
}
|
|
988
|
+
return {
|
|
989
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
990
|
+
success: false,
|
|
991
|
+
info: {
|
|
992
|
+
message: 'The response body of the system page is not of type "string"',
|
|
993
|
+
},
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
sessions.jsdomSystem = new JSDOM(sessions.axiosSystem.data, {
|
|
997
|
+
url: sessions.axiosSystem.config.url,
|
|
998
|
+
referrer: sessions.axiosSystem.config.headers.Referer,
|
|
999
|
+
contentType: 'text/html',
|
|
1000
|
+
pretendToBeVisual: true,
|
|
1001
|
+
});
|
|
1002
|
+
const jsdomSystemSensorsTable = sessions.jsdomSystem.window.document.querySelectorAll('#systemContentList tr[onclick^="goToUrl(\'device.jsp?id="]');
|
|
1003
|
+
const parsedSensorsTable = parseSensorsTable(jsdomSystemSensorsTable);
|
|
1004
|
+
await this.newInformationDispatcher('sensors-information', parsedSensorsTable);
|
|
1005
|
+
if (this.#internal.debug) {
|
|
1006
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'success', `Successfully retrieved sensors information from "${this.#internal.baseUrl}"`);
|
|
1007
|
+
}
|
|
1008
|
+
return {
|
|
1009
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
1010
|
+
success: true,
|
|
1011
|
+
info: {
|
|
1012
|
+
sensors: parsedSensorsTable,
|
|
1013
|
+
},
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
errorObject = serializeError(error);
|
|
1018
|
+
}
|
|
1019
|
+
if (this.#internal.debug) {
|
|
1020
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'error', 'Method encountered an error during execution');
|
|
1021
|
+
stackTracer('serialize-error', errorObject);
|
|
1022
|
+
}
|
|
1023
|
+
return {
|
|
1024
|
+
action: 'GET_SENSORS_INFORMATION',
|
|
1025
|
+
success: false,
|
|
1026
|
+
info: {
|
|
1027
|
+
error: errorObject,
|
|
1028
|
+
},
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
async getSensorsStatus() {
|
|
1032
|
+
let errorObject;
|
|
1033
|
+
if (this.#internal.debug) {
|
|
1034
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'info', `Attempting to retrieve sensors status from "${this.#internal.baseUrl}"`);
|
|
1035
|
+
}
|
|
1036
|
+
try {
|
|
1037
|
+
const internet = await this.isPortalAccessible();
|
|
1038
|
+
const sessions = {};
|
|
1039
|
+
if (!internet.success) {
|
|
1040
|
+
return {
|
|
1041
|
+
action: 'GET_SENSORS_STATUS',
|
|
1042
|
+
success: false,
|
|
1043
|
+
info: internet.info,
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
1047
|
+
headers: {
|
|
1048
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
1049
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1050
|
+
},
|
|
1051
|
+
}));
|
|
1052
|
+
if (typeof sessions.axiosSummary?.request === 'undefined') {
|
|
1053
|
+
if (this.#internal.debug) {
|
|
1054
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'error', 'The HTTP client responded without the "request" object');
|
|
1055
|
+
}
|
|
1056
|
+
return {
|
|
1057
|
+
action: 'GET_SENSORS_STATUS',
|
|
1058
|
+
success: false,
|
|
1059
|
+
info: {
|
|
1060
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1061
|
+
},
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
const axiosSummaryRequestPath = sessions.axiosSummary.request.path;
|
|
1065
|
+
const axiosSummaryRequestPathValid = requestPathSummarySummary.test(axiosSummaryRequestPath);
|
|
1066
|
+
if (this.#internal.debug) {
|
|
1067
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'info', `Request path ➜ ${axiosSummaryRequestPath}`);
|
|
1068
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'info', `Request path valid ➜ ${axiosSummaryRequestPathValid}`);
|
|
1069
|
+
}
|
|
1070
|
+
if (!axiosSummaryRequestPathValid) {
|
|
1071
|
+
if (this.#internal.debug) {
|
|
1072
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'error', `"${axiosSummaryRequestPath}" is not the summary page`);
|
|
1073
|
+
}
|
|
1074
|
+
this.handleLoginFailure(axiosSummaryRequestPath, sessions.axiosSummary);
|
|
1075
|
+
return {
|
|
1076
|
+
action: 'GET_SENSORS_STATUS',
|
|
1077
|
+
success: false,
|
|
1078
|
+
info: {
|
|
1079
|
+
message: `"${axiosSummaryRequestPath}" is not the summary page`,
|
|
1080
|
+
},
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
if (typeof sessions.axiosSummary.data !== 'string') {
|
|
1084
|
+
if (this.#internal.debug) {
|
|
1085
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'error', 'The response body of the summary page is not of type "string"');
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
action: 'GET_SENSORS_STATUS',
|
|
1089
|
+
success: false,
|
|
1090
|
+
info: {
|
|
1091
|
+
message: 'The response body of the summary page is not of type "string"',
|
|
1092
|
+
},
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
if (this.#session.backupSatCode === null) {
|
|
1096
|
+
const missingSatCode = fetchMissingSatCode(sessions.axiosSummary);
|
|
1097
|
+
if (missingSatCode !== null) {
|
|
1098
|
+
if (this.#internal.debug) {
|
|
1099
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'success', 'Backup sat code was successfully recovered from previous failed retrieval');
|
|
1100
|
+
}
|
|
1101
|
+
this.#session.backupSatCode = missingSatCode;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
sessions.jsdomSummary = new JSDOM(sessions.axiosSummary.data, {
|
|
1105
|
+
url: sessions.axiosSummary.config.url,
|
|
1106
|
+
referrer: sessions.axiosSummary.config.headers.Referer,
|
|
1107
|
+
contentType: 'text/html',
|
|
1108
|
+
pretendToBeVisual: true,
|
|
1109
|
+
});
|
|
1110
|
+
const jsdomSummaryOrbSensors = sessions.jsdomSummary.window.document.querySelectorAll('#orbSensorsList tr.p_listRow');
|
|
1111
|
+
const parsedOrbSensors = parseOrbSensors(jsdomSummaryOrbSensors);
|
|
1112
|
+
await this.newInformationDispatcher('sensors-status', parsedOrbSensors);
|
|
1113
|
+
if (this.#internal.debug) {
|
|
1114
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'success', `Successfully retrieved sensors status from "${this.#internal.baseUrl}"`);
|
|
1115
|
+
}
|
|
1116
|
+
return {
|
|
1117
|
+
action: 'GET_SENSORS_STATUS',
|
|
1118
|
+
success: true,
|
|
1119
|
+
info: {
|
|
1120
|
+
sensors: parsedOrbSensors,
|
|
1121
|
+
},
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
catch (error) {
|
|
1125
|
+
errorObject = serializeError(error);
|
|
1126
|
+
}
|
|
1127
|
+
if (this.#internal.debug) {
|
|
1128
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'error', 'Method encountered an error during execution');
|
|
1129
|
+
stackTracer('serialize-error', errorObject);
|
|
1130
|
+
}
|
|
1131
|
+
return {
|
|
1132
|
+
action: 'GET_SENSORS_STATUS',
|
|
1133
|
+
success: false,
|
|
1134
|
+
info: {
|
|
1135
|
+
error: errorObject,
|
|
1136
|
+
},
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
async performSyncCheck() {
|
|
1140
|
+
let errorObject;
|
|
1141
|
+
if (this.#internal.debug) {
|
|
1142
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'info', `Attempting to perform a sync check from "${this.#internal.baseUrl}"`);
|
|
1143
|
+
}
|
|
1144
|
+
try {
|
|
1145
|
+
const internet = await this.isPortalAccessible();
|
|
1146
|
+
const sessions = {};
|
|
1147
|
+
if (!internet.success) {
|
|
1148
|
+
return {
|
|
1149
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1150
|
+
success: false,
|
|
1151
|
+
info: internet.info,
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
sessions.axiosSyncCheck = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/Ajax/SyncCheckServ?t=${Date.now()}`, this.getRequestConfig({
|
|
1155
|
+
headers: {
|
|
1156
|
+
Accept: '*/*',
|
|
1157
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
1158
|
+
'Sec-Fetch-Dest': 'empty',
|
|
1159
|
+
'Sec-Fetch-Mode': 'cors',
|
|
1160
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1161
|
+
'Sec-Fetch-User': undefined,
|
|
1162
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
1163
|
+
},
|
|
1164
|
+
}));
|
|
1165
|
+
if (typeof sessions.axiosSyncCheck?.request === 'undefined') {
|
|
1166
|
+
if (this.#internal.debug) {
|
|
1167
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'error', 'The HTTP client responded without the "request" object');
|
|
1168
|
+
}
|
|
1169
|
+
return {
|
|
1170
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1171
|
+
success: false,
|
|
1172
|
+
info: {
|
|
1173
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1174
|
+
},
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
const syncCheckRequestPath = sessions.axiosSyncCheck.request.path;
|
|
1178
|
+
const syncCheckRequestPathValid = requestPathAjaxSyncCheckServTXx.test(syncCheckRequestPath);
|
|
1179
|
+
if (this.#internal.debug) {
|
|
1180
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'info', `Request path ➜ ${syncCheckRequestPath}`);
|
|
1181
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'info', `Request path valid ➜ ${syncCheckRequestPathValid}`);
|
|
1182
|
+
}
|
|
1183
|
+
if (!syncCheckRequestPathValid) {
|
|
1184
|
+
if (this.#internal.debug) {
|
|
1185
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'error', `"${syncCheckRequestPath}" is not the sync check page`);
|
|
1186
|
+
}
|
|
1187
|
+
this.handleLoginFailure(syncCheckRequestPath, sessions.axiosSyncCheck);
|
|
1188
|
+
return {
|
|
1189
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1190
|
+
success: false,
|
|
1191
|
+
info: {
|
|
1192
|
+
message: `"${syncCheckRequestPath}" is not the sync check page`,
|
|
1193
|
+
},
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
if (typeof sessions.axiosSyncCheck.data !== 'string') {
|
|
1197
|
+
if (this.#internal.debug) {
|
|
1198
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'error', 'The response body of the sync check page is not of type "string"');
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1202
|
+
success: false,
|
|
1203
|
+
info: {
|
|
1204
|
+
message: 'The response body of the sync check page is not of type "string"',
|
|
1205
|
+
},
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
if (!isPortalSyncCode(sessions.axiosSyncCheck.data)) {
|
|
1209
|
+
if (this.#internal.debug) {
|
|
1210
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'error', 'The sync code structure is invalid');
|
|
1211
|
+
}
|
|
1212
|
+
return {
|
|
1213
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1214
|
+
success: false,
|
|
1215
|
+
info: {
|
|
1216
|
+
message: 'The sync code structure is invalid',
|
|
1217
|
+
},
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
if (this.#internal.debug) {
|
|
1221
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'success', `Successfully performed a sync check from "${this.#internal.baseUrl}"`);
|
|
1222
|
+
}
|
|
1223
|
+
return {
|
|
1224
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1225
|
+
success: true,
|
|
1226
|
+
info: {
|
|
1227
|
+
syncCode: sessions.axiosSyncCheck.data,
|
|
1228
|
+
},
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
catch (error) {
|
|
1232
|
+
errorObject = serializeError(error);
|
|
1233
|
+
}
|
|
1234
|
+
if (this.#internal.debug) {
|
|
1235
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'error', 'Method encountered an error during execution');
|
|
1236
|
+
stackTracer('serialize-error', errorObject);
|
|
1237
|
+
}
|
|
1238
|
+
return {
|
|
1239
|
+
action: 'PERFORM_SYNC_CHECK',
|
|
1240
|
+
success: false,
|
|
1241
|
+
info: {
|
|
1242
|
+
error: errorObject,
|
|
1243
|
+
},
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
async performKeepAlive() {
|
|
1247
|
+
let errorObject;
|
|
1248
|
+
if (this.#internal.debug) {
|
|
1249
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'info', `Attempting to perform a keep alive from "${this.#internal.baseUrl}"`);
|
|
1250
|
+
}
|
|
1251
|
+
try {
|
|
1252
|
+
const internet = await this.isPortalAccessible();
|
|
1253
|
+
const sessions = {};
|
|
1254
|
+
if (!internet.success) {
|
|
1255
|
+
return {
|
|
1256
|
+
action: 'PERFORM_KEEP_ALIVE',
|
|
1257
|
+
success: false,
|
|
1258
|
+
info: internet.info,
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
sessions.axiosKeepAlive = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/KeepAlive`, '', this.getRequestConfig({
|
|
1262
|
+
headers: {
|
|
1263
|
+
Accept: '*/*',
|
|
1264
|
+
'Content-type': 'application/x-www-form-urlencoded',
|
|
1265
|
+
Origin: this.#internal.baseUrl,
|
|
1266
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
1267
|
+
'Sec-Fetch-Dest': 'empty',
|
|
1268
|
+
'Sec-Fetch-Mode': 'cors',
|
|
1269
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1270
|
+
'Sec-Fetch-User': undefined,
|
|
1271
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
1272
|
+
'x-dtpc': generateDynatracePCHeaderValue('keep-alive'),
|
|
1273
|
+
},
|
|
1274
|
+
}));
|
|
1275
|
+
if (typeof sessions.axiosKeepAlive?.request === 'undefined') {
|
|
1276
|
+
if (this.#internal.debug) {
|
|
1277
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'error', 'The HTTP client responded without the "request" object');
|
|
1278
|
+
}
|
|
1279
|
+
return {
|
|
1280
|
+
action: 'PERFORM_KEEP_ALIVE',
|
|
1281
|
+
success: false,
|
|
1282
|
+
info: {
|
|
1283
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1284
|
+
},
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
const axiosKeepAliveRequestPath = sessions.axiosKeepAlive.request.path;
|
|
1288
|
+
const axiosKeepAliveRequestPathValid = requestPathKeepAlive.test(axiosKeepAliveRequestPath);
|
|
1289
|
+
if (this.#internal.debug) {
|
|
1290
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'info', `Request path ➜ ${axiosKeepAliveRequestPath}`);
|
|
1291
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'info', `Request path valid ➜ ${axiosKeepAliveRequestPathValid}`);
|
|
1292
|
+
}
|
|
1293
|
+
if (!axiosKeepAliveRequestPathValid) {
|
|
1294
|
+
if (this.#internal.debug) {
|
|
1295
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'error', `"${axiosKeepAliveRequestPath}" is not the keep alive page`);
|
|
1296
|
+
}
|
|
1297
|
+
this.handleLoginFailure(axiosKeepAliveRequestPath, sessions.axiosKeepAlive);
|
|
1298
|
+
return {
|
|
1299
|
+
action: 'PERFORM_KEEP_ALIVE',
|
|
1300
|
+
success: false,
|
|
1301
|
+
info: {
|
|
1302
|
+
message: `"${axiosKeepAliveRequestPath}" is not the keep alive page`,
|
|
1303
|
+
},
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
if (this.#internal.debug) {
|
|
1307
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'success', `Successfully performed a keep alive from "${this.#internal.baseUrl}"`);
|
|
1308
|
+
}
|
|
1309
|
+
return {
|
|
1310
|
+
action: 'PERFORM_KEEP_ALIVE',
|
|
1311
|
+
success: true,
|
|
1312
|
+
info: null,
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
catch (error) {
|
|
1316
|
+
errorObject = serializeError(error);
|
|
1317
|
+
}
|
|
1318
|
+
if (this.#internal.debug) {
|
|
1319
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'error', 'Method encountered an error during execution');
|
|
1320
|
+
stackTracer('serialize-error', errorObject);
|
|
1321
|
+
}
|
|
1322
|
+
return {
|
|
1323
|
+
action: 'PERFORM_KEEP_ALIVE',
|
|
1324
|
+
success: false,
|
|
1325
|
+
info: {
|
|
1326
|
+
error: errorObject,
|
|
1327
|
+
},
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
isAuthenticated() {
|
|
1331
|
+
return this.#session.isAuthenticated;
|
|
1332
|
+
}
|
|
1333
|
+
async armDisarmHandler(relativeUrl, href, armState, arm, sat) {
|
|
1334
|
+
let errorObject;
|
|
1335
|
+
if (this.#internal.debug) {
|
|
1336
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Attempting to update arm state from "${armState}" to "${arm}" on "${this.#internal.baseUrl}"`);
|
|
1337
|
+
}
|
|
1338
|
+
if (armState === arm
|
|
1339
|
+
|| (armState === 'disarmed'
|
|
1340
|
+
&& arm === 'off')) {
|
|
1341
|
+
if (this.#internal.debug) {
|
|
1342
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `No need to change arm state from "${armState}" to "${arm}" due to its equivalence`);
|
|
1343
|
+
}
|
|
1344
|
+
return {
|
|
1345
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1346
|
+
success: true,
|
|
1347
|
+
info: {
|
|
1348
|
+
forceArmRequired: false,
|
|
1349
|
+
readyButtons: [],
|
|
1350
|
+
},
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
try {
|
|
1354
|
+
const internet = await this.isPortalAccessible();
|
|
1355
|
+
const sessions = {};
|
|
1356
|
+
if (!internet.success) {
|
|
1357
|
+
return {
|
|
1358
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1359
|
+
success: false,
|
|
1360
|
+
info: internet.info,
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
const armDisarmForm = new URLSearchParams();
|
|
1364
|
+
armDisarmForm.append('href', href);
|
|
1365
|
+
armDisarmForm.append('armstate', armState);
|
|
1366
|
+
armDisarmForm.append('arm', arm);
|
|
1367
|
+
armDisarmForm.append('sat', sat);
|
|
1368
|
+
sessions.axiosSetArmMode = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/${relativeUrl}`, armDisarmForm, this.getRequestConfig({
|
|
1369
|
+
headers: {
|
|
1370
|
+
'Cache-Control': 'max-age=0',
|
|
1371
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
1372
|
+
Origin: this.#internal.baseUrl,
|
|
1373
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
1374
|
+
'Sec-Fetch-Dest': 'iframe',
|
|
1375
|
+
'Sec-Fetch-Mode': 'navigate',
|
|
1376
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1377
|
+
'Sec-Fetch-User': undefined,
|
|
1378
|
+
},
|
|
1379
|
+
}));
|
|
1380
|
+
if (typeof sessions.axiosSetArmMode?.request === 'undefined') {
|
|
1381
|
+
if (this.#internal.debug) {
|
|
1382
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'The HTTP client responded without the "request" object');
|
|
1383
|
+
}
|
|
1384
|
+
return {
|
|
1385
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1386
|
+
success: false,
|
|
1387
|
+
info: {
|
|
1388
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1389
|
+
},
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
const axiosSetArmModeRequestPath = sessions.axiosSetArmMode.request.path;
|
|
1393
|
+
const axiosSetArmModeRequestPathValid = requestPathQuickControlArmDisarm.test(axiosSetArmModeRequestPath);
|
|
1394
|
+
if (this.#internal.debug) {
|
|
1395
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Request path ➜ ${axiosSetArmModeRequestPath}`);
|
|
1396
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Request path valid ➜ ${axiosSetArmModeRequestPathValid}`);
|
|
1397
|
+
}
|
|
1398
|
+
if (!axiosSetArmModeRequestPathValid) {
|
|
1399
|
+
if (this.#internal.debug) {
|
|
1400
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', `"${axiosSetArmModeRequestPath}" is not the arm disarm page`);
|
|
1401
|
+
}
|
|
1402
|
+
this.handleLoginFailure(axiosSetArmModeRequestPath, sessions.axiosSetArmMode);
|
|
1403
|
+
return {
|
|
1404
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1405
|
+
success: false,
|
|
1406
|
+
info: {
|
|
1407
|
+
message: `"${axiosSetArmModeRequestPath}" is not the arm disarm page`,
|
|
1408
|
+
},
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
let forceArmRequired = false;
|
|
1412
|
+
if (arm !== 'off') {
|
|
1413
|
+
const forceArmResponse = await this.forceArmHandler(sessions.axiosSetArmMode, relativeUrl);
|
|
1414
|
+
if (!forceArmResponse.success) {
|
|
1415
|
+
if (this.#internal.debug) {
|
|
1416
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'An error occurred in the force arm handler');
|
|
1417
|
+
}
|
|
1418
|
+
return {
|
|
1419
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1420
|
+
success: false,
|
|
1421
|
+
info: forceArmResponse.info,
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
forceArmRequired = forceArmResponse.info.forceArmRequired;
|
|
1425
|
+
}
|
|
1426
|
+
this.#session.isCleanState = false;
|
|
1427
|
+
await sleep(6000);
|
|
1428
|
+
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
1429
|
+
headers: {
|
|
1430
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
1431
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1432
|
+
},
|
|
1433
|
+
}));
|
|
1434
|
+
if (typeof sessions.axiosSummary?.request === 'undefined') {
|
|
1435
|
+
if (this.#internal.debug) {
|
|
1436
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'The HTTP client responded without the "request" object');
|
|
1437
|
+
}
|
|
1438
|
+
return {
|
|
1439
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1440
|
+
success: false,
|
|
1441
|
+
info: {
|
|
1442
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1443
|
+
},
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
const axiosSummaryRequestPath = sessions.axiosSummary.request.path;
|
|
1447
|
+
const axiosSummaryRequestPathValid = requestPathSummarySummary.test(axiosSummaryRequestPath);
|
|
1448
|
+
if (this.#internal.debug) {
|
|
1449
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Request path ➜ ${axiosSummaryRequestPath}`);
|
|
1450
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Request path valid ➜ ${axiosSummaryRequestPathValid}`);
|
|
1451
|
+
}
|
|
1452
|
+
if (!axiosSummaryRequestPathValid) {
|
|
1453
|
+
if (this.#internal.debug) {
|
|
1454
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', `"${axiosSummaryRequestPath}" is not the summary page`);
|
|
1455
|
+
}
|
|
1456
|
+
this.handleLoginFailure(axiosSummaryRequestPath, sessions.axiosSummary);
|
|
1457
|
+
return {
|
|
1458
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1459
|
+
success: false,
|
|
1460
|
+
info: {
|
|
1461
|
+
message: `"${axiosSummaryRequestPath}" is not the summary page`,
|
|
1462
|
+
},
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
if (typeof sessions.axiosSummary.data !== 'string') {
|
|
1466
|
+
if (this.#internal.debug) {
|
|
1467
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'The response body of the summary page is not of type "string"');
|
|
1468
|
+
}
|
|
1469
|
+
return {
|
|
1470
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1471
|
+
success: false,
|
|
1472
|
+
info: {
|
|
1473
|
+
message: 'The response body of the summary page is not of type "string"',
|
|
1474
|
+
},
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
if (this.#session.backupSatCode === null) {
|
|
1478
|
+
const missingSatCode = fetchMissingSatCode(sessions.axiosSummary);
|
|
1479
|
+
if (missingSatCode !== null) {
|
|
1480
|
+
if (this.#internal.debug) {
|
|
1481
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'success', 'Backup sat code was successfully recovered from previous failed retrieval');
|
|
1482
|
+
}
|
|
1483
|
+
this.#session.backupSatCode = missingSatCode;
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
sessions.jsdomSummary = new JSDOM(sessions.axiosSummary.data, {
|
|
1487
|
+
url: sessions.axiosSummary.config.url,
|
|
1488
|
+
referrer: sessions.axiosSummary.config.headers.Referer,
|
|
1489
|
+
contentType: 'text/html',
|
|
1490
|
+
pretendToBeVisual: true,
|
|
1491
|
+
});
|
|
1492
|
+
const jsdomSummaryOrbSecurityButtons = sessions.jsdomSummary.window.document.querySelectorAll('#divOrbSecurityButtons input');
|
|
1493
|
+
const parsedOrbSecurityButtons = parseOrbSecurityButtons(jsdomSummaryOrbSecurityButtons);
|
|
1494
|
+
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
|
|
1495
|
+
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton) => !parsedOrbSecurityButton.buttonDisabled);
|
|
1496
|
+
if (['disarmed', 'off'].includes(armState)
|
|
1497
|
+
&& ['night'].includes(arm)
|
|
1498
|
+
&& readyButtons.length === 0) {
|
|
1499
|
+
readyButtons = [
|
|
1500
|
+
{
|
|
1501
|
+
buttonDisabled: false,
|
|
1502
|
+
buttonId: 'security_button_0',
|
|
1503
|
+
buttonIndex: 0,
|
|
1504
|
+
buttonText: 'Disarm',
|
|
1505
|
+
changeAccessCode: false,
|
|
1506
|
+
loadingText: 'Disarming',
|
|
1507
|
+
relativeUrl,
|
|
1508
|
+
totalButtons: 1,
|
|
1509
|
+
urlParams: {
|
|
1510
|
+
arm: 'off',
|
|
1511
|
+
armState: (this.#session.isCleanState) ? 'night' : 'night+stay',
|
|
1512
|
+
href,
|
|
1513
|
+
sat,
|
|
1514
|
+
},
|
|
1515
|
+
},
|
|
1516
|
+
];
|
|
1517
|
+
}
|
|
1518
|
+
if (this.#internal.debug) {
|
|
1519
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'success', `Successfully updated arm state from "${armState}" to "${arm}" on "${this.#internal.baseUrl}"`);
|
|
1520
|
+
}
|
|
1521
|
+
return {
|
|
1522
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1523
|
+
success: true,
|
|
1524
|
+
info: {
|
|
1525
|
+
forceArmRequired,
|
|
1526
|
+
readyButtons,
|
|
1527
|
+
},
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
catch (error) {
|
|
1531
|
+
errorObject = serializeError(error);
|
|
1532
|
+
}
|
|
1533
|
+
if (this.#internal.debug) {
|
|
1534
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'Method encountered an error during execution');
|
|
1535
|
+
stackTracer('serialize-error', errorObject);
|
|
1536
|
+
}
|
|
1537
|
+
return {
|
|
1538
|
+
action: 'ARM_DISARM_HANDLER',
|
|
1539
|
+
success: false,
|
|
1540
|
+
info: {
|
|
1541
|
+
error: errorObject,
|
|
1542
|
+
},
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
async forceArmHandler(response, relativeUrl) {
|
|
1546
|
+
let errorObject;
|
|
1547
|
+
if (this.#internal.debug) {
|
|
1548
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'info', `Attempting to force arm on "${this.#internal.baseUrl}"`);
|
|
1549
|
+
}
|
|
1550
|
+
try {
|
|
1551
|
+
const internet = await this.isPortalAccessible();
|
|
1552
|
+
const sessions = {};
|
|
1553
|
+
if (!internet.success) {
|
|
1554
|
+
return {
|
|
1555
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1556
|
+
success: false,
|
|
1557
|
+
info: internet.info,
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
if (typeof response.data !== 'string') {
|
|
1561
|
+
if (this.#internal.debug) {
|
|
1562
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'The response body of the arm disarm page is not of type "string"');
|
|
1563
|
+
}
|
|
1564
|
+
return {
|
|
1565
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1566
|
+
success: false,
|
|
1567
|
+
info: {
|
|
1568
|
+
message: 'The response body of the arm disarm page is not of type "string"',
|
|
1569
|
+
},
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
sessions.jsdomArmDisarm = new JSDOM(response.data, {
|
|
1573
|
+
url: response.config.url,
|
|
1574
|
+
referrer: response.config.headers.Referer,
|
|
1575
|
+
contentType: 'text/html',
|
|
1576
|
+
pretendToBeVisual: true,
|
|
1577
|
+
});
|
|
1578
|
+
const jsdomArmDisarmDoSubmitHandlers = sessions.jsdomArmDisarm.window.document.querySelectorAll('.p_armDisarmWrapper input');
|
|
1579
|
+
const jsdomArmDisarmArmDisarmMessage = sessions.jsdomArmDisarm.window.document.querySelector('.p_armDisarmWrapper div:first-child');
|
|
1580
|
+
const parsedArmDisarmMessage = parseArmDisarmMessage(jsdomArmDisarmArmDisarmMessage);
|
|
1581
|
+
const parsedDoSubmitHandlers = parseDoSubmitHandlers(jsdomArmDisarmDoSubmitHandlers);
|
|
1582
|
+
await this.newInformationDispatcher('do-submit-handlers', parsedDoSubmitHandlers);
|
|
1583
|
+
if (parsedDoSubmitHandlers.length === 0
|
|
1584
|
+
|| parsedArmDisarmMessage === null) {
|
|
1585
|
+
if (this.#internal.testMode.enabled) {
|
|
1586
|
+
if (this.#internal.debug) {
|
|
1587
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'Test mode is active but no doors or windows were open');
|
|
1588
|
+
}
|
|
1589
|
+
return {
|
|
1590
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1591
|
+
success: false,
|
|
1592
|
+
info: {
|
|
1593
|
+
message: 'Test mode is active but no doors or windows were open',
|
|
1594
|
+
},
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
if (this.#internal.debug) {
|
|
1598
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'info', 'Force arming not required');
|
|
1599
|
+
}
|
|
1600
|
+
return {
|
|
1601
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1602
|
+
success: true,
|
|
1603
|
+
info: {
|
|
1604
|
+
forceArmRequired: false,
|
|
1605
|
+
},
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
const tracker = {
|
|
1609
|
+
complete: false,
|
|
1610
|
+
errorMessage: null,
|
|
1611
|
+
requestUrl: null,
|
|
1612
|
+
};
|
|
1613
|
+
if (this.#internal.debug) {
|
|
1614
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'warn', `Portal message ➜ "${parsedArmDisarmMessage}"`);
|
|
1615
|
+
}
|
|
1616
|
+
for (let i = 0; i < parsedDoSubmitHandlers.length; i += 1) {
|
|
1617
|
+
const forceArmRelativeUrl = parsedDoSubmitHandlers[i].relativeUrl;
|
|
1618
|
+
const forceArmSat = parsedDoSubmitHandlers[i].urlParams.sat;
|
|
1619
|
+
const forceArmHref = parsedDoSubmitHandlers[i].urlParams.href;
|
|
1620
|
+
const forceArmArmState = parsedDoSubmitHandlers[i].urlParams.armState;
|
|
1621
|
+
const forceArmArm = parsedDoSubmitHandlers[i].urlParams.arm;
|
|
1622
|
+
if ((tracker.complete
|
|
1623
|
+
&& tracker.errorMessage === null)
|
|
1624
|
+
|| forceArmArmState === null
|
|
1625
|
+
|| forceArmArm === null) {
|
|
1626
|
+
continue;
|
|
1627
|
+
}
|
|
1628
|
+
const forceArmForm = new URLSearchParams();
|
|
1629
|
+
forceArmForm.append('sat', forceArmSat);
|
|
1630
|
+
forceArmForm.append('href', forceArmHref);
|
|
1631
|
+
forceArmForm.append('armstate', forceArmArmState);
|
|
1632
|
+
forceArmForm.append('arm', forceArmArm);
|
|
1633
|
+
sessions.axiosForceArm = await this.#session.httpClient.post(this.#internal.baseUrl + forceArmRelativeUrl, forceArmForm, this.getRequestConfig({
|
|
1634
|
+
headers: {
|
|
1635
|
+
Accept: '*/*',
|
|
1636
|
+
'Content-type': 'application/x-www-form-urlencoded',
|
|
1637
|
+
Origin: this.#internal.baseUrl,
|
|
1638
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/${relativeUrl}`,
|
|
1639
|
+
'Sec-Fetch-Dest': 'empty',
|
|
1640
|
+
'Sec-Fetch-Mode': 'cors',
|
|
1641
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
1642
|
+
'Sec-Fetch-User': undefined,
|
|
1643
|
+
'x-dtpc': generateDynatracePCHeaderValue('force-arm'),
|
|
1644
|
+
},
|
|
1645
|
+
}));
|
|
1646
|
+
if (typeof sessions.axiosForceArm?.request === 'undefined') {
|
|
1647
|
+
if (this.#internal.debug) {
|
|
1648
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'The HTTP client responded without the "request" object');
|
|
1649
|
+
}
|
|
1650
|
+
return {
|
|
1651
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1652
|
+
success: false,
|
|
1653
|
+
info: {
|
|
1654
|
+
message: 'The HTTP client responded without the "request" object',
|
|
1655
|
+
},
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
const axiosForceArmRequestPath = sessions.axiosForceArm.request.path;
|
|
1659
|
+
const axiosForceArmRequestPathValid = requestPathQuickControlServRunRraCommand.test(axiosForceArmRequestPath);
|
|
1660
|
+
if (this.#internal.debug) {
|
|
1661
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'info', `Request path ➜ ${axiosForceArmRequestPath}`);
|
|
1662
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'info', `Request path valid ➜ ${axiosForceArmRequestPathValid}`);
|
|
1663
|
+
}
|
|
1664
|
+
if (!axiosForceArmRequestPathValid) {
|
|
1665
|
+
tracker.errorMessage = `"${axiosForceArmRequestPath}" is not the run rra command page`;
|
|
1666
|
+
tracker.requestUrl = axiosForceArmRequestPath;
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
if (typeof sessions.axiosForceArm.data !== 'string') {
|
|
1670
|
+
tracker.errorMessage = 'The response body of the run rra command page is not of type "string"';
|
|
1671
|
+
tracker.requestUrl = axiosForceArmRequestPath;
|
|
1672
|
+
continue;
|
|
1673
|
+
}
|
|
1674
|
+
if (!sessions.axiosForceArm.data.includes('1.0-OKAY')) {
|
|
1675
|
+
tracker.errorMessage = 'The response body of the run rra command page does not include "1.0-OKAY"';
|
|
1676
|
+
tracker.requestUrl = axiosForceArmRequestPath;
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
tracker.complete = true;
|
|
1680
|
+
tracker.errorMessage = null;
|
|
1681
|
+
tracker.requestUrl = null;
|
|
1682
|
+
}
|
|
1683
|
+
if (tracker.errorMessage !== null) {
|
|
1684
|
+
if (this.#internal.debug) {
|
|
1685
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', tracker.errorMessage);
|
|
1686
|
+
}
|
|
1687
|
+
this.handleLoginFailure(tracker.requestUrl, sessions.axiosForceArm);
|
|
1688
|
+
return {
|
|
1689
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1690
|
+
success: false,
|
|
1691
|
+
info: {
|
|
1692
|
+
message: tracker.errorMessage,
|
|
1693
|
+
},
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
if (!tracker.complete) {
|
|
1697
|
+
if (this.#internal.debug) {
|
|
1698
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'Force arming failed because the "Arm Anyway" button was not found');
|
|
1699
|
+
}
|
|
1700
|
+
return {
|
|
1701
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1702
|
+
success: false,
|
|
1703
|
+
info: {
|
|
1704
|
+
message: 'Force arming failed because the "Arm Anyway" button was not found',
|
|
1705
|
+
},
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
if (this.#internal.debug) {
|
|
1709
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'success', `Successfully forced arm on "${this.#internal.baseUrl}"`);
|
|
1710
|
+
}
|
|
1711
|
+
return {
|
|
1712
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1713
|
+
success: true,
|
|
1714
|
+
info: {
|
|
1715
|
+
forceArmRequired: true,
|
|
1716
|
+
},
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
catch (error) {
|
|
1720
|
+
errorObject = serializeError(error);
|
|
1721
|
+
}
|
|
1722
|
+
if (this.#internal.debug) {
|
|
1723
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'Method encountered an error during execution');
|
|
1724
|
+
stackTracer('serialize-error', errorObject);
|
|
1725
|
+
}
|
|
1726
|
+
return {
|
|
1727
|
+
action: 'FORCE_ARM_HANDLER',
|
|
1728
|
+
success: false,
|
|
1729
|
+
info: {
|
|
1730
|
+
error: errorObject,
|
|
1731
|
+
},
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
1734
|
+
async isPortalAccessible() {
|
|
1735
|
+
let errorObject;
|
|
1736
|
+
if (this.#internal.debug) {
|
|
1737
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.isPortalAccessible()', 'info', `Attempting to check if "${this.#internal.baseUrl}" is accessible`);
|
|
1738
|
+
}
|
|
1739
|
+
try {
|
|
1740
|
+
const response = await axios.head(this.#internal.baseUrl, this.getRequestConfig());
|
|
1741
|
+
if (response.status !== 200 || response.statusText !== 'OK') {
|
|
1742
|
+
if (this.#internal.debug) {
|
|
1743
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.isPortalAccessible()', 'error', `The portal at "${this.#internal.baseUrl}" is not accessible`);
|
|
1744
|
+
}
|
|
1745
|
+
return {
|
|
1746
|
+
action: 'IS_PORTAL_ACCESSIBLE',
|
|
1747
|
+
success: false,
|
|
1748
|
+
info: {
|
|
1749
|
+
message: `The portal at "${this.#internal.baseUrl}" is not accessible`,
|
|
1750
|
+
},
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
if (this.#internal.debug) {
|
|
1754
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.isPortalAccessible()', 'success', `Successfully checked if "${this.#internal.baseUrl}" is accessible`);
|
|
1755
|
+
}
|
|
1756
|
+
return {
|
|
1757
|
+
action: 'IS_PORTAL_ACCESSIBLE',
|
|
1758
|
+
success: true,
|
|
1759
|
+
info: null,
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
catch (error) {
|
|
1763
|
+
errorObject = serializeError(error);
|
|
1764
|
+
}
|
|
1765
|
+
if (this.#internal.debug) {
|
|
1766
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.isPortalAccessible()', 'error', 'Method encountered an error during execution');
|
|
1767
|
+
stackTracer('serialize-error', errorObject);
|
|
1768
|
+
}
|
|
1769
|
+
return {
|
|
1770
|
+
action: 'IS_PORTAL_ACCESSIBLE',
|
|
1771
|
+
success: false,
|
|
1772
|
+
info: {
|
|
1773
|
+
error: errorObject,
|
|
1774
|
+
},
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
async newInformationDispatcher(type, data) {
|
|
1778
|
+
const dataHash = generateHash(`${type}: ${JSON.stringify(data)}`);
|
|
1779
|
+
if (this.#internal.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {
|
|
1780
|
+
let detectedNew = false;
|
|
1781
|
+
switch (type) {
|
|
1782
|
+
case 'do-submit-handlers':
|
|
1783
|
+
detectedNew = await detectedNewDoSubmitHandlers(data, this.#internal.logger, this.#internal.debug);
|
|
1784
|
+
break;
|
|
1785
|
+
case 'gateway-information':
|
|
1786
|
+
detectedNew = await detectedNewGatewayInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1787
|
+
break;
|
|
1788
|
+
case 'orb-security-buttons':
|
|
1789
|
+
detectedNew = await detectedNewOrbSecurityButtons(data, this.#internal.logger, this.#internal.debug);
|
|
1790
|
+
break;
|
|
1791
|
+
case 'panel-information':
|
|
1792
|
+
detectedNew = await detectedNewPanelInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1793
|
+
break;
|
|
1794
|
+
case 'panel-status':
|
|
1795
|
+
detectedNew = await detectedNewPanelStatus(data, this.#internal.logger, this.#internal.debug);
|
|
1796
|
+
break;
|
|
1797
|
+
case 'portal-version':
|
|
1798
|
+
detectedNew = await detectedNewPortalVersion(data, this.#internal.logger, this.#internal.debug);
|
|
1799
|
+
break;
|
|
1800
|
+
case 'sensors-information':
|
|
1801
|
+
detectedNew = await detectedNewSensorsInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1802
|
+
break;
|
|
1803
|
+
case 'sensors-status':
|
|
1804
|
+
detectedNew = await detectedNewSensorsStatus(data, this.#internal.logger, this.#internal.debug);
|
|
1805
|
+
break;
|
|
1806
|
+
default:
|
|
1807
|
+
break;
|
|
1808
|
+
}
|
|
1809
|
+
if (detectedNew) {
|
|
1810
|
+
this.#internal.reportedHashes.push(dataHash);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
getRequestConfig(extraConfig) {
|
|
1815
|
+
const defaultConfig = {
|
|
1816
|
+
family: 4,
|
|
1817
|
+
headers: {
|
|
1818
|
+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
1819
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
1820
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
1821
|
+
Connection: 'keep-alive',
|
|
1822
|
+
Host: `${this.#credentials.subdomain}.adtpulse.com`,
|
|
1823
|
+
'Sec-Fetch-Dest': 'document',
|
|
1824
|
+
'Sec-Fetch-Mode': 'navigate',
|
|
1825
|
+
'Sec-Fetch-Site': 'none',
|
|
1826
|
+
'Sec-Fetch-User': '?1',
|
|
1827
|
+
'Upgrade-Insecure-Requests': '1',
|
|
1828
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
1829
|
+
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
|
1830
|
+
'sec-ch-ua-mobile': '?0',
|
|
1831
|
+
'sec-ch-ua-platform': '"macOS"',
|
|
1832
|
+
},
|
|
1833
|
+
timeout: 15000,
|
|
1834
|
+
validateStatus: undefined,
|
|
1835
|
+
};
|
|
1836
|
+
if (extraConfig === undefined) {
|
|
1837
|
+
return defaultConfig;
|
|
1838
|
+
}
|
|
1839
|
+
return _.merge(_.omit(defaultConfig, findNullKeys(extraConfig)), _.omit(extraConfig, findNullKeys(extraConfig)));
|
|
1840
|
+
}
|
|
1841
|
+
handleLoginFailure(requestPath, session) {
|
|
1842
|
+
if (requestPath === null) {
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
if (requestPathAccessSignIn.test(requestPath)
|
|
1846
|
+
|| requestPathAccessSignInENsPartnerAdt.test(requestPath)
|
|
1847
|
+
|| requestPathMfaMfaSignInWorkflowChallenge.test(requestPath)) {
|
|
1848
|
+
if (this.#internal.debug) {
|
|
1849
|
+
const errorMessage = fetchErrorMessage(session);
|
|
1850
|
+
if (requestPathAccessSignIn.test(requestPath) || requestPathAccessSignInENsPartnerAdt.test(requestPath)) {
|
|
1851
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.handleLoginFailure()', 'error', 'Either the username or password is incorrect, fingerprint format is invalid, or was signed out due to inactivity');
|
|
1852
|
+
}
|
|
1853
|
+
if (requestPathMfaMfaSignInWorkflowChallenge.test(requestPath)) {
|
|
1854
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.handleLoginFailure()', 'error', 'Either the fingerprint expired or "Trust this device" was not selected after completing MFA challenge');
|
|
1855
|
+
}
|
|
1856
|
+
if (errorMessage !== null) {
|
|
1857
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.handleLoginFailure()', 'warn', `Portal message ➜ "${errorMessage}"`);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
this.resetSession();
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
resetSession() {
|
|
1864
|
+
this.#session = {
|
|
1865
|
+
backupSatCode: null,
|
|
1866
|
+
httpClient: wrapper(axios.create({
|
|
1867
|
+
jar: new CookieJar(),
|
|
1868
|
+
})),
|
|
1869
|
+
isAuthenticated: false,
|
|
1870
|
+
isCleanState: true,
|
|
1871
|
+
networkId: null,
|
|
1872
|
+
portalVersion: null,
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
//# sourceMappingURL=api.js.map
|