Skip to content

KPIotr89/iobroker.lgtv-full

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ioBroker LG TV Full Adapter

LG TV Adapter Logo

Release Node.js webOS License Tested on LG G4

Full-featured ioBroker adapter for LG WebOS Smart TVs — control picture mode, sound mode, inputs, volume, remote control and more.
Designed as a replacement for homebridge-lgwebos-tv, tested on LG OLED77G4 (webOS 24).


✨ Features

  • 🖼️ Picture Mode — read & write (Vivid, Cinema, Filmmaker, Expert, HDR, Dolby Vision…)
  • 🎚️ Picture Settings — Brightness, Contrast, Backlight / OLED Light, Color, Sharpness
  • 🔊 Sound Mode — read & write (Standard, Cinema, AI Sound Pro…)
  • 🔉 Audio Output — switch between TV Speaker, HDMI ARC/eARC, Optical, Bluetooth Soundbar
  • 📺 Input switching — HDMI 1–4 and all other inputs
  • 📡 TV Channels — switch by number, see channel name and full list
  • 📱 App launcher — launch any webOS app by ID (Netflix, YouTube, Disney+…)
  • 🎮 Full remote control — all physical buttons simulated via ioBroker
  • 💡 Screen off / Screen saver — without powering off the TV
  • ⏯️ Media state — detect playback status
  • 🌐 Wake-on-LAN — turn the TV on remotely
  • 🔢 Numeric states — numeric mirror for every string state (perfect for MQTT / Loxone)
  • 🔔 Real-time push — picture & sound changes on TV are reflected instantly in ioBroker (no polling needed)
  • 🔄 Auto-reconnect — automatic reconnection if TV is turned off or goes to standby

📋 Requirements

Requirement Details
ioBroker js-controller ≥ 3.0
Node.js ≥ 14
LG WebOS TV webOS 4+ (fully tested on webOS 24 / LG G4)
Network TV and ioBroker on the same local network
Static IP Set a DHCP reservation for the TV in your router

🚀 Installation

Via ioBroker Admin (recommended)

  1. Open ioBroker Admin → Adapters
  2. Click the GitHub icon (install from custom URL)
  3. Enter the URL:
    https://github.com/KPIotr89/iobroker.lgtv-full
    
  4. Click Install and wait for completion
  5. Open the instance settings and configure the TV IP address and MAC address

Auto-updates via custom repository

To receive automatic update notifications in ioBroker Admin:

  1. Go to Settings → Repositories
  2. Add a new entry with this URL:
    https://raw.githubusercontent.com/KPIotr89/iobroker.lgtv-full/main/repository.json
    
  3. Enable Auto-Upgrade — ioBroker will notify you (or upgrade automatically) when a new version is published

⚙️ Configuration

Open the adapter instance settings in ioBroker Admin:

Field Example Description
TV IP Address 192.168.1.105 Local IP of the TV — assign a DHCP reservation in your router
MAC Address A1:B2:C3:D4:E5:F6 Required for Wake-on-LAN. Found in TV: Settings → Connection → Network → Advanced
Reconnect interval 10 Seconds between reconnect attempts when TV is off

First connection — Pairing

On the first run, the TV will display a pairing prompt on screen. Accept it with the remote control. The pairing key is saved automatically and pairing is only required once.

Note: If you see a pairing prompt every restart, delete lgtvkey.txt from the instance data directory and let it re-pair once.


📊 States Reference

🔌 Power & Screen

State Type R/W Description
power boolean R/W true = turn on via WoL / false = turn off
screenOff boolean R/W Turn the screen off without standby (panel goes dark, TV stays on)
screenSaver boolean R true when screen saver is active
info.connection boolean R true when adapter is connected to the TV

🔊 Audio

State Type R/W Description
audio.volume number (0–100) R/W Volume level in percent
audio.mute boolean R/W Mute on/off
audio.soundMode string R/W Sound mode key (e.g. cinema, aiSoundPro)
audio.soundModeNum number R/W Sound mode as number — see table below
audio.soundOutput string R/W Audio output key (e.g. tv_speaker, external_arc)
audio.soundOutputNum number R/W Audio output as number — see table below

Sound Modes:

# Key Label
1 standard Standard
2 music Music
3 cinema Cinema
4 sport Sport / Stadium
5 game Game
6 aiSound AI Sound
7 aiSoundPro AI Sound Pro

Sound Outputs:

