homebridge-adt-pulse 2.1.1 → 2.1.4
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/README.md +12 -6
- package/api-test.js +280 -0
- package/api.js +112 -79
- package/config.schema.json +1 -1
- package/index.js +6 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,16 +66,22 @@ If you have a sensor that is unsupported by this plugin, please [submit an issue
|
|
|
66
66
|
Due to ADT Pulse limitations, accessories that are connected to the Z-Wave Platform cannot be supported. Consider using other Homebridge plugins.
|
|
67
67
|
|
|
68
68
|
## Configure 2-Factor Authentication
|
|
69
|
-
With the recent updates, ADT Pulse now requires 2-factor authentication for your account. In the near future, this fingerprint will be required.
|
|
69
|
+
With the recent updates, ADT Pulse now requires 2-factor authentication for your account. In the near future, this fingerprint will be required. Before you begin, make sure 2-Factor Authentication is already setup.
|
|
70
70
|
|
|
71
|
-
1. Open a Chrome browser tab
|
|
71
|
+
1. Open a Chrome browser tab (under Incognito mode)
|
|
72
72
|
2. Open Developer Tools (using **View** ➜ **Developer** ➜ **Developer Tools** menu)
|
|
73
73
|
3. Click on the **Network** tab (make sure **Preserve log** checkbox is checked)
|
|
74
|
-
4. In the filter box, enter
|
|
74
|
+
4. In the filter box, enter `signin.jsp?networkid=`
|
|
75
75
|
5. Go to `https://portal.adtpulse.com` or `https://portal-ca.adtpulse.com` and login to your account
|
|
76
|
-
6. Click
|
|
77
|
-
7.
|
|
78
|
-
8.
|
|
76
|
+
6. Click **Request Code**, type in the requested code, and then click **Submit Code**
|
|
77
|
+
7. Click **Trust this device** and name the device `Homebridge`
|
|
78
|
+
8. Click **Save and Continue**
|
|
79
|
+
9. Click **Sign Out** in the top right corner of the webpage
|
|
80
|
+
10. Login to your account (once again)
|
|
81
|
+
11. Click on the network call (beginning with `signin.jsp?networkid=`) appearing in the DevTools window. Select the last one.
|
|
82
|
+
12. In the **Payload** tab, under **Form Data**, copy the entire **fingerprint** (after `fingerprint:`, do not include spaces)
|
|
83
|
+
13. Paste the copied text into the `fingerprint` field into your `config.json`
|
|
84
|
+
14. Close the Chrome window (DO NOT sign out)
|
|
79
85
|
|
|
80
86
|
## Force Arming (Arm Away/Stay/Night)
|
|
81
87
|
Due to the nature of how HomeKit and ADT Pulse processes `setDeviceStatus` commands, this plugin will force arm when it detects active motion or open sensors.
|
package/api-test.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADT Pulse Test.
|
|
3
|
+
*
|
|
4
|
+
* Test the ADT Pulse API responses using this script.
|
|
5
|
+
*
|
|
6
|
+
* Arguments:
|
|
7
|
+
* --username email@email.com
|
|
8
|
+
* --password 1234567890
|
|
9
|
+
* --fingerprint 2-factor authentication token
|
|
10
|
+
* --country "us" or "ca"
|
|
11
|
+
* --action "device-information", "device-status", "zone-status", "sync", "disarm", "arm-away", "arm-stay", or "arm-night"
|
|
12
|
+
* --overrideSensorName Sensor name as shown in ADT Pulse
|
|
13
|
+
* --overrideSensorType "sensor,glass", "sensor,motion", "sensor,co", "sensor,fire", or "sensor,doorWindow"
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* node api-test --username ! --password % --fingerprint ^ --country # --action @ --overrideSensorName $ --overrideSensorType ~
|
|
17
|
+
*
|
|
18
|
+
* Replace:
|
|
19
|
+
* ! - Account username
|
|
20
|
+
* % - Account password
|
|
21
|
+
* ^ - Fingerprint
|
|
22
|
+
* # - Country
|
|
23
|
+
* @ - Action type
|
|
24
|
+
* $ - Override sensor name (optional)
|
|
25
|
+
* ~ - Override sensor type (optional)
|
|
26
|
+
*
|
|
27
|
+
* @type {function(object): void}
|
|
28
|
+
*
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
*/
|
|
31
|
+
const Pulse = require('./api');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Script arguments.
|
|
35
|
+
*
|
|
36
|
+
* @since 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
const username = process.argv.indexOf('--username');
|
|
39
|
+
const usernameValue = (username > -1) ? process.argv[username + 1] : '';
|
|
40
|
+
|
|
41
|
+
const password = process.argv.indexOf('--password');
|
|
42
|
+
const passwordValue = (password > -1) ? process.argv[password + 1] : '';
|
|
43
|
+
|
|
44
|
+
const fingerprint = process.argv.indexOf('--fingerprint');
|
|
45
|
+
const fingerprintValue = (fingerprint > -1) ? process.argv[fingerprint + 1] : '';
|
|
46
|
+
|
|
47
|
+
const country = process.argv.indexOf('--country');
|
|
48
|
+
const countryValue = (country > -1) ? process.argv[country + 1] : '';
|
|
49
|
+
|
|
50
|
+
const action = process.argv.indexOf('--action');
|
|
51
|
+
const actionValue = (action > -1) ? process.argv[action + 1] : '';
|
|
52
|
+
|
|
53
|
+
const overrideSensorName = process.argv.indexOf('--overrideSensorName');
|
|
54
|
+
const overrideSensorNameValue = (overrideSensorName > -1) ? process.argv[overrideSensorName + 1] : '';
|
|
55
|
+
|
|
56
|
+
const overrideSensorType = process.argv.indexOf('--overrideSensorType');
|
|
57
|
+
const overrideSensorTypeValue = (overrideSensorType > -1) ? process.argv[overrideSensorType + 1] : '';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Sanitize arguments.
|
|
61
|
+
*
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
*/
|
|
64
|
+
if (!usernameValue || !passwordValue || !fingerprintValue || !countryValue || !actionValue) {
|
|
65
|
+
if (!usernameValue) {
|
|
66
|
+
console.error('ADT Pulse Test: Username is empty.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!passwordValue) {
|
|
70
|
+
console.error('ADT Pulse Test: Password is empty.');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!fingerprintValue) {
|
|
74
|
+
console.error('ADT Pulse Test: Fingerprint is empty.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!countryValue) {
|
|
78
|
+
console.error('ADT Pulse Test: Country is empty.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!actionValue) {
|
|
82
|
+
console.error('ADT Pulse Test: Action is empty.');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Initialize main script.
|
|
90
|
+
*
|
|
91
|
+
* @type {Pulse}
|
|
92
|
+
*
|
|
93
|
+
* @since 1.0.0
|
|
94
|
+
*/
|
|
95
|
+
const pulse = new Pulse({
|
|
96
|
+
username: usernameValue,
|
|
97
|
+
password: passwordValue,
|
|
98
|
+
fingerprint: fingerprintValue,
|
|
99
|
+
overrideSensors: (overrideSensorNameValue && overrideSensorTypeValue) ? [{
|
|
100
|
+
name: overrideSensorNameValue,
|
|
101
|
+
type: overrideSensorTypeValue,
|
|
102
|
+
}] : [],
|
|
103
|
+
country: countryValue,
|
|
104
|
+
debug: true,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Actions.
|
|
109
|
+
*
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
*/
|
|
112
|
+
switch (actionValue) {
|
|
113
|
+
case 'device-information':
|
|
114
|
+
console.log('ADT Pulse Test: Getting device information...');
|
|
115
|
+
|
|
116
|
+
pulse
|
|
117
|
+
.login()
|
|
118
|
+
.then((login) => console.log(login))
|
|
119
|
+
.then(() => pulse.getDeviceInformation())
|
|
120
|
+
.then((information) => console.log(information))
|
|
121
|
+
.then(() => pulse.logout())
|
|
122
|
+
.then((logout) => console.log(logout))
|
|
123
|
+
.catch((error) => console.error(error));
|
|
124
|
+
break;
|
|
125
|
+
case 'device-status':
|
|
126
|
+
console.log('ADT Pulse Test: Getting device status...');
|
|
127
|
+
|
|
128
|
+
pulse
|
|
129
|
+
.login()
|
|
130
|
+
.then((login) => console.log(login))
|
|
131
|
+
.then(() => pulse.getDeviceStatus())
|
|
132
|
+
.then((status) => console.log(status))
|
|
133
|
+
.then(() => pulse.logout())
|
|
134
|
+
.then((logout) => console.log(logout))
|
|
135
|
+
.catch((error) => console.error(error));
|
|
136
|
+
break;
|
|
137
|
+
case 'zone-status':
|
|
138
|
+
console.log('ADT Pulse Test: Getting zone status...');
|
|
139
|
+
|
|
140
|
+
pulse
|
|
141
|
+
.login()
|
|
142
|
+
.then((login) => console.log(login))
|
|
143
|
+
.then(() => pulse.getZoneStatus())
|
|
144
|
+
.then((statuses) => console.log(statuses))
|
|
145
|
+
.then(() => pulse.logout())
|
|
146
|
+
.then((logout) => console.log(logout))
|
|
147
|
+
.catch((error) => console.error(error));
|
|
148
|
+
break;
|
|
149
|
+
case 'sync':
|
|
150
|
+
console.log('ADT Pulse Test: Performing portal sync...');
|
|
151
|
+
|
|
152
|
+
pulse
|
|
153
|
+
.login()
|
|
154
|
+
.then((login) => console.log(login))
|
|
155
|
+
.then(() => pulse.performPortalSync())
|
|
156
|
+
.then((syncCode) => console.log(syncCode))
|
|
157
|
+
.then(() => pulse.logout())
|
|
158
|
+
.then((logout) => console.log(logout))
|
|
159
|
+
.catch((error) => console.error(error));
|
|
160
|
+
break;
|
|
161
|
+
case 'disarm':
|
|
162
|
+
console.log('ADT Pulse Test: Disarming...');
|
|
163
|
+
|
|
164
|
+
pulse
|
|
165
|
+
.login()
|
|
166
|
+
.then((login) => console.log(login))
|
|
167
|
+
.then(() => pulse.getDeviceStatus())
|
|
168
|
+
.then((status) => console.log(status))
|
|
169
|
+
.then(async () => {
|
|
170
|
+
/**
|
|
171
|
+
* setDeviceStatus function may fail because a wrong armState was set.
|
|
172
|
+
*/
|
|
173
|
+
await pulse
|
|
174
|
+
.setDeviceStatus('away', 'off')
|
|
175
|
+
.then((response) => console.log(response))
|
|
176
|
+
.catch((error) => console.error(error));
|
|
177
|
+
})
|
|
178
|
+
.then(() => {
|
|
179
|
+
setTimeout(() => {
|
|
180
|
+
pulse
|
|
181
|
+
.getDeviceStatus()
|
|
182
|
+
.then((status) => console.log(status))
|
|
183
|
+
.then(() => pulse.logout())
|
|
184
|
+
.then((logout) => console.log(logout))
|
|
185
|
+
.catch((error) => console.error(error));
|
|
186
|
+
}, 1000);
|
|
187
|
+
})
|
|
188
|
+
.catch((error) => console.error(error));
|
|
189
|
+
break;
|
|
190
|
+
case 'arm-away':
|
|
191
|
+
console.log('ADT Pulse Test: Arming away...');
|
|
192
|
+
|
|
193
|
+
pulse
|
|
194
|
+
.login()
|
|
195
|
+
.then((login) => console.log(login))
|
|
196
|
+
.then(() => pulse.getDeviceStatus())
|
|
197
|
+
.then((status) => console.log(status))
|
|
198
|
+
.then(async () => {
|
|
199
|
+
/**
|
|
200
|
+
* setDeviceStatus function may fail because a wrong armState was set.
|
|
201
|
+
*/
|
|
202
|
+
await pulse
|
|
203
|
+
.setDeviceStatus('disarmed', 'away')
|
|
204
|
+
.then((response) => console.log(response))
|
|
205
|
+
.catch((error) => console.error(error));
|
|
206
|
+
})
|
|
207
|
+
.then(() => {
|
|
208
|
+
setTimeout(() => {
|
|
209
|
+
pulse
|
|
210
|
+
.getDeviceStatus()
|
|
211
|
+
.then((status) => console.log(status))
|
|
212
|
+
.then(() => pulse.logout())
|
|
213
|
+
.then((logout) => console.log(logout))
|
|
214
|
+
.catch((error) => console.error(error));
|
|
215
|
+
}, 1000);
|
|
216
|
+
})
|
|
217
|
+
.catch((error) => console.error(error));
|
|
218
|
+
break;
|
|
219
|
+
case 'arm-stay':
|
|
220
|
+
console.log('ADT Pulse Test: Arming stay...');
|
|
221
|
+
|
|
222
|
+
pulse
|
|
223
|
+
.login()
|
|
224
|
+
.then((login) => console.log(login))
|
|
225
|
+
.then(() => pulse.getDeviceStatus())
|
|
226
|
+
.then((status) => console.log(status))
|
|
227
|
+
.then(async () => {
|
|
228
|
+
/**
|
|
229
|
+
* setDeviceStatus function may fail because a wrong armState was set.
|
|
230
|
+
*/
|
|
231
|
+
await pulse
|
|
232
|
+
.setDeviceStatus('disarmed', 'stay')
|
|
233
|
+
.then((response) => console.log(response))
|
|
234
|
+
.catch((error) => console.error(error));
|
|
235
|
+
})
|
|
236
|
+
.then(() => {
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
pulse
|
|
239
|
+
.getDeviceStatus()
|
|
240
|
+
.then((status) => console.log(status))
|
|
241
|
+
.then(() => pulse.logout())
|
|
242
|
+
.then((logout) => console.log(logout))
|
|
243
|
+
.catch((error) => console.error(error));
|
|
244
|
+
}, 1000);
|
|
245
|
+
})
|
|
246
|
+
.catch((error) => console.error(error));
|
|
247
|
+
break;
|
|
248
|
+
case 'arm-night':
|
|
249
|
+
console.log('ADT Pulse Test: Arming night...');
|
|
250
|
+
|
|
251
|
+
pulse
|
|
252
|
+
.login()
|
|
253
|
+
.then((login) => console.log(login))
|
|
254
|
+
.then(() => pulse.getDeviceStatus())
|
|
255
|
+
.then((status) => console.log(status))
|
|
256
|
+
.then(async () => {
|
|
257
|
+
/**
|
|
258
|
+
* setDeviceStatus function may fail because a wrong armState was set.
|
|
259
|
+
*/
|
|
260
|
+
await pulse
|
|
261
|
+
.setDeviceStatus('disarmed', 'night')
|
|
262
|
+
.then((response) => console.log(response))
|
|
263
|
+
.catch((error) => console.error(error));
|
|
264
|
+
})
|
|
265
|
+
.then(() => {
|
|
266
|
+
setTimeout(() => {
|
|
267
|
+
pulse
|
|
268
|
+
.getDeviceStatus()
|
|
269
|
+
.then((status) => console.log(status))
|
|
270
|
+
.then(() => pulse.logout())
|
|
271
|
+
.then((logout) => console.log(logout))
|
|
272
|
+
.catch((error) => console.error(error));
|
|
273
|
+
}, 1000);
|
|
274
|
+
})
|
|
275
|
+
.catch((error) => console.error(error));
|
|
276
|
+
break;
|
|
277
|
+
default:
|
|
278
|
+
console.error(`ADT Pulse Test: Unknown action type ${actionValue}.`);
|
|
279
|
+
break;
|
|
280
|
+
}
|
package/api.js
CHANGED
|
@@ -419,19 +419,20 @@ Pulse.prototype.getDeviceStatus = function getDeviceStatus() {
|
|
|
419
419
|
* - When Arming Night, armState will be set to "night+stay". It will be set to "night" after re-login.
|
|
420
420
|
* - If alarm occurred, you must Clear Alarm before setting to Armed Away/Stay/Night.
|
|
421
421
|
* - For ADT Pulse Canada, you must replace the "portal" sub-domain to "portal-ca" sub-domain.
|
|
422
|
+
* - "sat" code is now required for all set actions.
|
|
422
423
|
*
|
|
423
424
|
* Disarmed:
|
|
424
|
-
* - Arm Away (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=away).
|
|
425
|
-
* - Arm Stay (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=stay).
|
|
426
|
-
* - Arm Night (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=night).
|
|
427
|
-
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=off).
|
|
428
|
-
* - Clear Alarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed+with+alarm&arm=off).
|
|
425
|
+
* - Arm Away (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=away&sat=).
|
|
426
|
+
* - Arm Stay (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=stay&sat=).
|
|
427
|
+
* - Arm Night (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=night&sat=).
|
|
428
|
+
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed&arm=off&sat=).
|
|
429
|
+
* - Clear Alarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=disarmed+with+alarm&arm=off&sat=).
|
|
429
430
|
* Armed Away:
|
|
430
|
-
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=away&arm=off).
|
|
431
|
+
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=away&arm=off&sat=).
|
|
431
432
|
* Armed Stay:
|
|
432
|
-
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=stay&arm=off).
|
|
433
|
+
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=stay&arm=off&sat=).
|
|
433
434
|
* Armed Night:
|
|
434
|
-
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=night&arm=off).
|
|
435
|
+
* - Disarm (https://portal.adtpulse.com/myhome/quickcontrol/armDisarm.jsp?href=rest/adt/ui/client/security/setArmState&armstate=night&arm=off&sat=).
|
|
435
436
|
*
|
|
436
437
|
* @param {string} armState - Can be "disarmed", "disarmed+with+alarm", "away", "stay", or "night".
|
|
437
438
|
* @param {string} arm - Can be "off", "away", "stay", or "night".
|
|
@@ -444,26 +445,21 @@ Pulse.prototype.setDeviceStatus = function setDeviceStatus(armState, arm) {
|
|
|
444
445
|
const deferred = Q.defer();
|
|
445
446
|
|
|
446
447
|
this.hasInternetWrapper(deferred, () => {
|
|
447
|
-
const
|
|
448
|
-
const arg = `?href=rest/adt/ui/client/security/setArmState&armstate=${armState}&arm=${arm}`;
|
|
448
|
+
const url1 = `https://${countrySubDomain}.adtpulse.com/myhome/${lastKnownVersion}/summary/summary.jsp`;
|
|
449
449
|
|
|
450
450
|
this.consoleLogger('ADT Pulse: Setting device status...', 'log');
|
|
451
451
|
|
|
452
452
|
request.get(
|
|
453
|
-
|
|
454
|
-
this.generateRequestOptions(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}),
|
|
459
|
-
(error, response, body) => {
|
|
460
|
-
const regex = new RegExp(/(\/myhome\/)([0-9.-]+)(\/quickcontrol\/armDisarm\.jsp)(.*)/);
|
|
461
|
-
const responsePath = _.get(response, 'request.uri.path');
|
|
453
|
+
url1,
|
|
454
|
+
this.generateRequestOptions(),
|
|
455
|
+
(error1, response1, body1) => {
|
|
456
|
+
const regex1 = new RegExp(/(\/myhome\/)([0-9.-]+)(\/summary\/summary\.jsp)(.*)/);
|
|
457
|
+
const responsePath1 = _.get(response1, 'request.uri.path');
|
|
462
458
|
|
|
463
|
-
this.consoleLogger(`ADT Pulse: Response path -> ${
|
|
464
|
-
this.consoleLogger(`ADT Pulse: Response path matches -> ${
|
|
459
|
+
this.consoleLogger(`ADT Pulse: Response path -> ${responsePath1}`, 'log');
|
|
460
|
+
this.consoleLogger(`ADT Pulse: Response path matches -> ${regex1.test(responsePath1)}`, 'log');
|
|
465
461
|
|
|
466
|
-
if (
|
|
462
|
+
if (error1 || !regex1.test(responsePath1)) {
|
|
467
463
|
authenticated = false;
|
|
468
464
|
|
|
469
465
|
this.consoleLogger(`ADT Pulse: Set device status to ${arm} failed.`, 'error');
|
|
@@ -472,50 +468,99 @@ Pulse.prototype.setDeviceStatus = function setDeviceStatus(armState, arm) {
|
|
|
472
468
|
action: 'SET_DEVICE_STATUS',
|
|
473
469
|
success: false,
|
|
474
470
|
info: {
|
|
475
|
-
error,
|
|
476
|
-
message: this.getErrorMessage(
|
|
471
|
+
error: error1,
|
|
472
|
+
message: this.getErrorMessage(body1),
|
|
477
473
|
},
|
|
478
474
|
});
|
|
479
475
|
} else {
|
|
480
|
-
const $ = cheerio.load(
|
|
481
|
-
const
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
})
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
this.consoleLogger(`ADT Pulse:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
476
|
+
const $2 = cheerio.load(body1);
|
|
477
|
+
const onClick2 = $2('input[id^="security_button_"]').attr('onclick');
|
|
478
|
+
const satCode2 = (onClick2 !== undefined) ? onClick2.replace(/(.*)(&sat=)([0-9a-z-]*)('\))/g, '$3') : undefined;
|
|
479
|
+
const url2 = `https://${countrySubDomain}.adtpulse.com/myhome/${lastKnownVersion}/quickcontrol/armDisarm.jsp`;
|
|
480
|
+
const arg2 = `?href=rest/adt/ui/client/security/setArmState&armstate=${armState}&arm=${arm}&sat=${satCode2}`;
|
|
481
|
+
|
|
482
|
+
request.get(
|
|
483
|
+
url2 + arg2,
|
|
484
|
+
this.generateRequestOptions({
|
|
485
|
+
headers: {
|
|
486
|
+
Referer: `https://${countrySubDomain}.adtpulse.com/myhome/${lastKnownVersion}/summary/summary.jsp`,
|
|
487
|
+
},
|
|
488
|
+
}),
|
|
489
|
+
(error2, response2, body2) => {
|
|
490
|
+
const regex2 = new RegExp(/(\/myhome\/)([0-9.-]+)(\/quickcontrol\/armDisarm\.jsp)(.*)/);
|
|
491
|
+
const responsePath2 = _.get(response2, 'request.uri.path');
|
|
492
|
+
|
|
493
|
+
this.consoleLogger(`ADT Pulse: Response path -> ${responsePath2}`, 'log');
|
|
494
|
+
this.consoleLogger(`ADT Pulse: Response path matches -> ${regex2.test(responsePath2)}`, 'log');
|
|
495
|
+
|
|
496
|
+
if (error2 || !regex2.test(responsePath2)) {
|
|
497
|
+
authenticated = false;
|
|
498
|
+
|
|
499
|
+
this.consoleLogger(`ADT Pulse: Set device status to ${arm} failed.`, 'error');
|
|
500
|
+
|
|
501
|
+
deferred.reject({
|
|
502
|
+
action: 'SET_DEVICE_STATUS',
|
|
503
|
+
success: false,
|
|
504
|
+
info: {
|
|
505
|
+
error: error2,
|
|
506
|
+
message: this.getErrorMessage(body2),
|
|
507
|
+
},
|
|
508
|
+
});
|
|
509
|
+
} else {
|
|
510
|
+
const $3 = cheerio.load(body2);
|
|
511
|
+
const onClick3 = $3('input[id^="arm_button_"][value="Arm Anyway"]').attr('onclick');
|
|
512
|
+
const satCode3 = (onClick3 !== undefined) ? onClick3.replace(/(.*)(\?sat=)([0-9a-z-]*)(&href=)(.*)/g, '$3') : undefined;
|
|
513
|
+
|
|
514
|
+
const url3 = `https://${countrySubDomain}.adtpulse.com/myhome/${lastKnownVersion}/quickcontrol/serv/RunRRACommand`;
|
|
515
|
+
const arg3 = `?sat=${satCode3}&href=rest/adt/ui/client/security/setForceArm&armstate=forcearm&arm=${arm}`;
|
|
516
|
+
|
|
517
|
+
// Check if system requires force arming.
|
|
518
|
+
if (['away', 'stay', 'night'].includes(arm) && onClick3 !== undefined && satCode3 !== undefined) {
|
|
519
|
+
this.consoleLogger('ADT Pulse: Some sensors are open or reporting motion. Arming Anyway...', 'warn');
|
|
520
|
+
|
|
521
|
+
request.get(
|
|
522
|
+
url3 + arg3,
|
|
523
|
+
this.generateRequestOptions({
|
|
524
|
+
headers: {
|
|
525
|
+
Accept: '*/*',
|
|
526
|
+
Referer: `https://${countrySubDomain}.adtpulse.com/myhome/${lastKnownVersion}/quickcontrol/armDisarm.jsp`,
|
|
527
|
+
},
|
|
528
|
+
}),
|
|
529
|
+
(forceError, forceResponse, forceBody) => {
|
|
530
|
+
const forceRegex = new RegExp(/(\/myhome\/)([0-9.-]+)(\/quickcontrol\/serv\/RunRRACommand)(.*)/);
|
|
531
|
+
const forceResponsePath = _.get(forceResponse, 'request.uri.path');
|
|
532
|
+
|
|
533
|
+
this.consoleLogger(`ADT Pulse: Response path -> ${forceResponsePath}`, 'log');
|
|
534
|
+
this.consoleLogger(`ADT Pulse: Response path matches -> ${forceRegex.test(forceResponsePath)}`, 'log');
|
|
535
|
+
|
|
536
|
+
if (forceError || !forceRegex.test(forceResponsePath)) {
|
|
537
|
+
authenticated = false;
|
|
538
|
+
|
|
539
|
+
this.consoleLogger(`ADT Pulse: Set device status to ${arm} failed.`, 'error');
|
|
540
|
+
|
|
541
|
+
deferred.reject({
|
|
542
|
+
action: 'SET_DEVICE_STATUS',
|
|
543
|
+
success: false,
|
|
544
|
+
info: {
|
|
545
|
+
error: forceError,
|
|
546
|
+
message: this.getErrorMessage(forceBody),
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
} else {
|
|
550
|
+
this.consoleLogger(`ADT Pulse: Set device status to ${arm} success.`, 'log');
|
|
551
|
+
|
|
552
|
+
deferred.resolve({
|
|
553
|
+
action: 'SET_DEVICE_STATUS',
|
|
554
|
+
success: true,
|
|
555
|
+
info: {
|
|
556
|
+
forceArm: true,
|
|
557
|
+
previousArm: armState,
|
|
558
|
+
afterArm: arm,
|
|
559
|
+
},
|
|
560
|
+
});
|
|
561
|
+
}
|
|
517
562
|
},
|
|
518
|
-
|
|
563
|
+
);
|
|
519
564
|
} else {
|
|
520
565
|
this.consoleLogger(`ADT Pulse: Set device status to ${arm} success.`, 'log');
|
|
521
566
|
|
|
@@ -523,27 +568,15 @@ Pulse.prototype.setDeviceStatus = function setDeviceStatus(armState, arm) {
|
|
|
523
568
|
action: 'SET_DEVICE_STATUS',
|
|
524
569
|
success: true,
|
|
525
570
|
info: {
|
|
526
|
-
forceArm:
|
|
571
|
+
forceArm: false,
|
|
527
572
|
previousArm: armState,
|
|
528
573
|
afterArm: arm,
|
|
529
574
|
},
|
|
530
575
|
});
|
|
531
576
|
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
this.consoleLogger(`ADT Pulse: Set device status to ${arm} success.`, 'log');
|
|
536
|
-
|
|
537
|
-
deferred.resolve({
|
|
538
|
-
action: 'SET_DEVICE_STATUS',
|
|
539
|
-
success: true,
|
|
540
|
-
info: {
|
|
541
|
-
forceArm: false,
|
|
542
|
-
previousArm: armState,
|
|
543
|
-
afterArm: arm,
|
|
544
|
-
},
|
|
545
|
-
});
|
|
546
|
-
}
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
);
|
|
547
580
|
}
|
|
548
581
|
},
|
|
549
582
|
);
|
|
@@ -776,7 +809,7 @@ Pulse.prototype.generateRequestOptions = function generateRequestOptions(additio
|
|
|
776
809
|
headers: {
|
|
777
810
|
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
778
811
|
Host: `${countrySubDomain}.adtpulse.com`,
|
|
779
|
-
'User-Agent': 'Mozilla/5.0 (
|
|
812
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44',
|
|
780
813
|
},
|
|
781
814
|
ciphers: [
|
|
782
815
|
'ECDHE-RSA-AES256-GCM-SHA384',
|
package/config.schema.json
CHANGED
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const _ = require('lodash');
|
|
7
7
|
|
|
8
|
-
const packageJson = require('./package');
|
|
8
|
+
const packageJson = require('./package.json');
|
|
9
9
|
const Pulse = require('./api');
|
|
10
10
|
|
|
11
11
|
let Accessory;
|
|
@@ -61,6 +61,9 @@ function ADTPulsePlatform(log, config, api) {
|
|
|
61
61
|
this.syncIntervalDelay = 600; // 10 minutes.
|
|
62
62
|
this.setDeviceTimeout = 6; // 6 seconds.
|
|
63
63
|
|
|
64
|
+
// Tested builds.
|
|
65
|
+
this.testedBuilds = ['22.0.0-233', '23.0.0-99'];
|
|
66
|
+
|
|
64
67
|
// Setup logging function.
|
|
65
68
|
if (typeof this.logLevel !== 'number' || ![10, 20, 30, 40, 50].includes(this.logLevel)) {
|
|
66
69
|
if (this.logLevel !== undefined) {
|
|
@@ -847,9 +850,9 @@ ADTPulsePlatform.prototype.portalSync = function portalSync() {
|
|
|
847
850
|
.login()
|
|
848
851
|
.then((response) => {
|
|
849
852
|
const version = _.get(response, 'info.version');
|
|
850
|
-
const
|
|
853
|
+
const supportedVersions = that.testedBuilds;
|
|
851
854
|
|
|
852
|
-
if (version !== undefined && !
|
|
855
|
+
if (version !== undefined && !supportedVersions.includes(version) && version !== this.sessionVersion) {
|
|
853
856
|
this.logMessage(`Web Portal version ${version} detected. Test plugin to ensure system compatibility...`, 20);
|
|
854
857
|
}
|
|
855
858
|
|