From e3541691c7aef9f2d3aa920aeaa37aa747f69b33 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Tue, 3 Oct 2023 11:48:11 +0200 Subject: [PATCH 01/12] next beta --- package.json | 2 +- src/constans.json | 45 +++++++++++++++++++++--------------- src/localApi/xboxlocalapi.js | 2 +- src/xboxdevice.js | 40 +++++++++++++++----------------- 4 files changed, 47 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 5a8a7f1..4cef1b0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.198", + "version": "2.10.0-beta.205", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", diff --git a/src/constans.json b/src/constans.json index ecf6bac..df15570 100644 --- a/src/constans.json +++ b/src/constans.json @@ -3,66 +3,75 @@ "PluginName": "homebridge-xbox-tv", "DefaultInputs": [ { - "name": "Screensaver", + "oneStoreProductId": "Screensaver", "titleId": "851275400", "reference": "Xbox.IdleScreen_8wekyb3d8bbwe!Xbox.IdleScreen.Application", - "oneStoreProductId": "Screensaver", + "isGame": false, + "name": "Screensaver", "contentType": "Dashboard" }, { - "name": "Dashboard", + "oneStoreProductId": "Dashboard", "titleId": "750323071", "reference": "Xbox.Dashboard_8wekyb3d8bbwe!Xbox.Dashboard.Application", - "oneStoreProductId": "Dashboard", + "isGame": false, + "name": "Dashboard", "contentType": "Dashboard" }, { - "name": "Settings", + "oneStoreProductId": "Settings", "titleId": "1837352387", "reference": "Microsoft.Xbox.Settings_8wekyb3d8bbwe!Xbox.Settings.Application", - "oneStoreProductId": "Settings", + "isGame": false, + "name": "Settings", "contentType": "Dashboard" }, { - "name": "Television", + "oneStoreProductId": "Television", "titleId": "371594669", "reference": "Microsoft.Xbox.LiveTV_8wekyb3d8bbwe!Microsoft.Xbox.LiveTV.Application", - "oneStoreProductId": "Television", + "isGame": false, + "name": "Television", "contentType": "systemApp" }, { - "name": "Settings TV", + "oneStoreProductId": "SettingsTv", "titleId": "2019308066", "reference": "Microsoft.Xbox.TvSettings_8wekyb3d8bbwe!Microsoft.Xbox.TvSettings.Application", - "oneStoreProductId": "SettingsTv", + "isGame": false, + "name": "Settings TV", "contentType": "Dashboard" }, { - "name": "Accessory", + "oneStoreProductId": "Accessory", "titleId": "758407307", "reference": "Microsoft.XboxDevices_8wekyb3d8bbwe!App", - "oneStoreProductId": "Accessory", + "isGame": false, + "name": "Accessory", "contentType": "systemApp" }, { - "name": "Network Troubleshooter", + "oneStoreProductId": "NetworkTroubleshooter", "titleId": "1614319806", "reference": "Xbox.NetworkTroubleshooter_8wekyb3d8bbwe!Xbox.NetworkTroubleshooter.Application", - "oneStoreProductId": "NetworkTroubleshooter", + "isGame": false, + "name": "Network Troubleshooter", "contentType": "systemApp" }, { - "name": "Microsoft Store", + "oneStoreProductId": "MicrosoftStore", "titleId": "1864271209", "reference": "Microsoft.storify_8wekyb3d8bbwe!App", - "oneStoreProductId": "MicrosoftStore", + "isGame": false, + "name": "Microsoft Store", "contentType": "Dashboard" }, { - "name": "Xbox Guide", + "oneStoreProductId": "XboxGuide", "titleId": "1052052983", "reference": "Xbox.Guide_8wekyb3d8bbwe!Xbox.Guide.Application", - "oneStoreProductId": "XboxGuide", + "isGame": false, + "name": "Xbox Guide", "contentType": "systemApp" } ], diff --git a/src/localApi/xboxlocalapi.js b/src/localApi/xboxlocalapi.js index 978d4f5..1717b50 100644 --- a/src/localApi/xboxlocalapi.js +++ b/src/localApi/xboxlocalapi.js @@ -237,7 +237,7 @@ class XBOXLOCALAPI extends EventEmitter { //Start prepare accessory const prepareAccessory = this.startPrepareAccessory ? this.emit('prepareAccessory') : false; - const awaitToPrepareAccesory = this.startPrepareAccessory ? await new Promise(resolve => setTimeout(resolve, 1500)) : false; + const awaitToPrepareAccesory = this.startPrepareAccessory ? await new Promise(resolve => setTimeout(resolve, 1000)) : false; this.startPrepareAccessory = false; const appsCount = Array.isArray(packet.payloadProtected.activeTitles) ? packet.payloadProtected.activeTitles.length : 0; diff --git a/src/xboxdevice.js b/src/xboxdevice.js index 9b3a495..49b649f 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -166,11 +166,6 @@ class XboxDevice extends EventEmitter { }); this.xboxWebApi.on('consoleStatus', (consoleStatusData, consoleType) => { - if (this.informationService) { - this.informationService - .setCharacteristic(Characteristic.Model, consoleType) - }; - //this.serialNumber = id; this.modelName = consoleType; //this.power = powerState; @@ -239,7 +234,7 @@ class XboxDevice extends EventEmitter { if (!this.disableLogDeviceInfo) { this.emit('devInfo', `-------- ${this.name} --------'`); this.emit('devInfo', `Manufacturer: ${'Microsoft'}`); - this.emit('devInfo', `Model: ${this.modelName ?? 'Model Name'}`); + this.emit('devInfo', `Model: ${this.modelName ?? 'Xbox'}`); this.emit('devInfo', `Serialnr: ${this.xboxLiveId}`); this.emit('devInfo', `Firmware: ${firmwareRevision}`); this.emit('devInfo', `Locale: ${locale}`); @@ -248,7 +243,7 @@ class XboxDevice extends EventEmitter { const data = await fsPromises.readFile(this.devInfoFile); const savedInfo = data.length > 5 ? JSON.parse(data) : {}; - const infoHasNotchanged = firmwareRevision === savedInfo.firmwareRevision && locale === savedInfo.locale; + const infoHasNotchanged = this.modelName === savedInfo.modelName && firmwareRevision === savedInfo.firmwareRevision && locale === savedInfo.locale; if (infoHasNotchanged) { return; @@ -257,14 +252,14 @@ class XboxDevice extends EventEmitter { if (this.informationService) { this.informationService .setCharacteristic(Characteristic.Manufacturer, 'Microsoft') - .setCharacteristic(Characteristic.Model, this.modelName ?? 'Model Name') + .setCharacteristic(Characteristic.Model, this.modelName ?? 'Xbox') .setCharacteristic(Characteristic.SerialNumber, this.xboxLiveId) .setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision ?? 'Firmware Revision'); }; const obj = { manufacturer: 'Microsoft', - modelName: data.modelName ?? 'Model Name', + modelName: this.modelName ?? 'Xbox', serialNumber: this.xboxLiveId, firmwareRevision: firmwareRevision ?? 'Firmware Revision', locale: locale @@ -357,6 +352,7 @@ class XboxDevice extends EventEmitter { }) .on('prepareAccessory', async () => { try { + //read dev info from file try { const data = await fsPromises.readFile(this.devInfoFile); @@ -393,6 +389,7 @@ class XboxDevice extends EventEmitter { this.emit('error', `read saved Inputs/Channels Target Visibility error: ${error}`); }; + await new Promise(resolve => setTimeout(resolve, 1000)); const accessory = await this.prepareAccessory(); this.emit('publishAccessory', accessory) } catch (error) { @@ -428,8 +425,8 @@ class XboxDevice extends EventEmitter { //Pinformation service this.informationService = accessory.getService(Service.AccessoryInformation) .setCharacteristic(Characteristic.Manufacturer, this.savedInfo.manufacturer ?? 'Microsoft') - .setCharacteristic(Characteristic.Model, this.savedInfo.modelName ?? 'Model Name') - .setCharacteristic(Characteristic.SerialNumber, this.savedInfo.serialNumber ?? 'Serial Number') + .setCharacteristic(Characteristic.Model, this.savedInfo.modelName ?? 'Xbox') + .setCharacteristic(Characteristic.SerialNumber, this.savedInfo.serialNumber ?? this.xboxLiveId) .setCharacteristic(Characteristic.FirmwareRevision, this.savedInfo.firmwareRevision ?? 'Firmware Revision'); this.allServices.push(this.informationService); @@ -501,17 +498,17 @@ class XboxDevice extends EventEmitter { this.televisionService.getCharacteristic(Characteristic.ActiveIdentifier) .onGet(async () => { const inputIdentifier = this.inputIdentifier; - const inputName = this.inputsName[inputIdentifier]; - const inputReference = this.inputsReference[inputIdentifier]; const inputOneStoreProductId = this.inputsOneStoreProductId[inputIdentifier]; + const inputReference = this.inputsReference[inputIdentifier]; + const inputName = this.inputsName[inputIdentifier]; const logInfo = this.disableLogInfo ? false : this.emit('message', `Input: ${inputName}, Reference: ${inputReference}, Product Id: ${inputOneStoreProductId}`); return inputIdentifier; }) .onSet(async (inputIdentifier) => { try { - const inputName = this.inputsName[inputIdentifier]; - const inputReference = this.inputsReference[inputIdentifier]; const inputOneStoreProductId = this.inputsOneStoreProductId[inputIdentifier]; + const inputReference = this.inputsReference[inputIdentifier]; + const inputName = this.inputsName[inputIdentifier]; switch (this.power) { case false: @@ -783,12 +780,12 @@ class XboxDevice extends EventEmitter { //get input const input = inputs[i]; - //get input reference - const inputReference = input.reference || input.titleId || input.oneStoreProductId; - //get input oneStoreProductId const inputOneStoreProductId = input.oneStoreProductId; + //get input reference + const inputReference = input.reference || input.titleId || input.oneStoreProductId; + //get input name const inputName = this.savedInputsNames[inputReference] ?? input.name; @@ -832,10 +829,9 @@ class XboxDevice extends EventEmitter { }) .onSet(async (state) => { try { - const targetVisibilityIdentifier = inputReference || inputOneStoreProductId; - this.savedInputsTargetVisibility[this.targetVisibilityIdentifier] = state; - + this.savedInputsTargetVisibility[inputReference] = state; const newTargetVisibility = JSON.stringify(this.savedInputsTargetVisibility, null, 2); + await fsPromises.writeFile(this.inputsTargetVisibilityFile, newTargetVisibility); const debug = this.enableDebugMode ? this.emit('debug', `Saved Input: ${inputName} Target Visibility: ${state ? 'HIDEN' : 'SHOWN'}`) : false; inputService.setCharacteristic(Characteristic.CurrentVisibilityState, state); @@ -844,8 +840,8 @@ class XboxDevice extends EventEmitter { } }); - this.inputsReference.push(inputReference); this.inputsOneStoreProductId.push(inputOneStoreProductId); + this.inputsReference.push(inputReference); this.inputsName.push(inputName); this.televisionService.addLinkedService(inputService); From 77c0840a6d76931dfe11713ee402ff0d0737de9f Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Tue, 3 Oct 2023 12:10:52 +0200 Subject: [PATCH 02/12] cleanup --- package.json | 2 +- src/webApi/xboxwebapi.js | 31 +++++++++++++------------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 4cef1b0..b5ecf0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.205", + "version": "2.10.0-beta.206", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", diff --git a/src/webApi/xboxwebapi.js b/src/webApi/xboxwebapi.js index a1eb56e..d01cfb2 100644 --- a/src/webApi/xboxwebapi.js +++ b/src/webApi/xboxwebapi.js @@ -50,9 +50,9 @@ class XBOXWEBAPI extends EventEmitter { 'x-xbl-client-version': '39.39.22001.0', 'skillplatform': 'RemoteManagement' } + this.headers = headers; this.tokens = data.tokens; this.authorized = true; - this.headers = headers; //create axios instance this.axiosInstance = axios.create({ @@ -94,11 +94,10 @@ class XBOXWEBAPI extends EventEmitter { try { const url = `${CONSTANTS.WebApi.Url.Xccs}/consoles/${this.xboxLiveId}`; const getConsoleStatusData = await this.axiosInstance(url); - const responseObject = getConsoleStatusData.data; - const debug = this.debugLog ? this.emit('debug', `getConsoleStatusData, result: ${JSON.stringify(responseObject, null, 2)}`) : false; + const debug = this.debugLog ? this.emit('debug', `getConsoleStatusData, result: ${JSON.stringify(getConsoleStatusData.data, null, 2)}`) : false; //get console status - const consoleStatusData = responseObject; + const consoleStatusData = getConsoleStatusData.data; const id = consoleStatusData.id; const name = consoleStatusData.name; const locale = consoleStatusData.locale; @@ -126,8 +125,7 @@ class XBOXWEBAPI extends EventEmitter { try { const url = `${CONSTANTS.WebApi.Url.Xccs}/lists/devices?queryCurrentDevice=false&includeStorageDevices=true`; const getConsolesListData = await this.axiosInstance(url); - const responseObject = getConsolesListData.data; - const debug = this.debugLog ? this.emit('debug', `getConsolesListData, result: ${responseObject.result[0]}, ${responseObject.result[0].storageDevices[0]}`) : false; + const debug = this.debugLog ? this.emit('debug', `getConsolesListData, result: ${getConsolesListData.data.result[0]}, ${getConsolesListData.data.result[0].storageDevices[0]}`) : false; //get consoles list this.consolesId = []; @@ -149,7 +147,7 @@ class XBOXWEBAPI extends EventEmitter { this.consolesTotalSpaceBytes = []; this.consolesIsGen9Compatible = []; - const consolesList = responseObject.result; + const consolesList = getConsolesListData.data.result; for (const console of consolesList) { const id = console.id; const name = console.name; @@ -206,12 +204,11 @@ class XBOXWEBAPI extends EventEmitter { try { const url = `${CONSTANTS.WebApi.Url.Xccs}/lists/installedApps?deviceId=${this.xboxLiveId}`; const getInstalledAppsData = await this.axiosInstance(url); - const responseObject = getInstalledAppsData.data; - const debug = this.debugLog ? this.emit('debug', `getInstalledAppsData: ${JSON.stringify(responseObject.result, null, 2)}`) : false; + const debug = this.debugLog ? this.emit('debug', `getInstalledAppsData: ${JSON.stringify(getInstalledAppsData.data.result, null, 2)}`) : false; //get installed apps const appsArray = []; - const apps = responseObject.result; + const apps = getInstalledAppsData.data.result; for (const app of apps) { const oneStoreProductId = app.oneStoreProductId; const titleId = app.titleId; @@ -254,8 +251,7 @@ class XBOXWEBAPI extends EventEmitter { try { const url = `${CONSTANTS.WebApi.Url.Xccs}/lists/storageDevices?deviceId=${this.xboxLiveId}`; const getStorageDevicesData = await this.axiosInstance(url); - const responseObject = getStorageDevicesData.data; - const debug = this.debugLog ? this.emit('debug', `getStorageDevicesData, result: ${JSON.stringify(responseObject, null, 2)}`) : false; + const debug = this.debugLog ? this.emit('debug', `getStorageDevicesData, result: ${JSON.stringify(getStorageDevicesData.data, null, 2)}`) : false; //get console storages this.storageDeviceId = []; @@ -265,9 +261,9 @@ class XBOXWEBAPI extends EventEmitter { this.totalSpaceBytes = []; this.isGen9Compatible = []; - const storageDevices = responseObject.result; - const deviceId = responseObject.deviceId; - const agentUserId = responseObject.agentUserId; + const storageDevices = getStorageDevicesData.data.result; + const deviceId = getStorageDevicesData.data.deviceId; + const agentUserId = getStorageDevicesData.data.agentUserId; for (const storageDevice of storageDevices) { const storageDeviceId = storageDevice.storageDeviceId; const storageDeviceName = storageDevice.storageDeviceName; @@ -297,8 +293,7 @@ class XBOXWEBAPI extends EventEmitter { try { const url = `https://profile.xboxlive.com/users/xuid(${this.tokens.xsts.DisplayClaims.xui[0].xid})/profile/settings?settings=GameDisplayName,GameDisplayPicRaw,Gamerscore,Gamertag`; const getUserProfileData = await this.axiosInstance(url); - const responseObject = getUserProfileData.data; - const debug = this.debugLog ? this.emit('debug', `getUserProfileData, result: ${JSON.stringify(responseObject.profileUsers[0], null, 2)}, ${JSON.stringify(responseObject.profileUsers[0].settings[0], null, 2)}`) : false + const debug = this.debugLog ? this.emit('debug', `getUserProfileData, result: ${JSON.stringify(getUserProfileData.data.profileUsers[0], null, 2)}, ${JSON.stringify(getUserProfileData.data.profileUsers[0].settings[0], null, 2)}`) : false //get user profiles this.userProfileId = []; @@ -307,7 +302,7 @@ class XBOXWEBAPI extends EventEmitter { this.userProfileSettingsId = []; this.userProfileSettingsValue = []; - const profileUsers = responseObject.profileUsers; + const profileUsers = getUserProfileData.data.profileUsers; for (const userProfile of profileUsers) { const id = userProfile.id; const hostId = userProfile.hostId; From b92d33cec6f53d07d67dc1d2d118c9a5257211ac Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sat, 7 Oct 2023 06:36:21 +0200 Subject: [PATCH 03/12] Update xboxdevice.js --- src/xboxdevice.js | 58 ++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/src/xboxdevice.js b/src/xboxdevice.js index 49b649f..a62ebde 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -233,7 +233,7 @@ class XboxDevice extends EventEmitter { try { if (!this.disableLogDeviceInfo) { this.emit('devInfo', `-------- ${this.name} --------'`); - this.emit('devInfo', `Manufacturer: ${'Microsoft'}`); + this.emit('devInfo', `Manufacturer: Microsoft`); this.emit('devInfo', `Model: ${this.modelName ?? 'Xbox'}`); this.emit('devInfo', `Serialnr: ${this.xboxLiveId}`); this.emit('devInfo', `Firmware: ${firmwareRevision}`); @@ -243,7 +243,11 @@ class XboxDevice extends EventEmitter { const data = await fsPromises.readFile(this.devInfoFile); const savedInfo = data.length > 5 ? JSON.parse(data) : {}; - const infoHasNotchanged = this.modelName === savedInfo.modelName && firmwareRevision === savedInfo.firmwareRevision && locale === savedInfo.locale; + const infoHasNotchanged = + 'Microsoft' === savedInfo.manufacturer + && this.modelName === savedInfo.modelName + && firmwareRevision === savedInfo.firmwareRevision + && locale === savedInfo.locale; if (infoHasNotchanged) { return; @@ -254,14 +258,14 @@ class XboxDevice extends EventEmitter { .setCharacteristic(Characteristic.Manufacturer, 'Microsoft') .setCharacteristic(Characteristic.Model, this.modelName ?? 'Xbox') .setCharacteristic(Characteristic.SerialNumber, this.xboxLiveId) - .setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision ?? 'Firmware Revision'); + .setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision); }; const obj = { manufacturer: 'Microsoft', - modelName: this.modelName ?? 'Xbox', + modelName: this.modelName, serialNumber: this.xboxLiveId, - firmwareRevision: firmwareRevision ?? 'Firmware Revision', + firmwareRevision: firmwareRevision, locale: locale }; const devInfo = JSON.stringify(obj, null, 2); @@ -375,7 +379,7 @@ class XboxDevice extends EventEmitter { try { const data = await fsPromises.readFile(this.inputsNamesFile); this.savedInputsNames = data.length > 5 ? JSON.parse(data) : {}; - const debug = this.enableDebugMode ? this.emit('debug', `Read saved Inputs/Channels Names: ${JSON.stringify(this.savedInputsNames, null, 2)}`) : false; + const debug = this.enableDebugMode ? this.emit('debug', `Read saved Inputs Names: ${JSON.stringify(this.savedInputsNames, null, 2)}`) : false; } catch (error) { this.emit('error', `read saved Inputs/Channels Names error: ${error}`); }; @@ -384,12 +388,12 @@ class XboxDevice extends EventEmitter { try { const data = await fsPromises.readFile(this.inputsTargetVisibilityFile); this.savedInputsTargetVisibility = data.length > 5 ? JSON.parse(data) : {}; - const debug = this.enableDebugMode ? this.emit('debug', `Read saved Inputs/Channels Target Visibility: ${JSON.stringify(this.savedInputsTargetVisibility, null, 2)}`) : false; + const debug = this.enableDebugMode ? this.emit('debug', `Read saved Inputs Target Visibility: ${JSON.stringify(this.savedInputsTargetVisibility, null, 2)}`) : false; } catch (error) { this.emit('error', `read saved Inputs/Channels Target Visibility error: ${error}`); }; - await new Promise(resolve => setTimeout(resolve, 1000)); + await new Promise(resolve => setTimeout(resolve, 2000)); const accessory = await this.prepareAccessory(); this.emit('publishAccessory', accessory) } catch (error) { @@ -467,29 +471,33 @@ class XboxDevice extends EventEmitter { return state; }) .onSet(async (state) => { + if (this.power == state) { + return; + } + try { switch (this.webApiPowerOnOff) { case true: - switch (state) { - case 0: //off - const powerOff = this.power ? await this.xboxWebApi.powerOff() : false; + switch (this.power) { + case true: //off + await this.xboxWebApi.powerOff(); break; - case 1: //on - const powerOn = !this.power ? await this.xboxWebApi.powerOn() : false; + case false: //on + await this.xboxWebApi.powerOn(); break; } break; case false: - switch (state) { - case 0: //off - const powerOff = this.power ? await this.xboxLocalApi.powerOff() : false; + switch (this.power) { + case true: //off + await this.xboxLocalApi.powerOff(); break; - case 1: //on - const powerOn = !this.power ? await this.xboxLocalApi.powerOn() : false; + case false: //on + await this.xboxLocalApi.powerOn(); break; } } - const logInfo = this.disableLogInfo || (state === this.power) ? false : this.emit('message', `set Power: ${state ? 'ON' : 'OFF'}`); + const logInfo = this.disableLogInfo ? false : this.emit('message', `set Power: ${state ? 'ON' : 'OFF'}`); } catch (error) { this.emit('error', `set Power, error: ${error}`); }; @@ -758,8 +766,7 @@ class XboxDevice extends EventEmitter { accessory.addService(this.speakerService); //Prepare inputs services - const debug3 = !this.enableDebugMode ? false : this.emit('debug', `Prepare input service`); - + const debug3 = !this.enableDebugMode ? false : this.emit('debug', `Prepare inputs service`); //check possible inputs and filter custom unnecessary inputs const filteredInputsArr = []; for (const input of this.savedInputs) { @@ -809,6 +816,9 @@ class XboxDevice extends EventEmitter { .setCharacteristic(Characteristic.CurrentVisibilityState, currentVisibility) inputService.getCharacteristic(Characteristic.ConfiguredName) + .onGet(async () => { + return inputName; + }) .onSet(async (value) => { try { this.savedInputsNames[inputReference] = value; @@ -816,7 +826,8 @@ class XboxDevice extends EventEmitter { await fsPromises.writeFile(this.inputsNamesFile, newCustomName); const debug = this.enableDebugMode ? this.emit('debug', `Saved Input Name: ${value}, Reference: ${nameIdentifier}.`) : false; - inputService.setCharacteristic(Characteristic.Name, value); + inputService.updateCharacteristic(Characteristic.Name, value); + inputService.updateCharacteristic(Characteristic.ConfiguredName, value); } catch (error) { this.emit('error', `save Input Name error: ${error}`); } @@ -834,7 +845,8 @@ class XboxDevice extends EventEmitter { await fsPromises.writeFile(this.inputsTargetVisibilityFile, newTargetVisibility); const debug = this.enableDebugMode ? this.emit('debug', `Saved Input: ${inputName} Target Visibility: ${state ? 'HIDEN' : 'SHOWN'}`) : false; - inputService.setCharacteristic(Characteristic.CurrentVisibilityState, state); + inputService.updateCharacteristic(Characteristic.CurrentVisibilityState, state); + inputService.updateCharacteristic(Characteristic.TargetVisibilityState, state); } catch (error) { this.emit('error', `save Target Visibility error: ${error}`); } From b989c72817ed8886116ba7e8feb43e9dcc3a9f17 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sat, 7 Oct 2023 06:36:25 +0200 Subject: [PATCH 04/12] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b5ecf0f..72cb6f1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.206", + "version": "2.10.0-beta.210", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", From 9e1e1cfd5009869f67dc8044a28493a7e388beb8 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Fri, 20 Oct 2023 10:50:33 +0200 Subject: [PATCH 05/12] bump dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 72cb6f1..d5263a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.210", + "version": "2.10.0-beta.211", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", @@ -25,8 +25,8 @@ "LICENSE" ], "engines": { - "node": ">=16.0.0", - "homebridge": ">=1.5.0" + "node": ">=18.0.0", + "homebridge": ">=1.6.0" }, "dependencies": { "@homebridge/plugin-ui-utils": "^0.1.0", From 9a4396134a166eae99b6b2c3cccd1e72d1151e0c Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sun, 22 Oct 2023 11:23:06 +0200 Subject: [PATCH 06/12] cleanup --- CHANGELOG.md | 3 - README.md | 2 - config.schema.json | 2 - package.json | 2 +- sample-config.json | 2 - src/webApi/xboxwebapi.js | 136 --------------------------------- src/xboxdevice.js | 157 ++++++++++++++++++++++----------------- 7 files changed, 90 insertions(+), 214 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d07294..389f4d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Changes - full code refactor - added possibility toggle Power control between local/web api -- added possibility toggle RC control between local/web api -- added possibility toggle Volume control between local/web api -- fixed laggy remote control [#140](https://github.com/grzegorz914/homebridge-xbox-tv/issues/140) - fixed disconnect problem on first run - performance and stability improvements - config.schema updated diff --git a/README.md b/README.md index 947d94d..b03e6ed 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,6 @@ Homebridge plugin for Microsoft game Consoles. Tested with Xbox One X/S and Xbox | `sensorInputs.displayType` | Here select sensor type to be exposed in HomeKit app, possible `None/Disabled`, `Motion Sensor`, `Occupancy Sensor`, `Contact Sensor`. | | `webApiControl` | This enable console control over Web Api. Additional functions are available in `Advanced Settings` section. | | `webApiPowerOnOff` | This enable `Power` control over Web Api. | -| `webApiRcControl` | This enable `Remote` control over Web Api. | -| `webApiVolumeControl` | This enable `Volume/Mute` control over Web Api. | | `webApiToken` | Required if `webApiControl` enabled, use Authorization Manager to get it. | | `webApiClientId` | If You are created App on Azure AD then You can use your own Client Id. | | `webApiClientSecret` | If You are created App on Azure AD then You can use own Client Secret. | diff --git a/config.schema.json b/config.schema.json index a0c5c4c..30cc2c5 100644 --- a/config.schema.json +++ b/config.schema.json @@ -861,8 +861,6 @@ "items": [ "devices[].webApiControl", "devices[].webApiPowerOnOff", - "devices[].webApiRcControl", - "devices[].webApiVolumeControl", "devices[].webApiToken", "devices[].webApiClientId", "devices[].webApiClientSecret" diff --git a/package.json b/package.json index d5263a7..3940f6a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.211", + "version": "2.10.0-beta.212", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", diff --git a/sample-config.json b/sample-config.json index e62e06a..d1dce93 100644 --- a/sample-config.json +++ b/sample-config.json @@ -76,8 +76,6 @@ ], "webApiControl": false, "webApiPowerOnOff": false, - "webApiRcControl": false, - "webApiVolumeControl": false, "webApiToken": "", "webApiClientId": "", "webApiClientSecret": "", diff --git a/src/webApi/xboxwebapi.js b/src/webApi/xboxwebapi.js index d01cfb2..61714ea 100644 --- a/src/webApi/xboxwebapi.js +++ b/src/webApi/xboxwebapi.js @@ -330,84 +330,6 @@ class XBOXWEBAPI extends EventEmitter { }); } - powerOn() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Power', 'WakeUp'); - resolve(); - } catch (error) { - this.emit('powerOnError', false); - reject(error); - }; - }); - } - - powerOff() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Power', 'TurnOff'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - reboot() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Power', 'Reboot'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - mute() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Audio', 'Mute'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - unmute() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Audio', 'Unmute'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - volumeUp() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Volume', 'Up'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - volumeDown() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Volume', 'Down'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - next() { return new Promise(async (resolve, reject) => { try { @@ -463,64 +385,6 @@ class XBOXWEBAPI extends EventEmitter { }); } - - goHome() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Shell', 'GoHome'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - launchApp(oneStoreProductId) { - return new Promise(async (resolve, reject) => { - try { - await this.send('Shell', 'ActivateApplicationWithOneStoreProductId', [{ 'oneStoreProductId': oneStoreProductId }]); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - showGuideTab() { - return new Promise(async (resolve, reject) => { - try { - await this.send('Shell', 'ShowGuideTab', [{ - 'tabName': 'Guide' - }]); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - showTVGuide() { - return new Promise(async (resolve, reject) => { - try { - await this.send('TV', 'ShowGuide'); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - - sendButtonPress(button) { - return new Promise(async (resolve, reject) => { - try { - await this.send('Shell', 'InjectKey', [{ 'keyType': button }]); - resolve(); - } catch (error) { - reject(error); - }; - }); - } - send(commandType, command, payload) { return new Promise(async (resolve, reject) => { if (!this.authorized) { diff --git a/src/xboxdevice.js b/src/xboxdevice.js index a62ebde..2b41bb6 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -476,16 +476,23 @@ class XboxDevice extends EventEmitter { } try { + let channelName; + let command; + switch (this.webApiPowerOnOff) { case true: switch (this.power) { case true: //off - await this.xboxWebApi.powerOff(); + channelName = 'Power'; + command = 'WakeUp'; break; case false: //on - await this.xboxWebApi.powerOn(); + channelName = 'Power'; + command = 'TurnOff'; break; } + + await this.xboxWebApi.send(channelName, command); break; case false: switch (this.power) { @@ -497,6 +504,7 @@ class XboxDevice extends EventEmitter { break; } } + const logInfo = this.disableLogInfo ? false : this.emit('message', `set Power: ${state ? 'ON' : 'OFF'}`); } catch (error) { this.emit('error', `set Power, error: ${error}`); @@ -518,6 +526,9 @@ class XboxDevice extends EventEmitter { const inputReference = this.inputsReference[inputIdentifier]; const inputName = this.inputsName[inputIdentifier]; + let channelName; + let command; + let payload; switch (this.power) { case false: await new Promise(resolve => setTimeout(resolve, 3000)); @@ -526,18 +537,26 @@ class XboxDevice extends EventEmitter { case true: switch (inputOneStoreProductId) { case 'Dashboard': case 'Settings': case 'SettingsTv': case 'Accessory': case 'Screensaver': case 'NetworkTroubleshooter': case 'MicrosoftStore': - await this.xboxWebApi.goHome(); + channelName = 'Shell'; + command = 'GoHome'; break; case 'Television': - await this.xboxWebApi.showTVGuide(); + channelName = 'TV'; + command = 'ShowGuide'; break; case 'XboxGuide': - await this.xboxWebApi.showGuideTab(); + channelName = 'Shell'; + command = 'ShowGuideTab'; + payload = [{ 'tabName': 'Guide' }]; break; default: - await this.xboxWebApi.launchApp(inputOneStoreProductId); + channelName = 'Shell'; + command = 'ActivateApplicationWithOneStoreProductId'; + payload = [{ 'oneStoreProductId': inputOneStoreProductId }]; break; } + + await this.xboxWebApi.send(channelName, command, payload); const logInfo = this.disableLogInfo ? false : this.emit('message', `set Input: ${inputName}, Reference: ${inputReference}, Product Id: ${inputOneStoreProductId}`); break; } @@ -549,64 +568,65 @@ class XboxDevice extends EventEmitter { this.televisionService.getCharacteristic(Characteristic.RemoteKey) .onSet(async (remoteKey) => { try { - let command; let channelName; + let command; + switch (remoteKey) { case 0: //REWIND + channelName = 'Shell'; command = 'rewind'; - channelName = 'Media'; break; case 1: //FAST_FORWARD + channelName = 'Shell'; command = 'fastForward'; - channelName = 'Media'; break; case 2: //NEXT_TRACK + channelName = 'Shell'; command = 'nextTrack'; - channelName = 'Media'; break; case 3: //PREVIOUS_TRACK + channelName = 'Shell'; command = 'previousTrack'; - channelName = 'Media'; break; case 4: //ARROW_UP + channelName = 'Shell'; command = 'up'; - channelName = 'Input'; break; case 5: //ARROW_DOWN + channelName = 'Shell'; command = 'down'; - channelName = 1; break; case 6: //ARROW_LEFT + channelName = 'Shell'; command = 'left'; - channelName = 'Input'; break; case 7: //ARROW_RIGHT + channelName = 'Shell'; command = 'right'; - channelName = 'Input'; break; case 8: //SELECT + channelName = 'Shell'; command = 'a'; - channelName = 'Input'; break; case 9: //BACK + channelName = 'Shell'; command = 'b'; - channelName = 'Input'; break; case 10: //EXIT + channelName = 'Shell'; command = 'nexus'; - channelName = 'Input'; break; case 11: //PLAY_PAUSE + channelName = 'Shell'; command = 'playPause'; - channelName = 'Media'; break; case 15: //INFORMATION + channelName = 'Shell'; command = this.infoButtonCommand; - channelName = 'Input'; break; }; - const sendRcCommand = this.webApiRcControl ? await this.xboxWebApi.sendButtonPress(command) : await this.xboxLocalApi.sendButtonPress(channelName, command); + await this.xboxWebApi.send(channelName, 'InjectKey', [{ 'keyType': command }]); const logInfo = this.disableLogInfo ? false : this.emit('message', `Remote Key: ${command}`); } catch (error) { this.emit('error', `set Remote Key error: ${JSON.stringify(error, null, 2)}`); @@ -642,20 +662,20 @@ class XboxDevice extends EventEmitter { this.televisionService.getCharacteristic(Characteristic.PowerModeSelection) .onSet(async (powerModeSelection) => { try { - let command; let channelName; + let command; switch (powerModeSelection) { case 0: //SHOW + channelName = 'Shell'; command = 'nexus'; - channelName = 'Input'; break; case 1: //HIDE + channelName = 'Shell'; command = 'b'; - channelName = 'Input'; break; }; - const sendRcCommand = this.webApiRcControl ? await this.xboxWebApi.sendButtonPress(command) : await this.xboxLocalApi.sendButtonPress(channelName, command); + await this.xboxWebApi.send(channelName, 'InjectKey', [{ 'keyType': command }]); const logInfo = this.disableLogInfo ? false : this.emit('message', `set Power Mode Selection: ${powerModeSelection === 0 ? 'SHOW' : 'HIDE'}`); } catch (error) { this.emit('error', `set Power Mode Selection error: ${error}`); @@ -685,34 +705,20 @@ class XboxDevice extends EventEmitter { this.speakerService.getCharacteristic(Characteristic.VolumeSelector) .onSet(async (volumeSelector) => { try { - let command; let channelName; - switch (this.webApiVolumeControl) { - case true: - switch (volumeSelector) { - case 0: //volUp - const volDown = this.power ? await this.xboxWebApi.volumeUp() : false; - break; - case 1: //volDown - const volUp = this.power ? await this.xboxWebApi.volumeDown() : false; - break; - } + let command; + switch (volumeSelector) { + case 0: //Up + channelName = 'Volume'; + command = 'Up'; break; - case false: - switch (volumeSelector) { - case 0: //volUp - command = 'volUp'; - channelName = 'Media'; - break; - case 1: //volDown - command = 'volDown'; - channelName = 'Media'; - break; - }; - - await this.xboxLocalApi.sendButtonPress(channelName, command) + case 1: //Down + channelName = 'Volume'; + command = 'Down'; break; } + + await this.xboxWebApi.send(channelName, command); const logInfo = this.disableLogInfo ? false : this.emit('message', `set Volume Selector: ${volumeSelector ? 'Down' : 'UP'}`); } catch (error) { this.emit('error', `set Volume Selector error: ${error}`); @@ -740,22 +746,20 @@ class XboxDevice extends EventEmitter { }) .onSet(async (state) => { try { - switch (this.webApiVolumeControl) { - case true: - switch (state) { - case true: //mute - const mute = this.power ? await this.xboxWebApi.mute() : false; - break; - case false: //unmute - const unmute = this.power ? await this.xboxWebApi.unmute() : false; - break; - } + let channelName; + let command; + switch (volumeSelector) { + case 0: //Mute + channelName = 'Audio'; + command = 'Mute'; break; - case false: - const channelName = 'Media'; - const toggleMute = this.power ? await this.xboxLocalApi.sendButtonPress(channelName, 'volMute') : false; + case 1: //Unmute + channelName = 'Audio'; + command = 'Unmute'; break; } + + await this.xboxWebApi.send(channelName, command); const logInfo = this.disableLogInfo ? false : this.emit('message', `set Mute: ${state ? 'ON' : 'OFF'}`); } catch (error) { this.emit('error', `set Mute error: ${error}`); @@ -1065,36 +1069,53 @@ class XboxDevice extends EventEmitter { .onSet(async (state) => { if (state) { try { + let channelName; + let command; + let payload; + switch (buttonMode) { case 0: case 1: case 2: - await this.xboxWebApi.sendButtonPress(buttonCommand); + channelName = 'Shell'; + command = 'InjectKey'; + payload = [{ 'keyType': buttonCommand }]; break; case 3: + channelName = 'TV'; + command = 'ShowGuide'; await this.xboxLocalApi.recordGameDvr(); break; case 4: - await this.xboxWebApi.reboot(); + channelName = 'Power'; + command = 'Reboot'; break; case 5: switch (buttonOneStoreProductId) { case 'Dashboard': case 'Settings': case 'SettingsTv': case 'Accessory': case 'Screensaver': case 'NetworkTroubleshooter': case 'MicrosoftStore': - await this.xboxWebApi.goGome(); + channelName = 'Shell'; + command = 'GoHome'; break; case 'Television': - await this.xboxWebApi.showTVGuide(); + channelName = 'TV'; + command = 'ShowGuide'; break; case 'XboxGuide': - await this.xboxWebApi.showGuideTab(); + channelName = 'Shell'; + command = 'ShowGuideTab'; + payload = [{ 'tabName': 'Guide' }]; break; case 'Not set': case 'Web api disabled': this.emit('message', `trying to launch App/Game with one store product id: ${buttonOneStoreProductId}.`); break; default: - await this.xboxWebApi.launchApp(buttonOneStoreProductId); + channelName = 'Shell'; + command = 'ActivateApplicationWithOneStoreProductId'; + payload = [{ 'oneStoreProductId': buttonOneStoreProductId }]; break; } break; } + + const send = buttonMode !== 3 ? await this.xboxWebApi.send(channelName, command, payload) : false; const logInfo = this.disableLogInfo ? false : this.emit('message', `set Button Name: ${buttonName}, Command: ${buttonCommand}`); } catch (error) { this.emit('error', `set Button error: ${error}`); From da624a5998aa73f2585b973ddea7dd17cd13aa8f Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Tue, 31 Oct 2023 12:01:57 +0100 Subject: [PATCH 07/12] bump deps --- package.json | 6 +++--- src/xboxdevice.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3940f6a..bc7af21 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.212", + "version": "2.10.0-beta.223", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", @@ -29,7 +29,7 @@ "homebridge": ">=1.6.0" }, "dependencies": { - "@homebridge/plugin-ui-utils": "^0.1.0", + "@homebridge/plugin-ui-utils": "^1.0.0", "async-mqtt": "^2.6.3", "elliptic": "^6.5.4", "hex-to-binary": "^1.0.1", @@ -37,7 +37,7 @@ "uuid": "^9.0.1", "ping": "^0.4.4", "express": "^4.18.2", - "axios": "^1.5.1" + "axios": "^1.6.0" }, "keywords": [ "homebridge", diff --git a/src/xboxdevice.js b/src/xboxdevice.js index 2b41bb6..fc992ed 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -484,11 +484,11 @@ class XboxDevice extends EventEmitter { switch (this.power) { case true: //off channelName = 'Power'; - command = 'WakeUp'; + command = 'TurnOff'; break; case false: //on channelName = 'Power'; - command = 'TurnOff'; + command = 'WakeUp'; break; } From 6dc1ac25ff8c99a1d32871b4dc3445327cdafbd3 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Thu, 2 Nov 2023 09:42:08 +0100 Subject: [PATCH 08/12] better inputs handling --- package.json | 2 +- src/xboxdevice.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bc7af21..fe5969b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.223", + "version": "2.10.0-beta.224", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", diff --git a/src/xboxdevice.js b/src/xboxdevice.js index fc992ed..a008aad 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -811,7 +811,7 @@ class XboxDevice extends EventEmitter { const targetVisibility = currentVisibility; if (inputReference && inputName) { - const inputService = new Service.InputSource(inputName, `Input ${i}`); + const inputService = new Service.InputSource(`${inputName} ${i}`, `Input ${i}`); inputService .setCharacteristic(Characteristic.Identifier, i) .setCharacteristic(Characteristic.Name, inputName) From 07793d70325fd12eab3c3ae6565813956c394e1b Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Thu, 2 Nov 2023 10:02:16 +0100 Subject: [PATCH 09/12] add check exist configured inputs name and target visibility --- package.json | 2 +- src/xboxdevice.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index fe5969b..a755fb6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.224", + "version": "2.10.0-beta.225", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", diff --git a/src/xboxdevice.js b/src/xboxdevice.js index a008aad..c5b9b88 100644 --- a/src/xboxdevice.js +++ b/src/xboxdevice.js @@ -824,6 +824,11 @@ class XboxDevice extends EventEmitter { return inputName; }) .onSet(async (value) => { + const valueExist = value === this.savedInputsNames[inputReference]; + if (valueExist) { + return; + } + try { this.savedInputsNames[inputReference] = value; const newCustomName = JSON.stringify(this.savedInputsNames, null, 2); @@ -843,6 +848,11 @@ class XboxDevice extends EventEmitter { return targetVisibility; }) .onSet(async (state) => { + const stateExist = state === this.savedInputsTargetVisibility[inputReference]; + if (stateExist) { + return; + }; + try { this.savedInputsTargetVisibility[inputReference] = state; const newTargetVisibility = JSON.stringify(this.savedInputsTargetVisibility, null, 2); From a29fd422106a77f589471488836e016ae561952d Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Tue, 28 Nov 2023 15:36:02 +0100 Subject: [PATCH 10/12] bump --- package.json | 4 ++-- src/localApi/xboxlocalapi.js | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index a755fb6..e9c05b1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.225", + "version": "2.10.0-beta.229", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", @@ -37,7 +37,7 @@ "uuid": "^9.0.1", "ping": "^0.4.4", "express": "^4.18.2", - "axios": "^1.6.0" + "axios": "^1.6.1" }, "keywords": [ "homebridge", diff --git a/src/localApi/xboxlocalapi.js b/src/localApi/xboxlocalapi.js index 1717b50..c1fdd4e 100644 --- a/src/localApi/xboxlocalapi.js +++ b/src/localApi/xboxlocalapi.js @@ -2,6 +2,7 @@ const fs = require('fs'); const fsPromises = fs.promises; const Dgram = require('dgram'); +const Net = require('net'); const { parse: UuIdParse, v4: UuIdv4 } = require('uuid'); const EventEmitter = require('events'); const Ping = require('ping'); @@ -33,10 +34,15 @@ class XBOXLOCALAPI extends EventEmitter { //dgram socket this.connect = () => { - this.client = new Dgram.createSocket('udp4'); - this.client.on('error', (error) => { + const udpType = Net.isIPv6(this.host) ? 'udp6' : 'udp4'; + const socket = Dgram.createSocket(udpType); + socket.on('error', (error) => { this.emit('error', `Socket error: ${error}`); - this.client.close(); + socket.close(); + }).on('close', () => { + const debug = this.debugLog ? this.emit('debug', 'Socket closed.') : false; + this.isConnected = false; + this.reconnect(); }).on('message', async (message, remote) => { const debug = this.debugLog ? this.emit('debug', `Received message from: ${remote.address}:${remote.port}`) : false; this.heartBeatStartTime = Date.now(); @@ -285,8 +291,10 @@ class XBOXLOCALAPI extends EventEmitter { break; }; }).on('listening', async () => { - const address = this.client.address(); + //socket.setBroadcast(true); + const address = socket.address(); const debug = this.debugLog ? this.emit('debug', `Server start listening: ${address.address}:${address.port}.`) : false; + this.socket = socket; //ping console setInterval(async () => { @@ -325,10 +333,6 @@ class XBOXLOCALAPI extends EventEmitter { await new Promise(resolve => setTimeout(resolve, 5000)); const prepareAccessory = this.startPrepareAccessory ? this.emit('prepareAccessory') : false; this.startPrepareAccessory = false; - }).on('close', () => { - const debug = this.debugLog ? this.emit('debug', 'Socket closed.') : false; - this.isConnected = false; - this.reconnect(); }).bind(); }; @@ -581,7 +585,7 @@ class XBOXLOCALAPI extends EventEmitter { const offset = 0; const length = message.byteLength; - this.client.send(message, offset, length, 5050, this.host, (error, bytes) => { + this.socket.send(message, offset, length, 5050, this.host, (error, bytes) => { if (error) { reject(error); return; From e689d317627f285afc1d050e235117fba49401d6 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Mon, 4 Dec 2023 17:49:05 +0100 Subject: [PATCH 11/12] bump beta --- config.schema.json | 2 +- package.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config.schema.json b/config.schema.json index 30cc2c5..e087c77 100644 --- a/config.schema.json +++ b/config.schema.json @@ -4,7 +4,7 @@ "singular": true, "fixArrays": true, "customUi": true, - "headerDisplay": "This plugin works with Xbox game Consoles. Devices are exposed to HomeKit as separate accessories and each needs to be manually paired.\n\n1. Open the Home app on your device.\n2. Tap the .\n3. Tap *Add Accessory*, and select *I Don't Have a Code or Cannot Scan* or *More Options*.\n4. Select Your accessory and press add anyway.\n5. Enter the PIN or scan the QR code, this can be found in Homebridge UI or Homebridge logs.\n6. Complete the accessory setup.", + "headerDisplay": "This plugin works with Xbox Game Consoles. Devices are exposed to HomeKit as separate accessories and each needs to be manually paired.", "footerDisplay": "For documentation please see [GitHub repository](https://github.com/grzegorz914/homebridge-xbox-tv).", "schema": { "type": "object", diff --git a/package.json b/package.json index e9c05b1..71e52a5 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.229", - "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", + "version": "2.10.0-beta.230", + "description": "Homebridge plugin to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", "homepage": "https://github.com/grzegorz914/homebridge-xbox-tv#readme", @@ -33,11 +33,11 @@ "async-mqtt": "^2.6.3", "elliptic": "^6.5.4", "hex-to-binary": "^1.0.1", - "jsrsasign": "^10.8.6", + "jsrsasign": "^10.9.0", "uuid": "^9.0.1", "ping": "^0.4.4", "express": "^4.18.2", - "axios": "^1.6.1" + "axios": "^1.6.2" }, "keywords": [ "homebridge", From 380dab9bd9c1a42a3faa5b96ef2d72dade1ef4cf Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Tue, 26 Dec 2023 11:13:57 +0100 Subject: [PATCH 12/12] bump --- CHANGELOG.md | 2 +- index.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 389f4d1..5ade1d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### NOTE!!! ## After update to 2.x.x the plugin settings (xboxLiveId) need to be updated. -## [2.10.0] - (xx.09.2023) +## [2.10.0] - (26.12.2023) ## After update to this version the plugin properties are changed and console must be authorized and settings need to be corrected. ## Changes - full code refactor diff --git a/index.js b/index.js index 4334b95..3085413 100644 --- a/index.js +++ b/index.js @@ -22,7 +22,7 @@ class XboxPlatform { api.on('didFinishLaunching', () => { for (const device of config.devices) { if (!device.name || !device.host || !device.xboxLiveId) { - log.warn(`Device Name: ${device.name ? device.name : 'Missing'}, Host: ${device.host ? device.host : 'Missing'} or Xbox Live ID: ${device.xboxLiveId ? device.xboxLiveId : 'Missing'}.`); + log.warn(`Name: ${device.name ? 'OK' : device.name}, Host: ${device.host ? 'OK' : device.host}, Xbox Live ID: ${device.xboxLiveId ? 'OK' : device.xboxLiveId}, wromg or missing.`); return; } const debug = device.enableDebugMode ? log(`Device: ${device.host} ${device.name}, did finish launching.`) : false; diff --git a/package.json b/package.json index 71e52a5..d366daa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.10.0-beta.230", + "version": "2.10.0", "description": "Homebridge plugin to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914",