homebridge-tydom 0.23.2 → 0.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accessories/garageDoorOpener.js +74 -19
- package/lib/controller.js +1 -1
- package/lib/platform.js +2 -2
- package/lib/utils/basic.d.ts +1 -1
- package/lib/utils/basic.js +14 -1
- package/package.json +1 -1
|
@@ -10,12 +10,28 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
10
10
|
const { context } = accessory;
|
|
11
11
|
const { client } = controller;
|
|
12
12
|
const { CurrentDoorState, TargetDoorState } = hap_1.Characteristic;
|
|
13
|
-
const GARAGE_DOOR_DELAY =
|
|
13
|
+
const GARAGE_DOOR_DELAY = 20 * 1000;
|
|
14
14
|
const { deviceId, endpointId, state } = context;
|
|
15
15
|
const assignState = (update) => {
|
|
16
16
|
Object.assign(state, update);
|
|
17
17
|
};
|
|
18
|
+
const getDoorStateLabel = (currentDoorState) => {
|
|
19
|
+
switch (currentDoorState) {
|
|
20
|
+
case CurrentDoorState.OPEN:
|
|
21
|
+
return 'OPEN';
|
|
22
|
+
case CurrentDoorState.CLOSED:
|
|
23
|
+
return 'CLOSED';
|
|
24
|
+
case CurrentDoorState.OPENING:
|
|
25
|
+
return 'OPENING';
|
|
26
|
+
case CurrentDoorState.CLOSING:
|
|
27
|
+
return 'CLOSING';
|
|
28
|
+
case CurrentDoorState.STOPPED:
|
|
29
|
+
return 'STOPPED';
|
|
30
|
+
}
|
|
31
|
+
return 'UNKNOWN';
|
|
32
|
+
};
|
|
18
33
|
const assignCurrentDoorState = (currentDoorState) => {
|
|
34
|
+
(0, debug_1.debug)(`assignCurrentDoorState=${(0, chalk_1.chalkString)(getDoorStateLabel(currentDoorState))}`);
|
|
19
35
|
Object.assign(state, { currentDoorState });
|
|
20
36
|
service.updateCharacteristic(CurrentDoorState, currentDoorState);
|
|
21
37
|
};
|
|
@@ -31,14 +47,14 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
31
47
|
currentDoorState: CurrentDoorState.CLOSED,
|
|
32
48
|
targetDoorState: TargetDoorState.CLOSED,
|
|
33
49
|
lastUpdatedAt: 0,
|
|
34
|
-
computedPosition: 0 // 0 <->
|
|
50
|
+
computedPosition: 0 // 0 <-> 100%
|
|
35
51
|
});
|
|
36
52
|
const getNextCurrentDoorState = (targetDoorState) => {
|
|
37
53
|
switch (state.currentDoorState) {
|
|
38
54
|
case CurrentDoorState.OPEN: {
|
|
39
55
|
switch (targetDoorState) {
|
|
40
56
|
case TargetDoorState.CLOSED:
|
|
41
|
-
return CurrentDoorState.
|
|
57
|
+
return CurrentDoorState.CLOSING;
|
|
42
58
|
case TargetDoorState.OPEN:
|
|
43
59
|
return CurrentDoorState.OPEN;
|
|
44
60
|
}
|
|
@@ -49,7 +65,7 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
49
65
|
case TargetDoorState.CLOSED:
|
|
50
66
|
return CurrentDoorState.CLOSED;
|
|
51
67
|
case TargetDoorState.OPEN:
|
|
52
|
-
return CurrentDoorState.
|
|
68
|
+
return CurrentDoorState.OPENING;
|
|
53
69
|
}
|
|
54
70
|
break;
|
|
55
71
|
}
|
|
@@ -71,7 +87,7 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
71
87
|
};
|
|
72
88
|
const computeCurrentPosition = () => {
|
|
73
89
|
const { lastUpdatedAt, computedPosition: lastComputedPosition, currentDoorState } = state;
|
|
74
|
-
const elapsed =
|
|
90
|
+
const elapsed = Date.now() - lastUpdatedAt;
|
|
75
91
|
switch (currentDoorState) {
|
|
76
92
|
case CurrentDoorState.STOPPED: {
|
|
77
93
|
return lastComputedPosition;
|
|
@@ -83,10 +99,10 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
83
99
|
return 0;
|
|
84
100
|
}
|
|
85
101
|
case CurrentDoorState.OPENING: {
|
|
86
|
-
return Math.min(100, lastComputedPosition + elapsed / GARAGE_DOOR_DELAY);
|
|
102
|
+
return Math.min(100, lastComputedPosition + 100 * (elapsed / GARAGE_DOOR_DELAY));
|
|
87
103
|
}
|
|
88
104
|
case CurrentDoorState.CLOSING: {
|
|
89
|
-
return Math.max(0, lastComputedPosition - elapsed / GARAGE_DOOR_DELAY);
|
|
105
|
+
return Math.max(0, lastComputedPosition - 100 * (elapsed / GARAGE_DOOR_DELAY));
|
|
90
106
|
}
|
|
91
107
|
}
|
|
92
108
|
return 0;
|
|
@@ -126,10 +142,6 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
126
142
|
})
|
|
127
143
|
.on("set" /* CharacteristicEventTypes.SET */, async (value, callback) => {
|
|
128
144
|
(0, debug_1.debugSet)(TargetDoorState, service, value);
|
|
129
|
-
if (!value) {
|
|
130
|
-
callback();
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
145
|
try {
|
|
134
146
|
(0, debug_1.debugSetResult)(TargetDoorState, service, value);
|
|
135
147
|
const targetDoorState = (0, basic_1.asNumber)(value);
|
|
@@ -138,7 +150,9 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
138
150
|
lastUpdatedAt: Date.now(),
|
|
139
151
|
computedPosition: computeCurrentPosition()
|
|
140
152
|
});
|
|
153
|
+
// debug(`computedPosition=${chalkNumber(state.computedPosition)}`);
|
|
141
154
|
let nextCurrentDoorState = getNextCurrentDoorState(targetDoorState);
|
|
155
|
+
// debug(`nextCurrentDoorState=${chalkString(getDoorStateLabel(nextCurrentDoorState))}`);
|
|
142
156
|
if (nextCurrentDoorState === state.currentDoorState) {
|
|
143
157
|
(0, debug_1.debug)(`nextCurrentDoorState=${(0, chalk_1.chalkNumber)(nextCurrentDoorState)} === state.currentDoorState`);
|
|
144
158
|
callback();
|
|
@@ -146,30 +160,48 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
146
160
|
}
|
|
147
161
|
await toggleGarageDoor();
|
|
148
162
|
assignCurrentDoorState(nextCurrentDoorState);
|
|
149
|
-
callback();
|
|
150
163
|
// Handle Stopped state, if we are stopped, wait one second and trigger again to reverse course
|
|
151
164
|
// eg. Stopped -> Closing if target is Closed
|
|
152
165
|
if (nextCurrentDoorState === CurrentDoorState.STOPPED) {
|
|
153
|
-
await (0, basic_1.waitFor)(1000);
|
|
166
|
+
await (0, basic_1.waitFor)('stopping', 1000);
|
|
154
167
|
assignState({
|
|
155
168
|
targetDoorState: targetDoorState,
|
|
156
169
|
lastUpdatedAt: Date.now(),
|
|
157
170
|
computedPosition: computeCurrentPosition()
|
|
158
171
|
});
|
|
172
|
+
// debug(`computedPosition=${chalkNumber(state.computedPosition)}`);
|
|
159
173
|
nextCurrentDoorState = getNextCurrentDoorState(targetDoorState);
|
|
174
|
+
// debug(`nextCurrentDoorState=${chalkString(getDoorStateLabel(nextCurrentDoorState))}`);
|
|
160
175
|
await toggleGarageDoor();
|
|
161
176
|
assignCurrentDoorState(nextCurrentDoorState);
|
|
162
177
|
}
|
|
178
|
+
callback();
|
|
163
179
|
// Finally update pending states
|
|
164
180
|
switch (nextCurrentDoorState) {
|
|
165
|
-
case CurrentDoorState.OPENING:
|
|
166
|
-
|
|
167
|
-
|
|
181
|
+
case CurrentDoorState.OPENING: {
|
|
182
|
+
const delay = ((100 - state.computedPosition) * GARAGE_DOOR_DELAY) / 100;
|
|
183
|
+
// debug(`delay=${chalkNumber(delay)}`);
|
|
184
|
+
try {
|
|
185
|
+
await (0, basic_1.waitFor)(`${deviceId}.pending`, delay);
|
|
186
|
+
assignCurrentDoorState(CurrentDoorState.OPEN);
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
// debug(`Aborted OPEN update with delay=${chalkNumber(delay)}`);
|
|
190
|
+
}
|
|
168
191
|
break;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
192
|
+
}
|
|
193
|
+
case CurrentDoorState.CLOSING: {
|
|
194
|
+
const delay = (state.computedPosition * GARAGE_DOOR_DELAY) / 100;
|
|
195
|
+
// debug(`delay=${chalkNumber(delay)}`);
|
|
196
|
+
try {
|
|
197
|
+
await (0, basic_1.waitFor)(`${deviceId}.pending`, delay);
|
|
198
|
+
assignCurrentDoorState(CurrentDoorState.CLOSED);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
// debug(`Aborted CLOSED update with delay=${chalkNumber(delay)}`);
|
|
202
|
+
}
|
|
172
203
|
break;
|
|
204
|
+
}
|
|
173
205
|
}
|
|
174
206
|
}
|
|
175
207
|
catch (err) {
|
|
@@ -177,6 +209,29 @@ const setupGarageDoorOpener = (accessory, controller) => {
|
|
|
177
209
|
}
|
|
178
210
|
})
|
|
179
211
|
.getValue();
|
|
212
|
+
// const switchService = addAccessoryService(accessory, Service.Switch, `${accessory.displayName} Switch`, true);
|
|
213
|
+
// debugAddSubService(switchService, accessory);
|
|
214
|
+
// service.addLinkedService(switchService);
|
|
215
|
+
// switchService
|
|
216
|
+
// .getCharacteristic(Characteristic.On)
|
|
217
|
+
// .on(CharacteristicEventTypes.SET, async (value: CharacteristicValue, callback: CharacteristicSetCallback) => {
|
|
218
|
+
// debugSet(Characteristic.On, service, value);
|
|
219
|
+
// if (!value) {
|
|
220
|
+
// callback();
|
|
221
|
+
// return;
|
|
222
|
+
// }
|
|
223
|
+
// try {
|
|
224
|
+
// await toggleGarageDoor();
|
|
225
|
+
// debugSetResult(Characteristic.On, service, value);
|
|
226
|
+
// callback();
|
|
227
|
+
// setTimeout(() => {
|
|
228
|
+
// service.updateCharacteristic(Characteristic.On, false);
|
|
229
|
+
// }, 1000);
|
|
230
|
+
// } catch (err) {
|
|
231
|
+
// callback(err as Error);
|
|
232
|
+
// }
|
|
233
|
+
// })
|
|
234
|
+
// .updateValue(false);
|
|
180
235
|
};
|
|
181
236
|
exports.setupGarageDoorOpener = setupGarageDoorOpener;
|
|
182
237
|
const updateGarageDoorOpener = (accessory, _controller, updates, type) => {
|
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
|
}
|
package/lib/platform.js
CHANGED
|
@@ -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
|
|
97
|
+
this.log.info(`Creating accessory named="${accessoryName}" with 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,7 +102,7 @@ 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
|
|
105
|
+
this.log.info(`Updating accessory named="${name}" with deviceId="${context.deviceId}"`);
|
|
106
106
|
Object.assign(accessory.context, context);
|
|
107
107
|
const tydomAccessorySetup = (0, accessory_1.getTydomAccessorySetup)(accessory);
|
|
108
108
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
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;
|