# Key Label
1 tv_speaker TV Speaker
2 external_arc HDMI ARC / eARC
3 external_optical Optical Out
4 bt_soundbar Bluetooth Soundbar
5 headphone Headphone
6 lineout Line Out
7 tv_external_speaker TV + External Speaker

🖼️ Picture

State Type R/W Description
picture.mode string R/W Picture mode key (e.g. cinema, filmMaker)
picture.modeNum number R/W Picture mode as number — see table below
picture.brightness number (0–100) R/W Brightness
picture.contrast number (0–100) R/W Contrast
picture.backlight number (0–100) R/W Backlight / OLED Light intensity
picture.color number (0–100) R/W Color saturation
picture.sharpness number (0–50) R/W Sharpness
Picture Modes full list (click to expand)
# Key Label
1 vivid Vivid
2 standard Standard
3 eco Eco / APS
4 cinema Cinema
5 sport Sport
6 game Game
7 filmMaker Filmmaker Mode
8 expert1 Expert (Bright Room)
9 expert2 Expert (Dark Room)
10 hdrVivid HDR Vivid
11 hdrStandard HDR Standard
12 hdrCinema HDR Cinema
13 hdrFilmMaker HDR Filmmaker
14 hdrGame HDR Game
15 hdrSport HDR Sport
16 hdrCinemaBright HDR Cinema Home
17 dolbyHdrVivid Dolby Vision Vivid
18 dolbyHdrStandard Dolby Vision Standard
19 dolbyHdrCinema Dolby Vision Cinema
20 dolbyHdrCinemaBright Dolby Vision Cinema Bright
21 dolbyHdrFilmMaker Dolby Vision Filmmaker
22 dolbyHdrGame Dolby Vision Game

ℹ️ HDR and Dolby Vision modes are only available when the TV receives an HDR/DV signal. The TV will ignore the command if the source doesn't match.

📺 Input / Source

State Type R/W Description
input.current string R/W Active input ID — write to switch source
input.list JSON R All available inputs as a JSON object

Input IDs are the webOS app IDs (the exact set depends on your TV / connected devices). Typical HDMI IDs:

Input ID
HDMI 1 com.webos.app.hdmi1
HDMI 2 com.webos.app.hdmi2
HDMI 3 com.webos.app.hdmi3
HDMI 4 com.webos.app.hdmi4
Live TV com.webos.app.livetv

Read input.list for the exact IDs and labels reported by your TV.

📡 TV Channels

State Type R/W Description
channel.number string R/W Current channel number — write to switch
channel.name string R Current channel name
channel.list JSON R Full channel map { "number": "name" }

🔔 Notifications

State Type R/W Description
notify string W Write text to show a native toast on the TV screen (top corner, auto-dismisses ~5 s)

Uses createToast — no popup issue on webOS 24. Publish non-retained (impulse), so an old message doesn't reappear when the TV turns on. Bypasses command deduplication: the same text twice shows two toasts.

📱 Apps

State Type R/W Description
app.current string R Currently running app ID
app.launch string W Write an app ID to launch it

Common app IDs:

App ID
Netflix netflix
YouTube youtube.leanback.v4
Amazon Prime Video amazon
Disney+ disneyplus
Spotify spotify-beehive
Apple TV com.apple.appletv
Web Browser com.webos.app.browser
Live TV com.webos.app.livetv
LG Content Store com.webos.app.lgappstv

🎮 Remote Control

All remote buttons are exposed as writable boolean states under remote.*. Set any button to true to simulate a press — it resets to false automatically.

Category Buttons
Navigation LEFT RIGHT UP DOWN OK
System HOME BACK MENU EXIT INFO GUIDE MYAPPS
Colour RED GREEN YELLOW BLUE
Volume VOLUMEUP VOLUMEDOWN MUTE
Channels CHANNELUP CHANNELDOWN
Media PLAY PAUSE STOP FASTFORWARD REWIND
Numbers 0 1 2 3 4 5 6 7 8 9
Other DASH ENTER CC QMENU ASPECT_RATIO RECENT SEARCH
Streaming NETFLIX AMAZON DISNEY

🔢 Numeric States (for MQTT / Loxone)

Every string state (picture mode, sound mode, sound output) has a numeric mirror state ending in Num. Both are always in sync — write to either one and the other updates automatically.

This makes integration with systems that prefer numbers (MQTT, Loxone, KNX) straightforward:

