homebridge-eosstb 2.4.0-alpha.4 → 2.4.0-alpha.6
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.
Potentially problematic release.
This version of homebridge-eosstb might be problematic. Click here for more details.
- package/CHANGELOG.md +14 -1
- package/index.js +611 -796
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -106,7 +106,7 @@ const SETTOPBOX_NAME_MINLEN = 3; // min len of the set-top box name
|
|
|
106
106
|
const SETTOPBOX_NAME_MAXLEN = 14; // max len of the set-top box name
|
|
107
107
|
|
|
108
108
|
// state constants. Need to add an array for any characteristic that is not an array, or the array is not contiguous
|
|
109
|
-
const sessionState = {
|
|
109
|
+
const sessionState = Object.freeze({
|
|
110
110
|
DISCONNECTED: 0,
|
|
111
111
|
LOADING: 1,
|
|
112
112
|
LOGGING_IN: 2,
|
|
@@ -114,15 +114,14 @@ const sessionState = {
|
|
|
114
114
|
VERIFYING: 4,
|
|
115
115
|
AUTHENTICATED: 5,
|
|
116
116
|
CONNECTED: 6,
|
|
117
|
-
};
|
|
118
|
-
const powerStateName = ["OFF", "ON"]; // custom
|
|
119
|
-
const recordingState = {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Object.freeze(
|
|
125
|
-
Object.freeze(statusActiveName);
|
|
117
|
+
});
|
|
118
|
+
const powerStateName = Object.freeze(["OFF", "ON"]); // custom
|
|
119
|
+
const recordingState = Object.freeze({
|
|
120
|
+
IDLE: 0,
|
|
121
|
+
ONGOING_NDVR: 1,
|
|
122
|
+
ONGOING_LOCALDVR: 2,
|
|
123
|
+
}); // custom
|
|
124
|
+
const statusActiveName = Object.freeze(["NOT_ACTIVE", "ACTIVE"]); // custom, characteristic is boolean, not an array
|
|
126
125
|
|
|
127
126
|
// exec spawns child process to run a bash script
|
|
128
127
|
const exec = require("child_process").exec;
|
|
@@ -136,6 +135,7 @@ let currentSessionState;
|
|
|
136
135
|
let isShuttingDown = false; // to handle reboots cleanly
|
|
137
136
|
|
|
138
137
|
let Accessory, Characteristic, Service, Categories, UUID;
|
|
138
|
+
let CHAR_NAMES; // declared here, populated once Characteristic is available
|
|
139
139
|
|
|
140
140
|
// Returns the path to the system Chromium/Chrome executable.
|
|
141
141
|
// Used by getSessionCH() which requires puppeteer-core (no bundled browser).
|
|
@@ -190,10 +190,48 @@ function getTimestampInSeconds() {
|
|
|
190
190
|
// transform current media state of 0,1,2,4,5 to 1,2,3,4,5 to work with Object.keys
|
|
191
191
|
function currentMediaStateName(currentMediaState) {
|
|
192
192
|
let i = currentMediaState + 1; // get the new index
|
|
193
|
+
// modify if > 3 to get 1,2,3,4,5
|
|
193
194
|
if (i > 3) {
|
|
194
195
|
i = i - 1;
|
|
195
|
-
}
|
|
196
|
-
return
|
|
196
|
+
}
|
|
197
|
+
return CHAR_NAMES.CurrentMediaState[i];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// helper function to create consistent log text for set-to vs changed-from
|
|
201
|
+
function logCharValueChange(
|
|
202
|
+
log,
|
|
203
|
+
name,
|
|
204
|
+
label,
|
|
205
|
+
input,
|
|
206
|
+
previousValue,
|
|
207
|
+
previousLabel,
|
|
208
|
+
currentValue,
|
|
209
|
+
currentLabel,
|
|
210
|
+
) {
|
|
211
|
+
if (previousValue === null || previousValue === undefined) {
|
|
212
|
+
log("%s: %s set to %s [%s]", name, label, currentValue, currentLabel);
|
|
213
|
+
} else if (input === null || input === undefined) {
|
|
214
|
+
log(
|
|
215
|
+
"%s: %s changed from %s [%s] to %s [%s]",
|
|
216
|
+
name,
|
|
217
|
+
label,
|
|
218
|
+
previousValue,
|
|
219
|
+
previousLabel,
|
|
220
|
+
currentValue,
|
|
221
|
+
currentLabel,
|
|
222
|
+
);
|
|
223
|
+
} else {
|
|
224
|
+
log(
|
|
225
|
+
"%s: %s changed on input %s from %s [%s] to %s [%s]",
|
|
226
|
+
name,
|
|
227
|
+
label,
|
|
228
|
+
input,
|
|
229
|
+
previousValue,
|
|
230
|
+
previousLabel,
|
|
231
|
+
currentValue,
|
|
232
|
+
currentLabel,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
197
235
|
}
|
|
198
236
|
|
|
199
237
|
// clean a name so it is acceptable for HomeKit
|
|
@@ -271,7 +309,24 @@ module.exports = (api) => {
|
|
|
271
309
|
Service = api.hap.Service;
|
|
272
310
|
Categories = api.hap.Categories;
|
|
273
311
|
UUID = api.hap.uuid;
|
|
312
|
+
|
|
313
|
+
// Build CHAR_NAMES here, now that Characteristic is assigned
|
|
314
|
+
// Cached key name arrays for logging. These enums never change at runtime so build them once.
|
|
315
|
+
CHAR_NAMES = Object.freeze({
|
|
316
|
+
StatusFault: Object.keys(Characteristic.StatusFault),
|
|
317
|
+
ProgramMode: Object.keys(Characteristic.ProgramMode),
|
|
318
|
+
InputDeviceType: Object.keys(Characteristic.InputDeviceType),
|
|
319
|
+
InputSourceType: Object.keys(Characteristic.InputSourceType),
|
|
320
|
+
ClosedCaptions: Object.keys(Characteristic.ClosedCaptions),
|
|
321
|
+
PictureMode: Object.keys(Characteristic.PictureMode),
|
|
322
|
+
InUse: Object.keys(Characteristic.InUse),
|
|
323
|
+
CurrentVisibilityState: Object.keys(Characteristic.CurrentVisibilityState),
|
|
324
|
+
CurrentMediaState: Object.keys(Characteristic.CurrentMediaState),
|
|
325
|
+
TargetMediaState: Object.keys(Characteristic.TargetMediaState),
|
|
326
|
+
});
|
|
327
|
+
|
|
274
328
|
const isDynamicPlatform = true;
|
|
329
|
+
|
|
275
330
|
api.registerPlatform(
|
|
276
331
|
PLUGIN_NAME,
|
|
277
332
|
PLATFORM_NAME,
|
|
@@ -291,6 +346,7 @@ class StbPlatform {
|
|
|
291
346
|
this.stbDevices = []; // store stbDevice in this.stbDevices
|
|
292
347
|
this.masterChannelList = [];
|
|
293
348
|
this.isDev = config.devMode === true;
|
|
349
|
+
this.debugLevel = this.config.debugLevel || 0; // debugLevel defaults to 0 (minimum)
|
|
294
350
|
|
|
295
351
|
// show some useful version info
|
|
296
352
|
this.log.info(
|
|
@@ -349,7 +405,7 @@ class StbPlatform {
|
|
|
349
405
|
*/
|
|
350
406
|
//this.api.on('didFinishLaunching', () => {
|
|
351
407
|
this.api.on("didFinishLaunching", async () => {
|
|
352
|
-
if (this.
|
|
408
|
+
if (this.debugLevel > 2) {
|
|
353
409
|
this.log.warn("API event: didFinishLaunching");
|
|
354
410
|
}
|
|
355
411
|
debug("StbPlatform:apievent :: didFinishLaunching");
|
|
@@ -374,20 +430,20 @@ class StbPlatform {
|
|
|
374
430
|
// check for a channel list update every MASTER_CHANNEL_LIST_REFRESH_CHECK_INTERVAL_S seconds
|
|
375
431
|
this.checkChannelListInterval = setInterval(() => {
|
|
376
432
|
// check if master channel list has expired. If it has, refresh auth token, then refresh channel list
|
|
377
|
-
if (this.
|
|
433
|
+
if (this.debugLevel >= 1) {
|
|
378
434
|
this.log.warn("StbPlatform: checkChannelListInterval Start");
|
|
379
435
|
}
|
|
380
436
|
if (this.masterChannelListExpiryDate <= Date.now()) {
|
|
381
437
|
// must check and refresh auth token before each call to refresh master channel list
|
|
382
438
|
this.refreshAccessToken()
|
|
383
439
|
.then((response) => {
|
|
384
|
-
if (this.
|
|
440
|
+
if (this.debugLevel >= 1) {
|
|
385
441
|
this.log.warn("StbPlatform: refreshAccessToken completed OK");
|
|
386
442
|
}
|
|
387
443
|
return this.refreshMasterChannelList();
|
|
388
444
|
})
|
|
389
445
|
.then((response) => {
|
|
390
|
-
if (this.
|
|
446
|
+
if (this.debugLevel >= 1) {
|
|
391
447
|
this.log.warn(
|
|
392
448
|
"StbPlatform: refreshMasterChannelList completed OK",
|
|
393
449
|
);
|
|
@@ -411,7 +467,7 @@ class StbPlatform {
|
|
|
411
467
|
);
|
|
412
468
|
}
|
|
413
469
|
});
|
|
414
|
-
if (this.
|
|
470
|
+
if (this.debugLevel >= 1) {
|
|
415
471
|
this.log.warn("StbPlatform: checkChannelListInterval End");
|
|
416
472
|
}
|
|
417
473
|
}
|
|
@@ -426,7 +482,7 @@ class StbPlatform {
|
|
|
426
482
|
*/
|
|
427
483
|
this.api.on("shutdown", () => {
|
|
428
484
|
debug("StbPlatform:apievent :: shutdown");
|
|
429
|
-
if (this.
|
|
485
|
+
if (this.debugLevel > 2) {
|
|
430
486
|
this.log.warn("API event: shutdown");
|
|
431
487
|
}
|
|
432
488
|
isShuttingDown = true;
|
|
@@ -521,7 +577,7 @@ class StbPlatform {
|
|
|
521
577
|
const debugPrefix = "\x1b[33msessionWatchdog :: "; // 33=yellow
|
|
522
578
|
|
|
523
579
|
debug(debugPrefix + "started");
|
|
524
|
-
if (this.
|
|
580
|
+
if (this.debugLevel > 2) {
|
|
525
581
|
this.log.warn(
|
|
526
582
|
"%s: Started watchdog instance %s",
|
|
527
583
|
watchdogInstance,
|
|
@@ -539,7 +595,7 @@ class StbPlatform {
|
|
|
539
595
|
|
|
540
596
|
// Build a status snapshot for debug logging (only when needed to avoid the
|
|
541
597
|
// string allocation cost on every tick at lower debug levels).
|
|
542
|
-
if (this.
|
|
598
|
+
if (this.debugLevel > 0) {
|
|
543
599
|
const statusOverview = [
|
|
544
600
|
`sessionState=${Object.keys(sessionState)[currentSessionState]}`,
|
|
545
601
|
`mqttClient.connected=${mqttClient.connected}`,
|
|
@@ -551,7 +607,7 @@ class StbPlatform {
|
|
|
551
607
|
// ── Early-exit checks (in order of likelihood) ───────────────────────────
|
|
552
608
|
|
|
553
609
|
if (isShuttingDown) {
|
|
554
|
-
if (this.
|
|
610
|
+
if (this.debugLevel > 2) {
|
|
555
611
|
this.log.warn(
|
|
556
612
|
"%s: Homebridge is shutting down, exiting without action",
|
|
557
613
|
watchdogInstance,
|
|
@@ -563,7 +619,7 @@ class StbPlatform {
|
|
|
563
619
|
// A previous watchdog invocation is still executing its startup sequence.
|
|
564
620
|
// Return immediately — the running instance will reset the flag when done.
|
|
565
621
|
if (this.sessionWatchdogRunning) {
|
|
566
|
-
if (this.
|
|
622
|
+
if (this.debugLevel > 2) {
|
|
567
623
|
this.log.warn(
|
|
568
624
|
"%s: Previous watchdog still running, exiting without action",
|
|
569
625
|
watchdogInstance,
|
|
@@ -577,7 +633,7 @@ class StbPlatform {
|
|
|
577
633
|
currentSessionState === sessionState.CONNECTED &&
|
|
578
634
|
mqttClient.connected
|
|
579
635
|
) {
|
|
580
|
-
if (this.
|
|
636
|
+
if (this.debugLevel > 2) {
|
|
581
637
|
this.log.warn(
|
|
582
638
|
"%s: Session and mqtt fully connected, exiting without action",
|
|
583
639
|
watchdogInstance,
|
|
@@ -592,7 +648,7 @@ class StbPlatform {
|
|
|
592
648
|
currentSessionState === sessionState.CONNECTED &&
|
|
593
649
|
this.mqttClientConnecting
|
|
594
650
|
) {
|
|
595
|
-
if (this.
|
|
651
|
+
if (this.debugLevel > 2) {
|
|
596
652
|
this.log.warn(
|
|
597
653
|
"%s: Session connected, mqtt still connecting, exiting without action",
|
|
598
654
|
watchdogInstance,
|
|
@@ -607,7 +663,7 @@ class StbPlatform {
|
|
|
607
663
|
currentSessionState !== sessionState.DISCONNECTED &&
|
|
608
664
|
currentSessionState !== sessionState.CONNECTED
|
|
609
665
|
) {
|
|
610
|
-
if (this.
|
|
666
|
+
if (this.debugLevel > 2) {
|
|
611
667
|
this.log.warn(
|
|
612
668
|
"%s: Session is connecting (state=%s), exiting without action",
|
|
613
669
|
watchdogInstance,
|
|
@@ -631,7 +687,7 @@ class StbPlatform {
|
|
|
631
687
|
// IMPORTANT: this must be set BEFORE any await so that a concurrent watchdog
|
|
632
688
|
// tick that fires before the first await sees the flag and exits early.
|
|
633
689
|
this.sessionWatchdogRunning = true;
|
|
634
|
-
if (this.
|
|
690
|
+
if (this.debugLevel > 2) {
|
|
635
691
|
this.log.warn(
|
|
636
692
|
"%s: sessionWatchdogRunning set to true, beginning reconnect",
|
|
637
693
|
watchdogInstance,
|
|
@@ -643,9 +699,7 @@ class StbPlatform {
|
|
|
643
699
|
// Uses config.json "devMode": true or NODE_ENV
|
|
644
700
|
// Uses NODE_ENV so any developer can activate it without touching the code.
|
|
645
701
|
if (!PLUGIN_ENV) {
|
|
646
|
-
if (
|
|
647
|
-
this.isDev || process.env.NODE_ENV === "development"
|
|
648
|
-
) {
|
|
702
|
+
if (this.isDev || process.env.NODE_ENV === "development") {
|
|
649
703
|
PLUGIN_ENV = " DEV";
|
|
650
704
|
}
|
|
651
705
|
}
|
|
@@ -671,7 +725,7 @@ class StbPlatform {
|
|
|
671
725
|
} finally {
|
|
672
726
|
// Reset the running flag so the next watchdog tick can proceed.
|
|
673
727
|
this.sessionWatchdogRunning = false;
|
|
674
|
-
if (this.
|
|
728
|
+
if (this.debugLevel > 2) {
|
|
675
729
|
this.log.warn(
|
|
676
730
|
"%s: sessionWatchdogRunning reset to false, exiting",
|
|
677
731
|
watchdogInstance,
|
|
@@ -1076,7 +1130,7 @@ class StbPlatform {
|
|
|
1076
1130
|
async refreshAccessToken() {
|
|
1077
1131
|
// robustness: exit immediately if no session expiry exists yet (session not yet established)
|
|
1078
1132
|
if (!this.session.accessTokenExpiry) {
|
|
1079
|
-
if (this.
|
|
1133
|
+
if (this.debugLevel >= 1) {
|
|
1080
1134
|
this.log.warn(
|
|
1081
1135
|
"refreshAccessToken: No access token expiry set yet, session not yet established. Exiting.",
|
|
1082
1136
|
);
|
|
@@ -1086,7 +1140,7 @@ class StbPlatform {
|
|
|
1086
1140
|
|
|
1087
1141
|
// exit immediately if access token has not expired
|
|
1088
1142
|
if (this.session.accessTokenExpiry > Date.now()) {
|
|
1089
|
-
if (this.
|
|
1143
|
+
if (this.debugLevel >= 1) {
|
|
1090
1144
|
this.log.warn(
|
|
1091
1145
|
"refreshAccessToken: Access token has not expired yet. Next refresh will occur after %s",
|
|
1092
1146
|
this.session.accessTokenExpiry.toLocaleString(),
|
|
@@ -1095,7 +1149,7 @@ class StbPlatform {
|
|
|
1095
1149
|
return true;
|
|
1096
1150
|
}
|
|
1097
1151
|
|
|
1098
|
-
if (this.
|
|
1152
|
+
if (this.debugLevel >= 1) {
|
|
1099
1153
|
this.log.warn(
|
|
1100
1154
|
"refreshAccessToken: Access token has expired at %s. Requesting refresh",
|
|
1101
1155
|
this.session.accessTokenExpiry.toLocaleString(),
|
|
@@ -1124,7 +1178,7 @@ class StbPlatform {
|
|
|
1124
1178
|
},
|
|
1125
1179
|
};
|
|
1126
1180
|
|
|
1127
|
-
if (this.
|
|
1181
|
+
if (this.debugLevel >= 1) {
|
|
1128
1182
|
this.log.warn(
|
|
1129
1183
|
"refreshAccessToken: Post auth refresh request to",
|
|
1130
1184
|
axiosConfig.url,
|
|
@@ -1134,7 +1188,7 @@ class StbPlatform {
|
|
|
1134
1188
|
// throws on HTTP/network error → caller's catch or .catch() handles it
|
|
1135
1189
|
const response = await axiosWS(axiosConfig);
|
|
1136
1190
|
|
|
1137
|
-
if (this.
|
|
1191
|
+
if (this.debugLevel >= 2) {
|
|
1138
1192
|
this.log(
|
|
1139
1193
|
"refreshAccessToken: auth refresh response:",
|
|
1140
1194
|
response.status,
|
|
@@ -1294,7 +1348,7 @@ class StbPlatform {
|
|
|
1294
1348
|
"&language=en";
|
|
1295
1349
|
|
|
1296
1350
|
this.log("Step 1 of 7: get authentication details");
|
|
1297
|
-
if (this.
|
|
1351
|
+
if (this.debugLevel > 1) {
|
|
1298
1352
|
this.log.warn(
|
|
1299
1353
|
"Step 1 of 7: get authentication details from",
|
|
1300
1354
|
apiAuthorizationUrl,
|
|
@@ -1591,7 +1645,7 @@ class StbPlatform {
|
|
|
1591
1645
|
"Cookies for the session:",
|
|
1592
1646
|
cookieJar.getCookies(sessionUrl),
|
|
1593
1647
|
);
|
|
1594
|
-
if (this.
|
|
1648
|
+
if (this.debugLevel > 2) {
|
|
1595
1649
|
this.log(
|
|
1596
1650
|
"getSessionGB: response data (saved to this.session):",
|
|
1597
1651
|
);
|
|
@@ -1753,7 +1807,7 @@ class StbPlatform {
|
|
|
1753
1807
|
"Step 1 of 1: logging in with username %s",
|
|
1754
1808
|
this.config.username,
|
|
1755
1809
|
);
|
|
1756
|
-
if (this.
|
|
1810
|
+
if (this.debugLevel > 1) {
|
|
1757
1811
|
this.log.warn("Step 1 of 1: post login to", axiosConfig.url);
|
|
1758
1812
|
}
|
|
1759
1813
|
axiosWS(axiosConfig)
|
|
@@ -1763,7 +1817,7 @@ class StbPlatform {
|
|
|
1763
1817
|
response.status,
|
|
1764
1818
|
response.statusText,
|
|
1765
1819
|
);
|
|
1766
|
-
if (this.
|
|
1820
|
+
if (this.debugLevel > 2) {
|
|
1767
1821
|
this.log("getSession: response data (saved to this.session):");
|
|
1768
1822
|
this.log(response.data);
|
|
1769
1823
|
}
|
|
@@ -1900,7 +1954,7 @@ class StbPlatform {
|
|
|
1900
1954
|
let apiAuthorizationUrl =
|
|
1901
1955
|
this.configsvc.authorizationService.URL + "/v1/sso/authorization";
|
|
1902
1956
|
this.log("Step 1 of 6: get authentication details");
|
|
1903
|
-
if (this.
|
|
1957
|
+
if (this.debugLevel > 1) {
|
|
1904
1958
|
this.log.warn(
|
|
1905
1959
|
"Step 1 of 6: get authentication details from",
|
|
1906
1960
|
apiAuthorizationUrl,
|
|
@@ -2122,7 +2176,7 @@ class StbPlatform {
|
|
|
2122
2176
|
response.status,
|
|
2123
2177
|
response.statusText,
|
|
2124
2178
|
);
|
|
2125
|
-
if (this.
|
|
2179
|
+
if (this.debugLevel > 2) {
|
|
2126
2180
|
this.log(
|
|
2127
2181
|
"getSessionBE: response data (saved to this.session):",
|
|
2128
2182
|
);
|
|
@@ -2278,7 +2332,7 @@ class StbPlatform {
|
|
|
2278
2332
|
this.configsvc.authorizationService.URL + "/v1/sso/authorization";
|
|
2279
2333
|
|
|
2280
2334
|
this.log("Step 1 of 5: get authentication details");
|
|
2281
|
-
if (this.
|
|
2335
|
+
if (this.debugLevel > 1) {
|
|
2282
2336
|
this.log.warn("Step 1 of 5: GET", apiAuthorizationUrl);
|
|
2283
2337
|
}
|
|
2284
2338
|
|
|
@@ -2294,12 +2348,14 @@ class StbPlatform {
|
|
|
2294
2348
|
},
|
|
2295
2349
|
});
|
|
2296
2350
|
|
|
2297
|
-
this.
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2351
|
+
if (this.debugLevel > 1) {
|
|
2352
|
+
this.log.warn(
|
|
2353
|
+
"Step 1 of 5: response:",
|
|
2354
|
+
step1Response.status,
|
|
2355
|
+
step1Response.statusText,
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2358
|
+
if (this.debugLevel > 2) {
|
|
2303
2359
|
this.log.warn("Step 1 of 5: response data:", step1Response.data);
|
|
2304
2360
|
}
|
|
2305
2361
|
|
|
@@ -2377,7 +2433,7 @@ class StbPlatform {
|
|
|
2377
2433
|
}
|
|
2378
2434
|
});
|
|
2379
2435
|
|
|
2380
|
-
if (this.
|
|
2436
|
+
if (this.debugLevel > 2) {
|
|
2381
2437
|
page.on("framenavigated", (frame) => {
|
|
2382
2438
|
if (frame === page.mainFrame()) {
|
|
2383
2439
|
this.log.warn("Step 2: navigated to:", frame.url());
|
|
@@ -2399,8 +2455,8 @@ class StbPlatform {
|
|
|
2399
2455
|
//
|
|
2400
2456
|
// waitUntil: "networkidle2" waits until there are no more than 2
|
|
2401
2457
|
// in-flight requests for 500ms, giving Akamai JS time to initialise.
|
|
2402
|
-
this.
|
|
2403
|
-
|
|
2458
|
+
if (this.debugLevel > 1) {
|
|
2459
|
+
this.log.warn("Step 2 of 5: navigate to Keycloak login page");
|
|
2404
2460
|
this.log.warn("Step 2 of 5: navigating to:", authorizationUri);
|
|
2405
2461
|
}
|
|
2406
2462
|
|
|
@@ -2417,7 +2473,7 @@ class StbPlatform {
|
|
|
2417
2473
|
try {
|
|
2418
2474
|
await page.waitForSelector(usernameSelector, { timeout: 10000 });
|
|
2419
2475
|
} catch (e) {
|
|
2420
|
-
if (this.
|
|
2476
|
+
if (this.debugLevel > 1) {
|
|
2421
2477
|
const html = await page.content();
|
|
2422
2478
|
this.log.warn(
|
|
2423
2479
|
"Step 2 of 5: unexpected page content (first 1000 chars):",
|
|
@@ -2442,7 +2498,7 @@ class StbPlatform {
|
|
|
2442
2498
|
await page.type(usernameSelector, this.config.username, { delay: 50 });
|
|
2443
2499
|
await page.type(passwordSelector, this.config.password, { delay: 50 });
|
|
2444
2500
|
|
|
2445
|
-
if (this.
|
|
2501
|
+
if (this.debugLevel > 1) {
|
|
2446
2502
|
this.log.warn("Step 3 of 5: credentials entered, submitting form");
|
|
2447
2503
|
}
|
|
2448
2504
|
|
|
@@ -2466,7 +2522,7 @@ class StbPlatform {
|
|
|
2466
2522
|
]);
|
|
2467
2523
|
|
|
2468
2524
|
if (!submitSelector) {
|
|
2469
|
-
if (this.
|
|
2525
|
+
if (this.debugLevel > 1) {
|
|
2470
2526
|
const html = await page.content();
|
|
2471
2527
|
this.log.warn(
|
|
2472
2528
|
"Step 3 of 5: page HTML (first 2000 chars):",
|
|
@@ -2479,7 +2535,7 @@ class StbPlatform {
|
|
|
2479
2535
|
);
|
|
2480
2536
|
}
|
|
2481
2537
|
|
|
2482
|
-
if (this.
|
|
2538
|
+
if (this.debugLevel > 1) {
|
|
2483
2539
|
this.log.warn("Step 3 of 5: submit button found:", submitSelector);
|
|
2484
2540
|
}
|
|
2485
2541
|
|
|
@@ -2491,7 +2547,7 @@ class StbPlatform {
|
|
|
2491
2547
|
]);
|
|
2492
2548
|
|
|
2493
2549
|
const finalUrl = page.url();
|
|
2494
|
-
if (this.
|
|
2550
|
+
if (this.debugLevel > 1) {
|
|
2495
2551
|
this.log.warn("Step 3 of 5: post-submit URL:", finalUrl);
|
|
2496
2552
|
}
|
|
2497
2553
|
|
|
@@ -2503,7 +2559,7 @@ class StbPlatform {
|
|
|
2503
2559
|
this.log("Step 4 of 5: extract authorization code");
|
|
2504
2560
|
|
|
2505
2561
|
if (!finalUrl.startsWith(CH_LOGIN_SUCCESS_URL)) {
|
|
2506
|
-
if (this.
|
|
2562
|
+
if (this.debugLevel > 1) {
|
|
2507
2563
|
const html = await page.content();
|
|
2508
2564
|
this.log.warn(
|
|
2509
2565
|
"Step 4 of 5: unexpected final URL:",
|
|
@@ -2525,8 +2581,8 @@ class StbPlatform {
|
|
|
2525
2581
|
);
|
|
2526
2582
|
}
|
|
2527
2583
|
|
|
2528
|
-
this.
|
|
2529
|
-
|
|
2584
|
+
if (this.debugLevel > 2) {
|
|
2585
|
+
this.log.warn("Step 4 of 5: authorization code OK");
|
|
2530
2586
|
this.log.warn("Step 4 of 5: authorizationCode:", authorizationCode);
|
|
2531
2587
|
}
|
|
2532
2588
|
|
|
@@ -2538,7 +2594,7 @@ class StbPlatform {
|
|
|
2538
2594
|
this.log("Step 5 of 5: exchange authorization code");
|
|
2539
2595
|
currentSessionState = sessionState.AUTHENTICATING;
|
|
2540
2596
|
|
|
2541
|
-
if (this.
|
|
2597
|
+
if (this.debugLevel > 1) {
|
|
2542
2598
|
this.log.warn("Step 5 of 5: POST to", apiAuthorizationUrl);
|
|
2543
2599
|
}
|
|
2544
2600
|
|
|
@@ -2561,12 +2617,12 @@ class StbPlatform {
|
|
|
2561
2617
|
},
|
|
2562
2618
|
);
|
|
2563
2619
|
|
|
2564
|
-
this.
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2620
|
+
if (this.debugLevel > 2) {
|
|
2621
|
+
this.log.warn(
|
|
2622
|
+
"Step 5 of 5: response:",
|
|
2623
|
+
step5Response.status,
|
|
2624
|
+
step5Response.statusText,
|
|
2625
|
+
);
|
|
2570
2626
|
this.log.warn("Step 5 of 5: response data:", step5Response.data);
|
|
2571
2627
|
}
|
|
2572
2628
|
|
|
@@ -2639,7 +2695,7 @@ class StbPlatform {
|
|
|
2639
2695
|
// const GB_AUTH_OESP_URL = 'https://web-api-prod-obo.horizon.tv/oesp/v4/GB/eng/web';
|
|
2640
2696
|
let apiAuthorizationUrl = GB_AUTH_OESP_URL + "/authorization";
|
|
2641
2697
|
this.log("Step 1 of 7: get authentication details");
|
|
2642
|
-
if (this.
|
|
2698
|
+
if (this.debugLevel > 1) {
|
|
2643
2699
|
this.log.warn(
|
|
2644
2700
|
"Step 1 of 7: get authentication details from",
|
|
2645
2701
|
apiAuthorizationUrl,
|
|
@@ -2922,7 +2978,7 @@ class StbPlatform {
|
|
|
2922
2978
|
"Cookies for the session:",
|
|
2923
2979
|
cookieJar.getCookies(sessionUrl),
|
|
2924
2980
|
);
|
|
2925
|
-
if (this.
|
|
2981
|
+
if (this.debugLevel > 2) {
|
|
2926
2982
|
this.log(
|
|
2927
2983
|
"getSessionGB: response data (saved to this.session):",
|
|
2928
2984
|
);
|
|
@@ -3033,7 +3089,7 @@ class StbPlatform {
|
|
|
3033
3089
|
|
|
3034
3090
|
// exit immediately if the session does not exist
|
|
3035
3091
|
if (currentSessionState !== sessionState.CONNECTED) {
|
|
3036
|
-
if (this.
|
|
3092
|
+
if (this.debugLevel > 1) {
|
|
3037
3093
|
this.log.warn(
|
|
3038
3094
|
"refreshMasterChannelList: Session does not exist, exiting",
|
|
3039
3095
|
);
|
|
@@ -3044,7 +3100,7 @@ class StbPlatform {
|
|
|
3044
3100
|
|
|
3045
3101
|
// exit immediately if channel list has not expired
|
|
3046
3102
|
if (this.masterChannelListExpiryDate > Date.now()) {
|
|
3047
|
-
if (this.
|
|
3103
|
+
if (this.debugLevel >= 1) {
|
|
3048
3104
|
this.log.warn(
|
|
3049
3105
|
"refreshMasterChannelList: Master channel list has not expired yet. Next refresh will occur after %s",
|
|
3050
3106
|
this.masterChannelListExpiryDate.toLocaleString(),
|
|
@@ -3076,7 +3132,7 @@ class StbPlatform {
|
|
|
3076
3132
|
url = url + "&language=en"; // language
|
|
3077
3133
|
url = url + "&productClass=Orion-DASH"; // productClass, must be Orion-DASH
|
|
3078
3134
|
//url = url + '&includeNotEntitled=false' // includeNotEntitled testing to see if this parameter is accepted
|
|
3079
|
-
if (this.
|
|
3135
|
+
if (this.debugLevel > 0) {
|
|
3080
3136
|
this.log.warn("refreshMasterChannelList: GET %s", url);
|
|
3081
3137
|
}
|
|
3082
3138
|
// call the webservice to get all available channels
|
|
@@ -3091,7 +3147,7 @@ class StbPlatform {
|
|
|
3091
3147
|
};
|
|
3092
3148
|
axiosWS(axiosConfig)
|
|
3093
3149
|
.then((response) => {
|
|
3094
|
-
if (this.
|
|
3150
|
+
if (this.debugLevel > 0) {
|
|
3095
3151
|
this.log.warn(
|
|
3096
3152
|
"refreshMasterChannelList: response: %s %s",
|
|
3097
3153
|
response.status,
|
|
@@ -3119,7 +3175,7 @@ class StbPlatform {
|
|
|
3119
3175
|
this.log.debug("Channels to process:", channels.length);
|
|
3120
3176
|
for (let i = 0; i < channels.length; i++) {
|
|
3121
3177
|
const channel = channels[i];
|
|
3122
|
-
if (this.
|
|
3178
|
+
if (this.debugLevel > 2) {
|
|
3123
3179
|
this.log(
|
|
3124
3180
|
"Processing channel:",
|
|
3125
3181
|
i,
|
|
@@ -3129,8 +3185,8 @@ class StbPlatform {
|
|
|
3129
3185
|
);
|
|
3130
3186
|
} // for debug purposes
|
|
3131
3187
|
// log the detail of logicalChannelNumber 60 nicktoons, for which I have no subscription, as a test of entitlements
|
|
3132
|
-
//if (this.
|
|
3133
|
-
//if (this.
|
|
3188
|
+
//if (this.debugLevel > 0) { if (channel.logicalChannelNumber === 60){ this.log('DEV: Logging Channel 60 to check entitlements :',channel); } }
|
|
3189
|
+
//if (this.debugLevel > 0) { if (channel.logicalChannelNumber === 60){ this.log('DEV: Logging Channel 60 to check entitlements :',channel); } }
|
|
3134
3190
|
this.masterChannelList.push({
|
|
3135
3191
|
id: channel.id,
|
|
3136
3192
|
name: cleanNameForHomeKit(channel.name),
|
|
@@ -3138,8 +3194,12 @@ class StbPlatform {
|
|
|
3138
3194
|
linearProducts: channel.linearProducts,
|
|
3139
3195
|
});
|
|
3140
3196
|
}
|
|
3197
|
+
// add a map for faster access to the master channel list
|
|
3198
|
+
this.masterChannelMap = new Map(
|
|
3199
|
+
this.masterChannelList.map((ch) => [ch.id, ch]),
|
|
3200
|
+
);
|
|
3141
3201
|
|
|
3142
|
-
if (this.
|
|
3202
|
+
if (this.debugLevel > 0) {
|
|
3143
3203
|
this.log.warn(
|
|
3144
3204
|
"refreshMasterChannelList: Master channel list refreshed with %s channels, valid until %s",
|
|
3145
3205
|
this.masterChannelList.length,
|
|
@@ -3209,20 +3269,20 @@ class StbPlatform {
|
|
|
3209
3269
|
"/" +
|
|
3210
3270
|
ctryCodeForUrl +
|
|
3211
3271
|
"/en/config-service/conf/web/backoffice.json";
|
|
3212
|
-
if (this.
|
|
3272
|
+
if (this.debugLevel > 0) {
|
|
3213
3273
|
this.log.warn("getConfig: GET %s", url);
|
|
3214
3274
|
}
|
|
3215
3275
|
axiosWS
|
|
3216
3276
|
.get(url)
|
|
3217
3277
|
.then((response) => {
|
|
3218
|
-
if (this.
|
|
3278
|
+
if (this.debugLevel > 0) {
|
|
3219
3279
|
this.log.warn(
|
|
3220
3280
|
"getConfig: response: %s %s",
|
|
3221
3281
|
response.status,
|
|
3222
3282
|
response.statusText,
|
|
3223
3283
|
);
|
|
3224
3284
|
}
|
|
3225
|
-
if (this.
|
|
3285
|
+
if (this.debugLevel > 2) {
|
|
3226
3286
|
this.log.warn(
|
|
3227
3287
|
"getConfig: response data (saved to this.configsvc):",
|
|
3228
3288
|
);
|
|
@@ -3289,21 +3349,21 @@ class StbPlatform {
|
|
|
3289
3349
|
},
|
|
3290
3350
|
};
|
|
3291
3351
|
}
|
|
3292
|
-
if (this.
|
|
3352
|
+
if (this.debugLevel > 0) {
|
|
3293
3353
|
this.log.warn("getPersonalizationData: GET %s", url);
|
|
3294
3354
|
}
|
|
3295
3355
|
// this.log('getPersonalizationData: GET %s', url);
|
|
3296
3356
|
axiosWS
|
|
3297
3357
|
.get(url, config)
|
|
3298
3358
|
.then((response) => {
|
|
3299
|
-
if (this.
|
|
3359
|
+
if (this.debugLevel > 0) {
|
|
3300
3360
|
this.log.warn(
|
|
3301
3361
|
"getPersonalizationData: response: %s %s",
|
|
3302
3362
|
response.status,
|
|
3303
3363
|
response.statusText,
|
|
3304
3364
|
);
|
|
3305
3365
|
}
|
|
3306
|
-
if (this.
|
|
3366
|
+
if (this.debugLevel > 2) {
|
|
3307
3367
|
// DEBUG
|
|
3308
3368
|
this.log.warn(
|
|
3309
3369
|
"getPersonalizationData: response data (saved to this.customer):",
|
|
@@ -3319,7 +3379,7 @@ class StbPlatform {
|
|
|
3319
3379
|
//this.log('getPersonalizationData: this.stbDevices.length:', this.stbDevices.length)
|
|
3320
3380
|
if (this.stbDevices.length > 0) {
|
|
3321
3381
|
this.devices.forEach((device) => {
|
|
3322
|
-
if (this.
|
|
3382
|
+
if (this.debugLevel > 2) {
|
|
3323
3383
|
// DEBUG
|
|
3324
3384
|
this.log.warn(
|
|
3325
3385
|
"getPersonalizationData: device settings for device %s:",
|
|
@@ -3411,7 +3471,7 @@ class StbPlatform {
|
|
|
3411
3471
|
|
|
3412
3472
|
// set the Personalization Data for the current device via web request PUT
|
|
3413
3473
|
async setPersonalizationDataForDevice(deviceId, deviceSettings) {
|
|
3414
|
-
if (this.
|
|
3474
|
+
if (this.debugLevel > 0) {
|
|
3415
3475
|
this.log.warn(
|
|
3416
3476
|
"setPersonalizationDataForDevice: deviceSettings:",
|
|
3417
3477
|
deviceSettings,
|
|
@@ -3446,14 +3506,14 @@ class StbPlatform {
|
|
|
3446
3506
|
},
|
|
3447
3507
|
};
|
|
3448
3508
|
}
|
|
3449
|
-
if (this.
|
|
3509
|
+
if (this.debugLevel > 0) {
|
|
3450
3510
|
this.log.warn("setPersonalizationDataForDevice: PUT %s", url);
|
|
3451
3511
|
}
|
|
3452
3512
|
axiosWS
|
|
3453
3513
|
.put(url, data, config)
|
|
3454
3514
|
.then((response) => {
|
|
3455
3515
|
// returns 204 No Content when successful
|
|
3456
|
-
if (this.
|
|
3516
|
+
if (this.debugLevel > 0) {
|
|
3457
3517
|
this.log.warn(
|
|
3458
3518
|
"setPersonalizationDataForDevice: response: %s %s",
|
|
3459
3519
|
response.status,
|
|
@@ -3507,28 +3567,28 @@ class StbPlatform {
|
|
|
3507
3567
|
},
|
|
3508
3568
|
};
|
|
3509
3569
|
}
|
|
3510
|
-
if (this.
|
|
3570
|
+
if (this.debugLevel > 0) {
|
|
3511
3571
|
this.log.warn("getEntitlements: GET %s", url);
|
|
3512
3572
|
}
|
|
3513
3573
|
// this.log('getEntitlements: GET %s', url);
|
|
3514
3574
|
axiosWS
|
|
3515
3575
|
.get(url, config)
|
|
3516
3576
|
.then((response) => {
|
|
3517
|
-
if (this.
|
|
3577
|
+
if (this.debugLevel > 0) {
|
|
3518
3578
|
this.log.warn(
|
|
3519
3579
|
"getEntitlements: response: %s %s",
|
|
3520
3580
|
response.status,
|
|
3521
3581
|
response.statusText,
|
|
3522
3582
|
);
|
|
3523
3583
|
}
|
|
3524
|
-
if (this.
|
|
3584
|
+
if (this.debugLevel > 2) {
|
|
3525
3585
|
this.log.warn(
|
|
3526
3586
|
"getEntitlements: response data (saved to this.entitlements):",
|
|
3527
3587
|
);
|
|
3528
3588
|
this.log.warn(response.data);
|
|
3529
3589
|
}
|
|
3530
3590
|
this.entitlements = response.data; // store the entire entitlements data for future use in this.customer.entitlements
|
|
3531
|
-
if (this.
|
|
3591
|
+
if (this.debugLevel > 0) {
|
|
3532
3592
|
this.log.warn(
|
|
3533
3593
|
"getEntitlements: entitlements found:",
|
|
3534
3594
|
this.entitlements.entitlements.length,
|
|
@@ -3591,21 +3651,21 @@ class StbPlatform {
|
|
|
3591
3651
|
"/customers/" +
|
|
3592
3652
|
householdId +
|
|
3593
3653
|
"/recordings/state"; // limit to 20 recordings for performance
|
|
3594
|
-
if (this.
|
|
3654
|
+
if (this.debugLevel > 0) {
|
|
3595
3655
|
this.log.warn("getRecordingState: GET %s", url);
|
|
3596
3656
|
}
|
|
3597
3657
|
axiosWS
|
|
3598
3658
|
.get(url, config)
|
|
3599
3659
|
.then((response) => {
|
|
3600
3660
|
// log at level 1, 2
|
|
3601
|
-
if (this.
|
|
3661
|
+
if (this.debugLevel > 0) {
|
|
3602
3662
|
this.log.warn(
|
|
3603
3663
|
"getRecordingState: response: %s %s",
|
|
3604
3664
|
response.status,
|
|
3605
3665
|
response.statusText,
|
|
3606
3666
|
);
|
|
3607
3667
|
}
|
|
3608
|
-
if (this.
|
|
3668
|
+
if (this.debugLevel > 1) {
|
|
3609
3669
|
this.log.warn("getRecordingState: response data:");
|
|
3610
3670
|
this.log.warn(response.data);
|
|
3611
3671
|
}
|
|
@@ -3622,7 +3682,7 @@ class StbPlatform {
|
|
|
3622
3682
|
// mostRelevantEpisode.recordingState: 'ongoing',
|
|
3623
3683
|
// mostRelevantEpisode.recordingType: 'nDVR',
|
|
3624
3684
|
// logging at level 2
|
|
3625
|
-
if (this.
|
|
3685
|
+
if (this.debugLevel > 1) {
|
|
3626
3686
|
this.log.warn(
|
|
3627
3687
|
"getRecordingState: Recordings length %s:",
|
|
3628
3688
|
response.data.data.length,
|
|
@@ -3642,7 +3702,7 @@ class StbPlatform {
|
|
|
3642
3702
|
networkOngoingRecordings = 0;
|
|
3643
3703
|
|
|
3644
3704
|
// look for planned network single recordings: (type = "single" = one object, type = "season" = array)
|
|
3645
|
-
if (this.
|
|
3705
|
+
if (this.debugLevel > 0) {
|
|
3646
3706
|
this.log.warn(
|
|
3647
3707
|
"getRecordingState: searching for ongoing network recordings",
|
|
3648
3708
|
);
|
|
@@ -3658,7 +3718,7 @@ class StbPlatform {
|
|
|
3658
3718
|
|
|
3659
3719
|
// find if any local device recordings are ongoing, for each device, as each device can have a HDD
|
|
3660
3720
|
this.devices.forEach((device) => {
|
|
3661
|
-
if (this.
|
|
3721
|
+
if (this.debugLevel > 0) {
|
|
3662
3722
|
this.log.warn(
|
|
3663
3723
|
"getRecordingState: Checking device %s for ongoing local HDD recordings",
|
|
3664
3724
|
device.deviceId,
|
|
@@ -3667,7 +3727,7 @@ class StbPlatform {
|
|
|
3667
3727
|
if (device.capabilities.hasHDD) {
|
|
3668
3728
|
// device has HDD, look for local recordings
|
|
3669
3729
|
// look for ongoing local single recordings: (type = "single" = one object, type = "season" = array)
|
|
3670
|
-
if (this.
|
|
3730
|
+
if (this.debugLevel > 0) {
|
|
3671
3731
|
this.log.warn(
|
|
3672
3732
|
"getRecordingState: %s: searching for ongoing local recordings for this device",
|
|
3673
3733
|
device.deviceId,
|
|
@@ -3803,21 +3863,21 @@ class StbPlatform {
|
|
|
3803
3863
|
"/customers/" +
|
|
3804
3864
|
householdId +
|
|
3805
3865
|
"/bookings?limit=10&sort=time&sortOrder=asc"; // limit to 10 recordings for performance
|
|
3806
|
-
if (this.
|
|
3866
|
+
if (this.debugLevel > 0) {
|
|
3807
3867
|
this.log.warn("getRecordingBookings: GET %s", url);
|
|
3808
3868
|
}
|
|
3809
3869
|
axiosWS
|
|
3810
3870
|
.get(url, config)
|
|
3811
3871
|
.then((response) => {
|
|
3812
3872
|
// log at level 1, 2
|
|
3813
|
-
if (this.
|
|
3873
|
+
if (this.debugLevel > 0) {
|
|
3814
3874
|
this.log.warn(
|
|
3815
3875
|
"getRecordingBookings: response: %s %s",
|
|
3816
3876
|
response.status,
|
|
3817
3877
|
response.statusText,
|
|
3818
3878
|
);
|
|
3819
3879
|
}
|
|
3820
|
-
if (this.
|
|
3880
|
+
if (this.debugLevel > 1) {
|
|
3821
3881
|
this.log.warn("getRecordingBookings: response data:");
|
|
3822
3882
|
this.log.warn(response.data);
|
|
3823
3883
|
}
|
|
@@ -3834,7 +3894,7 @@ class StbPlatform {
|
|
|
3834
3894
|
// mostRelevantEpisode.recordingState: 'ongoing',
|
|
3835
3895
|
// mostRelevantEpisode.recordingType: 'nDVR',
|
|
3836
3896
|
// logging at level 2
|
|
3837
|
-
if (this.
|
|
3897
|
+
if (this.debugLevel > 1) {
|
|
3838
3898
|
this.log.warn(
|
|
3839
3899
|
"getRecordingBookings: Recordings length %s:",
|
|
3840
3900
|
response.data.data.length,
|
|
@@ -3856,7 +3916,7 @@ class StbPlatform {
|
|
|
3856
3916
|
networkPlannedRecordings = 0;
|
|
3857
3917
|
|
|
3858
3918
|
// look for planned network recordings: (type = "single" = one object, type = "season" = array)
|
|
3859
|
-
if (this.
|
|
3919
|
+
if (this.debugLevel > 0) {
|
|
3860
3920
|
this.log.warn(
|
|
3861
3921
|
"getRecordingBookings: searching for planned network recordings",
|
|
3862
3922
|
);
|
|
@@ -3881,7 +3941,7 @@ class StbPlatform {
|
|
|
3881
3941
|
|
|
3882
3942
|
// find if any local recordings are booked, for each device, as each device can have a HDD
|
|
3883
3943
|
this.devices.forEach((device) => {
|
|
3884
|
-
if (this.
|
|
3944
|
+
if (this.debugLevel > 0) {
|
|
3885
3945
|
this.log.warn(
|
|
3886
3946
|
"getRecordingBookings: Checking device %s for planned local HDD recordings",
|
|
3887
3947
|
device.deviceId,
|
|
@@ -3890,7 +3950,7 @@ class StbPlatform {
|
|
|
3890
3950
|
if (device.capabilities.hasHDD) {
|
|
3891
3951
|
// device has HDD, look for local recordings
|
|
3892
3952
|
// look for planned local single recordings: (type = "single")
|
|
3893
|
-
if (this.
|
|
3953
|
+
if (this.debugLevel > 0) {
|
|
3894
3954
|
this.log.warn(
|
|
3895
3955
|
"getRecordingBookings: %s: searching for planned local recordings for this device",
|
|
3896
3956
|
device.deviceId,
|
|
@@ -3930,7 +3990,7 @@ class StbPlatform {
|
|
|
3930
3990
|
localPlannedRecordings,
|
|
3931
3991
|
networkPlannedRecordings,
|
|
3932
3992
|
currProgramMode,
|
|
3933
|
-
|
|
3993
|
+
CHAR_NAMES.ProgramMode[currProgramMode + 1],
|
|
3934
3994
|
);
|
|
3935
3995
|
// mqttDeviceStateHandler(deviceId, powerState, mediaState, recordingState, channelId, eventId, sourceType, profileDataChanged, statusFault, programMode, statusActive, currInputDeviceType, currInputSourceType) {
|
|
3936
3996
|
this.mqttDeviceStateHandler(
|
|
@@ -4051,7 +4111,7 @@ class StbPlatform {
|
|
|
4051
4111
|
async getMqttToken(oespUsername, accessToken, householdId) {
|
|
4052
4112
|
this.log.debug("Getting mqtt token for householdId %s", householdId);
|
|
4053
4113
|
// get a JSON web token from the supplied accessToken and householdId
|
|
4054
|
-
if (this.
|
|
4114
|
+
if (this.debugLevel > 1) {
|
|
4055
4115
|
this.log.warn("getMqttToken");
|
|
4056
4116
|
}
|
|
4057
4117
|
// robustness checks
|
|
@@ -4095,7 +4155,7 @@ class StbPlatform {
|
|
|
4095
4155
|
|
|
4096
4156
|
try {
|
|
4097
4157
|
const response = await axiosWS(mqttAxiosConfig);
|
|
4098
|
-
if (this.
|
|
4158
|
+
if (this.debugLevel > 0) {
|
|
4099
4159
|
this.log.warn("getMqttToken: response.data:", response.data);
|
|
4100
4160
|
}
|
|
4101
4161
|
mqttUsername = householdId;
|
|
@@ -4115,7 +4175,7 @@ class StbPlatform {
|
|
|
4115
4175
|
startMqttClient(mqttUsername, mqttPassword) {
|
|
4116
4176
|
return new Promise((resolve, reject) => {
|
|
4117
4177
|
try {
|
|
4118
|
-
if (this.
|
|
4178
|
+
if (this.debugLevel > 0) {
|
|
4119
4179
|
this.log("Starting mqttClient...");
|
|
4120
4180
|
}
|
|
4121
4181
|
if (currentSessionState !== sessionState.CONNECTED) {
|
|
@@ -4134,7 +4194,7 @@ class StbPlatform {
|
|
|
4134
4194
|
|
|
4135
4195
|
// connect to the MQTT broker
|
|
4136
4196
|
const mqttBrokerUrl = this.configsvc.mqttBroker.URL;
|
|
4137
|
-
if (this.
|
|
4197
|
+
if (this.debugLevel > 0) {
|
|
4138
4198
|
this.log.warn("startMqttClient: mqttBrokerUrl:", mqttBrokerUrl);
|
|
4139
4199
|
this.log.warn(
|
|
4140
4200
|
"startMqttClient: Creating mqttClient with username %s, password %s",
|
|
@@ -4168,7 +4228,7 @@ class StbPlatform {
|
|
|
4168
4228
|
username: mqttUsername,
|
|
4169
4229
|
password: mqttPassword,
|
|
4170
4230
|
});
|
|
4171
|
-
if (this.
|
|
4231
|
+
if (this.debugLevel > 0) {
|
|
4172
4232
|
this.log.warn(
|
|
4173
4233
|
"startMqttClient: mqttBroker connect request sent using mqttClientId %s, waiting for connect event",
|
|
4174
4234
|
mqttClientId,
|
|
@@ -4267,7 +4327,7 @@ class StbPlatform {
|
|
|
4267
4327
|
this.lastMqttMessageReceived = Date.now();
|
|
4268
4328
|
|
|
4269
4329
|
let mqttMessage = JSON.parse(message);
|
|
4270
|
-
if (this.
|
|
4330
|
+
if (this.debugLevel > 0) {
|
|
4271
4331
|
this.log.warn(
|
|
4272
4332
|
"mqttClient: Received Message: \r\nTopic: %s\r\nMessage: (next log entry)",
|
|
4273
4333
|
topic,
|
|
@@ -4294,14 +4354,14 @@ class StbPlatform {
|
|
|
4294
4354
|
// Message: { action: 'OPS.getProfilesUpdate', source: '3C36E4-EOSSTB-00365657xxxx', ... }
|
|
4295
4355
|
// Message: { action: 'OPS.getDeviceUpdate', source: '3C36E4-EOSSTB-00365657xxxx', deviceId: '3C36E4-EOSSTB-00365657xxxx' }
|
|
4296
4356
|
if (topic.includes(mqttUsername + "/personalizationService")) {
|
|
4297
|
-
if (this.
|
|
4357
|
+
if (this.debugLevel > 0) {
|
|
4298
4358
|
this.log.warn("mqttClient: %s: action", mqttMessage.action);
|
|
4299
4359
|
}
|
|
4300
4360
|
if (
|
|
4301
4361
|
mqttMessage.action === "OPS.getProfilesUpdate" ||
|
|
4302
4362
|
mqttMessage.action === "OPS.getDeviceUpdate"
|
|
4303
4363
|
) {
|
|
4304
|
-
if (this.
|
|
4364
|
+
if (this.debugLevel > 0) {
|
|
4305
4365
|
this.log.warn(
|
|
4306
4366
|
"mqttClient: %s, calling getPersonalizationData",
|
|
4307
4367
|
mqttMessage.action,
|
|
@@ -4317,7 +4377,7 @@ class StbPlatform {
|
|
|
4317
4377
|
// Topic: Topic: 107xxxx_ch/recordingStatus
|
|
4318
4378
|
// Message: {"id":"crid:~~2F~~2Fgn.tv~~2F2004781~~2FEP019440730003,imi:2d369682b865679f2e5182ea52a93410171cfdc8","event":"scheduleEvent","transactionId":"/CH/eng/web/networkdvrrecordings - 013f12fc-23ef-4b77-a244-eeeea0c6901c"}
|
|
4319
4379
|
if (topic.includes(mqttUsername + "/recordingStatus")) {
|
|
4320
|
-
if (this.
|
|
4380
|
+
if (this.debugLevel > 0) {
|
|
4321
4381
|
this.log.warn("mqttClient: event: %s", mqttMessage.event);
|
|
4322
4382
|
}
|
|
4323
4383
|
this.refreshRecordings(this.session.householdId); // request a refresh of recording data
|
|
@@ -4328,7 +4388,7 @@ class StbPlatform {
|
|
|
4328
4388
|
// Message: {"deviceType":"STB","source":"3C36E4-EOSSTB-00365657xxxx","state":"ONLINE_RUNNING","mac":"F8:F5:32:45:DE:52","ipAddress":"192.168.0.33/255.255.255.0"}
|
|
4329
4389
|
if (topic.includes("/status")) {
|
|
4330
4390
|
if (mqttMessage.deviceType === "STB") {
|
|
4331
|
-
if (this.
|
|
4391
|
+
if (this.debugLevel > 0) {
|
|
4332
4392
|
this.log.warn(
|
|
4333
4393
|
"mqttClient: STB status: Detecting Power State: Received Message of deviceType %s for %s",
|
|
4334
4394
|
mqttMessage.deviceType,
|
|
@@ -4373,7 +4433,7 @@ class StbPlatform {
|
|
|
4373
4433
|
);
|
|
4374
4434
|
break;
|
|
4375
4435
|
}
|
|
4376
|
-
if (this.
|
|
4436
|
+
if (this.debugLevel > 0) {
|
|
4377
4437
|
this.log.warn("mqttClient: %s %s", deviceId, stbState);
|
|
4378
4438
|
}
|
|
4379
4439
|
}
|
|
@@ -4399,7 +4459,7 @@ class StbPlatform {
|
|
|
4399
4459
|
uiStatusFingerprint === this.lastUiStatusFingerprint &&
|
|
4400
4460
|
now - this.lastUiStatusFingerprintTime < 500
|
|
4401
4461
|
) {
|
|
4402
|
-
if (this.
|
|
4462
|
+
if (this.debugLevel > 0) {
|
|
4403
4463
|
this.log.warn(
|
|
4404
4464
|
"mqttClient: CPE.uiStatus: duplicate state fingerprint within 500ms, skipping",
|
|
4405
4465
|
);
|
|
@@ -4409,7 +4469,7 @@ class StbPlatform {
|
|
|
4409
4469
|
this.lastUiStatusFingerprint = uiStatusFingerprint;
|
|
4410
4470
|
this.lastUiStatusFingerprintTime = now;
|
|
4411
4471
|
|
|
4412
|
-
if (this.
|
|
4472
|
+
if (this.debugLevel > 0) {
|
|
4413
4473
|
this.log.warn(
|
|
4414
4474
|
"mqttClient: CPE.uiStatus received from %s",
|
|
4415
4475
|
mqttMessage.source,
|
|
@@ -4424,7 +4484,7 @@ class StbPlatform {
|
|
|
4424
4484
|
);
|
|
4425
4485
|
}
|
|
4426
4486
|
// if we have this message, then the power is on. Sometimes the message arrives before the status topic with the power state
|
|
4427
|
-
currStatusActive = Characteristic.Active.ACTIVE; // ensure
|
|
4487
|
+
currStatusActive = Characteristic.Active.ACTIVE; // ensure StatusActive is set to Active
|
|
4428
4488
|
currPowerState = Characteristic.Active.ACTIVE; // ensure power is set to ON
|
|
4429
4489
|
|
|
4430
4490
|
this.lastMqttUiStatusMessageReceived = now;
|
|
@@ -4432,7 +4492,7 @@ class StbPlatform {
|
|
|
4432
4492
|
const cpeUiStatus = mqttMessage.status;
|
|
4433
4493
|
// normal TV: cpeUiStatus = mainUI
|
|
4434
4494
|
// app: cpeUiStatus = apps (YouTube, Netflix, etc)
|
|
4435
|
-
if (this.
|
|
4495
|
+
if (this.debugLevel > 0) {
|
|
4436
4496
|
this.log.warn(
|
|
4437
4497
|
"mqttClient: CPE.uiStatus: cpeUiStatus:",
|
|
4438
4498
|
cpeUiStatus,
|
|
@@ -4449,7 +4509,7 @@ class StbPlatform {
|
|
|
4449
4509
|
// destructure playerState for cleaner access to nested properties
|
|
4450
4510
|
const playerState = cpeUiStatus.playerState;
|
|
4451
4511
|
currSourceType = playerState.sourceType;
|
|
4452
|
-
if (this.
|
|
4512
|
+
if (this.debugLevel > 1) {
|
|
4453
4513
|
this.log.warn(
|
|
4454
4514
|
"mqttClient: mainUI: Detected mqtt playerState.speed:",
|
|
4455
4515
|
playerState.speed,
|
|
@@ -4519,11 +4579,10 @@ class StbPlatform {
|
|
|
4519
4579
|
currChannelId =
|
|
4520
4580
|
playerState.source.channelId || NO_CHANNEL_ID; // must be a string
|
|
4521
4581
|
currEventId = playerState.source.eventId; // the title (program) id
|
|
4522
|
-
if (this.
|
|
4582
|
+
if (this.debugLevel > 0 && this.masterChannelList) {
|
|
4523
4583
|
let currentChannelName; // let is scoped to the current {} block
|
|
4524
|
-
let curChannel =
|
|
4525
|
-
(
|
|
4526
|
-
);
|
|
4584
|
+
let curChannel =
|
|
4585
|
+
this.masterChannelMap?.get(currChannelId);
|
|
4527
4586
|
if (curChannel) {
|
|
4528
4587
|
currentChannelName = curChannel.name;
|
|
4529
4588
|
}
|
|
@@ -4567,11 +4626,7 @@ class StbPlatform {
|
|
|
4567
4626
|
default:
|
|
4568
4627
|
// check if the app channel exists in the master channel list, if not, push it, using the user-defined name if one exists
|
|
4569
4628
|
currChannelId = cpeUiStatus.appsState.id;
|
|
4570
|
-
if (
|
|
4571
|
-
this.masterChannelList.findIndex(
|
|
4572
|
-
(channel) => channel.id === currChannelId,
|
|
4573
|
-
) === -1
|
|
4574
|
-
) {
|
|
4629
|
+
if (!this.masterChannelMap.has(currChannelId)) {
|
|
4575
4630
|
this.log(
|
|
4576
4631
|
"App %s detected. Adding to the master channel list at index %s with channelId %s",
|
|
4577
4632
|
cpeUiStatus.appsState.appName,
|
|
@@ -4581,16 +4636,17 @@ class StbPlatform {
|
|
|
4581
4636
|
const entitlementId =
|
|
4582
4637
|
this.entitlements.entitlements[0].id;
|
|
4583
4638
|
// for easy identification, make the logicalChannelNumber and channelNumber app10000 + the index number
|
|
4584
|
-
|
|
4639
|
+
const newAppChannel = {
|
|
4585
4640
|
id: currChannelId,
|
|
4586
4641
|
name: cleanNameForHomeKit(
|
|
4587
4642
|
cpeUiStatus.appsState.appName,
|
|
4588
4643
|
),
|
|
4589
4644
|
logicalChannelNumber:
|
|
4590
|
-
10000 + this.masterChannelList.length,
|
|
4591
|
-
linearProducts: entitlementId,
|
|
4592
|
-
|
|
4593
|
-
|
|
4645
|
+
10000 + this.masterChannelList.length,
|
|
4646
|
+
linearProducts: entitlementId,
|
|
4647
|
+
};
|
|
4648
|
+
this.masterChannelList.push(newAppChannel);
|
|
4649
|
+
this.masterChannelMap.set(currChannelId, newAppChannel);
|
|
4594
4650
|
}
|
|
4595
4651
|
}
|
|
4596
4652
|
break;
|
|
@@ -4606,7 +4662,7 @@ class StbPlatform {
|
|
|
4606
4662
|
// there's also a pullFromTV
|
|
4607
4663
|
// {"source":"7028f103-8494-4f79-9b76-beb67a2e5caa","type":"CPE.pullFromTV","runtimeType":"pull"}
|
|
4608
4664
|
if (mqttMessage.type === "CPE.pushToTV.rsp") {
|
|
4609
|
-
if (this.
|
|
4665
|
+
if (this.debugLevel > 0) {
|
|
4610
4666
|
this.log.warn(
|
|
4611
4667
|
"mqttClient: CPE.pushToTV.rsp: received from %s",
|
|
4612
4668
|
mqttMessage.source,
|
|
@@ -4804,7 +4860,7 @@ class StbPlatform {
|
|
|
4804
4860
|
// end the mqtt session cleanly
|
|
4805
4861
|
endMqttSession() {
|
|
4806
4862
|
return new Promise((resolve, reject) => {
|
|
4807
|
-
if (this.
|
|
4863
|
+
if (this.debugLevel > -1) {
|
|
4808
4864
|
this.log("Shutting down mqttClient...");
|
|
4809
4865
|
}
|
|
4810
4866
|
// https://github.com/mqttjs/MQTT.js#end
|
|
@@ -4834,7 +4890,7 @@ class StbPlatform {
|
|
|
4834
4890
|
currInputSourceType,
|
|
4835
4891
|
) {
|
|
4836
4892
|
try {
|
|
4837
|
-
if (this.
|
|
4893
|
+
if (this.debugLevel > 1) {
|
|
4838
4894
|
this.log.warn(
|
|
4839
4895
|
"mqttDeviceStateHandler: calling updateDeviceState with deviceId %s, powerState %s, mediaState %s, channelId %s, eventId %s, sourceType %s, profileDataChanged %s, statusFault %s, programMode %s, statusActive %s, currInputDeviceType %s, currInputSourceType %s",
|
|
4840
4896
|
deviceId,
|
|
@@ -4882,7 +4938,7 @@ class StbPlatform {
|
|
|
4882
4938
|
mqttPublishMessage(Topic, Message, Options) {
|
|
4883
4939
|
try {
|
|
4884
4940
|
// Syntax: {'test1': {qos: 0}, 'test2': {qos: 1}}
|
|
4885
|
-
if (this.
|
|
4941
|
+
if (this.debugLevel > 0) {
|
|
4886
4942
|
this.log.warn(
|
|
4887
4943
|
"mqttPublishMessage: Publish Message:\r\nTopic: %s\r\nMessage: %s\r\nOptions: %s",
|
|
4888
4944
|
Topic,
|
|
@@ -4901,7 +4957,7 @@ class StbPlatform {
|
|
|
4901
4957
|
errDetail,
|
|
4902
4958
|
);
|
|
4903
4959
|
} else {
|
|
4904
|
-
if (this.
|
|
4960
|
+
if (this.debugLevel > 0) {
|
|
4905
4961
|
this.log.warn("mqttPublishMessage: Published OK to %s", Topic);
|
|
4906
4962
|
}
|
|
4907
4963
|
}
|
|
@@ -4914,7 +4970,7 @@ class StbPlatform {
|
|
|
4914
4970
|
|
|
4915
4971
|
// subscribe to an mqtt topic, with logging, to help in debugging
|
|
4916
4972
|
mqttSubscribeToTopic(Topic) {
|
|
4917
|
-
if (this.
|
|
4973
|
+
if (this.debugLevel > 0) {
|
|
4918
4974
|
this.log.warn("mqttSubscribeToTopic: Subscribe to topic:", Topic);
|
|
4919
4975
|
}
|
|
4920
4976
|
mqttClient.subscribe(Topic, (err, granted) => {
|
|
@@ -4939,11 +4995,13 @@ class StbPlatform {
|
|
|
4939
4995
|
Topic,
|
|
4940
4996
|
);
|
|
4941
4997
|
} else {
|
|
4942
|
-
this.
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4998
|
+
if (this.debugLevel > 0) {
|
|
4999
|
+
this.log.warn(
|
|
5000
|
+
"mqttSubscribeToTopic: Subscribed OK to %s (granted QoS: %s)",
|
|
5001
|
+
Topic,
|
|
5002
|
+
grantedQos,
|
|
5003
|
+
);
|
|
5004
|
+
}
|
|
4947
5005
|
}
|
|
4948
5006
|
}
|
|
4949
5007
|
});
|
|
@@ -4951,7 +5009,7 @@ class StbPlatform {
|
|
|
4951
5009
|
|
|
4952
5010
|
// unsubscribe to an mqtt topic, with logging, to help in debugging
|
|
4953
5011
|
mqttUnsubscribeToTopic(Topic) {
|
|
4954
|
-
if (this.
|
|
5012
|
+
if (this.debugLevel > 0) {
|
|
4955
5013
|
this.log.warn("mqttUnsubscribeToTopic: Unsubscribe from topic:", Topic);
|
|
4956
5014
|
}
|
|
4957
5015
|
mqttClient.unsubscribe(Topic, (err) => {
|
|
@@ -4965,7 +5023,7 @@ class StbPlatform {
|
|
|
4965
5023
|
errDetail,
|
|
4966
5024
|
);
|
|
4967
5025
|
} else {
|
|
4968
|
-
if (this.
|
|
5026
|
+
if (this.debugLevel > 0) {
|
|
4969
5027
|
this.log.warn(
|
|
4970
5028
|
"mqttUnsubscribeToTopic: Unsubscribed OK from %s",
|
|
4971
5029
|
Topic,
|
|
@@ -4986,7 +5044,7 @@ class StbPlatform {
|
|
|
4986
5044
|
mac: "",
|
|
4987
5045
|
ipAddress: "",
|
|
4988
5046
|
});
|
|
4989
|
-
if (this.
|
|
5047
|
+
if (this.debugLevel > 0) {
|
|
4990
5048
|
this.log.warn("setHgoOnlineRunning: publishing to topic:", topic);
|
|
4991
5049
|
}
|
|
4992
5050
|
this.mqttPublishMessage(topic, message, { qos: 2, retain: true });
|
|
@@ -4997,7 +5055,7 @@ class StbPlatform {
|
|
|
4997
5055
|
// the friendlyDeviceName appears on the TV in a popup window
|
|
4998
5056
|
switchChannel(deviceId, deviceName, channelId, channelName) {
|
|
4999
5057
|
try {
|
|
5000
|
-
if (this.
|
|
5058
|
+
if (this.debugLevel > 0) {
|
|
5001
5059
|
this.log.warn(
|
|
5002
5060
|
"switchChannel: channelId %s %s on %s %s",
|
|
5003
5061
|
channelId,
|
|
@@ -5029,7 +5087,7 @@ class StbPlatform {
|
|
|
5029
5087
|
speed: 1,
|
|
5030
5088
|
},
|
|
5031
5089
|
});
|
|
5032
|
-
if (this.
|
|
5090
|
+
if (this.debugLevel > 0) {
|
|
5033
5091
|
this.log.warn("switchChannel: publishing to topic:", topic);
|
|
5034
5092
|
}
|
|
5035
5093
|
this.mqttPublishMessage(topic, payload, {
|
|
@@ -5050,7 +5108,7 @@ class StbPlatform {
|
|
|
5050
5108
|
// speed can be one of: -64 -30 -6 -2 0 2 6 30 64. 0=Paused, 1=Play, >1=FastForward, <0=Rewind
|
|
5051
5109
|
setMediaState(deviceId, deviceName, channelId, speed) {
|
|
5052
5110
|
try {
|
|
5053
|
-
if (this.
|
|
5111
|
+
if (this.debugLevel > 0) {
|
|
5054
5112
|
this.log.warn(
|
|
5055
5113
|
"setMediaState: set state to %s for channelId %s on %s %s",
|
|
5056
5114
|
speed,
|
|
@@ -5094,7 +5152,7 @@ class StbPlatform {
|
|
|
5094
5152
|
// Retain: false, QOS: 0
|
|
5095
5153
|
setPlayerPosition(deviceId, deviceName, relativePosition) {
|
|
5096
5154
|
try {
|
|
5097
|
-
if (this.
|
|
5155
|
+
if (this.debugLevel > 0) {
|
|
5098
5156
|
this.log.warn("setPlayerPosition: deviceId:", deviceId);
|
|
5099
5157
|
}
|
|
5100
5158
|
if (mqttUsername) {
|
|
@@ -5125,7 +5183,7 @@ class StbPlatform {
|
|
|
5125
5183
|
// send a remote control keySequence to the settopbox via mqtt
|
|
5126
5184
|
async sendKey(deviceId, deviceName, keySequence) {
|
|
5127
5185
|
try {
|
|
5128
|
-
if (this.
|
|
5186
|
+
if (this.debugLevel > 0) {
|
|
5129
5187
|
this.log.warn(
|
|
5130
5188
|
"sendKey: keySequence %s, deviceName %s, deviceId %s",
|
|
5131
5189
|
keySequence,
|
|
@@ -5350,7 +5408,7 @@ class StbPlatform {
|
|
|
5350
5408
|
"eventType": "keyDownUp"
|
|
5351
5409
|
}
|
|
5352
5410
|
}
|
|
5353
|
-
*/
|
|
5411
|
+
*/
|
|
5354
5412
|
const payload = JSON.stringify({
|
|
5355
5413
|
source: mqttClientId,
|
|
5356
5414
|
type: "CPE.KeyEvent",
|
|
@@ -5362,9 +5420,7 @@ class StbPlatform {
|
|
|
5362
5420
|
eventType: "keyDownUp",
|
|
5363
5421
|
},
|
|
5364
5422
|
});
|
|
5365
|
-
this.mqttPublishMessage(topic,payload,
|
|
5366
|
-
{ qos: 2, retain: true },
|
|
5367
|
-
);
|
|
5423
|
+
this.mqttPublishMessage(topic, payload, { qos: 2, retain: true });
|
|
5368
5424
|
this.log.debug("sendKey: key %s: send %s done", i + 1, keyName);
|
|
5369
5425
|
|
|
5370
5426
|
// set the Target Media State after key has been sent
|
|
@@ -5431,7 +5487,7 @@ class StbPlatform {
|
|
|
5431
5487
|
// get the settopbox UI status from the settopbox via mqtt
|
|
5432
5488
|
getUiStatus(deviceId, mqttClientId) {
|
|
5433
5489
|
try {
|
|
5434
|
-
if (this.
|
|
5490
|
+
if (this.debugLevel > 0) {
|
|
5435
5491
|
this.log.warn("getUiStatus for deviceId %s", deviceId);
|
|
5436
5492
|
}
|
|
5437
5493
|
if (mqttUsername) {
|
|
@@ -5475,6 +5531,7 @@ class StbDevice {
|
|
|
5475
5531
|
this.entitlements = this.platform.entitlements;
|
|
5476
5532
|
|
|
5477
5533
|
this.deviceId = this.device.deviceId;
|
|
5534
|
+
this._configDevice = this._getConfigDevice(); // cache it once, never changes
|
|
5478
5535
|
this.profileId = -1; // default -1
|
|
5479
5536
|
|
|
5480
5537
|
// set default name on restart, max 14 char
|
|
@@ -5487,9 +5544,7 @@ class StbDevice {
|
|
|
5487
5544
|
|
|
5488
5545
|
// allow user override of device name via config, but limit to max 14 char
|
|
5489
5546
|
if (this.config.devices) {
|
|
5490
|
-
const configDevice = this.
|
|
5491
|
-
(device) => device.deviceId === this.deviceId,
|
|
5492
|
-
);
|
|
5547
|
+
const configDevice = this._configDevice;
|
|
5493
5548
|
if (configDevice && configDevice.name) {
|
|
5494
5549
|
this.name = configDevice.name.substring(0, SETTOPBOX_NAME_MAXLEN);
|
|
5495
5550
|
}
|
|
@@ -5507,29 +5562,28 @@ class StbDevice {
|
|
|
5507
5562
|
this.accessoryConfigured; // true when the accessory is configured
|
|
5508
5563
|
|
|
5509
5564
|
// initial states. Will be updated by mqtt messages
|
|
5565
|
+
this.currentStatusFault = Characteristic.StatusFault.NO_FAULT;
|
|
5566
|
+
this.currentInUse = Characteristic.InUse.NOT_IN_USE;
|
|
5510
5567
|
this.currentPowerState = Characteristic.Active.INACTIVE;
|
|
5511
|
-
this.
|
|
5568
|
+
this.currentStatusActive = Characteristic.Active.INACTIVE;
|
|
5569
|
+
|
|
5512
5570
|
this.currentChannelId = NO_CHANNEL_ID; // string eg SV09038
|
|
5513
|
-
this.
|
|
5514
|
-
this.currentClosedCaptionsState = Characteristic.ClosedCaptions.DISABLED;
|
|
5515
|
-
this.previousClosedCaptionsState = Characteristic.ClosedCaptions.DISABLED;
|
|
5571
|
+
this.currentClosedCaptions = Characteristic.ClosedCaptions.DISABLED;
|
|
5516
5572
|
this.currentMediaState = Characteristic.CurrentMediaState.STOP;
|
|
5517
5573
|
this.targetMediaState = Characteristic.TargetMediaState.STOP;
|
|
5518
5574
|
this.currentPictureMode = Characteristic.PictureMode.STANDARD;
|
|
5519
|
-
this.previousPictureMode = null;
|
|
5520
5575
|
this.currentRecordingState = recordingState.IDLE;
|
|
5521
|
-
this.previousRecordingState = null;
|
|
5522
|
-
this.customPictureMode = 0; // default 0
|
|
5523
|
-
this.currentSourceType = "UNKNOWN";
|
|
5524
|
-
// custom characteristics, default values must be legal values otherwise Homebridge shows a warning
|
|
5525
|
-
this.currentStatusFault = Characteristic.StatusFault.NO_FAULT;
|
|
5526
|
-
this.currentInUse = Characteristic.InUse.NOT_IN_USE;
|
|
5527
|
-
this.previousInUse = Characteristic.InUse.NOT_IN_USE;
|
|
5528
5576
|
this.currentProgramMode = Characteristic.ProgramMode.NO_PROGRAM_SCHEDULED;
|
|
5529
|
-
this.currentStatusActive = Characteristic.Active.ACTIVE; // bool, use o=NotStatusActive, 1=StatusActive
|
|
5530
5577
|
this.currentInputSourceType = Characteristic.InputSourceType.TUNER;
|
|
5531
5578
|
this.currentInputDeviceType = Characteristic.InputDeviceType.TV;
|
|
5532
5579
|
|
|
5580
|
+
this.lastKeyMacroChannelId = null; // string eg $KeyMacro1
|
|
5581
|
+
|
|
5582
|
+
this.customPictureMode = 0; // default 0
|
|
5583
|
+
this.currentSourceType = "UNKNOWN";
|
|
5584
|
+
|
|
5585
|
+
// set defaults for the monitored characteristics
|
|
5586
|
+
|
|
5533
5587
|
this.lastRemoteKeyPressed = -1; // holds the last key pressed, -1 = no key
|
|
5534
5588
|
this.lastRemoteKeyPress0 = []; // holds the time value of the last remote button press for key index i
|
|
5535
5589
|
this.lastRemoteKeyPress1 = []; // holds the time value of the last-1 remote button press for key index i
|
|
@@ -5570,7 +5624,7 @@ class StbDevice {
|
|
|
5570
5624
|
*/
|
|
5571
5625
|
prepareAccessory() {
|
|
5572
5626
|
// Trace-level debug logging (level 3+)
|
|
5573
|
-
if (this.
|
|
5627
|
+
if (this.debugLevel > 2) {
|
|
5574
5628
|
this.log.warn("prepareAccessory");
|
|
5575
5629
|
}
|
|
5576
5630
|
|
|
@@ -5615,14 +5669,16 @@ class StbDevice {
|
|
|
5615
5669
|
|
|
5616
5670
|
// --- Post-publish Characteristic Defaults ---
|
|
5617
5671
|
// Set DisplayOrder after publish (TLV8 base64-encoded byte array)
|
|
5618
|
-
this.televisionService.
|
|
5672
|
+
this.televisionService.updateCharacteristic(
|
|
5619
5673
|
Characteristic.DisplayOrder,
|
|
5620
|
-
|
|
5674
|
+
Buffer.from(this.displayOrder).toString("base64"),
|
|
5675
|
+
);
|
|
5621
5676
|
|
|
5622
5677
|
// Default to no active input on startup
|
|
5623
|
-
this.televisionService
|
|
5624
|
-
|
|
5625
|
-
|
|
5678
|
+
this.televisionService.updateCharacteristic(
|
|
5679
|
+
Characteristic.ActiveIdentifier,
|
|
5680
|
+
NO_INPUT_ID,
|
|
5681
|
+
);
|
|
5626
5682
|
|
|
5627
5683
|
this.accessoryConfigured = true;
|
|
5628
5684
|
}
|
|
@@ -5688,7 +5744,7 @@ class StbDevice {
|
|
|
5688
5744
|
* FirmwareRevision MUST be a numeric string (e.g. "1.2.3") or it won't display in Home app.
|
|
5689
5745
|
*/
|
|
5690
5746
|
prepareAccessoryInformationService() {
|
|
5691
|
-
if (this.
|
|
5747
|
+
if (this.debugLevel > 1) {
|
|
5692
5748
|
this.log.warn("prepareAccessoryInformationService");
|
|
5693
5749
|
}
|
|
5694
5750
|
|
|
@@ -5800,7 +5856,7 @@ class StbDevice {
|
|
|
5800
5856
|
* These appear as "Custom" in the Shortcuts app.
|
|
5801
5857
|
*/
|
|
5802
5858
|
prepareTelevisionService() {
|
|
5803
|
-
if (this.
|
|
5859
|
+
if (this.debugLevel > 1) {
|
|
5804
5860
|
this.log.warn("prepareTelevisionService");
|
|
5805
5861
|
}
|
|
5806
5862
|
|
|
@@ -6001,7 +6057,7 @@ class StbDevice {
|
|
|
6001
6057
|
* Must be linked to the Television service so HomeKit associates them.
|
|
6002
6058
|
*/
|
|
6003
6059
|
prepareTelevisionSpeakerService() {
|
|
6004
|
-
if (this.
|
|
6060
|
+
if (this.debugLevel > 1) {
|
|
6005
6061
|
this.log.warn("prepareTelevisionSpeakerService");
|
|
6006
6062
|
}
|
|
6007
6063
|
|
|
@@ -6054,7 +6110,7 @@ class StbDevice {
|
|
|
6054
6110
|
* Terminated with: [0x00, 0x00]
|
|
6055
6111
|
*/
|
|
6056
6112
|
prepareInputSourceServices() {
|
|
6057
|
-
if (this.
|
|
6113
|
+
if (this.debugLevel > 1) {
|
|
6058
6114
|
this.log.warn("prepareInputSourceServices");
|
|
6059
6115
|
}
|
|
6060
6116
|
|
|
@@ -6087,7 +6143,7 @@ class StbDevice {
|
|
|
6087
6143
|
let chId = `HIDDEN_${i}`;
|
|
6088
6144
|
let visState = Characteristic.CurrentVisibilityState.HIDDEN;
|
|
6089
6145
|
let configState = Characteristic.IsConfigured.NOT_CONFIGURED;
|
|
6090
|
-
this.log.
|
|
6146
|
+
this.log.debug(
|
|
6091
6147
|
"prepareInputSourceServices loading channelList index %s input %s: %s",
|
|
6092
6148
|
i,
|
|
6093
6149
|
i + 1,
|
|
@@ -6118,7 +6174,7 @@ class StbDevice {
|
|
|
6118
6174
|
chFixedName = chName;
|
|
6119
6175
|
}
|
|
6120
6176
|
|
|
6121
|
-
if (this.
|
|
6177
|
+
if (this.debugLevel > 2) {
|
|
6122
6178
|
// log 1 of 95 to 95 of 95 (1-based)
|
|
6123
6179
|
this.log.warn(
|
|
6124
6180
|
"prepareInputSourceServices Adding service %s of %s: %s",
|
|
@@ -6185,9 +6241,9 @@ class StbDevice {
|
|
|
6185
6241
|
|
|
6186
6242
|
// --- Build TLV8 DisplayOrder entry ---
|
|
6187
6243
|
// Format: [type=0x01, length=0x01, value=identifier & 0xFF]
|
|
6188
|
-
// The identifier is masked to 8 bits; supports up to 255 inputs.
|
|
6244
|
+
// The identifier (1-based) is masked to 8 bits; supports up to 255 inputs.
|
|
6189
6245
|
// Reference: https://github.com/homebridge/HAP-NodeJS/issues/644
|
|
6190
|
-
this.displayOrder.push(0x01, 0x01, i & 0xff);
|
|
6246
|
+
this.displayOrder.push(0x01, 0x01, (i + 1) & 0xff);
|
|
6191
6247
|
|
|
6192
6248
|
// Register and link the service
|
|
6193
6249
|
this.accessory.addService(inputService);
|
|
@@ -6227,7 +6283,7 @@ class StbDevice {
|
|
|
6227
6283
|
// runs at the very start, and then every few seconds, so don't log it unless debugging
|
|
6228
6284
|
// doesn't get the data direct from the settop box, but rather: gets it from the this.currentPowerState and this.currentChannelId variables
|
|
6229
6285
|
// which are received by the mqtt messages, which occurs very often
|
|
6230
|
-
if (this.
|
|
6286
|
+
if (this.debugLevel > 0) {
|
|
6231
6287
|
this.log.warn(
|
|
6232
6288
|
"%s: updateDeviceState: powerState %s, mediaState %s [%s], recState %s [%s], channelId %s, eventId %s, sourceType %s, profileDataChanged %s, statusFault %s [%s], programMode %s [%s], statusActive %s [%s], inputDeviceType %s [%s], inputSourceType %s [%s]",
|
|
6233
6289
|
this.name,
|
|
@@ -6241,25 +6297,20 @@ class StbDevice {
|
|
|
6241
6297
|
sourceType,
|
|
6242
6298
|
profileDataChanged,
|
|
6243
6299
|
statusFault,
|
|
6244
|
-
|
|
6300
|
+
CHAR_NAMES.StatusFault[statusFault + 1],
|
|
6245
6301
|
programMode,
|
|
6246
|
-
|
|
6302
|
+
CHAR_NAMES.ProgramMode[programMode + 1],
|
|
6247
6303
|
statusActive,
|
|
6248
6304
|
statusActiveName[statusActive],
|
|
6249
6305
|
inputDeviceType,
|
|
6250
|
-
|
|
6306
|
+
CHAR_NAMES.InputDeviceType[inputDeviceType + 1],
|
|
6251
6307
|
inputSourceType,
|
|
6252
|
-
|
|
6308
|
+
CHAR_NAMES.InputSourceType[inputSourceType + 1],
|
|
6253
6309
|
);
|
|
6254
6310
|
}
|
|
6255
6311
|
|
|
6256
6312
|
// get the config for the device, needed for a few status checks
|
|
6257
|
-
|
|
6258
|
-
if (this.config.devices) {
|
|
6259
|
-
configDevice = this.config.devices.find(
|
|
6260
|
-
(device) => device.deviceId === this.deviceId,
|
|
6261
|
-
);
|
|
6262
|
-
}
|
|
6313
|
+
const configDevice = this._configDevice;
|
|
6263
6314
|
|
|
6264
6315
|
// grab the input variables
|
|
6265
6316
|
// A small helper — reads clearly at point of use
|
|
@@ -6298,30 +6349,30 @@ class StbDevice {
|
|
|
6298
6349
|
}
|
|
6299
6350
|
|
|
6300
6351
|
// profile data is stored on the platform
|
|
6301
|
-
// get the
|
|
6352
|
+
// get the currentClosedCaptions from the currently selected profile (stored in this.profileId)
|
|
6302
6353
|
if (
|
|
6303
6354
|
this.customer.profiles[this.profileId] &&
|
|
6304
6355
|
this.customer.profiles[this.profileId].options.showSubtitles
|
|
6305
6356
|
) {
|
|
6306
|
-
this.
|
|
6357
|
+
this.currentClosedCaptions = Characteristic.ClosedCaptions.ENABLED;
|
|
6307
6358
|
} else {
|
|
6308
|
-
this.
|
|
6359
|
+
this.currentClosedCaptions =
|
|
6309
6360
|
Characteristic.ClosedCaptions.DISABLED;
|
|
6310
6361
|
}
|
|
6311
6362
|
|
|
6312
6363
|
// debugging, helps a lot to see channelName
|
|
6313
|
-
if (this.
|
|
6364
|
+
if (this.debugLevel > 0) {
|
|
6314
6365
|
let curChannel, currentChannelName;
|
|
6315
6366
|
if (this.platform.masterChannelList) {
|
|
6316
|
-
curChannel = this.platform.
|
|
6317
|
-
|
|
6318
|
-
);
|
|
6367
|
+
curChannel = this.platform.masterChannelMap?.get(
|
|
6368
|
+
this.currentChannelId,
|
|
6369
|
+
);
|
|
6319
6370
|
if (curChannel) {
|
|
6320
6371
|
currentChannelName = curChannel.name;
|
|
6321
6372
|
}
|
|
6322
6373
|
}
|
|
6323
6374
|
this.log.warn(
|
|
6324
|
-
"%s: updateDeviceState: currentPowerState %s, currentMediaState %s [%s], currentRecordingState %s [%s], currentChannelId %s [%s], currentSourceType %s,
|
|
6375
|
+
"%s: updateDeviceState: currentPowerState %s, currentMediaState %s [%s], currentRecordingState %s [%s], currentChannelId %s [%s], currentSourceType %s, currentClosedCaptions %s [%s], currentPictureMode %s [%s], profileDataChanged %s, currentStatusFault %s [%s], currentProgramMode %s [%s], currentStatusActive %s",
|
|
6325
6376
|
this.name,
|
|
6326
6377
|
this.currentPowerState,
|
|
6327
6378
|
this.currentMediaState,
|
|
@@ -6331,17 +6382,15 @@ class StbDevice {
|
|
|
6331
6382
|
this.currentChannelId,
|
|
6332
6383
|
currentChannelName,
|
|
6333
6384
|
this.currentSourceType,
|
|
6334
|
-
this.
|
|
6335
|
-
|
|
6336
|
-
this.currentClosedCaptionsState + 1
|
|
6337
|
-
],
|
|
6385
|
+
this.currentClosedCaptions,
|
|
6386
|
+
CHAR_NAMES.ClosedCaptions[this.currentClosedCaptions + 1],
|
|
6338
6387
|
this.currentPictureMode,
|
|
6339
|
-
|
|
6388
|
+
CHAR_NAMES.PictureMode[this.currentPictureMode + 1],
|
|
6340
6389
|
this.profileDataChanged,
|
|
6341
6390
|
this.currentStatusFault,
|
|
6342
|
-
|
|
6391
|
+
CHAR_NAMES.StatusFault[this.currentStatusFault + 1],
|
|
6343
6392
|
this.currentProgramMode,
|
|
6344
|
-
|
|
6393
|
+
CHAR_NAMES.ProgramMode[this.currentProgramMode + 1],
|
|
6345
6394
|
this.currentStatusActive,
|
|
6346
6395
|
);
|
|
6347
6396
|
}
|
|
@@ -6375,46 +6424,49 @@ class StbDevice {
|
|
|
6375
6424
|
currentDeviceName,
|
|
6376
6425
|
);
|
|
6377
6426
|
this.name = currentDeviceName;
|
|
6378
|
-
this.televisionService
|
|
6379
|
-
|
|
6380
|
-
|
|
6427
|
+
this.televisionService.updateCharacteristic(
|
|
6428
|
+
Characteristic.ConfiguredName,
|
|
6429
|
+
currentDeviceName,
|
|
6430
|
+
);
|
|
6381
6431
|
}
|
|
6382
6432
|
|
|
6383
6433
|
// check for change of StatusFault state
|
|
6384
6434
|
if (this.previousStatusFault !== this.currentStatusFault) {
|
|
6385
|
-
|
|
6386
|
-
|
|
6435
|
+
logCharValueChange(
|
|
6436
|
+
this.log,
|
|
6387
6437
|
this.name,
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6438
|
+
"Status Fault",
|
|
6439
|
+
null,
|
|
6440
|
+
this.previousStatusFault,
|
|
6441
|
+
CHAR_NAMES.StatusFault[this.previousStatusFault + 1],
|
|
6442
|
+
this.currentStatusFault,
|
|
6443
|
+
CHAR_NAMES.StatusFault[this.currentStatusFault + 1],
|
|
6444
|
+
);
|
|
6445
|
+
this.televisionService.updateCharacteristic(
|
|
6446
|
+
Characteristic.StatusFault,
|
|
6392
6447
|
this.currentStatusFault,
|
|
6393
|
-
Object.keys(Characteristic.StatusFault)[
|
|
6394
|
-
this.currentStatusFault + 1
|
|
6395
|
-
],
|
|
6396
6448
|
);
|
|
6449
|
+
this.previousStatusFault = this.currentStatusFault;
|
|
6397
6450
|
}
|
|
6398
|
-
this.televisionService
|
|
6399
|
-
.getCharacteristic(Characteristic.StatusFault)
|
|
6400
|
-
.updateValue(this.currentStatusFault);
|
|
6401
|
-
this.previousStatusFault = this.currentStatusFault;
|
|
6402
6451
|
|
|
6403
6452
|
// check for change of StatusActive state
|
|
6404
6453
|
if (this.previousStatusActive !== this.currentStatusActive) {
|
|
6405
|
-
|
|
6406
|
-
|
|
6454
|
+
logCharValueChange(
|
|
6455
|
+
this.log,
|
|
6407
6456
|
this.name,
|
|
6408
|
-
|
|
6409
|
-
|
|
6457
|
+
"Status Active",
|
|
6458
|
+
null,
|
|
6459
|
+
this.previousStatusActive,
|
|
6460
|
+
statusActiveName[this.previousStatusActive],
|
|
6410
6461
|
this.currentStatusActive,
|
|
6411
6462
|
statusActiveName[this.currentStatusActive],
|
|
6412
6463
|
);
|
|
6464
|
+
this.televisionService.updateCharacteristic(
|
|
6465
|
+
Characteristic.StatusActive,
|
|
6466
|
+
this.currentStatusActive,
|
|
6467
|
+
);
|
|
6468
|
+
this.previousStatusActive = this.currentStatusActive;
|
|
6413
6469
|
}
|
|
6414
|
-
this.televisionService
|
|
6415
|
-
.getCharacteristic(Characteristic.StatusActive)
|
|
6416
|
-
.updateValue(this.currentStatusActive);
|
|
6417
|
-
this.previousStatusActive = this.currentStatusActive;
|
|
6418
6470
|
|
|
6419
6471
|
// check for change of power state
|
|
6420
6472
|
// The accessory changes state immediately, and the box takes time to catch up
|
|
@@ -6424,133 +6476,103 @@ class StbDevice {
|
|
|
6424
6476
|
//this.log("Wanted device power state: %s %s", this.currentPowerState, powerStateName[this.currentPowerState]);
|
|
6425
6477
|
//let oldPowerState = this.televisionService.getCharacteristic(Characteristic.Active).value;
|
|
6426
6478
|
if (this.previousPowerState !== this.currentPowerState) {
|
|
6427
|
-
|
|
6428
|
-
|
|
6479
|
+
logCharValueChange(
|
|
6480
|
+
this.log,
|
|
6429
6481
|
this.name,
|
|
6482
|
+
"Power",
|
|
6483
|
+
null,
|
|
6430
6484
|
this.previousPowerState,
|
|
6431
|
-
powerStateName[this.previousPowerState]
|
|
6485
|
+
powerStateName[this.previousPowerState],
|
|
6432
6486
|
this.currentPowerState,
|
|
6433
6487
|
powerStateName[this.currentPowerState],
|
|
6434
6488
|
);
|
|
6489
|
+
this.televisionService.updateCharacteristic(
|
|
6490
|
+
Characteristic.Active,
|
|
6491
|
+
this.currentPowerState,
|
|
6492
|
+
);
|
|
6493
|
+
this.previousPowerState = this.currentPowerState;
|
|
6435
6494
|
}
|
|
6436
|
-
this.televisionService
|
|
6437
|
-
.getCharacteristic(Characteristic.Active)
|
|
6438
|
-
.updateValue(this.currentPowerState);
|
|
6439
|
-
this.previousPowerState = this.currentPowerState;
|
|
6440
6495
|
|
|
6441
6496
|
// check for change of InUse state
|
|
6442
6497
|
if (this.previousInUse !== this.currentInUse) {
|
|
6443
|
-
|
|
6444
|
-
|
|
6498
|
+
logCharValueChange(
|
|
6499
|
+
this.log,
|
|
6445
6500
|
this.name,
|
|
6501
|
+
"In Use",
|
|
6502
|
+
null,
|
|
6446
6503
|
this.previousInUse,
|
|
6447
|
-
|
|
6504
|
+
CHAR_NAMES.InUse[this.previousInUse + 1],
|
|
6505
|
+
this.currentInUse,
|
|
6506
|
+
CHAR_NAMES.InUse[this.currentInUse + 1],
|
|
6507
|
+
);
|
|
6508
|
+
this.televisionService.updateCharacteristic(
|
|
6509
|
+
Characteristic.InUse,
|
|
6448
6510
|
this.currentInUse,
|
|
6449
|
-
Object.keys(Characteristic.InUse)[this.currentInUse + 1],
|
|
6450
6511
|
);
|
|
6512
|
+
this.previousInUse = this.currentInUse;
|
|
6451
6513
|
}
|
|
6452
|
-
this.televisionService
|
|
6453
|
-
.getCharacteristic(Characteristic.InUse)
|
|
6454
|
-
.updateValue(this.currentInUse);
|
|
6455
|
-
this.previousInUse = this.currentInUse;
|
|
6456
6514
|
|
|
6457
6515
|
// check for change of closed captions state
|
|
6458
|
-
//this.log("Previous closed captions state: %s %s", this.previousClosedCaptionsState, closedCaptionsStateName[this.previousClosedCaptionsState]);
|
|
6459
|
-
//this.log("Current closed captions state: %s %s", this.televisionService.getCharacteristic(Characteristic.ClosedCaptions).value, closedCaptionsStateName[this.televisionService.getCharacteristic(Characteristic.ClosedCaptions).value]);
|
|
6460
|
-
//this.log("Wanted closed captions state: %s %s", this.currentClosedCaptionsState, closedCaptionsStateName[this.currentClosedCaptionsState]);
|
|
6461
6516
|
if (
|
|
6462
|
-
this.previousClosedCaptionsState !== this.
|
|
6517
|
+
this.previousClosedCaptionsState !== this.currentClosedCaptions
|
|
6463
6518
|
) {
|
|
6464
|
-
|
|
6465
|
-
|
|
6519
|
+
logCharValueChange(
|
|
6520
|
+
this.log,
|
|
6466
6521
|
this.name,
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
this.
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6522
|
+
"Closed Captions",
|
|
6523
|
+
null,
|
|
6524
|
+
this.previousClosedCaptionsState,
|
|
6525
|
+
CHAR_NAMES.ClosedCaptions[this.previousClosedCaptionsState + 1],
|
|
6526
|
+
this.currentClosedCaptions,
|
|
6527
|
+
CHAR_NAMES.ClosedCaptions[this.currentClosedCaptions + 1],
|
|
6528
|
+
);
|
|
6529
|
+
this.televisionService.updateCharacteristic(
|
|
6530
|
+
Characteristic.ClosedCaptions,
|
|
6531
|
+
this.currentClosedCaptions,
|
|
6475
6532
|
);
|
|
6533
|
+
this.previousClosedCaptionsState = this.currentClosedCaptions;
|
|
6476
6534
|
}
|
|
6477
|
-
this.televisionService
|
|
6478
|
-
.getCharacteristic(Characteristic.ClosedCaptions)
|
|
6479
|
-
.updateValue(this.currentClosedCaptionsState);
|
|
6480
|
-
this.previousClosedCaptionsState = this.currentClosedCaptionsState;
|
|
6481
6535
|
|
|
6482
6536
|
// check for change of picture mode or recordingState (both stored in picture mode)
|
|
6483
|
-
//
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
this.
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
this.currentRecordingState,
|
|
6500
|
-
Object.keys(recordingState)[this.currentRecordingState],
|
|
6501
|
-
);
|
|
6502
|
-
}
|
|
6503
|
-
//this.log("configDevice.customPictureMode found %s, setting PictureMode to %s", (configDevice || {}).customPictureMode, this.currentRecordingState);
|
|
6504
|
-
this.customPictureMode = this.currentRecordingState;
|
|
6505
|
-
this.previousRecordingState = this.currentRecordingState;
|
|
6506
|
-
} else {
|
|
6507
|
-
// PictureMode is used for default function: pictureMode
|
|
6508
|
-
//this.log("previousPictureMode", this.previousPictureMode);
|
|
6509
|
-
//this.log("currentPictureMode", this.currentPictureMode);
|
|
6510
|
-
if (this.previousPictureMode !== this.currentPictureMode) {
|
|
6511
|
-
this.log(
|
|
6512
|
-
"%s: Picture Mode changed from %s [%s] to %s [%s]",
|
|
6513
|
-
this.name,
|
|
6514
|
-
this.previousPictureMode || "-",
|
|
6515
|
-
Object.keys(Characteristic.PictureMode)[
|
|
6516
|
-
this.previousPictureMode + 1
|
|
6517
|
-
] || "unknown",
|
|
6518
|
-
this.currentPictureMode,
|
|
6519
|
-
Object.keys(Characteristic.PictureMode)[
|
|
6520
|
-
this.currentPictureMode + 1
|
|
6521
|
-
],
|
|
6522
|
-
);
|
|
6523
|
-
}
|
|
6524
|
-
//this.log("configDevice.customPictureMode not found %s, setting PictureMode to %s", (configDevice || {}).customPictureMode, this.currentPictureMode);
|
|
6525
|
-
this.customPictureMode = this.currentPictureMode;
|
|
6537
|
+
// PictureMode is used for default function: pictureMode
|
|
6538
|
+
if (this.previousPictureMode !== this.currentPictureMode) {
|
|
6539
|
+
logCharValueChange(
|
|
6540
|
+
this.log,
|
|
6541
|
+
this.name,
|
|
6542
|
+
"Picture Mode",
|
|
6543
|
+
null,
|
|
6544
|
+
this.previousPictureMode,
|
|
6545
|
+
CHAR_NAMES.PictureMode[this.previousPictureMode + 1],
|
|
6546
|
+
this.currentPictureMode,
|
|
6547
|
+
CHAR_NAMES.PictureMode[this.currentPictureMode + 1],
|
|
6548
|
+
);
|
|
6549
|
+
this.televisionService.updateCharacteristic(
|
|
6550
|
+
Characteristic.PictureMode,
|
|
6551
|
+
this.customPictureMode,
|
|
6552
|
+
);
|
|
6526
6553
|
this.previousPictureMode = this.currentPictureMode;
|
|
6527
6554
|
}
|
|
6528
|
-
//this.log("setting PictureMode to %s", this.customPictureMode);
|
|
6529
|
-
this.televisionService
|
|
6530
|
-
.getCharacteristic(Characteristic.PictureMode)
|
|
6531
|
-
.updateValue(this.customPictureMode);
|
|
6532
6555
|
|
|
6533
|
-
// check for change of ProgramMode
|
|
6556
|
+
// check for change of ProgramMode
|
|
6534
6557
|
if (this.previousProgramMode !== this.currentProgramMode) {
|
|
6535
|
-
|
|
6536
|
-
|
|
6558
|
+
logCharValueChange(
|
|
6559
|
+
this.log,
|
|
6537
6560
|
this.name,
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6561
|
+
"Program Mode",
|
|
6562
|
+
null,
|
|
6563
|
+
this.previousProgramMode,
|
|
6564
|
+
CHAR_NAMES.ProgramMode[this.previousProgramMode + 1],
|
|
6542
6565
|
this.currentProgramMode,
|
|
6543
|
-
|
|
6544
|
-
this.currentProgramMode + 1
|
|
6545
|
-
],
|
|
6566
|
+
CHAR_NAMES.ProgramMode[this.currentProgramMode + 1],
|
|
6546
6567
|
);
|
|
6568
|
+
this.televisionService.updateCharacteristic(
|
|
6569
|
+
Characteristic.ProgramMode,
|
|
6570
|
+
this.currentProgramMode,
|
|
6571
|
+
);
|
|
6572
|
+
this.previousProgramMode = this.currentProgramMode;
|
|
6547
6573
|
}
|
|
6548
|
-
this.televisionService
|
|
6549
|
-
.getCharacteristic(Characteristic.ProgramMode)
|
|
6550
|
-
.updateValue(this.currentProgramMode);
|
|
6551
|
-
this.previousProgramMode = this.currentProgramMode;
|
|
6552
6574
|
|
|
6553
|
-
// check for change of
|
|
6575
|
+
// check for change of ActiveIdentifier (channel, 1-based)
|
|
6554
6576
|
// temporarily wrapped this in a try-catch to capture any errors
|
|
6555
6577
|
//this.log("Before error trap");
|
|
6556
6578
|
let searchChannelId = this.currentChannelId; // this.currentChannelId is a string eg SV09038
|
|
@@ -6564,9 +6586,8 @@ class StbDevice {
|
|
|
6564
6586
|
searchChannelId,
|
|
6565
6587
|
);
|
|
6566
6588
|
// get the name from the master channel list
|
|
6567
|
-
let masterChannelApp =
|
|
6568
|
-
(
|
|
6569
|
-
);
|
|
6589
|
+
let masterChannelApp =
|
|
6590
|
+
this.platform.masterChannelMap.get(searchChannelId);
|
|
6570
6591
|
//this.log("found masterChannelApp", masterChannelApp)
|
|
6571
6592
|
// now look again in the master channel list to find this channel with the same name but not an app id
|
|
6572
6593
|
if (masterChannelApp) {
|
|
@@ -6597,34 +6618,30 @@ class StbDevice {
|
|
|
6597
6618
|
//this.log("After error trap. searchChannelId:", searchChannelId);
|
|
6598
6619
|
|
|
6599
6620
|
// search by subtype in the inputServices array, index 0 = input 1, subtype: 'input_SV09038',
|
|
6600
|
-
const oldActiveIdentifier = this.televisionService.getCharacteristic(
|
|
6601
|
-
Characteristic.ActiveIdentifier,
|
|
6602
|
-
).value;
|
|
6603
|
-
//this.log("updateDeviceState: oldActiveIdentifier %s, currentActiveIdentifier %s, searchChannelId %s", oldActiveIdentifier, currentActiveIdentifier, searchChannelId)
|
|
6604
|
-
//this.log("this.inputServices")
|
|
6605
|
-
//this.log(this.inputServices)
|
|
6606
6621
|
// ActiveIdentifier: 1-based: 1=Input1, 2=Input2, etc
|
|
6607
6622
|
// channelList: 0-based: 0=index0, 1=index1, etc
|
|
6623
|
+
// Single scan: reused for both ActiveIdentifier and InputDeviceType/InputSourceType updates below.
|
|
6624
|
+
// searchChannelId equals this.currentChannelId except when an app ID has been remapped,
|
|
6625
|
+
// in which case the remapped ID is the correct one to locate in inputServices.
|
|
6626
|
+
let currInputIndex = this.inputServices.findIndex(
|
|
6627
|
+
(InputSource) => InputSource.subtype === "input_" + searchChannelId,
|
|
6628
|
+
);
|
|
6629
|
+
// if nothing found, set to NO_INPUT_ID to clear the name from the Home app tile
|
|
6608
6630
|
currentActiveIdentifier =
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
if (
|
|
6614
|
-
currentActiveIdentifier = NO_INPUT_ID;
|
|
6615
|
-
} // if nothing found, set to NO_INPUT_ID to clear the name from the Home app tile
|
|
6616
|
-
//this.log("found searchChannelId at currentActiveIdentifier ", currentActiveIdentifier)
|
|
6617
|
-
|
|
6618
|
-
if (oldActiveIdentifier !== currentActiveIdentifier) {
|
|
6631
|
+
currInputIndex >= 0 ? currInputIndex + 1 : NO_INPUT_ID;
|
|
6632
|
+
let currInputNumber = currInputIndex >= 0 ? currInputIndex + 1 : null;
|
|
6633
|
+
if (currInputIndex < 0) currInputIndex = null;
|
|
6634
|
+
|
|
6635
|
+
if (this.previousActiveIdentifier !== currentActiveIdentifier) {
|
|
6619
6636
|
// get names from loaded channel list. Using Ch Up/Ch Down buttons on the remote rolls around the profile channel list
|
|
6620
6637
|
// what happens if the TV is changed to another profile?
|
|
6621
6638
|
let oldName = NO_CHANNEL_NAME,
|
|
6622
6639
|
newName = oldName; // default to UNKNOWN
|
|
6623
6640
|
if (
|
|
6624
|
-
|
|
6625
|
-
this.channelList[
|
|
6641
|
+
this.previousActiveIdentifier !== NO_INPUT_ID &&
|
|
6642
|
+
this.channelList[this.previousActiveIdentifier - 1]
|
|
6626
6643
|
) {
|
|
6627
|
-
oldName = this.channelList[
|
|
6644
|
+
oldName = this.channelList[this.previousActiveIdentifier - 1].name;
|
|
6628
6645
|
}
|
|
6629
6646
|
|
|
6630
6647
|
if (
|
|
@@ -6633,18 +6650,21 @@ class StbDevice {
|
|
|
6633
6650
|
) {
|
|
6634
6651
|
newName = this.channelList[currentActiveIdentifier - 1].name;
|
|
6635
6652
|
}
|
|
6636
|
-
|
|
6637
|
-
|
|
6653
|
+
logCharValueChange(
|
|
6654
|
+
this.log,
|
|
6638
6655
|
this.name,
|
|
6639
|
-
|
|
6640
|
-
|
|
6656
|
+
"Channel",
|
|
6657
|
+
null,
|
|
6658
|
+
this.previousActiveIdentifier,
|
|
6659
|
+
oldName,
|
|
6641
6660
|
currentActiveIdentifier,
|
|
6642
6661
|
newName,
|
|
6643
6662
|
);
|
|
6644
|
-
this.televisionService
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6663
|
+
this.televisionService.updateCharacteristic(
|
|
6664
|
+
Characteristic.ActiveIdentifier,
|
|
6665
|
+
currentActiveIdentifier,
|
|
6666
|
+
);
|
|
6667
|
+
this.previousActiveIdentifier = currentActiveIdentifier;
|
|
6648
6668
|
}
|
|
6649
6669
|
|
|
6650
6670
|
// +++++++++++++++ Input Service characteristics ++++++++++++++
|
|
@@ -6660,97 +6680,76 @@ class StbDevice {
|
|
|
6660
6680
|
.setCharacteristic(Characteristic.TargetVisibilityState, visState);
|
|
6661
6681
|
*/
|
|
6662
6682
|
// check for change of InputDeviceType state: (a characteristic of Input Source)
|
|
6663
|
-
|
|
6664
|
-
//this.log('looking for input subtype ', 'input_' + this.currentChannelId)
|
|
6665
|
-
let currInputIndex = this.inputServices.findIndex(
|
|
6666
|
-
(InputSource) =>
|
|
6667
|
-
InputSource.subtype === "input_" + this.currentChannelId,
|
|
6668
|
-
);
|
|
6669
|
-
let currInputNumber = currInputIndex + 1;
|
|
6670
|
-
if (currInputIndex < 0) {
|
|
6671
|
-
currInputIndex = null;
|
|
6672
|
-
currInputNumber = null;
|
|
6673
|
-
}
|
|
6674
6683
|
//this.log('found input index %s input %s subtype %s', currInputIndex, currInputIndex+1, (this.inputServices[currInputIndex] || {}).subtype)
|
|
6675
6684
|
if (this.previousInputDeviceType !== this.currentInputDeviceType) {
|
|
6676
|
-
|
|
6677
|
-
|
|
6685
|
+
logCharValueChange(
|
|
6686
|
+
this.log,
|
|
6678
6687
|
this.name,
|
|
6679
|
-
|
|
6680
|
-
this.currentChannelId,
|
|
6681
|
-
this.previousInputDeviceType
|
|
6682
|
-
|
|
6683
|
-
this.previousInputDeviceType + 1
|
|
6684
|
-
] || "unknown",
|
|
6688
|
+
"Input Device Type",
|
|
6689
|
+
currInputNumber + " " +this.currentChannelId,
|
|
6690
|
+
this.previousInputDeviceType,
|
|
6691
|
+
CHAR_NAMES.InputDeviceType[this.previousInputDeviceType + 1],
|
|
6685
6692
|
this.currentInputDeviceType,
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
.updateValue(this.currentInputDeviceType);
|
|
6693
|
+
CHAR_NAMES.InputDeviceType[this.currentInputDeviceType + 1],
|
|
6694
|
+
);
|
|
6695
|
+
if (currInputIndex !== null) {
|
|
6696
|
+
this.inputServices[currInputIndex].updateCharacteristic(
|
|
6697
|
+
Characteristic.InputDeviceType,
|
|
6698
|
+
this.currentInputDeviceType,
|
|
6699
|
+
);
|
|
6700
|
+
}
|
|
6701
|
+
this.previousInputDeviceType = this.currentInputDeviceType;
|
|
6696
6702
|
}
|
|
6697
|
-
this.previousInputDeviceType = this.currentInputDeviceType;
|
|
6698
6703
|
|
|
6699
6704
|
// check for change of InputSourceType state: (a characteristic of Input Source)
|
|
6700
6705
|
if (this.previousInputSourceType !== this.currentInputSourceType) {
|
|
6701
|
-
|
|
6702
|
-
|
|
6706
|
+
logCharValueChange(
|
|
6707
|
+
this.log,
|
|
6703
6708
|
this.name,
|
|
6704
|
-
|
|
6705
|
-
this.currentChannelId,
|
|
6706
|
-
this.previousInputSourceType
|
|
6707
|
-
|
|
6708
|
-
this.previousInputSourceType + 1
|
|
6709
|
-
] || "unknown",
|
|
6709
|
+
"Input Source Type",
|
|
6710
|
+
currInputNumber + " " +this.currentChannelId,
|
|
6711
|
+
this.previousInputSourceType,
|
|
6712
|
+
CHAR_NAMES.InputSourceType[this.previousInputSourceType + 1],
|
|
6710
6713
|
this.currentInputSourceType,
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6714
|
+
CHAR_NAMES.InputSourceType[this.currentInputSourceType + 1],
|
|
6715
|
+
);
|
|
6716
|
+
if (currInputIndex !== null) {
|
|
6717
|
+
this.inputServices[currInputIndex].updateCharacteristic(
|
|
6718
|
+
Characteristic.InputSourceType,
|
|
6719
|
+
this.currentInputSourceType,
|
|
6720
|
+
);
|
|
6721
|
+
} // generates Homebridge warning
|
|
6722
|
+
this.previousInputSourceType = this.currentInputSourceType;
|
|
6715
6723
|
}
|
|
6716
|
-
// [12/11/2022, 12:22:37] [homebridge-eosstb] This plugin generated a warning from the characteristic 'Input Source Type': Characteristic not in required or optional characteristic section for service Television. Adding anyway.. See https://homebridge.io/w/JtMGR for more info.
|
|
6717
|
-
if (currInputIndex) {
|
|
6718
|
-
this.inputServices[currInputIndex]
|
|
6719
|
-
.getCharacteristic(Characteristic.InputSourceType)
|
|
6720
|
-
.updateValue(this.currentInputSourceType);
|
|
6721
|
-
} // generates Homebridge warning
|
|
6722
|
-
this.previousInputSourceType = this.currentInputSourceType;
|
|
6723
|
-
//this.log('++++DEBUG: this.inputServices[currInputIndex]')
|
|
6724
|
-
//this.log(this.inputServices[currInputIndex])
|
|
6725
6724
|
|
|
6726
6725
|
// +++++++++++++++ end of Input Service characteristics ++++++++++++++
|
|
6727
6726
|
|
|
6728
6727
|
// check for change of current media state
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
if (prevCurrentMediaState !== this.currentMediaState) {
|
|
6733
|
-
this.log(
|
|
6734
|
-
"%s: Current Media state changed from %s [%s] to %s [%s]",
|
|
6728
|
+
if (this.previousMediaState !== this.currentMediaState) {
|
|
6729
|
+
logCharValueChange(
|
|
6730
|
+
this.log,
|
|
6735
6731
|
this.name,
|
|
6736
|
-
|
|
6737
|
-
|
|
6732
|
+
"Media State",
|
|
6733
|
+
null,
|
|
6734
|
+
this.previousMediaState,
|
|
6735
|
+
currentMediaStateName(this.previousMediaState),
|
|
6738
6736
|
this.currentMediaState,
|
|
6739
6737
|
currentMediaStateName(this.currentMediaState),
|
|
6740
6738
|
);
|
|
6741
|
-
|
|
6742
6739
|
// set targetMediaState to same as currentMediaState as long as currentMediaState is <= 2 (supports 0 PLAY, 1 PAUSE, 2 STOP)
|
|
6743
6740
|
if (this.currentMediaState <= Characteristic.TargetMediaState.STOP) {
|
|
6744
6741
|
this.targetMediaState = this.currentMediaState;
|
|
6745
|
-
this.televisionService
|
|
6746
|
-
|
|
6747
|
-
|
|
6742
|
+
this.televisionService.updateCharacteristic(
|
|
6743
|
+
Characteristic.TargetMediaState,
|
|
6744
|
+
this.targetMediaState,
|
|
6745
|
+
);
|
|
6748
6746
|
}
|
|
6747
|
+
this.televisionService.updateCharacteristic(
|
|
6748
|
+
Characteristic.CurrentMediaState,
|
|
6749
|
+
this.currentMediaState,
|
|
6750
|
+
);
|
|
6751
|
+
this.previousMediaState = this.currentMediaState;
|
|
6749
6752
|
}
|
|
6750
|
-
this.televisionService
|
|
6751
|
-
.getCharacteristic(Characteristic.CurrentMediaState)
|
|
6752
|
-
.updateValue(this.currentMediaState);
|
|
6753
|
-
this.previousMediaState = this.currentMediaState;
|
|
6754
6753
|
|
|
6755
6754
|
// check for change of profile
|
|
6756
6755
|
if (this.profileDataChanged) {
|
|
@@ -6775,7 +6774,7 @@ class StbDevice {
|
|
|
6775
6774
|
// refresh the channel list that shows in the Home app
|
|
6776
6775
|
async refreshDeviceChannelList(callback) {
|
|
6777
6776
|
try {
|
|
6778
|
-
if (this.
|
|
6777
|
+
if (this.debugLevel > 1) {
|
|
6779
6778
|
this.log.warn("%s: refreshDeviceChannelList", this.name);
|
|
6780
6779
|
}
|
|
6781
6780
|
this.log("%s: Refreshing device channel list...", this.name);
|
|
@@ -6802,24 +6801,15 @@ class StbDevice {
|
|
|
6802
6801
|
|
|
6803
6802
|
// limit the amount of max channels to load as Apple HomeKit is limited to 100 services per accessory.
|
|
6804
6803
|
// if a config exists for this device, read the users configured maxSources, if it exists
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
);
|
|
6811
|
-
if (configDevice) {
|
|
6812
|
-
// homebridge config for this device exists, read maxSources (if exists)
|
|
6813
|
-
maxSources = Math.min(
|
|
6814
|
-
configDevice.maxChannels || maxSources,
|
|
6815
|
-
maxSources,
|
|
6816
|
-
);
|
|
6817
|
-
}
|
|
6818
|
-
}
|
|
6804
|
+
const configDevice = this._configDevice;
|
|
6805
|
+
const maxChannels = configDevice.maxChannels;
|
|
6806
|
+
const maxSources = maxChannels
|
|
6807
|
+
? Math.min(maxChannels, MAX_INPUT_SOURCES)
|
|
6808
|
+
: MAX_INPUT_SOURCES;
|
|
6819
6809
|
|
|
6820
6810
|
// get a user configured Profile, if it exists, otherwise we will use the default Profile for the channel list
|
|
6821
6811
|
let wantedProfile;
|
|
6822
|
-
if (this.
|
|
6812
|
+
if (this.debugLevel > 1) {
|
|
6823
6813
|
this.log.warn("%s: Getting profile data from config", this.name);
|
|
6824
6814
|
}
|
|
6825
6815
|
if (configDevice) {
|
|
@@ -6828,7 +6818,7 @@ class StbDevice {
|
|
|
6828
6818
|
(profile) => profile.name === configDevice.profile,
|
|
6829
6819
|
);
|
|
6830
6820
|
if (wantedProfile) {
|
|
6831
|
-
if (this.
|
|
6821
|
+
if (this.debugLevel > 1) {
|
|
6832
6822
|
this.log.warn(
|
|
6833
6823
|
"%s: Configured profile found: '%s'",
|
|
6834
6824
|
this.name,
|
|
@@ -6843,7 +6833,7 @@ class StbDevice {
|
|
|
6843
6833
|
wantedProfile = this.customer.profiles.find(
|
|
6844
6834
|
(profile) => profile.profileId === this.device.defaultProfileId,
|
|
6845
6835
|
);
|
|
6846
|
-
if (this.
|
|
6836
|
+
if (this.debugLevel > 1) {
|
|
6847
6837
|
this.log.warn(
|
|
6848
6838
|
"%s: No user-configured profile found, reverting to default profile: '%s'",
|
|
6849
6839
|
this.name,
|
|
@@ -6875,7 +6865,7 @@ class StbDevice {
|
|
|
6875
6865
|
);
|
|
6876
6866
|
let subscribedChIds = []; // an array of channelIds: SV00302, SV09091, etc
|
|
6877
6867
|
if (wantedProfile.favoriteChannels.length > 0) {
|
|
6878
|
-
if (this.
|
|
6868
|
+
if (this.debugLevel > 1) {
|
|
6879
6869
|
this.log.warn(
|
|
6880
6870
|
"%s: Loading channels from profile '%s' into the subscribedChIds",
|
|
6881
6871
|
this.name,
|
|
@@ -6896,7 +6886,7 @@ class StbDevice {
|
|
|
6896
6886
|
(this.mostWatched || []).length > 0
|
|
6897
6887
|
) {
|
|
6898
6888
|
// load by mostWatched sort order
|
|
6899
|
-
if (this.
|
|
6889
|
+
if (this.debugLevel > 1) {
|
|
6900
6890
|
this.log.warn(
|
|
6901
6891
|
"%s: Loading channel using most watched sort order",
|
|
6902
6892
|
this.name,
|
|
@@ -6906,7 +6896,7 @@ class StbDevice {
|
|
|
6906
6896
|
const favoriteChannelsSet = new Set(wantedProfile.favoriteChannels);
|
|
6907
6897
|
this.mostWatched.forEach((mostWatchedChannelId) => {
|
|
6908
6898
|
if (favoriteChannelsSet.has(mostWatchedChannelId)) {
|
|
6909
|
-
if (this.
|
|
6899
|
+
if (this.debugLevel > 2) {
|
|
6910
6900
|
this.log.warn(
|
|
6911
6901
|
"%s: Loading channel using most watched sort order. Channel %s found, loading at index %s",
|
|
6912
6902
|
this.name,
|
|
@@ -6919,14 +6909,14 @@ class StbDevice {
|
|
|
6919
6909
|
});
|
|
6920
6910
|
} else {
|
|
6921
6911
|
// load by standard sort order
|
|
6922
|
-
if (this.
|
|
6912
|
+
if (this.debugLevel > 1) {
|
|
6923
6913
|
this.log.warn(
|
|
6924
6914
|
"%s: Loading channel using standard sort order",
|
|
6925
6915
|
this.name,
|
|
6926
6916
|
);
|
|
6927
6917
|
}
|
|
6928
6918
|
wantedProfile.favoriteChannels.forEach((channel) => {
|
|
6929
|
-
if (this.
|
|
6919
|
+
if (this.debugLevel > 1) {
|
|
6930
6920
|
this.log.warn(
|
|
6931
6921
|
"%s: Loading channel using standard sort order. Channel %s found, loading at index %s",
|
|
6932
6922
|
this.name,
|
|
@@ -6938,7 +6928,7 @@ class StbDevice {
|
|
|
6938
6928
|
});
|
|
6939
6929
|
}
|
|
6940
6930
|
}
|
|
6941
|
-
if (this.
|
|
6931
|
+
if (this.debugLevel > 1) {
|
|
6942
6932
|
this.log.warn(
|
|
6943
6933
|
"%s: subscribedChIds.length: %s",
|
|
6944
6934
|
this.name,
|
|
@@ -6954,11 +6944,11 @@ class StbDevice {
|
|
|
6954
6944
|
|
|
6955
6945
|
// if the subscribedChIds is empty, load the channels from the master channel list
|
|
6956
6946
|
// sorted by logicalChannelNumber, including only entitled channels
|
|
6957
|
-
//if (this.
|
|
6947
|
+
//if (this.debugLevel > 1) { this.log.warn("%s: Checking if subscribed channel list is needed", this.name); }
|
|
6958
6948
|
//this.log.warn("%s: this.customer.profiles", this.name, this.customer.profiles);
|
|
6959
6949
|
//wantedProfile = this.customer.profiles.find(profile => profile.profileId === this.device.defaultProfileId);
|
|
6960
6950
|
if (subscribedChIds.length === 0) {
|
|
6961
|
-
if (this.
|
|
6951
|
+
if (this.debugLevel > 1) {
|
|
6962
6952
|
this.log(
|
|
6963
6953
|
"%s: Profile '%s' contains 0 favorite channels. Channel list will be loaded from master channel list",
|
|
6964
6954
|
this.name,
|
|
@@ -6967,13 +6957,18 @@ class StbDevice {
|
|
|
6967
6957
|
}
|
|
6968
6958
|
// get a clean list of entitled channels (will not be in correct order)
|
|
6969
6959
|
// some entitlements are not in the masterchannelList, these must be ignored
|
|
6970
|
-
//if (this.
|
|
6960
|
+
//if (this.debugLevel > 1) { this.log.warn("%s: Checking %s entitlements within %s channels in the master channel list", this.name, this.platform.session.entitlements.length, this.platform.masterChannelList.length); }
|
|
6971
6961
|
|
|
6972
6962
|
// entitlements needs to be reworked, currently load everything
|
|
6973
6963
|
//this.log.warn("%s: Loading all channels into the subscribedChIds", this.name)
|
|
6974
6964
|
//this.log.warn("%s: masterChannelList.length", this.name, this.platform.masterChannelList.length)
|
|
6975
6965
|
//this.log.warn("%s: this.entitlements %s", this.name, this.entitlements)
|
|
6976
6966
|
//this.log.warn("%s: this.platform.entitlements.entitlements %s", this.name, this.platform.entitlements.entitlements)
|
|
6967
|
+
// build Set once BEFORE the masterChannelList.forEach loop:
|
|
6968
|
+
const entitlementIdSet = new Set(
|
|
6969
|
+
this.platform.entitlements.entitlements.map((e) => e.id),
|
|
6970
|
+
);
|
|
6971
|
+
|
|
6977
6972
|
this.platform.masterChannelList.forEach((channel) => {
|
|
6978
6973
|
// check entitlements of this channel
|
|
6979
6974
|
// channel.linearProducts is an array of entitlement codes assigned to a channel, each channel can have multiple entitlement codes
|
|
@@ -6982,7 +6977,6 @@ class StbDevice {
|
|
|
6982
6977
|
// [{ casIndicator: 0, id: '600000001' }, { casIndicator: 0, id: '600000080' }, { casIndicator: 1, id: '600000070' }, { casIndicator: 1, id: '600000300' }]
|
|
6983
6978
|
// control channel: SV09038 SRF 1 HD (entitled), with "linearProducts": [ '100000000', '100000001', '600000300' ],
|
|
6984
6979
|
// control channel: SV06321 Nicktoons (not entitled), with linearProducts: [ '601007005' ],
|
|
6985
|
-
let isEntitled = false;
|
|
6986
6980
|
this.log.debug(
|
|
6987
6981
|
"%s: checking entitlements for %s %s",
|
|
6988
6982
|
this.name,
|
|
@@ -6994,18 +6988,8 @@ class StbDevice {
|
|
|
6994
6988
|
this.name,
|
|
6995
6989
|
channel.linearProducts,
|
|
6996
6990
|
);
|
|
6997
|
-
|
|
6998
|
-
(
|
|
6999
|
-
if (channel.linearProducts.includes(subscribedlEntitlement.id)) {
|
|
7000
|
-
this.log.debug(
|
|
7001
|
-
"%s: channel channelId %s, linearProducts includes subscribedlEntitlement.id %s, channel is entitled",
|
|
7002
|
-
this.name,
|
|
7003
|
-
channel.id,
|
|
7004
|
-
subscribedlEntitlement.id,
|
|
7005
|
-
);
|
|
7006
|
-
isEntitled = true;
|
|
7007
|
-
}
|
|
7008
|
-
},
|
|
6991
|
+
const isEntitled = channel.linearProducts.some((id) =>
|
|
6992
|
+
entitlementIdSet.has(id),
|
|
7009
6993
|
);
|
|
7010
6994
|
if (isEntitled) {
|
|
7011
6995
|
subscribedChIds.push(channel.id);
|
|
@@ -7024,7 +7008,7 @@ class StbDevice {
|
|
|
7024
7008
|
subscribedChIds.length,
|
|
7025
7009
|
);
|
|
7026
7010
|
}
|
|
7027
|
-
if (this.
|
|
7011
|
+
if (this.debugLevel > 1) {
|
|
7028
7012
|
this.log(
|
|
7029
7013
|
"%s: Subscribed channel list loaded with %s channels",
|
|
7030
7014
|
this.name,
|
|
@@ -7033,7 +7017,7 @@ class StbDevice {
|
|
|
7033
7017
|
}
|
|
7034
7018
|
|
|
7035
7019
|
// recently viewed apps
|
|
7036
|
-
if (this.
|
|
7020
|
+
if (this.debugLevel > 1) {
|
|
7037
7021
|
this.log.warn(
|
|
7038
7022
|
"%s: refreshDeviceChannelList: recentlyUsedApps",
|
|
7039
7023
|
this.name,
|
|
@@ -7041,24 +7025,6 @@ class StbDevice {
|
|
|
7041
7025
|
);
|
|
7042
7026
|
}
|
|
7043
7027
|
|
|
7044
|
-
// grab the current ActiveIdentifier, and currentChannel, it might change during the channel refresh
|
|
7045
|
-
/*
|
|
7046
|
-
let currentActiveIdentifier = NO_INPUT_ID, currentChannel, currentChannelName = NO_CHANNEL_NAME;
|
|
7047
|
-
if (this.accessoryConfigured) {
|
|
7048
|
-
currentActiveIdentifier = this.televisionService.getCharacteristic(Characteristic.ActiveIdentifier).value;
|
|
7049
|
-
}
|
|
7050
|
-
if (currentActiveIdentifier !== NO_INPUT_ID) {
|
|
7051
|
-
currentChannel = this.inputServices[currentActiveIdentifier - 1];
|
|
7052
|
-
currentChannelName = this.inputServices[currentActiveIdentifier - 1].getCharacteristic(Characteristic.ConfiguredName).value;
|
|
7053
|
-
}
|
|
7054
|
-
if (this.config.debugLevel > 0) {
|
|
7055
|
-
this.log.warn("%s: refreshDeviceChannelList: before channel refresh: this.currentChannelId %s currentActiveIdentifier %s currentChannelName %s", this.name, this.currentChannelId, currentActiveIdentifier, currentChannelName);
|
|
7056
|
-
}
|
|
7057
|
-
*/
|
|
7058
|
-
|
|
7059
|
-
//const currentInpIndex = this.inputServices.findIndex(channel => channel.subtype === 'input_' + this.currentChannelId);
|
|
7060
|
-
//this.log("Found before channel load: this.currentChannelId %s found at currentInpIndex %s", this.currentChannelId, currentInpIndex);
|
|
7061
|
-
|
|
7062
7028
|
////////////////////////////////////////////////////////
|
|
7063
7029
|
// load the input list
|
|
7064
7030
|
////////////////////////////////////////////////////////
|
|
@@ -7144,30 +7110,26 @@ class StbDevice {
|
|
|
7144
7110
|
i,
|
|
7145
7111
|
subscribedChIds[i],
|
|
7146
7112
|
);
|
|
7147
|
-
channel = this.platform.
|
|
7148
|
-
(channel) => channel.id === subscribedChIds[i],
|
|
7149
|
-
);
|
|
7113
|
+
channel = this.platform.masterChannelMap.get(subscribedChIds[i]);
|
|
7150
7114
|
if (!channel) {
|
|
7151
|
-
const
|
|
7152
|
-
|
|
7115
|
+
const newChannel = {
|
|
7116
|
+
id: subscribedChIds[i],
|
|
7117
|
+
name: customChannel.name || "Channel " + subscribedChIds[i],
|
|
7118
|
+
logicalChannelNumber:
|
|
7119
|
+
10000 + this.platform.masterChannelList.length,
|
|
7120
|
+
linearProducts: this.platform.entitlements.entitlements[0].id,
|
|
7121
|
+
};
|
|
7122
|
+
newChannel.configuredName = newChannel.name;
|
|
7153
7123
|
this.log(
|
|
7154
7124
|
"%s: Unknown channel %s [%s] discovered. Adding to the master channel list",
|
|
7155
7125
|
this.name,
|
|
7156
|
-
|
|
7157
|
-
|
|
7126
|
+
newChannel.id,
|
|
7127
|
+
newChannel.name,
|
|
7158
7128
|
);
|
|
7159
|
-
this.platform.masterChannelList.push({
|
|
7160
|
-
id: subscribedChIds[i],
|
|
7161
|
-
name: newChName,
|
|
7162
|
-
logicalChannelNumber:
|
|
7163
|
-
10000 + this.platform.masterChannelList.length, // integer
|
|
7164
|
-
linearProducts: this.platform.entitlements.entitlements[0].id, // must be a valid entitlement id
|
|
7165
|
-
});
|
|
7166
7129
|
// refresh channel as the not found channel will now be in the masterChannelList
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
channel.configuredName = channel.name; // set a configured name same as name
|
|
7130
|
+
this.platform.masterChannelList.push(newChannel);
|
|
7131
|
+
this.platform.masterChannelMap.set(subscribedChIds[i], newChannel);
|
|
7132
|
+
channel = newChannel;
|
|
7171
7133
|
} else {
|
|
7172
7134
|
// show some useful debug data
|
|
7173
7135
|
this.log.debug(
|
|
@@ -7256,7 +7218,7 @@ class StbDevice {
|
|
|
7256
7218
|
// update accessory only when configured, as this.inputServices[i] can only be updated when it exists
|
|
7257
7219
|
if (this.accessoryConfigured) {
|
|
7258
7220
|
// update existing services
|
|
7259
|
-
if (this.
|
|
7221
|
+
if (this.debugLevel > 2) {
|
|
7260
7222
|
this.log.warn(
|
|
7261
7223
|
"Adding %s %s to input %s at index %s",
|
|
7262
7224
|
channel.id,
|
|
@@ -7303,9 +7265,10 @@ class StbDevice {
|
|
|
7303
7265
|
//this.log("DEBUG: this.currentChannelId %s", this.currentChannelId)
|
|
7304
7266
|
//this.log("DEBUG: currentInput %s", currentInput)
|
|
7305
7267
|
if (currentInput) {
|
|
7268
|
+
const currentInputIndex = this.inputServices.indexOf(currentInput);
|
|
7306
7269
|
this.televisionService.updateCharacteristic(
|
|
7307
|
-
Characteristic.ActiveIdentifier,
|
|
7308
|
-
|
|
7270
|
+
Characteristic.ActiveIdentifier,
|
|
7271
|
+
currentInputIndex + 1, // Identifier is always index + 1
|
|
7309
7272
|
);
|
|
7310
7273
|
} else {
|
|
7311
7274
|
// not found, set to NO_INPUT_ID
|
|
@@ -7317,40 +7280,6 @@ class StbDevice {
|
|
|
7317
7280
|
}
|
|
7318
7281
|
}
|
|
7319
7282
|
|
|
7320
|
-
// save to disk
|
|
7321
|
-
// not yet active
|
|
7322
|
-
// this.platform.persistConfig(this.deviceId, this.channelList);
|
|
7323
|
-
|
|
7324
|
-
// add the recently used apps, if we are loading from a user profile
|
|
7325
|
-
/*
|
|
7326
|
-
if (this.profileId > 0) {
|
|
7327
|
-
// apps have a channel number starting with "app"
|
|
7328
|
-
let appsToload = this.platform.profiles[this.profileId].recentlyUsedApps;
|
|
7329
|
-
appsToload.forEach( (appId, i) => {
|
|
7330
|
-
this.log("loading app", i, appId);
|
|
7331
|
-
if (i <= maxChs) {
|
|
7332
|
-
// get the channel
|
|
7333
|
-
let foundIndex = this.platform.masterChannelList.findIndex(channel => channel.id === appId);
|
|
7334
|
-
//this.log("foundIndex", foundIndex);
|
|
7335
|
-
if (foundIndex >= 0) {
|
|
7336
|
-
let channel = this.platform.masterChannelList[foundIndex];
|
|
7337
|
-
this.log("loading app", channel);
|
|
7338
|
-
|
|
7339
|
-
// update existing services
|
|
7340
|
-
|
|
7341
|
-
const inputService = this.inputServices[i];
|
|
7342
|
-
inputService
|
|
7343
|
-
.updateCharacteristic(Characteristic.ConfiguredName, channel.name)
|
|
7344
|
-
.updateCharacteristic(Characteristic.IsConfigured, Characteristic.IsConfigured.CONFIGURED)
|
|
7345
|
-
.updateCharacteristic(Characteristic.CurrentVisibilityState, Characteristic.CurrentVisibilityState.SHOWN)
|
|
7346
|
-
.updateCharacteristic(Characteristic.TargetVisibilityState, Characteristic.TargetVisibilityState.SHOWN);
|
|
7347
|
-
|
|
7348
|
-
}
|
|
7349
|
-
}
|
|
7350
|
-
});
|
|
7351
|
-
}
|
|
7352
|
-
*/
|
|
7353
|
-
|
|
7354
7283
|
// for any remaining inputs that may have been previously visible, set to not configured and hidden
|
|
7355
7284
|
//this.log("channelList pre filter:", this.channelList);
|
|
7356
7285
|
//let loadedChs = Math.min(chs, MAX_INPUT_SOURCES);
|
|
@@ -7404,7 +7333,7 @@ class StbDevice {
|
|
|
7404
7333
|
// this is for the web session type as of 13.10.2022
|
|
7405
7334
|
async getMostWatchedChannels(profileId, callback) {
|
|
7406
7335
|
try {
|
|
7407
|
-
if (this.
|
|
7336
|
+
if (this.debugLevel > 1) {
|
|
7408
7337
|
this.log(
|
|
7409
7338
|
"%s: getMostWatchedChannels started with %s",
|
|
7410
7339
|
this.name,
|
|
@@ -7434,14 +7363,14 @@ class StbDevice {
|
|
|
7434
7363
|
"x-profile": profile.profileId,
|
|
7435
7364
|
},
|
|
7436
7365
|
};
|
|
7437
|
-
if (this.
|
|
7366
|
+
if (this.debugLevel > 0) {
|
|
7438
7367
|
this.log.warn("getMostWatchedChannels: GET %s", url);
|
|
7439
7368
|
}
|
|
7440
7369
|
// this.log('getMostWatchedChannels: GET %s', url);
|
|
7441
7370
|
axiosWS
|
|
7442
7371
|
.get(url, config)
|
|
7443
7372
|
.then((response) => {
|
|
7444
|
-
if (this.
|
|
7373
|
+
if (this.debugLevel > 0) {
|
|
7445
7374
|
this.log.warn(
|
|
7446
7375
|
"getMostWatchedChannels: Profile %s: response: %s %s",
|
|
7447
7376
|
profile.name,
|
|
@@ -7449,7 +7378,7 @@ class StbDevice {
|
|
|
7449
7378
|
response.statusText,
|
|
7450
7379
|
);
|
|
7451
7380
|
}
|
|
7452
|
-
if (this.
|
|
7381
|
+
if (this.debugLevel > 2) {
|
|
7453
7382
|
this.log.warn(
|
|
7454
7383
|
"getMostWatchedChannels: %s: response data:",
|
|
7455
7384
|
profile.name,
|
|
@@ -7494,21 +7423,10 @@ class StbDevice {
|
|
|
7494
7423
|
getMaxSources(callback) {
|
|
7495
7424
|
// limit the amount of max channels to load as Apple HomeKit is limited to 100 services per accessory.
|
|
7496
7425
|
// if a config exists for this device, read the users configured maxSources, if it exists
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
(device) => device.deviceId === this.deviceId,
|
|
7502
|
-
);
|
|
7503
|
-
if (configDevice) {
|
|
7504
|
-
// homebridge config for this device exists, read maxSources (if exists)
|
|
7505
|
-
maxSources = Math.min(
|
|
7506
|
-
configDevice.maxChannels || maxSources,
|
|
7507
|
-
maxSources,
|
|
7508
|
-
);
|
|
7509
|
-
}
|
|
7510
|
-
}
|
|
7511
|
-
return maxSources;
|
|
7426
|
+
const maxChannels = this._configDevice.maxChannels;
|
|
7427
|
+
return maxChannels
|
|
7428
|
+
? Math.min(maxChannels, MAX_INPUT_SOURCES)
|
|
7429
|
+
: MAX_INPUT_SOURCES;
|
|
7512
7430
|
//this.log("%s: Setting maxSources to %s", this.name, maxSources);
|
|
7513
7431
|
}
|
|
7514
7432
|
|
|
@@ -7522,12 +7440,12 @@ class StbDevice {
|
|
|
7522
7440
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
7523
7441
|
|
|
7524
7442
|
// get power state
|
|
7525
|
-
|
|
7443
|
+
getPower(callback) {
|
|
7526
7444
|
// fired when the user clicks away from the Remote Control, regardless of which TV was selected
|
|
7527
7445
|
// fired when the Home app wants to refresh the TV tile. Refresh occurs when tile is displayed.
|
|
7528
7446
|
// this.currentPowerState is updated by the polling mechanism
|
|
7529
7447
|
//this.log('getPowerState current power state:', this.currentPowerState);
|
|
7530
|
-
if (this.
|
|
7448
|
+
if (this.debugLevel > 1) {
|
|
7531
7449
|
this.log.warn(
|
|
7532
7450
|
"%s: getPower returning %s [%s]",
|
|
7533
7451
|
this.name,
|
|
@@ -7539,12 +7457,12 @@ class StbDevice {
|
|
|
7539
7457
|
}
|
|
7540
7458
|
|
|
7541
7459
|
// set power state
|
|
7542
|
-
|
|
7460
|
+
setPower(targetPowerState, callback) {
|
|
7543
7461
|
// fired when the user clicks the power button in the TV accessory in the Home app
|
|
7544
7462
|
// fired when the user clicks the TV tile in the Home app
|
|
7545
7463
|
// fired when the first key is pressed after opening the Remote Control
|
|
7546
7464
|
// wantedPowerState is the wanted power state: 0=off, 1=on
|
|
7547
|
-
if (this.
|
|
7465
|
+
if (this.debugLevel > 1) {
|
|
7548
7466
|
this.log.warn(
|
|
7549
7467
|
"%s: setPower targetPowerState:",
|
|
7550
7468
|
this.name,
|
|
@@ -7560,29 +7478,21 @@ class StbDevice {
|
|
|
7560
7478
|
}
|
|
7561
7479
|
|
|
7562
7480
|
// get device name (the accessory visible name)
|
|
7563
|
-
|
|
7481
|
+
getDeviceName(callback) {
|
|
7564
7482
|
// fired by the user changing a the accessory name in Home app accessory setup
|
|
7565
7483
|
// a user can rename any box at any time
|
|
7566
|
-
if (this.
|
|
7484
|
+
if (this.debugLevel > 1) {
|
|
7567
7485
|
this.log.warn("%s: getDeviceName returning '%s'", this.name, this.name);
|
|
7568
7486
|
}
|
|
7569
7487
|
callback(null, this.name);
|
|
7570
7488
|
}
|
|
7571
7489
|
|
|
7572
7490
|
// set device name (change the accessory visible name)
|
|
7573
|
-
|
|
7491
|
+
setDeviceName(deviceName, callback) {
|
|
7574
7492
|
// fired by the user changing the accessory name in Home app accessory setup
|
|
7575
7493
|
|
|
7576
7494
|
// check if user wants to sync the box name
|
|
7577
|
-
|
|
7578
|
-
if (this.config.devices) {
|
|
7579
|
-
const configDevice = this.config.devices.find(
|
|
7580
|
-
(device) => device.deviceId === this.deviceId,
|
|
7581
|
-
);
|
|
7582
|
-
if (configDevice && configDevice.syncName === false) {
|
|
7583
|
-
syncName = configDevice.syncName;
|
|
7584
|
-
}
|
|
7585
|
-
}
|
|
7495
|
+
const syncName = this._configDevice.syncName !== false; // default true
|
|
7586
7496
|
|
|
7587
7497
|
// sync name to physical device if enabled
|
|
7588
7498
|
if (syncName) {
|
|
@@ -7617,7 +7527,7 @@ class StbDevice {
|
|
|
7617
7527
|
deviceName,
|
|
7618
7528
|
);
|
|
7619
7529
|
} else {
|
|
7620
|
-
if (this.
|
|
7530
|
+
if (this.debugLevel > 1) {
|
|
7621
7531
|
this.log.warn(
|
|
7622
7532
|
"%s: setDeviceName: deviceName %s",
|
|
7623
7533
|
this.name,
|
|
@@ -7635,20 +7545,11 @@ class StbDevice {
|
|
|
7635
7545
|
callback(null);
|
|
7636
7546
|
}
|
|
7637
7547
|
|
|
7638
|
-
// get mute state
|
|
7639
|
-
async getMute(callback) {
|
|
7640
|
-
// not supported, but might use somehow in the future
|
|
7641
|
-
if (this.config.debugLevel > 1) {
|
|
7642
|
-
this.log.warn("getMute");
|
|
7643
|
-
}
|
|
7644
|
-
callback(null);
|
|
7645
|
-
}
|
|
7646
|
-
|
|
7647
7548
|
// set mute state
|
|
7648
|
-
|
|
7549
|
+
setMute(muteState, callback) {
|
|
7649
7550
|
// sends the mute command. Mute is boolean
|
|
7650
7551
|
// works for TVs that accept a mute toggle command
|
|
7651
|
-
if (this.
|
|
7552
|
+
if (this.debugLevel > 1) {
|
|
7652
7553
|
this.log.warn("%s: setMute muteState: %s", this.name, muteState);
|
|
7653
7554
|
}
|
|
7654
7555
|
|
|
@@ -7660,43 +7561,27 @@ class StbDevice {
|
|
|
7660
7561
|
this.log("Send key Mute to %s ", this.name);
|
|
7661
7562
|
|
|
7662
7563
|
// Execute command to toggle mute
|
|
7663
|
-
if (this.
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
if (error) {
|
|
7672
|
-
this.log.warn("setMute Error:", stderr.trim());
|
|
7673
|
-
}
|
|
7674
|
-
});
|
|
7675
|
-
} else {
|
|
7676
|
-
this.log("%s: Mute command not configured", this.name);
|
|
7677
|
-
}
|
|
7564
|
+
if (this._configDevice.muteCommand) {
|
|
7565
|
+
// assumes the end device toggles between mute on and mute off with each command
|
|
7566
|
+
exec(this._configDevice.muteCommand, (error, stdout, stderr) => {
|
|
7567
|
+
// Error detection. error is true when an exec error occured
|
|
7568
|
+
if (error) {
|
|
7569
|
+
this.log.warn("setMute Error:", stderr.trim());
|
|
7570
|
+
}
|
|
7571
|
+
});
|
|
7678
7572
|
} else {
|
|
7679
7573
|
this.log("%s: Mute command not configured", this.name);
|
|
7680
7574
|
}
|
|
7681
7575
|
}
|
|
7682
7576
|
|
|
7683
|
-
// get volume
|
|
7684
|
-
async getVolume(callback) {
|
|
7685
|
-
// not supported, but might use somehow in the future
|
|
7686
|
-
if (this.config.debugLevel > 1) {
|
|
7687
|
-
this.log.warn("getVolume");
|
|
7688
|
-
}
|
|
7689
|
-
callback(null);
|
|
7690
|
-
}
|
|
7691
|
-
|
|
7692
7577
|
// set volume
|
|
7693
|
-
|
|
7578
|
+
setVolume(volumeSelectorValue, callback) {
|
|
7694
7579
|
// set the volume of the TV using bash scripts
|
|
7695
7580
|
// the ARRIS box remote control communicates with the stereo via IR commands, not over mqtt
|
|
7696
7581
|
// so volume must be handled over a different method
|
|
7697
7582
|
// here we send execute a bash command on the raspberry pi using the samsungctl command
|
|
7698
7583
|
// to control the authors samsung stereo at 192.168.0.152
|
|
7699
|
-
if (this.
|
|
7584
|
+
if (this.debugLevel > 1) {
|
|
7700
7585
|
this.log.warn(
|
|
7701
7586
|
"%s: setVolume volumeSelectorValue:",
|
|
7702
7587
|
this.name,
|
|
@@ -7751,29 +7636,23 @@ class StbDevice {
|
|
|
7751
7636
|
return false;
|
|
7752
7637
|
} else {
|
|
7753
7638
|
// Execute command to change volume, but only if command exists
|
|
7754
|
-
if (this.
|
|
7755
|
-
|
|
7756
|
-
|
|
7639
|
+
if (this._configDevice.volUpCommand) {
|
|
7640
|
+
// assumes the end device toggles between mute on and mute off with each command
|
|
7641
|
+
exec(
|
|
7642
|
+
volumeSelectorValue === Characteristic.VolumeSelector.DECREMENT
|
|
7643
|
+
? this._configDevice.volDownCommand
|
|
7644
|
+
: this._configDevice.volUpCommand,
|
|
7645
|
+
(error, _stdout, stderr) => {
|
|
7646
|
+
// Error detection. error is true when an exec error occured
|
|
7647
|
+
if (error) {
|
|
7648
|
+
this.log.warn(
|
|
7649
|
+
"%s: setVolume Error: %s",
|
|
7650
|
+
this.name,
|
|
7651
|
+
stderr.trim(),
|
|
7652
|
+
);
|
|
7653
|
+
}
|
|
7654
|
+
},
|
|
7757
7655
|
);
|
|
7758
|
-
if (device && device.volUpCommand && device.volDownCommand) {
|
|
7759
|
-
exec(
|
|
7760
|
-
volumeSelectorValue === Characteristic.VolumeSelector.DECREMENT
|
|
7761
|
-
? device.volDownCommand
|
|
7762
|
-
: device.volUpCommand,
|
|
7763
|
-
(error, _stdout, stderr) => {
|
|
7764
|
-
// Error detection. error is true when an exec error occured
|
|
7765
|
-
if (error) {
|
|
7766
|
-
this.log.warn(
|
|
7767
|
-
"%s: setVolume Error: %s",
|
|
7768
|
-
this.name,
|
|
7769
|
-
stderr.trim(),
|
|
7770
|
-
);
|
|
7771
|
-
}
|
|
7772
|
-
},
|
|
7773
|
-
);
|
|
7774
|
-
} else {
|
|
7775
|
-
this.log("%s: Volume commands not configured", this.name);
|
|
7776
|
-
}
|
|
7777
7656
|
} else {
|
|
7778
7657
|
this.log("%s: Volume commands not configured", this.name);
|
|
7779
7658
|
}
|
|
@@ -7781,39 +7660,20 @@ class StbDevice {
|
|
|
7781
7660
|
}
|
|
7782
7661
|
|
|
7783
7662
|
// get input (TV channel)
|
|
7784
|
-
|
|
7663
|
+
getInput(callback) {
|
|
7785
7664
|
// fired when the user clicks away from the iOS Device TV Remote Control, regardless of which TV was selected
|
|
7786
7665
|
// fired when the icon is clicked in the Home app and HomeKit requests a refresh
|
|
7787
7666
|
// fired when the Home app is opened
|
|
7788
|
-
//
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
// find the this.currentChannelId (eg SV09038) in the accessory inputs and return the inputindex once found
|
|
7793
|
-
// this allows HomeKit to show the selected current channel
|
|
7794
|
-
// as we cannot guarantee the list order due to personalizationServices changing it at any time
|
|
7795
|
-
// we must search by input_channelId within the current accessory InputSource.subtype
|
|
7796
|
-
//this.log.warn('%s: getInput looking for this.currentChannelId %s in this.inputServices', this.name, this.currentChannelId);
|
|
7797
|
-
let currentChannelName = NO_CHANNEL_NAME;
|
|
7798
|
-
let currentInputIndex = this.inputServices.findIndex(
|
|
7799
|
-
(InputSource) => InputSource.subtype === "input_" + this.currentChannelId,
|
|
7800
|
-
);
|
|
7801
|
-
if (currentInputIndex === -1) {
|
|
7802
|
-
currentInputIndex = NO_INPUT_ID - 1;
|
|
7803
|
-
} // if nothing found, set to NO_INPUT_ID to clear the name from the Home app tile
|
|
7804
|
-
if (currentInputIndex > -1 && currentInputIndex !== NO_INPUT_ID - 1) {
|
|
7805
|
-
currentChannelName = this.inputServices[
|
|
7806
|
-
currentInputIndex
|
|
7807
|
-
].getCharacteristic(Characteristic.ConfiguredName).value;
|
|
7808
|
-
}
|
|
7809
|
-
const currentActiveInput = currentInputIndex + 1;
|
|
7810
|
-
if (this.config.debugLevel > 1) {
|
|
7667
|
+
// polled by HomeKit every 2-15 minutes
|
|
7668
|
+
const currentActiveInput = this.previousActiveIdentifier ?? NO_INPUT_ID;
|
|
7669
|
+
if (this.debugLevel > 1) {
|
|
7670
|
+
const ch = this.channelList[currentActiveInput - 1];
|
|
7811
7671
|
this.log.warn(
|
|
7812
7672
|
"%s: getInput returning input %s %s [%s]",
|
|
7813
7673
|
this.name,
|
|
7814
7674
|
currentActiveInput,
|
|
7815
7675
|
this.currentChannelId,
|
|
7816
|
-
|
|
7676
|
+
(ch || {}).configuredName || NO_CHANNEL_NAME,
|
|
7817
7677
|
);
|
|
7818
7678
|
}
|
|
7819
7679
|
|
|
@@ -7821,9 +7681,9 @@ class StbDevice {
|
|
|
7821
7681
|
}
|
|
7822
7682
|
|
|
7823
7683
|
// set input (change the TV channel)
|
|
7824
|
-
|
|
7684
|
+
setInput(input, callback) {
|
|
7825
7685
|
input = input ?? {}; // ensure input is never null or undefined
|
|
7826
|
-
if (this.
|
|
7686
|
+
if (this.debugLevel > 1) {
|
|
7827
7687
|
this.log.warn(
|
|
7828
7688
|
"%s: setInput input %s %s",
|
|
7829
7689
|
this.name,
|
|
@@ -7833,25 +7693,16 @@ class StbDevice {
|
|
|
7833
7693
|
}
|
|
7834
7694
|
callback(); // for rapid response
|
|
7835
7695
|
// get current channel, also finds keyMacro channels
|
|
7836
|
-
|
|
7837
|
-
(channel) => channel.id === this.currentChannelId,
|
|
7838
|
-
);
|
|
7839
|
-
// if not found look in the master channel list
|
|
7840
|
-
if (!channel) {
|
|
7841
|
-
channel = this.platform.masterChannelList.find(
|
|
7842
|
-
(channel) => channel.id === this.currentChannelId,
|
|
7843
|
-
);
|
|
7844
|
-
}
|
|
7845
|
-
|
|
7846
|
-
// robustness: only try to switch channel if an input.id exists. Handle KeyMacros
|
|
7696
|
+
const prevChannel = this.channelList[this.previousActiveIdentifier - 1];
|
|
7847
7697
|
this.log(
|
|
7848
7698
|
"%s: Change channel from %s [%s] to %s [%s]",
|
|
7849
7699
|
this.name,
|
|
7850
7700
|
this.currentChannelId,
|
|
7851
|
-
(
|
|
7701
|
+
(prevChannel || {}).name || NO_CHANNEL_NAME,
|
|
7852
7702
|
input.id,
|
|
7853
7703
|
input.name,
|
|
7854
7704
|
);
|
|
7705
|
+
// robustness: only try to switch channel if an input.id exists. Handle KeyMacros
|
|
7855
7706
|
if (input.id && input.id.startsWith("$KeyMacro")) {
|
|
7856
7707
|
this.lastKeyMacroChannelId = input.id; // remember last keyMacro id
|
|
7857
7708
|
this.platform.sendKey(this.deviceId, this.name, input.keyMacro);
|
|
@@ -7869,11 +7720,11 @@ class StbDevice {
|
|
|
7869
7720
|
}
|
|
7870
7721
|
|
|
7871
7722
|
// get input name (the TV channel name)
|
|
7872
|
-
|
|
7723
|
+
getInputName(inputId, callback) {
|
|
7873
7724
|
// fired by the user changing a channel name in Home app accessory setup
|
|
7874
|
-
//if (this.
|
|
7725
|
+
//if (this.debugLevel > 1) { this.log.warn('%s: getInputName inputId %s', this.name, inputId); }
|
|
7875
7726
|
const inputName = (this.channelList[inputId] || {}).configuredName || ""; // Empty string if not found
|
|
7876
|
-
if (this.
|
|
7727
|
+
if (this.debugLevel > 1) {
|
|
7877
7728
|
this.log.warn(
|
|
7878
7729
|
"%s: getInputName for input %s returning '%s'",
|
|
7879
7730
|
this.name,
|
|
@@ -7885,7 +7736,7 @@ class StbDevice {
|
|
|
7885
7736
|
}
|
|
7886
7737
|
|
|
7887
7738
|
// set input name (change the TV channel name)
|
|
7888
|
-
|
|
7739
|
+
setInputName(inputId, newInputName, callback) {
|
|
7889
7740
|
// fired by the user changing a channel name in Home app accessory setup
|
|
7890
7741
|
// we cannot handle this as we don't know which channel got renamed
|
|
7891
7742
|
// as user could name multiple channels to xxx
|
|
@@ -7893,7 +7744,7 @@ class StbDevice {
|
|
|
7893
7744
|
// channel 3 renamed from BBC Four/Cbeebies HD to BBC Four Cbeebies HD (valid only for HomeKit)
|
|
7894
7745
|
// inputId is an integer of the input
|
|
7895
7746
|
|
|
7896
|
-
if (this.
|
|
7747
|
+
if (this.debugLevel > 1) {
|
|
7897
7748
|
this.log.warn(
|
|
7898
7749
|
"%s: setInputName for input %s to inputName %s",
|
|
7899
7750
|
this.name,
|
|
@@ -7904,7 +7755,7 @@ class StbDevice {
|
|
|
7904
7755
|
|
|
7905
7756
|
// store in channelList array and write to disk at every change
|
|
7906
7757
|
// ensure that this.channelList bounds are not exceeded!
|
|
7907
|
-
//if (this.
|
|
7758
|
+
//if (this.debugLevel > 1) { this.log('%s: DEBUG setInputName inputId %s, this.channelList.length %s', this.name, inputId, this.channelList.length); }
|
|
7908
7759
|
// not yet working, sometimes causes errors when channelList is not full of data, so commented out
|
|
7909
7760
|
/*
|
|
7910
7761
|
this.log.warn('%s: setInputName inputId %s, this.channelList.length %s', this.name, inputId, this.channelList.length);
|
|
@@ -7918,7 +7769,7 @@ class StbDevice {
|
|
|
7918
7769
|
//this.platform.persistConfig(this.deviceId, this.channelList);
|
|
7919
7770
|
|
|
7920
7771
|
// maybe suppress
|
|
7921
|
-
if (this.
|
|
7772
|
+
if (this.debugLevel > 2) {
|
|
7922
7773
|
//this.log('%s: Renamed channel %s from %s to %s (valid only for HomeKit)', this.name, inputId+1, oldInputName, newInputName);
|
|
7923
7774
|
this.log(
|
|
7924
7775
|
"%s: Renamed channel %s to %s (valid only for HomeKit)",
|
|
@@ -7933,13 +7784,13 @@ class StbDevice {
|
|
|
7933
7784
|
// get current channel id (the TV channel identifier, a string)
|
|
7934
7785
|
// added in v2.1.0
|
|
7935
7786
|
// custom characteristic, returns a string, the event updates the characteristic value automatically
|
|
7936
|
-
|
|
7787
|
+
getCurrentChannelId(callback, currentChannelId) {
|
|
7937
7788
|
// fired by the user reading the Custom characteristic in Shortcuts
|
|
7938
7789
|
// fired when the accessory is first created and HomeKit requests a refresh
|
|
7939
7790
|
// fired when the icon is clicked in the Home app and HomeKit requests a refresh
|
|
7940
7791
|
// fired when the Home app is opened
|
|
7941
7792
|
currentChannelId = this.currentChannelId || ""; // this.currentChannelId is a string eg SV09038. Empty string if not found
|
|
7942
|
-
if (this.
|
|
7793
|
+
if (this.debugLevel > 1) {
|
|
7943
7794
|
this.log.warn(
|
|
7944
7795
|
"%s: getCurrentChannelId returning '%s'",
|
|
7945
7796
|
this.name,
|
|
@@ -7952,17 +7803,17 @@ class StbDevice {
|
|
|
7952
7803
|
// get current channel name (the TV channel name)
|
|
7953
7804
|
// added in v2.1.0
|
|
7954
7805
|
// custom characteristic, returns a string, the event updates the characteristic value automatically
|
|
7955
|
-
|
|
7806
|
+
getCurrentChannelName(callback, currentChannelName) {
|
|
7956
7807
|
// fired by the user reading the Custom characteristic in Shortcuts
|
|
7957
7808
|
// fired when the accessory is first created and HomeKit requests a refresh
|
|
7958
7809
|
// fired when the icon is clicked in the Home app and HomeKit requests a refresh
|
|
7959
7810
|
// fired when the Home app is opened
|
|
7960
|
-
const curChannel = this.platform.
|
|
7961
|
-
|
|
7962
|
-
);
|
|
7811
|
+
const curChannel = this.platform.masterChannelMap?.get(
|
|
7812
|
+
this.currentChannelId,
|
|
7813
|
+
);
|
|
7963
7814
|
// consider setting to Radio if radio is playing
|
|
7964
7815
|
currentChannelName = (curChannel || {}).name || ""; // Empty string if not found
|
|
7965
|
-
if (this.
|
|
7816
|
+
if (this.debugLevel > 1) {
|
|
7966
7817
|
this.log.warn(
|
|
7967
7818
|
"%s: getCurrentChannelName returning '%s'",
|
|
7968
7819
|
this.name,
|
|
@@ -7973,9 +7824,9 @@ class StbDevice {
|
|
|
7973
7824
|
}
|
|
7974
7825
|
|
|
7975
7826
|
// get input visibility state (of the TV channel in the accessory)
|
|
7976
|
-
|
|
7827
|
+
getInputVisibilityState(inputId, callback) {
|
|
7977
7828
|
// fired when ??
|
|
7978
|
-
if (this.
|
|
7829
|
+
if (this.debugLevel > 1) {
|
|
7979
7830
|
this.log.warn(
|
|
7980
7831
|
"%s: getInputVisibilityState inputId %s",
|
|
7981
7832
|
this.name,
|
|
@@ -7986,36 +7837,37 @@ class StbDevice {
|
|
|
7986
7837
|
//if (this.channelList[inputId-1].name === 'HIDDEN') {
|
|
7987
7838
|
// visibilityState = Characteristic.CurrentVisibilityState.HIDDEN;
|
|
7988
7839
|
// }
|
|
7989
|
-
const visibilityState =
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
if (this.
|
|
7840
|
+
const visibilityState =
|
|
7841
|
+
(this.channelList[inputId] || {}).visibilityState ??
|
|
7842
|
+
Characteristic.CurrentVisibilityState.HIDDEN;
|
|
7843
|
+
if (this.debugLevel > 2) {
|
|
7993
7844
|
this.log.warn(
|
|
7994
7845
|
"%s: getInputVisibilityState input %s returning %s [%s]",
|
|
7995
7846
|
this.name,
|
|
7996
7847
|
inputId,
|
|
7997
7848
|
visibilityState,
|
|
7998
|
-
|
|
7849
|
+
CHAR_NAMES.CurrentVisibilityState[visibilityState + 1],
|
|
7999
7850
|
);
|
|
8000
7851
|
}
|
|
8001
7852
|
callback(null, visibilityState);
|
|
8002
7853
|
}
|
|
8003
7854
|
|
|
8004
7855
|
// set input visibility state (show or hide the TV channel)
|
|
8005
|
-
|
|
7856
|
+
setInputVisibilityState(inputId, visibilityState, callback) {
|
|
8006
7857
|
// fired when ??
|
|
8007
|
-
if (this.
|
|
7858
|
+
if (this.debugLevel > 1) {
|
|
8008
7859
|
this.log.warn(
|
|
8009
7860
|
"%s: setInputVisibilityState for input %s inputVisibilityState %s [%s]",
|
|
8010
7861
|
this.name,
|
|
8011
7862
|
inputId,
|
|
8012
7863
|
visibilityState,
|
|
8013
|
-
|
|
7864
|
+
CHAR_NAMES.CurrentVisibilityState[visibilityState + 1],
|
|
8014
7865
|
);
|
|
8015
7866
|
}
|
|
8016
|
-
this.inputServices[inputId]
|
|
8017
|
-
|
|
8018
|
-
|
|
7867
|
+
this.inputServices[inputId].updateCharacteristic(
|
|
7868
|
+
Characteristic.CurrentVisibilityState,
|
|
7869
|
+
visibilityState,
|
|
7870
|
+
);
|
|
8019
7871
|
|
|
8020
7872
|
// store in channelList array and write to disk at every change
|
|
8021
7873
|
this.channelList[inputId].visibilityState = visibilityState;
|
|
@@ -8026,54 +7878,42 @@ class StbDevice {
|
|
|
8026
7878
|
}
|
|
8027
7879
|
|
|
8028
7880
|
// get closed captions state
|
|
8029
|
-
|
|
7881
|
+
getClosedCaptions(callback) {
|
|
8030
7882
|
// fired when the Home app wants to refresh the TV tile. Refresh occurs when tile is displayed.
|
|
8031
|
-
if (this.
|
|
7883
|
+
if (this.debugLevel > 1) {
|
|
8032
7884
|
this.log.warn(
|
|
8033
7885
|
"%s: getClosedCaptions returning %s [%s]",
|
|
8034
7886
|
this.name,
|
|
8035
|
-
this.
|
|
8036
|
-
|
|
8037
|
-
this.currentClosedCaptionsState + 1
|
|
8038
|
-
],
|
|
7887
|
+
this.currentClosedCaptions,
|
|
7888
|
+
CHAR_NAMES.ClosedCaptions[this.currentClosedCaptions + 1],
|
|
8039
7889
|
);
|
|
8040
7890
|
}
|
|
8041
|
-
callback(null, this.
|
|
7891
|
+
callback(null, this.currentClosedCaptions); // return current state
|
|
8042
7892
|
}
|
|
8043
7893
|
|
|
8044
7894
|
// set closed captions state
|
|
8045
|
-
|
|
7895
|
+
setClosedCaptions(targetClosedCaptionsState, callback) {
|
|
8046
7896
|
// fired when ?? Apple HomeKit has no ability to control setClosedCaptions
|
|
8047
7897
|
// targetClosedCaptionsState is the wanted state
|
|
8048
|
-
if (this.
|
|
7898
|
+
if (this.debugLevel > 1) {
|
|
8049
7899
|
this.log.warn(
|
|
8050
7900
|
"%s: setClosedCaptions targetClosedCaptionsState:",
|
|
8051
7901
|
this.name,
|
|
8052
7902
|
targetClosedCaptionsState,
|
|
8053
|
-
|
|
8054
|
-
targetClosedCaptionsState + 1
|
|
8055
|
-
],
|
|
7903
|
+
CHAR_NAMES.ClosedCaptions[targetClosedCaptionsState + 1],
|
|
8056
7904
|
);
|
|
8057
7905
|
}
|
|
8058
|
-
if (this.
|
|
7906
|
+
if (this.currentClosedCaptions !== targetClosedCaptionsState) {
|
|
8059
7907
|
this.log("setClosedCaptions: not yet implemented");
|
|
8060
7908
|
}
|
|
8061
7909
|
callback();
|
|
8062
7910
|
}
|
|
8063
7911
|
|
|
8064
7912
|
// get picture mode state
|
|
8065
|
-
|
|
7913
|
+
getPictureMode(callback) {
|
|
8066
7914
|
// fired when the Home app wants to refresh the TV tile. Refresh occurs when tile is displayed.
|
|
8067
|
-
if (this.
|
|
8068
|
-
|
|
8069
|
-
// get the config for the device, needed for a few status checks
|
|
8070
|
-
let configDevice;
|
|
8071
|
-
if (this.config.devices) {
|
|
8072
|
-
configDevice = this.config.devices.find(
|
|
8073
|
-
(device) => device.deviceId === this.deviceId,
|
|
8074
|
-
);
|
|
8075
|
-
}
|
|
8076
|
-
if ((configDevice || {}).customPictureMode === "recordingState") {
|
|
7915
|
+
if (this.debugLevel > 1) {
|
|
7916
|
+
if (this._configDevice.customPictureMode === "recordingState") {
|
|
8077
7917
|
this.log.warn(
|
|
8078
7918
|
"%s: getPictureMode returning %s [%s]",
|
|
8079
7919
|
this.name,
|
|
@@ -8085,7 +7925,7 @@ class StbDevice {
|
|
|
8085
7925
|
"%s: getPictureMode returning %s [%s]",
|
|
8086
7926
|
this.name,
|
|
8087
7927
|
this.customPictureMode,
|
|
8088
|
-
|
|
7928
|
+
CHAR_NAMES.PictureMode[this.customPictureMode + 1],
|
|
8089
7929
|
);
|
|
8090
7930
|
}
|
|
8091
7931
|
}
|
|
@@ -8093,15 +7933,15 @@ class StbDevice {
|
|
|
8093
7933
|
}
|
|
8094
7934
|
|
|
8095
7935
|
// set picture mode state
|
|
8096
|
-
|
|
7936
|
+
setPictureMode(targetPictureMode, callback) {
|
|
8097
7937
|
// The current Home app (iOS 16.0) does not support setting this characteristic, thus is never fired
|
|
8098
7938
|
// targetClosedCaptionsState is the wanted state
|
|
8099
|
-
if (this.
|
|
7939
|
+
if (this.debugLevel > 1) {
|
|
8100
7940
|
this.log.warn(
|
|
8101
7941
|
"%s: setPictureMode targetPictureMode:",
|
|
8102
7942
|
this.name,
|
|
8103
7943
|
targetPictureMode,
|
|
8104
|
-
|
|
7944
|
+
CHAR_NAMES.PictureMode[targetPictureMode + 1],
|
|
8105
7945
|
);
|
|
8106
7946
|
}
|
|
8107
7947
|
if (this.customPictureMode !== targetPictureMode) {
|
|
@@ -8111,12 +7951,11 @@ class StbDevice {
|
|
|
8111
7951
|
}
|
|
8112
7952
|
|
|
8113
7953
|
// set power mode selection (View TV Settings menu option)
|
|
8114
|
-
|
|
7954
|
+
setPowerModeSelection(state, callback) {
|
|
8115
7955
|
// fired by the View TV Settings command in the Home app TV accessory Settings
|
|
8116
|
-
if (this.
|
|
7956
|
+
if (this.debugLevel > 1) {
|
|
8117
7957
|
this.log.warn("%s: setPowerModeSelection state:", this.name, state);
|
|
8118
7958
|
}
|
|
8119
|
-
callback(false); // for rapid response
|
|
8120
7959
|
this.log("Menu command: View TV Settings");
|
|
8121
7960
|
// only send the keys if the power is on
|
|
8122
7961
|
if (this.currentPowerState === Characteristic.Active.ACTIVE) {
|
|
@@ -8130,10 +7969,10 @@ class StbDevice {
|
|
|
8130
7969
|
}
|
|
8131
7970
|
|
|
8132
7971
|
// get current media state
|
|
8133
|
-
|
|
7972
|
+
getCurrentMediaState(callback) {
|
|
8134
7973
|
// The current Home app (iOS 16.0) does not support setting this characteristic, thus is never fired
|
|
8135
7974
|
// cannot be controlled by Apple Home app, but could be controlled by other HomeKit apps
|
|
8136
|
-
if (this.
|
|
7975
|
+
if (this.debugLevel > 1) {
|
|
8137
7976
|
this.log.warn(
|
|
8138
7977
|
"%s: getCurrentMediaState returning %s [%s]",
|
|
8139
7978
|
this.name,
|
|
@@ -8145,11 +7984,11 @@ class StbDevice {
|
|
|
8145
7984
|
}
|
|
8146
7985
|
|
|
8147
7986
|
// get target media state
|
|
8148
|
-
|
|
7987
|
+
getTargetMediaState(callback) {
|
|
8149
7988
|
// The current Home app (iOS 16.0) does not support getting this characteristic, thus is never fired
|
|
8150
7989
|
// cannot be controlled by Apple Home app, but could be controlled by other HomeKit apps
|
|
8151
7990
|
// must never return null, so send STOP as default value
|
|
8152
|
-
if (this.
|
|
7991
|
+
if (this.debugLevel > 1) {
|
|
8153
7992
|
this.log.warn(
|
|
8154
7993
|
"%s: getTargetMediaState returning %s [%s]",
|
|
8155
7994
|
this.name,
|
|
@@ -8161,34 +8000,20 @@ class StbDevice {
|
|
|
8161
8000
|
}
|
|
8162
8001
|
|
|
8163
8002
|
// set target media state
|
|
8164
|
-
|
|
8003
|
+
setTargetMediaState(targetMediaState, logChangeOnly, callback) {
|
|
8165
8004
|
// The current Home app (iOS 16.0) does not support setting this characteristic, thus is never fired
|
|
8166
8005
|
// cannot be controlled by Apple Home app, but could be controlled by other HomeKit apps
|
|
8167
8006
|
// can be controlled by the Apple TV Remote Control, and is called when changing Play / Pause / Stop
|
|
8168
8007
|
// logChangeOnly = TRUE: only the changes are logged, no media state change occurs. Needed when sending remote keypresses to prevent double commands
|
|
8169
|
-
if (this.
|
|
8008
|
+
if (this.debugLevel > 1) {
|
|
8170
8009
|
this.log.warn(
|
|
8171
8010
|
"%s: setTargetMediaState targetMediaState:",
|
|
8172
8011
|
this.name,
|
|
8173
8012
|
targetMediaState,
|
|
8174
|
-
|
|
8013
|
+
CHAR_NAMES.TargetMediaState[targetMediaState + 1],
|
|
8175
8014
|
);
|
|
8176
8015
|
}
|
|
8177
8016
|
|
|
8178
|
-
let prevTargetMediaState = this.televisionService.getCharacteristic(
|
|
8179
|
-
Characteristic.TargetMediaState,
|
|
8180
|
-
).value;
|
|
8181
|
-
if (prevTargetMediaState !== targetMediaState) {
|
|
8182
|
-
this.targetMediaState = targetMediaState;
|
|
8183
|
-
this.log(
|
|
8184
|
-
"%s: Target Media state changed from %s [%s] to %s [%s]",
|
|
8185
|
-
this.name,
|
|
8186
|
-
prevTargetMediaState,
|
|
8187
|
-
Object.keys(Characteristic.TargetMediaState)[prevTargetMediaState + 1],
|
|
8188
|
-
targetMediaState,
|
|
8189
|
-
Object.keys(Characteristic.TargetMediaState)[targetMediaState + 1],
|
|
8190
|
-
);
|
|
8191
|
-
}
|
|
8192
8017
|
if (!logChangeOnly) {
|
|
8193
8018
|
// send the setMediaState command if we are not just logging the change
|
|
8194
8019
|
const boxMediaStatePAUSE = 0,
|
|
@@ -8205,10 +8030,10 @@ class StbDevice {
|
|
|
8205
8030
|
newBoxMediaState = boxMediaStatePAUSE;
|
|
8206
8031
|
break;
|
|
8207
8032
|
}
|
|
8208
|
-
if (this.
|
|
8033
|
+
if (this.debugLevel > 1) {
|
|
8209
8034
|
this.log(
|
|
8210
8035
|
"setTargetMediaState: Set media to %s for",
|
|
8211
|
-
|
|
8036
|
+
CHAR_NAMES.TargetMediaState[targetMediaState + 1],
|
|
8212
8037
|
this.currentChannelId,
|
|
8213
8038
|
);
|
|
8214
8039
|
}
|
|
@@ -8221,11 +8046,11 @@ class StbDevice {
|
|
|
8221
8046
|
}
|
|
8222
8047
|
if (callback && typeof callback === "function") {
|
|
8223
8048
|
callback();
|
|
8224
|
-
}
|
|
8049
|
+
}
|
|
8225
8050
|
}
|
|
8226
8051
|
|
|
8227
8052
|
// get display order
|
|
8228
|
-
|
|
8053
|
+
getDisplayOrder(callback) {
|
|
8229
8054
|
// fired when the user clicks away from the iOS Device TV Remote Control, regardless of which TV was selected
|
|
8230
8055
|
// fired when the icon is clicked in the Home app and the Home app requests a refresh
|
|
8231
8056
|
|
|
@@ -8233,17 +8058,17 @@ class StbDevice {
|
|
|
8233
8058
|
let dispOrder = this.televisionService.getCharacteristic(
|
|
8234
8059
|
Characteristic.DisplayOrder,
|
|
8235
8060
|
).value;
|
|
8236
|
-
if (this.
|
|
8061
|
+
if (this.debugLevel > 1) {
|
|
8237
8062
|
this.log.warn("%s: getDisplayOrder returning '%s'", this.name, dispOrder);
|
|
8238
8063
|
}
|
|
8239
8064
|
callback(null, dispOrder);
|
|
8240
8065
|
}
|
|
8241
8066
|
|
|
8242
8067
|
// set display order
|
|
8243
|
-
|
|
8068
|
+
setDisplayOrder(displayOrder, callback) {
|
|
8244
8069
|
// fired when the user clicks away from the iOS Device TV Remote Control, regardless of which TV was selected
|
|
8245
8070
|
// fired when the icon is clicked in the Home app and the Home app requests a refresh
|
|
8246
|
-
if (this.
|
|
8071
|
+
if (this.debugLevel > 1) {
|
|
8247
8072
|
this.log.warn(
|
|
8248
8073
|
"%s: setDisplayOrder displayOrder",
|
|
8249
8074
|
this.name,
|
|
@@ -8254,40 +8079,40 @@ class StbDevice {
|
|
|
8254
8079
|
}
|
|
8255
8080
|
|
|
8256
8081
|
// get in use
|
|
8257
|
-
|
|
8082
|
+
getInUse(callback) {
|
|
8258
8083
|
// useful in Shortcuts and Automations
|
|
8259
8084
|
// log the inUse value
|
|
8260
|
-
if (this.
|
|
8085
|
+
if (this.debugLevel > 1) {
|
|
8261
8086
|
this.log.warn(
|
|
8262
8087
|
"%s: getInUse returning %s [%s]",
|
|
8263
8088
|
this.name,
|
|
8264
8089
|
this.currentInUse,
|
|
8265
|
-
|
|
8090
|
+
CHAR_NAMES.InUse[this.currentInUse + 1],
|
|
8266
8091
|
);
|
|
8267
8092
|
}
|
|
8268
8093
|
callback(null, this.currentInUse);
|
|
8269
8094
|
}
|
|
8270
8095
|
|
|
8271
8096
|
// get program mode (recording scheduled, not scheduled)
|
|
8272
|
-
|
|
8097
|
+
getProgramMode(callback) {
|
|
8273
8098
|
// useful in Shortcuts and Automations
|
|
8274
8099
|
// log the programMode value
|
|
8275
|
-
if (this.
|
|
8100
|
+
if (this.debugLevel > 1) {
|
|
8276
8101
|
this.log.warn(
|
|
8277
8102
|
"%s: getProgramMode returning %s [%s]",
|
|
8278
8103
|
this.name,
|
|
8279
8104
|
this.currentProgramMode,
|
|
8280
|
-
|
|
8105
|
+
CHAR_NAMES.ProgramMode[this.currentProgramMode + 1],
|
|
8281
8106
|
);
|
|
8282
8107
|
}
|
|
8283
8108
|
callback(null, this.currentProgramMode);
|
|
8284
8109
|
}
|
|
8285
8110
|
|
|
8286
8111
|
// get StatusActive state
|
|
8287
|
-
|
|
8112
|
+
getStatusActive(callback) {
|
|
8288
8113
|
// useful in Shortcuts and Automations
|
|
8289
8114
|
// log the StatusActive value
|
|
8290
|
-
if (this.
|
|
8115
|
+
if (this.debugLevel > 1) {
|
|
8291
8116
|
this.log.warn(
|
|
8292
8117
|
"%s: getStatusActive returning %s [%s]",
|
|
8293
8118
|
this.name,
|
|
@@ -8299,57 +8124,53 @@ class StbDevice {
|
|
|
8299
8124
|
}
|
|
8300
8125
|
|
|
8301
8126
|
// get status fault
|
|
8302
|
-
|
|
8127
|
+
getStatusFault(callback) {
|
|
8303
8128
|
// useful in Shortcuts and Automations
|
|
8304
8129
|
// log the StatusFault
|
|
8305
|
-
if (this.
|
|
8130
|
+
if (this.debugLevel > 1) {
|
|
8306
8131
|
this.log.warn(
|
|
8307
8132
|
"%s: getStatusFault returning %s [%s]",
|
|
8308
8133
|
this.name,
|
|
8309
8134
|
this.currentStatusFault,
|
|
8310
|
-
|
|
8135
|
+
CHAR_NAMES.StatusFault[this.currentStatusFault + 1],
|
|
8311
8136
|
);
|
|
8312
8137
|
}
|
|
8313
8138
|
callback(null, this.currentStatusFault);
|
|
8314
8139
|
}
|
|
8315
8140
|
|
|
8316
8141
|
// get InputSourceType state
|
|
8317
|
-
|
|
8142
|
+
getInputSourceType(callback) {
|
|
8318
8143
|
// useful in Shortcuts and Automations
|
|
8319
8144
|
// log the InputSourceType value
|
|
8320
|
-
if (this.
|
|
8145
|
+
if (this.debugLevel > 1) {
|
|
8321
8146
|
this.log.warn(
|
|
8322
8147
|
"%s: getInputSourceType returning %s [%s]",
|
|
8323
8148
|
this.name,
|
|
8324
8149
|
this.currentInputSourceType,
|
|
8325
|
-
|
|
8326
|
-
this.currentInputSourceType + 1
|
|
8327
|
-
],
|
|
8150
|
+
CHAR_NAMES.InputSourceType[this.currentInputSourceType + 1],
|
|
8328
8151
|
);
|
|
8329
8152
|
}
|
|
8330
8153
|
callback(null, this.currentInputSourceType);
|
|
8331
8154
|
}
|
|
8332
8155
|
|
|
8333
8156
|
// get InputDeviceType state
|
|
8334
|
-
|
|
8157
|
+
getInputDeviceType(callback) {
|
|
8335
8158
|
// useful in Shortcuts and Automations
|
|
8336
8159
|
// log the InputDeviceType value
|
|
8337
|
-
if (this.
|
|
8160
|
+
if (this.debugLevel > 1) {
|
|
8338
8161
|
this.log.warn(
|
|
8339
8162
|
"%s: getInputDeviceType returning %s [%s]",
|
|
8340
8163
|
this.name,
|
|
8341
8164
|
this.currentInputDeviceType,
|
|
8342
|
-
|
|
8343
|
-
this.currentInputDeviceType + 1
|
|
8344
|
-
],
|
|
8165
|
+
CHAR_NAMES.InputDeviceType[this.currentInputDeviceType + 1],
|
|
8345
8166
|
);
|
|
8346
8167
|
}
|
|
8347
8168
|
callback(null, this.currentInputDeviceType);
|
|
8348
8169
|
}
|
|
8349
8170
|
|
|
8350
8171
|
// set remote key
|
|
8351
|
-
|
|
8352
|
-
if (this.
|
|
8172
|
+
setRemoteKey(remoteKey, callback) {
|
|
8173
|
+
if (this.debugLevel > 1) {
|
|
8353
8174
|
this.log.warn("%s: setRemoteKey remoteKey:", this.name, remoteKey);
|
|
8354
8175
|
}
|
|
8355
8176
|
callback(null); // for rapid response
|
|
@@ -8378,13 +8199,7 @@ class StbDevice {
|
|
|
8378
8199
|
//this.log.debug("%s: setRemoteKey: remoteKey %s, lastKeyPressTime %s",this.name, remoteKey, lastKeyPressTime);
|
|
8379
8200
|
|
|
8380
8201
|
// get the config for this device
|
|
8381
|
-
|
|
8382
|
-
if (this.config.devices) {
|
|
8383
|
-
configDevice = this.config.devices.find(
|
|
8384
|
-
(device) => device.deviceId === this.deviceId,
|
|
8385
|
-
);
|
|
8386
|
-
}
|
|
8387
|
-
|
|
8202
|
+
const configDevice = this._configDevice;
|
|
8388
8203
|
const DEFAULT_DOUBLE_PRESS_DELAY_TIME = 300; // default, in case config missing
|
|
8389
8204
|
const DEFAULT_TRIPLE_PRESS_DELAY_TIME = 800; // default, in case config missing
|
|
8390
8205
|
|