homebridge-adt-pulse 3.0.0-beta.9 → 3.0.1
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/LICENSE +198 -12
- package/README.md +167 -106
- package/build/config.schema.json +12 -13
- package/build/src/lib/accessory.js +434 -124
- package/build/src/lib/accessory.js.map +1 -1
- package/build/src/lib/api.js +276 -240
- package/build/src/lib/api.js.map +1 -1
- package/build/src/lib/detect.js +308 -280
- package/build/src/lib/detect.js.map +1 -1
- package/build/src/lib/items.js +345 -0
- package/build/src/lib/items.js.map +1 -0
- package/build/src/lib/platform.js +198 -38
- package/build/src/lib/platform.js.map +1 -1
- package/build/src/lib/regex.js +2 -2
- package/build/src/lib/regex.js.map +1 -1
- package/build/src/lib/schema.js +3 -3
- package/build/src/lib/schema.js.map +1 -1
- package/build/src/lib/utility.js +284 -38
- package/build/src/lib/utility.js.map +1 -1
- package/build/src/scripts/repl.js +23 -17
- package/build/src/scripts/repl.js.map +1 -1
- package/build/src/scripts/test-api.js +12 -12
- package/build/src/scripts/test-api.js.map +1 -1
- package/config.schema.json +12 -13
- package/package.json +25 -15
package/build/src/lib/api.js
CHANGED
|
@@ -4,9 +4,9 @@ import { JSDOM } from 'jsdom';
|
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
import { serializeError } from 'serialize-error';
|
|
6
6
|
import { CookieJar } from 'tough-cookie';
|
|
7
|
-
import {
|
|
8
|
-
import { paramNetworkId, paramSat, requestPathAccessSignIn,
|
|
9
|
-
import { debugLog, fetchErrorMessage, fetchMissingSatCode, fetchTableCells, findNullKeys, generateDynatracePCHeaderValue, generateHash, isPortalSyncCode, parseArmDisarmMessage, parseDoSubmitHandlers, parseOrbSecurityButtons, parseOrbSensors, parseOrbTextSummary, parseSensorsTable, sleep, stackTracer, } from './utility.js';
|
|
7
|
+
import { detectApiDebugParser, detectApiDoSubmitHandlers, detectApiGatewayInformation, detectApiOrbSecurityButtons, detectApiPanelInformation, detectApiPanelStatus, detectApiPortalVersion, detectApiSensorsInformation, detectApiSensorsStatus, } from './detect.js';
|
|
8
|
+
import { paramNetworkId, paramSat, requestPathAccessSignIn, requestPathAccessSignInEXxPartnerAdt, requestPathAccessSignInNetworkIdXxPartnerAdt, requestPathAjaxSyncCheckServTXx, requestPathKeepAlive, requestPathMfaMfaSignInWorkflowChallenge, requestPathQuickControlArmDisarm, requestPathQuickControlServRunRraCommand, requestPathSummarySummary, requestPathSystemDeviceId1, requestPathSystemGateway, requestPathSystemSystem, textPanelEmergencyKeys, } from './regex.js';
|
|
9
|
+
import { debugLog, fetchErrorMessage, fetchMissingSatCode, fetchTableCells, findNullKeys, generateDynatracePCHeaderValue, generateFakeReadyButtons, generateHash, isEmptyOrbTextSummary, isPortalSyncCode, parseArmDisarmMessage, parseDoSubmitHandlers, parseOrbSecurityButtons, parseOrbSensors, parseOrbTextSummary, parseSensorsTable, sleep, stackTracer, } from './utility.js';
|
|
10
10
|
export class ADTPulse {
|
|
11
11
|
#credentials;
|
|
12
12
|
#internal;
|
|
@@ -25,19 +25,39 @@ export class ADTPulse {
|
|
|
25
25
|
reportedHashes: [],
|
|
26
26
|
testMode: {
|
|
27
27
|
enabled: internalConfig.testMode?.enabled ?? false,
|
|
28
|
-
|
|
28
|
+
isSystemDisarmedBeforeTest: internalConfig.testMode?.isSystemDisarmedBeforeTest ?? false,
|
|
29
29
|
},
|
|
30
|
+
waitTimeAfterArm: 5000,
|
|
30
31
|
};
|
|
31
32
|
this.#session = {
|
|
32
33
|
backupSatCode: null,
|
|
33
34
|
httpClient: wrapper(axios.create({
|
|
34
35
|
jar: new CookieJar(),
|
|
36
|
+
validateStatus: () => true,
|
|
35
37
|
})),
|
|
36
38
|
isAuthenticated: false,
|
|
37
39
|
isCleanState: true,
|
|
38
40
|
networkId: null,
|
|
39
41
|
portalVersion: null,
|
|
40
42
|
};
|
|
43
|
+
if (config.speed !== 1) {
|
|
44
|
+
if (this.#internal.debug) {
|
|
45
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.constructor()', 'warn', `Plugin is now running under ${config.speed}x operational speed. You may see slower device updates`);
|
|
46
|
+
}
|
|
47
|
+
switch (config.speed) {
|
|
48
|
+
case 0.75:
|
|
49
|
+
this.#internal.waitTimeAfterArm = 6000;
|
|
50
|
+
break;
|
|
51
|
+
case 0.5:
|
|
52
|
+
this.#internal.waitTimeAfterArm = 7000;
|
|
53
|
+
break;
|
|
54
|
+
case 0.25:
|
|
55
|
+
this.#internal.waitTimeAfterArm = 8000;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
41
61
|
}
|
|
42
62
|
async login() {
|
|
43
63
|
let errorObject;
|
|
@@ -45,15 +65,7 @@ export class ADTPulse {
|
|
|
45
65
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', `Attempting to login to "${this.#internal.baseUrl}"`);
|
|
46
66
|
}
|
|
47
67
|
try {
|
|
48
|
-
const internet = await this.isPortalAccessible();
|
|
49
68
|
const sessions = {};
|
|
50
|
-
if (!internet.success) {
|
|
51
|
-
return {
|
|
52
|
-
action: 'LOGIN',
|
|
53
|
-
success: false,
|
|
54
|
-
info: internet.info,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
69
|
if (this.isAuthenticated()) {
|
|
58
70
|
if (this.#internal.debug) {
|
|
59
71
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.login()', 'info', [
|
|
@@ -224,15 +236,7 @@ export class ADTPulse {
|
|
|
224
236
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', `Attempting to logout of "${this.#internal.baseUrl}"`);
|
|
225
237
|
}
|
|
226
238
|
try {
|
|
227
|
-
const internet = await this.isPortalAccessible();
|
|
228
239
|
const sessions = {};
|
|
229
|
-
if (!internet.success) {
|
|
230
|
-
return {
|
|
231
|
-
action: 'LOGOUT',
|
|
232
|
-
success: false,
|
|
233
|
-
info: internet.info,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
240
|
if (!this.isAuthenticated()) {
|
|
237
241
|
if (this.#internal.debug) {
|
|
238
242
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.logout()', 'info', [
|
|
@@ -341,15 +345,7 @@ export class ADTPulse {
|
|
|
341
345
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'info', `Attempting to retrieve gateway information from "${this.#internal.baseUrl}"`);
|
|
342
346
|
}
|
|
343
347
|
try {
|
|
344
|
-
const internet = await this.isPortalAccessible();
|
|
345
348
|
const sessions = {};
|
|
346
|
-
if (!internet.success) {
|
|
347
|
-
return {
|
|
348
|
-
action: 'GET_GATEWAY_INFORMATION',
|
|
349
|
-
success: false,
|
|
350
|
-
info: internet.info,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
349
|
sessions.axiosSystemGateway = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/gateway.jsp`, this.getRequestConfig({
|
|
354
350
|
headers: {
|
|
355
351
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`,
|
|
@@ -429,10 +425,10 @@ export class ADTPulse {
|
|
|
429
425
|
], 1, 1);
|
|
430
426
|
const gatewayInformation = {
|
|
431
427
|
communication: {
|
|
432
|
-
primaryConnectionType: _.get(fetchedTableCells, ['Primary Connection Type:', 0], null),
|
|
433
428
|
broadbandConnectionStatus: _.get(fetchedTableCells, ['Broadband Connection Status:', 0], null),
|
|
434
429
|
cellularConnectionStatus: _.get(fetchedTableCells, ['Cellular Connection Status:', 0], null),
|
|
435
430
|
cellularSignalStrength: _.get(fetchedTableCells, ['Cellular Signal Strength:', 0], null),
|
|
431
|
+
primaryConnectionType: _.get(fetchedTableCells, ['Primary Connection Type:', 0], null),
|
|
436
432
|
},
|
|
437
433
|
manufacturer: _.get(fetchedTableCells, ['Manufacturer:', 0], null),
|
|
438
434
|
model: _.get(fetchedTableCells, ['Model:', 0], null),
|
|
@@ -462,6 +458,17 @@ export class ADTPulse {
|
|
|
462
458
|
},
|
|
463
459
|
};
|
|
464
460
|
await this.newInformationDispatcher('gateway-information', gatewayInformation);
|
|
461
|
+
if (Object.keys(fetchedTableCells).length !== 18) {
|
|
462
|
+
if (this.#internal.debug) {
|
|
463
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'warn', 'The fetchTableCells() function may be parsing the gateway information incorrectly');
|
|
464
|
+
}
|
|
465
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
466
|
+
parserName: 'fetchTableCells()',
|
|
467
|
+
parserReason: 'length does not equal to 18',
|
|
468
|
+
parserResponse: fetchedTableCells,
|
|
469
|
+
rawData: sessions.axiosSystemGateway.data,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
465
472
|
if (this.#internal.debug) {
|
|
466
473
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'success', `Successfully retrieved gateway information from "${this.#internal.baseUrl}"`);
|
|
467
474
|
}
|
|
@@ -492,15 +499,7 @@ export class ADTPulse {
|
|
|
492
499
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'info', `Attempting to retrieve panel information from "${this.#internal.baseUrl}"`);
|
|
493
500
|
}
|
|
494
501
|
try {
|
|
495
|
-
const internet = await this.isPortalAccessible();
|
|
496
502
|
const sessions = {};
|
|
497
|
-
if (!internet.success) {
|
|
498
|
-
return {
|
|
499
|
-
action: 'GET_PANEL_INFORMATION',
|
|
500
|
-
success: false,
|
|
501
|
-
info: internet.info,
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
503
|
sessions.axiosSystemDeviceId1 = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/device.jsp?id=1`, this.getRequestConfig({
|
|
505
504
|
headers: {
|
|
506
505
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`,
|
|
@@ -565,13 +564,13 @@ export class ADTPulse {
|
|
|
565
564
|
'Type/Model:',
|
|
566
565
|
], 1, 1);
|
|
567
566
|
const emergencyKeys = _.get(fetchedTableCells, ['Emergency Keys:', 0], null);
|
|
568
|
-
const parsedEmergencyKeys = (
|
|
567
|
+
const parsedEmergencyKeys = (emergencyKeys !== null) ? emergencyKeys.match(textPanelEmergencyKeys) : null;
|
|
569
568
|
const manufacturerProvider = _.get(fetchedTableCells, ['Manufacturer/Provider:', 0], null);
|
|
570
|
-
const parsedManufacturer = (
|
|
571
|
-
const parsedProvider = (
|
|
569
|
+
const parsedManufacturer = (manufacturerProvider !== null) ? manufacturerProvider.split(' - ')[0] ?? null : null;
|
|
570
|
+
const parsedProvider = (manufacturerProvider !== null) ? manufacturerProvider.split(' - ')[1] ?? null : null;
|
|
572
571
|
const typeModel = _.get(fetchedTableCells, ['Type/Model:', 0], null);
|
|
573
|
-
const parsedType = (
|
|
574
|
-
const parsedModel = (
|
|
572
|
+
const parsedType = (typeModel !== null) ? typeModel.split(' - ')[0] ?? null : null;
|
|
573
|
+
const parsedModel = (typeModel !== null) ? typeModel.split(' - ')[1] ?? null : null;
|
|
575
574
|
const panelInformation = {
|
|
576
575
|
emergencyKeys: parsedEmergencyKeys,
|
|
577
576
|
manufacturer: parsedManufacturer,
|
|
@@ -582,6 +581,17 @@ export class ADTPulse {
|
|
|
582
581
|
status: _.get(fetchedTableCells, ['Status:', 0], null),
|
|
583
582
|
};
|
|
584
583
|
await this.newInformationDispatcher('panel-information', panelInformation);
|
|
584
|
+
if (Object.keys(fetchedTableCells).length !== 5) {
|
|
585
|
+
if (this.#internal.debug) {
|
|
586
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'warn', 'The fetchTableCells() function may be parsing the panel information incorrectly');
|
|
587
|
+
}
|
|
588
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
589
|
+
parserName: 'fetchTableCells()',
|
|
590
|
+
parserReason: 'length does not equal to 5',
|
|
591
|
+
parserResponse: fetchedTableCells,
|
|
592
|
+
rawData: sessions.axiosSystemDeviceId1.data,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
585
595
|
if (this.#internal.debug) {
|
|
586
596
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'success', `Successfully retrieved panel information from "${this.#internal.baseUrl}"`);
|
|
587
597
|
}
|
|
@@ -612,15 +622,7 @@ export class ADTPulse {
|
|
|
612
622
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'info', `Attempting to retrieve panel status from "${this.#internal.baseUrl}"`);
|
|
613
623
|
}
|
|
614
624
|
try {
|
|
615
|
-
const internet = await this.isPortalAccessible();
|
|
616
625
|
const sessions = {};
|
|
617
|
-
if (!internet.success) {
|
|
618
|
-
return {
|
|
619
|
-
action: 'GET_PANEL_STATUS',
|
|
620
|
-
success: false,
|
|
621
|
-
info: internet.info,
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
626
|
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
625
627
|
headers: {
|
|
626
628
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
@@ -688,6 +690,17 @@ export class ADTPulse {
|
|
|
688
690
|
const jsdomSummaryOrbTextSummary = sessions.jsdomSummary.window.document.querySelector('#divOrbTextSummary');
|
|
689
691
|
const parsedOrbTextSummary = parseOrbTextSummary(jsdomSummaryOrbTextSummary);
|
|
690
692
|
await this.newInformationDispatcher('panel-status', parsedOrbTextSummary);
|
|
693
|
+
if (isEmptyOrbTextSummary(parsedOrbTextSummary)) {
|
|
694
|
+
if (this.#internal.debug) {
|
|
695
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'warn', 'The parseOrbTextSummary() function may be parsing sensors information incorrectly');
|
|
696
|
+
}
|
|
697
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
698
|
+
parserName: 'parseOrbTextSummary()',
|
|
699
|
+
parserReason: 'empty response',
|
|
700
|
+
parserResponse: parsedOrbTextSummary,
|
|
701
|
+
rawData: sessions.axiosSummary.data,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
691
704
|
if (this.#internal.debug) {
|
|
692
705
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'success', `Successfully retrieved panel status from "${this.#internal.baseUrl}"`);
|
|
693
706
|
}
|
|
@@ -712,10 +725,22 @@ export class ADTPulse {
|
|
|
712
725
|
},
|
|
713
726
|
};
|
|
714
727
|
}
|
|
715
|
-
async setPanelStatus(armTo) {
|
|
728
|
+
async setPanelStatus(armFrom, armTo, isAlarmActive) {
|
|
716
729
|
let errorObject;
|
|
717
730
|
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}"`);
|
|
731
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'info', `Attempting to update panel status from "${armFrom}" to "${armTo}" at "${this.#internal.baseUrl}"`);
|
|
732
|
+
}
|
|
733
|
+
if (armFrom !== 'away'
|
|
734
|
+
&& armFrom !== 'night'
|
|
735
|
+
&& armFrom !== 'off'
|
|
736
|
+
&& armFrom !== 'stay') {
|
|
737
|
+
return {
|
|
738
|
+
action: 'SET_PANEL_STATUS',
|
|
739
|
+
success: false,
|
|
740
|
+
info: {
|
|
741
|
+
message: `"${armFrom}" is an invalid arm from state`,
|
|
742
|
+
},
|
|
743
|
+
};
|
|
719
744
|
}
|
|
720
745
|
if (armTo !== 'away'
|
|
721
746
|
&& armTo !== 'night'
|
|
@@ -729,16 +754,41 @@ export class ADTPulse {
|
|
|
729
754
|
},
|
|
730
755
|
};
|
|
731
756
|
}
|
|
757
|
+
if (typeof isAlarmActive !== 'boolean') {
|
|
758
|
+
return {
|
|
759
|
+
action: 'SET_PANEL_STATUS',
|
|
760
|
+
success: false,
|
|
761
|
+
info: {
|
|
762
|
+
message: 'You must specify if the system\'s alarm is currently ringing (true) or not (false)',
|
|
763
|
+
},
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
if ((armFrom === 'away'
|
|
767
|
+
&& armTo === 'away')
|
|
768
|
+
|| (armFrom === 'night'
|
|
769
|
+
&& armTo === 'night')
|
|
770
|
+
|| (armFrom === 'stay'
|
|
771
|
+
&& armTo === 'stay')
|
|
772
|
+
|| (armFrom === 'off'
|
|
773
|
+
&& armTo === 'off'
|
|
774
|
+
&& !isAlarmActive)) {
|
|
775
|
+
if (this.#internal.debug) {
|
|
776
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'info', `No need to change arm state from "${armFrom}" to "${armTo}" due to its equivalence`);
|
|
777
|
+
}
|
|
778
|
+
return {
|
|
779
|
+
action: 'SET_PANEL_STATUS',
|
|
780
|
+
success: true,
|
|
781
|
+
info: {
|
|
782
|
+
forceArmRequired: false,
|
|
783
|
+
},
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
if (this.#internal.debug && isAlarmActive) {
|
|
787
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', `Alarm is currently ringing and arm state is being changed from "${armFrom}" to "${armTo}"`);
|
|
788
|
+
}
|
|
732
789
|
try {
|
|
733
|
-
const internet = await this.isPortalAccessible();
|
|
734
790
|
const sessions = {};
|
|
735
|
-
|
|
736
|
-
return {
|
|
737
|
-
action: 'SET_PANEL_STATUS',
|
|
738
|
-
success: false,
|
|
739
|
-
info: internet.info,
|
|
740
|
-
};
|
|
741
|
-
}
|
|
791
|
+
let isAlarmCurrentlyActive = isAlarmActive;
|
|
742
792
|
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
743
793
|
headers: {
|
|
744
794
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
@@ -806,34 +856,44 @@ export class ADTPulse {
|
|
|
806
856
|
const jsdomSummaryOrbSecurityButtons = sessions.jsdomSummary.window.document.querySelectorAll('#divOrbSecurityButtons input');
|
|
807
857
|
const parsedOrbSecurityButtons = parseOrbSecurityButtons(jsdomSummaryOrbSecurityButtons);
|
|
808
858
|
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
|
|
809
|
-
|
|
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) {
|
|
859
|
+
if (parsedOrbSecurityButtons.length < 1 || parsedOrbSecurityButtons.length > 3) {
|
|
816
860
|
if (this.#internal.debug) {
|
|
817
|
-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', '
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
861
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', 'The parseOrbSecurityButtons() function may be parsing the orb security buttons incorrectly');
|
|
862
|
+
}
|
|
863
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
864
|
+
parserName: 'parseOrbSecurityButtons()',
|
|
865
|
+
parserReason: 'length is not between 1 to 3',
|
|
866
|
+
parserResponse: parsedOrbSecurityButtons,
|
|
867
|
+
rawData: sessions.axiosSummary.data,
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton) => !parsedOrbSecurityButton.buttonDisabled);
|
|
871
|
+
if (readyButtons.length === 0 && this.#session.backupSatCode !== null) {
|
|
872
|
+
readyButtons = generateFakeReadyButtons(parsedOrbSecurityButtons, this.#session.isCleanState, {
|
|
826
873
|
relativeUrl: 'quickcontrol/armDisarm.jsp',
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
874
|
+
href: 'rest/adt/ui/client/security/setArmState',
|
|
875
|
+
sat: this.#session.backupSatCode,
|
|
876
|
+
});
|
|
877
|
+
if (this.#internal.debug) {
|
|
878
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', 'No security buttons were found. Replacing stuck orb security buttons with fake buttons');
|
|
879
|
+
stackTracer('fake-ready-buttons', {
|
|
880
|
+
before: parsedOrbSecurityButtons,
|
|
881
|
+
after: readyButtons,
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
if (readyButtons.length === 0 && this.#session.backupSatCode === null) {
|
|
886
|
+
if (this.#internal.debug) {
|
|
887
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'No security buttons were found and replacement failed because no backup sat code exists');
|
|
888
|
+
}
|
|
889
|
+
return {
|
|
890
|
+
action: 'SET_PANEL_STATUS',
|
|
891
|
+
success: false,
|
|
892
|
+
info: {
|
|
893
|
+
message: 'No security buttons were found and replacement failed because no backup sat code exists',
|
|
833
894
|
},
|
|
834
895
|
};
|
|
835
896
|
}
|
|
836
|
-
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton) => !parsedOrbSecurityButton.buttonDisabled);
|
|
837
897
|
if (readyButtons.length < 1) {
|
|
838
898
|
if (this.#internal.debug) {
|
|
839
899
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Security buttons are not found on the summary page');
|
|
@@ -847,7 +907,7 @@ export class ADTPulse {
|
|
|
847
907
|
};
|
|
848
908
|
}
|
|
849
909
|
if (this.#internal.testMode.enabled
|
|
850
|
-
&& !this.#internal.testMode.
|
|
910
|
+
&& !this.#internal.testMode.isSystemDisarmedBeforeTest) {
|
|
851
911
|
if (!['off', 'disarmed'].includes(readyButtons[0].urlParams.armState)) {
|
|
852
912
|
if (this.#internal.debug) {
|
|
853
913
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'Test mode is active and system is not disarmed');
|
|
@@ -860,10 +920,16 @@ export class ADTPulse {
|
|
|
860
920
|
},
|
|
861
921
|
};
|
|
862
922
|
}
|
|
863
|
-
this.#internal.testMode.
|
|
923
|
+
this.#internal.testMode.isSystemDisarmedBeforeTest = true;
|
|
864
924
|
}
|
|
865
|
-
while (!['off', 'disarmed'].includes(readyButtons[0].urlParams.armState)) {
|
|
866
|
-
const armDisarmResponse = await this.armDisarmHandler(
|
|
925
|
+
while (isAlarmCurrentlyActive || !['off', 'disarmed'].includes(readyButtons[0].urlParams.armState)) {
|
|
926
|
+
const armDisarmResponse = await this.armDisarmHandler(isAlarmCurrentlyActive, {
|
|
927
|
+
relativeUrl: readyButtons[0].relativeUrl,
|
|
928
|
+
href: readyButtons[0].urlParams.href,
|
|
929
|
+
armState: readyButtons[0].urlParams.armState,
|
|
930
|
+
arm: 'off',
|
|
931
|
+
sat: readyButtons[0].urlParams.sat,
|
|
932
|
+
});
|
|
867
933
|
if (!armDisarmResponse.success) {
|
|
868
934
|
if (this.#internal.debug) {
|
|
869
935
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'An error occurred in the arm disarm handler (while disarming)');
|
|
@@ -887,10 +953,19 @@ export class ADTPulse {
|
|
|
887
953
|
};
|
|
888
954
|
}
|
|
889
955
|
readyButtons = armDisarmResponse.info.readyButtons;
|
|
956
|
+
if (isAlarmCurrentlyActive) {
|
|
957
|
+
isAlarmCurrentlyActive = false;
|
|
958
|
+
}
|
|
890
959
|
}
|
|
891
960
|
let forceArmRequired = false;
|
|
892
961
|
if (armTo !== 'off') {
|
|
893
|
-
const armDisarmResponse = await this.armDisarmHandler(
|
|
962
|
+
const armDisarmResponse = await this.armDisarmHandler(false, {
|
|
963
|
+
relativeUrl: readyButtons[0].relativeUrl,
|
|
964
|
+
href: readyButtons[0].urlParams.href,
|
|
965
|
+
armState: readyButtons[0].urlParams.armState,
|
|
966
|
+
arm: armTo,
|
|
967
|
+
sat: readyButtons[0].urlParams.sat,
|
|
968
|
+
});
|
|
894
969
|
if (!armDisarmResponse.success) {
|
|
895
970
|
if (this.#internal.debug) {
|
|
896
971
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'error', 'An error occurred in the arm disarm handler (while arming)');
|
|
@@ -904,7 +979,7 @@ export class ADTPulse {
|
|
|
904
979
|
forceArmRequired = armDisarmResponse.info.forceArmRequired;
|
|
905
980
|
}
|
|
906
981
|
if (this.#internal.debug) {
|
|
907
|
-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'success', `Successfully updated panel status to "${armTo}" at "${this.#internal.baseUrl}"`);
|
|
982
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'success', `Successfully updated panel status from "${armFrom}" to "${armTo}" at "${this.#internal.baseUrl}"`);
|
|
908
983
|
}
|
|
909
984
|
return {
|
|
910
985
|
action: 'SET_PANEL_STATUS',
|
|
@@ -935,15 +1010,7 @@ export class ADTPulse {
|
|
|
935
1010
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'info', `Attempting to retrieve sensors information from "${this.#internal.baseUrl}"`);
|
|
936
1011
|
}
|
|
937
1012
|
try {
|
|
938
|
-
const internet = await this.isPortalAccessible();
|
|
939
1013
|
const sessions = {};
|
|
940
|
-
if (!internet.success) {
|
|
941
|
-
return {
|
|
942
|
-
action: 'GET_SENSORS_INFORMATION',
|
|
943
|
-
success: false,
|
|
944
|
-
info: internet.info,
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
1014
|
sessions.axiosSystem = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`, this.getRequestConfig({
|
|
948
1015
|
headers: {
|
|
949
1016
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
@@ -999,9 +1066,20 @@ export class ADTPulse {
|
|
|
999
1066
|
contentType: 'text/html',
|
|
1000
1067
|
pretendToBeVisual: true,
|
|
1001
1068
|
});
|
|
1002
|
-
const jsdomSystemSensorsTable = sessions.jsdomSystem.window.document.querySelectorAll('#systemContentList tr[
|
|
1069
|
+
const jsdomSystemSensorsTable = sessions.jsdomSystem.window.document.querySelectorAll('#systemContentList tr[class^=\'p_row\'] tr.p_listRow');
|
|
1003
1070
|
const parsedSensorsTable = parseSensorsTable(jsdomSystemSensorsTable);
|
|
1004
1071
|
await this.newInformationDispatcher('sensors-information', parsedSensorsTable);
|
|
1072
|
+
if (parsedSensorsTable.length < 1) {
|
|
1073
|
+
if (this.#internal.debug) {
|
|
1074
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'warn', 'The parseSensorsTable() function may be parsing the sensors table incorrectly');
|
|
1075
|
+
}
|
|
1076
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
1077
|
+
parserName: 'parseSensorsTable()',
|
|
1078
|
+
parserReason: 'length is not 1 or more',
|
|
1079
|
+
parserResponse: parsedSensorsTable,
|
|
1080
|
+
rawData: sessions.axiosSystem.data,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1005
1083
|
if (this.#internal.debug) {
|
|
1006
1084
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'success', `Successfully retrieved sensors information from "${this.#internal.baseUrl}"`);
|
|
1007
1085
|
}
|
|
@@ -1034,15 +1112,7 @@ export class ADTPulse {
|
|
|
1034
1112
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'info', `Attempting to retrieve sensors status from "${this.#internal.baseUrl}"`);
|
|
1035
1113
|
}
|
|
1036
1114
|
try {
|
|
1037
|
-
const internet = await this.isPortalAccessible();
|
|
1038
1115
|
const sessions = {};
|
|
1039
|
-
if (!internet.success) {
|
|
1040
|
-
return {
|
|
1041
|
-
action: 'GET_SENSORS_STATUS',
|
|
1042
|
-
success: false,
|
|
1043
|
-
info: internet.info,
|
|
1044
|
-
};
|
|
1045
|
-
}
|
|
1046
1116
|
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
1047
1117
|
headers: {
|
|
1048
1118
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
@@ -1110,6 +1180,17 @@ export class ADTPulse {
|
|
|
1110
1180
|
const jsdomSummaryOrbSensors = sessions.jsdomSummary.window.document.querySelectorAll('#orbSensorsList tr.p_listRow');
|
|
1111
1181
|
const parsedOrbSensors = parseOrbSensors(jsdomSummaryOrbSensors);
|
|
1112
1182
|
await this.newInformationDispatcher('sensors-status', parsedOrbSensors);
|
|
1183
|
+
if (parsedOrbSensors.length < 1) {
|
|
1184
|
+
if (this.#internal.debug) {
|
|
1185
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'warn', 'The parseOrbSensors() function may be parsing the orb sensors incorrectly');
|
|
1186
|
+
}
|
|
1187
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
1188
|
+
parserName: 'parseOrbSensors()',
|
|
1189
|
+
parserReason: 'length is not 1 or more',
|
|
1190
|
+
parserResponse: parsedOrbSensors,
|
|
1191
|
+
rawData: sessions.axiosSummary.data,
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1113
1194
|
if (this.#internal.debug) {
|
|
1114
1195
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'success', `Successfully retrieved sensors status from "${this.#internal.baseUrl}"`);
|
|
1115
1196
|
}
|
|
@@ -1142,15 +1223,7 @@ export class ADTPulse {
|
|
|
1142
1223
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performSyncCheck()', 'info', `Attempting to perform a sync check from "${this.#internal.baseUrl}"`);
|
|
1143
1224
|
}
|
|
1144
1225
|
try {
|
|
1145
|
-
const internet = await this.isPortalAccessible();
|
|
1146
1226
|
const sessions = {};
|
|
1147
|
-
if (!internet.success) {
|
|
1148
|
-
return {
|
|
1149
|
-
action: 'PERFORM_SYNC_CHECK',
|
|
1150
|
-
success: false,
|
|
1151
|
-
info: internet.info,
|
|
1152
|
-
};
|
|
1153
|
-
}
|
|
1154
1227
|
sessions.axiosSyncCheck = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/Ajax/SyncCheckServ?t=${Date.now()}`, this.getRequestConfig({
|
|
1155
1228
|
headers: {
|
|
1156
1229
|
Accept: '*/*',
|
|
@@ -1249,15 +1322,7 @@ export class ADTPulse {
|
|
|
1249
1322
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.performKeepAlive()', 'info', `Attempting to perform a keep alive from "${this.#internal.baseUrl}"`);
|
|
1250
1323
|
}
|
|
1251
1324
|
try {
|
|
1252
|
-
const internet = await this.isPortalAccessible();
|
|
1253
1325
|
const sessions = {};
|
|
1254
|
-
if (!internet.success) {
|
|
1255
|
-
return {
|
|
1256
|
-
action: 'PERFORM_KEEP_ALIVE',
|
|
1257
|
-
success: false,
|
|
1258
|
-
info: internet.info,
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
1326
|
sessions.axiosKeepAlive = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/KeepAlive`, '', this.getRequestConfig({
|
|
1262
1327
|
headers: {
|
|
1263
1328
|
Accept: '*/*',
|
|
@@ -1330,16 +1395,40 @@ export class ADTPulse {
|
|
|
1330
1395
|
isAuthenticated() {
|
|
1331
1396
|
return this.#session.isAuthenticated;
|
|
1332
1397
|
}
|
|
1333
|
-
|
|
1398
|
+
resetSession() {
|
|
1399
|
+
this.#session = {
|
|
1400
|
+
backupSatCode: null,
|
|
1401
|
+
httpClient: wrapper(axios.create({
|
|
1402
|
+
jar: new CookieJar(),
|
|
1403
|
+
validateStatus: () => true,
|
|
1404
|
+
})),
|
|
1405
|
+
isAuthenticated: false,
|
|
1406
|
+
isCleanState: true,
|
|
1407
|
+
networkId: null,
|
|
1408
|
+
portalVersion: null,
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
async armDisarmHandler(isAlarmActive, options) {
|
|
1334
1412
|
let errorObject;
|
|
1335
1413
|
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}"`);
|
|
1414
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `Attempting to update arm state from "${options.armState}" to "${options.arm}" on "${this.#internal.baseUrl}"`);
|
|
1337
1415
|
}
|
|
1338
|
-
if (armState ===
|
|
1339
|
-
|
|
1340
|
-
|
|
1416
|
+
if ((options.armState === 'away'
|
|
1417
|
+
&& options.arm === 'away')
|
|
1418
|
+
|| (options.armState === 'night'
|
|
1419
|
+
&& options.arm === 'night')
|
|
1420
|
+
|| (options.armState === 'night+stay'
|
|
1421
|
+
&& options.arm === 'night')
|
|
1422
|
+
|| (options.armState === 'stay'
|
|
1423
|
+
&& options.arm === 'stay')
|
|
1424
|
+
|| (options.armState === 'disarmed'
|
|
1425
|
+
&& options.arm === 'off'
|
|
1426
|
+
&& !isAlarmActive)
|
|
1427
|
+
|| (options.armState === 'off'
|
|
1428
|
+
&& options.arm === 'off'
|
|
1429
|
+
&& !isAlarmActive)) {
|
|
1341
1430
|
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`);
|
|
1431
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'info', `No need to change arm state from "${options.armState}" to "${options.arm}" due to its equivalence`);
|
|
1343
1432
|
}
|
|
1344
1433
|
return {
|
|
1345
1434
|
action: 'ARM_DISARM_HANDLER',
|
|
@@ -1351,21 +1440,13 @@ export class ADTPulse {
|
|
|
1351
1440
|
};
|
|
1352
1441
|
}
|
|
1353
1442
|
try {
|
|
1354
|
-
const internet = await this.isPortalAccessible();
|
|
1355
1443
|
const sessions = {};
|
|
1356
|
-
if (!internet.success) {
|
|
1357
|
-
return {
|
|
1358
|
-
action: 'ARM_DISARM_HANDLER',
|
|
1359
|
-
success: false,
|
|
1360
|
-
info: internet.info,
|
|
1361
|
-
};
|
|
1362
|
-
}
|
|
1363
1444
|
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({
|
|
1445
|
+
armDisarmForm.append('href', options.href);
|
|
1446
|
+
armDisarmForm.append('armstate', options.armState);
|
|
1447
|
+
armDisarmForm.append('arm', options.arm);
|
|
1448
|
+
armDisarmForm.append('sat', options.sat);
|
|
1449
|
+
sessions.axiosSetArmMode = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/${options.relativeUrl}`, armDisarmForm, this.getRequestConfig({
|
|
1369
1450
|
headers: {
|
|
1370
1451
|
'Cache-Control': 'max-age=0',
|
|
1371
1452
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -1409,8 +1490,8 @@ export class ADTPulse {
|
|
|
1409
1490
|
};
|
|
1410
1491
|
}
|
|
1411
1492
|
let forceArmRequired = false;
|
|
1412
|
-
if (arm !== 'off') {
|
|
1413
|
-
const forceArmResponse = await this.forceArmHandler(sessions.axiosSetArmMode, relativeUrl);
|
|
1493
|
+
if (options.arm !== 'off') {
|
|
1494
|
+
const forceArmResponse = await this.forceArmHandler(sessions.axiosSetArmMode, options.relativeUrl);
|
|
1414
1495
|
if (!forceArmResponse.success) {
|
|
1415
1496
|
if (this.#internal.debug) {
|
|
1416
1497
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'error', 'An error occurred in the force arm handler');
|
|
@@ -1424,7 +1505,7 @@ export class ADTPulse {
|
|
|
1424
1505
|
forceArmRequired = forceArmResponse.info.forceArmRequired;
|
|
1425
1506
|
}
|
|
1426
1507
|
this.#session.isCleanState = false;
|
|
1427
|
-
await sleep(
|
|
1508
|
+
await sleep(this.#internal.waitTimeAfterArm);
|
|
1428
1509
|
sessions.axiosSummary = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`, this.getRequestConfig({
|
|
1429
1510
|
headers: {
|
|
1430
1511
|
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
@@ -1492,31 +1573,34 @@ export class ADTPulse {
|
|
|
1492
1573
|
const jsdomSummaryOrbSecurityButtons = sessions.jsdomSummary.window.document.querySelectorAll('#divOrbSecurityButtons input');
|
|
1493
1574
|
const parsedOrbSecurityButtons = parseOrbSecurityButtons(jsdomSummaryOrbSecurityButtons);
|
|
1494
1575
|
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
|
|
1576
|
+
if (parsedOrbSecurityButtons.length < 1 || parsedOrbSecurityButtons.length > 3) {
|
|
1577
|
+
if (this.#internal.debug) {
|
|
1578
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'warn', 'The parseOrbSecurityButtons() function may be parsing the orb security buttons incorrectly');
|
|
1579
|
+
}
|
|
1580
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
1581
|
+
parserName: 'parseOrbSecurityButtons()',
|
|
1582
|
+
parserReason: 'length is not between 1 to 3',
|
|
1583
|
+
parserResponse: parsedOrbSecurityButtons,
|
|
1584
|
+
rawData: sessions.axiosSummary.data,
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1495
1587
|
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton) => !parsedOrbSecurityButton.buttonDisabled);
|
|
1496
|
-
if (
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
urlParams: {
|
|
1510
|
-
arm: 'off',
|
|
1511
|
-
armState: (this.#session.isCleanState) ? 'night' : 'night+stay',
|
|
1512
|
-
href,
|
|
1513
|
-
sat,
|
|
1514
|
-
},
|
|
1515
|
-
},
|
|
1516
|
-
];
|
|
1588
|
+
if (readyButtons.length === 0) {
|
|
1589
|
+
readyButtons = generateFakeReadyButtons(parsedOrbSecurityButtons, this.#session.isCleanState, {
|
|
1590
|
+
relativeUrl: options.relativeUrl,
|
|
1591
|
+
href: options.href,
|
|
1592
|
+
sat: options.sat,
|
|
1593
|
+
});
|
|
1594
|
+
if (this.#internal.debug) {
|
|
1595
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'warn', 'No security buttons were found. Replacing stuck orb security buttons with fake buttons');
|
|
1596
|
+
stackTracer('fake-ready-buttons', {
|
|
1597
|
+
before: parsedOrbSecurityButtons,
|
|
1598
|
+
after: readyButtons,
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1517
1601
|
}
|
|
1518
1602
|
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}"`);
|
|
1603
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'success', `Successfully updated arm state from "${options.armState}" to "${options.arm}" on "${this.#internal.baseUrl}"`);
|
|
1520
1604
|
}
|
|
1521
1605
|
return {
|
|
1522
1606
|
action: 'ARM_DISARM_HANDLER',
|
|
@@ -1548,15 +1632,7 @@ export class ADTPulse {
|
|
|
1548
1632
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'info', `Attempting to force arm on "${this.#internal.baseUrl}"`);
|
|
1549
1633
|
}
|
|
1550
1634
|
try {
|
|
1551
|
-
const internet = await this.isPortalAccessible();
|
|
1552
1635
|
const sessions = {};
|
|
1553
|
-
if (!internet.success) {
|
|
1554
|
-
return {
|
|
1555
|
-
action: 'FORCE_ARM_HANDLER',
|
|
1556
|
-
success: false,
|
|
1557
|
-
info: internet.info,
|
|
1558
|
-
};
|
|
1559
|
-
}
|
|
1560
1636
|
if (typeof response.data !== 'string') {
|
|
1561
1637
|
if (this.#internal.debug) {
|
|
1562
1638
|
debugLog(this.#internal.logger, 'api.ts / ADTPulse.forceArmHandler()', 'error', 'The response body of the arm disarm page is not of type "string"');
|
|
@@ -1580,6 +1656,17 @@ export class ADTPulse {
|
|
|
1580
1656
|
const parsedArmDisarmMessage = parseArmDisarmMessage(jsdomArmDisarmArmDisarmMessage);
|
|
1581
1657
|
const parsedDoSubmitHandlers = parseDoSubmitHandlers(jsdomArmDisarmDoSubmitHandlers);
|
|
1582
1658
|
await this.newInformationDispatcher('do-submit-handlers', parsedDoSubmitHandlers);
|
|
1659
|
+
if (parsedDoSubmitHandlers.length !== 2) {
|
|
1660
|
+
if (this.#internal.debug) {
|
|
1661
|
+
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'warn', 'The parseDoSubmitHandlers() function may be parsing the do submit handlers incorrectly');
|
|
1662
|
+
}
|
|
1663
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
1664
|
+
parserName: 'parseDoSubmitHandlers()',
|
|
1665
|
+
parserReason: 'length does not equal to 2',
|
|
1666
|
+
parserResponse: parsedDoSubmitHandlers,
|
|
1667
|
+
rawData: response.data,
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1583
1670
|
if (parsedDoSubmitHandlers.length === 0
|
|
1584
1671
|
|| parsedArmDisarmMessage === null) {
|
|
1585
1672
|
if (this.#internal.testMode.enabled) {
|
|
@@ -1731,77 +1818,37 @@ export class ADTPulse {
|
|
|
1731
1818
|
},
|
|
1732
1819
|
};
|
|
1733
1820
|
}
|
|
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
1821
|
async newInformationDispatcher(type, data) {
|
|
1778
1822
|
const dataHash = generateHash(`${type}: ${JSON.stringify(data)}`);
|
|
1779
1823
|
if (this.#internal.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {
|
|
1780
1824
|
let detectedNew = false;
|
|
1781
1825
|
switch (type) {
|
|
1826
|
+
case 'debug-parser':
|
|
1827
|
+
detectedNew = await detectApiDebugParser(data, this.#internal.logger, this.#internal.debug);
|
|
1828
|
+
break;
|
|
1782
1829
|
case 'do-submit-handlers':
|
|
1783
|
-
detectedNew = await
|
|
1830
|
+
detectedNew = await detectApiDoSubmitHandlers(data, this.#internal.logger, this.#internal.debug);
|
|
1784
1831
|
break;
|
|
1785
1832
|
case 'gateway-information':
|
|
1786
|
-
detectedNew = await
|
|
1833
|
+
detectedNew = await detectApiGatewayInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1787
1834
|
break;
|
|
1788
1835
|
case 'orb-security-buttons':
|
|
1789
|
-
detectedNew = await
|
|
1836
|
+
detectedNew = await detectApiOrbSecurityButtons(data, this.#internal.logger, this.#internal.debug);
|
|
1790
1837
|
break;
|
|
1791
1838
|
case 'panel-information':
|
|
1792
|
-
detectedNew = await
|
|
1839
|
+
detectedNew = await detectApiPanelInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1793
1840
|
break;
|
|
1794
1841
|
case 'panel-status':
|
|
1795
|
-
detectedNew = await
|
|
1842
|
+
detectedNew = await detectApiPanelStatus(data, this.#internal.logger, this.#internal.debug);
|
|
1796
1843
|
break;
|
|
1797
1844
|
case 'portal-version':
|
|
1798
|
-
detectedNew = await
|
|
1845
|
+
detectedNew = await detectApiPortalVersion(data, this.#internal.logger, this.#internal.debug);
|
|
1799
1846
|
break;
|
|
1800
1847
|
case 'sensors-information':
|
|
1801
|
-
detectedNew = await
|
|
1848
|
+
detectedNew = await detectApiSensorsInformation(data, this.#internal.logger, this.#internal.debug);
|
|
1802
1849
|
break;
|
|
1803
1850
|
case 'sensors-status':
|
|
1804
|
-
detectedNew = await
|
|
1851
|
+
detectedNew = await detectApiSensorsStatus(data, this.#internal.logger, this.#internal.debug);
|
|
1805
1852
|
break;
|
|
1806
1853
|
default:
|
|
1807
1854
|
break;
|
|
@@ -1818,8 +1865,10 @@ export class ADTPulse {
|
|
|
1818
1865
|
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
1866
|
'Accept-Encoding': 'gzip, deflate, br',
|
|
1820
1867
|
'Accept-Language': 'en-US,en;q=0.9',
|
|
1868
|
+
'Cache-Control': 'no-cache',
|
|
1821
1869
|
Connection: 'keep-alive',
|
|
1822
1870
|
Host: `${this.#credentials.subdomain}.adtpulse.com`,
|
|
1871
|
+
Pragma: 'no-cache',
|
|
1823
1872
|
'Sec-Fetch-Dest': 'document',
|
|
1824
1873
|
'Sec-Fetch-Mode': 'navigate',
|
|
1825
1874
|
'Sec-Fetch-Site': 'none',
|
|
@@ -1831,7 +1880,6 @@ export class ADTPulse {
|
|
|
1831
1880
|
'sec-ch-ua-platform': '"macOS"',
|
|
1832
1881
|
},
|
|
1833
1882
|
timeout: 15000,
|
|
1834
|
-
validateStatus: undefined,
|
|
1835
1883
|
};
|
|
1836
1884
|
if (extraConfig === undefined) {
|
|
1837
1885
|
return defaultConfig;
|
|
@@ -1843,11 +1891,11 @@ export class ADTPulse {
|
|
|
1843
1891
|
return;
|
|
1844
1892
|
}
|
|
1845
1893
|
if (requestPathAccessSignIn.test(requestPath)
|
|
1846
|
-
||
|
|
1894
|
+
|| requestPathAccessSignInEXxPartnerAdt.test(requestPath)
|
|
1847
1895
|
|| requestPathMfaMfaSignInWorkflowChallenge.test(requestPath)) {
|
|
1848
1896
|
if (this.#internal.debug) {
|
|
1849
1897
|
const errorMessage = fetchErrorMessage(session);
|
|
1850
|
-
if (requestPathAccessSignIn.test(requestPath) ||
|
|
1898
|
+
if (requestPathAccessSignIn.test(requestPath) || requestPathAccessSignInEXxPartnerAdt.test(requestPath)) {
|
|
1851
1899
|
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
1900
|
}
|
|
1853
1901
|
if (requestPathMfaMfaSignInWorkflowChallenge.test(requestPath)) {
|
|
@@ -1860,17 +1908,5 @@ export class ADTPulse {
|
|
|
1860
1908
|
this.resetSession();
|
|
1861
1909
|
}
|
|
1862
1910
|
}
|
|
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
1911
|
}
|
|
1876
1912
|
//# sourceMappingURL=api.js.map
|