homebridge-eosstb 2.2.8 → 2.2.9
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/CHANGELOG.md +5 -0
- package/index.js +120 -37
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,11 @@ Please restart Homebridge after every plugin update.
|
|
|
10
10
|
* Implement refreshToken capabilities
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
## 2.2.9 (2023-05-29)
|
|
14
|
+
* Fixed bug with access token expiring causing 401 unauthorised errors when refreshing channel list
|
|
15
|
+
* Cleaned up some code
|
|
16
|
+
|
|
17
|
+
|
|
13
18
|
## 2.2.8 (2023-05-22)
|
|
14
19
|
* Updated iOS version references
|
|
15
20
|
* Fixed bug causing Homebridge crash when master channel list is not yet loaded
|
package/index.js
CHANGED
|
@@ -352,18 +352,28 @@ class stbPlatform {
|
|
|
352
352
|
|
|
353
353
|
|
|
354
354
|
this.checkChannelListInterval = setInterval(() => {
|
|
355
|
-
//
|
|
356
|
-
this.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
355
|
+
// check if master channel list has expired. If it has, refresh auth token, then refresh channel list
|
|
356
|
+
if (this.config.debugLevel >= 1) { this.log.warn('stbPlatform: checkChannelListInterval Start'); }
|
|
357
|
+
if (this.masterChannelListExpiryDate <= Date.now()) {
|
|
358
|
+
// must check and refresh auth token before each call to refresh master channel list
|
|
359
|
+
this.refreshAccessToken()
|
|
360
|
+
.then(response => {
|
|
361
|
+
if (this.config.debugLevel >= 1) { this.log.warn('stbPlatform: refreshAccessToken completed OK'); }
|
|
362
|
+
return this.refreshMasterChannelList()
|
|
363
|
+
})
|
|
364
|
+
.then(response => {
|
|
365
|
+
if (this.config.debugLevel >= 1) { this.log.warn('stbPlatform: refreshMasterChannelList completed OK'); }
|
|
366
|
+
return true
|
|
367
|
+
})
|
|
368
|
+
.catch(error => {
|
|
369
|
+
if (error.code) {
|
|
370
|
+
this.log.warn('stbPlatform: checkChannelListInterval Error', (error.syscall || '') + ' ' + (error.code || '') + ' ' + (error.config.url || error.hostname || ''));
|
|
371
|
+
} else {
|
|
372
|
+
this.log.warn('stbPlatform: checkChannelListInterval Error', error);
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
if (this.config.debugLevel >= 1) { this.log.warn('stbPlatform: checkChannelListInterval end'); }
|
|
376
|
+
}
|
|
367
377
|
}, MASTER_CHANNEL_LIST_REFRESH_CHECK_INTERVAL_S * 1000 ) // need to pass ms
|
|
368
378
|
|
|
369
379
|
debug('stbPlatform:apievent :: didFinishLaunching end of code block')
|
|
@@ -581,17 +591,17 @@ class stbPlatform {
|
|
|
581
591
|
.then((objStbDevices) => {
|
|
582
592
|
this.log('Discovery completed');
|
|
583
593
|
this.log.debug('%s: ++++++ step 8: devices found:', watchdogInstance, this.devices.length)
|
|
584
|
-
this.log.debug('%s: ++++++ step 8: calling
|
|
594
|
+
this.log.debug('%s: ++++++ step 8: calling getMqttToken', watchdogInstance)
|
|
585
595
|
errorTitle = 'Failed to start mqtt session';
|
|
586
|
-
debug(debugPrefix + 'calling
|
|
587
|
-
return this.
|
|
596
|
+
debug(debugPrefix + 'calling getMqttToken')
|
|
597
|
+
return this.getMqttToken(this.session.username, this.session.accessToken, this.session.householdId);
|
|
588
598
|
})
|
|
589
|
-
.then((
|
|
590
|
-
this.log.debug('%s: ++++++ step 9:
|
|
599
|
+
.then((mqttToken) => {
|
|
600
|
+
this.log.debug('%s: ++++++ step 9: getMqttToken token was retrieved, token %s', watchdogInstance, mqttToken)
|
|
591
601
|
this.log.debug('%s: ++++++ step 9: start mqtt client', watchdogInstance)
|
|
592
602
|
debug(debugPrefix + 'calling startMqttClient')
|
|
593
|
-
return this.startMqttClient(this, this.session.householdId,
|
|
594
|
-
})
|
|
603
|
+
return this.startMqttClient(this, this.session.householdId, mqttToken); // returns true
|
|
604
|
+
})
|
|
595
605
|
.catch(errorReason => {
|
|
596
606
|
// log any errors and set the currentSessionState
|
|
597
607
|
this.log.warn(errorTitle + ' - %s', errorReason);
|
|
@@ -695,6 +705,73 @@ class stbPlatform {
|
|
|
695
705
|
}
|
|
696
706
|
|
|
697
707
|
|
|
708
|
+
// get a new access token
|
|
709
|
+
async refreshAccessToken() {
|
|
710
|
+
return new Promise((resolve, reject) => {
|
|
711
|
+
|
|
712
|
+
// exit immediately if access token has not expired
|
|
713
|
+
if (this.session.accessTokenExpiry > Date.now()) {
|
|
714
|
+
if (this.config.debugLevel >= 1) { this.log.warn('refreshAccessToken: Access token has not expired yet. Next refresh will occur after %s', this.session.accessTokenExpiry.toLocaleString()); }
|
|
715
|
+
resolve(true);
|
|
716
|
+
return
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (this.config.debugLevel >= 1) { this.log.warn('refreshAccessToken: Access token has expired at %s. Requesting refresh', this.session.accessTokenExpiry.toLocaleString()); }
|
|
720
|
+
|
|
721
|
+
const axiosConfig = {
|
|
722
|
+
method: 'POST',
|
|
723
|
+
// https://prod.spark.sunrisetv.ch/auth-service/v1/authorization/refresh
|
|
724
|
+
url: countryBaseUrlArray[this.config.country.toLowerCase()] + '/auth-service/v1/authorization/refresh',
|
|
725
|
+
headers: {
|
|
726
|
+
'x-oesp-username': this.session.username
|
|
727
|
+
},
|
|
728
|
+
jar: cookieJar,
|
|
729
|
+
data: {
|
|
730
|
+
refreshToken: this.session.refreshToken,
|
|
731
|
+
username: this.config.username
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
if (this.config.debugLevel >=1) { this.log.warn('refreshAccessToken: Post auth refresh request to',axiosConfig.url); }
|
|
736
|
+
axiosWS(axiosConfig)
|
|
737
|
+
.then(response => {
|
|
738
|
+
if (this.config.debugLevel >= 2) {
|
|
739
|
+
this.log('refreshAccessToken: auth refresh response:',response.status, response.statusText);
|
|
740
|
+
this.log('refreshAccessToken: response data (saved to this.session):');
|
|
741
|
+
this.log(response.data);
|
|
742
|
+
//this.log(response.headers);
|
|
743
|
+
}
|
|
744
|
+
this.session = response.data;
|
|
745
|
+
|
|
746
|
+
// add an expiry date for the access token: 2 min (120000ms) after created date
|
|
747
|
+
this.session.accessTokenExpiry = new Date(new Date().getTime() + 2*60000);
|
|
748
|
+
|
|
749
|
+
// check if householdId exists, if so, we have authenticated ok
|
|
750
|
+
if (this.session.householdId) { currentSessionState = sessionState.AUTHENTICATED; }
|
|
751
|
+
this.log.debug('Session username:', this.session.username);
|
|
752
|
+
this.log.debug('Session householdId:', this.session.householdId);
|
|
753
|
+
this.log.debug('Session accessToken:', this.session.accessToken);
|
|
754
|
+
this.log.debug('Session accessTokenExpiry:', this.session.accessTokenExpiry);
|
|
755
|
+
this.log.debug('Session refreshToken:', this.session.refreshToken);
|
|
756
|
+
this.log.debug('Session refreshTokenExpiry:', this.session.refreshTokenExpiry);
|
|
757
|
+
// Robustness: Observed that new APLSTB Apollo box on NL did not always return username during session logon, so store username from settings if missing
|
|
758
|
+
if (this.session.username == '') {
|
|
759
|
+
this.log.debug('Session username empty, setting to %s', this.config.username);
|
|
760
|
+
this.session.username = this.config.username;
|
|
761
|
+
} else {
|
|
762
|
+
this.log.debug('Session username exists: %s', this.session.username);
|
|
763
|
+
}
|
|
764
|
+
currentSessionState = sessionState.CONNECTED;
|
|
765
|
+
this.currentStatusFault = Characteristic.StatusFault.NO_FAULT;
|
|
766
|
+
resolve(this.session.householdId) // resolve the promise with the householdId
|
|
767
|
+
})
|
|
768
|
+
.catch(error => {
|
|
769
|
+
this.log.debug('refreshAccessToken: error:', error);
|
|
770
|
+
reject(error); // reject the promise and return the error
|
|
771
|
+
});
|
|
772
|
+
})
|
|
773
|
+
}
|
|
774
|
+
|
|
698
775
|
|
|
699
776
|
// select the right session to create
|
|
700
777
|
async createSession(country) {
|
|
@@ -785,11 +862,16 @@ class stbPlatform {
|
|
|
785
862
|
this.log(response.data);
|
|
786
863
|
}
|
|
787
864
|
this.session = response.data;
|
|
865
|
+
|
|
866
|
+
// add an expiry date for the access token: 2 min (120000ms) after created date
|
|
867
|
+
this.session.accessTokenExpiry = new Date(new Date().getTime() + 2*60000);
|
|
868
|
+
|
|
788
869
|
// check if householdId exists, if so, we have authenticated ok
|
|
789
870
|
if (this.session.householdId) { currentSessionState = sessionState.AUTHENTICATED; }
|
|
790
871
|
this.log.debug('Session username:', this.session.username);
|
|
791
872
|
this.log.debug('Session householdId:', this.session.householdId);
|
|
792
873
|
this.log.debug('Session accessToken:', this.session.accessToken);
|
|
874
|
+
this.log.debug('Session accessTokenExpiry:', this.session.accessTokenExpiry);
|
|
793
875
|
this.log.debug('Session refreshToken:', this.session.refreshToken);
|
|
794
876
|
this.log.debug('Session refreshTokenExpiry:', this.session.refreshTokenExpiry);
|
|
795
877
|
// Robustness: Observed that new APLSTB Apollo box on NL did not always return username during session logon, so store username from settings if missing
|
|
@@ -812,8 +894,10 @@ class stbPlatform {
|
|
|
812
894
|
errReason = 'try again later: ' + error.response.status + ' ' + (error.response.statusText || '');
|
|
813
895
|
} else if (error.response && error.response.status) {
|
|
814
896
|
errReason = 'check your internet connection: ' + error.response.status + ' ' + (error.response.statusText || '');
|
|
815
|
-
} else {
|
|
897
|
+
} else if (error.code) {
|
|
816
898
|
errReason = 'check your internet connection: ' + error.code + ' ' + (error.hostname || '');
|
|
899
|
+
} else {
|
|
900
|
+
errReason = 'unexpected error: ' + error;
|
|
817
901
|
}
|
|
818
902
|
//this.log('%s %s', errText, (errReason || ''));
|
|
819
903
|
this.log.debug('getSession: error:', error);
|
|
@@ -1353,7 +1437,7 @@ class stbPlatform {
|
|
|
1353
1437
|
|
|
1354
1438
|
// exit immediately if channel list has not expired
|
|
1355
1439
|
if (this.masterChannelListExpiryDate > Date.now()) {
|
|
1356
|
-
if (this.config.debugLevel
|
|
1440
|
+
if (this.config.debugLevel >= 1) { this.log.warn('refreshMasterChannelList: Master channel list has not expired yet. Next refresh will occur after %s', this.masterChannelListExpiryDate.toLocaleString()); }
|
|
1357
1441
|
resolve(true);
|
|
1358
1442
|
return
|
|
1359
1443
|
}
|
|
@@ -1987,28 +2071,28 @@ class stbPlatform {
|
|
|
1987
2071
|
// START session handler mqtt
|
|
1988
2072
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1989
2073
|
|
|
1990
|
-
// get
|
|
1991
|
-
async
|
|
2074
|
+
// get the mqtt token
|
|
2075
|
+
async getMqttToken(oespUsername, accessToken, householdId){
|
|
1992
2076
|
return new Promise((resolve, reject) => {
|
|
1993
|
-
this.log.debug("Getting
|
|
2077
|
+
this.log.debug("Getting mqtt token for householdId %s", householdId);
|
|
1994
2078
|
// get a JSON web token from the supplied accessToken and householdId
|
|
1995
|
-
if (this.config.debugLevel > 1) { this.log.warn('
|
|
2079
|
+
if (this.config.debugLevel > 1) { this.log.warn('getMqttToken'); }
|
|
1996
2080
|
// robustness checks
|
|
1997
2081
|
if (currentSessionState !== sessionState.CONNECTED) {
|
|
1998
|
-
this.log.warn('Cannot get
|
|
2082
|
+
this.log.warn('Cannot get mqtt token: currentSessionState incorrect:', currentSessionState);
|
|
1999
2083
|
return false;
|
|
2000
2084
|
}
|
|
2001
2085
|
if (!accessToken) {
|
|
2002
|
-
this.log.warn('Cannot get
|
|
2086
|
+
this.log.warn('Cannot get mqtt token: accessToken not set');
|
|
2003
2087
|
return false;
|
|
2004
2088
|
}
|
|
2005
2089
|
|
|
2006
|
-
//this.log.warn('
|
|
2090
|
+
//this.log.warn('getMqttToken disabled while I build channel list');
|
|
2007
2091
|
//return false;
|
|
2008
2092
|
|
|
2009
|
-
const
|
|
2093
|
+
const mqttAxiosConfig = {
|
|
2010
2094
|
method: 'GET',
|
|
2011
|
-
url: countryBaseUrlArray[this.config.country.toLowerCase()] + '/tokens/jwt',
|
|
2095
|
+
//url: countryBaseUrlArray[this.config.country.toLowerCase()] + '/tokens/jwt', prior to October 2022
|
|
2012
2096
|
// examples of auth-service/v1/mqtt/token urls:
|
|
2013
2097
|
// https://prod.spark.ziggogo.tv/auth-service/v1/mqtt/token
|
|
2014
2098
|
// https://prod.spark.sunrisetv.ch/auth-service/v1/mqtt/token
|
|
@@ -2018,23 +2102,22 @@ class stbPlatform {
|
|
|
2018
2102
|
'X-OESP-Username': oespUsername,
|
|
2019
2103
|
}
|
|
2020
2104
|
};
|
|
2021
|
-
this.log.debug("
|
|
2022
|
-
axiosWS(
|
|
2105
|
+
this.log.debug("getMqttToken: mqttAxiosConfig:", mqttAxiosConfig)
|
|
2106
|
+
axiosWS(mqttAxiosConfig)
|
|
2023
2107
|
.then(response => {
|
|
2024
2108
|
if (this.config.debugLevel > 0) {
|
|
2025
|
-
this.log.warn("
|
|
2109
|
+
this.log.warn("getMqttToken: response.data:", response.data)
|
|
2026
2110
|
}
|
|
2027
|
-
//this.jwtToken = response.data.token; // store the token
|
|
2028
2111
|
mqttUsername = householdId; // used in sendKey to ensure that mqtt is connected
|
|
2029
|
-
resolve(response.data.token); // resolve with the
|
|
2112
|
+
resolve(response.data.token); // resolve with the token
|
|
2030
2113
|
//this.startMqttClient(this, householdId, response.data.token); // this starts the mqtt session
|
|
2031
2114
|
|
|
2032
2115
|
})
|
|
2033
2116
|
.catch(error => {
|
|
2034
|
-
this.log.debug('
|
|
2117
|
+
this.log.debug('getMqttToken error details:', error);
|
|
2035
2118
|
// set session flag to disconnected to force a session reconnect
|
|
2036
2119
|
currentSessionState = sessionState.DISCONNECTED;
|
|
2037
|
-
reject('Failed to get
|
|
2120
|
+
reject('Failed to get mqtt token: ', error.code + ' ' + (error.hostname || ''));
|
|
2038
2121
|
});
|
|
2039
2122
|
})
|
|
2040
2123
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"displayName": "Homebridge EOSSTB",
|
|
4
4
|
"description": "homebridge-plugin - Add your set-top box to Homekit (for Magenta AT, Telenet BE, Sunrise CH, Virgin Media GB & IE, Ziggo NL)",
|
|
5
5
|
"author": "Jochen Siegenthaler (https://github.com/jsiegenthaler/)",
|
|
6
|
-
"version": "2.2.
|
|
6
|
+
"version": "2.2.9",
|
|
7
7
|
"platformname": "eosstb",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"axios-cookiejar-support": "^4.0.6",
|