homebridge-adt-pulse 3.0.0-beta.4 → 3.0.0-beta.6

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.
@@ -1,405 +0,0 @@
1
- import type {
2
- ADTPulseAccessoryAccessory,
3
- ADTPulseAccessoryApi,
4
- ADTPulseAccessoryCharacteristic,
5
- ADTPulseAccessoryConstructorAccessory,
6
- ADTPulseAccessoryConstructorApi,
7
- ADTPulseAccessoryConstructorCharacteristic,
8
- ADTPulseAccessoryConstructorInstance,
9
- ADTPulseAccessoryConstructorLog,
10
- ADTPulseAccessoryConstructorService,
11
- ADTPulseAccessoryConstructorState,
12
- ADTPulseAccessoryGetPanelStatusContext,
13
- ADTPulseAccessoryGetPanelStatusMode,
14
- ADTPulseAccessoryGetPanelStatusReturns,
15
- ADTPulseAccessoryGetSensorStatusContext,
16
- ADTPulseAccessoryGetSensorStatusReturns,
17
- ADTPulseAccessoryInstance,
18
- ADTPulseAccessoryLog,
19
- ADTPulseAccessoryServices,
20
- ADTPulseAccessorySetPanelStatusArm,
21
- ADTPulseAccessorySetPanelStatusContext,
22
- ADTPulseAccessorySetPanelStatusReturns,
23
- ADTPulseAccessoryState,
24
- } from '@/types/index.d.ts';
25
-
26
- /**
27
- * ADT Pulse Accessory.
28
- *
29
- * @since 1.0.0
30
- */
31
- export class ADTPulseAccessory {
32
- /**
33
- * ADT Pulse Accessory - Accessory.
34
- *
35
- * @private
36
- *
37
- * @since 1.0.0
38
- */
39
- #accessory: ADTPulseAccessoryAccessory;
40
-
41
- /**
42
- * ADT Pulse Accessory - Api.
43
- *
44
- * @private
45
- *
46
- * @since 1.0.0
47
- */
48
- #api: ADTPulseAccessoryApi;
49
-
50
- /**
51
- * ADT Pulse Accessory - Characteristic.
52
- *
53
- * @private
54
- *
55
- * @since 1.0.0
56
- */
57
- #characteristic: ADTPulseAccessoryCharacteristic;
58
-
59
- /**
60
- * ADT Pulse Accessory - Instance.
61
- *
62
- * @private
63
- *
64
- * @since 1.0.0
65
- */
66
- #instance: ADTPulseAccessoryInstance;
67
-
68
- /**
69
- * ADT Pulse Accessory - Log.
70
- *
71
- * @private
72
- *
73
- * @since 1.0.0
74
- */
75
- #log: ADTPulseAccessoryLog;
76
-
77
- /**
78
- * ADT Pulse Accessory - Services.
79
- *
80
- * @private
81
- *
82
- * @since 1.0.0
83
- */
84
- #services: ADTPulseAccessoryServices;
85
-
86
- /**
87
- * ADT Pulse Accessory - State.
88
- *
89
- * @private
90
- *
91
- * @since 1.0.0
92
- */
93
- readonly #state: ADTPulseAccessoryState;
94
-
95
- /**
96
- * ADT Pulse Accessory - Constructor.
97
- *
98
- * @param {ADTPulseAccessoryConstructorAccessory} accessory - Accessory.
99
- * @param {ADTPulseAccessoryConstructorState} state - State.
100
- * @param {ADTPulseAccessoryConstructorInstance} instance - Instance.
101
- * @param {ADTPulseAccessoryConstructorService} service - Service.
102
- * @param {ADTPulseAccessoryConstructorCharacteristic} characteristic - Characteristic.
103
- * @param {ADTPulseAccessoryConstructorApi} api - Api.
104
- * @param {ADTPulseAccessoryConstructorLog} log - Log.
105
- *
106
- * @since 1.0.0
107
- */
108
- constructor(accessory: ADTPulseAccessoryConstructorAccessory, state: ADTPulseAccessoryConstructorState, instance: ADTPulseAccessoryConstructorInstance, service: ADTPulseAccessoryConstructorService, characteristic: ADTPulseAccessoryConstructorCharacteristic, api: ADTPulseAccessoryConstructorApi, log: ADTPulseAccessoryConstructorLog) {
109
- this.#accessory = accessory;
110
- this.#api = api;
111
- this.#characteristic = characteristic;
112
- this.#instance = instance;
113
- this.#log = log;
114
- this.#services = {};
115
- this.#state = state;
116
-
117
- // Set the "AccessoryInformation" service.
118
- this.#services.Information = this.#accessory.getService(service.AccessoryInformation) ?? this.#accessory.addService(service.AccessoryInformation);
119
-
120
- // Set the "AccessoryInformation" characteristics.
121
- this.#services.Information
122
- .setCharacteristic(this.#characteristic.Identify, false)
123
- .setCharacteristic(this.#characteristic.Manufacturer, accessory.context.manufacturer ?? 'ADT')
124
- .setCharacteristic(this.#characteristic.Model, accessory.context.model ?? 'N/A')
125
- .setCharacteristic(this.#characteristic.Name, accessory.context.name)
126
- .setCharacteristic(this.#characteristic.SerialNumber, accessory.context.serial ?? 'N/A')
127
- .setCharacteristic(this.#characteristic.FirmwareRevision, accessory.context.firmware ?? 'N/A')
128
- .setCharacteristic(this.#characteristic.HardwareRevision, accessory.context.hardware ?? 'N/A')
129
- .setCharacteristic(this.#characteristic.SoftwareRevision, accessory.context.software ?? 'N/A');
130
-
131
- // Set the service associated with the accessory.
132
- switch (accessory.context.type) {
133
- case 'co':
134
- this.#services.Primary = this.#accessory.getService(service.CarbonMonoxideSensor) ?? this.#accessory.addService(service.CarbonMonoxideSensor);
135
- break;
136
- case 'doorWindow':
137
- this.#services.Primary = this.#accessory.getService(service.ContactSensor) ?? this.#accessory.addService(service.ContactSensor);
138
- break;
139
- case 'fire':
140
- this.#services.Primary = this.#accessory.getService(service.SmokeSensor) ?? this.#accessory.addService(service.SmokeSensor);
141
- break;
142
- case 'flood':
143
- this.#services.Primary = this.#accessory.getService(service.LeakSensor) ?? this.#accessory.addService(service.LeakSensor);
144
- break;
145
- case 'gateway':
146
- // No supported service available.
147
- break;
148
- case 'glass':
149
- this.#services.Primary = this.#accessory.getService(service.MotionSensor) ?? this.#accessory.addService(service.MotionSensor);
150
- break;
151
- case 'motion':
152
- this.#services.Primary = this.#accessory.getService(service.MotionSensor) ?? this.#accessory.addService(service.MotionSensor);
153
- break;
154
- case 'panel':
155
- this.#services.Primary = this.#accessory.getService(service.SecuritySystem) ?? this.#accessory.addService(service.SecuritySystem);
156
- break;
157
- case 'temperature':
158
- this.#services.Primary = this.#accessory.getService(service.TemperatureSensor) ?? this.#accessory.addService(service.TemperatureSensor);
159
- break;
160
- default:
161
- break;
162
- }
163
-
164
- // Check for missing services.
165
- if (this.#services.Primary === undefined) {
166
- // The "gateway" accessory does not need to be initialized further.
167
- if (accessory.context.type !== 'gateway') {
168
- this.#log.error(`Failed to initialize ${accessory.context.name} (id: ${accessory.context.id}, uuid: ${accessory.context.uuid}) accessory services ...`);
169
- }
170
-
171
- return;
172
- }
173
-
174
- // Set the characteristics associated with the specific type of accessory.
175
- switch (accessory.context.type) {
176
- case 'co':
177
- this.#services.Primary.getCharacteristic(this.#characteristic.CarbonMonoxideDetected)
178
- .onGet(() => this.getSensorStatus(accessory.context));
179
- break;
180
- case 'doorWindow':
181
- this.#services.Primary.getCharacteristic(this.#characteristic.ContactSensorState)
182
- .onGet(() => this.getSensorStatus(accessory.context));
183
- break;
184
- case 'fire':
185
- this.#services.Primary.getCharacteristic(this.#characteristic.SmokeDetected)
186
- .onGet(() => this.getSensorStatus(accessory.context));
187
- break;
188
- case 'flood':
189
- this.#services.Primary.getCharacteristic(this.#characteristic.LeakDetected)
190
- .onGet(() => this.getSensorStatus(accessory.context));
191
- break;
192
- case 'gateway':
193
- // No supported characteristic available.
194
- break;
195
- case 'glass':
196
- this.#services.Primary.getCharacteristic(this.#characteristic.MotionDetected)
197
- .onGet(() => this.getSensorStatus(accessory.context));
198
- break;
199
- case 'motion':
200
- this.#services.Primary.getCharacteristic(this.#characteristic.MotionDetected)
201
- .onGet(() => this.getSensorStatus(accessory.context));
202
- break;
203
- case 'panel':
204
- this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemCurrentState)
205
- .onGet(() => this.getPanelStatus('current', accessory.context));
206
- this.#services.Primary.getCharacteristic(this.#characteristic.SecuritySystemTargetState)
207
- .onGet(() => this.getPanelStatus('target', accessory.context))
208
- .onSet((value) => this.setPanelStatus(value, accessory.context));
209
- break;
210
- case 'temperature':
211
- this.#services.Primary.getCharacteristic(this.#characteristic.CurrentTemperature)
212
- .onGet(() => this.getSensorStatus(accessory.context));
213
- break;
214
- default:
215
- break;
216
- }
217
- }
218
-
219
- /**
220
- * ADT Pulse Accessory - Get sensor status.
221
- *
222
- * @param {ADTPulseAccessoryGetSensorStatusContext} context - Context.
223
- *
224
- * @private
225
- *
226
- * @returns {ADTPulseAccessoryGetSensorStatusReturns}
227
- *
228
- * @since 1.0.0
229
- */
230
- private getSensorStatus(context: ADTPulseAccessoryGetSensorStatusContext): ADTPulseAccessoryGetSensorStatusReturns {
231
- const { name, type, zone } = context;
232
-
233
- const sensor = this.#state.data.sensorsStatus.find((sensorStatus) => zone !== null && sensorStatus.name === name && sensorStatus.zone === zone);
234
-
235
- // If the sensor is not found or sensor type is invalid.
236
- if (sensor === undefined || !['co', 'doorWindow', 'fire', 'flood', 'glass', 'motion', 'temperature'].includes(type)) {
237
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST);
238
- }
239
-
240
- const { status } = sensor;
241
-
242
- // If the sensor is currently offline.
243
- if (status === 'Unknown') {
244
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
245
- }
246
-
247
- // Find the status based on the sensor type.
248
- switch (context.type) {
249
- case 'co':
250
- return this.#characteristic.CarbonMonoxideDetected.CO_LEVELS_NORMAL; // TODO Fake status, need more information from portal.
251
- // break; TODO Put this back later when I get the full information in.
252
- case 'doorWindow':
253
- if (status.includes('Open')) {
254
- return this.#characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
255
- }
256
-
257
- if (status.includes('Closed')) {
258
- return this.#characteristic.ContactSensorState.CONTACT_DETECTED;
259
- }
260
- break;
261
- case 'fire':
262
- return this.#characteristic.SmokeDetected.SMOKE_NOT_DETECTED; // TODO Fake status, need more information from portal.
263
- // break; TODO Put this back later when I get the full information in.
264
- case 'flood':
265
- if (status.includes('ALARM')) {
266
- return this.#characteristic.LeakDetected.LEAK_DETECTED;
267
- }
268
-
269
- if (status.includes('Okay')) {
270
- return this.#characteristic.LeakDetected.LEAK_NOT_DETECTED; // TODO Not 100% sure yet.
271
- }
272
- break;
273
- case 'glass':
274
- if (status.includes('Okay')) {
275
- return false;
276
- }
277
-
278
- if (status.includes('Tripped')) {
279
- return true;
280
- }
281
- break;
282
- case 'motion':
283
- if (status.includes('No Motion')) {
284
- return false;
285
- }
286
-
287
- if (status.includes('Motion')) {
288
- return true;
289
- }
290
- break;
291
- case 'temperature':
292
- return 75; // TODO Fake status, need more information from portal.
293
- // break; TODO Put this back later when I get the full information in.
294
- default:
295
- break;
296
- }
297
-
298
- // Throw error if sensor type not found.
299
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST);
300
- }
301
-
302
- /**
303
- * ADT Pulse Accessory - Get panel status.
304
- *
305
- * @param {ADTPulseAccessoryGetPanelStatusMode} mode - Mode.
306
- * @param {ADTPulseAccessoryGetPanelStatusContext} context - Context.
307
- *
308
- * @private
309
- *
310
- * @returns {ADTPulseAccessoryGetPanelStatusReturns}
311
- *
312
- * @since 1.0.0
313
- */
314
- private getPanelStatus(mode: ADTPulseAccessoryGetPanelStatusMode, context: ADTPulseAccessoryGetPanelStatusContext): ADTPulseAccessoryGetPanelStatusReturns {
315
- // If device is not a security panel.
316
- if (context.type !== 'panel') {
317
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST);
318
- }
319
-
320
- // If panel has no status.
321
- if (
322
- this.#state.data.panelStatus === null
323
- || this.#state.data.panelStatus.state === null
324
- || this.#state.data.panelStatus.status === null
325
- ) {
326
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
327
- }
328
-
329
- const { state, status } = this.#state.data.panelStatus;
330
-
331
- // If panel state is "Service Unavailable".
332
- if (state === 'Status Unavailable') {
333
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
334
- }
335
-
336
- // If mode is "current" and panel status is "BURGLARY ALARM".
337
- if (mode === 'current' && status === 'BURGLARY ALARM') {
338
- return this.#characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED;
339
- }
340
-
341
- // All the other panel states.
342
- switch (state) {
343
- case 'Armed Away':
344
- return (mode === 'current') ? this.#characteristic.SecuritySystemCurrentState.AWAY_ARM : this.#characteristic.SecuritySystemTargetState.AWAY_ARM;
345
- case 'Armed Stay':
346
- return (mode === 'current') ? this.#characteristic.SecuritySystemCurrentState.STAY_ARM : this.#characteristic.SecuritySystemTargetState.STAY_ARM;
347
- case 'Armed Night':
348
- return (mode === 'current') ? this.#characteristic.SecuritySystemCurrentState.NIGHT_ARM : this.#characteristic.SecuritySystemTargetState.NIGHT_ARM;
349
- case 'Disarmed':
350
- return (mode === 'current') ? this.#characteristic.SecuritySystemCurrentState.DISARMED : this.#characteristic.SecuritySystemTargetState.DISARM;
351
- default:
352
- break;
353
- }
354
-
355
- // If panel has unknown status.
356
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
357
- }
358
-
359
- /**
360
- * ADT Pulse Accessory - Set panel status.
361
- *
362
- * @param {ADTPulseAccessorySetPanelStatusArm} arm - Arm.
363
- * @param {ADTPulseAccessorySetPanelStatusContext} context - Context.
364
- *
365
- * @private
366
- *
367
- * @returns {ADTPulseAccessorySetPanelStatusReturns}
368
- *
369
- * @since 1.0.0
370
- */
371
- private async setPanelStatus(arm: ADTPulseAccessorySetPanelStatusArm, context: ADTPulseAccessorySetPanelStatusContext): ADTPulseAccessorySetPanelStatusReturns {
372
- let result;
373
-
374
- // If device is not a security panel.
375
- if (context.type !== 'panel') {
376
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST);
377
- }
378
-
379
- // Set the panel status.
380
- switch (arm) {
381
- case this.#characteristic.SecuritySystemTargetState.STAY_ARM:
382
- result = await this.#instance.setPanelStatus('stay');
383
- break;
384
- case this.#characteristic.SecuritySystemTargetState.AWAY_ARM:
385
- result = await this.#instance.setPanelStatus('away');
386
- break;
387
- case this.#characteristic.SecuritySystemTargetState.NIGHT_ARM:
388
- result = await this.#instance.setPanelStatus('night');
389
- break;
390
- case this.#characteristic.SecuritySystemTargetState.DISARM:
391
- result = await this.#instance.setPanelStatus('off');
392
- break;
393
- default:
394
- break;
395
- }
396
-
397
- // If setting the panel status was successful.
398
- if (result && result.success) {
399
- return;
400
- }
401
-
402
- // If panel has unknown arm value.
403
- throw new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.INVALID_VALUE_IN_REQUEST);
404
- }
405
- }