homey-api 3.4.16 → 3.4.18
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/HomeyAPI/HomeyAPIV3.js +160 -119
- package/package.json +1 -1
|
@@ -26,7 +26,6 @@ const versionCache = {};
|
|
|
26
26
|
* @extends HomeyAPI
|
|
27
27
|
*/
|
|
28
28
|
class HomeyAPIV3 extends HomeyAPI {
|
|
29
|
-
|
|
30
29
|
static MANAGERS = {
|
|
31
30
|
ManagerApps,
|
|
32
31
|
ManagerDrivers,
|
|
@@ -72,6 +71,12 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
72
71
|
writable: true,
|
|
73
72
|
});
|
|
74
73
|
|
|
74
|
+
Object.defineProperty(this, '__destroyed', {
|
|
75
|
+
value: false,
|
|
76
|
+
enumerable: false,
|
|
77
|
+
writable: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
75
80
|
Object.defineProperty(this, '__token', {
|
|
76
81
|
value: token,
|
|
77
82
|
enumerable: false,
|
|
@@ -85,9 +90,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
85
90
|
});
|
|
86
91
|
|
|
87
92
|
Object.defineProperty(this, '__strategies', {
|
|
88
|
-
value: Array.isArray(strategy)
|
|
89
|
-
? strategy
|
|
90
|
-
: [strategy],
|
|
93
|
+
value: Array.isArray(strategy) ? strategy : [strategy],
|
|
91
94
|
enumerable: false,
|
|
92
95
|
writable: false,
|
|
93
96
|
});
|
|
@@ -99,9 +102,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
99
102
|
});
|
|
100
103
|
|
|
101
104
|
Object.defineProperty(this, '__baseUrlPromise', {
|
|
102
|
-
value: typeof baseUrl === 'string'
|
|
103
|
-
? Promise.resolve(baseUrl)
|
|
104
|
-
: null,
|
|
105
|
+
value: typeof baseUrl === 'string' ? Promise.resolve(baseUrl) : null,
|
|
105
106
|
enumerable: false,
|
|
106
107
|
writable: true,
|
|
107
108
|
});
|
|
@@ -124,7 +125,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
124
125
|
this.__baseUrlPromise = this.discoverBaseUrl().then(({ baseUrl }) => {
|
|
125
126
|
return baseUrl;
|
|
126
127
|
});
|
|
127
|
-
this.__baseUrlPromise.catch(() => {
|
|
128
|
+
this.__baseUrlPromise.catch(() => {});
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
return this.__baseUrlPromise;
|
|
@@ -167,8 +168,8 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
167
168
|
const ManagerClass = this.constructor.MANAGERS[managerName]
|
|
168
169
|
? this.constructor.MANAGERS[managerName]
|
|
169
170
|
: (() => {
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
return class extends Manager {};
|
|
172
|
+
})();
|
|
172
173
|
|
|
173
174
|
ManagerClass.ID = manager.id;
|
|
174
175
|
|
|
@@ -254,7 +255,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
254
255
|
this.__baseUrl = baseUrl;
|
|
255
256
|
this.__strategyId = strategyId;
|
|
256
257
|
})
|
|
257
|
-
.catch(() => {
|
|
258
|
+
.catch(() => {});
|
|
258
259
|
|
|
259
260
|
// Ping method
|
|
260
261
|
const ping = async (strategyId, timeout) => {
|
|
@@ -299,7 +300,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
299
300
|
if (urls[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE]) {
|
|
300
301
|
pings[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE] = ping(HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE, 5000);
|
|
301
302
|
pings[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE].catch(err => {
|
|
302
|
-
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE} Error:`, err && err.message)
|
|
303
|
+
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE} Error:`, err && err.message);
|
|
303
304
|
this.__debug(urls[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL_SECURE]);
|
|
304
305
|
});
|
|
305
306
|
}
|
|
@@ -307,25 +308,36 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
307
308
|
// Ping local (http://xxx-xxx-xxx-xxx)
|
|
308
309
|
if (urls[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL]) {
|
|
309
310
|
pings[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL] = ping(HomeyAPI.DISCOVERY_STRATEGIES.LOCAL, 1000);
|
|
310
|
-
pings[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL].catch(err =>
|
|
311
|
+
pings[HomeyAPI.DISCOVERY_STRATEGIES.LOCAL].catch(err =>
|
|
312
|
+
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.LOCAL} Error:`, err && err.message)
|
|
313
|
+
);
|
|
311
314
|
}
|
|
312
315
|
|
|
313
316
|
// Ping mdns (http://homey-<homeyId>.local)
|
|
314
317
|
if (urls[HomeyAPI.DISCOVERY_STRATEGIES.MDNS]) {
|
|
315
318
|
pings[HomeyAPI.DISCOVERY_STRATEGIES.MDNS] = ping(HomeyAPI.DISCOVERY_STRATEGIES.MDNS, 3000);
|
|
316
|
-
pings[HomeyAPI.DISCOVERY_STRATEGIES.MDNS].catch(err =>
|
|
319
|
+
pings[HomeyAPI.DISCOVERY_STRATEGIES.MDNS].catch(err =>
|
|
320
|
+
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.MDNS} Error:`, err && err.message)
|
|
321
|
+
);
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
// Ping cloud (https://<homeyId>.connect.athom.com)
|
|
320
325
|
if (urls[HomeyAPI.DISCOVERY_STRATEGIES.CLOUD]) {
|
|
321
326
|
pings[HomeyAPI.DISCOVERY_STRATEGIES.CLOUD] = ping(HomeyAPI.DISCOVERY_STRATEGIES.CLOUD, 5000);
|
|
322
|
-
pings[HomeyAPI.DISCOVERY_STRATEGIES.CLOUD].catch(err =>
|
|
327
|
+
pings[HomeyAPI.DISCOVERY_STRATEGIES.CLOUD].catch(err =>
|
|
328
|
+
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.CLOUD} Error:`, err && err.message)
|
|
329
|
+
);
|
|
323
330
|
}
|
|
324
331
|
|
|
325
332
|
// Ping Direct (https://xxx-xxx-xxx-xx.homey.homeylocal.com:12345)
|
|
326
333
|
if (urls[HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED]) {
|
|
327
|
-
pings[HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED] = ping(
|
|
328
|
-
|
|
334
|
+
pings[HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED] = ping(
|
|
335
|
+
HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED,
|
|
336
|
+
2000
|
|
337
|
+
);
|
|
338
|
+
pings[HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED].catch(err =>
|
|
339
|
+
this.__debug(`Ping ${HomeyAPI.DISCOVERY_STRATEGIES.REMOTE_FORWARDED} Error:`, err && err.message)
|
|
340
|
+
);
|
|
329
341
|
}
|
|
330
342
|
|
|
331
343
|
// Select the best route
|
|
@@ -400,15 +412,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
400
412
|
return promise;
|
|
401
413
|
}
|
|
402
414
|
|
|
403
|
-
async call({
|
|
404
|
-
$timeout = 10000,
|
|
405
|
-
method,
|
|
406
|
-
headers,
|
|
407
|
-
path,
|
|
408
|
-
body,
|
|
409
|
-
json = true,
|
|
410
|
-
retryAfterRefresh = false,
|
|
411
|
-
}) {
|
|
415
|
+
async call({ $timeout = 10000, method, headers, path, body, json = true, retryAfterRefresh = false }) {
|
|
412
416
|
const baseUrl = await this.baseUrl;
|
|
413
417
|
|
|
414
418
|
method = String(method).toUpperCase();
|
|
@@ -433,11 +437,14 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
433
437
|
}
|
|
434
438
|
|
|
435
439
|
this.__debug(method, `${baseUrl}${path}`);
|
|
436
|
-
const res = await Util.timeout(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
440
|
+
const res = await Util.timeout(
|
|
441
|
+
Util.fetch(`${baseUrl}${path}`, {
|
|
442
|
+
method,
|
|
443
|
+
headers,
|
|
444
|
+
body,
|
|
445
|
+
}),
|
|
446
|
+
$timeout
|
|
447
|
+
);
|
|
441
448
|
|
|
442
449
|
const resStatusCode = res.status;
|
|
443
450
|
if (resStatusCode === 204) return undefined;
|
|
@@ -458,10 +465,8 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
458
465
|
if (resHeadersContentType && resHeadersContentType.startsWith('application/json')) {
|
|
459
466
|
try {
|
|
460
467
|
resBodyJson = JSON.parse(resBodyText);
|
|
461
|
-
|
|
462
|
-
} catch (err) {
|
|
463
|
-
|
|
464
|
-
}
|
|
468
|
+
// eslint-disable-next-line no-empty
|
|
469
|
+
} catch (err) {}
|
|
465
470
|
}
|
|
466
471
|
|
|
467
472
|
if (!res.ok) {
|
|
@@ -485,22 +490,31 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
485
490
|
});
|
|
486
491
|
}
|
|
487
492
|
|
|
488
|
-
throw new HomeyAPIError(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
+
throw new HomeyAPIError(
|
|
494
|
+
{
|
|
495
|
+
error: resBodyJson.error,
|
|
496
|
+
error_description: resBodyJson.error_description,
|
|
497
|
+
stack: resBodyJson.stack,
|
|
498
|
+
},
|
|
499
|
+
resStatusCode
|
|
500
|
+
);
|
|
493
501
|
}
|
|
494
502
|
|
|
495
503
|
if (resBodyText) {
|
|
496
|
-
throw new HomeyAPIError(
|
|
497
|
-
|
|
498
|
-
|
|
504
|
+
throw new HomeyAPIError(
|
|
505
|
+
{
|
|
506
|
+
error: resBodyText,
|
|
507
|
+
},
|
|
508
|
+
resStatusCode
|
|
509
|
+
);
|
|
499
510
|
}
|
|
500
511
|
|
|
501
|
-
throw new HomeyAPIError(
|
|
502
|
-
|
|
503
|
-
|
|
512
|
+
throw new HomeyAPIError(
|
|
513
|
+
{
|
|
514
|
+
error: resStatusText,
|
|
515
|
+
},
|
|
516
|
+
resStatusCode
|
|
517
|
+
);
|
|
504
518
|
}
|
|
505
519
|
|
|
506
520
|
if (typeof resBodyJson !== 'undefined') {
|
|
@@ -550,7 +564,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
550
564
|
});
|
|
551
565
|
|
|
552
566
|
this.__loginPromise
|
|
553
|
-
.then(() => {
|
|
567
|
+
.then(() => {})
|
|
554
568
|
.catch(err => {
|
|
555
569
|
this.__debug('Error Logging In:', err);
|
|
556
570
|
this.__token = null;
|
|
@@ -580,36 +594,43 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
580
594
|
return this.__homeySocket && this.__homeySocket.connected;
|
|
581
595
|
}
|
|
582
596
|
|
|
583
|
-
async subscribe(
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
597
|
+
async subscribe(
|
|
598
|
+
uri,
|
|
599
|
+
{
|
|
600
|
+
onConnect = () => {},
|
|
601
|
+
onReconnect = () => {},
|
|
602
|
+
onReconnectError = () => {},
|
|
603
|
+
onDisconnect = () => {},
|
|
604
|
+
onEvent = () => {},
|
|
605
|
+
}
|
|
606
|
+
) {
|
|
590
607
|
this.__debug('subscribe', uri);
|
|
591
608
|
|
|
592
609
|
await this.connect();
|
|
593
|
-
await Util.timeout(
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
this.__homeySocket.once('disconnect', (reason) => {
|
|
600
|
-
reject(new Error(reason));
|
|
601
|
-
});
|
|
602
|
-
this.__debug('subscribing', uri);
|
|
603
|
-
this.__homeySocket.emit('subscribe', uri, err => {
|
|
604
|
-
if (err) {
|
|
605
|
-
this.__debug('Failed to subscribe', uri, err);
|
|
606
|
-
return reject(err)
|
|
610
|
+
await Util.timeout(
|
|
611
|
+
new Promise((resolve, reject) => {
|
|
612
|
+
if (this.isConnected() !== true) {
|
|
613
|
+
reject(new Error('Not connected after connect.'));
|
|
614
|
+
return;
|
|
607
615
|
}
|
|
608
|
-
|
|
609
|
-
this.
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
616
|
+
|
|
617
|
+
this.__homeySocket.once('disconnect', reason => {
|
|
618
|
+
reject(new Error(reason));
|
|
619
|
+
});
|
|
620
|
+
this.__debug('subscribing', uri);
|
|
621
|
+
this.__homeySocket.emit('subscribe', uri, err => {
|
|
622
|
+
if (err) {
|
|
623
|
+
this.__debug('Failed to subscribe', uri, err);
|
|
624
|
+
return reject(err);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
this.__debug('subscribed', uri);
|
|
628
|
+
return resolve();
|
|
629
|
+
});
|
|
630
|
+
}),
|
|
631
|
+
10000,
|
|
632
|
+
`Failed to subscribe to ${uri} (Timeout after 10000ms).`
|
|
633
|
+
);
|
|
613
634
|
|
|
614
635
|
// On Connect
|
|
615
636
|
const __onEvent = (event, data) => {
|
|
@@ -627,33 +648,39 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
627
648
|
|
|
628
649
|
// On Reconnect
|
|
629
650
|
const __onReconnect = () => {
|
|
630
|
-
Promise.resolve()
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
this.
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
651
|
+
Promise.resolve()
|
|
652
|
+
.then(async () => {
|
|
653
|
+
await this.connect();
|
|
654
|
+
await Util.timeout(
|
|
655
|
+
new Promise((resolve, reject) => {
|
|
656
|
+
if (this.isConnected() !== true) {
|
|
657
|
+
reject(new Error('Not connected after connect. (Reconnect)'));
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
this.__homeySocket.once('disconnect', reason => {
|
|
662
|
+
reject(new Error(reason));
|
|
663
|
+
});
|
|
664
|
+
this.__debug('subscribing', uri);
|
|
665
|
+
this.__homeySocket.emit('subscribe', uri, err => {
|
|
666
|
+
if (err) {
|
|
667
|
+
this.__debug('Failed to subscribe', uri, err);
|
|
668
|
+
return reject(err);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
this.__debug('subscribed', uri);
|
|
672
|
+
return resolve();
|
|
673
|
+
});
|
|
674
|
+
}),
|
|
675
|
+
10000,
|
|
676
|
+
`Failed to subscribe to ${uri} (Timeout after 10000ms).`
|
|
677
|
+
);
|
|
652
678
|
|
|
653
|
-
|
|
679
|
+
this.__homeySocket.on(uri, __onEvent);
|
|
654
680
|
|
|
655
|
-
|
|
656
|
-
|
|
681
|
+
onReconnect();
|
|
682
|
+
})
|
|
683
|
+
.catch(err => onReconnectError(err));
|
|
657
684
|
};
|
|
658
685
|
this.__socket.on('reconnect', __onReconnect);
|
|
659
686
|
|
|
@@ -708,7 +735,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
708
735
|
this.__debug('SocketIOClient.onReconnect');
|
|
709
736
|
this.emit('reconnect');
|
|
710
737
|
});
|
|
711
|
-
|
|
738
|
+
|
|
712
739
|
this.__socket.on('reconnect_attempt', () => {
|
|
713
740
|
this.__debug(`SocketIOClient.onReconnectAttempt`);
|
|
714
741
|
this.emit('reconnect_attempt');
|
|
@@ -774,11 +801,13 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
774
801
|
this.__socket = null;
|
|
775
802
|
});
|
|
776
803
|
}
|
|
777
|
-
|
|
804
|
+
|
|
778
805
|
// TODO todo what?
|
|
779
806
|
}
|
|
780
807
|
|
|
781
808
|
destroy() {
|
|
809
|
+
this.__destroyed = true;
|
|
810
|
+
|
|
782
811
|
if (this.__homeySocket) {
|
|
783
812
|
this.__homeySocket.removeAllListeners();
|
|
784
813
|
this.__homeySocket.close();
|
|
@@ -794,6 +823,10 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
794
823
|
this.removeAllListeners();
|
|
795
824
|
}
|
|
796
825
|
|
|
826
|
+
isDestroyed() {
|
|
827
|
+
return this.__destroyed;
|
|
828
|
+
}
|
|
829
|
+
|
|
797
830
|
async __handshakeClient() {
|
|
798
831
|
this.__debug('__handshakeClient');
|
|
799
832
|
|
|
@@ -831,30 +864,35 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
831
864
|
|
|
832
865
|
this.__homeySocket.open();
|
|
833
866
|
});
|
|
834
|
-
}
|
|
867
|
+
};
|
|
835
868
|
|
|
836
869
|
const handshakeClient = async () => {
|
|
837
870
|
return new Promise((resolve, reject) => {
|
|
838
|
-
this.__socket.emit(
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
871
|
+
this.__socket.emit(
|
|
872
|
+
'handshakeClient',
|
|
873
|
+
{
|
|
874
|
+
token: this.__token,
|
|
875
|
+
homeyId: this.id,
|
|
876
|
+
},
|
|
877
|
+
(err, result) => {
|
|
878
|
+
if (err) {
|
|
879
|
+
if (err instanceof Error) {
|
|
880
|
+
return reject(err);
|
|
881
|
+
}
|
|
846
882
|
|
|
847
|
-
|
|
848
|
-
|
|
883
|
+
// .statusCode for homey-core .code for homey-client.
|
|
884
|
+
if (typeof err === 'object') {
|
|
885
|
+
return reject(new HomeyAPIError({ error_description: err.message }, err.statusCode || err.code));
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
return reject(new Error(String(err)));
|
|
849
889
|
}
|
|
850
890
|
|
|
851
|
-
return
|
|
891
|
+
return resolve(result);
|
|
852
892
|
}
|
|
853
|
-
|
|
854
|
-
return resolve(result);
|
|
855
|
-
});
|
|
893
|
+
);
|
|
856
894
|
});
|
|
857
|
-
}
|
|
895
|
+
};
|
|
858
896
|
|
|
859
897
|
try {
|
|
860
898
|
const result = await Util.timeout(handshakeClient(), 5000, `Failed to handshake client (Timeout after 5000ms).`);
|
|
@@ -866,7 +904,11 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
866
904
|
await this.logout();
|
|
867
905
|
await this.login();
|
|
868
906
|
|
|
869
|
-
const result = await Util.timeout(
|
|
907
|
+
const result = await Util.timeout(
|
|
908
|
+
handshakeClient(),
|
|
909
|
+
5000,
|
|
910
|
+
`Failed to handshake client (Timeout after 5000ms).`
|
|
911
|
+
);
|
|
870
912
|
|
|
871
913
|
return onResult(result);
|
|
872
914
|
}
|
|
@@ -881,7 +923,7 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
881
923
|
return true;
|
|
882
924
|
}
|
|
883
925
|
|
|
884
|
-
return this.__session.intersectedScopes.some(
|
|
926
|
+
return this.__session.intersectedScopes.some(availableScope => {
|
|
885
927
|
return this.constructor.instanceOfScope(scope, availableScope);
|
|
886
928
|
});
|
|
887
929
|
}
|
|
@@ -898,7 +940,6 @@ class HomeyAPIV3 extends HomeyAPI {
|
|
|
898
940
|
|
|
899
941
|
return scopeOne.indexOf(partsTwo[0]) === 0 && suffixIsEqual;
|
|
900
942
|
}
|
|
901
|
-
|
|
902
943
|
}
|
|
903
944
|
|
|
904
945
|
module.exports = HomeyAPIV3;
|