homebridge-tydom 0.23.3 → 0.23.5
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 +32 -0
- package/lib/accessories/contactSensor.d.ts +3 -2
- package/lib/accessories/fan.d.ts +3 -2
- package/lib/accessories/garageDoorOpener.d.ts +17 -4
- package/lib/accessories/garageDoorOpener.js +98 -32
- package/lib/accessories/lightbulb.d.ts +11 -2
- package/lib/accessories/outlet.d.ts +3 -2
- package/lib/accessories/securitySystem.d.ts +14 -2
- package/lib/accessories/securitySystem.js +3 -3
- package/lib/accessories/securitySystemSensors.d.ts +3 -2
- package/lib/accessories/services/switchableService.d.ts +3 -2
- package/lib/accessories/switch.d.ts +3 -2
- package/lib/accessories/switch.js +3 -3
- package/lib/accessories/temperatureSensor.d.ts +3 -2
- package/lib/accessories/thermostat.d.ts +3 -2
- package/lib/accessories/triggerSwitch.d.ts +10 -0
- package/lib/accessories/{basicGarageDoorOpener.js → triggerSwitch.js} +11 -12
- package/lib/accessories/windowCovering.d.ts +13 -2
- package/lib/controller.js +1 -1
- package/lib/helpers/accessory.d.ts +17 -5
- package/lib/helpers/accessory.js +12 -4
- package/lib/platform.d.ts +4 -4
- package/lib/platform.js +4 -4
- package/lib/typings/tydom.d.ts +10 -8
- package/lib/utils/basic.d.ts +1 -1
- package/lib/utils/basic.js +14 -1
- package/package.json +3 -2
- package/lib/accessories/basicGarageDoorOpener.d.ts +0 -3
- package/lib/utils/accessory.d.ts +0 -19
- package/lib/utils/accessory.js +0 -139
- package/lib/utils/array.d.ts +0 -2
- package/lib/utils/array.js +0 -8
- package/lib/utils/hap.d.ts +0 -6
- package/lib/utils/hap.js +0 -8
- package/lib/utils/tydom.d.ts +0 -27
- package/lib/utils/tydom.js +0 -126
- package/lib/utils/webhook.d.ts +0 -19
- package/lib/utils/webhook.js +0 -31
package/README.md
CHANGED
|
@@ -139,6 +139,38 @@ You can optionnaly rename zones (default is `Zone 1`, `Zone 2`, etc.),
|
|
|
139
139
|
}
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
#### GarageDoorOpener
|
|
143
|
+
|
|
144
|
+
You can customize the default GarageDoorOpener `delay` (defaults to 20 seconds)
|
|
145
|
+
|
|
146
|
+
Value is in milliseconds:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"platforms": [
|
|
151
|
+
{
|
|
152
|
+
"settings": {
|
|
153
|
+
"1529094720": {"delay": 10000} // 10 seconds
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can also configure an `autoCloseDelay`
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"platforms": [
|
|
165
|
+
{
|
|
166
|
+
"settings": {
|
|
167
|
+
"1529094720": {"autoCloseDelay": 300000} // 5 minutes
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
142
174
|
#### Webhooks
|
|
143
175
|
|
|
144
176
|
You can specify webhooks in your `config.json` to receive non homekit-dependent notifications.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
3
|
+
import { TydomAccessoryContext } from '../typings';
|
|
4
|
+
export declare const setupContactSensor: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateContactSensor: (accessory: PlatformAccessory<TydomAccessoryContext>, _controller: TydomController, updates: Record<string, unknown>[]) => void;
|
package/lib/accessories/fan.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
3
|
+
import type { TydomAccessoryContext } from '../typings';
|
|
4
|
+
export declare const setupFan: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateFan: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
import { TydomAccessoryUpdateType } from '../helpers
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { TydomAccessoryUpdateType } from '../helpers';
|
|
4
|
+
import { TydomAccessoryContext } from '../typings';
|
|
5
|
+
type GarageDoorOpenerSettings = {
|
|
6
|
+
delay?: number;
|
|
7
|
+
autoCloseDelay?: number;
|
|
8
|
+
};
|
|
9
|
+
type GarageDoorOpenerState = {
|
|
10
|
+
currentDoorState: number;
|
|
11
|
+
targetDoorState: number;
|
|
12
|
+
lastUpdatedAt: number;
|
|
13
|
+
computedPosition: number;
|
|
14
|
+
};
|
|
15
|
+
type GarageDoorOpenerContext = TydomAccessoryContext<GarageDoorOpenerSettings, GarageDoorOpenerState>;
|
|
16
|
+
export declare const setupGarageDoorOpener: (accessory: PlatformAccessory<GarageDoorOpenerContext>, controller: TydomController) => void;
|
|
17
|
+
export declare const updateGarageDoorOpener: (accessory: PlatformAccessory<GarageDoorOpenerContext>, _controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
18
|
+
export {};
|
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.updateGarageDoorOpener = exports.setupGarageDoorOpener = void 0;
|
|
7
|
+
const debug_1 = __importDefault(require("debug"));
|
|
8
|
+
const helpers_1 = require("../helpers");
|
|
9
|
+
const utils_1 = require("../utils");
|
|
4
10
|
const hap_1 = require("../config/hap");
|
|
5
|
-
const
|
|
6
|
-
const basic_1 = require("../utils/basic");
|
|
7
|
-
const chalk_1 = require("../utils/chalk");
|
|
8
|
-
const debug_1 = require("../utils/debug");
|
|
11
|
+
const DEFAULT_GARAGE_DOOR_DELAY = 20 * 1000;
|
|
9
12
|
const setupGarageDoorOpener = (accessory, controller) => {
|
|
10
13
|
const { context } = accessory;
|
|
11
14
|
const { client } = controller;
|
|
12
15
|
const { CurrentDoorState, TargetDoorState } = hap_1.Characteristic;
|
|
13
|
-
const
|
|
14
|
-
const {
|
|
16
|
+
const { deviceId, endpointId, state, settings } = context;
|
|
17
|
+
const { delay: garageDoorDelay = DEFAULT_GARAGE_DOOR_DELAY, autoCloseDelay } = settings;
|
|
15
18
|
const assignState = (update) => {
|
|
16
19
|
Object.assign(state, update);
|
|
17
20
|
};
|
|
21
|
+
const getDoorStateLabel = (currentDoorState) => {
|
|
22
|
+
switch (currentDoorState) {
|
|
23
|
+
case CurrentDoorState.OPEN:
|
|
24
|
+
return 'OPEN';
|
|
25
|
+
case CurrentDoorState.CLOSED:
|
|
26
|
+
return 'CLOSED';
|
|
27
|
+
case CurrentDoorState.OPENING:
|
|
28
|
+
return 'OPENING';
|
|
29
|
+
case CurrentDoorState.CLOSING:
|
|
30
|
+
return 'CLOSING';
|
|
31
|
+
case CurrentDoorState.STOPPED:
|
|
32
|
+
return 'STOPPED';
|
|
33
|
+
}
|
|
34
|
+
return 'UNKNOWN';
|
|
35
|
+
};
|
|
18
36
|
const assignCurrentDoorState = (currentDoorState) => {
|
|
37
|
+
(0, debug_1.default)(`assignCurrentDoorState=${(0, utils_1.chalkString)(getDoorStateLabel(currentDoorState))}`);
|
|
19
38
|
Object.assign(state, { currentDoorState });
|
|
20
39
|
service.updateCharacteristic(CurrentDoorState, currentDoorState);
|
|
21
40
|
};
|
|
@@ -25,20 +44,20 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
25
44
|
value: 'TOGGLE'
|
|
26
45
|
}
|
|
27
46
|
]);
|
|
28
|
-
(0,
|
|
29
|
-
(0,
|
|
47
|
+
(0, helpers_1.setupAccessoryInformationService)(accessory, controller);
|
|
48
|
+
(0, helpers_1.setupAccessoryIdentifyHandler)(accessory, controller);
|
|
30
49
|
assignState({
|
|
31
50
|
currentDoorState: CurrentDoorState.CLOSED,
|
|
32
51
|
targetDoorState: TargetDoorState.CLOSED,
|
|
33
52
|
lastUpdatedAt: 0,
|
|
34
|
-
computedPosition: 0 // 0 <->
|
|
53
|
+
computedPosition: 0 // 0 <-> 100%
|
|
35
54
|
});
|
|
36
55
|
const getNextCurrentDoorState = (targetDoorState) => {
|
|
37
56
|
switch (state.currentDoorState) {
|
|
38
57
|
case CurrentDoorState.OPEN: {
|
|
39
58
|
switch (targetDoorState) {
|
|
40
59
|
case TargetDoorState.CLOSED:
|
|
41
|
-
return CurrentDoorState.
|
|
60
|
+
return CurrentDoorState.CLOSING;
|
|
42
61
|
case TargetDoorState.OPEN:
|
|
43
62
|
return CurrentDoorState.OPEN;
|
|
44
63
|
}
|
|
@@ -49,7 +68,7 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
49
68
|
case TargetDoorState.CLOSED:
|
|
50
69
|
return CurrentDoorState.CLOSED;
|
|
51
70
|
case TargetDoorState.OPEN:
|
|
52
|
-
return CurrentDoorState.
|
|
71
|
+
return CurrentDoorState.OPENING;
|
|
53
72
|
}
|
|
54
73
|
break;
|
|
55
74
|
}
|
|
@@ -71,7 +90,7 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
71
90
|
};
|
|
72
91
|
const computeCurrentPosition = () => {
|
|
73
92
|
const { lastUpdatedAt, computedPosition: lastComputedPosition, currentDoorState } = state;
|
|
74
|
-
const elapsed =
|
|
93
|
+
const elapsed = Date.now() - lastUpdatedAt;
|
|
75
94
|
switch (currentDoorState) {
|
|
76
95
|
case CurrentDoorState.STOPPED: {
|
|
77
96
|
return lastComputedPosition;
|
|
@@ -83,10 +102,10 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
83
102
|
return 0;
|
|
84
103
|
}
|
|
85
104
|
case CurrentDoorState.OPENING: {
|
|
86
|
-
return Math.min(100, lastComputedPosition + elapsed /
|
|
105
|
+
return Math.min(100, lastComputedPosition + 100 * (elapsed / garageDoorDelay));
|
|
87
106
|
}
|
|
88
107
|
case CurrentDoorState.CLOSING: {
|
|
89
|
-
return Math.max(0, lastComputedPosition - elapsed /
|
|
108
|
+
return Math.max(0, lastComputedPosition - 100 * (elapsed / garageDoorDelay));
|
|
90
109
|
}
|
|
91
110
|
}
|
|
92
111
|
return 0;
|
|
@@ -96,14 +115,14 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
96
115
|
if (legacyService) {
|
|
97
116
|
accessory.removeService(legacyService);
|
|
98
117
|
}
|
|
99
|
-
const service = (0,
|
|
118
|
+
const service = (0, helpers_1.addAccessoryService)(accessory, hap_1.Service.GarageDoorOpener, `${accessory.displayName}`, true);
|
|
100
119
|
service
|
|
101
120
|
.getCharacteristic(CurrentDoorState)
|
|
102
121
|
.on("get" /* CharacteristicEventTypes.GET */, async (callback) => {
|
|
103
|
-
(0,
|
|
122
|
+
(0, utils_1.debugGet)(CurrentDoorState, service);
|
|
104
123
|
try {
|
|
105
124
|
const nextValue = state.currentDoorState;
|
|
106
|
-
(0,
|
|
125
|
+
(0, utils_1.debugGetResult)(CurrentDoorState, service, nextValue);
|
|
107
126
|
callback(null, nextValue);
|
|
108
127
|
}
|
|
109
128
|
catch (err) {
|
|
@@ -114,10 +133,10 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
114
133
|
service
|
|
115
134
|
.getCharacteristic(TargetDoorState)
|
|
116
135
|
.on("get" /* CharacteristicEventTypes.GET */, async (callback) => {
|
|
117
|
-
(0,
|
|
136
|
+
(0, utils_1.debugGet)(TargetDoorState, service);
|
|
118
137
|
try {
|
|
119
138
|
const nextValue = state.targetDoorState;
|
|
120
|
-
(0,
|
|
139
|
+
(0, utils_1.debugGetResult)(TargetDoorState, service, nextValue);
|
|
121
140
|
callback(null, nextValue);
|
|
122
141
|
}
|
|
123
142
|
catch (err) {
|
|
@@ -125,47 +144,71 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
125
144
|
}
|
|
126
145
|
})
|
|
127
146
|
.on("set" /* CharacteristicEventTypes.SET */, async (value, callback) => {
|
|
128
|
-
(0,
|
|
147
|
+
(0, utils_1.debugSet)(TargetDoorState, service, value);
|
|
129
148
|
try {
|
|
130
|
-
(0,
|
|
131
|
-
const targetDoorState = (0,
|
|
149
|
+
(0, utils_1.debugSetResult)(TargetDoorState, service, value);
|
|
150
|
+
const targetDoorState = (0, utils_1.asNumber)(value);
|
|
132
151
|
assignState({
|
|
133
152
|
targetDoorState: targetDoorState,
|
|
134
153
|
lastUpdatedAt: Date.now(),
|
|
135
154
|
computedPosition: computeCurrentPosition()
|
|
136
155
|
});
|
|
156
|
+
// debug(`computedPosition=${chalkNumber(state.computedPosition)}`);
|
|
137
157
|
let nextCurrentDoorState = getNextCurrentDoorState(targetDoorState);
|
|
158
|
+
// debug(`nextCurrentDoorState=${chalkString(getDoorStateLabel(nextCurrentDoorState))}`);
|
|
138
159
|
if (nextCurrentDoorState === state.currentDoorState) {
|
|
139
|
-
(0, debug_1.
|
|
160
|
+
(0, debug_1.default)(`nextCurrentDoorState=${(0, utils_1.chalkNumber)(nextCurrentDoorState)} === state.currentDoorState`);
|
|
140
161
|
callback();
|
|
141
162
|
return;
|
|
142
163
|
}
|
|
143
164
|
await toggleGarageDoor();
|
|
144
165
|
assignCurrentDoorState(nextCurrentDoorState);
|
|
145
|
-
callback();
|
|
146
166
|
// Handle Stopped state, if we are stopped, wait one second and trigger again to reverse course
|
|
147
167
|
// eg. Stopped -> Closing if target is Closed
|
|
148
168
|
if (nextCurrentDoorState === CurrentDoorState.STOPPED) {
|
|
149
|
-
await (0,
|
|
169
|
+
await (0, utils_1.waitFor)('stopping', 1000);
|
|
150
170
|
assignState({
|
|
151
171
|
targetDoorState: targetDoorState,
|
|
152
172
|
lastUpdatedAt: Date.now(),
|
|
153
173
|
computedPosition: computeCurrentPosition()
|
|
154
174
|
});
|
|
175
|
+
// debug(`computedPosition=${chalkNumber(state.computedPosition)}`);
|
|
155
176
|
nextCurrentDoorState = getNextCurrentDoorState(targetDoorState);
|
|
177
|
+
// debug(`nextCurrentDoorState=${chalkString(getDoorStateLabel(nextCurrentDoorState))}`);
|
|
156
178
|
await toggleGarageDoor();
|
|
157
179
|
assignCurrentDoorState(nextCurrentDoorState);
|
|
158
180
|
}
|
|
181
|
+
callback();
|
|
159
182
|
// Finally update pending states
|
|
160
183
|
switch (nextCurrentDoorState) {
|
|
161
|
-
case CurrentDoorState.OPENING:
|
|
162
|
-
|
|
163
|
-
|
|
184
|
+
case CurrentDoorState.OPENING: {
|
|
185
|
+
const delay = ((100 - state.computedPosition) * garageDoorDelay) / 100;
|
|
186
|
+
// debug(`delay=${chalkNumber(delay)}`);
|
|
187
|
+
try {
|
|
188
|
+
await (0, utils_1.waitFor)(`${deviceId}.pending`, delay);
|
|
189
|
+
assignCurrentDoorState(CurrentDoorState.OPEN);
|
|
190
|
+
if (autoCloseDelay) {
|
|
191
|
+
await (0, utils_1.waitFor)(`${deviceId}.pending`, autoCloseDelay);
|
|
192
|
+
assignCurrentDoorState(CurrentDoorState.CLOSED);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
// debug(`Aborted OPEN update with delay=${chalkNumber(delay)}`);
|
|
197
|
+
}
|
|
164
198
|
break;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
}
|
|
200
|
+
case CurrentDoorState.CLOSING: {
|
|
201
|
+
const delay = (state.computedPosition * garageDoorDelay) / 100;
|
|
202
|
+
// debug(`delay=${chalkNumber(delay)}`);
|
|
203
|
+
try {
|
|
204
|
+
await (0, utils_1.waitFor)(`${deviceId}.pending`, delay);
|
|
205
|
+
assignCurrentDoorState(CurrentDoorState.CLOSED);
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
// debug(`Aborted CLOSED update with delay=${chalkNumber(delay)}`);
|
|
209
|
+
}
|
|
168
210
|
break;
|
|
211
|
+
}
|
|
169
212
|
}
|
|
170
213
|
}
|
|
171
214
|
catch (err) {
|
|
@@ -173,6 +216,29 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
173
216
|
}
|
|
174
217
|
})
|
|
175
218
|
.getValue();
|
|
219
|
+
// const switchService = addAccessoryService(accessory, Service.Switch, `${accessory.displayName} Switch`, true);
|
|
220
|
+
// debugAddSubService(switchService, accessory);
|
|
221
|
+
// service.addLinkedService(switchService);
|
|
222
|
+
// switchService
|
|
223
|
+
// .getCharacteristic(Characteristic.On)
|
|
224
|
+
// .on(CharacteristicEventTypes.SET, async (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
|
225
|
+
// debugSet(Characteristic.On, service, value);
|
|
226
|
+
// if (!value) {
|
|
227
|
+
// callback();
|
|
228
|
+
// return;
|
|
229
|
+
// }
|
|
230
|
+
// try {
|
|
231
|
+
// await toggleGarageDoor();
|
|
232
|
+
// debugSetResult(Characteristic.On, service, value);
|
|
233
|
+
// callback();
|
|
234
|
+
// setTimeout(() => {
|
|
235
|
+
// service.updateCharacteristic(Characteristic.On, false);
|
|
236
|
+
// }, 1000);
|
|
237
|
+
// } catch (err) {
|
|
238
|
+
// callback(err as Error);
|
|
239
|
+
// }
|
|
240
|
+
// })
|
|
241
|
+
// .updateValue(false);
|
|
176
242
|
};
|
|
177
243
|
exports.setupGarageDoorOpener = setupGarageDoorOpener;
|
|
178
244
|
const updateGarageDoorOpener = (accessory, _controller, updates, type) => {
|
|
@@ -183,7 +249,7 @@ const updateGarageDoorOpener = (accessory, _controller, updates, type) => {
|
|
|
183
249
|
updates.forEach((update) => {
|
|
184
250
|
const { values } = update;
|
|
185
251
|
const { event } = values;
|
|
186
|
-
(0, debug_1.
|
|
252
|
+
(0, debug_1.default)(`New ${(0, utils_1.chalkKeyword)('GarageDoorOpener')} event=${(0, utils_1.chalkJson)(event)}`);
|
|
187
253
|
});
|
|
188
254
|
return;
|
|
189
255
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { TydomAccessoryContext } from '../typings/tydom';
|
|
4
|
+
type LightbulbSettings = Record<string, never>;
|
|
5
|
+
type LightbulbState = {
|
|
6
|
+
latestBrightness: number;
|
|
7
|
+
pendingUpdatedValues: number[];
|
|
8
|
+
lastUpdatedAt: number;
|
|
9
|
+
};
|
|
10
|
+
type LightbulbContext = TydomAccessoryContext<LightbulbSettings, LightbulbState>;
|
|
11
|
+
export declare const setupLightbulb: (accessory: PlatformAccessory<LightbulbContext>, controller: TydomController) => void;
|
|
12
|
+
export declare const updateLightbulb: (accessory: PlatformAccessory<LightbulbContext>, controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
13
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import { TydomAccessoryContext } from '../typings';
|
|
2
3
|
import TydomController from '../controller';
|
|
3
|
-
export declare const setupOutlet: (accessory: PlatformAccessory
|
|
4
|
-
export declare const updateOutlet: (accessory: PlatformAccessory
|
|
4
|
+
export declare const setupOutlet: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateOutlet: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
3
|
import { TydomAccessoryUpdateType } from '../helpers/accessory';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
5
|
+
type ZoneAliases = {
|
|
6
|
+
stay?: number[];
|
|
7
|
+
night?: number[];
|
|
8
|
+
};
|
|
9
|
+
type SecuritySystemSettings = {
|
|
10
|
+
aliases?: ZoneAliases;
|
|
11
|
+
sensors?: boolean;
|
|
12
|
+
pin?: string;
|
|
13
|
+
};
|
|
14
|
+
type SecuritySystemContext = TydomAccessoryContext<SecuritySystemSettings>;
|
|
15
|
+
export declare const setupSecuritySystem: (accessory: PlatformAccessory<SecuritySystemContext>, controller: TydomController) => Promise<void>;
|
|
16
|
+
export declare const updateSecuritySystem: (accessory: PlatformAccessory<SecuritySystemContext>, controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
17
|
+
export {};
|
|
@@ -52,7 +52,7 @@ const setupSecuritySystem = async (accessory, controller) => {
|
|
|
52
52
|
const { deviceId, endpointId, settings } = context;
|
|
53
53
|
(0, accessory_1.setupAccessoryInformationService)(accessory, controller);
|
|
54
54
|
(0, accessory_1.setupAccessoryIdentifyHandler)(accessory, controller);
|
|
55
|
-
const aliases =
|
|
55
|
+
const { aliases = {}, pin: settingsPin } = settings;
|
|
56
56
|
// Create separate dedicated sensor extra accessory;
|
|
57
57
|
if (settings.sensors !== false) {
|
|
58
58
|
const { accessoryId } = context;
|
|
@@ -68,7 +68,7 @@ const setupSecuritySystem = async (accessory, controller) => {
|
|
|
68
68
|
const labelResults = await client.command(`/devices/${deviceId}/endpoints/${endpointId}/cdata?name=label`);
|
|
69
69
|
const { zones } = labelResults[0];
|
|
70
70
|
// Pin code check
|
|
71
|
-
const pin = env_1.HOMEBRIDGE_TYDOM_PIN ? (0, utils_1.decode)(env_1.HOMEBRIDGE_TYDOM_PIN) :
|
|
71
|
+
const pin = env_1.HOMEBRIDGE_TYDOM_PIN ? (0, utils_1.decode)(env_1.HOMEBRIDGE_TYDOM_PIN) : settingsPin;
|
|
72
72
|
if (!pin) {
|
|
73
73
|
controller.log.warn(`Missing pin for device securitySystem, add either {"settings": {"${deviceId}": {"pin": "123456"}}} or HOMEBRIDGE_TYDOM_PIN env var (base64 encoded)`);
|
|
74
74
|
}
|
|
@@ -258,7 +258,7 @@ exports.setupSecuritySystem = setupSecuritySystem;
|
|
|
258
258
|
const updateSecuritySystem = (accessory, controller, updates, type) => {
|
|
259
259
|
// Relay to separate dedicated sensor extra accessory;
|
|
260
260
|
const { deviceId, endpointId, accessoryId, settings } = accessory.context;
|
|
261
|
-
const aliases =
|
|
261
|
+
const { aliases = {} } = settings;
|
|
262
262
|
const { SecuritySystemCurrentState, ContactSensorState, On } = hap_1.Characteristic;
|
|
263
263
|
if (settings.sensors !== false) {
|
|
264
264
|
const extraUpdateContext = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
3
|
import { TydomAccessoryUpdateType } from '../helpers/accessory';
|
|
4
|
-
|
|
5
|
-
export declare const
|
|
4
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
5
|
+
export declare const setupSecuritySystemSensors: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => Promise<void>;
|
|
6
|
+
export declare const updateSecuritySystemSensors: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PlatformAccessory, Service } from 'homebridge';
|
|
2
2
|
import TydomController from '../../controller';
|
|
3
3
|
import { ServiceClass } from '../../helpers/accessory';
|
|
4
|
-
|
|
5
|
-
export declare const
|
|
4
|
+
import type { TydomAccessoryContext } from '../../typings/tydom';
|
|
5
|
+
export declare const addAccessorySwitchableService: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController, serviceClass: ServiceClass) => Service;
|
|
6
|
+
export declare const updateAccessorySwitchableService: (accessory: PlatformAccessory<TydomAccessoryContext>, _controller: TydomController, updates: Record<string, unknown>[], ServiceClass: ServiceClass) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
3
|
+
import { TydomAccessoryContext } from '../typings';
|
|
4
|
+
export declare const setupSwitch: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateSwitch: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.updateSwitch = exports.setupSwitch = void 0;
|
|
4
4
|
const hap_1 = require("../config/hap");
|
|
5
|
-
const
|
|
5
|
+
const helpers_1 = require("../helpers");
|
|
6
6
|
const switchableService_1 = require("./services/switchableService");
|
|
7
7
|
const setupSwitch = (accessory, controller) => {
|
|
8
|
-
(0,
|
|
9
|
-
(0,
|
|
8
|
+
(0, helpers_1.setupAccessoryInformationService)(accessory, controller);
|
|
9
|
+
(0, helpers_1.setupAccessoryIdentifyHandler)(accessory, controller);
|
|
10
10
|
// Add the actual accessory Service
|
|
11
11
|
(0, switchableService_1.addAccessorySwitchableService)(accessory, controller, hap_1.Service.Switch);
|
|
12
12
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
3
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
4
|
+
export declare const setupTemperatureSensor: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateTemperatureSensor: (accessory: PlatformAccessory<TydomAccessoryContext>, _controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
3
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
4
|
+
export declare const setupThermostat: (accessory: PlatformAccessory<TydomAccessoryContext>, controller: TydomController) => void;
|
|
5
|
+
export declare const updateThermostat: (accessory: PlatformAccessory<TydomAccessoryContext>, _controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import TydomController from '../controller';
|
|
3
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
4
|
+
type TriggerSwitchSettings = {
|
|
5
|
+
delay?: number;
|
|
6
|
+
};
|
|
7
|
+
type TriggerSwitchContext = TydomAccessoryContext<TriggerSwitchSettings>;
|
|
8
|
+
export declare const setupTriggerSwitch: (accessory: PlatformAccessory<TriggerSwitchContext>, controller: TydomController) => void;
|
|
9
|
+
export declare const updateTriggerSwitch: (accessory: PlatformAccessory<TriggerSwitchContext>, controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
10
|
+
export {};
|
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.updateTriggerSwitch = exports.setupTriggerSwitch = void 0;
|
|
4
4
|
const hap_1 = require("../config/hap");
|
|
5
5
|
const accessory_1 = require("../helpers/accessory");
|
|
6
6
|
const debug_1 = require("../utils/debug");
|
|
7
|
-
const
|
|
7
|
+
const TRIGGER_SWITCH_DEFAULT_DELAY = 1000;
|
|
8
|
+
const setupTriggerSwitch = (accessory, controller) => {
|
|
8
9
|
const { context } = accessory;
|
|
9
10
|
const { client } = controller;
|
|
10
|
-
const { deviceId, endpointId } = context;
|
|
11
|
+
const { deviceId, endpointId, settings } = context;
|
|
12
|
+
const { delay = TRIGGER_SWITCH_DEFAULT_DELAY } = settings;
|
|
11
13
|
(0, accessory_1.setupAccessoryInformationService)(accessory, controller);
|
|
12
14
|
(0, accessory_1.setupAccessoryIdentifyHandler)(accessory, controller);
|
|
13
15
|
// Add the actual accessory Service
|
|
14
16
|
const service = (0, accessory_1.addAccessoryService)(accessory, hap_1.Service.Switch, `${accessory.displayName}`, true);
|
|
15
|
-
// State
|
|
16
|
-
// const state = {
|
|
17
|
-
// isOn: false
|
|
18
|
-
// };
|
|
19
17
|
service
|
|
20
18
|
.getCharacteristic(hap_1.Characteristic.On)
|
|
21
|
-
// .on(CharacteristicEventTypes.GET, async (callback: NodeCallback<CharacteristicValue>) => {
|
|
22
|
-
// callback(null, state.isOn);
|
|
23
|
-
// })
|
|
24
19
|
.on("set" /* CharacteristicEventTypes.SET */, async (value, callback) => {
|
|
25
20
|
(0, debug_1.debugSet)(hap_1.Characteristic.On, service, value);
|
|
26
21
|
if (!value) {
|
|
@@ -38,7 +33,7 @@ const setupBasicGarageDoorOpener = (accessory, controller) => {
|
|
|
38
33
|
callback();
|
|
39
34
|
setTimeout(() => {
|
|
40
35
|
service.updateCharacteristic(hap_1.Characteristic.On, false);
|
|
41
|
-
},
|
|
36
|
+
}, delay);
|
|
42
37
|
}
|
|
43
38
|
catch (err) {
|
|
44
39
|
callback(err);
|
|
@@ -46,4 +41,8 @@ const setupBasicGarageDoorOpener = (accessory, controller) => {
|
|
|
46
41
|
})
|
|
47
42
|
.updateValue(false);
|
|
48
43
|
};
|
|
49
|
-
exports.
|
|
44
|
+
exports.setupTriggerSwitch = setupTriggerSwitch;
|
|
45
|
+
const updateTriggerSwitch = (accessory, controller, updates) => {
|
|
46
|
+
// no-op
|
|
47
|
+
};
|
|
48
|
+
exports.updateTriggerSwitch = updateTriggerSwitch;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { PlatformAccessory } from 'homebridge';
|
|
2
2
|
import TydomController from '../controller';
|
|
3
3
|
import { TydomAccessoryUpdateType } from '../helpers/accessory';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import type { TydomAccessoryContext } from '../typings/tydom';
|
|
5
|
+
type WindowCoveringSettings = {
|
|
6
|
+
invertDirection?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type WindowCoveringState = {
|
|
9
|
+
latestPosition: number;
|
|
10
|
+
pendingUpdatedValues: number[];
|
|
11
|
+
lastUpdatedAt: number;
|
|
12
|
+
};
|
|
13
|
+
type WindowCoveringContext = TydomAccessoryContext<WindowCoveringSettings, WindowCoveringState>;
|
|
14
|
+
export declare const setupWindowCovering: (accessory: PlatformAccessory<WindowCoveringContext>, controller: TydomController) => void;
|
|
15
|
+
export declare const updateWindowCovering: (accessory: PlatformAccessory<WindowCoveringContext>, _controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
16
|
+
export {};
|
package/lib/controller.js
CHANGED
|
@@ -110,7 +110,7 @@ class TydomController extends events_1.EventEmitter {
|
|
|
110
110
|
}
|
|
111
111
|
const category = categoryFromSettings || (0, tydom_1.resolveEndpointCategory)({ firstUsage, metadata });
|
|
112
112
|
if (!category) {
|
|
113
|
-
this.log.warn(`Unsupported firstUsage="${firstUsage}" for endpoint with
|
|
113
|
+
this.log.warn(`Unsupported firstUsage="${firstUsage}" for endpoint with deviceId="${deviceId}"`);
|
|
114
114
|
(0, utils_1.debug)({ endpoint });
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
@@ -7,12 +7,24 @@ export declare const getAccessoryService: (accessory: PlatformAccessory, Service
|
|
|
7
7
|
export declare const getAccessoryServiceWithSubtype: (accessory: PlatformAccessory, ServiceClass: ServiceClass, subtype: string) => Service;
|
|
8
8
|
export declare const addAccessoryService: (accessory: PlatformAccessory, service: ServiceClass, name: string, removeExisting?: boolean) => Service;
|
|
9
9
|
export declare const addAccessoryServiceWithSubtype: (accessory: PlatformAccessory, service: ServiceClass, name: string, subtype: string, removeExisting?: boolean) => Service;
|
|
10
|
-
type TydomAccessorySetup = (accessory: PlatformAccessory
|
|
11
|
-
export declare const getTydomAccessorySetup:
|
|
10
|
+
type TydomAccessorySetup<T extends TydomAccessoryContext> = (accessory: PlatformAccessory<T>, controller: TydomController) => void | Promise<void>;
|
|
11
|
+
export declare const getTydomAccessorySetup: <T extends TydomAccessoryContext<any, any> = TydomAccessoryContext<{
|
|
12
|
+
[x: string]: unknown;
|
|
13
|
+
}, {
|
|
14
|
+
[x: string]: unknown;
|
|
15
|
+
}>>(accessory: PlatformAccessory<T>, context: T) => TydomAccessorySetup<T>;
|
|
12
16
|
export type TydomAccessoryUpdateType = 'data' | 'cdata';
|
|
13
|
-
type TydomAccessoryUpdate = (accessory: PlatformAccessory
|
|
14
|
-
export declare const getTydomAccessoryDataUpdate:
|
|
17
|
+
type TydomAccessoryUpdate<T extends TydomAccessoryContext> = (accessory: PlatformAccessory<T>, controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void | Promise<void>;
|
|
18
|
+
export declare const getTydomAccessoryDataUpdate: <T extends TydomAccessoryContext<any, any> = TydomAccessoryContext<{
|
|
19
|
+
[x: string]: unknown;
|
|
20
|
+
}, {
|
|
21
|
+
[x: string]: unknown;
|
|
22
|
+
}>>(accessory: PlatformAccessory<T>, context: T) => TydomAccessoryUpdate<T>;
|
|
15
23
|
export declare const setupAccessoryInformationService: (accessory: PlatformAccessory, _controller: TydomController) => void;
|
|
16
24
|
export declare const setupAccessoryIdentifyHandler: (accessory: PlatformAccessory, _controller: TydomController) => void;
|
|
17
|
-
export declare const assignTydomContext: (prev: PlatformAccessory['context'], next: TydomAccessoryContext) => prev is TydomAccessoryContext<
|
|
25
|
+
export declare const assignTydomContext: (prev: PlatformAccessory['context'], next: TydomAccessoryContext) => prev is TydomAccessoryContext<{
|
|
26
|
+
[x: string]: unknown;
|
|
27
|
+
}, {
|
|
28
|
+
[x: string]: unknown;
|
|
29
|
+
}>;
|
|
18
30
|
export {};
|
package/lib/helpers/accessory.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assignTydomContext = exports.setupAccessoryIdentifyHandler = exports.setupAccessoryInformationService = exports.getTydomAccessoryDataUpdate = exports.getTydomAccessorySetup = exports.addAccessoryServiceWithSubtype = exports.addAccessoryService = exports.getAccessoryServiceWithSubtype = exports.getAccessoryService = exports.SECURITY_SYSTEM_SENSORS = void 0;
|
|
4
|
+
const switch_1 = require("../accessories/switch");
|
|
5
|
+
const triggerSwitch_1 = require("../accessories/triggerSwitch");
|
|
4
6
|
const contactSensor_1 = require("../accessories/contactSensor");
|
|
5
7
|
const fan_1 = require("../accessories/fan");
|
|
6
8
|
const garageDoorOpener_1 = require("../accessories/garageDoorOpener");
|
|
7
9
|
const lightbulb_1 = require("../accessories/lightbulb");
|
|
10
|
+
const outlet_1 = require("../accessories/outlet");
|
|
8
11
|
const securitySystem_1 = require("../accessories/securitySystem");
|
|
9
12
|
const securitySystemSensors_1 = require("../accessories/securitySystemSensors");
|
|
10
13
|
const temperatureSensor_1 = require("../accessories/temperatureSensor");
|
|
11
14
|
const thermostat_1 = require("../accessories/thermostat");
|
|
12
15
|
const windowCovering_1 = require("../accessories/windowCovering");
|
|
13
|
-
const utils_1 = require("../utils");
|
|
14
16
|
const hap_1 = require("../config/hap");
|
|
15
|
-
const
|
|
17
|
+
const utils_1 = require("../utils");
|
|
16
18
|
exports.SECURITY_SYSTEM_SENSORS = parseInt(`${11 /* Categories.SECURITY_SYSTEM */}0`);
|
|
17
19
|
const getAccessoryService = (accessory, ServiceClass) => {
|
|
18
20
|
const service = accessory.getService(ServiceClass);
|
|
@@ -48,7 +50,8 @@ const addAccessoryServiceWithSubtype = (accessory, service, name, subtype, remov
|
|
|
48
50
|
return accessory.addService(service, name, subtype);
|
|
49
51
|
};
|
|
50
52
|
exports.addAccessoryServiceWithSubtype = addAccessoryServiceWithSubtype;
|
|
51
|
-
const getTydomAccessorySetup = (accessory) => {
|
|
53
|
+
const getTydomAccessorySetup = (accessory, context) => {
|
|
54
|
+
var _a;
|
|
52
55
|
const { category } = accessory;
|
|
53
56
|
switch (category) {
|
|
54
57
|
case 5 /* Categories.LIGHTBULB */:
|
|
@@ -61,6 +64,8 @@ const getTydomAccessorySetup = (accessory) => {
|
|
|
61
64
|
return fan_1.setupFan;
|
|
62
65
|
case 4 /* Categories.GARAGE_DOOR_OPENER */:
|
|
63
66
|
return garageDoorOpener_1.setupGarageDoorOpener;
|
|
67
|
+
case 8 /* Categories.SWITCH */:
|
|
68
|
+
return ((_a = context.settings) === null || _a === void 0 ? void 0 : _a.trigger) ? switch_1.setupSwitch : triggerSwitch_1.setupTriggerSwitch;
|
|
64
69
|
case 14 /* Categories.WINDOW_COVERING */:
|
|
65
70
|
return windowCovering_1.setupWindowCovering;
|
|
66
71
|
case 11 /* Categories.SECURITY_SYSTEM */:
|
|
@@ -77,7 +82,8 @@ const getTydomAccessorySetup = (accessory) => {
|
|
|
77
82
|
}
|
|
78
83
|
};
|
|
79
84
|
exports.getTydomAccessorySetup = getTydomAccessorySetup;
|
|
80
|
-
const getTydomAccessoryDataUpdate = (accessory) => {
|
|
85
|
+
const getTydomAccessoryDataUpdate = (accessory, context) => {
|
|
86
|
+
var _a;
|
|
81
87
|
const { category } = accessory;
|
|
82
88
|
switch (category) {
|
|
83
89
|
case 5 /* Categories.LIGHTBULB */:
|
|
@@ -90,6 +96,8 @@ const getTydomAccessoryDataUpdate = (accessory) => {
|
|
|
90
96
|
return fan_1.updateFan;
|
|
91
97
|
case 4 /* Categories.GARAGE_DOOR_OPENER */:
|
|
92
98
|
return garageDoorOpener_1.updateGarageDoorOpener;
|
|
99
|
+
case 8 /* Categories.SWITCH */:
|
|
100
|
+
return ((_a = context.settings) === null || _a === void 0 ? void 0 : _a.trigger) ? switch_1.updateSwitch : triggerSwitch_1.updateTriggerSwitch;
|
|
93
101
|
case 14 /* Categories.WINDOW_COVERING */:
|
|
94
102
|
return windowCovering_1.updateWindowCovering;
|
|
95
103
|
case 11 /* Categories.SECURITY_SYSTEM */:
|
package/lib/platform.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type TydomPlatformConfig = PlatformConfig & {
|
|
|
21
21
|
};
|
|
22
22
|
export default class TydomPlatform implements DynamicPlatformPlugin {
|
|
23
23
|
cleanupAccessoriesIds: Set<string>;
|
|
24
|
-
accessories: Map<string, PlatformAccessory
|
|
24
|
+
accessories: Map<string, PlatformAccessory<TydomAccessoryContext>>;
|
|
25
25
|
controller?: TydomController;
|
|
26
26
|
api: Homebridge;
|
|
27
27
|
config: TydomPlatformConfig;
|
|
@@ -32,7 +32,7 @@ export default class TydomPlatform implements DynamicPlatformPlugin {
|
|
|
32
32
|
handleControllerDevice(context: ControllerDevicePayload): Promise<void>;
|
|
33
33
|
handleControllerDataUpdate({ type, updates, context }: ControllerUpdatePayload): void;
|
|
34
34
|
handleControllerNotification({ level, message }: ControllerNotificationPayload): void;
|
|
35
|
-
createAccessory(name: string, id: string, category: Categories, context: TydomAccessoryContext): Promise<PlatformAccessory
|
|
36
|
-
updateAccessory(accessory: PlatformAccessory
|
|
37
|
-
configureAccessory(accessory: PlatformAccessory): void;
|
|
35
|
+
createAccessory(name: string, id: string, category: Categories, context: TydomAccessoryContext): Promise<PlatformAccessory<TydomAccessoryContext>>;
|
|
36
|
+
updateAccessory(accessory: PlatformAccessory<TydomAccessoryContext>, context: TydomAccessoryContext): Promise<void>;
|
|
37
|
+
configureAccessory(accessory: PlatformAccessory<TydomAccessoryContext>): void;
|
|
38
38
|
}
|
package/lib/platform.js
CHANGED
|
@@ -70,7 +70,7 @@ class TydomPlatform {
|
|
|
70
70
|
}
|
|
71
71
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
72
72
|
const accessory = this.accessories.get(id);
|
|
73
|
-
const tydomAccessoryUpdate = (0, accessory_1.getTydomAccessoryDataUpdate)(accessory);
|
|
73
|
+
const tydomAccessoryUpdate = (0, accessory_1.getTydomAccessoryDataUpdate)(accessory, context);
|
|
74
74
|
if (tydomAccessoryUpdate) {
|
|
75
75
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
76
76
|
tydomAccessoryUpdate(accessory, this.controller, updates, type);
|
|
@@ -94,7 +94,7 @@ class TydomPlatform {
|
|
|
94
94
|
const { platformAccessory: PlatformAccessory } = this.api;
|
|
95
95
|
const { group } = context;
|
|
96
96
|
const accessoryName = category === 13 /* Categories.WINDOW */ && group ? group.name || name : name;
|
|
97
|
-
this.log.info(`Creating accessory named="${accessoryName}" with id="${id}"`);
|
|
97
|
+
this.log.info(`Creating accessory named="${accessoryName}" with id="${id}", deviceId="${context.deviceId}"`);
|
|
98
98
|
const accessory = new PlatformAccessory(accessoryName, id, category);
|
|
99
99
|
Object.assign(accessory.context, context);
|
|
100
100
|
await this.updateAccessory(accessory, context);
|
|
@@ -102,9 +102,9 @@ class TydomPlatform {
|
|
|
102
102
|
}
|
|
103
103
|
async updateAccessory(accessory, context) {
|
|
104
104
|
const { displayName: name, UUID: id } = accessory;
|
|
105
|
-
this.log.info(`Updating accessory named="${name}" with id="${id}"`);
|
|
105
|
+
this.log.info(`Updating accessory named="${name}" with id="${id}", deviceId="${context.deviceId}"`);
|
|
106
106
|
Object.assign(accessory.context, context);
|
|
107
|
-
const tydomAccessorySetup = (0, accessory_1.getTydomAccessorySetup)(accessory);
|
|
107
|
+
const tydomAccessorySetup = (0, accessory_1.getTydomAccessorySetup)(accessory, context);
|
|
108
108
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
109
109
|
await tydomAccessorySetup(accessory, this.controller);
|
|
110
110
|
this.api.updatePlatformAccessories([accessory]);
|
package/lib/typings/tydom.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Categories } from '../config/hap';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
type UnknownObject = Record<string, unknown>;
|
|
3
|
+
export type TydomAccessoryContext<T extends UnknownObject = UnknownObject, U extends UnknownObject = UnknownObject> = {
|
|
4
|
+
accessoryId: string;
|
|
4
5
|
category: Categories;
|
|
5
|
-
metadata: TydomMetaElement[];
|
|
6
|
-
settings: Record<string, unknown>;
|
|
7
6
|
deviceId: number;
|
|
8
7
|
endpointId: number;
|
|
9
|
-
|
|
8
|
+
group?: TydomConfigGroup;
|
|
10
9
|
manufacturer?: string;
|
|
11
|
-
|
|
10
|
+
metadata: TydomMetaElement[];
|
|
12
11
|
model?: string;
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
name: string;
|
|
13
|
+
serialNumber?: string;
|
|
14
|
+
settings: T;
|
|
15
|
+
state: U;
|
|
15
16
|
};
|
|
16
17
|
export type TydomAccessoryUpdateContext = Pick<TydomAccessoryContext, 'category' | 'deviceId' | 'endpointId' | 'accessoryId'>;
|
|
17
18
|
export type TydomConfigEndpoint = {
|
|
@@ -184,3 +185,4 @@ export type SecuritySystemAlarmEvent = {
|
|
|
184
185
|
}>;
|
|
185
186
|
product?: SecuritySystemProduct;
|
|
186
187
|
};
|
|
188
|
+
export {};
|
package/lib/utils/basic.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const stringIncludes: (array: unknown[], value: string | number) => boolean;
|
|
2
2
|
export declare const sameArrays: (source: unknown[], array: unknown[]) => boolean;
|
|
3
3
|
export declare const asNumber: (maybeNumber: unknown) => number;
|
|
4
|
-
export declare const waitFor: (ms: number) => Promise<void>;
|
|
4
|
+
export declare const waitFor: (key: string, ms: number) => Promise<void>;
|
package/lib/utils/basic.js
CHANGED
|
@@ -8,5 +8,18 @@ const sameArrays = (source, array) => source.length === array.length && (0, loda
|
|
|
8
8
|
exports.sameArrays = sameArrays;
|
|
9
9
|
const asNumber = (maybeNumber) => parseInt(`${maybeNumber}`, 10);
|
|
10
10
|
exports.asNumber = asNumber;
|
|
11
|
-
const
|
|
11
|
+
const timeouts = new Map();
|
|
12
|
+
const waitFor = async (key, ms) => {
|
|
13
|
+
if (timeouts.has(key)) {
|
|
14
|
+
const { timeout, reject } = timeouts.get(key);
|
|
15
|
+
clearTimeout(timeout);
|
|
16
|
+
timeouts.delete(key);
|
|
17
|
+
reject();
|
|
18
|
+
}
|
|
19
|
+
await new Promise((resolve, reject) => {
|
|
20
|
+
const timeout = setTimeout(resolve, ms);
|
|
21
|
+
timeouts.set(key, { timeout, reject });
|
|
22
|
+
});
|
|
23
|
+
timeouts.delete(key);
|
|
24
|
+
};
|
|
12
25
|
exports.waitFor = waitFor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-tydom",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.5",
|
|
4
4
|
"description": "Homebridge plugin to manage Tydom devices by Delta Dore",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"start:node": "NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=src/ ts-node .",
|
|
23
23
|
"start:watch": "nodemon --ext \"ts,tsx\" --watch \"lib/\" --exec \"yarn start\"",
|
|
24
24
|
"start:prod": "yarn spec:watch",
|
|
25
|
-
"build": "tsc --build",
|
|
25
|
+
"build": "tsc --build && tsc-alias --project tsconfig.json",
|
|
26
26
|
"clean": "rm -rf .homebridge/persist/* .homebridge/accessories/*",
|
|
27
27
|
"lint": "eslint src/",
|
|
28
28
|
"prettycheck": "prettier --check src/",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"nock": "^13.2.9",
|
|
57
57
|
"prettier": "^2.8.0",
|
|
58
58
|
"ts-node": "^10.9.1",
|
|
59
|
+
"tsc-alias": "^1.7.1",
|
|
59
60
|
"typescript": "^4.9.3"
|
|
60
61
|
}
|
|
61
62
|
}
|
package/lib/utils/accessory.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { PlatformAccessory, Service, WithUUID } from 'homebridge';
|
|
2
|
-
import TydomController from '../controller';
|
|
3
|
-
import { TydomAccessoryContext } from '../typings/tydom';
|
|
4
|
-
export declare const SECURITY_SYSTEM_SENSORS: number;
|
|
5
|
-
export declare const asNumber: (maybeNumber: unknown) => number;
|
|
6
|
-
export declare type ServiceClass = WithUUID<typeof Service>;
|
|
7
|
-
export declare const getAccessoryService: (accessory: PlatformAccessory, ServiceClass: ServiceClass) => Service;
|
|
8
|
-
export declare const getAccessoryServiceWithSubtype: (accessory: PlatformAccessory, ServiceClass: ServiceClass, subtype: string) => Service;
|
|
9
|
-
export declare const addAccessoryService: (accessory: PlatformAccessory, service: ServiceClass, name: string, removeExisting?: boolean) => Service;
|
|
10
|
-
export declare const addAccessoryServiceWithSubtype: (accessory: PlatformAccessory, service: ServiceClass, name: string, subtype: string, removeExisting?: boolean) => Service;
|
|
11
|
-
declare type TydomAccessorySetup = (accessory: PlatformAccessory, controller: TydomController) => void | Promise<void>;
|
|
12
|
-
export declare const getTydomAccessorySetup: (accessory: PlatformAccessory) => TydomAccessorySetup;
|
|
13
|
-
export declare type TydomAccessoryUpdateType = 'data' | 'cdata';
|
|
14
|
-
declare type TydomAccessoryUpdate = (accessory: PlatformAccessory, controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void | Promise<void>;
|
|
15
|
-
export declare const getTydomAccessoryDataUpdate: (accessory: PlatformAccessory) => TydomAccessoryUpdate;
|
|
16
|
-
export declare const setupAccessoryInformationService: (accessory: PlatformAccessory, _controller: TydomController) => void;
|
|
17
|
-
export declare const setupAccessoryIdentifyHandler: (accessory: PlatformAccessory, _controller: TydomController) => void;
|
|
18
|
-
export declare const assignTydomContext: (prev: PlatformAccessory['context'], next: TydomAccessoryContext) => prev is TydomAccessoryContext<Record<string, any>>;
|
|
19
|
-
export {};
|
package/lib/utils/accessory.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
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.assignTydomContext = exports.setupAccessoryIdentifyHandler = exports.setupAccessoryInformationService = exports.getTydomAccessoryDataUpdate = exports.getTydomAccessorySetup = exports.addAccessoryServiceWithSubtype = exports.addAccessoryService = exports.getAccessoryServiceWithSubtype = exports.getAccessoryService = exports.asNumber = exports.SECURITY_SYSTEM_SENSORS = void 0;
|
|
7
|
-
const contactSensor_1 = require("../accessories/contactSensor");
|
|
8
|
-
const fan_1 = require("../accessories/fan");
|
|
9
|
-
const garageDoorOpener_1 = require("../accessories/garageDoorOpener");
|
|
10
|
-
const lightbulb_1 = require("../accessories/lightbulb");
|
|
11
|
-
const securitySystem_1 = require("../accessories/securitySystem");
|
|
12
|
-
const securitySystemSensors_1 = require("../accessories/securitySystemSensors");
|
|
13
|
-
const temperatureSensor_1 = require("../accessories/temperatureSensor");
|
|
14
|
-
const thermostat_1 = require("../accessories/thermostat");
|
|
15
|
-
const windowCovering_1 = require("../accessories/windowCovering");
|
|
16
|
-
const assert_1 = __importDefault(require("../utils/assert"));
|
|
17
|
-
const debug_1 = __importDefault(require("../utils/debug"));
|
|
18
|
-
const hap_1 = require("../utils/hap");
|
|
19
|
-
exports.SECURITY_SYSTEM_SENSORS = parseInt(`${11 /* SECURITY_SYSTEM */}0`);
|
|
20
|
-
const asNumber = (maybeNumber) => parseInt(`${maybeNumber}`, 10);
|
|
21
|
-
exports.asNumber = asNumber;
|
|
22
|
-
const getAccessoryService = (accessory, ServiceClass) => {
|
|
23
|
-
const service = accessory.getService(ServiceClass);
|
|
24
|
-
assert_1.default(service, `Unexpected missing service "${ServiceClass.name}" in accessory`);
|
|
25
|
-
return service;
|
|
26
|
-
};
|
|
27
|
-
exports.getAccessoryService = getAccessoryService;
|
|
28
|
-
const getAccessoryServiceWithSubtype = (accessory, ServiceClass, subtype) => {
|
|
29
|
-
const service = accessory.getServiceByUUIDAndSubType(ServiceClass, subtype);
|
|
30
|
-
assert_1.default(service, `Unexpected missing service "${ServiceClass.name}" with subtype="${subtype}" in accessory`);
|
|
31
|
-
return service;
|
|
32
|
-
};
|
|
33
|
-
exports.getAccessoryServiceWithSubtype = getAccessoryServiceWithSubtype;
|
|
34
|
-
const addAccessoryService = (accessory, service, name, removeExisting = false) => {
|
|
35
|
-
const existingService = accessory.getService(service);
|
|
36
|
-
if (existingService) {
|
|
37
|
-
if (!removeExisting) {
|
|
38
|
-
return existingService;
|
|
39
|
-
}
|
|
40
|
-
accessory.removeService(existingService);
|
|
41
|
-
}
|
|
42
|
-
return accessory.addService(service, name);
|
|
43
|
-
};
|
|
44
|
-
exports.addAccessoryService = addAccessoryService;
|
|
45
|
-
const addAccessoryServiceWithSubtype = (accessory, service, name, subtype, removeExisting = false) => {
|
|
46
|
-
const existingService = accessory.getServiceById(service, subtype);
|
|
47
|
-
if (existingService) {
|
|
48
|
-
if (!removeExisting) {
|
|
49
|
-
return existingService;
|
|
50
|
-
}
|
|
51
|
-
accessory.removeService(existingService);
|
|
52
|
-
}
|
|
53
|
-
return accessory.addService(service, name, subtype);
|
|
54
|
-
};
|
|
55
|
-
exports.addAccessoryServiceWithSubtype = addAccessoryServiceWithSubtype;
|
|
56
|
-
const getTydomAccessorySetup = (accessory) => {
|
|
57
|
-
const { category } = accessory;
|
|
58
|
-
switch (category) {
|
|
59
|
-
case 5 /* LIGHTBULB */:
|
|
60
|
-
return lightbulb_1.setupLightbulb;
|
|
61
|
-
case 9 /* THERMOSTAT */:
|
|
62
|
-
return thermostat_1.setupThermostat;
|
|
63
|
-
case 3 /* FAN */:
|
|
64
|
-
return fan_1.setupFan;
|
|
65
|
-
case 4 /* GARAGE_DOOR_OPENER */:
|
|
66
|
-
return garageDoorOpener_1.setupGarageDoorOpener;
|
|
67
|
-
case 14 /* WINDOW_COVERING */:
|
|
68
|
-
return windowCovering_1.setupWindowCovering;
|
|
69
|
-
case 11 /* SECURITY_SYSTEM */:
|
|
70
|
-
return securitySystem_1.setupSecuritySystem;
|
|
71
|
-
case 10 /* SENSOR */:
|
|
72
|
-
return temperatureSensor_1.setupTemperatureSensor;
|
|
73
|
-
case 13 /* WINDOW */:
|
|
74
|
-
case 12 /* DOOR */:
|
|
75
|
-
return contactSensor_1.setupContactSensor;
|
|
76
|
-
case exports.SECURITY_SYSTEM_SENSORS:
|
|
77
|
-
return securitySystemSensors_1.setupSecuritySystemSensors;
|
|
78
|
-
default:
|
|
79
|
-
throw new Error(`Unsupported accessory category=${category}`);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
exports.getTydomAccessorySetup = getTydomAccessorySetup;
|
|
83
|
-
const getTydomAccessoryDataUpdate = (accessory) => {
|
|
84
|
-
const { category } = accessory;
|
|
85
|
-
switch (category) {
|
|
86
|
-
case 5 /* LIGHTBULB */:
|
|
87
|
-
return lightbulb_1.updateLightbulb;
|
|
88
|
-
case 9 /* THERMOSTAT */:
|
|
89
|
-
return thermostat_1.updateThermostat;
|
|
90
|
-
case 3 /* FAN */:
|
|
91
|
-
return fan_1.updateFan;
|
|
92
|
-
case 4 /* GARAGE_DOOR_OPENER */:
|
|
93
|
-
return () => {
|
|
94
|
-
// no-op
|
|
95
|
-
};
|
|
96
|
-
case 14 /* WINDOW_COVERING */:
|
|
97
|
-
return windowCovering_1.updateWindowCovering;
|
|
98
|
-
case 11 /* SECURITY_SYSTEM */:
|
|
99
|
-
return securitySystem_1.updateSecuritySystem;
|
|
100
|
-
case 10 /* SENSOR */:
|
|
101
|
-
return temperatureSensor_1.updateTemperatureSensor;
|
|
102
|
-
case 13 /* WINDOW */:
|
|
103
|
-
case 12 /* DOOR */:
|
|
104
|
-
return contactSensor_1.updateContactSensor;
|
|
105
|
-
case exports.SECURITY_SYSTEM_SENSORS:
|
|
106
|
-
return securitySystemSensors_1.updateSecuritySystemSensors;
|
|
107
|
-
default:
|
|
108
|
-
throw new Error(`Unsupported accessory category=${category}`);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
exports.getTydomAccessoryDataUpdate = getTydomAccessoryDataUpdate;
|
|
112
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
113
|
-
const setupAccessoryInformationService = (accessory, _controller) => {
|
|
114
|
-
const { context } = accessory;
|
|
115
|
-
const { manufacturer = 'Delta Dore', serialNumber = 'N/A', model = 'N/A' } = context;
|
|
116
|
-
const informationService = accessory.getService(hap_1.Service.AccessoryInformation);
|
|
117
|
-
assert_1.default(informationService, `Did not found AccessoryInformation service`);
|
|
118
|
-
informationService
|
|
119
|
-
.setCharacteristic(hap_1.Characteristic.Manufacturer, manufacturer)
|
|
120
|
-
.setCharacteristic(hap_1.Characteristic.SerialNumber, serialNumber)
|
|
121
|
-
.setCharacteristic(hap_1.Characteristic.Model, model);
|
|
122
|
-
};
|
|
123
|
-
exports.setupAccessoryInformationService = setupAccessoryInformationService;
|
|
124
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
125
|
-
const setupAccessoryIdentifyHandler = (accessory, _controller) => {
|
|
126
|
-
const { displayName: name, UUID: id } = accessory;
|
|
127
|
-
// listen for the "identify" event for this Accessory
|
|
128
|
-
accessory.on("identify" /* IDENTIFY */, ( /* paired: boolean, callback: VoidCallback */) => {
|
|
129
|
-
// debug({id, type: 'AccessoryEventTypes.IDENTIFY', paired});
|
|
130
|
-
debug_1.default(`New identify request for device named="${name}" with id="${id}"`);
|
|
131
|
-
// callback();
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
exports.setupAccessoryIdentifyHandler = setupAccessoryIdentifyHandler;
|
|
135
|
-
const assignTydomContext = (prev, next) => {
|
|
136
|
-
Object.assign(prev, next);
|
|
137
|
-
return true;
|
|
138
|
-
};
|
|
139
|
-
exports.assignTydomContext = assignTydomContext;
|
package/lib/utils/array.d.ts
DELETED
package/lib/utils/array.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sameArrays = exports.stringIncludes = void 0;
|
|
4
|
-
const lodash_1 = require("lodash");
|
|
5
|
-
const stringIncludes = (array, value) => array.includes(value) || array.includes(`${value}`);
|
|
6
|
-
exports.stringIncludes = stringIncludes;
|
|
7
|
-
const sameArrays = (source, array) => source.length === array.length && lodash_1.xor(source, array).length === 0;
|
|
8
|
-
exports.sameArrays = sameArrays;
|
package/lib/utils/hap.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { API as Homebridge, HAP } from 'homebridge';
|
|
2
|
-
export { AccessoryEventTypes, Categories, CharacteristicEventTypes } from 'homebridge';
|
|
3
|
-
export type { CharacteristicProps, CharacteristicSetCallback, CharacteristicValue, NodeCallback, VoidCallback } from 'homebridge';
|
|
4
|
-
export declare let Characteristic: HAP['Characteristic'];
|
|
5
|
-
export declare let Service: HAP['Service'];
|
|
6
|
-
export declare const defineHAPGlobals: (homebridge: Homebridge) => void;
|
package/lib/utils/hap.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defineHAPGlobals = exports.Service = exports.Characteristic = void 0;
|
|
4
|
-
const defineHAPGlobals = (homebridge) => {
|
|
5
|
-
exports.Characteristic = homebridge.hap.Characteristic;
|
|
6
|
-
exports.Service = homebridge.hap.Service;
|
|
7
|
-
};
|
|
8
|
-
exports.defineHAPGlobals = defineHAPGlobals;
|
package/lib/utils/tydom.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Categories } from '../utils/hap';
|
|
2
|
-
import { TydomConfigEndpoint, TydomEndpointData, TydomMetaElement, TydomMetaResponse, AnyTydomDataValue, TydomGroupsResponse, TydomMetaEndpoint } from '../typings/tydom';
|
|
3
|
-
import TydomClient from 'tydom-client';
|
|
4
|
-
import type { PlatformAccessory } from 'homebridge';
|
|
5
|
-
export declare type GetTydomDeviceDataOptions = {
|
|
6
|
-
deviceId: number;
|
|
7
|
-
endpointId: number;
|
|
8
|
-
accessory?: PlatformAccessory;
|
|
9
|
-
};
|
|
10
|
-
export declare const getTydomDeviceData: <T extends TydomEndpointData = TydomEndpointData>(client: TydomClient, { deviceId, endpointId }: GetTydomDeviceDataOptions) => Promise<T>;
|
|
11
|
-
export declare type RunTydomDeviceCommandOptions = {
|
|
12
|
-
deviceId: number;
|
|
13
|
-
endpointId: number;
|
|
14
|
-
searchParams?: Record<string, string>;
|
|
15
|
-
};
|
|
16
|
-
export declare const runTydomDeviceCommand: <T extends Record<string, unknown> = Record<string, unknown>>(client: TydomClient, name: string, { deviceId, endpointId, searchParams }: RunTydomDeviceCommandOptions) => Promise<T[]>;
|
|
17
|
-
export declare const getTydomDataPropValue: <V extends AnyTydomDataValue = AnyTydomDataValue, T extends TydomEndpointData = TydomEndpointData>(data: T, name: string) => V;
|
|
18
|
-
export declare const getEndpointDetailsFromMeta: ({ id_endpoint: endpointId, id_device: deviceId }: TydomConfigEndpoint, meta: TydomMetaResponse) => TydomMetaEndpoint;
|
|
19
|
-
export declare const getEndpointGroupIdFromGroups: ({ id_endpoint: endpointId, id_device: deviceId }: TydomConfigEndpoint, groups: TydomGroupsResponse) => number | null;
|
|
20
|
-
export declare const getEndpointSignatureFromMetadata: (metadata: TydomMetaElement[]) => string;
|
|
21
|
-
declare type ResolveEndpointCategoryOptions = {
|
|
22
|
-
firstUsage: string;
|
|
23
|
-
metadata: TydomMetaElement[];
|
|
24
|
-
};
|
|
25
|
-
export declare const resolveEndpointCategory: ({ firstUsage, metadata }: ResolveEndpointCategoryOptions) => Categories | null;
|
|
26
|
-
export declare const asyncWait: (ms: number) => Promise<void>;
|
|
27
|
-
export {};
|
package/lib/utils/tydom.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
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.asyncWait = exports.resolveEndpointCategory = exports.getEndpointSignatureFromMetadata = exports.getEndpointGroupIdFromGroups = exports.getEndpointDetailsFromMeta = exports.getTydomDataPropValue = exports.runTydomDeviceCommand = exports.getTydomDeviceData = void 0;
|
|
7
|
-
const lodash_1 = require("lodash");
|
|
8
|
-
const assert_1 = __importDefault(require("../utils/assert"));
|
|
9
|
-
const debug_1 = __importDefault(require("./debug"));
|
|
10
|
-
const hash_1 = require("./hash");
|
|
11
|
-
const url_1 = require("url");
|
|
12
|
-
const chalk_1 = require("./chalk");
|
|
13
|
-
const cacheMap = new Map();
|
|
14
|
-
const DEBOUNCE_TIME = 1 * 1e3;
|
|
15
|
-
const getTydomDeviceData = async (client, { deviceId, endpointId }) => {
|
|
16
|
-
const now = Date.now();
|
|
17
|
-
const uri = `/devices/${deviceId}/endpoints/${endpointId}/data`;
|
|
18
|
-
if (cacheMap.has(uri)) {
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
20
|
-
const { time, promise } = cacheMap.get(uri);
|
|
21
|
-
if (now < time + DEBOUNCE_TIME) {
|
|
22
|
-
return promise;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const promise = client.get(uri).then((res) => {
|
|
26
|
-
if (res.error > 0) {
|
|
27
|
-
debug_1.default(`Received non-zero error=${chalk_1.chalkNumber(res.error)} while querying uri=${chalk_1.chalkString(uri)}`);
|
|
28
|
-
if (res.error > 10) {
|
|
29
|
-
debug_1.default(`Accessory with uri=${chalk_1.chalkString(uri)} seems unreacheable (error=${chalk_1.chalkNumber(res.error)}).`);
|
|
30
|
-
throw new Error('UnreacheableAccessory');
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
debug_1.default(`Accessory with uri=${chalk_1.chalkString(uri)} is reporting unknown issues (error=${chalk_1.chalkNumber(res.error)}).`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return res.data ? res.data : res;
|
|
37
|
-
});
|
|
38
|
-
cacheMap.set(uri, { time: now, promise });
|
|
39
|
-
return promise;
|
|
40
|
-
};
|
|
41
|
-
exports.getTydomDeviceData = getTydomDeviceData;
|
|
42
|
-
const runTydomDeviceCommand = async (client, name, { deviceId, endpointId, searchParams }) => {
|
|
43
|
-
const now = Date.now();
|
|
44
|
-
const uri = `/devices/${deviceId}/endpoints/${endpointId}/cdata?name=${name}${searchParams ? `&${new url_1.URLSearchParams(searchParams)}` : ''}`;
|
|
45
|
-
if (cacheMap.has(uri)) {
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
47
|
-
const { time, promise } = cacheMap.get(uri);
|
|
48
|
-
if (now < time + DEBOUNCE_TIME) {
|
|
49
|
-
return promise;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const promise = client.command(uri);
|
|
53
|
-
cacheMap.set(uri, { time: now, promise });
|
|
54
|
-
return promise;
|
|
55
|
-
};
|
|
56
|
-
exports.runTydomDeviceCommand = runTydomDeviceCommand;
|
|
57
|
-
const getTydomDataPropValue = (data, name) => {
|
|
58
|
-
const item = data.find((prop) => prop.name === name);
|
|
59
|
-
assert_1.default(item, `Missing property with name="${name}" in endpoint data`);
|
|
60
|
-
return item.value;
|
|
61
|
-
};
|
|
62
|
-
exports.getTydomDataPropValue = getTydomDataPropValue;
|
|
63
|
-
const getEndpointDetailsFromMeta = ({ id_endpoint: endpointId, id_device: deviceId }, meta) => {
|
|
64
|
-
const device = lodash_1.find(meta, { id: deviceId });
|
|
65
|
-
assert_1.default(device, `Device with id="${deviceId}" not found in Tydom meta`);
|
|
66
|
-
const details = lodash_1.find(device.endpoints, { id: endpointId });
|
|
67
|
-
assert_1.default(details, `Endpoint with id="${endpointId}" not found in device with id="${deviceId}" meta`);
|
|
68
|
-
return details;
|
|
69
|
-
};
|
|
70
|
-
exports.getEndpointDetailsFromMeta = getEndpointDetailsFromMeta;
|
|
71
|
-
const getEndpointGroupIdFromGroups = ({ id_endpoint: endpointId, id_device: deviceId }, groups) => {
|
|
72
|
-
const group = groups.groups.find(({ devices }) => devices.some(({ id, endpoints }) => id === deviceId && endpoints.some(({ id }) => id === endpointId)));
|
|
73
|
-
return group ? group.id : null;
|
|
74
|
-
};
|
|
75
|
-
exports.getEndpointGroupIdFromGroups = getEndpointGroupIdFromGroups;
|
|
76
|
-
const getEndpointSignatureFromMetadata = (metadata) => metadata
|
|
77
|
-
.map((value) => value.name)
|
|
78
|
-
.sort()
|
|
79
|
-
.join('|');
|
|
80
|
-
exports.getEndpointSignatureFromMetadata = getEndpointSignatureFromMetadata;
|
|
81
|
-
const LEGACY_SUPPORTED_CATEGORIES_MAP = {
|
|
82
|
-
alarm: 11 /* SECURITY_SYSTEM */,
|
|
83
|
-
awning: 14 /* WINDOW_COVERING */,
|
|
84
|
-
belmDoor: 12 /* DOOR */,
|
|
85
|
-
gate: 4 /* GARAGE_DOOR_OPENER */,
|
|
86
|
-
garage_door: 4 /* GARAGE_DOOR_OPENER */,
|
|
87
|
-
hvac: 9 /* THERMOSTAT */,
|
|
88
|
-
light: 5 /* LIGHTBULB */,
|
|
89
|
-
shutter: 14 /* WINDOW_COVERING */,
|
|
90
|
-
window: 13 /* WINDOW */
|
|
91
|
-
};
|
|
92
|
-
const ENDPOINTS_SIGNATURES_CATEGORIES = {
|
|
93
|
-
'alarm:0c6e1d33808fa50a0a921502f80d36430dfaeda5abfed2467f9f2b07821e4842': 11 /* SECURITY_SYSTEM */,
|
|
94
|
-
'alarm:aad768ee0367013a974276117fd5ed4834cc26e4d31acc88d35134731331b0e7': 11 /* SECURITY_SYSTEM */,
|
|
95
|
-
'alarm:6e33f7ee5e62b58f4e888c91a13fd9b9d868f3751cead5ea1252578ba86523a5': 11 /* SECURITY_SYSTEM */,
|
|
96
|
-
'awning:48f43ebab20eba438fa9cc2b6ce44311d3cfb01c5be84bf17599d9c152c348d3': 14 /* WINDOW_COVERING */,
|
|
97
|
-
'belmDoor:fb935867933d89b3058f09384f76fd63f3defb18cfb3172f60fa9f4f237f748b': 12 /* DOOR */,
|
|
98
|
-
'conso:16804a9994bce28275150db329a9c0b931ef7f20608c1a3d2ff248f58569f0d3': 10 /* SENSOR */,
|
|
99
|
-
'gate:83b0912c6fe14622219522922ea0347dcbf86bf9cfd3346a2eca8eac70ca8260': 4 /* GARAGE_DOOR_OPENER */,
|
|
100
|
-
'garage_door:83b0912c6fe14622219522922ea0347dcbf86bf9cfd3346a2eca8eac70ca8260': 4 /* GARAGE_DOOR_OPENER */,
|
|
101
|
-
'hvac:1bab47d1dd7e898b5dc2e9867b14dfb8bc9272c4cb0b5d1221da962d43a6ffb4': 9 /* THERMOSTAT */,
|
|
102
|
-
'light:449e2a60377094cde10224cee91d378fb0ae373ae6ceea0ac2cbc1ed011bffa7': 5 /* LIGHTBULB */,
|
|
103
|
-
'light:fce45085835f4f2790ea3b17d208b5ace34935444d2535e75ba3f0a2ce86de5f': 5 /* LIGHTBULB */,
|
|
104
|
-
'shutter:c3fe8e2afa864e1a7a5c6676b4287a7b2f2a886a466baec3df8a1ec4f898ad6c': 14 /* WINDOW_COVERING */,
|
|
105
|
-
'window:fb935867933d89b3058f09384f76fd63f3defb18cfb3172f60fa9f4f237f748b': 13 /* WINDOW */ // @mgcrea (MDO)
|
|
106
|
-
};
|
|
107
|
-
const resolveEndpointCategory = ({ firstUsage, metadata }) => {
|
|
108
|
-
// Compute device signature
|
|
109
|
-
const metaSignature = exports.getEndpointSignatureFromMetadata(metadata);
|
|
110
|
-
const hash = `${firstUsage}:${hash_1.sha256Sync(metaSignature)}`;
|
|
111
|
-
// dir({metaSignature, hash});
|
|
112
|
-
if (ENDPOINTS_SIGNATURES_CATEGORIES[hash]) {
|
|
113
|
-
return ENDPOINTS_SIGNATURES_CATEGORIES[hash];
|
|
114
|
-
}
|
|
115
|
-
debug_1.default(`Unknown hash=${hash} with firstUsage="${firstUsage}"`);
|
|
116
|
-
// Fallback on legacy resolution
|
|
117
|
-
if (LEGACY_SUPPORTED_CATEGORIES_MAP[firstUsage]) {
|
|
118
|
-
return LEGACY_SUPPORTED_CATEGORIES_MAP[firstUsage];
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
};
|
|
122
|
-
exports.resolveEndpointCategory = resolveEndpointCategory;
|
|
123
|
-
const asyncWait = (ms) => new Promise((resolve) => {
|
|
124
|
-
setTimeout(resolve, ms);
|
|
125
|
-
});
|
|
126
|
-
exports.asyncWait = asyncWait;
|
package/lib/utils/webhook.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare type Webhook = {
|
|
2
|
-
url: string;
|
|
3
|
-
type: string;
|
|
4
|
-
};
|
|
5
|
-
export declare type WebhookPayload = {
|
|
6
|
-
message: string;
|
|
7
|
-
level?: string;
|
|
8
|
-
};
|
|
9
|
-
declare type DiscordPayload = {
|
|
10
|
-
content: string;
|
|
11
|
-
username?: string;
|
|
12
|
-
avatar_url?: string;
|
|
13
|
-
tts?: boolean;
|
|
14
|
-
payload_json?: string;
|
|
15
|
-
allowed_mentions?: boolean;
|
|
16
|
-
};
|
|
17
|
-
export declare const asDiscordPayload: ({ level, message }: WebhookPayload) => DiscordPayload;
|
|
18
|
-
export declare const triggerWebhook: (webhook: Webhook, { message, level }: WebhookPayload) => Promise<void>;
|
|
19
|
-
export {};
|
package/lib/utils/webhook.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.triggerWebhook = exports.asDiscordPayload = void 0;
|
|
4
|
-
const request_1 = require("./request");
|
|
5
|
-
const asDiscordPayload = ({ level, message }) => {
|
|
6
|
-
let prefix = '';
|
|
7
|
-
switch (level) {
|
|
8
|
-
case 'warn':
|
|
9
|
-
prefix = ':warning: ';
|
|
10
|
-
break;
|
|
11
|
-
default:
|
|
12
|
-
prefix = ':question: ';
|
|
13
|
-
break;
|
|
14
|
-
}
|
|
15
|
-
return {
|
|
16
|
-
content: `${prefix}${message}`
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
exports.asDiscordPayload = asDiscordPayload;
|
|
20
|
-
const triggerWebhook = async (webhook, { message, level = 'info' }) => {
|
|
21
|
-
const { url, type } = webhook;
|
|
22
|
-
switch (type) {
|
|
23
|
-
case 'discord':
|
|
24
|
-
const res = await request_1.postJson({ url, json: exports.asDiscordPayload({ message, level }) });
|
|
25
|
-
console.dir({ res });
|
|
26
|
-
break;
|
|
27
|
-
default:
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
exports.triggerWebhook = triggerWebhook;
|