homebridge-xbox-tv 3.5.8 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
  - After update to v3.0.0 RESTFull and MQTT config settings need to be updated
12
12
  - After update to v3.4.0 all buttons in config need to be updated
13
13
 
14
+ ## [3.6.0] - (30.05.2025)
15
+
16
+ ## Changes
17
+
18
+ - added speaker option to volume control (for feature use)
19
+ - now if volume control option is set to disable/nonethe also TV Speakers (hardware control) is disabled
20
+ - stability improvements
21
+ - cleanup
22
+
14
23
  ## [3.5.1] - (15.03.2025)
15
24
 
16
25
  ## Changes
package/README.md CHANGED
@@ -109,7 +109,7 @@ Homebridge plugin for Microsoft game Consoles. Tested with Xbox One X/S and Xbox
109
109
  | `webApiClientSecret` | Here set your Client Secret from Azure AD or leave empty if you do not have own account. |
110
110
  | `volumeControlNamePrefix` | Here enable/disable the accessory name as a prefix for volume control name. |
111
111
  | `volumeControlName` | Here set Your own volume control name or leave empty. |
112
- | `volumeControl` | Here choice what a additional volume control mode You want to use (`0 - None/Disabled`, `1 - Lightbulb`, `2 - Fan`), not working yet. |
112
+ | `volumeControl` | Here choice what a additional volume control mode You want to use (`0 - None/Disabled`, `1 - Lightbulb`, `2 - Fan`, `3 - Speaker`), not working yet. |
113
113
  | `infoButtonCommand` | Here select the function of `I` button in RC app. |
114
114
  | `disableLogDeviceInfo` | If enabled, add ability to disable log device info by every connections device to the network. |
115
115
  | `disableLogInfo` | If enabled, disable log info, all values and state will not be displayed in Homebridge log console. |
@@ -42,7 +42,7 @@
42
42
  "default": false,
43
43
  "description": "Here You can disable this accessory.",
44
44
  "required": false
45
- },
45
+ },
46
46
  "webApiControl": {
47
47
  "title": "Web Api",
48
48
  "type": "boolean",
@@ -721,27 +721,13 @@
721
721
  "description": "Here select the function of info button in RC.",
722
722
  "required": false
723
723
  },
724
- "volumeControlNamePrefix": {
725
- "title": "Volume Control Name Prefix",
726
- "type": "boolean",
727
- "default": false,
728
- "description": "Here enable/disable the accessory name as a prefix for volume control name.",
729
- "required": false
730
- },
731
- "volumeControlName": {
732
- "title": "Volume Control Name",
733
- "type": "string",
734
- "placeholder": "Name",
735
- "description": "Here set Your own volume control name or leave empty.",
736
- "required": false
737
- },
738
724
  "volumeControl": {
739
725
  "title": "Volume Control",
740
726
  "type": "integer",
741
727
  "minimum": 0,
742
- "maximum": 2,
728
+ "maximum": 3,
743
729
  "default": 0,
744
- "description": "Here select what a volume control mode You want to use. If select *None/Disabled* only hardware buttons in RC app can be used to control volume.",
730
+ "description": "Here select what a volume control mode You want to use.",
745
731
  "oneOf": [
746
732
  {
747
733
  "title": "None/Disabled",
@@ -760,10 +746,36 @@
760
746
  "enum": [
761
747
  2
762
748
  ]
749
+ },
750
+ {
751
+ "title": "Speaker",
752
+ "enum": [
753
+ 3
754
+ ]
763
755
  }
764
756
  ],
765
757
  "required": false
766
758
  },
759
+ "volumeControlName": {
760
+ "title": "Volume Control Name",
761
+ "type": "string",
762
+ "placeholder": "Name",
763
+ "description": "Here set Your own volume control name or leave empty.",
764
+ "required": false,
765
+ "condition": {
766
+ "functionBody": "return model.devices[arrayIndices].volumeControl > 0;"
767
+ }
768
+ },
769
+ "volumeControlNamePrefix": {
770
+ "title": "Volume Control Name Prefix",
771
+ "type": "boolean",
772
+ "default": false,
773
+ "description": "Here enable/disable the accessory name as a prefix for volume control name.",
774
+ "required": false,
775
+ "condition": {
776
+ "functionBody": "return model.devices[arrayIndices].volumeControl > 0;"
777
+ }
778
+ },
767
779
  "disableLogDeviceInfo": {
768
780
  "title": "Disable Log Device Info",
769
781
  "type": "boolean",
@@ -1077,9 +1089,9 @@
1077
1089
  "key": "devices[]",
1078
1090
  "title": "Volume",
1079
1091
  "items": [
1080
- "devices[].volumeControlNamePrefix",
1092
+ "devices[].volumeControl",
1081
1093
  "devices[].volumeControlName",
1082
- "devices[].volumeControl"
1094
+ "devices[].volumeControlNamePrefix"
1083
1095
  ]
1084
1096
  },
