A Python library to interact with and control LG Horizon set-top boxes. This library provides functionalities for authentication, real-time device status monitoring via MQTT, and various control commands for your Horizon devices.
- Authentication: Supports authentication using username/password or a refresh token. The library automatically handles access token refreshing.
- Device Management: Discover and manage multiple LG Horizon set-top boxes associated with your account.
- Real-time Status: Monitor device status (online/running/standby) and current playback information (channel, show, VOD, recording, app) through MQTT.
- Channel Information: Retrieve a list of available channels and profile-specific favorite channels.
- Recording Management:
- Get a list of all recordings.
- Retrieve recordings for specific shows.
- Check recording quota and usage.
- Device Control: Send various commands to your set-top box:
- Power on/off.
- Play, pause, stop, rewind, fast forward.
- Change channels (up/down, direct channel selection).
- Record current program.
- Set player position for VOD/recordings.
- Display custom messages on the TV screen.
- Send emulated remote control key presses.
- Robustness: Includes automatic MQTT reconnection with exponential backoff and token refresh logic to maintain a stable connection.
pip install lghorizon-python # (Replace with actual package name if different)Here's a basic example of how to use the library to connect to your LG Horizon devices and monitor their state:
First, create a secrets.json file in the root of your project with your LG Horizon credentials:
{
"username": "your_username",
"password": "your_password",
"country": "nl" // e.g., "nl" for Netherlands, "be" for Belgium
}Then, you can use the library as follows:
import asyncio
import json
import logging
import aiohttp
from lghorizon.lghorizon_api import LGHorizonApi
from lghorizon.lghorizon_models import LGHorizonAuth
_LOGGER = logging.getLogger(__name__)
async def main():
logging.basicConfig(level=logging.INFO) # Set to DEBUG for more verbose output
with open("secrets.json", encoding="utf-8") as f:
secrets = json.load(f)
username = secrets.get("username")
password = secrets.get("password")
country = secrets.get("country", "nl")
async with aiohttp.ClientSession() as session:
auth = LGHorizonAuth(session, country, username=username, password=password)
api = LGHorizonApi(auth)
async def device_state_changed_callback(device_id: str):
device = devices[device_id]
_LOGGER.info(
f"Device {device.device_friendly_name} ({device.device_id}) state changed:\n"
f" State: {device.device_state.state.value}\n"
f" UI State: {device.device_state.ui_state_type.value}\n"
f" Source Type: {device.device_state.source_type.value}\n"
f" Channel: {device.device_state.channel_name or 'N/A'} ({device.device_state.channel_id or 'N/A'})\n"
f" Show: {device.device_state.show_title or 'N/A'}\n"
f" Episode: {device.device_state.episode_title or 'N/A'}\n"
f" Position: {device.device_state.position or 'N/A'} / {device.device_state.duration or 'N/A'}\n"
)
try:
_LOGGER.info("Initializing LG Horizon API...")
await api.initialize()
devices = await api.get_devices()
for device in devices.values():
_LOGGER.info(f"Registering callback for device: {device.device_friendly_name}")
await device.set_callback(device_state_changed_callback)
_LOGGER.info("API initialized. Monitoring device states. Press Ctrl+C to exit.")
# Keep the script running to receive MQTT updates
while True:
await asyncio.sleep(3600) # Sleep for a long time, MQTT callbacks will still fire
except Exception as e:
_LOGGER.error(f"An error occurred: {e}", exc_info=True)
finally:
_LOGGER.info("Disconnecting from LG Horizon API.")
await api.disconnect()
_LOGGER.info("Disconnected.")
if __name__ == "__main__":
asyncio.run(main())The LGHorizonAuth class handles authentication. You can initialize it with a username and password, or directly with a refresh token if you have one. The library automatically refreshes access tokens as needed.
# Using username and password
auth = LGHorizonAuth(session, "nl", username="your_username", password="your_password")
# Using a refresh token (e.g., if you've saved it from a previous session)
# auth = LGHorizonAuth(session, "nl", refresh_token="your_refresh_token")You can also set a callback to receive the updated refresh token when it's refreshed, allowing you to persist it for future sessions:
def token_updated_callback(new_refresh_token: str):
print(f"New refresh token received: {new_refresh_token}")
# Here you would typically save this new_refresh_token
# to your secrets.json or other persistent storage.
# After initializing LGHorizonApi:
# api.set_token_refresh_callback(token_updated_callback)The library defines custom exceptions for common error scenarios:
LGHorizonApiError: Base exception for all API-related errors.LGHorizonApiConnectionError: Raised for network or connection issues.LGHorizonApiUnauthorizedError: Raised when authentication fails (e.g., invalid credentials).LGHorizonApiLockedError: A specific type ofLGHorizonApiUnauthorizedErrorindicating a locked account.
These exceptions allow for more granular error handling in your application.
To run the example script (main.py) from the repository:
- Clone this repository.
- Install dependencies:
pip install -r requirements.txt(ensurerequirements.txtis up-to-date). - Create a
secrets.jsonfile as described in the Usage section. - Run
python main.py.