homey-api 3.0.0-rc.9 → 3.0.1
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/specifications/AthomCloudAPI.json +16 -0
- package/assets/specifications/HomeyAPIV3Local.json +173 -7
- package/assets/types/homey-api.d.ts +496 -223
- package/assets/types/homey-api.private.d.ts +542 -223
- package/index.browser.js +1 -0
- package/index.js +39 -20
- package/lib/API.js +6 -0
- package/lib/AthomCloudAPI/StorageAdapter.js +1 -0
- package/lib/AthomCloudAPI/User.js +4 -0
- package/lib/HomeyAPI/HomeyAPI.js +123 -9
- package/lib/HomeyAPI/HomeyAPIV1.js +8 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices/Device.js +2 -1
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevkit.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/AdvancedFlow.js +3 -1
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/Flow.js +2 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow.js +1 -1
- package/lib/HomeyAPI/HomeyAPIV2.js +10 -0
- package/lib/HomeyAPI/HomeyAPIV3/Manager.js +10 -4
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices/Device.js +2 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices/DeviceCapability.js +3 -3
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/AdvancedFlow.js +119 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/Flow.js +96 -1
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlowToken/FlowToken.js +8 -3
- package/lib/HomeyAPI/HomeyAPIV3.js +22 -17
- package/lib/HomeyAPI/HomeyAPIV3Cloud.js +8 -0
- package/lib/HomeyAPI/HomeyAPIV3Local/ManagerDevkit.js +32 -0
- package/lib/HomeyAPI/HomeyAPIV3Local.js +14 -0
- package/package.json +4 -3
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
|
|
1
3
|
'use strict';
|
|
2
4
|
|
|
3
5
|
const Item = require('../Item');
|
|
@@ -9,7 +11,100 @@ class Flow extends Item {
|
|
|
9
11
|
* @returns Promise<Boolean>
|
|
10
12
|
*/
|
|
11
13
|
async isBroken() {
|
|
12
|
-
|
|
14
|
+
const managerFlow = this.homey.flow;
|
|
15
|
+
if (!managerFlow.isConnected()) {
|
|
16
|
+
throw new Error('Flow.isBroken requires ManagerFlow to be connected.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const managerFlowToken = this.homey.flowtoken;
|
|
20
|
+
if (!managerFlowToken.isConnected()) {
|
|
21
|
+
throw new Error('Flow.isBroken requires ManagerFlowToken to be connected.');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Array of local & global Token IDs.
|
|
25
|
+
// For example [ 'foo', 'homey:x:y|abc' ]
|
|
26
|
+
const tokenIds = [];
|
|
27
|
+
|
|
28
|
+
const checkToken = async tokenId => {
|
|
29
|
+
// If this is a global Token, fetch all FlowTokens
|
|
30
|
+
if (tokenId.includes('|')) {
|
|
31
|
+
const flowTokens = await managerFlowToken.getFlowTokens(); // Fill the cache
|
|
32
|
+
for (const flowTokenId of Object.keys(flowTokens)) {
|
|
33
|
+
tokenIds.push(flowTokenId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
tokenId = tokenId.replace('|', ':');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!tokenIds.includes(tokenId)) {
|
|
40
|
+
throw new Error(`Missing Token: ${tokenId}`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const checkTokens = async card => {
|
|
45
|
+
// Check droptoken
|
|
46
|
+
if (card.droptoken) {
|
|
47
|
+
await checkToken(card.droptoken);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (typeof card.args === 'object') {
|
|
51
|
+
for (const arg of Object.values(card.args)) {
|
|
52
|
+
if (typeof arg !== 'string') continue;
|
|
53
|
+
for (const [tokenMatch, tokenId] of arg.matchAll(/\[\[(.*?)\]\]/g)) {
|
|
54
|
+
await checkToken(tokenId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Check Trigger
|
|
61
|
+
if (this.trigger) {
|
|
62
|
+
try {
|
|
63
|
+
await managerFlow.getFlowCardTriggers(); // Fill the cache
|
|
64
|
+
const triggerCard = await this.manager.getFlowCardTrigger({ id: this.trigger.id });
|
|
65
|
+
await checkTokens(this.trigger);
|
|
66
|
+
|
|
67
|
+
// Add FlowCardTrigger.tokens to internal tokens cache
|
|
68
|
+
if (Array.isArray(triggerCard.tokens)) {
|
|
69
|
+
for (const tokenId of Object.keys(triggerCard.tokens)) {
|
|
70
|
+
tokenIds.push(tokenId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch (err) {
|
|
74
|
+
this.__debug(err.message);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check Conditions
|
|
80
|
+
if (Array.isArray(this.conditions)) {
|
|
81
|
+
for (const condition of Object.values(this.conditions)) {
|
|
82
|
+
try {
|
|
83
|
+
await managerFlow.getFlowCardConditions(); // Fill the cache
|
|
84
|
+
const conditionCard = await this.manager.getFlowCardCondition({ id: condition.id });
|
|
85
|
+
await checkTokens(condition);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
this.__debug(err.message);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check Actions
|
|
94
|
+
if (Array.isArray(this.actions)) {
|
|
95
|
+
for (const action of Object.values(this.actions)) {
|
|
96
|
+
try {
|
|
97
|
+
await managerFlow.getFlowCardActions(); // Fill the cache
|
|
98
|
+
const actionCard = await this.manager.getFlowCardAction({ id: action.id });
|
|
99
|
+
await checkTokens(action);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
this.__debug(err.message);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
13
108
|
}
|
|
14
109
|
|
|
15
110
|
}
|
|
@@ -4,14 +4,19 @@ const Item = require('../Item');
|
|
|
4
4
|
|
|
5
5
|
class FlowToken extends Item {
|
|
6
6
|
|
|
7
|
-
// TODO: Remove when back-end has removed these properties.
|
|
8
7
|
static transformGet(item) {
|
|
9
8
|
item = super.transformGet(item);
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
if (item.uri) {
|
|
11
|
+
item.id = `${item.uri}:${item.id}`;
|
|
12
|
+
delete item.uri;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// TODO: Remove when back-end has removed these properties.
|
|
13
16
|
delete item.uriObj;
|
|
14
17
|
delete item.ownerName; // Prepare for back-end change
|
|
18
|
+
|
|
19
|
+
return item;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
}
|
|
@@ -16,6 +16,7 @@ const ManagerInsights = require('./HomeyAPIV3/ManagerInsights');
|
|
|
16
16
|
const Manager = require('./HomeyAPIV3/Manager');
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
+
* An authenticated Homey API. Do not construct this class manually.
|
|
19
20
|
* @class
|
|
20
21
|
* @hideconstructor
|
|
21
22
|
* @extends HomeyAPIV2
|
|
@@ -378,32 +379,32 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
378
379
|
headers,
|
|
379
380
|
path,
|
|
380
381
|
body,
|
|
382
|
+
json = true,
|
|
381
383
|
retryAfterRefresh = false,
|
|
382
384
|
}) {
|
|
383
385
|
const baseUrl = await this.baseUrl;
|
|
384
386
|
|
|
385
|
-
method = method.toUpperCase();
|
|
387
|
+
method = String(method).toUpperCase();
|
|
386
388
|
|
|
387
389
|
headers = {
|
|
388
390
|
...headers,
|
|
389
391
|
'X-Homey-ID': this.id,
|
|
390
392
|
};
|
|
391
393
|
|
|
392
|
-
if (body) {
|
|
393
|
-
headers['Content-Type'] = 'application/json';
|
|
394
|
-
}
|
|
395
|
-
|
|
396
394
|
if (this.__token) {
|
|
397
395
|
headers['Authorization'] = `Bearer ${this.__token}`;
|
|
398
396
|
}
|
|
399
397
|
|
|
398
|
+
if (body && json === true && ['PUT', 'POST'].includes(method)) {
|
|
399
|
+
headers['Content-Type'] = 'application/json';
|
|
400
|
+
body = JSON.stringify(body);
|
|
401
|
+
}
|
|
402
|
+
|
|
400
403
|
this.__debug(method, `${baseUrl}${path}`);
|
|
401
404
|
const res = await Util.timeout(Util.fetch(`${baseUrl}${path}`, {
|
|
402
405
|
method,
|
|
403
406
|
headers,
|
|
404
|
-
body
|
|
405
|
-
? JSON.stringify(body)
|
|
406
|
-
: undefined,
|
|
407
|
+
body,
|
|
407
408
|
}), $timeout);
|
|
408
409
|
|
|
409
410
|
const resStatusCode = res.status;
|
|
@@ -477,16 +478,20 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
477
478
|
|
|
478
479
|
// Create a Session by generating a JWT token on AthomCloudAPI,
|
|
479
480
|
// and then sending the JWT token to Homey.
|
|
480
|
-
this.
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
481
|
+
if (this.__api) {
|
|
482
|
+
this.__debug('Retrieving token...');
|
|
483
|
+
const jwtToken = await this.__api.createDelegationToken({ audience: 'homey' });
|
|
484
|
+
const token = await this.users.login({
|
|
485
|
+
$socket: false,
|
|
486
|
+
token: jwtToken,
|
|
487
|
+
});
|
|
488
|
+
await this.__setStore({ token });
|
|
489
|
+
this.__debug('Got token');
|
|
490
|
+
|
|
491
|
+
return token;
|
|
492
|
+
}
|
|
488
493
|
|
|
489
|
-
|
|
494
|
+
throw new Error('Cannot Sign In: Missing AthomCloudAPI');
|
|
490
495
|
});
|
|
491
496
|
|
|
492
497
|
this.__loginPromise
|
|
@@ -33,6 +33,14 @@ class HomeyAPIV3Cloud extends HomeyAPIV3 {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
get platform() {
|
|
37
|
+
return 'cloud';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get platformVersion() {
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
getSpecification() {
|
|
37
45
|
// eslint-disable-next-line global-require
|
|
38
46
|
return require('../../assets/specifications/HomeyAPIV3Cloud.json');
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const FormData = require('form-data');
|
|
4
|
+
|
|
5
|
+
const Manager = require('./Manager');
|
|
6
|
+
|
|
7
|
+
class ManagerDevkit extends Manager {
|
|
8
|
+
|
|
9
|
+
async runApp({
|
|
10
|
+
app, // Readable
|
|
11
|
+
env = {},
|
|
12
|
+
debug = false,
|
|
13
|
+
clean = false,
|
|
14
|
+
}) {
|
|
15
|
+
const form = new FormData();
|
|
16
|
+
form.append('app', app);
|
|
17
|
+
form.append('env', JSON.stringify(env));
|
|
18
|
+
form.append('debug', debug ? 'true' : 'false');
|
|
19
|
+
form.append('purgeSettings', clean ? 'true' : 'false');
|
|
20
|
+
|
|
21
|
+
return this.homey.call({
|
|
22
|
+
$timeout: 1000 * 60 * 5, // 5 minutes
|
|
23
|
+
method: 'POST',
|
|
24
|
+
path: '/api/manager/devkit/',
|
|
25
|
+
body: form,
|
|
26
|
+
json: false,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = ManagerDevkit;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const HomeyAPIV3 = require('./HomeyAPIV3');
|
|
4
|
+
const ManagerDevkit = require('./HomeyAPIV3Local/ManagerDevkit');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* This class is returned by {@link AthomCloudAPI.Homey#authenticate} for a Homey with `platform: 'local'` and `platformVersion: 1`.
|
|
@@ -11,6 +12,19 @@ const HomeyAPIV3 = require('./HomeyAPIV3');
|
|
|
11
12
|
*/
|
|
12
13
|
class HomeyAPIV3Local extends HomeyAPIV3 {
|
|
13
14
|
|
|
15
|
+
static MANAGERS = {
|
|
16
|
+
...HomeyAPIV3.MANAGERS,
|
|
17
|
+
ManagerDevkit,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
get platform() {
|
|
21
|
+
return 'local';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get platformVersion() {
|
|
25
|
+
return 2;
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
getSpecification() {
|
|
15
29
|
// eslint-disable-next-line global-require
|
|
16
30
|
return require('../../assets/specifications/HomeyAPIV3Local.json');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homey-api",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Homey API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"build:jsdoc": "npm run jsdoc",
|
|
24
24
|
"webpack": "webpack",
|
|
25
25
|
"webpack:watch": "webpack --watch",
|
|
26
|
-
"jsdoc": "npm run jsdoc:clean; npm run generate-specs; npm run generate-jsdoc; jsdoc --configure ./jsdoc.json --recurse; jsdoc --configure ./jsdoc.json --recurse --private --destination ./jsdoc/private; rm ./jsdoc/*.js.html;",
|
|
27
|
-
"jsdoc:clean": "rm -rf ./build/jsdoc
|
|
26
|
+
"jsdoc": "npm run jsdoc:clean; cp -r ./lib/ ./build/jsdoc-tmp; npm run generate-specs; npm run generate-jsdoc; jsdoc --configure ./jsdoc.json --recurse; jsdoc --configure ./jsdoc.json --recurse --private --destination ./jsdoc/private; rm ./jsdoc/*.js.html;",
|
|
27
|
+
"jsdoc:clean": "rm -rf ./build/jsdoc/; rm -rf ./build/jsdoc-tmp/",
|
|
28
28
|
"jsdoc:watch": "watch \"npm run jsdoc:clean; npm run generate-jsdoc; npm run jsdoc;\" lib \"node_modules/@athombv/jsdoc-template\" --interval 0.5",
|
|
29
29
|
"jsdoc:serve": "http-server ./jsdoc/",
|
|
30
30
|
"generate-specs": "node tools/generate-specs.js",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"core-js": "^3.19.1",
|
|
49
|
+
"form-data": "^4.0.0",
|
|
49
50
|
"node-fetch": "^2.6.7",
|
|
50
51
|
"regenerator-runtime": "^0.13.9",
|
|
51
52
|
"socket.io-client": "^2.5.0"
|