picture.mode    = "cinema"   ←→   picture.modeNum    = 4
audio.soundMode = "aiSound"  ←→   audio.soundModeNum = 6
audio.soundOutput = "external_arc" ←→ audio.soundOutputNum = 2

🔗 Built-in MQTT Client

Since v1.2.0 the adapter includes a built-in MQTT client — no separate ioBroker MQTT adapter needed.

Configuration

Open the adapter instance settings and fill in the MQTT Integration section:

Field Default Description
Enable MQTT client off Toggle to activate
Broker Host IP or hostname of your MQTT broker (e.g. 192.168.1.10)
Broker Port 1883 Standard MQTT port
Topic prefix lgtv Base topic for all messages
Username Optional broker authentication
Password Optional broker authentication

All MQTT fields are hidden when the client is disabled.

Topic structure

Direction Topic pattern Example
TV → broker (publish) {prefix}/state/{name} lgtv/state/picture/modecinema
Broker → TV (subscribe) {prefix}/set/{name} lgtv/set/picture/modefilmMaker

All published values use / as separator and are retained on the broker, so a newly connected client always gets the current state immediately.

Example topics

lgtv/state/info/connection       → true / false
lgtv/state/audio/volume          → 45
lgtv/state/audio/soundMode       → cinema
lgtv/state/audio/soundModeNum    → 3
lgtv/state/picture/mode          → filmMaker
lgtv/state/picture/modeNum       → 7
lgtv/state/picture/backlight     → 30
lgtv/state/input/current         → com.webos.app.hdmi3

lgtv/set/audio/volume            ← 50
lgtv/set/picture/mode            ← cinema
lgtv/set/picture/modeNum         ← 4
lgtv/set/picture/backlight       ← 60
lgtv/set/audio/soundMode         ← aiSoundPro
lgtv/set/input/current           ← com.webos.app.hdmi3
lgtv/set/power                   ← true / false
lgtv/set/notify                  ← Someone at the gate 🔔

notify shows a native webOS toast in the corner of the screen (auto-dismisses after ~5 s). It bypasses command deduplication — publishing the same text twice shows two toasts. Publish non-retained so old notifications don't pop up when the TV turns on.

Loxone / LoxBerry integration

Point the adapter to your Mosquitto broker running on LoxBerry. In Loxone Config, create Virtual Inputs and Virtual Outputs mapped to the topics above — no scripting required.

For systems that prefer numbers, use the Num variants:

picture.modeNum    1–22   (see picture modes table)
audio.soundModeNum 1–7
audio.soundOutputNum 1–7

🛠️ Troubleshooting

TV does not respond to Wake-on-LAN
  • Verify the MAC address in TV: Settings → Connection → Network → Wi-Fi / Wired → View Details
  • Enable "Turn on via Wi-Fi" in TV: Settings → General → External Devices → Quick Start+
  • The TV must be in standby (not fully unplugged) for WoL to work
Pairing prompt appears on every restart

The pairing key file was not saved correctly. Check that the adapter has write access to its data directory. If the file exists but is empty, delete it and restart:

rm /opt/iobroker/iobroker-data/lgtv-full.0/lgtvkey.txt

Then restart the adapter and accept the pairing prompt on the TV.

401 insufficient permissions on writes

This means the adapter was paired with an older manifest that didn't include WRITE_SETTINGS. To fix:

  1. Stop the adapter
  2. Delete the key file: rm /opt/iobroker/iobroker-data/lgtv-full.0/lgtvkey.txt
  3. Start the adapter
  4. Accept the pairing prompt on the TV
"Unknown message OK" popup appears when changing picture / sound mode (webOS 24)

This popup was shown by webOS 24 (LG G4 and newer) when an external app called ssap://settings/setSystemSettings directly. The adapter uses a different approach since v1.2.20: it triggers settings via a Luna service callback inside createAlert, bypassing the popup entirely. If you still see the popup, make sure you are running v1.2.29 or later. Check the debug log for createAlert cb: alertId= — if you see alertId=none the createAlert call failed and the adapter fell back to direct SSAP.

Picture mode does not change (HDR / Dolby Vision modes)

HDR and Dolby Vision picture modes are only available when the TV receives a compatible signal (e.g. HDR10 or Dolby Vision content from HDMI). The TV will silently ignore the command if the current source doesn't support that mode. This is a TV firmware limitation, not an adapter issue.

Some states show null / not updating

