homey-api 3.0.22 → 3.0.24

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.
@@ -1,13 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const Util = require('../Util');
4
+ const EventEmitter = require('../EventEmitter');
4
5
 
5
6
  /**
6
7
  * An authenticated Homey API. Do not construct this class manually.
7
8
  * @class
8
9
  * @hideconstructor
9
10
  */
10
- class HomeyAPI {
11
+ class HomeyAPI extends EventEmitter {
11
12
 
12
13
  /**
13
14
  * Platforms
@@ -46,6 +47,8 @@ class HomeyAPI {
46
47
  properties = {},
47
48
  debug = () => { },
48
49
  }) {
50
+ super();
51
+
49
52
  // Set Debug Enabled
50
53
  Object.defineProperty(this, '__debugFunction', {
51
54
  value: debug,
@@ -9,10 +9,11 @@ class FlowCardAction extends FlowCardActionV3 {
9
9
 
10
10
  item.id = `${item.uri}:${item.id}`;
11
11
  item.ownerUri = item.uri;
12
- item.ownerId = item.uriObj.id;
13
- item.ownerName = item.uriObj.name;
14
- item.color = item.uriObj.color;
15
- item.iconObj = item.uriObj.iconObj;
12
+ // I dont know how uriObj can be null but it is possible.
13
+ item.ownerId = item.uriObj != null ? item.uriObj.id : null;
14
+ item.ownerName = item.uriObj != null ? item.uriObj.name : null;
15
+ item.color = item.uriObj != null ? item.uriObj.color : null;
16
+ item.iconObj = item.uriObj != null ? item.uriObj.iconObj : null;
16
17
 
17
18
  delete item.uri;
18
19
  delete item.uriObj;
@@ -9,10 +9,11 @@ class FlowCardCondition extends FlowCardConditionV3 {
9
9
 
10
10
  item.id = `${item.uri}:${item.id}`;
11
11
  item.ownerUri = item.uri;
12
- item.ownerId = item.uriObj.id;
13
- item.ownerName = item.uriObj.name;
14
- item.color = item.uriObj.color;
15
- item.iconObj = item.uriObj.iconObj;
12
+ // I dont know how uriObj can be null but it is possible.
13
+ item.ownerId = item.uriObj != null ? item.uriObj.id : null;
14
+ item.ownerName = item.uriObj != null ? item.uriObj.name : null;
15
+ item.color = item.uriObj != null ? item.uriObj.color : null;
16
+ item.iconObj = item.uriObj != null ? item.uriObj.iconObj : null;
16
17
 
17
18
  delete item.uri;
18
19
  delete item.uriObj;
@@ -9,10 +9,11 @@ class FlowCardTrigger extends FlowCardTriggerV3 {
9
9
 
10
10
  item.id = `${item.uri}:${item.id}`;
11
11
  item.ownerUri = item.uri;
12
- item.ownerId = item.uriObj.id;
13
- item.ownerName = item.uriObj.name;
14
- item.color = item.uriObj.color;
15
- item.iconObj = item.uriObj.iconObj;
12
+ // I dont know how uriObj can be null but it is possible.
13
+ item.ownerId = item.uriObj != null ? item.uriObj.id : null;
14
+ item.ownerName = item.uriObj != null ? item.uriObj.name : null;
15
+ item.color = item.uriObj != null ? item.uriObj.color : null;
16
+ item.iconObj = item.uriObj != null ? item.uriObj.iconObj : null;
16
17
 
17
18
  delete item.uri;
18
19
  delete item.uriObj;
@@ -275,7 +275,7 @@ class Manager extends EventEmitter {
275
275
  if (this.homey.isConnected() && $socket === true) {
276
276
  result = await Util.timeout(new Promise((resolve, reject) => {
277
277
  this.__debug(`IO ${operationId}`);
278
- this.homey.__ioNamespace.emit('api', {
278
+ this.homey.__homeySocket.emit('api', {
279
279
  args,
280
280
  operation: operationId,
281
281
  uri: this.uri,
@@ -480,11 +480,17 @@ class Manager extends EventEmitter {
480
480
  this.__debug(`onDisconnect Reason:${reason}`);
481
481
  this.__connected = false;
482
482
 
483
+ // Disable for now. We should probably only set the cache to invalid.
484
+
483
485
  // Clear CRUD Item cache
484
- for (const itemId of Object.keys(this.__cache)) {
485
- this.__cache[itemId] = {};
486
- this.__cacheAllComplete[itemId] = false;
487
- }
486
+ // for (const itemId of Object.keys(this.__cache)) {
487
+ // this.__cache[itemId] = {};
488
+ // this.__cacheAllComplete[itemId] = false;
489
+ // }
490
+ },
491
+ onReconnect: () => {
492
+ this.__debug(`onReconnect`);
493
+ this.__connected = true;
488
494
  },
489
495
  onEvent: (event, data) => {
490
496
  this.__debug('onEvent', event);
@@ -561,7 +567,7 @@ class Manager extends EventEmitter {
561
567
  }
562
568
 
563
569
  /**
564
- * Discconnect from this manager's Socket.io namespace.
570
+ * Disconnect from this manager's Socket.io namespace.
565
571
  * @returns {Promise<void>}
566
572
  */
567
573
  async disconnect() {
@@ -102,12 +102,6 @@ class HomeyAPIV3 extends HomeyAPI {
102
102
  writable: true,
103
103
  });
104
104
 
105
- Object.defineProperty(this, '__connected', {
106
- value: false,
107
- enumerable: false,
108
- writable: true,
109
- });
110
-
111
105
  this.generateManagersFromSpecification();
112
106
  }
113
107
 
@@ -559,7 +553,7 @@ class HomeyAPIV3 extends HomeyAPI {
559
553
  * @returns {Boolean}
560
554
  */
561
555
  isConnected() {
562
- return this.__connected === true;
556
+ return this.__homeySocket && this.__homeySocket.connected;
563
557
  }
564
558
 
565
559
  async subscribe(uri, {
@@ -572,12 +566,12 @@ class HomeyAPIV3 extends HomeyAPI {
572
566
  this.__debug('subscribe', uri);
573
567
 
574
568
  await this.connect();
575
- await new Promise((resolve, reject) => {
576
- this.__ioNamespace.once('disconnect', (reason) => {
569
+ await Util.timeout(new Promise((resolve, reject) => {
570
+ this.__homeySocket.once('disconnect', (reason) => {
577
571
  reject(new Error(reason));
578
572
  });
579
573
  this.__debug('subscribing', uri);
580
- this.__ioNamespace.emit('subscribe', uri, err => {
574
+ this.__homeySocket.emit('subscribe', uri, err => {
581
575
  if (err) {
582
576
  this.__debug('Failed to subscribe', uri, err);
583
577
  return reject(err)
@@ -586,13 +580,13 @@ class HomeyAPIV3 extends HomeyAPI {
586
580
  this.__debug('subscribed', uri);
587
581
  return resolve();
588
582
  });
589
- });
583
+ }), 5000, `Failed to subscribe to ${uri} (Timeout after 5000ms).`);
590
584
 
591
585
  // On Connect
592
586
  const __onEvent = (event, data) => {
593
587
  onEvent(event, data);
594
588
  };
595
- this.__ioNamespace.on(uri, __onEvent);
589
+ this.__homeySocket.on(uri, __onEvent);
596
590
 
597
591
  onConnect();
598
592
 
@@ -600,43 +594,48 @@ class HomeyAPIV3 extends HomeyAPI {
600
594
  const __onDisconnect = reason => {
601
595
  onDisconnect(reason);
602
596
  };
603
- this.__io.on('disconnect', __onDisconnect);
597
+ this.__socket.on('disconnect', __onDisconnect);
604
598
 
605
599
  // On Reconnect
606
600
  const __onReconnect = () => {
607
601
  Promise.resolve().then(async () => {
608
602
  await this.connect();
609
- await new Promise((resolve, reject) => {
610
- this.__ioNamespace.emit('subscribe', uri, err => {
603
+ await Util.timeout(new Promise((resolve, reject) => {
604
+ this.__homeySocket.once('disconnect', (reason) => {
605
+ reject(new Error(reason));
606
+ });
607
+ this.__debug('subscribing', uri);
608
+ this.__homeySocket.emit('subscribe', uri, err => {
611
609
  if (err) {
612
610
  this.__debug('Failed to subscribe', uri, err);
613
611
  return reject(err)
614
612
  }
615
-
613
+
614
+ this.__debug('subscribed', uri);
616
615
  return resolve();
617
616
  });
618
- });
617
+ }), 5000, `Failed to subscribe to ${uri} (Timeout after 5000ms).`);
619
618
 
620
- this.__ioNamespace.on(uri, __onEvent);
619
+ this.__homeySocket.on(uri, __onEvent);
621
620
 
622
621
  onReconnect();
623
622
  }).catch(err => onReconnectError(err));
624
623
  };
625
- this.__io.on('reconnect', __onReconnect);
624
+ this.__socket.on('reconnect', __onReconnect);
626
625
 
627
626
  return {
628
627
  unsubscribe: () => {
629
- this.__ioNamespace.emit('unsubscribe', uri);
630
- this.__ioNamespace.removeListener(uri, __onEvent);
631
- this.__io.removeListener('disconnect', __onDisconnect);
632
- this.__io.removeListener('reconnect', __onReconnect);
628
+ this.__homeySocket.emit('unsubscribe', uri);
629
+ this.__homeySocket.removeListener(uri, __onEvent);
630
+ this.__socket.removeListener('disconnect', __onDisconnect);
631
+ this.__socket.removeListener('reconnect', __onReconnect);
633
632
  },
634
633
  };
635
634
  }
636
635
 
637
636
  async connect() {
638
- if (!this.io) {
639
- this.io = Promise.resolve().then(async () => {
637
+ if (!this.__connectPromise) {
638
+ this.__connectPromise = Promise.resolve().then(async () => {
640
639
  // Ensure Base URL
641
640
  const baseUrl = await this.baseUrl;
642
641
 
@@ -645,8 +644,9 @@ class HomeyAPIV3 extends HomeyAPI {
645
644
 
646
645
  return new Promise((resolve, reject) => {
647
646
  this.__debug(`SocketIOClient ${baseUrl}`);
648
- this.__io = SocketIOClient(baseUrl, {
649
- autoConnect: true,
647
+
648
+ this.__socket = SocketIOClient(baseUrl, {
649
+ autoConnect: false,
650
650
  transports: ['websocket'],
651
651
  transportOptions: {
652
652
  pingTimeout: 8000,
@@ -655,65 +655,40 @@ class HomeyAPIV3 extends HomeyAPI {
655
655
  reconnection: true,
656
656
  });
657
657
 
658
- this.__io.on('disconnect', reason => {
658
+ this.__socket.on('disconnect', reason => {
659
659
  this.__debug('SocketIOClient.onDisconnect', reason);
660
- this.__connected = false;
661
-
662
- if (this.__ioNamespace) {
663
- this.__ioNamespace.disconnect();
664
- this.__ioNamespace.destroy();
665
- this.__ioNamespace.removeAllListeners();
666
- }
667
-
668
- if (reason === 'io server disconnect') {
669
- // The disconnect was initiated by the server.
670
- this.__io.connect();
671
- }
672
-
673
- reject(new Error('Disconnected'));
674
660
  });
675
661
 
676
- this.__io.on('error', err => {
662
+ this.__socket.on('error', err => {
677
663
  this.__debug('SocketIOClient.onError', err.message);
678
664
  });
679
665
 
680
- this.__io.on('reconnect', () => {
666
+ this.__socket.on('reconnect', () => {
681
667
  this.__debug('SocketIOClient.onReconnect');
682
- this.__handshakeClient()
683
- .then(() => {
684
- this.__debug('SocketIOClient.onReconnect.onHandshakeClientSuccess');
685
- this.__connected = true;
686
- resolve();
687
- })
688
- .catch(err => {
689
- this.__debug('SocketIOClient.onReconnect.onHandshakeClientError', err.message);
690
- reject(err);
691
- });
692
668
  });
693
669
 
694
- this.__io.on('reconnect_attempt', () => {
670
+ this.__socket.on('reconnect_attempt', () => {
695
671
  this.__debug(`SocketIOClient.onReconnectAttempt`);
696
672
  });
697
673
 
698
- this.__io.on('reconnecting', attempt => {
674
+ this.__socket.on('reconnecting', attempt => {
699
675
  this.__debug(`SocketIOClient.onReconnecting (Attempt #${attempt})`);
700
676
  });
701
677
 
702
- this.__io.on('reconnect_error', err => {
678
+ this.__socket.on('reconnect_error', err => {
703
679
  this.__debug('SocketIOClient.onReconnectError', err.message);
704
680
  });
705
681
 
706
- this.__io.on('connect_error', err => {
682
+ this.__socket.on('connect_error', err => {
707
683
  this.__debug('SocketIOClient.onConnectError', err.message);
708
684
  reject(err);
709
685
  });
710
686
 
711
- this.__io.on('connect', () => {
687
+ this.__socket.on('connect', () => {
712
688
  this.__debug('SocketIOClient.onConnect');
713
689
  this.__handshakeClient()
714
690
  .then(() => {
715
691
  this.__debug('SocketIOClient.onConnect.onHandshakeClientSuccess');
716
- this.__connected = true;
717
692
  resolve();
718
693
  })
719
694
  .catch(err => {
@@ -721,34 +696,39 @@ class HomeyAPIV3 extends HomeyAPI {
721
696
  reject(err);
722
697
  });
723
698
  });
724
- // this.__io.connect();
699
+
700
+ this.__socket.open();
725
701
  });
726
702
  });
727
703
 
728
- this.io.catch(err => {
704
+ this.__connectPromise.catch(err => {
729
705
  this.__debug('SocketIOClient Error', err.message);
706
+ delete this.__connectPromise;
730
707
  });
731
708
  }
732
709
 
733
- return this.io;
710
+ return this.__connectPromise;
734
711
  }
735
712
 
736
713
  async disconnect() {
737
- if (this.__io) {
714
+ // Should we wait for connect here?
715
+
716
+ if (this.__socket) {
738
717
  await new Promise(resolve => {
739
- this.__io.once('disconnect', resolve());
740
- this.__io.disconnect();
741
- this.__io.removeAllListeners();
742
- this.__io = null;
718
+ this.__socket.once('disconnect', resolve());
719
+ this.__socket.disconnect();
720
+ this.__socket.removeAllListeners();
721
+ this.__socket = null;
743
722
  });
744
723
  }
724
+
745
725
  // TODO todo what?
746
726
  }
747
727
 
748
728
  destroy() {
749
- if (this.__io) {
750
- this.__io.removeAllListeners();
751
- this.__io.close();
729
+ if (this.__socket) {
730
+ this.__socket.removeAllListeners();
731
+ this.__socket.close();
752
732
  }
753
733
  }
754
734
 
@@ -756,7 +736,7 @@ class HomeyAPIV3 extends HomeyAPI {
756
736
  this.__debug('__handshakeClient');
757
737
 
758
738
  return new Promise((resolve, reject) => {
759
- this.__io.emit('handshakeClient', {
739
+ this.__socket.emit('handshakeClient', {
760
740
  token: this.__token,
761
741
  homeyId: this.id,
762
742
  }, (err, result) => {
@@ -772,7 +752,7 @@ class HomeyAPIV3 extends HomeyAPI {
772
752
  await this.login();
773
753
 
774
754
  return new Promise((resolve, reject) => {
775
- this.__io.emit('handshakeClient', {
755
+ this.__socket.emit('handshakeClient', {
776
756
  token: this.__token,
777
757
  homeyId: this.id,
778
758
  }, (err, result) => {
@@ -788,43 +768,35 @@ class HomeyAPIV3 extends HomeyAPI {
788
768
  this.__debug('SocketIOClient.onHandshakeClientSuccess', `Namespace: ${namespace}`);
789
769
 
790
770
  return new Promise((resolve, reject) => {
791
- this.__ioNamespace = this.__io.io.socket(namespace);
792
-
793
- this.__debug(this.__ioNamespace);
771
+ this.__homeySocket = this.__socket.io.socket(namespace);
794
772
 
795
- // Assuming this.__ioNamespace is your namespace object
796
- if (this.__ioNamespace.connected) {
797
- this.__debug(`SocketIOClient.Namespace[${namespace}].connected`);
798
- }
799
-
800
- this.__ioNamespace.once('connect', () => {
773
+ this.__homeySocket.once('connect', () => {
801
774
  this.__debug(`SocketIOClient.Namespace[${namespace}].onConnect`);
802
775
  resolve();
803
776
  });
804
777
 
805
- this.__ioNamespace.once('connect_error', err => {
778
+ this.__homeySocket.once('connect_error', err => {
806
779
  this.__debug(`SocketIOClient.Namespace[${namespace}].onConnectError`, err.message);
807
780
  reject(err);
808
781
  });
809
782
 
810
- this.__ioNamespace.on('reconnecting', attempt => {
783
+ this.__homeySocket.on('disconnect', reason => {
784
+ this.__debug(`SocketIOClient.Namespace[${namespace}].onDisconnect`, reason);
785
+ });
786
+
787
+ this.__homeySocket.on('reconnecting', attempt => {
811
788
  this.__debug(`SocketIOClient.Namespace[${namespace}].onReconnecting (Attempt #${attempt})`);
812
789
  });
813
790
 
814
- this.__ioNamespace.on('reconnect', () => {
791
+ this.__homeySocket.on('reconnect', () => {
815
792
  this.__debug(`SocketIOClient.Namespace[${namespace}].onReconnect`);
816
793
  });
817
794
 
818
- this.__ioNamespace.on('reconnect_error', err => {
795
+ this.__homeySocket.on('reconnect_error', err => {
819
796
  this.__debug(`SocketIOClient.Namespace[${namespace}].onReconnectError`, err.message);
820
797
  });
821
798
 
822
- this.__ioNamespace.on('disconnect', reason => {
823
- this.__debug(`SocketIOClient.Namespace[${namespace}].onDisconnect`, reason);
824
- });
825
-
826
- this.__debug(`SocketIOClient.Namespace[${namespace}].disconnected`, this.__ioNamespace.disconnected);
827
- this.__debug(`SocketIOClient.Namespace[${namespace}].connected`, this.__ioNamespace.connected);
799
+ this.__homeySocket.open();
828
800
  });
829
801
  });
830
802
  }
package/lib/Util.js CHANGED
@@ -56,16 +56,24 @@ class Util {
56
56
  static async timeout(promise, timeoutMillis = 5000, message = `Timeout after ${timeoutMillis}ms`) {
57
57
  const timeoutError = new APIErrorTimeout(message);
58
58
  let timeoutRef;
59
- return Promise.race([
59
+
60
+ const returnPromise = Promise.race([
60
61
  promise,
61
62
  new Promise((_, reject) => {
62
63
  timeoutRef = setTimeout(() => {
63
64
  reject(timeoutError);
64
65
  }, timeoutMillis);
65
66
  }),
66
- ]).finally(() => {
67
- clearTimeout(timeoutRef);
68
- });
67
+ ]);
68
+
69
+ returnPromise
70
+ // eslint-disable-next-line no-unused-vars
71
+ .catch(err => { })
72
+ .finally(() => {
73
+ clearTimeout(timeoutRef);
74
+ });
75
+
76
+ return returnPromise;
69
77
  }
70
78
 
71
79
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homey-api",
3
- "version": "3.0.22",
3
+ "version": "3.0.24",
4
4
  "description": "Homey API",
5
5
  "main": "index.js",
6
6
  "files": [