homebridge-tydom 0.21.9
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/CHANGELOG.md +9 -0
- package/README.md +287 -0
- package/config.schema.json +38 -0
- package/lib/accessories/contactSensor.d.ts +4 -0
- package/lib/accessories/contactSensor.js +49 -0
- package/lib/accessories/fan.d.ts +4 -0
- package/lib/accessories/fan.js +17 -0
- package/lib/accessories/garageDoorOpener.d.ts +3 -0
- package/lib/accessories/garageDoorOpener.js +49 -0
- package/lib/accessories/lightbulb.d.ts +4 -0
- package/lib/accessories/lightbulb.js +147 -0
- package/lib/accessories/securitySystem.d.ts +5 -0
- package/lib/accessories/securitySystem.js +422 -0
- package/lib/accessories/securitySystemSensors.d.ts +5 -0
- package/lib/accessories/securitySystemSensors.js +160 -0
- package/lib/accessories/services/switchableService.d.ts +5 -0
- package/lib/accessories/services/switchableService.js +66 -0
- package/lib/accessories/switch.d.ts +4 -0
- package/lib/accessories/switch.js +17 -0
- package/lib/accessories/temperatureSensor.d.ts +4 -0
- package/lib/accessories/temperatureSensor.js +52 -0
- package/lib/accessories/thermostat.d.ts +4 -0
- package/lib/accessories/thermostat.js +340 -0
- package/lib/accessories/windowCovering.d.ts +5 -0
- package/lib/accessories/windowCovering.js +167 -0
- package/lib/config/env.d.ts +3 -0
- package/lib/config/env.js +7 -0
- package/lib/config/i18n/en.d.ts +1021 -0
- package/lib/config/i18n/en.js +1022 -0
- package/lib/config/i18n/fr.d.ts +1035 -0
- package/lib/config/i18n/fr.js +1036 -0
- package/lib/config/locale.d.ts +4110 -0
- package/lib/config/locale.js +12 -0
- package/lib/controller.d.ts +40 -0
- package/lib/controller.js +199 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +13 -0
- package/lib/platform.d.ts +37 -0
- package/lib/platform.js +114 -0
- package/lib/typings/tydom.d.ts +186 -0
- package/lib/typings/tydom.js +2 -0
- package/lib/utils/accessory.d.ts +19 -0
- package/lib/utils/accessory.js +139 -0
- package/lib/utils/array.d.ts +2 -0
- package/lib/utils/array.js +8 -0
- package/lib/utils/assert.d.ts +2 -0
- package/lib/utils/assert.js +9 -0
- package/lib/utils/chalk.d.ts +7 -0
- package/lib/utils/chalk.js +21 -0
- package/lib/utils/debug.d.ts +14 -0
- package/lib/utils/debug.js +44 -0
- package/lib/utils/hap.d.ts +6 -0
- package/lib/utils/hap.js +8 -0
- package/lib/utils/hash.d.ts +4 -0
- package/lib/utils/hash.js +28 -0
- package/lib/utils/request.d.ts +10 -0
- package/lib/utils/request.js +43 -0
- package/lib/utils/tydom.d.ts +27 -0
- package/lib/utils/tydom.js +126 -0
- package/lib/utils/webhook.d.ts +19 -0
- package/lib/utils/webhook.js +31 -0
- package/package.json +62 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.updateSecuritySystem = exports.setupSecuritySystem = void 0;
|
|
26
|
+
const lodash_1 = require("lodash");
|
|
27
|
+
const env_1 = require("../config/env");
|
|
28
|
+
const locale_1 = __importDefault(require("../config/locale"));
|
|
29
|
+
const accessory_1 = require("../utils/accessory");
|
|
30
|
+
const array_1 = require("../utils/array");
|
|
31
|
+
const assert_1 = __importDefault(require("../utils/assert"));
|
|
32
|
+
const chalk_1 = require("../utils/chalk");
|
|
33
|
+
const debug_1 = __importStar(require("../utils/debug"));
|
|
34
|
+
const hap_1 = require("../utils/hap");
|
|
35
|
+
const hash_1 = require("../utils/hash");
|
|
36
|
+
const tydom_1 = require("../utils/tydom");
|
|
37
|
+
const getActiveZones = (alarmData) => alarmData.reduce((soFar, { name, value }) => {
|
|
38
|
+
const matches = name.match(/zone([1-8])State/i);
|
|
39
|
+
if (matches && value === 'ON') {
|
|
40
|
+
soFar.push(accessory_1.asNumber(matches[1]));
|
|
41
|
+
}
|
|
42
|
+
return soFar;
|
|
43
|
+
}, []);
|
|
44
|
+
const getStateForActiveZones = (activeZones, zoneAliases) => {
|
|
45
|
+
const { SecuritySystemCurrentState } = hap_1.Characteristic;
|
|
46
|
+
if (zoneAliases.stay && array_1.sameArrays(activeZones, zoneAliases.stay)) {
|
|
47
|
+
return SecuritySystemCurrentState.STAY_ARM;
|
|
48
|
+
}
|
|
49
|
+
if (zoneAliases.night && array_1.sameArrays(activeZones, zoneAliases.night)) {
|
|
50
|
+
return SecuritySystemCurrentState.NIGHT_ARM;
|
|
51
|
+
}
|
|
52
|
+
return SecuritySystemCurrentState.DISARMED;
|
|
53
|
+
};
|
|
54
|
+
const getStateForAlarmData = (alarmData, zoneAliases) => {
|
|
55
|
+
const { SecuritySystemCurrentState } = hap_1.Characteristic;
|
|
56
|
+
const alarmMode = tydom_1.getTydomDataPropValue(alarmData, 'alarmMode');
|
|
57
|
+
const alarmState = tydom_1.getTydomDataPropValue(alarmData, 'alarmState');
|
|
58
|
+
if (['DELAYED', 'ON', 'QUIET'].includes(alarmState)) {
|
|
59
|
+
return SecuritySystemCurrentState.ALARM_TRIGGERED;
|
|
60
|
+
}
|
|
61
|
+
if (alarmMode === 'ON') {
|
|
62
|
+
return SecuritySystemCurrentState.AWAY_ARM;
|
|
63
|
+
}
|
|
64
|
+
if (alarmMode === 'ZONE') {
|
|
65
|
+
const activeZones = getActiveZones(alarmData);
|
|
66
|
+
return getStateForActiveZones(activeZones, zoneAliases);
|
|
67
|
+
}
|
|
68
|
+
return SecuritySystemCurrentState.DISARMED;
|
|
69
|
+
};
|
|
70
|
+
const setupSecuritySystem = async (accessory, controller) => {
|
|
71
|
+
const { context } = accessory;
|
|
72
|
+
const { client } = controller;
|
|
73
|
+
const { SecuritySystemTargetState, SecuritySystemCurrentState, StatusTampered, ContactSensorState, On } = hap_1.Characteristic;
|
|
74
|
+
const { deviceId, endpointId, settings } = context;
|
|
75
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
76
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
77
|
+
const aliases = (settings.aliases || {});
|
|
78
|
+
// Create separate dedicated sensor extra accessory;
|
|
79
|
+
if (settings.sensors !== false) {
|
|
80
|
+
const { accessoryId } = context;
|
|
81
|
+
const extraDevice = {
|
|
82
|
+
...context,
|
|
83
|
+
name: `${lodash_1.get(locale_1.default, 'ALARME_ISSUES_OUVERTES', 'N/A')}`,
|
|
84
|
+
category: accessory_1.SECURITY_SYSTEM_SENSORS,
|
|
85
|
+
accessoryId: `${accessoryId}:sensors`
|
|
86
|
+
};
|
|
87
|
+
controller.emit('device', extraDevice);
|
|
88
|
+
}
|
|
89
|
+
const initialData = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
90
|
+
const labelResults = await client.command(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=label`);
|
|
91
|
+
const { zones } = labelResults[0];
|
|
92
|
+
// Pin code check
|
|
93
|
+
const pin = env_1.HOMEBRIDGE_TYDOM_PIN ? hash_1.decode(env_1.HOMEBRIDGE_TYDOM_PIN) : settings.pin;
|
|
94
|
+
if (!pin) {
|
|
95
|
+
controller.log.warn(`Missing pin for device securitySystem, add either {"settings": {"${deviceId}": {"pin": "123456"}}} or HOMEBRIDGE_TYDOM_PIN env var (base64 encoded)`);
|
|
96
|
+
}
|
|
97
|
+
// Add the actual accessory Service
|
|
98
|
+
const service = accessory_1.addAccessoryService(accessory, hap_1.Service.SecuritySystem, `${accessory.displayName}`, true);
|
|
99
|
+
service
|
|
100
|
+
.getCharacteristic(SecuritySystemCurrentState)
|
|
101
|
+
.setValue(SecuritySystemCurrentState.DISARMED) // Default to disarmed to prevent notifications
|
|
102
|
+
.on("get" /* GET */, async (callback) => {
|
|
103
|
+
debug_1.debugGet(SecuritySystemCurrentState, service);
|
|
104
|
+
try {
|
|
105
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
106
|
+
const nextValue = getStateForAlarmData(data, aliases);
|
|
107
|
+
debug_1.debugGetResult(SecuritySystemCurrentState, service, nextValue);
|
|
108
|
+
callback(null, nextValue);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
callback(err);
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
.getValue();
|
|
115
|
+
service
|
|
116
|
+
.getCharacteristic(StatusTampered)
|
|
117
|
+
.on("get" /* GET */, async (callback) => {
|
|
118
|
+
debug_1.debugGet(StatusTampered, service);
|
|
119
|
+
try {
|
|
120
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
121
|
+
const systAutoProtect = tydom_1.getTydomDataPropValue(data, 'systAutoProtect');
|
|
122
|
+
debug_1.debugGetResult(StatusTampered, service, systAutoProtect);
|
|
123
|
+
callback(null, systAutoProtect);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
callback(err);
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
.getValue();
|
|
130
|
+
service
|
|
131
|
+
.getCharacteristic(SecuritySystemTargetState)
|
|
132
|
+
.on("get" /* GET */, async (callback) => {
|
|
133
|
+
debug_1.debugGet(SecuritySystemTargetState, service);
|
|
134
|
+
try {
|
|
135
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
136
|
+
const nextValue = getStateForAlarmData(data, aliases);
|
|
137
|
+
debug_1.debugGetResult(SecuritySystemTargetState, service, nextValue);
|
|
138
|
+
callback(null, nextValue);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
callback(err);
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
145
|
+
debug_1.debugSet(SecuritySystemTargetState, service, value);
|
|
146
|
+
if (!pin) {
|
|
147
|
+
callback();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Clear preAlarm trigger
|
|
151
|
+
if ([SecuritySystemTargetState.DISARM].includes(value)) {
|
|
152
|
+
preAlarmService.updateCharacteristic(ContactSensorState, false);
|
|
153
|
+
}
|
|
154
|
+
// Global ON/OFF
|
|
155
|
+
if ([SecuritySystemTargetState.AWAY_ARM, SecuritySystemTargetState.DISARM].includes(value)) {
|
|
156
|
+
const tydomValue = value === SecuritySystemTargetState.DISARM ? 'OFF' : 'ON';
|
|
157
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=alarmCmd`, {
|
|
158
|
+
value: tydomValue,
|
|
159
|
+
pwd: pin
|
|
160
|
+
});
|
|
161
|
+
debug_1.debugSetResult(SecuritySystemTargetState, service, value, tydomValue);
|
|
162
|
+
callback();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Zones ON/OFF
|
|
166
|
+
if ([SecuritySystemTargetState.STAY_ARM, SecuritySystemTargetState.NIGHT_ARM].includes(value)) {
|
|
167
|
+
const tydomValue = value === SecuritySystemTargetState.DISARM ? 'OFF' : 'ON';
|
|
168
|
+
const targetZones = value === SecuritySystemTargetState.STAY_ARM ? aliases.stay : aliases.night;
|
|
169
|
+
if (Array.isArray(targetZones) && targetZones.length > 0) {
|
|
170
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=zoneCmd`, {
|
|
171
|
+
value: tydomValue,
|
|
172
|
+
pwd: pin,
|
|
173
|
+
zones: targetZones
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
debug_1.debugSetResult(SecuritySystemTargetState, service, value, tydomValue);
|
|
177
|
+
callback();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// Setup systOpenIssue contactSensor
|
|
182
|
+
const systOpenIssueId = `systOpenIssue`;
|
|
183
|
+
const systOpenIssueName = lodash_1.get(locale_1.default, 'ALARME_ISSUES_OUVERTES', 'N/A');
|
|
184
|
+
const systOpenIssueService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, systOpenIssueName, systOpenIssueId, true);
|
|
185
|
+
debug_1.debugAddSubService(systOpenIssueService, accessory);
|
|
186
|
+
service.addLinkedService(systOpenIssueService);
|
|
187
|
+
systOpenIssueService
|
|
188
|
+
.getCharacteristic(ContactSensorState)
|
|
189
|
+
.on("get" /* GET */, async (callback) => {
|
|
190
|
+
debug_1.debugGet(ContactSensorState, systOpenIssueService);
|
|
191
|
+
try {
|
|
192
|
+
const data = (await tydom_1.getTydomDeviceData(client, { deviceId, endpointId }));
|
|
193
|
+
const systOpenIssue = tydom_1.getTydomDataPropValue(data, 'systOpenIssue');
|
|
194
|
+
debug_1.debugGetResult(ContactSensorState, systOpenIssueService, systOpenIssue);
|
|
195
|
+
callback(null, systOpenIssue);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
callback(err);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
systOpenIssueService.getCharacteristic(hap_1.Characteristic.StatusActive).setValue(true);
|
|
202
|
+
systOpenIssueService.getCharacteristic(hap_1.Characteristic.StatusFault).setValue(false);
|
|
203
|
+
// Setup alarmSOS contactSensor
|
|
204
|
+
const alarmSOSId = `alarmSOS`;
|
|
205
|
+
const alarmSOSName = lodash_1.get(locale_1.default, 'DISCRETE_ALARM_V3', 'N/A');
|
|
206
|
+
const alarmSOSService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, alarmSOSName, alarmSOSId, true);
|
|
207
|
+
debug_1.debugAddSubService(alarmSOSService, accessory);
|
|
208
|
+
service.addLinkedService(alarmSOSService);
|
|
209
|
+
alarmSOSService
|
|
210
|
+
.getCharacteristic(ContactSensorState)
|
|
211
|
+
.on("get" /* GET */, async (callback) => {
|
|
212
|
+
debug_1.debugGet(ContactSensorState, alarmSOSService);
|
|
213
|
+
try {
|
|
214
|
+
const data = (await tydom_1.getTydomDeviceData(client, { deviceId, endpointId }));
|
|
215
|
+
const alarmSOS = tydom_1.getTydomDataPropValue(data, 'alarmSOS');
|
|
216
|
+
debug_1.debugGetResult(ContactSensorState, alarmSOSService, alarmSOS);
|
|
217
|
+
callback(null, alarmSOS);
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
callback(err);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
alarmSOSService.getCharacteristic(hap_1.Characteristic.StatusActive).setValue(true);
|
|
224
|
+
alarmSOSService.getCharacteristic(hap_1.Characteristic.StatusFault).setValue(false);
|
|
225
|
+
// Setup preAlarm contactSensor
|
|
226
|
+
const preAlarmId = `preAlarm`;
|
|
227
|
+
const preAlarmName = lodash_1.get(locale_1.default, 'PREALARM', 'N/A');
|
|
228
|
+
const preAlarmService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, preAlarmName, preAlarmId, true);
|
|
229
|
+
debug_1.debugAddSubService(preAlarmService, accessory);
|
|
230
|
+
service.addLinkedService(preAlarmService);
|
|
231
|
+
preAlarmService.getCharacteristic(ContactSensorState).setValue(false);
|
|
232
|
+
preAlarmService.getCharacteristic(hap_1.Characteristic.StatusActive).setValue(true);
|
|
233
|
+
preAlarmService.getCharacteristic(hap_1.Characteristic.StatusFault).setValue(false);
|
|
234
|
+
// Setup zones switches
|
|
235
|
+
for (let zoneIndex = 1; zoneIndex < 9; zoneIndex++) {
|
|
236
|
+
const zoneState = tydom_1.getTydomDataPropValue(initialData, `zone${zoneIndex}State`);
|
|
237
|
+
if (zoneState === 'UNUSED') {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
assert_1.default(zones[zoneIndex - 1], `Unexpected missing zone label data for index ${zoneIndex}`);
|
|
241
|
+
const { id: productId, nameStd, nameCustom } = zones[zoneIndex - 1];
|
|
242
|
+
const subDeviceId = `zone_${productId}`;
|
|
243
|
+
const subDeviceName = nameCustom || `${nameStd ? lodash_1.get(locale_1.default, nameStd, 'N/A') : `Zone ${zoneIndex}`}`;
|
|
244
|
+
const zoneService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.Switch, subDeviceName, subDeviceId, true);
|
|
245
|
+
debug_1.debugAddSubService(zoneService, accessory);
|
|
246
|
+
service.addLinkedService(zoneService);
|
|
247
|
+
zoneService
|
|
248
|
+
.getCharacteristic(On)
|
|
249
|
+
.on("get" /* GET */, async (callback) => {
|
|
250
|
+
debug_1.debugGet(On, zoneService);
|
|
251
|
+
try {
|
|
252
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
253
|
+
const zoneState = tydom_1.getTydomDataPropValue(data, `zone${zoneIndex}State`);
|
|
254
|
+
const nextValue = zoneState === 'ON';
|
|
255
|
+
debug_1.debugGetResult(On, zoneService, nextValue);
|
|
256
|
+
callback(null, nextValue);
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
callback(err);
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
263
|
+
debug_1.debugSet(On, zoneService, value);
|
|
264
|
+
if (!pin) {
|
|
265
|
+
callback();
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const tydomValue = value ? 'ON' : 'OFF';
|
|
269
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=zoneCmd`, {
|
|
270
|
+
value: tydomValue,
|
|
271
|
+
pwd: pin,
|
|
272
|
+
zones: [zoneIndex]
|
|
273
|
+
});
|
|
274
|
+
debug_1.debugSetResult(On, zoneService, value, tydomValue);
|
|
275
|
+
callback();
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
exports.setupSecuritySystem = setupSecuritySystem;
|
|
280
|
+
const updateSecuritySystem = (accessory, controller, updates, type) => {
|
|
281
|
+
// Relay to separate dedicated sensor extra accessory;
|
|
282
|
+
const { deviceId, endpointId, accessoryId, settings } = accessory.context;
|
|
283
|
+
const aliases = (settings.aliases || {});
|
|
284
|
+
const { SecuritySystemCurrentState, ContactSensorState, On } = hap_1.Characteristic;
|
|
285
|
+
if (settings.sensors !== false) {
|
|
286
|
+
const extraUpdateContext = {
|
|
287
|
+
category: accessory_1.SECURITY_SYSTEM_SENSORS,
|
|
288
|
+
deviceId,
|
|
289
|
+
endpointId,
|
|
290
|
+
accessoryId: `${accessoryId}:sensors`
|
|
291
|
+
};
|
|
292
|
+
controller.emit('update', {
|
|
293
|
+
type,
|
|
294
|
+
updates,
|
|
295
|
+
context: extraUpdateContext
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
// Process command updates
|
|
299
|
+
if (type === 'cdata') {
|
|
300
|
+
updates.forEach((update) => {
|
|
301
|
+
const { name, parameters, values } = update;
|
|
302
|
+
// Notify with webhooks
|
|
303
|
+
switch (name) {
|
|
304
|
+
case 'eventAlarm': {
|
|
305
|
+
const { event } = values;
|
|
306
|
+
debug_1.default(`New ${chalk_1.chalkKeyword('SecuritySystem')} alarm event=${chalk_1.chalkJson(event)}`);
|
|
307
|
+
controller.emit('notification', {
|
|
308
|
+
level: 'warn',
|
|
309
|
+
message: `SecuritySystem \`${name}\` event, name=\`${event.name}\` parameters=\`${JSON.stringify(parameters)}\`, values=\`${JSON.stringify(values)}\``
|
|
310
|
+
});
|
|
311
|
+
switch (event.name) {
|
|
312
|
+
case 'arret': {
|
|
313
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.SecuritySystem);
|
|
314
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, SecuritySystemCurrentState.DISARMED);
|
|
315
|
+
service.updateCharacteristic(SecuritySystemCurrentState, SecuritySystemCurrentState.DISARMED);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
case 'marcheTotale': {
|
|
319
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.SecuritySystem);
|
|
320
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, SecuritySystemCurrentState.AWAY_ARM);
|
|
321
|
+
service.updateCharacteristic(SecuritySystemCurrentState, SecuritySystemCurrentState.AWAY_ARM);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
case 'marcheZone': {
|
|
325
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.SecuritySystem);
|
|
326
|
+
const activeZones = event.zones.map((zone) => zone.id + 1);
|
|
327
|
+
const nextValue = getStateForActiveZones(activeZones, aliases);
|
|
328
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, nextValue);
|
|
329
|
+
service.updateCharacteristic(SecuritySystemCurrentState, nextValue);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
case 'preAlarm': {
|
|
333
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, 'preAlarm');
|
|
334
|
+
debug_1.debugSetUpdate(ContactSensorState, service, true);
|
|
335
|
+
service.updateCharacteristic(ContactSensorState, true);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
default: {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
default: {
|
|
344
|
+
controller.emit('notification', {
|
|
345
|
+
level: 'debug',
|
|
346
|
+
message: `SecuritySystem \`${name}\` event parameters=\`${JSON.stringify(parameters)}\`, values=\`${JSON.stringify(values)}\``
|
|
347
|
+
});
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
updates.forEach((update) => {
|
|
355
|
+
const { name, value } = update;
|
|
356
|
+
switch (name) {
|
|
357
|
+
case 'alarmMode': {
|
|
358
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.SecuritySystem);
|
|
359
|
+
switch (value) {
|
|
360
|
+
case 'OFF': {
|
|
361
|
+
const nextValue = SecuritySystemCurrentState.DISARMED;
|
|
362
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, nextValue);
|
|
363
|
+
service.updateCharacteristic(SecuritySystemCurrentState, nextValue);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
case 'ON': {
|
|
367
|
+
const nextValue = SecuritySystemCurrentState.AWAY_ARM;
|
|
368
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, nextValue);
|
|
369
|
+
service.updateCharacteristic(SecuritySystemCurrentState, nextValue);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
case 'ZONE': {
|
|
373
|
+
const activeZones = getActiveZones(updates);
|
|
374
|
+
const nextValue = getStateForActiveZones(activeZones, aliases);
|
|
375
|
+
debug_1.debugSetUpdate(SecuritySystemCurrentState, service, nextValue);
|
|
376
|
+
service.updateCharacteristic(SecuritySystemCurrentState, nextValue);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
default:
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
case 'alarmSOS': {
|
|
384
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, 'alarmSOS');
|
|
385
|
+
const alarmSOS = !!value;
|
|
386
|
+
debug_1.debugSetUpdate(ContactSensorState, service, alarmSOS);
|
|
387
|
+
service.updateCharacteristic(ContactSensorState, alarmSOS);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
case 'zone1State':
|
|
391
|
+
case 'zone2State':
|
|
392
|
+
case 'zone3State':
|
|
393
|
+
case 'zone4State':
|
|
394
|
+
case 'zone5State':
|
|
395
|
+
case 'zone6State':
|
|
396
|
+
case 'zone7State':
|
|
397
|
+
case 'zone8State': {
|
|
398
|
+
const zoneState = value;
|
|
399
|
+
if (zoneState === 'UNUSED') {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
403
|
+
const zoneIndex = parseInt(name.match(/zone(\d+)State/)[1], 10) - 1; // @NOTE Adjust for productId starting at 0
|
|
404
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.Switch, `zone_${zoneIndex}`);
|
|
405
|
+
const nextValue = zoneState === 'ON';
|
|
406
|
+
debug_1.debugSetUpdate(On, service, nextValue);
|
|
407
|
+
service.updateCharacteristic(On, nextValue);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
case 'systOpenIssue': {
|
|
411
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, 'systOpenIssue');
|
|
412
|
+
const systOpenIssue = !!value;
|
|
413
|
+
debug_1.debugSetUpdate(ContactSensorState, service, systOpenIssue);
|
|
414
|
+
service.updateCharacteristic(ContactSensorState, systOpenIssue);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
default:
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
exports.updateSecuritySystem = updateSecuritySystem;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import TydomController from '../controller';
|
|
3
|
+
import { TydomAccessoryUpdateType } from '../utils/accessory';
|
|
4
|
+
export declare const setupSecuritySystemSensors: (accessory: PlatformAccessory, controller: TydomController) => Promise<void>;
|
|
5
|
+
export declare const updateSecuritySystemSensors: (accessory: PlatformAccessory, controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.updateSecuritySystemSensors = exports.setupSecuritySystemSensors = void 0;
|
|
7
|
+
const lodash_1 = require("lodash");
|
|
8
|
+
const locale_1 = __importDefault(require("../config/locale"));
|
|
9
|
+
const accessory_1 = require("../utils/accessory");
|
|
10
|
+
const debug_1 = require("../utils/debug");
|
|
11
|
+
const hap_1 = require("../utils/hap");
|
|
12
|
+
const tydom_1 = require("../utils/tydom");
|
|
13
|
+
const getOpenedIssues = (commandResults) => lodash_1.keyBy(
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15
|
+
commandResults.filter((result) => result.product).map((result) => result.product), 'id');
|
|
16
|
+
let contactSensorProducts = [];
|
|
17
|
+
let histoSearchParams;
|
|
18
|
+
const setupSecuritySystemSensors = async (accessory, controller) => {
|
|
19
|
+
const { context } = accessory;
|
|
20
|
+
const { client } = controller;
|
|
21
|
+
const { ContactSensorState } = hap_1.Characteristic;
|
|
22
|
+
const { deviceId, endpointId } = context;
|
|
23
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
24
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
25
|
+
const labelResults = await client.command(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=label`);
|
|
26
|
+
const { products } = labelResults[0];
|
|
27
|
+
contactSensorProducts = products.filter((product) => ['MDO'].includes(product.typeLong));
|
|
28
|
+
histoSearchParams = { type: 'OPEN_ISSUES', indexStart: '0', nbElem: `${contactSensorProducts.length}` };
|
|
29
|
+
const initialOpenedIssues = getOpenedIssues(await tydom_1.runTydomDeviceCommand(client, 'histo', {
|
|
30
|
+
deviceId,
|
|
31
|
+
endpointId,
|
|
32
|
+
searchParams: histoSearchParams
|
|
33
|
+
}));
|
|
34
|
+
contactSensorProducts.forEach((contactSensorProduct) => {
|
|
35
|
+
const { id: productId, nameStd, nameCustom, number } = contactSensorProduct;
|
|
36
|
+
const subDeviceId = `systOpenIssue_${productId}`;
|
|
37
|
+
const subDeviceName = nameCustom || `${lodash_1.get(locale_1.default, nameStd, 'N/A')}${number ? ` ${number}` : ''}`;
|
|
38
|
+
const contactSensorService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, subDeviceName, subDeviceId, true);
|
|
39
|
+
debug_1.debugAddSubService(contactSensorService, accessory);
|
|
40
|
+
// service.addLinkedService(contactSensorService); // @TODO ServiceLabel?
|
|
41
|
+
contactSensorService
|
|
42
|
+
.getCharacteristic(ContactSensorState)
|
|
43
|
+
.setValue(initialOpenedIssues[productId] ? 1 : 0)
|
|
44
|
+
.on("get" /* GET */, async (callback) => {
|
|
45
|
+
debug_1.debugGet(ContactSensorState, contactSensorService);
|
|
46
|
+
try {
|
|
47
|
+
const openedIssues = getOpenedIssues(await tydom_1.runTydomDeviceCommand(client, 'histo', {
|
|
48
|
+
deviceId,
|
|
49
|
+
endpointId,
|
|
50
|
+
searchParams: histoSearchParams
|
|
51
|
+
}));
|
|
52
|
+
const nextValue = openedIssues[productId] ? 1 : 0;
|
|
53
|
+
debug_1.debugGetResult(ContactSensorState, contactSensorService, nextValue);
|
|
54
|
+
callback(null, nextValue);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
callback(err);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
contactSensorService.getCharacteristic(hap_1.Characteristic.StatusActive).setValue(1);
|
|
61
|
+
contactSensorService.getCharacteristic(hap_1.Characteristic.StatusFault).setValue(0);
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
exports.setupSecuritySystemSensors = setupSecuritySystemSensors;
|
|
65
|
+
const updateSecuritySystemSensors = (accessory, controller, updates, type) => {
|
|
66
|
+
const { client } = controller;
|
|
67
|
+
// Process command updates
|
|
68
|
+
if (type === 'cdata') {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
updates.forEach(async (update) => {
|
|
72
|
+
const { context } = accessory;
|
|
73
|
+
const { deviceId, endpointId } = context;
|
|
74
|
+
const { ContactSensorState } = hap_1.Characteristic;
|
|
75
|
+
const { name, value } = update;
|
|
76
|
+
switch (name) {
|
|
77
|
+
case 'systOpenIssue': {
|
|
78
|
+
const systOpenIssue = value;
|
|
79
|
+
if (!systOpenIssue) {
|
|
80
|
+
contactSensorProducts.forEach(({ id: productId }) => {
|
|
81
|
+
const subDeviceId = `systOpenIssue_${productId}`;
|
|
82
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, subDeviceId);
|
|
83
|
+
const nextValue = 0;
|
|
84
|
+
debug_1.debugSetUpdate(ContactSensorState, service, nextValue);
|
|
85
|
+
service.updateCharacteristic(ContactSensorState, nextValue);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const openedIssues = getOpenedIssues(await tydom_1.runTydomDeviceCommand(client, 'histo', {
|
|
90
|
+
deviceId,
|
|
91
|
+
endpointId,
|
|
92
|
+
searchParams: histoSearchParams
|
|
93
|
+
}));
|
|
94
|
+
contactSensorProducts.forEach(({ id: productId }) => {
|
|
95
|
+
const subDeviceId = `systOpenIssue_${productId}`;
|
|
96
|
+
const service = accessory_1.getAccessoryServiceWithSubtype(accessory, hap_1.Service.ContactSensor, subDeviceId);
|
|
97
|
+
const nextValue = openedIssues[productId] ? 1 : 0;
|
|
98
|
+
debug_1.debugSetUpdate(ContactSensorState, service, nextValue);
|
|
99
|
+
service.updateCharacteristic(ContactSensorState, nextValue);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
default:
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
exports.updateSecuritySystemSensors = updateSecuritySystemSensors;
|
|
110
|
+
/*
|
|
111
|
+
{
|
|
112
|
+
initialOpenedIssues: [
|
|
113
|
+
{
|
|
114
|
+
step: 0,
|
|
115
|
+
nbElemTot: 2,
|
|
116
|
+
index: 16,
|
|
117
|
+
product: {
|
|
118
|
+
typeShort: 'MDO',
|
|
119
|
+
typeLong: 'MDO',
|
|
120
|
+
id: 16,
|
|
121
|
+
nameStd: 'BASEMENT',
|
|
122
|
+
number: 3
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
step: 1,
|
|
127
|
+
nbElemTot: 2,
|
|
128
|
+
index: 17,
|
|
129
|
+
product: {
|
|
130
|
+
typeShort: 'MDO',
|
|
131
|
+
typeLong: 'MDO',
|
|
132
|
+
id: 17,
|
|
133
|
+
nameStd: 'BASEMENT',
|
|
134
|
+
number: 2
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{ step: 2, nbElemTot: 2, index: 51 }
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
*/
|
|
141
|
+
/*
|
|
142
|
+
{
|
|
143
|
+
openedIssues: {
|
|
144
|
+
'16': {
|
|
145
|
+
typeShort: 'MDO',
|
|
146
|
+
typeLong: 'MDO',
|
|
147
|
+
id: 16,
|
|
148
|
+
nameStd: 'BASEMENT',
|
|
149
|
+
number: 3
|
|
150
|
+
},
|
|
151
|
+
'17': {
|
|
152
|
+
typeShort: 'MDO',
|
|
153
|
+
typeLong: 'MDO',
|
|
154
|
+
id: 17,
|
|
155
|
+
nameStd: 'BASEMENT',
|
|
156
|
+
number: 2
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
*/
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PlatformAccessory, Service } from 'homebridge';
|
|
2
|
+
import TydomController from '../../controller';
|
|
3
|
+
import { ServiceClass } from '../../utils/accessory';
|
|
4
|
+
export declare const addAccessorySwitchableService: (accessory: PlatformAccessory, controller: TydomController, serviceClass: ServiceClass) => Service;
|
|
5
|
+
export declare const updateAccessorySwitchableService: (accessory: PlatformAccessory, _controller: TydomController, updates: Record<string, unknown>[], ServiceClass: ServiceClass) => void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateAccessorySwitchableService = exports.addAccessorySwitchableService = void 0;
|
|
4
|
+
const accessory_1 = require("../../utils/accessory");
|
|
5
|
+
const debug_1 = require("../../utils/debug");
|
|
6
|
+
const hap_1 = require("../../utils/hap");
|
|
7
|
+
const tydom_1 = require("../../utils/tydom");
|
|
8
|
+
const addAccessorySwitchableService = (accessory, controller, serviceClass) => {
|
|
9
|
+
const { context } = accessory;
|
|
10
|
+
const { client } = controller;
|
|
11
|
+
const { On } = hap_1.Characteristic;
|
|
12
|
+
const { deviceId, endpointId } = context;
|
|
13
|
+
const service = accessory_1.addAccessoryService(accessory, serviceClass, `${accessory.displayName}`, true);
|
|
14
|
+
service
|
|
15
|
+
.getCharacteristic(On)
|
|
16
|
+
.on("get" /* GET */, async (callback) => {
|
|
17
|
+
debug_1.debugGet(On, service);
|
|
18
|
+
try {
|
|
19
|
+
const data = (await tydom_1.getTydomDeviceData(client, { deviceId, endpointId }));
|
|
20
|
+
const level = tydom_1.getTydomDataPropValue(data, 'level');
|
|
21
|
+
const nextValue = level === 100;
|
|
22
|
+
debug_1.debugGetResult(On, service, nextValue);
|
|
23
|
+
callback(null, nextValue);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
callback(err);
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
30
|
+
debug_1.debugSet(On, service, value);
|
|
31
|
+
try {
|
|
32
|
+
const tydomValue = value ? 100 : 0;
|
|
33
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
34
|
+
{
|
|
35
|
+
name: 'level',
|
|
36
|
+
value: tydomValue
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
debug_1.debugSetResult(On, service, value, tydomValue);
|
|
40
|
+
callback();
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
callback(err);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return service;
|
|
47
|
+
};
|
|
48
|
+
exports.addAccessorySwitchableService = addAccessorySwitchableService;
|
|
49
|
+
const updateAccessorySwitchableService = (accessory, _controller, updates, ServiceClass) => {
|
|
50
|
+
updates.forEach((update) => {
|
|
51
|
+
const { name, value } = update;
|
|
52
|
+
const { On } = hap_1.Characteristic;
|
|
53
|
+
switch (name) {
|
|
54
|
+
case 'level': {
|
|
55
|
+
const service = accessory_1.getAccessoryService(accessory, ServiceClass);
|
|
56
|
+
const nextValue = value === 100;
|
|
57
|
+
debug_1.debugSetUpdate(On, service, nextValue);
|
|
58
|
+
service.updateCharacteristic(On, nextValue);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
default:
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
exports.updateAccessorySwitchableService = updateAccessorySwitchableService;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import TydomController from '../controller';
|
|
2
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
3
|
+
export declare const setupSwitch: (accessory: PlatformAccessory, controller: TydomController) => void;
|
|
4
|
+
export declare const updateSwitch: (accessory: PlatformAccessory, controller: TydomController, updates: Record<string, unknown>[]) => void;
|