Check the debug logs in ioBroker Admin (set log level to debug). Common causes:

  • TV is in standby — states will update after the TV wakes up
  • Subscription failed — the adapter will fall back to polling every 60 seconds
  • Incorrect setting keys for your TV firmware — post an issue with your debug log

📝 Changelog

1.2.48

  • Fix: power stayed at 1 with the screen off — with Quick Start+ the SSAP socket stays alive in standby, so a socket close never happened and power was never reported as off
  • Now subscribes to ssap://com.webos.service.tvpower/power/getPowerState and maps the real state: Active / Screen Saver / Screen Off → on, Active Standby / Suspend / Power Off → off
  • Updates power instantly (pushed by the TV) — much faster than waiting for the socket to drop; same approach as homebridge-lgwebos-tv
  • Falls back to socket-based detection if the endpoint errors on older webOS

1.2.47

  • Fix: Input switching never worked — ssap://tv/switchInput expects the device id (e.g. HDMI_3) but the adapter passed the appId (com.webos.app.hdmi3), so the TV ignored it
  • Additionally, the optimistic cache write then made every later input command be skipped as a duplicate
  • Now switches by launching the input as an app (system.launcher/launch), with a switchInput fallback using the resolved device id
  • input.current is synced from the TV's foreground app, so the dedup cache tracks the real source (and reflects manual input changes via remote)
  • Reminder: the correct MQTT topic is lgtv/set/input/current (not lgtv/set/input)

1.2.46

  • Fix: Picture-mode dictionary had a non-existent key hdrCinemaHome — the real webOS key is hdrCinemaBright (verified). The TV reporting hdrCinemaBright left modeNum stale and writing that mode was rejected by validation
  • Replaced the key at the same position (nr 16) — existing numeric mappings unchanged
  • modeNum now falls back to 0 for any unrecognised mode instead of keeping a stale value

1.2.45

  • Fix: A weekend webOS system-app update (TV sw 33.31.68) changed alert timing — the single closeAlert at 20 ms fired before the alert was registered and was ignored, leaving an empty "OK" dialog on screen that stacked with every verify-retry
  • closeAlert now fires repeatedly (40 / 150 / 400 / 900 ms) across the registration window
  • The previous alert is pre-closed before any retry, so dialogs can no longer stack
  • Note: webOS system apps update independently of firmware, often on weekends — this class of regression recurs; see the technical notes

1.2.44

  • Improvement: Faster connection pickup — fast-retry window polls every 3 s (was 5 s), regular backoff cap lowered to 15 s (was 30 s)
  • Recommended companion: publish lgtv/set/power = true from your home automation when it detects the TV turning on — the adapter opens the fast-retry window immediately

1.2.43

  • Fix: With Loxone gating its commands on info.connection, nothing external kicks the adapter anymore — a TV powered on after deep sleep waited up to 5 min for the next backoff slot
  • Backoff cap lowered from 300 s to 30 s (attempts are silent, so no log spam)
  • A dropped established link opens a 2-minute window of 5 s polling — a TV switching state (standby wake) is caught within seconds

1.2.42

  • Fix: A command-forced reconnect that hit a still-booting TV failed once and fell back to the backoff slot (up to 5 min), letting the queued scene expire — forced reconnects now open the 60 s fast-retry window (5 s polling), same as WoL
  • Queued command max age raised from 120 s to 180 s
  • Unknown picture.mode / audio.soundMode values are rejected with a warning before reaching the TV or the offline queue

1.2.41

  • Fix: Reconnect loop could die permanently when a connect attempt got a socket that never fired open/close — the stuck connecting flag blocked all future attempts
  • 15 s watchdog per connect attempt: force-clean and reschedule if neither event fires
  • Forced reconnects override attempts stuck longer than 15 s
  • disconnect() now also calls terminate()close() is a no-op on sockets stuck in CONNECTING

1.2.40

  • Fix: States set before the MQTT client finished connecting (typically info.connection when the TV link came up first) were silently dropped and never re-published
  • All cached states are re-published on every MQTT (re)connect

1.2.39

  • Fix: Commands arriving milliseconds before the reconnect completed were lost forever (one-shot Loxone scenes fired shortly after TV-on detection)
  • Commands received while disconnected are queued (latest value per key, max age 2 min) and replayed 2 s after connecting through the normal dedup + verify path
  • Dedup caches are cleared on disconnect — stale values from the previous session no longer swallow commands while the TV is off
  • notify and remote.* are never replayed late (time-sensitive)

