homey-api 3.0.0-rc.2 → 3.0.0-rc.21
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/assets/specifications/AthomCloudAPI.json +16 -0
- package/assets/specifications/HomeyAPIV3Local.json +365 -7
- package/assets/types/homey-api.d.ts +382 -59
- package/assets/types/homey-api.private.d.ts +428 -59
- package/index.browser.js +1 -0
- package/index.js +19 -20
- package/lib/HomeyAPI/HomeyAPI.js +58 -5
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices/Capability.js +2 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices/Device.js +4 -3
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDevices.js +0 -14
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDrivers/Driver.js +2 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDrivers/PairSession.js +20 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerDrivers.js +17 -0
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/AdvancedFlow.js +19 -4
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/Flow.js +27 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardAction.js +2 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardCondition.js +2 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow/FlowCardTrigger.js +2 -2
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlow.js +37 -14
- package/lib/HomeyAPI/HomeyAPIV2/ManagerFlowToken/FlowToken.js +3 -3
- package/lib/HomeyAPI/HomeyAPIV2/ManagerInsights/Log.js +2 -3
- package/lib/HomeyAPI/HomeyAPIV2/ManagerInsights.js +17 -0
- package/lib/HomeyAPI/HomeyAPIV3/Item.js +14 -1
- package/lib/HomeyAPI/HomeyAPIV3/Manager.js +34 -46
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices/Device.js +14 -12
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDevices/DeviceCapability.js +1 -1
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDrivers/PairSession.js +9 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerDrivers.js +2 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/AdvancedFlow.js +119 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/Flow.js +103 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlow/FlowCard.js +8 -0
- package/lib/HomeyAPI/HomeyAPIV3/ManagerFlowToken/FlowToken.js +12 -4
- package/lib/HomeyAPI/HomeyAPIV3/ManagerInsights/Log.js +14 -0
- package/lib/HomeyAPI/HomeyAPIV3.js +8 -8
- package/lib/HomeyAPI/HomeyAPIV3Local/ManagerDevkit.js +32 -0
- package/lib/HomeyAPI/HomeyAPIV3Local.js +6 -0
- package/package.json +2 -1
|
@@ -108,7 +108,7 @@ class DeviceCapability extends EventEmitter {
|
|
|
108
108
|
const capabilityReference = this.device.capabilitiesObj && this.device.capabilitiesObj[this.id];
|
|
109
109
|
if (capabilityReference) {
|
|
110
110
|
capabilityReference.value = value;
|
|
111
|
-
capabilityReference.lastUpdated = this.__lastChanged
|
|
111
|
+
capabilityReference.lastUpdated = this.__lastChanged;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
this.__listener(value);
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
const Manager = require('./Manager');
|
|
4
4
|
const Driver = require('./ManagerDrivers/Driver');
|
|
5
|
+
const PairSession = require('./ManagerDrivers/PairSession');
|
|
5
6
|
|
|
6
7
|
class ManagerDrivers extends Manager {
|
|
7
8
|
|
|
8
9
|
static CRUD = {
|
|
9
10
|
...super.CRUD,
|
|
10
11
|
Driver,
|
|
12
|
+
PairSession,
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
}
|
|
@@ -1,9 +1,128 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
|
|
1
3
|
'use strict';
|
|
2
4
|
|
|
3
5
|
const Item = require('../Item');
|
|
4
6
|
|
|
5
7
|
class AdvancedFlow extends Item {
|
|
6
8
|
|
|
9
|
+
async isBroken() {
|
|
10
|
+
const managerFlow = this.homey.flow;
|
|
11
|
+
if (!managerFlow.isConnected()) {
|
|
12
|
+
throw new Error('Flow.isBroken requires ManagerFlow to be connected.');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const managerFlowToken = this.homey.flowtoken;
|
|
16
|
+
if (!managerFlowToken.isConnected()) {
|
|
17
|
+
throw new Error('Flow.isBroken requires ManagerFlowToken to be connected.');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Array of local & global Token IDs.
|
|
21
|
+
// For example [ 'foo', 'homey:x:y|abc' ]
|
|
22
|
+
const tokenIds = [];
|
|
23
|
+
|
|
24
|
+
const checkToken = async tokenId => {
|
|
25
|
+
// If this is a global Token, fetch all FlowTokens
|
|
26
|
+
if (tokenId.includes('|')) {
|
|
27
|
+
const flowTokens = await managerFlowToken.getFlowTokens(); // Fill the cache
|
|
28
|
+
for (const flowTokenId of Object.keys(flowTokens)) {
|
|
29
|
+
tokenIds.push(flowTokenId);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
tokenId = tokenId.replace('|', ':');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!tokenIds.includes(tokenId)) {
|
|
36
|
+
throw new Error(`Missing Token: ${tokenId}`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const checkTokens = async card => {
|
|
41
|
+
// Check droptoken
|
|
42
|
+
if (card.droptoken) {
|
|
43
|
+
await checkToken(card.droptoken);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (typeof card.args === 'object') {
|
|
47
|
+
for (const arg of Object.values(card.args)) {
|
|
48
|
+
if (typeof arg !== 'string') continue;
|
|
49
|
+
for (const [tokenMatch, tokenId] of arg.matchAll(/\[\[(.*?)\]\]/g)) {
|
|
50
|
+
await checkToken(tokenId);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Check if FlowCards exist, and add Tokens
|
|
57
|
+
for (const [cardId, card] of Object.entries(this.cards)) {
|
|
58
|
+
switch (card.type) {
|
|
59
|
+
case 'trigger': {
|
|
60
|
+
try {
|
|
61
|
+
await managerFlow.getFlowCardTriggers(); // Fill the cache
|
|
62
|
+
const triggerCard = await this.manager.getFlowCardTrigger({ id: card.id });
|
|
63
|
+
|
|
64
|
+
// Add FlowCardTrigger.tokens to internal tokens cache
|
|
65
|
+
if (Array.isArray(triggerCard.tokens)) {
|
|
66
|
+
for (const token of Object.values(triggerCard.tokens)) {
|
|
67
|
+
tokenIds.push(`trigger::${cardId}::${token.id}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
break;
|
|
72
|
+
} catch (err) {
|
|
73
|
+
this.__debug(err);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
case 'condition': {
|
|
78
|
+
try {
|
|
79
|
+
await managerFlow.getFlowCardConditions(); // Fill the cache
|
|
80
|
+
const conditionCard = await this.manager.getFlowCardCondition({ id: card.id });
|
|
81
|
+
|
|
82
|
+
// Add Error Token
|
|
83
|
+
tokenIds.push(`card::${cardId}::error`);
|
|
84
|
+
|
|
85
|
+
break;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
this.__debug(err);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
case 'action': {
|
|
92
|
+
try {
|
|
93
|
+
await managerFlow.getFlowCardActions(); // Fill the cache
|
|
94
|
+
const actionCard = await this.manager.getFlowCardAction({ id: card.id });
|
|
95
|
+
|
|
96
|
+
// Add Error Token
|
|
97
|
+
tokenIds.push(`card::${cardId}::error`);
|
|
98
|
+
|
|
99
|
+
// Add FlowCardAction.tokens to internal tokens cache
|
|
100
|
+
if (Array.isArray(actionCard.tokens)) {
|
|
101
|
+
for (const token of Object.values(actionCard.tokens)) {
|
|
102
|
+
tokenIds.push(`action::${cardId}::${token.id}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
break;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
this.__debug(err);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
default: {
|
|
113
|
+
// Do nothing
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check Tokens
|
|
119
|
+
for (const card of Object.values(this.cards)) {
|
|
120
|
+
await checkTokens(card);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
7
126
|
}
|
|
8
127
|
|
|
9
128
|
module.exports = AdvancedFlow;
|
|
@@ -1,9 +1,112 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
|
|
1
3
|
'use strict';
|
|
2
4
|
|
|
3
5
|
const Item = require('../Item');
|
|
4
6
|
|
|
5
7
|
class Flow extends Item {
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Check whether this Flow misses one or more {@link FlowCard} or {@link FlowToken}.
|
|
11
|
+
* @returns Promise<Boolean>
|
|
12
|
+
*/
|
|
13
|
+
async isBroken() {
|
|
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;
|
|
108
|
+
}
|
|
109
|
+
|
|
7
110
|
}
|
|
8
111
|
|
|
9
112
|
module.exports = Flow;
|
|
@@ -4,6 +4,14 @@ const Item = require('../Item');
|
|
|
4
4
|
|
|
5
5
|
class FlowCard extends Item {
|
|
6
6
|
|
|
7
|
+
static transformGet(item) {
|
|
8
|
+
item = super.transformGet(item);
|
|
9
|
+
|
|
10
|
+
delete item.ownerName; // Prepare for back-end change
|
|
11
|
+
|
|
12
|
+
return item;
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
module.exports = FlowCard;
|
|
@@ -4,11 +4,19 @@ const Item = require('../Item');
|
|
|
4
4
|
|
|
5
5
|
class FlowToken extends Item {
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
static transformGet(item) {
|
|
8
|
+
item = super.transformGet(item);
|
|
9
|
+
|
|
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.
|
|
11
16
|
delete item.uriObj;
|
|
17
|
+
delete item.ownerName; // Prepare for back-end change
|
|
18
|
+
|
|
19
|
+
return item;
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
}
|
|
@@ -4,6 +4,20 @@ const Item = require('../Item');
|
|
|
4
4
|
|
|
5
5
|
class Log extends Item {
|
|
6
6
|
|
|
7
|
+
async getEntries() {
|
|
8
|
+
return this.manager.getLogEntries({
|
|
9
|
+
id: this.id,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static transformGet(item) {
|
|
14
|
+
item = super.transformGet(item);
|
|
15
|
+
|
|
16
|
+
delete item.ownerName; // Prepare for back-end change
|
|
17
|
+
|
|
18
|
+
return item;
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
}
|
|
8
22
|
|
|
9
23
|
module.exports = Log;
|
|
@@ -378,32 +378,32 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
378
378
|
headers,
|
|
379
379
|
path,
|
|
380
380
|
body,
|
|
381
|
+
json = true,
|
|
381
382
|
retryAfterRefresh = false,
|
|
382
383
|
}) {
|
|
383
384
|
const baseUrl = await this.baseUrl;
|
|
384
385
|
|
|
385
|
-
method = method.toUpperCase();
|
|
386
|
+
method = String(method).toUpperCase();
|
|
386
387
|
|
|
387
388
|
headers = {
|
|
388
389
|
...headers,
|
|
389
390
|
'X-Homey-ID': this.id,
|
|
390
391
|
};
|
|
391
392
|
|
|
392
|
-
if (body) {
|
|
393
|
-
headers['Content-Type'] = 'application/json';
|
|
394
|
-
}
|
|
395
|
-
|
|
396
393
|
if (this.__token) {
|
|
397
394
|
headers['Authorization'] = `Bearer ${this.__token}`;
|
|
398
395
|
}
|
|
399
396
|
|
|
397
|
+
if (body && json === true && ['PUT', 'POST'].includes(method)) {
|
|
398
|
+
headers['Content-Type'] = 'application/json';
|
|
399
|
+
body = JSON.stringify(body);
|
|
400
|
+
}
|
|
401
|
+
|
|
400
402
|
this.__debug(method, `${baseUrl}${path}`);
|
|
401
403
|
const res = await Util.timeout(Util.fetch(`${baseUrl}${path}`, {
|
|
402
404
|
method,
|
|
403
405
|
headers,
|
|
404
|
-
body
|
|
405
|
-
? JSON.stringify(body)
|
|
406
|
-
: undefined,
|
|
406
|
+
body,
|
|
407
407
|
}), $timeout);
|
|
408
408
|
|
|
409
409
|
const resStatusCode = res.status;
|
|
@@ -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('purgseSettings', 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,11 @@ const HomeyAPIV3 = require('./HomeyAPIV3');
|
|
|
11
12
|
*/
|
|
12
13
|
class HomeyAPIV3Local extends HomeyAPIV3 {
|
|
13
14
|
|
|
15
|
+
static MANAGERS = {
|
|
16
|
+
...HomeyAPIV3.MANAGERS,
|
|
17
|
+
ManagerDevkit,
|
|
18
|
+
};
|
|
19
|
+
|
|
14
20
|
getSpecification() {
|
|
15
21
|
// eslint-disable-next-line global-require
|
|
16
22
|
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.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.21",
|
|
4
4
|
"description": "Homey API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -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"
|