diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d0378..aeed1be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +## [2.19.0] - (19.05.2024) + +## Changes + +- added support for service menu access from the input list +- added support for ez adjust menu access from the input list +- config schema updated +- cleanup + ## [2.18.0] - (18.05.2024) ## Changes diff --git a/README.md b/README.md index d163fd9..dec3dd1 100644 --- a/README.md +++ b/README.md @@ -110,11 +110,13 @@ Tested with OLED65G6V, 32LM6300PLA, 49SK8500, OLED65C7T, 55SK800PLB, OLED48CX. | `turnScreenOnOff` | This enable possibility turn the screen ON/OFF, webOS >= 4.0. | | `turnScreenSaverOnOff` | This enable possibility turn the screen saver ON/OFF, webOS >= 4.0. | | `sslWebSocket` | If enabled, SSL WebSocket will support TV with new firmware. | +| `serviceMenu` | If enabled, service menu will be available from the input list. | +| `ezAdjustMenu` | If enabled, ez adjust menu will be available from the input list. | +| `infoButtonCommand` | Here select the function of `I` button in RC app. | `enableDebugMode` | If enabled, deep log will be present in homebridge console. | | `disableLogInfo` | If enabled, disable log info, all values and state will not be displayed in Homebridge log console. | | `disableLogDeviceInfo` | If enabled, add ability to disable log device info by every connections device to the network. | | `disableTvService` | If enabled, TV service will be disabled and prevent display double services if TV already support HomeKit native. | -| `infoButtonCommand` | Here select the function of `I` button in RC app. | | `enableRestFul` | If enabled, RESTful server will start automatically and respond to any path request. | | `restFulPort` | Here set the listening `Port` for RESTful server, every device need own port. | | `restFulDebug` | If enabled, deep log will be present in homebridge console for RESTFul server. | diff --git a/config.schema.json b/config.schema.json index a313d7f..f22861d 100644 --- a/config.schema.json +++ b/config.schema.json @@ -1233,6 +1233,20 @@ } } }, + "serviceMenu": { + "title": "Service Menu", + "type": "boolean", + "default": false, + "description": "This enable access to the service menu from input list.", + "required": false + }, + "ezAdjustMenu": { + "title": "EZ Adjust Menu", + "type": "boolean", + "default": false, + "description": "This enable access to the ez adjust menu from input list.", + "required": false + }, "enableDebugMode": { "title": "Debug", "type": "boolean", @@ -1631,6 +1645,8 @@ "title": "Device", "items": [ "devices[].sslWebSocket", + "devices[].serviceMenu", + "devices[].ezAdjustMenu", "devices[].infoButtonCommand" ] }, diff --git a/package.json b/package.json index 67d2649..bf600e6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "LG webOS TV", "name": "homebridge-lgwebos-tv", - "version": "2.18.3", + "version": "2.19.0", "description": "Homebridge plugin to control LG webOS TV.", "license": "MIT", "author": "grzegorz914", diff --git a/sample-config.json b/sample-config.json index 2da6a4b..6b632ea 100644 --- a/sample-config.json +++ b/sample-config.json @@ -132,6 +132,8 @@ "enableRestFul": false, "restFulPort": 3000, "restFulDebug": false, + "serviceMenu": false, + "ezAdjustMenu": false, "enableMqtt": false, "mqttDebug": false, "mqttHost": "192.168.1.33", diff --git a/src/constants.json b/src/constants.json index 6929dd0..0a78c8b 100644 --- a/src/constants.json +++ b/src/constants.json @@ -90,7 +90,8 @@ "RebootTvWebOs5": "luna://com.webos.service.tv.power/reboot", "ShowInputPicker": "luna://com.webos.surfacemanager/showInputPicker", "SetDeviceInfo": "luna://com.webos.service.eim/setDeviceInfo", - "EjectDevice": "luna://com.webos.service.attachedstoragemanager/ejectDevice" + "EjectDevice": "luna://com.webos.service.attachedstoragemanager/ejectDevice", + "ServiceMenu": "com.webos.app.factorywin" }, "Pairing": { "forcePairing": false, @@ -226,7 +227,6 @@ "com.webos.app.twinlivezoom-intwindemo", "com.webos.app.twinzoom-inmiracast", "com.webos.app.tvtutorial", - "com.webos.app.factorywin", "com.webos.app.inputcommon", "com.webos.app.mvpdwin", "com.webos.app.mystarter", @@ -307,6 +307,7 @@ "com.webos.app.lgnlp", "com.webos.app.actionhandler", "com.webos.app.channeledit", + "com.webos.app.factorywin", "com.webos.exampleapp.enyoapp.epg", "com.webos.exampleapp.qmlapp.hbbtv", "com.webos.exampleapp.qmlapp.client.positive.one", diff --git a/src/lgwebosdevice.js b/src/lgwebosdevice.js index bfb2821..9670d3b 100644 --- a/src/lgwebosdevice.js +++ b/src/lgwebosdevice.js @@ -52,6 +52,8 @@ class LgWebOsDevice extends EventEmitter { this.soundModes = this.soundModeControl ? device.soundModes || [] : []; this.soundOutputControl = device.soundOutputControl || false; this.soundOutputs = this.soundOutputControl ? device.soundOutputs || [] : []; + this.serviceMenu = device.serviceMenu || false; + this.ezAdjustMenu = device.ezAdjustMenu || false; this.enableDebugMode = device.enableDebugMode || false; this.disableLogInfo = device.disableLogInfo || false; this.disableLogDeviceInfo = device.disableLogDeviceInfo || false; @@ -238,6 +240,8 @@ class LgWebOsDevice extends EventEmitter { inputsFile: inputsFile, channelsFile: channelsFile, getInputsFromDevice: this.getInputsFromDevice, + serviceMenu: this.serviceMenu, + ezAdjustMenu: this.ezAdjustMenu, filterSystemApps: this.filterSystemApps, debugLog: this.enableDebugMode, sslWebSocket: this.sslWebSocket @@ -924,9 +928,41 @@ class LgWebOsDevice extends EventEmitter { case true: switch (inputMode) { case 0: - const screenSaver = 'com.webos.app.screensaver'; - const cid = inputReference === screenSaver ? await this.lgWebOsSocket.getCid() : await this.lgWebOsSocket.getCid('App'); - const set = inputReference === screenSaver ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.TurnOnScreenSaver, undefined, cid, 'Set Screen Saver', `Value: ON`) : await this.lgWebOsSocket.send('request', CONSTANTS.ApiUrls.LaunchApp, { id: inputReference }, cid); + switch (inputReference) { + case 'com.webos.app.screensaver': //screen saver + const cid = await this.lgWebOsSocket.getCid(); + await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.TurnOnScreenSaver, undefined, cid, 'Screen Saver', `ON`); + break; + case 'service.menu': //service menu + const payload1 = { + id: CONSTANTS.ApiUrls.ServiceMenu, + params: { + id: "executeFactory", + irKey: "inStart" + } + } + const cid1 = await this.lgWebOsSocket.getCid('App'); + await this.lgWebOsSocket.send('request', CONSTANTS.ApiUrls.LaunchApp, payload1, cid1); + break; + case 'ez.adjust': //ez adjust + const payload2 = { + id: CONSTANTS.ApiUrls.ServiceMenu, + params: { + id: "executeFactory", + irKey: "ezAdjust" + } + } + const cid2 = await this.lgWebOsSocket.getCid('App'); + await this.lgWebOsSocket.send('request', CONSTANTS.ApiUrls.LaunchApp, payload2, cid2); + break; + default: + const payload3 = { + id: inputReference + } + const cid3 = await this.lgWebOsSocket.getCid('App'); + await this.lgWebOsSocket.send('request', CONSTANTS.ApiUrls.LaunchApp, payload3, cid3); + break; + } break; case 1: const liveTv = 'com.webos.app.livetv'; @@ -1431,7 +1467,7 @@ class LgWebOsDevice extends EventEmitter { }; const cid = await this.lgWebOsSocket.getCid(); - await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Backlight', `Value: ${value}`); + await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Backlight', `Value: ${value}`); const info = this.disableLogInfo ? false : this.emit('message', `set Backlight: ${value}`); } catch (error) { this.emit('error', `set Backlight error: ${error}`); @@ -1467,7 +1503,7 @@ class LgWebOsDevice extends EventEmitter { }; const cid = await this.lgWebOsSocket.getCid(); - await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Brightness', `Value: ${value}`); + await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Brightness', `Value: ${value}`); const info = this.disableLogInfo ? false : this.emit('message', `set Brightness: ${value}`); } catch (error) { this.emit('error', `set Brightness error: ${error}`); @@ -1503,7 +1539,7 @@ class LgWebOsDevice extends EventEmitter { }; const cid = await this.lgWebOsSocket.getCid(); - await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Contrast', `Value: ${value}`); + await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Contrast', `Value: ${value}`); const info = this.disableLogInfo ? false : this.emit('message', `set Contrast: ${value}`); } catch (error) { this.emit('error', `set Contrast error: ${error}`); @@ -1539,7 +1575,7 @@ class LgWebOsDevice extends EventEmitter { }; const cid = await this.lgWebOsSocket.getCid(); - await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Color', `Value: ${value}`); + await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Color', `Value: ${value}`); const info = this.disableLogInfo ? false : this.emit('message', `set Color: ${value}`); } catch (error) { this.emit('error', `set Color error: ${error}`); @@ -1576,7 +1612,7 @@ class LgWebOsDevice extends EventEmitter { } const cid = state ? await this.lgWebOsSocket.getCid() : false; - const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Picture Mode', `Value: ${modeName}`) : false; + const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Picture Mode', `Value: ${modeName}`) : false; const info = this.disableLogInfo ? false : this.emit('message', `set Picture Mode: ${modeName}`); } catch (error) { this.emit('error', `set Picture Mode error: ${error}`); @@ -1602,7 +1638,7 @@ class LgWebOsDevice extends EventEmitter { .onSet(async (state) => { try { const cid = await this.lgWebOsSocket.getCid(); - const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.TurnOnScreenSaver, undefined, cid, 'Set Screen Saver', `Value: ON`) : await this.lgWebOsSocket.send('button', undefined, { name: 'EXIT' }); + const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.TurnOnScreenSaver, undefined, cid, 'Screen Saver', `ON`) : await this.lgWebOsSocket.send('button', undefined, { name: 'EXIT' }); const info = this.disableLogInfo ? false : this.emit('message', `set Screen Saver: ${state}`); } catch (error) { this.emit('error', `set Color error: ${error}`); @@ -1673,7 +1709,7 @@ class LgWebOsDevice extends EventEmitter { } const cid = state ? await this.lgWebOsSocket.getCid() : false; - const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Set Sound Mode', `Value: ${modeName}`) : false; + const set = state ? await this.lgWebOsSocket.send('alert', CONSTANTS.ApiUrls.SetSystemSettings, payload, cid, 'Sound Mode', `Value: ${modeName}`) : false; const info = this.disableLogInfo ? false : this.emit('message', `set Sound Mode: ${modeName}`); } catch (error) { this.emit('error', `set Sound Mode error: ${error}`); diff --git a/src/lgwebossocket.js b/src/lgwebossocket.js index 4373aa2..b858194 100644 --- a/src/lgwebossocket.js +++ b/src/lgwebossocket.js @@ -17,15 +17,14 @@ class LgWebOsSocket extends EventEmitter { const channelsFile = config.channelsFile; const getInputsFromDevice = config.getInputsFromDevice; const filterSystemApps = config.filterSystemApps; + const serviceMenu = config.serviceMenu; + const ezAdjustMenu = config.ezAdjustMenu; const debugLog = config.debugLog; const sslWebSocket = config.sslWebSocket; const url = sslWebSocket ? CONSTANTS.ApiUrls.WssUrl.replace('lgwebostv', host) : CONSTANTS.ApiUrls.WsUrl.replace('lgwebostv', host); const webSocketPort = sslWebSocket ? 3001 : 3000; - this.inputs = inputs; this.keyFile = keyFile; - this.getInputsFromDevice = getInputsFromDevice; - this.filterSystemApps = filterSystemApps; this.debugLog = debugLog; this.externalInputsArr = []; @@ -288,8 +287,22 @@ class LgWebOsSocket extends EventEmitter { return; }; + const channelsArr = []; + for (const channel of channelsList) { + const name = channel.channelName; + const channelId = channel.channelId; + const number = channel.channelNumber; + const channelsObj = { + 'name': name, + 'reference': channelId, + 'number': number, + 'mode': 1 + } + channelsArr.push(channelsObj); + }; + //save channels to the file - await this.saveChannels(channelsFile, channelsList); + await this.saveChannels(channelsFile, channelsArr); //restFul this.emit('restFul', 'channels', messageData); @@ -315,6 +328,7 @@ class LgWebOsSocket extends EventEmitter { return; }; + //parse inputs for (const input of externalInputList) { const name = input.label; const reference = input.appId; @@ -351,6 +365,7 @@ class LgWebOsSocket extends EventEmitter { return; }; + //parse apps const appsArr = []; for (const input of appsList) { const name = input.title; @@ -364,9 +379,37 @@ class LgWebOsSocket extends EventEmitter { appsArr.push(obj); }; - //save apps to the file - const inputsApps = this.getInputsFromDevice ? [...this.externalInputsArr, ...appsArr] : this.inputs; - await this.saveInputs(inputsFile, inputsApps); + //add service menu + const serviceMenuInput = { + 'name': 'Service Menu', + 'reference': 'service.menu', + 'mode': 0 + }; + const pushServiceMenu = serviceMenu ? appsArr.push(serviceMenuInput) : false; + + //add ez adjust menu + const ezAdjustMenuInput = { + 'name': 'EZ Adjust', + 'reference': 'ez.adjust', + 'mode': 0 + }; + const pushEzAdjusteMenu = ezAdjustMenu ? appsArr.push(ezAdjustMenuInput) : false; + + //add external inputs and apps to array + const inputsApps = getInputsFromDevice ? [...this.externalInputsArr, ...appsArr] : inputs; + + //chack duplicated object in array and filter system apps + const inputsArr = []; + for (const input of inputsApps) { + const inputName = input.name; + const inputReference = input.reference; + const duplicatedInput = inputsArr.some(input => input.reference === inputReference); + const filter = filterSystemApps ? CONSTANTS.SystemApps.includes(inputReference) : false; + const push = inputName && inputReference && !filter && !duplicatedInput ? inputsArr.push(input) : false; + } + + //save apps to the file + await this.saveInputs(inputsFile, inputsArr); //restFul this.emit('restFul', 'apps', messageData); @@ -449,8 +492,9 @@ class LgWebOsSocket extends EventEmitter { return; }; - const emit = this.screenState === 'Screen Saver' ? this.emit('currentApp', 'com.webos.app.screensaver') : this.emit('currentApp', appId); - this.appId = appId; + const app = appId === 'com.webos.app.factorywin' ? 'service.menu' : appId + const emit = this.screenState === 'Screen Saver' ? this.emit('currentApp', 'com.webos.app.screensaver') : this.emit('currentApp', app); + this.appId = app; //restFul this.emit('restFul', 'currentapp', messageData); @@ -760,20 +804,7 @@ class LgWebOsSocket extends EventEmitter { saveChannels(path, channelsList) { return new Promise(async (resolve, reject) => { try { - const channelsArr = []; - for (const channel of channelsList) { - const name = channel.channelName; - const channelId = channel.channelId; - const number = channel.channelNumber; - const channelsObj = { - 'name': name, - 'reference': channelId, - 'number': number, - 'mode': 1 - } - channelsArr.push(channelsObj); - }; - const channels = JSON.stringify(channelsArr, null, 2); + const channels = JSON.stringify(channelsList, null, 2); await fsPromises.writeFile(path, channels); const debug = this.enableDebugMode ? this.emit('debug', `Channels list saved: ${channels}`) : false; @@ -787,20 +818,9 @@ class LgWebOsSocket extends EventEmitter { saveInputs(path, appsList) { return new Promise(async (resolve, reject) => { try { - //chack duplicated inputs - const inputsArr = []; - for (const input of appsList) { - const inputName = input.name; - const inputReference = input.reference; - const duplicatedInput = inputsArr.some(input => input.reference === inputReference); - const filterSystemApps = this.filterSystemApps ? CONSTANTS.SystemApps.includes(inputReference) : false; - const push = inputName && inputReference && !filterSystemApps && !duplicatedInput ? inputsArr.push(input) : false; - } - - //save inputs - const allInputs = JSON.stringify(inputsArr, null, 2); - await fsPromises.writeFile(path, allInputs); - const debug = this.debugLog ? this.emit('debug', `Apps list saved: ${allInputs}`) : false; + const inputs = JSON.stringify(appsList, null, 2); + await fsPromises.writeFile(path, inputs); + const debug = this.debugLog ? this.emit('debug', `Apps list saved: ${inputs}`) : false; resolve() } catch (error) {