1.2.38

  • Fix: After a cold boot (night in deep standby) webOS silently drops or overrides early settings writes — the TV would ignore the morning scene until power-cycled
  • Picture/sound writes are now verified against TV push confirmations and invisibly re-sent (up to 4 attempts at 2/4/8/15 s) within 2 minutes of connecting
  • New _confirmed store tracks only TV-reported values (optimistic writes no longer mask verification)

1.2.37

  • Fix: Incoming command while disconnected forces an immediate reconnect — a TV turned on in the morning connects within seconds instead of waiting for the next backoff slot (up to 5 min)
  • WoL opens a 60 s fast-retry window (polling every 5 s) while the TV boots
  • Ignored commands are removed from the 55 s throttle, so a re-send applies right after reconnecting
  • Stale socket handlers are detached before a new connection — prevents duplicate reconnect loops

1.2.36

  • Feature: New notify state — native toast notification on the TV screen (ssap://system.notifications/createToast)
  • Writable over MQTT at lgtv/set/notify — e.g. from Loxone: doorbell, alarms, appliances
  • Bypasses command deduplication so repeated identical messages always display

1.2.30 – 1.2.35

  • Two-layer command deduplication (TV state cache + 55 s throttle) against MQTT spam
  • closeAlert at 20 ms confirmed required on webOS 24 (isSysReq+timeout:0 alone insufficient)
  • Exponential backoff reconnect (10 s → 300 s) — no log spam while the TV is off

1.2.29

  • Fix: Critical bug in v1.2.28 — createAlert rejected by webOS 24 with "Message can't be empty" when title/message were empty strings; restored single-space values
  • Fix: Removed all ssap://input/sendButton calls (404 on webOS 24)
  • Simplified pointer socket: silent no-op on webOS 24 (404), works on older webOS as before
  • Added fallback: if createAlert fails for any reason, falls back to direct ssap://settings/setSystemSettings

1.2.28

  • Add CONTROL_MOUSE_AND_KEYBOARD and CONTROL_INPUT_TEXT to unsigned permissions
  • Improved pointer socket diagnostics: log actual error message instead of {}
  • _setWithAlert: added isSysReq: true + modal: false — system-level alert auto-dismisses on webOS 24
  • (contained the empty title/message regression — superseded by 1.2.29)

1.2.27

  • Added diagnostic logging for pointer socket failures (revealed 404 on webOS 24)
  • _setWithAlert: multiple ENTER retries inside createAlert callback

1.2.26

  • _setWithAlert: fallback from ENTER to BACK when modal is active

1.2.25

  • Fix: move setTimeout(pressEnter) inside createAlert callback — it was firing before TV responded

1.2.20 – 1.2.24

  • Pointer socket text-frame format (type:button\nname:ENTER\n\n)
  • Various timing and dismiss attempts for webOS 24 alert dialog

1.2.0

  • Feature: Built-in MQTT client — configure broker host, port, credentials and topic prefix directly in adapter settings
  • All states published automatically to {prefix}/state/{name} with retain: true
  • Commands received on {prefix}/set/{name} — supports strings, numbers and booleans
  • No separate ioBroker MQTT adapter required

1.1.6

  • Fix: Use the real LG-signed RSA manifest from lgtv2 — TV now validates the signature and grants WRITE_SETTINGS, enabling write operations for picture and sound settings via SSAP

1.1.5

  • Experimental: Luna notification trick for settings writes (superseded by 1.1.6)

1.1.4

  • Add WRITE_SETTINGS to unsigned permissions array

1.1.3

  • Add CONTROL_DISPLAY to signed manifest permissions

1.1.2

  • Fix: acknowledge all state changes (no more red values in ioBroker)
  • Fix: sync numeric and string states on write

1.1.1

  • Add numeric mirror states for picture mode, sound mode and sound output (for MQTT / Loxone)

1.1.0

  • Full English translation of all code, comments, logs and object names
  • Push subscriptions for picture and sound settings (instant updates)
  • Polling fallback every 60 seconds

1.0.0

  • Initial release: WebSocket/SSAP on port 3001 (TLS), custom LgTvSocket class, no lgtv2 dependency
  • Picture Mode, Sound Mode, volume, mute, inputs, channels, remote control, Wake-on-LAN

📄 License

MIT — © 2024 KPIotr89


Made with ❤️ for ioBroker and LG OLED owners
Tested on LG OLED77G4 · webOS 24 · js-controller 7.0

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors