homey-api 1.10.17 → 3.0.0-rc.2
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 +1 -1
- package/assets/types/homey-api.d.ts +47 -588
- package/assets/types/homey-api.private.d.ts +47 -648
- package/index.js +1 -1
- package/lib/APIErrorNotFound.js +20 -0
- package/lib/AthomCloudAPI/Homey.js +3 -1
- package/lib/EventEmitter.js +0 -6
- package/lib/HomeyAPI/HomeyAPI.js +49 -5
- package/lib/HomeyAPI/HomeyAPIErrorNotFound.js +21 -0
- package/lib/HomeyAPI/HomeyAPIV2/Manager.js +2 -575
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices/Capability.js +20 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices/Device.js +18 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices.js +20 -3
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDrivers/Driver.js +25 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDrivers.js +29 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/AdvancedFlow.js +17 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/Flow.js +34 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardAction.js +25 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardCondition.js +25 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardTrigger.js +25 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow.js +104 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlowToken/FlowToken.js +24 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlowToken.js +29 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerInsights/Log.js +23 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerInsights.js +29 -0
- package/lib/HomeyAPI/HomeyAPIV2.js +12 -716
- package/lib/HomeyAPI/HomeyAPIV3/Item.js +173 -2
- package/lib/HomeyAPI/HomeyAPIV3/Manager.js +531 -3
- package/lib/HomeyAPI/{HomeyAPIV2 → HomeyAPIV3/ManagerApps}/App.js +1 -1
- package/lib/HomeyAPI/{HomeyAPIV2 → HomeyAPIV3}/ManagerApps.js +4 -3
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices/Capability.js +9 -0
- package/lib/HomeyAPI/{HomeyAPIV2 → HomeyAPIV3/ManagerDevices}/Device.js +78 -3
- package/lib/HomeyAPI/{HomeyAPIV2 → HomeyAPIV3/ManagerDevices}/DeviceCapability.js +3 -3
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices.js +17 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDrivers/Driver.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDrivers.js +15 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/AdvancedFlow.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/Flow.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/FlowCard.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/FlowCardAction.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/FlowCardCondition.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/FlowCardTrigger.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow.js +12 -23
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlowToken/FlowToken.js +16 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlowToken.js +15 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerInsights/Log.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerInsights.js +15 -0
- package/lib/HomeyAPI/HomeyAPIV3.js +728 -4
- package/lib/HomeyAPI/HomeyAPIV3Cloud.js +1 -1
- package/lib/HomeyAPI/HomeyAPIV3Local.js +1 -1
- package/package.json +1 -1
- package/lib/HomeyAPI/HomeyAPIApp.js +0 -127
- package/lib/HomeyAPI/HomeyAPIV2/Item.js +0 -177
|
@@ -2,587 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const Util = require('../../Util');
|
|
7
|
-
const HomeyAPIError = require('../HomeyAPIError');
|
|
8
|
-
const Item = require('./Item');
|
|
5
|
+
const HomeyAPIV3Manager = require('../HomeyAPIV3/Manager');
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* @class
|
|
12
9
|
* @hideconstructor
|
|
13
10
|
* @memberof HomeyAPIV2
|
|
14
11
|
*/
|
|
15
|
-
class Manager extends
|
|
16
|
-
|
|
17
|
-
static ITEMS = {};
|
|
18
|
-
|
|
19
|
-
constructor({
|
|
20
|
-
id,
|
|
21
|
-
name,
|
|
22
|
-
homey,
|
|
23
|
-
items,
|
|
24
|
-
operations,
|
|
25
|
-
}) {
|
|
26
|
-
super();
|
|
27
|
-
|
|
28
|
-
// Set Homey
|
|
29
|
-
Object.defineProperty(this, 'homey', {
|
|
30
|
-
value: homey,
|
|
31
|
-
enumerable: false,
|
|
32
|
-
writable: false,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Set ID
|
|
36
|
-
Object.defineProperty(this, 'id', {
|
|
37
|
-
value: id,
|
|
38
|
-
enumerable: false,
|
|
39
|
-
writable: false,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
// Set URI
|
|
43
|
-
Object.defineProperty(this, 'uri', {
|
|
44
|
-
value: `homey:manager:${id}`,
|
|
45
|
-
enumerable: false,
|
|
46
|
-
writable: false,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Set Name
|
|
50
|
-
Object.defineProperty(this, 'name', {
|
|
51
|
-
value: name,
|
|
52
|
-
enumerable: false,
|
|
53
|
-
writable: false,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Set Connected
|
|
57
|
-
Object.defineProperty(this, '__connected', {
|
|
58
|
-
value: false,
|
|
59
|
-
enumerable: false,
|
|
60
|
-
writable: true,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Set Items
|
|
64
|
-
Object.defineProperty(this, '__items', {
|
|
65
|
-
value: items,
|
|
66
|
-
enumerable: false,
|
|
67
|
-
writable: false,
|
|
68
|
-
});
|
|
69
|
-
Object.defineProperty(this, '__itemsById', {
|
|
70
|
-
value: Object.entries(items).reduce((obj, [itemName, item]) => ({
|
|
71
|
-
[item.id]: {
|
|
72
|
-
name: itemName,
|
|
73
|
-
...item,
|
|
74
|
-
},
|
|
75
|
-
...obj,
|
|
76
|
-
}), {}),
|
|
77
|
-
enumerable: false,
|
|
78
|
-
writable: false,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Set Cache
|
|
82
|
-
Object.defineProperty(this, '__cache', {
|
|
83
|
-
value: {},
|
|
84
|
-
enumerable: false,
|
|
85
|
-
writable: false,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
Object.defineProperty(this, '__cacheAllComplete', {
|
|
89
|
-
value: {},
|
|
90
|
-
enumerable: false,
|
|
91
|
-
writable: false,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Prepare caches
|
|
95
|
-
for (const { id } of Object.values(items)) {
|
|
96
|
-
this.__cache[id] = {};
|
|
97
|
-
this.__cacheAllComplete[id] = false;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Create methods
|
|
101
|
-
for (const [operationId, operation] of Object.entries(operations)) {
|
|
102
|
-
Object.defineProperty(this,
|
|
103
|
-
// Name method __super__foo if there's an override method
|
|
104
|
-
this[operationId]
|
|
105
|
-
? `__super__${operationId}`
|
|
106
|
-
: operationId,
|
|
107
|
-
{
|
|
108
|
-
value: async ({
|
|
109
|
-
$validate = true,
|
|
110
|
-
$cache = true,
|
|
111
|
-
$timeout = 5000,
|
|
112
|
-
$socket = true,
|
|
113
|
-
$body = {},
|
|
114
|
-
$query = {},
|
|
115
|
-
$headers = {},
|
|
116
|
-
...args
|
|
117
|
-
} = {}) => {
|
|
118
|
-
let { path } = operation;
|
|
119
|
-
let body = { ...$body };
|
|
120
|
-
const query = { ...$query };
|
|
121
|
-
const headers = { ...$headers };
|
|
122
|
-
|
|
123
|
-
// Verify & Transform parameters
|
|
124
|
-
if (operation.parameters) {
|
|
125
|
-
// Parse Parameters
|
|
126
|
-
for (const [parameterId, parameter] of Object.entries(operation.parameters)) {
|
|
127
|
-
const value = args[parameterId];
|
|
128
|
-
|
|
129
|
-
// Validate the parameter
|
|
130
|
-
if ($validate) {
|
|
131
|
-
if (parameter.required === true && typeof value === 'undefined') {
|
|
132
|
-
throw new Error(`Missing Parameter: ${parameterId}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (typeof value !== 'undefined') {
|
|
136
|
-
if (parameter.type === 'string' && typeof value !== 'string') {
|
|
137
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: string`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (parameter.type === 'number' && typeof value !== 'number') {
|
|
141
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: number`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (parameter.type === 'boolean' && typeof value !== 'boolean') {
|
|
145
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: boolean`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (parameter.type === 'object' && typeof value !== 'object') {
|
|
149
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: object`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (parameter.type === 'array' && !Array.isArray(value)) {
|
|
153
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: array`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (Array.isArray(parameter.type)) {
|
|
157
|
-
// TODO
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Set the parameter
|
|
163
|
-
if (typeof value !== 'undefined') {
|
|
164
|
-
switch (parameter.in) {
|
|
165
|
-
case 'path': {
|
|
166
|
-
if (typeof value !== 'string') {
|
|
167
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: string`);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
path = path.replace(`:${parameterId}`, value);
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
case 'body': {
|
|
174
|
-
if (parameter.root) {
|
|
175
|
-
body = value;
|
|
176
|
-
} else {
|
|
177
|
-
body[parameterId] = value;
|
|
178
|
-
}
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
case 'query': {
|
|
182
|
-
if (typeof value !== 'string') {
|
|
183
|
-
throw new Error(`Invalid Parameter Type: ${parameterId}. Got: ${typeof value}. Expected: string`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
query[parameterId] = value;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
default: {
|
|
190
|
-
throw new Error(`Invalid 'in': ${parameter.in}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Append query to path
|
|
198
|
-
if (Object.keys(query).length > 0) {
|
|
199
|
-
const queryString = Object.entries(query).map(([key, value]) => {
|
|
200
|
-
return `${key}=${encodeURIComponent(value)}`;
|
|
201
|
-
}).join('&');
|
|
202
|
-
path = `${path}?${queryString}`;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
let result;
|
|
206
|
-
const benchmark = Util.benchmark();
|
|
207
|
-
|
|
208
|
-
// If connected to Socket.io,
|
|
209
|
-
// try to get the CRUD Item from Cache.
|
|
210
|
-
if (this.isConnected() && operation.crud && $cache === true) {
|
|
211
|
-
const itemId = items[operation.crud.item].id;
|
|
212
|
-
const itemType = items[operation.crud.item].type || 'id';
|
|
213
|
-
|
|
214
|
-
switch (operation.crud.type) {
|
|
215
|
-
case 'getOne': {
|
|
216
|
-
const key = (itemType === 'filter')
|
|
217
|
-
? `${args.uri}:${args.id}`
|
|
218
|
-
: `${args.id}`;
|
|
219
|
-
|
|
220
|
-
if (this.__cache[itemId][key]) {
|
|
221
|
-
this.__debug(`Serving ${itemId}:${key} from cache`);
|
|
222
|
-
return this.__cache[itemId][key];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
case 'getAll': {
|
|
228
|
-
// If array (uri + id)
|
|
229
|
-
if (this.__cache[itemId]
|
|
230
|
-
&& this.__cacheAllComplete[itemId]
|
|
231
|
-
&& itemType === 'filter') {
|
|
232
|
-
this.__debug(`Serving ${itemId}:all from cache`);
|
|
233
|
-
return Object.values(this.__cache[itemId]);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// If object (id)
|
|
237
|
-
if (this.__cache[itemId]
|
|
238
|
-
&& this.__cacheAllComplete[itemId]) {
|
|
239
|
-
this.__debug(`Serving ${itemId}:all from cache`);
|
|
240
|
-
return this.__cache[itemId];
|
|
241
|
-
}
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
default:
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// If Homey is connected to Socket.io,
|
|
250
|
-
// send the API request to socket.io.
|
|
251
|
-
// This is about ~2x faster than HTTP
|
|
252
|
-
if (this.homey.isConnected() && $socket === true) {
|
|
253
|
-
result = await Util.timeout(new Promise((resolve, reject) => {
|
|
254
|
-
this.homey.__ioNamespace.emit('api', {
|
|
255
|
-
args,
|
|
256
|
-
operation: operationId,
|
|
257
|
-
uri: this.uri,
|
|
258
|
-
}, (err, result) => {
|
|
259
|
-
// String Error
|
|
260
|
-
if (typeof err === 'string') {
|
|
261
|
-
err = new HomeyAPIError({
|
|
262
|
-
error: err,
|
|
263
|
-
}, 500);
|
|
264
|
-
return reject(err);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Object Error
|
|
268
|
-
if (typeof err === 'object' && err !== null) {
|
|
269
|
-
err = new HomeyAPIError({
|
|
270
|
-
stack: err.stack,
|
|
271
|
-
error: err.error,
|
|
272
|
-
error_description: err.error_description,
|
|
273
|
-
}, err.statusCode || 500);
|
|
274
|
-
return reject(err);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return resolve(result);
|
|
278
|
-
});
|
|
279
|
-
}), $timeout);
|
|
280
|
-
} else {
|
|
281
|
-
// Get from HTTP
|
|
282
|
-
result = await this.homey.call({
|
|
283
|
-
$timeout,
|
|
284
|
-
headers,
|
|
285
|
-
body,
|
|
286
|
-
path: `/api/manager/${this.id}${path}`,
|
|
287
|
-
method: operation.method,
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Transform and cache output if this is a CRUD call
|
|
292
|
-
if (operation.crud) {
|
|
293
|
-
const itemId = items[operation.crud.item].id;
|
|
294
|
-
const itemType = items[operation.crud.item].type || 'id';
|
|
295
|
-
const ItemClass = this.constructor.ITEMS[itemId] || Item;
|
|
296
|
-
const getItemKey = props => {
|
|
297
|
-
if (itemType === 'filter') return `${props.uri}:${props.id}`;
|
|
298
|
-
if (itemType === 'id') return props.id;
|
|
299
|
-
throw new Error('Invalid Item Type');
|
|
300
|
-
};
|
|
301
|
-
const getItemUri = props => {
|
|
302
|
-
if (itemType === 'filter') return null;
|
|
303
|
-
if (itemType === 'id') return `homey:${itemId}:${props.id}`;
|
|
304
|
-
throw new Error('Invalid Item Type');
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
switch (operation.crud.type) {
|
|
308
|
-
case 'getOne': {
|
|
309
|
-
const key = getItemKey(result);
|
|
310
|
-
const uri = getItemUri(result);
|
|
311
|
-
|
|
312
|
-
result = new ItemClass({
|
|
313
|
-
key,
|
|
314
|
-
uri,
|
|
315
|
-
homey: this.homey,
|
|
316
|
-
manager: this,
|
|
317
|
-
properties: { ...result },
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
if (this.isConnected()) {
|
|
321
|
-
this.__cache[itemId][key] = result;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
case 'getAll': {
|
|
327
|
-
// Add all to cache
|
|
328
|
-
const currentKeys = {};
|
|
329
|
-
for (const [resultKey, item] of Object.entries(result)) {
|
|
330
|
-
const key = getItemKey(item);
|
|
331
|
-
const uri = getItemUri(item);
|
|
332
|
-
currentKeys[key] = true;
|
|
333
|
-
|
|
334
|
-
if (this.__cache[itemId][key]) {
|
|
335
|
-
result[resultKey] = this.__cache[itemId][key].__update(item);
|
|
336
|
-
} else {
|
|
337
|
-
result[resultKey] = new ItemClass({
|
|
338
|
-
key,
|
|
339
|
-
uri,
|
|
340
|
-
homey: this.homey,
|
|
341
|
-
manager: this,
|
|
342
|
-
properties: { ...item },
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
if (this.isConnected()) {
|
|
346
|
-
this.__cache[itemId][key] = result[resultKey];
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Find and delete deleted items from cache
|
|
352
|
-
if (this.__cache[itemId]) {
|
|
353
|
-
for (const cachedItem of Object.values(this.__cache[itemId])) {
|
|
354
|
-
const key = getItemKey(cachedItem);
|
|
355
|
-
|
|
356
|
-
if (!currentKeys[key]) {
|
|
357
|
-
delete this.__cache[itemId][key];
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (this.isConnected()) {
|
|
363
|
-
// Mark cache as complete
|
|
364
|
-
this.__cacheAllComplete[itemId] = true;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
break;
|
|
368
|
-
}
|
|
369
|
-
case 'createOne':
|
|
370
|
-
case 'updateOne': {
|
|
371
|
-
const key = getItemKey(result);
|
|
372
|
-
const uri = getItemUri(result);
|
|
373
|
-
|
|
374
|
-
if (this.__cache[itemId][key]) {
|
|
375
|
-
result = this.__cache[itemId][key].__update(result);
|
|
376
|
-
} else {
|
|
377
|
-
result = new ItemClass({
|
|
378
|
-
key,
|
|
379
|
-
uri,
|
|
380
|
-
homey: this.homey,
|
|
381
|
-
manager: this,
|
|
382
|
-
properties: result,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
if (this.isConnected()) {
|
|
386
|
-
this.__cache[itemId][key] = result;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
break;
|
|
390
|
-
}
|
|
391
|
-
case 'deleteOne': {
|
|
392
|
-
const key = getItemKey(args);
|
|
393
|
-
|
|
394
|
-
if (this.__cache[itemId][key]) {
|
|
395
|
-
this.__cache[itemId][key].destroy();
|
|
396
|
-
delete this.__cache[itemId][key];
|
|
397
|
-
}
|
|
398
|
-
result = null;
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
default:
|
|
402
|
-
break;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
this.__debug(`${operationId} took ${benchmark()}ms`);
|
|
407
|
-
return result;
|
|
408
|
-
},
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
__debug(...props) {
|
|
414
|
-
this.homey.__debug(`[${this.name}]`, ...props);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* If this manager's namespace is connected to Socket.io.
|
|
419
|
-
* @returns {Boolean}
|
|
420
|
-
*/
|
|
421
|
-
isConnected() {
|
|
422
|
-
return this.__connected === true;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Connect to the realtime namespace.
|
|
427
|
-
* @returns {Promise<void>}
|
|
428
|
-
*/
|
|
429
|
-
async connect() {
|
|
430
|
-
this.__debug('connect');
|
|
431
|
-
|
|
432
|
-
// If disconnecting, await that first
|
|
433
|
-
try {
|
|
434
|
-
await this.__disconnectPromise;
|
|
435
|
-
} catch (err) { }
|
|
436
|
-
|
|
437
|
-
this.__connectPromise = Promise.resolve().then(async () => {
|
|
438
|
-
if (!this.io) {
|
|
439
|
-
this.io = this.homey.subscribe(this.uri, {
|
|
440
|
-
onConnect: () => {
|
|
441
|
-
this.__debug('onConnect');
|
|
442
|
-
this.__connected = true;
|
|
443
|
-
},
|
|
444
|
-
onDisconnect: reason => {
|
|
445
|
-
this.__debug(`onDisconnect Reason:${reason}`);
|
|
446
|
-
this.__connected = false;
|
|
447
|
-
|
|
448
|
-
// Clear CRUD Item cache
|
|
449
|
-
for (const itemId of Object.keys(this.__cache)) {
|
|
450
|
-
this.__cache[itemId] = {};
|
|
451
|
-
this.__cacheAllComplete[itemId] = false;
|
|
452
|
-
}
|
|
453
|
-
},
|
|
454
|
-
onEvent: (event, data) => {
|
|
455
|
-
this.__debug('onEvent', event);
|
|
456
|
-
|
|
457
|
-
// Transform & add to cache if this is a CRUD event
|
|
458
|
-
if (event.endsWith('.create')
|
|
459
|
-
|| event.endsWith('.update')
|
|
460
|
-
|| event.endsWith('.delete')) {
|
|
461
|
-
const [itemId, operation] = event.split('.');
|
|
462
|
-
const ItemClass = this.constructor.ITEMS[itemId] || Item;
|
|
463
|
-
const itemType = this.__itemsById[itemId].type || 'id';
|
|
464
|
-
const key = itemType === 'filter'
|
|
465
|
-
? `${data.uri}:${data.id}`
|
|
466
|
-
: `${data.id}`;
|
|
467
|
-
const uri = itemType === 'filter'
|
|
468
|
-
? null
|
|
469
|
-
: `homey:${itemId}:${data.id}`;
|
|
470
|
-
|
|
471
|
-
switch (operation) {
|
|
472
|
-
case 'create': {
|
|
473
|
-
this.__cache[itemId][key] = new ItemClass({
|
|
474
|
-
key,
|
|
475
|
-
uri,
|
|
476
|
-
homey: this.homey,
|
|
477
|
-
manager: this,
|
|
478
|
-
properties: { ...data },
|
|
479
|
-
});
|
|
480
|
-
this.__cache[itemId][key].emit('create', data);
|
|
481
|
-
|
|
482
|
-
data = this.__cache[itemId][key];
|
|
483
|
-
|
|
484
|
-
break;
|
|
485
|
-
}
|
|
486
|
-
case 'update': {
|
|
487
|
-
if (this.__cache[itemId][key]) {
|
|
488
|
-
this.__cache[itemId][key].__update(data);
|
|
489
|
-
this.__cache[itemId][key].emit('update', data);
|
|
490
|
-
} else {
|
|
491
|
-
this.__cache[itemId][key] = new ItemClass({
|
|
492
|
-
key,
|
|
493
|
-
uri,
|
|
494
|
-
homey: this.homey,
|
|
495
|
-
manager: this,
|
|
496
|
-
properties: { ...data },
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
data = this.__cache[itemId][key];
|
|
501
|
-
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
case 'delete': {
|
|
505
|
-
if (this.__cache[itemId][key]) {
|
|
506
|
-
this.__cache[itemId][key].emit('delete');
|
|
507
|
-
this.__cache[itemId][key].destroy();
|
|
508
|
-
delete this.__cache[itemId][key];
|
|
509
|
-
}
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
default:
|
|
513
|
-
break;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Fire event listeners
|
|
518
|
-
this.emit(event, data);
|
|
519
|
-
},
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
await this.io;
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
// Delete the connecting Promise
|
|
527
|
-
this.__connectPromise
|
|
528
|
-
.catch(() => { })
|
|
529
|
-
.finally(() => {
|
|
530
|
-
delete this.__connectPromise;
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
await this.__connectPromise;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* Disconnect from the realtime namespace.
|
|
538
|
-
* @returns {Promise<void>}
|
|
539
|
-
*/
|
|
540
|
-
async disconnect() {
|
|
541
|
-
this.__debug('disconnect');
|
|
542
|
-
|
|
543
|
-
// If connecting, await that first
|
|
544
|
-
try {
|
|
545
|
-
await this.__connectPromise;
|
|
546
|
-
} catch (err) { }
|
|
547
|
-
|
|
548
|
-
this.__disconnectPromise = Promise.resolve().then(async () => {
|
|
549
|
-
this.__connected = false;
|
|
550
|
-
|
|
551
|
-
if (this.io) {
|
|
552
|
-
await this.io
|
|
553
|
-
.then(io => io.unsubscribe())
|
|
554
|
-
.catch(err => this.__debug('Error Disconnecting:', err));
|
|
555
|
-
|
|
556
|
-
delete this.io;
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
|
|
560
|
-
// Delete the disconnecting Promise
|
|
561
|
-
this.__disconnectPromise
|
|
562
|
-
.catch(() => { })
|
|
563
|
-
.finally(() => {
|
|
564
|
-
delete this.__disconnectPromise;
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
await this.__disconnectPromise;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
destroy() {
|
|
571
|
-
// Clear cache
|
|
572
|
-
for (const id of Object.keys(this.__cache)) {
|
|
573
|
-
this.__cache[id] = {};
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
for (const id of Object.keys(this.__cacheAllComplete)) {
|
|
577
|
-
this.__cacheAllComplete[id] = false;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// Remove all event listeners
|
|
581
|
-
this.removeAllListeners();
|
|
582
|
-
|
|
583
|
-
// Disconnect from Socket.io
|
|
584
|
-
this.disconnect().catch(() => { });
|
|
585
|
-
}
|
|
12
|
+
class Manager extends HomeyAPIV3Manager {
|
|
586
13
|
|
|
587
14
|
}
|
|
588
15
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const CapabilityV3 = require('../../HomeyAPIV3/ManagerDevices/Capability');
|
|
4
|
+
|
|
5
|
+
class Capability extends CapabilityV3 {
|
|
6
|
+
|
|
7
|
+
static transform(item) {
|
|
8
|
+
item = super.transform(item);
|
|
9
|
+
|
|
10
|
+
item.id = `${item.uri}:${item.id}`;
|
|
11
|
+
item.ownerUri = item.uri;
|
|
12
|
+
|
|
13
|
+
delete item.uri;
|
|
14
|
+
|
|
15
|
+
return item;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = Capability;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DeviceV3 = require('../../HomeyAPIV3/ManagerDevices/Device');
|
|
4
|
+
|
|
5
|
+
class Device extends DeviceV3 {
|
|
6
|
+
|
|
7
|
+
static transform(item) {
|
|
8
|
+
item = super.transform(item);
|
|
9
|
+
|
|
10
|
+
item.driverId = `${item.driverUri}:${item.driverId}`;
|
|
11
|
+
delete item.driverUri;
|
|
12
|
+
delete item.zoneName;
|
|
13
|
+
return item;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = Device;
|
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Manager = require('./Manager');
|
|
4
|
-
const
|
|
4
|
+
const Capability = require('./ManagerDevices/Capability');
|
|
5
|
+
const Device = require('./ManagerDevices/Device');
|
|
5
6
|
|
|
6
7
|
class ManagerDevices extends Manager {
|
|
7
8
|
|
|
8
|
-
static
|
|
9
|
-
|
|
9
|
+
static CRUD = {
|
|
10
|
+
...super.CRUD,
|
|
11
|
+
Capability,
|
|
12
|
+
Device,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getCapability({
|
|
16
|
+
$cache = true,
|
|
17
|
+
id,
|
|
18
|
+
}) {
|
|
19
|
+
if ($cache === true && this.__cache['capability'][id]) {
|
|
20
|
+
return this.__cache['capability'][id];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return this.__super__getCapability({
|
|
24
|
+
id: id.split(':').reverse()[0],
|
|
25
|
+
uri: id.split(':', 3).join(':'),
|
|
26
|
+
});
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DriverV3 = require('../../HomeyAPIV3/ManagerDrivers/Driver');
|
|
4
|
+
|
|
5
|
+
class Driver extends DriverV3 {
|
|
6
|
+
|
|
7
|
+
static transform(item) {
|
|
8
|
+
item = super.transform(item);
|
|
9
|
+
|
|
10
|
+
item.ownerId = item.id;
|
|
11
|
+
item.ownerUri = item.uri;
|
|
12
|
+
item.ownerName = item.uriObj.name;
|
|
13
|
+
item.ownerIconObj = item.uriObj.iconObj;
|
|
14
|
+
item.color = item.uriObj.color;
|
|
15
|
+
item.id = `${item.uri}:${item.id}`;
|
|
16
|
+
|
|
17
|
+
delete item.uri;
|
|
18
|
+
delete item.uriObj;
|
|
19
|
+
|
|
20
|
+
return item;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = Driver;
|