homebridge-adt-pulse 3.0.0-beta.23 → 3.0.0-beta.24
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 +10 -6
- package/build/config.schema.json +6 -0
- package/build/src/lib/accessory.js +130 -251
- package/build/src/lib/accessory.js.map +1 -1
- package/build/src/lib/api.js +92 -71
- package/build/src/lib/api.js.map +1 -1
- package/build/src/lib/detect.js +80 -0
- package/build/src/lib/detect.js.map +1 -1
- package/build/src/lib/items.js +22 -0
- package/build/src/lib/items.js.map +1 -1
- package/build/src/lib/platform.js +94 -6
- package/build/src/lib/platform.js.map +1 -1
- package/build/src/lib/schema.js +1 -0
- package/build/src/lib/schema.js.map +1 -1
- package/build/src/lib/utility.js +137 -6
- package/build/src/lib/utility.js.map +1 -1
- package/build/src/scripts/repl.js +9 -6
- package/build/src/scripts/repl.js.map +1 -1
- package/build/src/scripts/test-api.js +4 -4
- package/build/src/scripts/test-api.js.map +1 -1
- package/config.schema.json +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
ADT Pulse for Homebridge
|
|
2
2
|
=========================
|
|
3
3
|
|
|
4
|
-
### ⚠️ Please Install the Beta Version ⚠️
|
|
5
|
-
This plugin is completely re-written from the ground up (supports v27.0.0-140), and I would love everyone on board! Please install the beta version, so I can quickly get a faster and more stable version to you!
|
|
6
|
-
|
|
7
|
-
Please bear with me, as the beta version is being actively developed and tested. If you see any unusual or annoying bugs, please comment on this [GitHub issue](https://github.com/mrjackyliang/homebridge-adt-pulse/issues/124).
|
|
8
|
-
|
|
9
4
|
[](https://www.npmjs.com/package/homebridge-adt-pulse)
|
|
10
5
|
[](https://www.npmjs.com/package/homebridge-adt-pulse)
|
|
11
6
|
[](https://github.com/mrjackyliang/homebridge-adt-pulse/blob/main/LICENSE)
|
|
@@ -71,7 +66,8 @@ This plugin can expose these devices (in read-only mode) based on your configura
|
|
|
71
66
|
6. `heat` - Heat (Rate-of-Rise) Detector
|
|
72
67
|
7. `motion` - Motion Sensor __::__ Motion Sensor (Notable Events Only)
|
|
73
68
|
8. `shock` - Shock Sensor
|
|
74
|
-
9. `
|
|
69
|
+
9. `supervisory` - System/Supervisory
|
|
70
|
+
10. `temperature` - Temperature Sensor
|
|
75
71
|
|
|
76
72
|
Due to implementation complexity and platform instability, all Z-Wave accessories connected to the ADT Pulse gateway will not be planned for development or be supported overall. Consider purchasing the [Hubitat Hub](https://hubitat.com) for a seamless setup experience, or read about the [Home Assistant Z-Wave](https://www.home-assistant.io/integrations/zwave_js/) integration.
|
|
77
73
|
|
|
@@ -162,6 +158,14 @@ Consumers would enable debug mode, but forget to also enable Homebridge debug mo
|
|
|
162
158
|
|
|
163
159
|
To improve this, debug mode is now activated __ONLY when debug mode is enabled on Homebridge__ itself. This approach promotes isolation (logs can be separated for each bridge) and helps enhance the troubleshooting experience in case any issues arise.
|
|
164
160
|
|
|
161
|
+
## Temperature Sensors in HAP Protocol
|
|
162
|
+
The Temperature Sensor (`temperature`) functions differently compared to standard contact sensors when it comes to processing sensor statuses.
|
|
163
|
+
|
|
164
|
+
In contrast to typical contact sensors that convey open or closed status, the temperature sensor exposed in the Home app (utilizing the HAP protocol) operates with temperature values. To accommodate this difference, the accessory converts these binary states into corresponding temperature degrees:
|
|
165
|
+
- Cold temperatures are represented as __0°C__.
|
|
166
|
+
- Normal temperatures are indicated as __20°C__.
|
|
167
|
+
- Hot temperatures are reflected as __40°C__.
|
|
168
|
+
|
|
165
169
|
## Support for HOOBS
|
|
166
170
|
Please note that HOOBS may use an outdated configuration UI. This issue that was reported by me, remains unresolved by the HOOBS team. For additional details, refer to this [GitHub issue](https://github.com/hoobs-org/HOOBS/issues/1873).
|
|
167
171
|
|
package/build/config.schema.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { condensedSensorTypeItems } from './items.js';
|
|
3
|
-
import { condensePanelStates, stackTracer } from './utility.js';
|
|
3
|
+
import { condensePanelStates, isPanelAlarmActive, stackTracer } from './utility.js';
|
|
4
4
|
export class ADTPulseAccessory {
|
|
5
5
|
#accessory;
|
|
6
6
|
#api;
|
|
@@ -9,6 +9,7 @@ export class ADTPulseAccessory {
|
|
|
9
9
|
#log;
|
|
10
10
|
#services;
|
|
11
11
|
#state;
|
|
12
|
+
#status;
|
|
12
13
|
constructor(accessory, state, instance, service, characteristic, api, log) {
|
|
13
14
|
this.#accessory = accessory;
|
|
14
15
|
this.#api = api;
|
|
@@ -17,8 +18,12 @@ export class ADTPulseAccessory {
|
|
|
17
18
|
this.#log = log;
|
|
18
19
|
this.#services = {};
|
|
19
20
|
this.#state = state;
|
|
21
|
+
this.#status = {
|
|
22
|
+
isBusy: false,
|
|
23
|
+
setValue: null,
|
|
24
|
+
};
|
|
20
25
|
const { context } = this.#accessory;
|
|
21
|
-
const { firmware, hardware,
|
|
26
|
+
const { firmware, hardware, manufacturer, model, name, serial, software, type, } = context;
|
|
22
27
|
this.#services.Information = this.#accessory.getService(service.AccessoryInformation) ?? this.#accessory.addService(service.AccessoryInformation);
|
|
23
28
|
this.#services.Information
|
|
24
29
|
.setCharacteristic(this.#characteristic.Identify, false)
|
|
@@ -63,122 +68,11 @@ export class ADTPulseAccessory {
|
|
|
63
68
|
case 'shock':
|
|
64
69
|
this.#services.Primary = this.#accessory.getService(service.OccupancySensor) ?? this.#accessory.addService(service.OccupancySensor);
|
|
65
70
|
break;
|
|
66
|
-
case '
|
|
67
|
-
this.#services.Primary = this.#accessory.getService(service.
|
|
68
|
-
break;
|
|
69
|
-
default:
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
if (this.#services.Primary === undefined) {
|
|
73
|
-
if (type !== 'gateway') {
|
|
74
|
-
this.#log.error(`Failed to initialize ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory because the primary service does not exist ...`);
|
|
75
|
-
}
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
switch (type) {
|
|
79
|
-
case 'gateway':
|
|
80
|
-
break;
|
|
81
|
-
case 'panel':
|
|
82
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemCurrentState)
|
|
83
|
-
.onGet(() => this.getPanelStatus('constructor', 'current'))
|
|
84
|
-
.updateValue(this.getPanelStatus('updater', 'current'));
|
|
85
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemTargetState)
|
|
86
|
-
.onGet(() => this.getPanelStatus('constructor', 'target'))
|
|
87
|
-
.updateValue(this.getPanelStatus('updater', 'target'));
|
|
88
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemTargetState)
|
|
89
|
-
.onSet(async (value) => this.setPanelStatus(value));
|
|
90
|
-
break;
|
|
91
|
-
default:
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
switch (type) {
|
|
95
|
-
case 'gateway':
|
|
96
|
-
break;
|
|
97
|
-
case 'panel':
|
|
98
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemAlarmType)
|
|
99
|
-
.onGet(() => this.getPanelStatus('constructor', 'alarmType'))
|
|
100
|
-
.updateValue(this.getPanelStatus('updater', 'alarmType'));
|
|
101
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusFault)
|
|
102
|
-
.onGet(() => this.getPanelStatus('constructor', 'fault'))
|
|
103
|
-
.updateValue(this.getPanelStatus('updater', 'fault'));
|
|
104
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusTampered)
|
|
105
|
-
.onGet(() => this.getPanelStatus('constructor', 'tamper'))
|
|
106
|
-
.updateValue(this.getPanelStatus('updater', 'tamper'));
|
|
107
|
-
break;
|
|
108
|
-
default:
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
switch (type) {
|
|
112
|
-
case 'co':
|
|
113
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.CarbonMonoxideDetected)
|
|
114
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
115
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
116
|
-
break;
|
|
117
|
-
case 'doorWindow':
|
|
118
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.ContactSensorState)
|
|
119
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
120
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
121
|
-
break;
|
|
122
|
-
case 'fire':
|
|
123
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.SmokeDetected)
|
|
124
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
125
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
126
|
-
break;
|
|
127
|
-
case 'flood':
|
|
128
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.LeakDetected)
|
|
129
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
130
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
131
|
-
break;
|
|
132
|
-
case 'glass':
|
|
133
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
134
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
135
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
136
|
-
break;
|
|
137
|
-
case 'heat':
|
|
138
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
139
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
140
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
141
|
-
break;
|
|
142
|
-
case 'motion':
|
|
143
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.MotionDetected)
|
|
144
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
145
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
146
|
-
break;
|
|
147
|
-
case 'shock':
|
|
148
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
149
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
150
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
71
|
+
case 'supervisory':
|
|
72
|
+
this.#services.Primary = this.#accessory.getService(service.OccupancySensor) ?? this.#accessory.addService(service.OccupancySensor);
|
|
151
73
|
break;
|
|
152
74
|
case 'temperature':
|
|
153
|
-
this.#services.Primary.
|
|
154
|
-
.onGet(() => this.getSensorStatus('constructor', 'status'))
|
|
155
|
-
.updateValue(this.getSensorStatus('updater', 'status'));
|
|
156
|
-
break;
|
|
157
|
-
default:
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
switch (type) {
|
|
161
|
-
case 'co':
|
|
162
|
-
case 'doorWindow':
|
|
163
|
-
case 'fire':
|
|
164
|
-
case 'flood':
|
|
165
|
-
case 'glass':
|
|
166
|
-
case 'heat':
|
|
167
|
-
case 'motion':
|
|
168
|
-
case 'shock':
|
|
169
|
-
case 'temperature':
|
|
170
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusActive)
|
|
171
|
-
.onGet(() => this.getSensorStatus('constructor', 'active'))
|
|
172
|
-
.updateValue(this.getSensorStatus('updater', 'active'));
|
|
173
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusFault)
|
|
174
|
-
.onGet(() => this.getSensorStatus('constructor', 'fault'))
|
|
175
|
-
.updateValue(this.getSensorStatus('updater', 'fault'));
|
|
176
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusLowBattery)
|
|
177
|
-
.onGet(() => this.getSensorStatus('constructor', 'lowBattery'))
|
|
178
|
-
.updateValue(this.getSensorStatus('updater', 'lowBattery'));
|
|
179
|
-
this.#services.Primary.getCharacteristic(this.#characteristic.StatusTampered)
|
|
180
|
-
.onGet(() => this.getSensorStatus('constructor', 'tamper'))
|
|
181
|
-
.updateValue(this.getSensorStatus('updater', 'tamper'));
|
|
75
|
+
this.#services.Primary = this.#accessory.getService(service.TemperatureSensor) ?? this.#accessory.addService(service.TemperatureSensor);
|
|
182
76
|
break;
|
|
183
77
|
default:
|
|
184
78
|
break;
|
|
@@ -198,11 +92,11 @@ export class ADTPulseAccessory {
|
|
|
198
92
|
break;
|
|
199
93
|
case 'panel':
|
|
200
94
|
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemCurrentState)
|
|
201
|
-
.updateValue(this.getPanelStatus('
|
|
95
|
+
.updateValue(this.getPanelStatus('current'));
|
|
202
96
|
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemTargetState)
|
|
203
|
-
.updateValue(this.getPanelStatus('
|
|
204
|
-
this.#services.Primary.
|
|
205
|
-
|
|
97
|
+
.updateValue(this.getPanelStatus('target'));
|
|
98
|
+
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemTargetState)
|
|
99
|
+
.onSet(async (value) => this.setPanelStatus(value));
|
|
206
100
|
break;
|
|
207
101
|
default:
|
|
208
102
|
break;
|
|
@@ -212,14 +106,11 @@ export class ADTPulseAccessory {
|
|
|
212
106
|
break;
|
|
213
107
|
case 'panel':
|
|
214
108
|
this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemAlarmType)
|
|
215
|
-
.updateValue(this.getPanelStatus('
|
|
109
|
+
.updateValue(this.getPanelStatus('alarmType'));
|
|
216
110
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusFault)
|
|
217
|
-
.updateValue(this.getPanelStatus('
|
|
111
|
+
.updateValue(this.getPanelStatus('fault'));
|
|
218
112
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusTampered)
|
|
219
|
-
.updateValue(this.getPanelStatus('
|
|
220
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.SecuritySystemAlarmType, this.getPanelStatus('constructor', 'alarmType'));
|
|
221
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusFault, this.getPanelStatus('constructor', 'fault'));
|
|
222
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusTampered, this.getPanelStatus('constructor', 'tamper'));
|
|
113
|
+
.updateValue(this.getPanelStatus('tamper'));
|
|
223
114
|
break;
|
|
224
115
|
default:
|
|
225
116
|
break;
|
|
@@ -227,48 +118,43 @@ export class ADTPulseAccessory {
|
|
|
227
118
|
switch (type) {
|
|
228
119
|
case 'co':
|
|
229
120
|
this.#services.Primary.getCharacteristic(this.#characteristic.CarbonMonoxideDetected)
|
|
230
|
-
.updateValue(this.getSensorStatus('
|
|
231
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.CarbonMonoxideDetected, this.getSensorStatus('constructor', 'status'));
|
|
121
|
+
.updateValue(this.getSensorStatus('status'));
|
|
232
122
|
break;
|
|
233
123
|
case 'doorWindow':
|
|
234
124
|
this.#services.Primary.getCharacteristic(this.#characteristic.ContactSensorState)
|
|
235
|
-
.updateValue(this.getSensorStatus('
|
|
236
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.ContactSensorState, this.getSensorStatus('constructor', 'status'));
|
|
125
|
+
.updateValue(this.getSensorStatus('status'));
|
|
237
126
|
break;
|
|
238
127
|
case 'fire':
|
|
239
128
|
this.#services.Primary.getCharacteristic(this.#characteristic.SmokeDetected)
|
|
240
|
-
.updateValue(this.getSensorStatus('
|
|
241
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.SmokeDetected, this.getSensorStatus('constructor', 'status'));
|
|
129
|
+
.updateValue(this.getSensorStatus('status'));
|
|
242
130
|
break;
|
|
243
131
|
case 'flood':
|
|
244
132
|
this.#services.Primary.getCharacteristic(this.#characteristic.LeakDetected)
|
|
245
|
-
.updateValue(this.getSensorStatus('
|
|
246
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.LeakDetected, this.getSensorStatus('constructor', 'status'));
|
|
133
|
+
.updateValue(this.getSensorStatus('status'));
|
|
247
134
|
break;
|
|
248
135
|
case 'glass':
|
|
249
136
|
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
250
|
-
.updateValue(this.getSensorStatus('
|
|
251
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.OccupancyDetected, this.getSensorStatus('constructor', 'status'));
|
|
137
|
+
.updateValue(this.getSensorStatus('status'));
|
|
252
138
|
break;
|
|
253
139
|
case 'heat':
|
|
254
140
|
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
255
|
-
.updateValue(this.getSensorStatus('
|
|
256
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.OccupancyDetected, this.getSensorStatus('constructor', 'status'));
|
|
141
|
+
.updateValue(this.getSensorStatus('status'));
|
|
257
142
|
break;
|
|
258
143
|
case 'motion':
|
|
259
144
|
this.#services.Primary.getCharacteristic(this.#characteristic.MotionDetected)
|
|
260
|
-
.updateValue(this.getSensorStatus('
|
|
261
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.MotionDetected, this.getSensorStatus('constructor', 'status'));
|
|
145
|
+
.updateValue(this.getSensorStatus('status'));
|
|
262
146
|
break;
|
|
263
147
|
case 'shock':
|
|
264
148
|
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
265
|
-
.updateValue(this.getSensorStatus('
|
|
266
|
-
|
|
149
|
+
.updateValue(this.getSensorStatus('status'));
|
|
150
|
+
break;
|
|
151
|
+
case 'supervisory':
|
|
152
|
+
this.#services.Primary.getCharacteristic(this.#characteristic.OccupancyDetected)
|
|
153
|
+
.updateValue(this.getSensorStatus('status'));
|
|
267
154
|
break;
|
|
268
155
|
case 'temperature':
|
|
269
156
|
this.#services.Primary.getCharacteristic(this.#characteristic.CurrentTemperature)
|
|
270
|
-
.updateValue(this.getSensorStatus('
|
|
271
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.CurrentTemperature, this.getSensorStatus('constructor', 'status'));
|
|
157
|
+
.updateValue(this.getSensorStatus('status'));
|
|
272
158
|
break;
|
|
273
159
|
default:
|
|
274
160
|
break;
|
|
@@ -282,52 +168,46 @@ export class ADTPulseAccessory {
|
|
|
282
168
|
case 'heat':
|
|
283
169
|
case 'motion':
|
|
284
170
|
case 'shock':
|
|
171
|
+
case 'supervisory':
|
|
285
172
|
case 'temperature':
|
|
286
173
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusActive)
|
|
287
|
-
.updateValue(this.getSensorStatus('
|
|
174
|
+
.updateValue(this.getSensorStatus('active'));
|
|
288
175
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusFault)
|
|
289
|
-
.updateValue(this.getSensorStatus('
|
|
176
|
+
.updateValue(this.getSensorStatus('fault'));
|
|
290
177
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusLowBattery)
|
|
291
|
-
.updateValue(this.getSensorStatus('
|
|
178
|
+
.updateValue(this.getSensorStatus('lowBattery'));
|
|
292
179
|
this.#services.Primary.getCharacteristic(this.#characteristic.StatusTampered)
|
|
293
|
-
.updateValue(this.getSensorStatus('
|
|
294
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusActive, this.getSensorStatus('constructor', 'active'));
|
|
295
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusFault, this.getSensorStatus('constructor', 'fault'));
|
|
296
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusLowBattery, this.getSensorStatus('constructor', 'lowBattery'));
|
|
297
|
-
this.#services.Primary.updateCharacteristic(this.#characteristic.StatusTampered, this.getSensorStatus('constructor', 'tamper'));
|
|
180
|
+
.updateValue(this.getSensorStatus('tamper'));
|
|
298
181
|
break;
|
|
299
182
|
default:
|
|
300
183
|
break;
|
|
301
184
|
}
|
|
302
185
|
}
|
|
303
|
-
getSensorStatus(
|
|
186
|
+
getSensorStatus(mode) {
|
|
304
187
|
const { context } = this.#accessory;
|
|
305
188
|
const { id, name, originalName, type, uuid, zone, } = context;
|
|
306
189
|
const matchedSensorStatus = this.#state.data.sensorsStatus.find((sensorStatus) => originalName === sensorStatus.name && zone !== null && sensorStatus.zone === zone);
|
|
307
|
-
let hapStatus
|
|
190
|
+
let hapStatus;
|
|
308
191
|
if (matchedSensorStatus === undefined
|
|
309
192
|
|| type === 'gateway'
|
|
310
193
|
|| type === 'panel'
|
|
311
194
|
|| !condensedSensorTypeItems.includes(type)) {
|
|
312
195
|
hapStatus = new this.#api.hap.HapStatusError(-70409);
|
|
313
196
|
this.#log.error(`Attempted to get sensor status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but sensor is not found or sensor type is not supported.`);
|
|
314
|
-
|
|
315
|
-
case 'updater':
|
|
316
|
-
return hapStatus;
|
|
317
|
-
default:
|
|
318
|
-
throw hapStatus;
|
|
319
|
-
}
|
|
197
|
+
return hapStatus;
|
|
320
198
|
}
|
|
321
199
|
const { icon, statuses } = matchedSensorStatus;
|
|
322
200
|
if (mode === 'active') {
|
|
323
|
-
return !statuses.includes('Offline')
|
|
201
|
+
return (!statuses.includes('Offline')
|
|
324
202
|
&& !statuses.includes('Unknown')
|
|
325
203
|
&& icon !== 'devStatOffline'
|
|
326
|
-
&& icon !== 'devStatUnknown';
|
|
204
|
+
&& icon !== 'devStatUnknown');
|
|
327
205
|
}
|
|
328
206
|
if (mode === 'fault') {
|
|
329
|
-
if (statuses.includes('
|
|
330
|
-
|| statuses.includes('
|
|
207
|
+
if (statuses.includes('ALARM')
|
|
208
|
+
|| statuses.includes('Bypassed')
|
|
209
|
+
|| statuses.includes('Trouble')
|
|
210
|
+
|| icon === 'devStatAlarm') {
|
|
331
211
|
return this.#characteristic.StatusFault.GENERAL_FAULT;
|
|
332
212
|
}
|
|
333
213
|
return this.#characteristic.StatusFault.NO_FAULT;
|
|
@@ -355,7 +235,7 @@ export class ADTPulseAccessory {
|
|
|
355
235
|
}
|
|
356
236
|
break;
|
|
357
237
|
case 'doorWindow':
|
|
358
|
-
if (statuses.includes('Open')) {
|
|
238
|
+
if (statuses.includes('ALARM') || statuses.includes('Open')) {
|
|
359
239
|
return this.#characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
360
240
|
}
|
|
361
241
|
if (statuses.includes('Closed')) {
|
|
@@ -363,6 +243,9 @@ export class ADTPulseAccessory {
|
|
|
363
243
|
}
|
|
364
244
|
break;
|
|
365
245
|
case 'fire':
|
|
246
|
+
if (statuses.includes('ALARM') || statuses.includes('Tripped')) {
|
|
247
|
+
return this.#characteristic.SmokeDetected.SMOKE_DETECTED;
|
|
248
|
+
}
|
|
366
249
|
if (statuses.includes('Okay')) {
|
|
367
250
|
return this.#characteristic.SmokeDetected.SMOKE_NOT_DETECTED;
|
|
368
251
|
}
|
|
@@ -373,7 +256,7 @@ export class ADTPulseAccessory {
|
|
|
373
256
|
}
|
|
374
257
|
break;
|
|
375
258
|
case 'glass':
|
|
376
|
-
if (statuses.includes('Tripped')) {
|
|
259
|
+
if (statuses.includes('ALARM') || statuses.includes('Tripped')) {
|
|
377
260
|
return this.#characteristic.OccupancyDetected.OCCUPANCY_DETECTED;
|
|
378
261
|
}
|
|
379
262
|
if (statuses.includes('Okay')) {
|
|
@@ -386,16 +269,21 @@ export class ADTPulseAccessory {
|
|
|
386
269
|
}
|
|
387
270
|
break;
|
|
388
271
|
case 'motion':
|
|
272
|
+
if (statuses.includes('ALARM') || statuses.includes('Motion')) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
389
275
|
if (statuses.includes('No Motion') || statuses.includes('Okay')) {
|
|
390
276
|
return false;
|
|
391
277
|
}
|
|
392
|
-
if (statuses.includes('Motion')) {
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
278
|
break;
|
|
396
279
|
case 'shock':
|
|
397
280
|
break;
|
|
281
|
+
case 'supervisory':
|
|
282
|
+
break;
|
|
398
283
|
case 'temperature':
|
|
284
|
+
if (statuses.includes('ALARM') || statuses.includes('Tripped')) {
|
|
285
|
+
return 0;
|
|
286
|
+
}
|
|
399
287
|
if (statuses.includes('Okay')) {
|
|
400
288
|
return 20;
|
|
401
289
|
}
|
|
@@ -406,55 +294,31 @@ export class ADTPulseAccessory {
|
|
|
406
294
|
if (statuses.includes('Offline') || statuses.includes('Unknown')) {
|
|
407
295
|
hapStatus = new this.#api.hap.HapStatusError(-70412);
|
|
408
296
|
this.#log.warn(`Attempted to get sensor status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but sensor is currently "Offline" or "Unknown".`);
|
|
409
|
-
|
|
410
|
-
case 'updater':
|
|
411
|
-
return hapStatus;
|
|
412
|
-
default:
|
|
413
|
-
throw hapStatus;
|
|
414
|
-
}
|
|
297
|
+
return hapStatus;
|
|
415
298
|
}
|
|
416
299
|
hapStatus = new this.#api.hap.HapStatusError(-70410);
|
|
417
300
|
this.#log.warn(`Attempted to get sensor status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but actions have not been implemented yet.`);
|
|
418
|
-
|
|
419
|
-
case 'updater':
|
|
420
|
-
return hapStatus;
|
|
421
|
-
default:
|
|
422
|
-
throw hapStatus;
|
|
423
|
-
}
|
|
301
|
+
return hapStatus;
|
|
424
302
|
}
|
|
425
|
-
getPanelStatus(
|
|
303
|
+
getPanelStatus(mode) {
|
|
426
304
|
const { context } = this.#accessory;
|
|
427
305
|
const { id, name, type, uuid, } = context;
|
|
428
|
-
let hapStatus
|
|
306
|
+
let hapStatus;
|
|
429
307
|
if (type !== 'panel') {
|
|
430
308
|
hapStatus = new this.#api.hap.HapStatusError(-70410);
|
|
431
309
|
this.#log.error(`Attempted to get panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but device is not a security panel.`);
|
|
432
|
-
|
|
433
|
-
case 'updater':
|
|
434
|
-
return hapStatus;
|
|
435
|
-
default:
|
|
436
|
-
throw hapStatus;
|
|
437
|
-
}
|
|
310
|
+
return hapStatus;
|
|
438
311
|
}
|
|
439
312
|
if (this.#state.data.panelStatus === null
|
|
440
313
|
|| this.#state.data.panelStatus.panelStates.length === 0
|
|
441
314
|
|| this.#state.data.panelStatus.panelStatuses.length === 0) {
|
|
442
315
|
hapStatus = new this.#api.hap.HapStatusError(-70403);
|
|
443
316
|
this.#log.debug(`Attempted to get panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but panel status has not been retrieved yet.`);
|
|
444
|
-
|
|
445
|
-
case 'updater':
|
|
446
|
-
return hapStatus;
|
|
447
|
-
default:
|
|
448
|
-
throw hapStatus;
|
|
449
|
-
}
|
|
317
|
+
return hapStatus;
|
|
450
318
|
}
|
|
451
319
|
const { panelStates, panelStatuses } = this.#state.data.panelStatus;
|
|
452
320
|
if (mode === 'alarmType') {
|
|
453
|
-
if (panelStatuses
|
|
454
|
-
|| panelStatuses.includes('Carbon Monoxide Alarm')
|
|
455
|
-
|| panelStatuses.includes('FIRE ALARM')
|
|
456
|
-
|| panelStatuses.includes('Uncleared Alarm')
|
|
457
|
-
|| panelStatuses.includes('WATER ALARM')) {
|
|
321
|
+
if (isPanelAlarmActive(panelStatuses)) {
|
|
458
322
|
return 1;
|
|
459
323
|
}
|
|
460
324
|
return 0;
|
|
@@ -466,19 +330,20 @@ export class ADTPulseAccessory {
|
|
|
466
330
|
return this.#characteristic.StatusFault.NO_FAULT;
|
|
467
331
|
}
|
|
468
332
|
if (mode === 'tamper') {
|
|
333
|
+
if (panelStatuses.includes('Sensor Problem') || panelStatuses.includes('Sensor Problems')) {
|
|
334
|
+
return this.#characteristic.StatusTampered.TAMPERED;
|
|
335
|
+
}
|
|
469
336
|
return this.#characteristic.StatusTampered.NOT_TAMPERED;
|
|
470
337
|
}
|
|
471
338
|
switch (true) {
|
|
472
|
-
case mode === 'current' && panelStatuses
|
|
473
|
-
case mode === 'current' && panelStatuses.includes('Carbon Monoxide Alarm'):
|
|
474
|
-
case mode === 'current' && panelStatuses.includes('FIRE ALARM'):
|
|
475
|
-
case mode === 'current' && panelStatuses.includes('Uncleared Alarm'):
|
|
476
|
-
case mode === 'current' && panelStatuses.includes('WATER ALARM'):
|
|
339
|
+
case mode === 'current' && isPanelAlarmActive(panelStatuses):
|
|
477
340
|
return this.#characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED;
|
|
478
|
-
case mode === 'current' &&
|
|
479
|
-
return this.#
|
|
341
|
+
case mode === 'current' && this.#status.isBusy && this.#status.setValue !== null:
|
|
342
|
+
return this.#status.setValue;
|
|
480
343
|
case mode === 'current' && panelStates.includes('Armed Stay'):
|
|
481
344
|
return this.#characteristic.SecuritySystemCurrentState.STAY_ARM;
|
|
345
|
+
case mode === 'current' && panelStates.includes('Armed Away'):
|
|
346
|
+
return this.#characteristic.SecuritySystemCurrentState.AWAY_ARM;
|
|
482
347
|
case mode === 'current' && panelStates.includes('Armed Night'):
|
|
483
348
|
return this.#characteristic.SecuritySystemCurrentState.NIGHT_ARM;
|
|
484
349
|
case mode === 'current' && panelStates.includes('Disarmed'):
|
|
@@ -487,10 +352,14 @@ export class ADTPulseAccessory {
|
|
|
487
352
|
break;
|
|
488
353
|
}
|
|
489
354
|
switch (true) {
|
|
490
|
-
case mode === 'target' && panelStates.includes('
|
|
491
|
-
return this.#characteristic.SecuritySystemTargetState.
|
|
355
|
+
case mode === 'target' && panelStates.includes('Disarmed') && isPanelAlarmActive(panelStatuses):
|
|
356
|
+
return this.#characteristic.SecuritySystemTargetState.STAY_ARM;
|
|
357
|
+
case mode === 'target' && this.#status.isBusy && this.#status.setValue !== null:
|
|
358
|
+
return this.#status.setValue;
|
|
492
359
|
case mode === 'target' && panelStates.includes('Armed Stay'):
|
|
493
360
|
return this.#characteristic.SecuritySystemTargetState.STAY_ARM;
|
|
361
|
+
case mode === 'target' && panelStates.includes('Armed Away'):
|
|
362
|
+
return this.#characteristic.SecuritySystemTargetState.AWAY_ARM;
|
|
494
363
|
case mode === 'target' && panelStates.includes('Armed Night'):
|
|
495
364
|
return this.#characteristic.SecuritySystemTargetState.NIGHT_ARM;
|
|
496
365
|
case mode === 'target' && panelStates.includes('Disarmed'):
|
|
@@ -501,68 +370,78 @@ export class ADTPulseAccessory {
|
|
|
501
370
|
if (panelStates.includes('Status Unavailable')) {
|
|
502
371
|
hapStatus = new this.#api.hap.HapStatusError(-70403);
|
|
503
372
|
this.#log.warn(`Attempted to get panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but panel state is "Status Unavailable".`);
|
|
504
|
-
|
|
505
|
-
case 'updater':
|
|
506
|
-
return hapStatus;
|
|
507
|
-
default:
|
|
508
|
-
throw hapStatus;
|
|
509
|
-
}
|
|
373
|
+
return hapStatus;
|
|
510
374
|
}
|
|
511
375
|
hapStatus = new this.#api.hap.HapStatusError(-70402);
|
|
512
376
|
this.#log.warn(`Attempted to get panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but actions have not been implemented yet.`);
|
|
513
|
-
|
|
514
|
-
case 'updater':
|
|
515
|
-
return hapStatus;
|
|
516
|
-
default:
|
|
517
|
-
throw hapStatus;
|
|
518
|
-
}
|
|
377
|
+
return hapStatus;
|
|
519
378
|
}
|
|
520
379
|
async setPanelStatus(arm) {
|
|
521
380
|
const { context } = this.#accessory;
|
|
522
381
|
const { id, name, type, uuid, } = context;
|
|
382
|
+
let hapStatus;
|
|
523
383
|
let result = {
|
|
524
384
|
success: false,
|
|
525
385
|
};
|
|
526
386
|
let unknownArmValue = false;
|
|
527
387
|
if (type !== 'panel') {
|
|
388
|
+
hapStatus = new this.#api.hap.HapStatusError(-70410);
|
|
528
389
|
this.#log.error(`Attempted to set panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but device is not a security panel.`);
|
|
529
|
-
throw
|
|
390
|
+
throw hapStatus;
|
|
530
391
|
}
|
|
531
392
|
if (this.#state.data.panelStatus === null || this.#state.data.panelStatus.panelStates.length === 0) {
|
|
393
|
+
hapStatus = new this.#api.hap.HapStatusError(-70403);
|
|
532
394
|
this.#log.warn(`Attempted to set panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but panel status has not been retrieved yet.`);
|
|
533
|
-
throw
|
|
395
|
+
throw hapStatus;
|
|
534
396
|
}
|
|
535
397
|
const { panelStates } = this.#state.data.panelStatus;
|
|
536
|
-
const armFrom = condensePanelStates(panelStates);
|
|
398
|
+
const armFrom = condensePanelStates(this.#characteristic, panelStates);
|
|
399
|
+
const isAlarmActive = isPanelAlarmActive(this.#state.data.panelStatus.panelStatuses);
|
|
537
400
|
if (armFrom === undefined) {
|
|
401
|
+
hapStatus = new this.#api.hap.HapStatusError(-70403);
|
|
538
402
|
this.#log.warn(`Attempted to set panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but panel status cannot be found or most likely "Status Unavailable".`);
|
|
539
|
-
throw
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
403
|
+
throw hapStatus;
|
|
404
|
+
}
|
|
405
|
+
if (armFrom.characteristicValue !== arm
|
|
406
|
+
|| (armFrom.armValue === 'off'
|
|
407
|
+
&& arm === this.#characteristic.SecuritySystemTargetState.DISARM
|
|
408
|
+
&& isAlarmActive)) {
|
|
409
|
+
this.#status = {
|
|
410
|
+
isBusy: true,
|
|
411
|
+
setValue: arm,
|
|
412
|
+
};
|
|
413
|
+
switch (arm) {
|
|
414
|
+
case this.#characteristic.SecuritySystemTargetState.STAY_ARM:
|
|
415
|
+
result = await this.#instance.setPanelStatus(armFrom.armValue, 'stay', isAlarmActive);
|
|
416
|
+
break;
|
|
417
|
+
case this.#characteristic.SecuritySystemTargetState.AWAY_ARM:
|
|
418
|
+
result = await this.#instance.setPanelStatus(armFrom.armValue, 'away', isAlarmActive);
|
|
419
|
+
break;
|
|
420
|
+
case this.#characteristic.SecuritySystemTargetState.NIGHT_ARM:
|
|
421
|
+
result = await this.#instance.setPanelStatus(armFrom.armValue, 'night', isAlarmActive);
|
|
422
|
+
break;
|
|
423
|
+
case this.#characteristic.SecuritySystemTargetState.DISARM:
|
|
424
|
+
result = await this.#instance.setPanelStatus(armFrom.armValue, 'off', isAlarmActive);
|
|
425
|
+
break;
|
|
426
|
+
default:
|
|
427
|
+
unknownArmValue = true;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
this.#status = {
|
|
431
|
+
isBusy: false,
|
|
432
|
+
setValue: null,
|
|
433
|
+
};
|
|
434
|
+
if (unknownArmValue) {
|
|
435
|
+
hapStatus = new this.#api.hap.HapStatusError(-70410);
|
|
436
|
+
this.#log.error(`Attempted to set panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but request has unknown arm value.`);
|
|
437
|
+
throw hapStatus;
|
|
438
|
+
}
|
|
439
|
+
if (!result.success) {
|
|
440
|
+
hapStatus = new this.#api.hap.HapStatusError(-70408);
|
|
441
|
+
this.#log.error(`Attempted to set panel status on ${chalk.underline(name)} (id: ${id}, uuid: ${uuid}) accessory but request was not successful.`);
|
|
442
|
+
stackTracer('api-response', result);
|
|
443
|
+
throw hapStatus;
|
|
444
|
+
}
|
|
566
445
|
}
|
|
567
446
|
}
|
|
568
447
|
}
|