homebridge-xbox-tv 2.12.8 → 2.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/localApi/xboxlocalapi.js +39 -2
- package/src/webApi/xboxwebapi.js +44 -5
- package/src/xboxdevice.js +38 -92
package/package.json
CHANGED
|
@@ -18,8 +18,9 @@ class XBOXLOCALAPI extends EventEmitter {
|
|
|
18
18
|
this.crypto = new SGCrypto();
|
|
19
19
|
this.host = config.host;
|
|
20
20
|
this.xboxLiveId = config.xboxLiveId;
|
|
21
|
-
this.infoLog = config.infoLog;
|
|
22
21
|
this.tokensFile = config.tokensFile;
|
|
22
|
+
this.devInfoFile = config.devInfoFile;
|
|
23
|
+
this.infoLog = config.infoLog;
|
|
23
24
|
this.debugLog = config.debugLog;
|
|
24
25
|
|
|
25
26
|
this.isConnected = false;
|
|
@@ -236,7 +237,10 @@ class XBOXLOCALAPI extends EventEmitter {
|
|
|
236
237
|
const buildNumber = packet.payloadProtected.buildNumber;
|
|
237
238
|
const locale = packet.payloadProtected.locale;
|
|
238
239
|
const firmwareRevision = `${majorVersion}.${minorVersion}.${buildNumber}`;
|
|
239
|
-
|
|
240
|
+
|
|
241
|
+
//save device info to the file
|
|
242
|
+
await this.saveDevInfo(this.tokensFile, firmwareRevision, locale)
|
|
243
|
+
|
|
240
244
|
this.emit('deviceInfo', firmwareRevision, locale);
|
|
241
245
|
this.emitDevInfo = false;
|
|
242
246
|
};
|
|
@@ -257,6 +261,18 @@ class XBOXLOCALAPI extends EventEmitter {
|
|
|
257
261
|
|
|
258
262
|
this.emit('stateChanged', power, volume, mute, mediaState, titleId, reference);
|
|
259
263
|
const debug = this.debugLog ? this.emit('debug', `Status changed, app Id: ${titleId}, reference: ${reference}`) : false;
|
|
264
|
+
|
|
265
|
+
//emit restFul and mqtt
|
|
266
|
+
const obj = {
|
|
267
|
+
'power': power,
|
|
268
|
+
'titleId': titleId,
|
|
269
|
+
'app': reference,
|
|
270
|
+
'volume': volume,
|
|
271
|
+
'mute': mute,
|
|
272
|
+
'mediaState': mediaState,
|
|
273
|
+
};
|
|
274
|
+
this.emit('restFul', 'state', obj);
|
|
275
|
+
this.emit('mqtt', 'State', obj);
|
|
260
276
|
};
|
|
261
277
|
|
|
262
278
|
//acknowledge
|
|
@@ -357,6 +373,27 @@ class XBOXLOCALAPI extends EventEmitter {
|
|
|
357
373
|
});
|
|
358
374
|
}
|
|
359
375
|
|
|
376
|
+
saveDevInfo(path, firmwareRevision, locale) {
|
|
377
|
+
return new Promise(async (resolve, reject) => {
|
|
378
|
+
try {
|
|
379
|
+
const obj = {
|
|
380
|
+
manufacturer: 'Microsoft',
|
|
381
|
+
modelName: 'Xbox',
|
|
382
|
+
serialNumber: this.xboxLiveId,
|
|
383
|
+
firmwareRevision: firmwareRevision,
|
|
384
|
+
locale: locale
|
|
385
|
+
};
|
|
386
|
+
const devInfo = JSON.stringify(obj, null, 2);
|
|
387
|
+
await fsPromises.writeFile(path, devInfo);
|
|
388
|
+
const debug = this.debugLog ? this.emit('debug', `Saved device info: ${devInfo}`) : false;
|
|
389
|
+
|
|
390
|
+
resolve();
|
|
391
|
+
} catch (error) {
|
|
392
|
+
reject(error);
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
|
|
360
397
|
acknowledge(sequenceNumber) {
|
|
361
398
|
return new Promise(async (resolve, reject) => {
|
|
362
399
|
try {
|
package/src/webApi/xboxwebapi.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const fsPromises = fs.promises;
|
|
2
4
|
const QueryString = require('querystring');
|
|
3
5
|
const EventEmitter = require('events');
|
|
4
6
|
const { v4: UuIdv4 } = require('uuid');
|
|
@@ -23,6 +25,7 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
23
25
|
this.xboxLiveId = config.xboxLiveId;
|
|
24
26
|
this.webApiClientId = config.webApiClientId;
|
|
25
27
|
this.webApiClientSecret = config.webApiClientSecret;
|
|
28
|
+
this.inputsFile = config.inputsFile;
|
|
26
29
|
this.debugLog = config.debugLog;
|
|
27
30
|
|
|
28
31
|
//variables
|
|
@@ -112,7 +115,13 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
112
115
|
const consoleStreamingEnabled = consoleStatusData.consoleStreamingEnabled;
|
|
113
116
|
const remoteManagementEnabled = consoleStatusData.remoteManagementEnabled;
|
|
114
117
|
|
|
115
|
-
|
|
118
|
+
//emit console type
|
|
119
|
+
this.emit('consoleStatus', consoleType);
|
|
120
|
+
|
|
121
|
+
//emit restFul and mqtt
|
|
122
|
+
this.emit('restFul', 'status', consoleStatusData);
|
|
123
|
+
this.emit('mqtt', 'status', consoleStatusData);
|
|
124
|
+
|
|
116
125
|
resolve(remoteManagementEnabled);
|
|
117
126
|
} catch (error) {
|
|
118
127
|
reject(`get status error: ${error}`);
|
|
@@ -191,7 +200,10 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
191
200
|
}
|
|
192
201
|
}
|
|
193
202
|
|
|
194
|
-
|
|
203
|
+
//emit restFul and mqtt
|
|
204
|
+
this.emit('restFul', 'consoleslist', consolesList);
|
|
205
|
+
this.emit('mqtt', 'Consoles List', consolesList);
|
|
206
|
+
|
|
195
207
|
resolve();
|
|
196
208
|
} catch (error) {
|
|
197
209
|
reject(`Consoles list error: ${error}`);
|
|
@@ -238,7 +250,13 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
238
250
|
appsArray.push(inputsObj);
|
|
239
251
|
};
|
|
240
252
|
|
|
241
|
-
|
|
253
|
+
//save apps to the file
|
|
254
|
+
await this.saveInputs(this.inputsFile, appsArray);
|
|
255
|
+
|
|
256
|
+
//emit restFul and mqtt
|
|
257
|
+
this.emit('restFul', 'apps', apps);
|
|
258
|
+
this.emit('mqtt', 'Apps', apps);
|
|
259
|
+
|
|
242
260
|
resolve();
|
|
243
261
|
} catch (error) {
|
|
244
262
|
reject(`get installed apps error: ${error}`);
|
|
@@ -280,7 +298,10 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
280
298
|
this.isGen9Compatible.push(isGen9Compatible);
|
|
281
299
|
};
|
|
282
300
|
|
|
283
|
-
|
|
301
|
+
//emit restFul and mqtt
|
|
302
|
+
this.emit('restFul', 'storages', storageDevices);
|
|
303
|
+
this.emit('mqtt', 'Storages', storageDevices);
|
|
304
|
+
|
|
284
305
|
resolve();
|
|
285
306
|
} catch (error) {
|
|
286
307
|
reject(`get storage devices error: ${error}`);
|
|
@@ -322,7 +343,10 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
322
343
|
};
|
|
323
344
|
};
|
|
324
345
|
|
|
325
|
-
|
|
346
|
+
//emit restFul and mqtt
|
|
347
|
+
this.emit('restFul', 'profile', profileUsers);
|
|
348
|
+
this.emit('mqtt', 'Profile', profileUsers);
|
|
349
|
+
|
|
326
350
|
resolve();
|
|
327
351
|
} catch (error) {
|
|
328
352
|
reject(`User profile error: ${error}`);
|
|
@@ -330,6 +354,21 @@ class XBOXWEBAPI extends EventEmitter {
|
|
|
330
354
|
});
|
|
331
355
|
}
|
|
332
356
|
|
|
357
|
+
saveInputs(path, appsArray) {
|
|
358
|
+
return new Promise(async (resolve, reject) => {
|
|
359
|
+
try {
|
|
360
|
+
const allApps = [...CONSTANTS.DefaultInputs, ...appsArray];
|
|
361
|
+
const apps = JSON.stringify(allApps, null, 2)
|
|
362
|
+
await fsPromises.writeFile(path, apps);
|
|
363
|
+
const debug = this.debugLog ? this.emit('debug', `Saved apps: ${apps}`) : false;
|
|
364
|
+
|
|
365
|
+
resolve()
|
|
366
|
+
} catch (error) {
|
|
367
|
+
reject(error);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
|
|
333
372
|
next() {
|
|
334
373
|
return new Promise(async (resolve, reject) => {
|
|
335
374
|
try {
|
package/src/xboxdevice.js
CHANGED
|
@@ -72,13 +72,13 @@ class XboxDevice extends EventEmitter {
|
|
|
72
72
|
//add configured inputs to the default inputs
|
|
73
73
|
this.inputs = [...CONSTANTS.DefaultInputs, ...this.inputs];
|
|
74
74
|
this.inputsConfigured = [];
|
|
75
|
+
this.inputIdentifier = 1;
|
|
75
76
|
|
|
76
77
|
//state variable
|
|
77
78
|
this.power = false;
|
|
78
79
|
this.volume = 0;
|
|
79
80
|
this.mute = true;
|
|
80
81
|
this.mediaState = 0;
|
|
81
|
-
this.inputIdentifier = 1;
|
|
82
82
|
this.reference = '';
|
|
83
83
|
|
|
84
84
|
//sensors variable
|
|
@@ -166,43 +166,16 @@ class XboxDevice extends EventEmitter {
|
|
|
166
166
|
webApiClientId: this.webApiClientId,
|
|
167
167
|
webApiClientSecret: this.webApiClientSecret,
|
|
168
168
|
tokensFile: this.authTokenFile,
|
|
169
|
+
inputsFile: this.inputsFile,
|
|
169
170
|
debugLog: this.enableDebugMode
|
|
170
171
|
});
|
|
171
172
|
|
|
172
|
-
this.xboxWebApi.on('consoleStatus', (
|
|
173
|
+
this.xboxWebApi.on('consoleStatus', (consoleType) => {
|
|
173
174
|
//this.serialNumber = id;
|
|
174
175
|
this.modelName = consoleType;
|
|
175
176
|
//this.power = powerState;
|
|
176
177
|
//this.mediaState = playbackState;
|
|
177
|
-
|
|
178
|
-
const restFul = this.restFulConnected ? this.restFul.update('status', consoleStatusData) : false;
|
|
179
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('Status', consoleStatusData) : false;
|
|
180
178
|
})
|
|
181
|
-
.on('consolesList', (consolesList) => {
|
|
182
|
-
const restFul = this.restFulConnected ? this.restFul.update('consoleslist', consolesList) : false;
|
|
183
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('Consoles List', consolesList) : false;
|
|
184
|
-
})
|
|
185
|
-
.on('appsList', async (appsArray) => {
|
|
186
|
-
try {
|
|
187
|
-
const apps = [...CONSTANTS.DefaultInputs, ...appsArray];
|
|
188
|
-
const stringifyApps = JSON.stringify(apps, null, 2)
|
|
189
|
-
await fsPromises.writeFile(this.inputsFile, stringifyApps);
|
|
190
|
-
const debug = this.enableDebugMode ? this.emit('debug', `Saved apps: ${stringifyApps}`) : false;
|
|
191
|
-
|
|
192
|
-
const restFul = this.restFulConnected ? this.restFul.update('apps', apps) : false;
|
|
193
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('Apps', apps) : false;
|
|
194
|
-
} catch (error) {
|
|
195
|
-
this.emit('error', `save apps error: ${error}`);
|
|
196
|
-
};
|
|
197
|
-
})
|
|
198
|
-
.on('storageDevices', (storageDevices) => {
|
|
199
|
-
const restFul = this.restFulConnected ? this.restFul.update('storages', storageDevices) : false;
|
|
200
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('Storages', storageDevices) : false;
|
|
201
|
-
})
|
|
202
|
-
.on('userProfile', (profileUsers) => {
|
|
203
|
-
const restFul = this.restFulConnected ? this.restFul.update('profile', profileUsers) : false;
|
|
204
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('Profile', profileUsers) : false;
|
|
205
|
-
})
|
|
206
179
|
.on('powerOnError', (power) => {
|
|
207
180
|
if (this.televisionService) {
|
|
208
181
|
this.televisionService
|
|
@@ -210,6 +183,12 @@ class XboxDevice extends EventEmitter {
|
|
|
210
183
|
};
|
|
211
184
|
this.power = power;
|
|
212
185
|
})
|
|
186
|
+
.on('restFul', (path, data) => {
|
|
187
|
+
const restFul = this.restFulConnected ? this.restFul.update(path, data) : false;
|
|
188
|
+
})
|
|
189
|
+
.on('mqtt', (topic, data) => {
|
|
190
|
+
const mqtt = this.mqttConnected ? this.mqtt.send(topic, data) : false;
|
|
191
|
+
})
|
|
213
192
|
.on('message', (message) => {
|
|
214
193
|
this.emit('message', message);
|
|
215
194
|
})
|
|
@@ -225,60 +204,32 @@ class XboxDevice extends EventEmitter {
|
|
|
225
204
|
this.xboxLocalApi = new XboxLocalApi({
|
|
226
205
|
host: this.host,
|
|
227
206
|
xboxLiveId: this.xboxLiveId,
|
|
228
|
-
infoLog: this.disableLogInfo,
|
|
229
207
|
tokensFile: this.authTokenFile,
|
|
208
|
+
devInfoFile: this.devInfoFile,
|
|
209
|
+
infoLog: this.disableLogInfo,
|
|
230
210
|
debugLog: this.enableDebugMode
|
|
231
211
|
});
|
|
232
212
|
|
|
233
|
-
this.xboxLocalApi.on('
|
|
234
|
-
this.emit('message',
|
|
213
|
+
this.xboxLocalApi.on('deviceInfo', (firmwareRevision, locale) => {
|
|
214
|
+
this.emit('message', 'Connected.');
|
|
215
|
+
if (!this.disableLogDeviceInfo) {
|
|
216
|
+
this.emit('devInfo', `-------- ${this.name} --------'`);
|
|
217
|
+
this.emit('devInfo', `Manufacturer: Microsoft`);
|
|
218
|
+
this.emit('devInfo', `Model: ${this.modelName ?? 'Xbox'}`);
|
|
219
|
+
this.emit('devInfo', `Serialnr: ${this.xboxLiveId}`);
|
|
220
|
+
this.emit('devInfo', `Firmware: ${firmwareRevision}`);
|
|
221
|
+
this.emit('devInfo', `Locale: ${locale}`);
|
|
222
|
+
this.emit('devInfo', `----------------------------------`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (this.informationService) {
|
|
226
|
+
this.informationService
|
|
227
|
+
.setCharacteristic(Characteristic.Manufacturer, 'Microsoft')
|
|
228
|
+
.setCharacteristic(Characteristic.Model, this.modelName ?? 'Xbox')
|
|
229
|
+
.setCharacteristic(Characteristic.SerialNumber, this.xboxLiveId)
|
|
230
|
+
.setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision);
|
|
231
|
+
};
|
|
235
232
|
})
|
|
236
|
-
.on('deviceInfo', async (firmwareRevision, locale) => {
|
|
237
|
-
try {
|
|
238
|
-
if (!this.disableLogDeviceInfo) {
|
|
239
|
-
this.emit('devInfo', `-------- ${this.name} --------'`);
|
|
240
|
-
this.emit('devInfo', `Manufacturer: Microsoft`);
|
|
241
|
-
this.emit('devInfo', `Model: ${this.modelName ?? 'Xbox'}`);
|
|
242
|
-
this.emit('devInfo', `Serialnr: ${this.xboxLiveId}`);
|
|
243
|
-
this.emit('devInfo', `Firmware: ${firmwareRevision}`);
|
|
244
|
-
this.emit('devInfo', `Locale: ${locale}`);
|
|
245
|
-
this.emit('devInfo', `----------------------------------`);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const data = await fsPromises.readFile(this.devInfoFile);
|
|
249
|
-
const savedInfo = data.length > 5 ? JSON.parse(data) : {};
|
|
250
|
-
const infoHasNotchanged =
|
|
251
|
-
'Microsoft' === savedInfo.manufacturer
|
|
252
|
-
&& this.modelName === savedInfo.modelName
|
|
253
|
-
&& firmwareRevision === savedInfo.firmwareRevision
|
|
254
|
-
&& locale === savedInfo.locale;
|
|
255
|
-
|
|
256
|
-
if (infoHasNotchanged) {
|
|
257
|
-
return;
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
if (this.informationService) {
|
|
261
|
-
this.informationService
|
|
262
|
-
.setCharacteristic(Characteristic.Manufacturer, 'Microsoft')
|
|
263
|
-
.setCharacteristic(Characteristic.Model, this.modelName ?? 'Xbox')
|
|
264
|
-
.setCharacteristic(Characteristic.SerialNumber, this.xboxLiveId)
|
|
265
|
-
.setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision);
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const obj = {
|
|
269
|
-
manufacturer: 'Microsoft',
|
|
270
|
-
modelName: this.modelName,
|
|
271
|
-
serialNumber: this.xboxLiveId,
|
|
272
|
-
firmwareRevision: firmwareRevision,
|
|
273
|
-
locale: locale
|
|
274
|
-
};
|
|
275
|
-
const devInfo = JSON.stringify(obj, null, 2);
|
|
276
|
-
await fsPromises.writeFile(this.devInfoFile, devInfo);
|
|
277
|
-
const debug = this.enableDebugMode ? this.emit('debug', `Saved device info: ${devInfo}`) : false;
|
|
278
|
-
} catch (error) {
|
|
279
|
-
this.emit('error', `save device info error: ${error}`);
|
|
280
|
-
}
|
|
281
|
-
})
|
|
282
233
|
.on('stateChanged', (power, volume, mute, mediaState, titleId, reference) => {
|
|
283
234
|
const index = this.inputsConfigured.findIndex(input => input.reference === reference || input.titleId === titleId) ?? -1;
|
|
284
235
|
const inputIdentifier = index !== -1 ? this.inputsConfigured[index].identifier : this.inputIdentifier;
|
|
@@ -289,7 +240,7 @@ class XboxDevice extends EventEmitter {
|
|
|
289
240
|
.updateCharacteristic(Characteristic.Active, power)
|
|
290
241
|
};
|
|
291
242
|
|
|
292
|
-
if (this.televisionService
|
|
243
|
+
if (this.televisionService) {
|
|
293
244
|
this.televisionService
|
|
294
245
|
.updateCharacteristic(Characteristic.ActiveIdentifier, inputIdentifier);
|
|
295
246
|
};
|
|
@@ -315,7 +266,7 @@ class XboxDevice extends EventEmitter {
|
|
|
315
266
|
.updateCharacteristic(Characteristic.ContactSensorState, power)
|
|
316
267
|
}
|
|
317
268
|
|
|
318
|
-
if (this.sensorInputService
|
|
269
|
+
if (this.sensorInputService) {
|
|
319
270
|
const state = power ? (this.inputIdentifier !== inputIdentifier) : false;
|
|
320
271
|
this.sensorInputService
|
|
321
272
|
.updateCharacteristic(Characteristic.ContactSensorState, state)
|
|
@@ -350,17 +301,6 @@ class XboxDevice extends EventEmitter {
|
|
|
350
301
|
this.mute = mute;
|
|
351
302
|
this.mediaState = mediaState;
|
|
352
303
|
|
|
353
|
-
const obj = {
|
|
354
|
-
'power': power,
|
|
355
|
-
'titleId': titleId,
|
|
356
|
-
'app': reference,
|
|
357
|
-
'volume': volume,
|
|
358
|
-
'mute': mute,
|
|
359
|
-
'mediaState': mediaState,
|
|
360
|
-
};
|
|
361
|
-
const restFul = this.restFulConnected ? this.restFul.update('state', obj) : false;
|
|
362
|
-
const mqtt = this.mqttConnected ? this.mqtt.send('State', obj) : false;
|
|
363
|
-
|
|
364
304
|
if (!this.disableLogInfo) {
|
|
365
305
|
const name = index !== -1 ? this.inputsConfigured[index].name : reference;
|
|
366
306
|
const productId = index !== -1 ? this.inputsConfigured[index].oneStoreProductId : reference;
|
|
@@ -423,6 +363,12 @@ class XboxDevice extends EventEmitter {
|
|
|
423
363
|
this.emit('error', `prepare accessory error: ${error}`);
|
|
424
364
|
};
|
|
425
365
|
})
|
|
366
|
+
.on('restFul', (path, data) => {
|
|
367
|
+
const restFul = this.restFulConnected ? this.restFul.update(path, data) : false;
|
|
368
|
+
})
|
|
369
|
+
.on('mqtt', (topic, data) => {
|
|
370
|
+
const mqtt = this.mqttConnected ? this.mqtt.send(topic, data) : false;
|
|
371
|
+
})
|
|
426
372
|
.on('message', (message) => {
|
|
427
373
|
this.emit('message', message);
|
|
428
374
|
})
|