1085
1097
  {
package/index.js CHANGED
@@ -57,7 +57,7 @@ class XboxPlatform {
57
57
  ...device.mqtt,
58
58
  passwd: 'removed'
59
59
  }
60
- };
60
+ }
61
61
  const debug1 = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, Config: ${JSON.stringify(config, null, 2)}.`);
62
62
 
63
63
  //check files exists, if not then create it
@@ -125,7 +125,7 @@ class XboxPlatform {
125
125
  const startImpulseGenerator = startDone ? await xboxDevice.startImpulseGenerator() : false;
126
126
  } catch (error) {
127
127
  const emitLog = disableLogError ? false : log.error(`Device: ${host} ${deviceName}, ${error}, trying again.`);
128
- };
128
+ }
129
129
  }).on('state', (state) => {
130
130
  const emitLog = !enableDebugMode ? false : state ? log.info(`Device: ${host} ${deviceName}, Start impulse generator started.`) : log.info(`Device: ${host} ${deviceName}, Start impulse generator stopped.`);
131
131
  });
@@ -143,8 +143,8 @@ class XboxPlatform {
143
143
  configureAccessory(accessory) {
144
144
  this.accessories.push(accessory);
145
145
  }
146
- };
146
+ }
147
147
 
148
148
  export default (api) => {
149
149
  api.registerPlatform(PluginName, PlatformName, XboxPlatform);
150
- };
150
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Xbox TV",
3
3
  "name": "homebridge-xbox-tv",
4
- "version": "3.5.8",
4
+ "version": "3.6.0",
5
5
  "description": "Homebridge plugin to control Xbox game consoles.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -24,7 +24,7 @@ class ImpulseGenerator extends EventEmitter {
24
24
  this.emit(timer.name);
25
25
  }, timer.sampling);
26
26
  this.timers.push(newTimer);
27
- };
27
+ }
28
28
 
29
29
  return true;
30
30
  }
package/src/mqtt.js CHANGED
@@ -37,7 +37,7 @@ class Mqtt extends EventEmitter {
37
37
  });
38
38
  } catch (error) {
39
39
  this.emit('warn', `MQTT Connect error: ${error}`);
40
- };
40
+ }
41
41
  }).on('publish', async (topic, message) => {
42
42
  try {
43
43
  const fullTopic = `${config.prefix}/${topic}`;
@@ -46,10 +46,10 @@ class Mqtt extends EventEmitter {
46
46
  const emitDebug = config.debug ? this.emit('debug', `MQTT Publish topic: ${fullTopic}, message: ${publishMessage}`) : false;
47
47
  } catch (error) {
48
48
  this.emit('warn', `MQTT Publish error: ${error}`);
49
- };
49
+ }
50
50
  });
51
51
 
52
52
  this.emit('connect');
53
- };
54
- };
53
+ }
54
+ }
55
55
  export default Mqtt;
package/src/restful.js CHANGED
@@ -15,9 +15,9 @@ class RestFul extends EventEmitter {
15
15
  apps: 'This data is not available in your system.',
16
16
  storages: 'This data is not available in your system.',
17
17
  status: 'This data is not available in your system.'
18
- };
18
+ }
19
19
  this.connect();
20
- };
20
+ }
21
21
 
22
22
  connect() {
23
23
  try {
@@ -89,8 +89,8 @@ class RestFul extends EventEmitter {
89
89
  default:
90
90
  this.emit('warn', `RESTFul update unknown path: ${path}, data: ${data}`)
91
91
  break;
92
- };
92
+ }
93
93
  const emitDebug = this.restFulDebug ? this.emit('debug', `RESTFul update path: ${path}, data: ${JSON.stringify(data, null, 2)}`) : false;
94
- };
95
- };
94
+ }
95
+ }
96
96
  export default RestFul;
@@ -12,7 +12,7 @@ class Authentication {
12
12
  oauth: {},
13
13
  user: {},
14
14
  xsts: {}
15
- };
15
+ }
16
16
  }
17
17
 
18
18
  async refreshTokens(type) {
@@ -30,7 +30,6 @@ class Authentication {
30
30
  } catch (error) {
31
31
  throw new Error(error);
32
32
  };
33
- break;
34
33
  case false:
35
34
  try {
36
35
  await this.refreshTokens('xsts');
@@ -38,7 +37,6 @@ class Authentication {
38
37
  } catch (error) {
39
38
  throw new Error(error);
40
39
  };
41
- break;
42
40
  }
43
41
  } else {
44
42
  try {
@@ -47,9 +45,8 @@ class Authentication {
47
45
  return true;
48
46
  } catch (error) {
49
47
  throw new Error(error);
50
- };
48
+ }
51
49
  }
52
- break;
53
50
  case 'xsts':
54
51
  if (this.tokens.xsts.Token) {
55
52
  const tokenExpired = new Date() > new Date(this.tokens.xsts.NotAfter).getTime();
@@ -62,10 +59,8 @@ class Authentication {
62
59
  } catch (error) {
63
60
  throw new Error(error);
64
61
  };
65
- break;
66
62
  case false:
67
63
  return true;
68
- break;
69
64
  }
70
65
  } else {
71
66
  try {
@@ -73,12 +68,10 @@ class Authentication {
73
68
  return true;
74
69
  } catch (error) {
75
70
  throw new Error(error);
76
- };
71
+ }
77
72
  }
78
- break;
79
73
  default:
80
74
  throw new Error(`Unknow refresh token type: ${type}`);
81
- break;
82
75
  }
83
76
  }
84
77
 
@@ -101,7 +94,7 @@ class Authentication {
101
94
  return true;
102
95
  } catch (error) {
103
96
  throw new Error(`Refresh token error: ${error}`);
104
- };
97
+ }
105
98
  }
106
99
 
107
100
  async getUserToken(accessToken) {
@@ -113,7 +106,7 @@ class Authentication {
113
106
  "AuthMethod": 'RPS',
114
107
  "SiteName": 'user.auth.xboxlive.com',
115
108
  "RpsTicket": `d=${accessToken}`
116
- },
109
+ }
117
110
  }
118
111
 
119
112
  const postData = JSON.stringify(payload);
@@ -125,7 +118,7 @@ class Authentication {
125
118
  return true;
126
119
  } catch (error) {
127
120
  throw new Error(`User token error: ${error}`);
128
- };
121
+ }
129
122
  }
130
123
 
131
124
  async getXstsToken(userToken) {
@@ -136,7 +129,7 @@ class Authentication {
136
129
  "Properties": {
137
130
  "UserTokens": [userToken],
138
131
  "SandboxId": 'RETAIL',
139
- },
132
+ }
140
133
  }
141
134
 
142
135
  const postData = JSON.stringify(payload);
@@ -147,7 +140,7 @@ class Authentication {
147
140
  return true;
148
141
  } catch (error) {
149
142
  throw new Error(`Xsts token error: ${error}`);
150
- };
143
+ }
151
144
  }
152
145
 
153
146
  async accessToken(webApiToken) {
@@ -171,7 +164,7 @@ class Authentication {
171
164
  return true;
172
165
  } catch (error) {
173
166
  throw new Error(`Access token error: ${error}`);
174
- };
167
+ }
175
168
  }
176
169
 
177
170
  async checkAuthorization() {
@@ -190,7 +183,7 @@ class Authentication {
190
183
  }
191
184
  } catch (error) {
192
185
  throw new Error(error);
193
- };
186
+ }
194
187
  } else {
195
188
  throw new Error(`Authorization not possible, check plugin settings - Client Id: ${this.webApiClientId}`);
196
189
  }
@@ -210,7 +203,7 @@ class Authentication {
210
203
  return oauth2URI;
211
204
  } catch (error) {
212
205
  throw new Error(`Authorization URL error: ${error}`);
213
- };
206
+ }
214
207
  }
215
208
 
216
209
  async readData(path) {
@@ -220,7 +213,7 @@ class Authentication {
220
213
  return tokens;
221
214
  } catch (error) {
222
215
  throw new Error(`Read data error: ${error}`);
223
- };
216
+ }
224
217
  }
225
218
 
226
219
  async saveData(path, data) {
@@ -230,7 +223,7 @@ class Authentication {
230
223
  return true;
231
224
  } catch (error) {
232
225
  throw new Error(`Save data error: ${error}`);
233
- };
226
+ }
234
227
  }
235
228
  }
236
229
  export default Authentication;
@@ -33,7 +33,7 @@ class XboxWebApi extends EventEmitter {
33
33
  await this.checkAuthorization();
34
34
  } catch (error) {
35
35
  this.emit('error', error);
36
- };
36
+ }
37
37
  }).on('state', (state) => {
38
38
  const emitState = state ? this.emit('success', `Web Api monitoring started`) : this.emit('warn', `Web Api monitoring stopped`);
39
39
  });
@@ -48,7 +48,7 @@ class XboxWebApi extends EventEmitter {
48
48
  if (!authorized) {
49
49
  this.emit('warn', `not authorized`);
50
50
  return false;
51
- };
51
+ }
52
52
  this.tokens = data.tokens;
53
53
  this.consoleAuthorized = true;
54
54
 
@@ -64,7 +64,7 @@ class XboxWebApi extends EventEmitter {
64
64
  'x-xbl-client-version': '39.39.22001.0',
65
65
  'skillplatform': 'RemoteManagement',
66
66
  'Content-Type': 'application/json'
67
- }
67
+ };
68
68
  this.headers = headers;
69
69
 
70
70
  //create axios instance
@@ -83,12 +83,12 @@ class XboxWebApi extends EventEmitter {
83
83
  //await this.userProfile();
84
84
  } catch (error) {
85
85
  this.emit('error', `Check xbox live data error: ${error}`);
86
- };
86
+ }
87
87
 
88
88
  return true;
89
89
  } catch (error) {
90
90
  throw new Error(`Check authorization error: ${error}`);
91
- };
91
+ }
92
92
  }
93
93
 
94
94
  async consoleStatus() {
@@ -123,7 +123,7 @@ class XboxWebApi extends EventEmitter {
123
123
  return remoteManagementEnabled;
124
124
  } catch (error) {
125
125
  throw new Error(`Status error: ${error}`);
126
- };
126
+ }
127
127
  }
128
128
 
129
129
  async consolesList() {
@@ -203,7 +203,7 @@ class XboxWebApi extends EventEmitter {
203
203
  return true;
204
204
  } catch (error) {
205
205
  throw new Error(`Consoles list error: ${error}`);
206
- };
206
+ }
207
207
  }
208
208
 
209
209
  async installedApps() {
@@ -240,10 +240,10 @@ class XboxWebApi extends EventEmitter {
240
240
  'isGame': isGame,
241
241
  'name': name,
242
242
  'contentType': contentType
243
- };
243
+ }
244
244
  const duplicatedInput = appsArray.some(input => input.reference === aumid);
245
245
  const push = name && aumid && !duplicatedInput ? appsArray.push(inputsObj) : false;
246
- };
246
+ }
247
247
 
248
248
  //save inputs
249
249
  await this.saveData(this.inputsFile, appsArray);
@@ -255,7 +255,7 @@ class XboxWebApi extends EventEmitter {
255
255
  return true;
256
256
  } catch (error) {
257
257
  throw new Error(`Installed apps error: ${error}`);
258
- };
258
+ }
259
259
  }
260
260
 
261
261
  async storageDevices() {
@@ -298,7 +298,7 @@ class XboxWebApi extends EventEmitter {
298
298
  return true;
299
299
  } catch (error) {
300
300
  throw new Error(`storage devices error: ${error}`);
301
- };
301
+ }
302
302
  }
303
303
 
304
304
  async userProfile() {
@@ -331,8 +331,8 @@ class XboxWebApi extends EventEmitter {
331
331
 
332
332
  this.userProfileSettingsId.push(id);
333
333
  this.userProfileSettingsValue.push(value);
334
- };
335
- };
334
+ }
335
+ }
336
336
 
337
337
  //emit restFul and mqtt
338
338
  this.emit('restFul', 'profile', profileUsers);
@@ -341,7 +341,7 @@ class XboxWebApi extends EventEmitter {
341
341
  return true;
342
342
  } catch (error) {
343
343
  throw new Error(`User profile error: ${error}`);
344
- };
344
+ }
345
345
  }
346
346
 
347
347
  async saveData(path, data) {
@@ -352,7 +352,7 @@ class XboxWebApi extends EventEmitter {
352
352
  return true;
353
353
  } catch (error) {
354
354
  throw new Error(`Save data error: ${error}`);
355
- };
355
+ }
356
356
  };
357
357
 
358
358
  async next() {
@@ -361,7 +361,7 @@ class XboxWebApi extends EventEmitter {
361
361
  return true;
362
362
  } catch (error) {
363
363
  throw new Error(error);
364
- };
364
+ }
365
365
  }
366
366
 
367
367
  async previous() {
@@ -370,7 +370,7 @@ class XboxWebApi extends EventEmitter {
370
370
  return true;
371
371
  } catch (error) {
372
372
  throw new Error(error);
373
- };
373
+ }
374
374
  }
375
375
 
376
376
  async pause() {
@@ -379,7 +379,7 @@ class XboxWebApi extends EventEmitter {
379
379
  return true;
380
380
  } catch (error) {
381
381
  throw new Error(error);
382
- };
382
+ }
383
383
  }
384
384
 
385
385
  async play() {
@@ -388,7 +388,7 @@ class XboxWebApi extends EventEmitter {
388
388
  return true;
389
389
  } catch (error) {
390
390
  throw new Error(error);
391
- };
391
+ }
392
392
  }
393
393
 
394
394
  async goBack() {
@@ -397,14 +397,14 @@ class XboxWebApi extends EventEmitter {
397
397
  return true;
398
398
  } catch (error) {
399
399
  throw new Error(error);
400
- };
400
+ }
401
401
  }
402
402
 
403
403
  async send(commandType, command, payload) {
404
404
  if (!this.consoleAuthorized || !this.rmEnabled) {
405
405
  this.emit('warn', `not authorized or remote management not enabled`);
406
406
  return;
407
- };
407
+ }
408
408
 
409
409
  const sessionid = UuIdv4();
410
410
  const params = payload ?? [];
@@ -431,7 +431,7 @@ class XboxWebApi extends EventEmitter {
431
431
  return true;
432
432
  } catch (error) {
433
433
  throw new Error(`send command type: ${commandType}, command: ${command}, params: ${params}, error: ${error}`);
434
- };
434
+ }
435
435
  }
436
436
  }
437
437
  export default XboxWebApi;
package/src/xboxdevice.js CHANGED
@@ -82,7 +82,7 @@ class XboxDevice extends EventEmitter {
82
82
  this.sensorsInputsConfigured.push(sensor);
83
83
  } else {
84
84
  const log = sensorInputDisplayType === 0 ? false : this.emit('info', `Sensor Name: ${sensorInputName ? sensorInputName : 'Missing'}, Reference: ${sensorInputReference ? sensorInputReference : 'Missing'}`);
85
- };
85
+ }
86
86
  }
87
87
  this.sensorsInputsConfiguredCount = this.sensorsInputsConfigured.length || 0;
88
88
 
@@ -99,7 +99,7 @@ class XboxDevice extends EventEmitter {
99
99
  this.buttonsConfigured.push(button);
100
100
  } else {
101
101
  const log = buttonDisplayType === 0 ? false : this.emit('info', `Button Name: ${buttonName ? buttonName : 'Missing'}, ${buttonMode ? 'Command:' : 'Reference:'} ${buttonReferenceCommand ? buttonReferenceCommand : 'Missing'}, Mode: ${buttonMode ? buttonMode : 'Missing'}`);
102
- };
102
+ }
103
103
  }
104
104
  this.buttonsConfiguredCount = this.buttonsConfigured.length || 0;
105
105
 
@@ -127,7 +127,7 @@ class XboxDevice extends EventEmitter {
127
127
  return true;
128
128
  } catch (error) {
129
129
  throw new Error(`Save data error: ${error}`);
130
- };
130
+ }
131
131
  }
132
132
 
133
133
  async readData(path) {
@@ -136,7 +136,7 @@ class XboxDevice extends EventEmitter {
136
136
  return data;
137
137
  } catch (error) {
138
138
  throw new Error(`Read data error: ${error}`);
139
- };
139
+ }
140
140
  }
141
141
 
142
142
  async sanitizeString(str) {
@@ -216,7 +216,7 @@ class XboxDevice extends EventEmitter {
216
216
  return set;
217
217
  } catch (error) {
218
218
  throw new Error(`${integration} set key: ${key}, value: ${value}, error: ${error}`);
219
- };
219
+ }
220
220
  }
221
221
 
222
222
  async externalIntegrations() {
@@ -238,7 +238,7 @@ class XboxDevice extends EventEmitter {
238
238
  await this.setOverExternalIntegration('RESTFul', key, value);
239
239
  } catch (error) {
240
240
  this.emit('warn', `RESTFul set error: ${error}`);
241
- };
241
+ }
242
242
  })
243
243
  .on('debug', (debug) => {
244
244
  this.emit('debug', debug);
@@ -276,7 +276,7 @@ class XboxDevice extends EventEmitter {
276
276
  await this.setOverExternalIntegration('MQTT', key, value);
277
277
  } catch (error) {
278
278
  this.emit('warn', `MQTT set error: ${error}`);
279
- };
279
+ }
280
280
  })
281
281
  .on('debug', (debug) => {
282
282
  this.emit('debug', debug);
@@ -292,7 +292,7 @@ class XboxDevice extends EventEmitter {
292
292
  return true;
293
293
  } catch (error) {
294
294
  this.emit('warn', `External integration start error: ${error}`);
295
- };
295
+ }
296
296
  }
297
297
 
298
298
  async displayOrder() {
@@ -321,7 +321,7 @@ class XboxDevice extends EventEmitter {
321
321
  return true;
322
322
  } catch (error) {
323
323
  throw new Error(`Display order error: ${error}`);
324
- };
324
+ }
325
325
  }
326
326
 
327
327
  async prepareDataForAccessory() {
@@ -362,7 +362,7 @@ class XboxDevice extends EventEmitter {
362
362
  return true;
363
363
  } catch (error) {
364
364
  throw new Error(`Impulse generator start error: ${error}`);
365
- };
365
+ }
366
366
  }
367
367
 
368
368
  //Prepare accessory
@@ -427,7 +427,7 @@ class XboxDevice extends EventEmitter {
427
427
  await new Promise(resolve => setTimeout(resolve, 3000));
428
428
  } catch (error) {
429
429
  this.emit('warn', `set Power, error: ${error}`);
430
- };
430
+ }
431
431
  });
432
432
 
433
433
  this.televisionService.getCharacteristic(Characteristic.ActiveIdentifier)
@@ -480,7 +480,7 @@ class XboxDevice extends EventEmitter {
480
480
  }
481
481
  } catch (error) {
482
482
  this.emit('warn', `set Input error: ${JSON.stringify(error, null, 2)}`);
483
- };
483
+ }
484
484
  });
485
485
 
486
486
  this.televisionService.getCharacteristic(Characteristic.RemoteKey)
@@ -542,13 +542,13 @@ class XboxDevice extends EventEmitter {
542
542
  channelName = 'Shell';
543
543
  command = this.infoButtonCommand;
544
544
  break;
545
- };
545
+ }
546
546
 
547
547
  await this.xboxWebApi.send(channelName, 'InjectKey', [{ 'keyType': command }]);
548
548
  const logInfo = this.disableLogInfo ? false : this.emit('info', `Remote Key: ${command}`);
549
549
  } catch (error) {
550
550
  this.emit('warn', `set Remote Key error: ${JSON.stringify(error, null, 2)}`);
551
- };
551
+ }
552
552
  });
553
553
 
554
554
  this.televisionService.getCharacteristic(Characteristic.CurrentMediaState)
@@ -572,7 +572,7 @@ class XboxDevice extends EventEmitter {
572
572
  const logInfo = this.disableLogInfo ? false : this.emit('info', `set Target Media: ${['PLAY', 'PAUSE', 'STOP', 'LOADING', 'INTERRUPTED'][value]}`);
573
573
  } catch (error) {
574
574
  this.emit('warn', `set Target Media error: ${error}`);
575
- };
575
+ }
576
576
  });
577
577
 
578
578
  this.televisionService.getCharacteristic(Characteristic.PowerModeSelection)
@@ -589,74 +589,159 @@ class XboxDevice extends EventEmitter {
589
589
  const logInfo = this.disableLogInfo ? false : this.emit('info', `set Power Mode Selection: ${powerModeSelection === 0 ? 'SHOW' : 'HIDE'}`);
590
590
  } catch (error) {
591
591
  this.emit('warn', `set Power Mode Selection error: ${error}`);
592
- };
592
+ }
593
593
  });
594
594
  this.allServices.push(this.televisionService);
595
595
 
596
- //Prepare speaker service
597
- const debug2 = !this.enableDebugMode ? false : this.emit('debug', `Prepare speaker service`);
598
- this.speakerService = accessory.addService(Service.TelevisionSpeaker, `${accessoryName} Speaker`, 'Speaker');
599
- this.speakerService.getCharacteristic(Characteristic.Active)
600
- .onGet(async () => {
601
- const state = this.power;
602
- return state;
603
- })
604
- .onSet(async (state) => {
605
- });
596
+ //Prepare volume service
597
+ if (this.volumeControl > 0) {
598
+ const debug3 = this.enableDebugMode ? this.emit('debug', `Prepare television speaker service`) : false;
599
+ const volumeServiceName = this.volumeControlNamePrefix ? `${accessoryName} ${this.volumeControlName}` : this.volumeControlName;
600
+ this.volumeServiceTvSpeaker = accessory.addService(Service.TelevisionSpeaker, volumeServiceName, 'TV Speaker');
601
+ this.volumeServiceTvSpeaker.addOptionalCharacteristic(Characteristic.ConfiguredName);
602
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.ConfiguredName, volumeServiceName);
603
+ this.volumeServiceTvSpeaker.getCharacteristic(Characteristic.Active)
604
+ .onGet(async () => {
605
+ const state = this.power;
606
+ return state;
607
+ })
608
+ .onSet(async (state) => {
609
+ });
606
610
 
607
- this.speakerService.getCharacteristic(Characteristic.VolumeControlType)
608
- .onGet(async () => {
609
- const state = 3; //none, relative, relative with current, absolute
610
- return state;
611
- });
611
+ this.volumeServiceTvSpeaker.getCharacteristic(Characteristic.VolumeControlType)
612
+ .onGet(async () => {
613
+ const state = 3; //none, relative, relative with current, absolute
614
+ return state;
615
+ });
612
616
 
613
- this.speakerService.getCharacteristic(Characteristic.VolumeSelector)
614
- .onSet(async (volumeSelector) => {
615
- try {
616
- switch (volumeSelector) {
617
- case 0: //Up
618
- await this.xboxWebApi.send('Volume', 'Up');
619
- break;
620
- case 1: //Down
621
- await this.xboxWebApi.send('Volume', 'Down');
622
- break;
617
+ this.volumeServiceTvSpeaker.getCharacteristic(Characteristic.VolumeSelector)
618
+ .onSet(async (volumeSelector) => {
619
+ try {
620
+ switch (volumeSelector) {
621
+ case 0: //Up
622
+ await this.xboxWebApi.send('Volume', 'Up');
623
+ break;
624
+ case 1: //Down
625
+ await this.xboxWebApi.send('Volume', 'Down');
626
+ break;
627
+ }
628
+ const logInfo = this.disableLogInfo ? false : this.emit('info', `set Volume Selector: ${volumeSelector ? 'Down' : 'UP'}`);
629
+ } catch (error) {
630
+ this.emit('warn', `set Volume Selector error: ${error}`);
623
631
  }
624
- const logInfo = this.disableLogInfo ? false : this.emit('info', `set Volume Selector: ${volumeSelector ? 'Down' : 'UP'}`);
625
- } catch (error) {
626
- this.emit('warn', `set Volume Selector error: ${error}`);
627
- };
628
- })
632
+ })
629
633
 
630
- this.speakerService.getCharacteristic(Characteristic.Volume)
631
- .onGet(async () => {
632
- const volume = this.volume;
633
- return volume;
634
- })
635
- .onSet(async (volume) => {
636
- const logInfo = this.disableLogInfo ? false : this.emit('info', `set Volume: ${volume}`);
637
- });
634
+ this.volumeServiceTvSpeaker.getCharacteristic(Characteristic.Volume)
635
+ .onGet(async () => {
636
+ const volume = this.volume;
637
+ return volume;
638
+ })
639
+ .onSet(async (volume) => {
640
+ const logInfo = this.disableLogInfo ? false : this.emit('info', `set Volume: ${volume}`);
641
+ });
638
642
 
639
- this.speakerService.getCharacteristic(Characteristic.Mute)
640
- .onGet(async () => {
641
- const state = this.mute;
642
- return state;
643
- })
644
- .onSet(async (state) => {
645
- try {
646
- switch (state) {
647
- case 0: //Mute
648
- await this.xboxWebApi.send('Audio', 'Mute');
649
- break;
650
- case 1: //Unmute
651
- await this.xboxWebApi.send('Audio', 'Unmute');
652
- break;
643
+ this.volumeServiceTvSpeaker.getCharacteristic(Characteristic.Mute)
644
+ .onGet(async () => {
645
+ const state = this.mute;
646
+ return state;
647
+ })
648
+ .onSet(async (state) => {
649
+ try {
650
+ switch (state) {
651
+ case 0: //Mute
652
+ await this.xboxWebApi.send('Audio', 'Mute');
653
+ break;
654
+ case 1: //Unmute
655
+ await this.xboxWebApi.send('Audio', 'Unmute');
656
+ break;
657
+ }
658
+ const logInfo = this.disableLogInfo ? false : this.emit('info', `set Mute: ${state ? 'ON' : 'OFF'}`);
659
+ } catch (error) {
660
+ this.emit('warn', `set Mute error: ${error}`);
653
661
  }
654
- const logInfo = this.disableLogInfo ? false : this.emit('info', `set Mute: ${state ? 'ON' : 'OFF'}`);
655
- } catch (error) {
656
- this.emit('warn', `set Mute error: ${error}`);
657
- };
658
- });
659
- this.allServices.push(this.speakerService);
662
+ });
663
+ this.allServices.push(this.volumeServiceTvSpeaker);
664
+
665
+ //legacy control
666
+ switch (this.volumeControl) {
667
+ case 1: //lightbulb
668
+ const debug = this.enableDebugMode ? this.emit('debug', `Prepare volume service lightbulb`) : false;
669
+ this.volumeServiceLightbulb = accessory.addService(Service.Lightbulb, volumeServiceName, 'Lightbulb Speaker');
670
+ this.volumeServiceLightbulb.addOptionalCharacteristic(Characteristic.ConfiguredName);
671
+ this.volumeServiceLightbulb.setCharacteristic(Characteristic.ConfiguredName, volumeServiceName);
672
+ this.volumeServiceLightbulb.getCharacteristic(Characteristic.Brightness)
673
+ .onGet(async () => {
674
+ const volume = this.volume;
675
+ return volume;
676
+ })
677
+ .onSet(async (value) => {
678
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Volume, value);
679
+ });
680
+ this.volumeServiceLightbulb.getCharacteristic(Characteristic.On)
681
+ .onGet(async () => {
682
+ const state = this.power ? !this.mute : false;
683
+ return state;
684
+ })
685
+ .onSet(async (state) => {
686
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Mute, !state);
687
+ });
688
+ this.allServices.push(this.volumeServiceLightbulb);
689
+ break;
690
+ case 2: //fan
691
+ const debug1 = this.enableDebugMode ? this.emit('debug', `Prepare volume service fan`) : false;
692
+ this.volumeServiceFan = accessory.addService(Service.Fan, volumeServiceName, 'Fan Speaker');
693
+ this.volumeServiceFan.addOptionalCharacteristic(Characteristic.ConfiguredName);
694
+ this.volumeServiceFan.setCharacteristic(Characteristic.ConfiguredName, volumeServiceName);
695
+ this.volumeServiceFan.getCharacteristic(Characteristic.RotationSpeed)
696
+ .onGet(async () => {
697
+ const volume = this.volume;
698
+ return volume;
699
+ })
700
+ .onSet(async (value) => {
701
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Volume, value);
702
+ });
703
+ this.volumeServiceFan.getCharacteristic(Characteristic.On)
704
+ .onGet(async () => {
705
+ const state = this.power ? !this.mute : false;
706
+ return state;
707
+ })
708
+ .onSet(async (state) => {
709
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Mute, !state);
710
+ });
711
+ this.allServices.push(this.volumeServiceFan);
712
+ break;
713
+ case 3: // speaker
714
+ const debug2 = this.enableDebugMode ? this.emit('debug', `Prepare volume service speaker`) : false;
715
+ this.volumeServiceSpeaker = accessory.addService(Service.Speaker, volumeServiceName, 'Speaker');
716
+ this.volumeServiceSpeaker.addOptionalCharacteristic(Characteristic.ConfiguredName);
717
+ this.volumeServiceSpeaker.setCharacteristic(Characteristic.ConfiguredName, volumeServiceName);
718
+ this.volumeServiceSpeaker.getCharacteristic(Characteristic.Mute)
719
+ .onGet(async () => {
720
+ const state = this.mute;
721
+ return state;
722
+ })
723
+ .onSet(async (state) => {
724
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Mute, state);
725
+ });
726
+ this.volumeServiceSpeaker.getCharacteristic(Characteristic.Active)
727
+ .onGet(async () => {
728
+ const state = this.power;
729
+ return state;
730
+ })
731
+ .onSet(async (state) => {
732
+ });
733
+ this.volumeServiceSpeaker.getCharacteristic(Characteristic.Volume)
734
+ .onGet(async () => {
735
+ const volume = this.volume;
736
+ return volume;
737
+ })
738
+ .onSet(async (value) => {
739
+ this.volumeServiceTvSpeaker.setCharacteristic(Characteristic.Volume, value);
740
+ });
741
+ this.allServices.push(this.volumeServiceSpeaker);
742
+ break;
743
+ }
744
+ }
660
745
 
661
746
  //prepare inputs service
662
747
  const debug3 = !this.enableDebugMode ? false : this.emit('debug', `Prepare inputs service`);
@@ -715,7 +800,7 @@ class XboxDevice extends EventEmitter {
715
800
  .setCharacteristic(Characteristic.Name, sanitizedName)
716
801
  .setCharacteristic(Characteristic.InputSourceType, inputSourceType)
717
802
  .setCharacteristic(Characteristic.IsConfigured, isConfigured)
718
- .setCharacteristic(Characteristic.CurrentVisibilityState, input.visibility)
803
+ .setCharacteristic(Characteristic.CurrentVisibilityState, input.visibility);
719
804
 
720
805
  inputService.getCharacteristic(Characteristic.ConfiguredName)
721
806
  .onGet(async () => {
@@ -756,58 +841,6 @@ class XboxDevice extends EventEmitter {
756
841
  this.allServices.push(inputService);
757
842
  }
758
843
 
759
- //Prepare volume service
760
- if (this.volumeControl) {
761
- const debug = !this.enableDebugMode ? false : this.emit('debug', `Prepare volume service`);
762
- const volumeServiceName = this.volumeControlNamePrefix ? `${accessoryName} ${this.volumeControlName}` : this.volumeControlName;
763
- if (this.volumeControl === 1) {
764
- this.volumeService = accessory.addService(Service.Lightbulb, `${volumeServiceName}`, volumeServiceName);
765
- this.volumeService.addOptionalCharacteristic(Characteristic.ConfiguredName);
766
- this.volumeService.setCharacteristic(Characteristic.ConfiguredName, `${volumeServiceName}`);
767
- this.volumeService.getCharacteristic(Characteristic.Brightness)
768
- .onGet(async () => {
769
- const volume = this.volume;
770
- return volume;
771
- })
772
- .onSet(async (volume) => {
773
- this.speakerService.setCharacteristic(Characteristic.Volume, volume);
774
- });
775
- this.volumeService.getCharacteristic(Characteristic.On)
776
- .onGet(async () => {
777
- const state = !this.mute;
778
- return state;
779
- })
780
- .onSet(async (state) => {
781
- this.speakerService.setCharacteristic(Characteristic.Mute, !state);
782
- });
783
-
784
- this.allServices.push(this.volumeService);
785
- }
786
-
787
- if (this.volumeControl === 2) {
788
- this.volumeServiceFan = accessory.addService(Service.Fan, `${volumeServiceName}`, volumeServiceName);
789
- this.volumeServiceFan.addOptionalCharacteristic(Characteristic.ConfiguredName);
790
- this.volumeServiceFan.setCharacteristic(Characteristic.ConfiguredName, `${volumeServiceName}`);
791
- this.volumeServiceFan.getCharacteristic(Characteristic.RotationSpeed)
792
- .onGet(async () => {
793
- const volume = this.volume;
794
- return volume;
795
- })
796
- .onSet(async (volume) => {
797
- this.speakerService.setCharacteristic(Characteristic.Volume, volume);
798
- });
799
- this.volumeServiceFan.getCharacteristic(Characteristic.On)
800
- .onGet(async () => {
801
- const state = !this.mute;
802
- return state;
803
- })
804
- .onSet(async (state) => {
805
- this.speakerService.setCharacteristic(Characteristic.Mute, !state);
806
- });
807
- this.allServices.push(this.volumeServiceFan);
808
- }
809
- }
810
-
811
844
  //prepare sensor service
812
845
  if (this.sensorPower) {
813
846
  const debug = !this.enableDebugMode ? false : this.emit('debug', `Prepare power sensor service`);
@@ -820,7 +853,7 @@ class XboxDevice extends EventEmitter {
820
853
  return state;
821
854
  });
822
855
  this.allServices.push(this.sensorPowerService);
823
- };
856
+ }
824
857
 
825
858
  if (this.sensorInput) {
826
859
  const debug = !this.enableDebugMode ? false : this.emit('debug', `Prepare input sensor service`);
@@ -833,7 +866,7 @@ class XboxDevice extends EventEmitter {
833
866
  return state;
834
867
  });
835
868
  this.allServices.push(this.sensorInputService);
836
- };
869
+ }
837
870
 
838
871
  if (this.sensorScreenSaver) {
839
872
  const debug = !this.enableDebugMode ? false : this.emit('debug', `Prepare screen saver sensor service`);
@@ -846,7 +879,7 @@ class XboxDevice extends EventEmitter {
846
879
  return state;
847
880
  });
848
881
  this.allServices.push(this.sensorScreenSaverService);
849
- };
882
+ }
850
883
 
851
884
  //prepare sonsor service
852
885
  const possibleSensorInputsCount = 99 - this.allServices.length;
@@ -958,7 +991,7 @@ class XboxDevice extends EventEmitter {
958
991
  }
959
992
  } catch (error) {
960
993
  this.emit('warn', `set Button error: ${error}`);
961
- };
994
+ }
962
995
  });
963
996
  this.buttonsServices.push(buttonService);
964
997
  this.allServices.push(buttonService);
@@ -993,7 +1026,7 @@ class XboxDevice extends EventEmitter {
993
1026
  if (this.informationService) {
994
1027
  this.informationService
995
1028
  .setCharacteristic(Characteristic.Model, consoleType)
996
- };
1029
+ }
997
1030
 
998
1031
  //this.serialNumber = id;
999
1032
  this.modelName = consoleType;
@@ -1026,7 +1059,7 @@ class XboxDevice extends EventEmitter {
1026
1059
  this.consoleAuthorized = this.webApiControl ? await this.xboxWebApi.checkAuthorization() : false;
1027
1060
  } catch (error) {
1028
1061
  this.emit('error', `Start web api error: ${error}`);
1029
- };
1062
+ }
1030
1063
 
1031
1064
  //xbox local client
1032
1065
  this.xboxLocalApi = new XboxLocalApi({
@@ -1056,23 +1089,35 @@ class XboxDevice extends EventEmitter {
1056
1089
  this.televisionService
1057
1090
  .updateCharacteristic(Characteristic.Active, power)
1058
1091
  .updateCharacteristic(Characteristic.ActiveIdentifier, inputIdentifier);
1059
- };
1092
+ }
1060
1093
 
1061
- if (this.speakerService) {
1062
- this.speakerService
1094
+ if (this.volumeServiceTvSpeaker) {
1095
+ this.volumeServiceTvSpeaker
1096
+ .updateCharacteristic(Characteristic.Active, power)
1063
1097
  .updateCharacteristic(Characteristic.Volume, volume)
1064
1098
  .updateCharacteristic(Characteristic.Mute, mute);
1065
- if (this.volumeService) {
1066
- this.volumeService
1067
- .updateCharacteristic(Characteristic.Brightness, volume)
1068
- .updateCharacteristic(Characteristic.On, !mute);
1069
- };
1070
- if (this.volumeServiceFan) {
1071
- this.volumeServiceFan
1072
- .updateCharacteristic(Characteristic.RotationSpeed, volume)
1073
- .updateCharacteristic(Characteristic.On, !mute);
1074
- };
1075
- };
1099
+ }
1100
+
1101
+ if (this.volumeServiceLightbulb) {
1102
+ const muteV = this.power ? !mute : false;
1103
+ this.volumeServiceLightbulb
1104
+ .updateCharacteristic(Characteristic.Brightness, volume)
1105
+ .updateCharacteristic(Characteristic.On, muteV);
1106
+ }
1107
+
1108
+ if (this.volumeServiceFan) {
1109
+ const muteV = this.power ? !mute : false;
1110
+ this.volumeServiceFan
1111
+ .updateCharacteristic(Characteristic.RotationSpeed, volume)
1112
+ .updateCharacteristic(Characteristic.On, muteV);
1113
+ }
1114
+
1115
+ if (this.volumeServiceSpeaker) {
1116
+ this.volumeServiceSpeaker
1117
+ .updateCharacteristic(Characteristic.Active, power)
1118
+ .updateCharacteristic(Characteristic.Volume, volume)
1119
+ .updateCharacteristic(Characteristic.Mute, mute);
1120
+ }
1076
1121
 
1077
1122
  if (this.sensorPowerService) {
1078
1123
  this.sensorPowerService
@@ -1135,7 +1180,7 @@ class XboxDevice extends EventEmitter {
1135
1180
  this.emit('info', `Volume: ${volume}%`);
1136
1181
  this.emit('info', `Mute: ${mute ? 'ON' : 'OFF'}`);
1137
1182
  this.emit('info', `Media State: ${['PLAY', 'PAUSE', 'STOPPED', 'LOADING', 'INTERRUPTED'][mediaState]}`);
1138
- };
1183
+ }
1139
1184
  })
1140
1185
  .on('success', (success) => {
1141
1186
  this.emit('success', success);
@@ -1181,7 +1226,7 @@ class XboxDevice extends EventEmitter {
1181
1226
  return true;
1182
1227
  } catch (error) {
1183
1228
  throw new Error(`Start error: ${error}`);
1184
- };
1229
+ }
1185
1230
  }
1186
- };
1231
+ }
1187
1232
  export default XboxDevice;