Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lghorizon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
LGHorizonApiLockedError,
)

from .const import COUNTRY_SETTINGS

__all__ = [
"LGHorizonApi",
"LGHorizonDevice",
Expand Down Expand Up @@ -68,4 +70,5 @@
"LGHorizonServicesConfig",
"LGHorizonRecording",
"LGHorizonShowRecordingList",
"COUNTRY_SETTINGS",
]
89 changes: 12 additions & 77 deletions lghorizon/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,106 +50,41 @@
"api_url": "https://spark-prod-nl.gnp.cloud.ziggogo.tv",
"mqtt_url": "obomsg.prod.nl.horizon.tv",
"use_refreshtoken": False,
"channels": [
{
"channelId": "NL_000073_019506",
"channelName": "Netflix",
"channelNumber": "150",
},
{
"channelId": "NL_000074_019507",
"channelName": "Videoland",
"channelNumber": "151",
},
{
"channelId": "NL_000194_019352",
"channelName": "NPO",
"channelNumber": "152",
},
{
"channelId": "NL_000199_019356",
"channelName": "Prime Video",
"channelNumber": "153",
},
],
"platform_types": {
"EOS": {"manufacturer": "Arris", "model": "DCX960"},
"APOLLO": {"manufacturer": "Arris", "model": "VIP5002W"},
},
"language": "nl",
"name": "Ziggo",
},
"ch": {
"api_url": "https://spark-prod-ch.gnp.cloud.sunrisetv.ch",
"channels": [],
"language": "de",
"use_refreshtoken": True,
"name": "UPC Switzerland",
},
"be-basetv": {
"api_url": "https://spark-prod-be.gnp.cloud.base.tv",
"channels": [],
"language": "nl",
"platform_types": {
"EOS": {"manufacturer": "Arris", "model": "DCX960"},
"HORIZON": {"manufacturer": "Arris", "model": "VIP5002W"},
},
"use_refreshtoken": True,
"name": "BASE TV (BE)",
},
"be-nl": {
"api_url": "https://spark-prod-be.gnp.cloud.telenet.tv",
"oauth_username_fieldname": "j_username",
"oauth_password_fieldname": "j_password",
"oauth_add_accept_header": False,
"oauth_url": "https://login.prd.telenet.be/openid/login.do",
"oauth_quote_login": False,
"oauth_redirect_header": "Location",
"channels": [
{"channelId": "netflix", "channelName": "Netflix", "channelNumber": "600"},
{"channelId": "youtube", "channelName": "Youtube", "channelNumber": "-1"},
],
"platform_types": {
"EOS": {"manufacturer": "Arris", "model": "DCX960"},
"HORIZON": {"manufacturer": "Arris", "model": "DCX960"},
"EOS2": {"manufacturer": "HUMAX", "model": "2008C-STB-TN"},
},
"language": "nl",
"use_refreshtoken": True,
"name": "Telenet (BE)",
},
"be-nl-preprod": {
"api_url": "https://spark-preprod-be.gnp.cloud.telenet.tv",
"use_refreshtoken": True,
"oauth_username_fieldname": "j_username",
"oauth_password_fieldname": "j_password",
"oauth_add_accept_header": False,
"oauth_url": "https://login.prd.telenet.be/openid/login.do",
"oauth_quote_login": False,
"oauth_redirect_header": "Location",
"channels": [
{"channelId": "netflix", "channelName": "Netflix", "channelNumber": "600"},
{"channelId": "youtube", "channelName": "Youtube", "channelNumber": "-1"},
],
"platform_types": {
"EOS": {"manufacturer": "Arris", "model": "DCX960"},
"HORIZON": {"manufacturer": "Arris", "model": "DCX960"},
"EOS2": {"manufacturer": "HUMAX", "model": "2008C-STB-TN"},
},
"language": "nl",
"name": "Telenet (BE, PREPROD)",
},
"gb": {
"api_url": "https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com",
"channels": [],
"language": "en",
"use_refreshtoken": True,
"name": "Virgin Media (GB)",
},
"ie": {
"api_url": "https://spark-prod-ie.gnp.cloud.virginmediatv.ie",
"use_refreshtoken": False,
"channels": [],
"language": "en",
"name": "Virgin Media (IE)",
},
"pl": {
"api_url": "https://spark-prod-pl.gnp.cloud.upctv.pl",
"use_refreshtoken": False,
"channels": [],
"language": "pl",
"platform_types": {
"EOS": {"manufacturer": "Arris", "model": "DCX960"},
"APOLLO": {"manufacturer": "Arris", "model": "VIP5002W"},
},
"name": "UPC (PL)",
},
}
16 changes: 8 additions & 8 deletions lghorizon/lghorizon_mqtt_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ async def connect(self) -> None:
self._reconnect_task.cancel()
self._reconnect_task = None

_logger.info("Attempting initial MQTT connection...")
_logger.debug("Attempting initial MQTT connection...")
# Blocking connect → executor
await self._loop.run_in_executor(
None,
Expand Down Expand Up @@ -185,7 +185,7 @@ def _on_connect(self, client, userdata, flags, result_code):
result_code: The connection result code.
"""
if result_code == 0:
_logger.info("MQTT client connected successfully.")
_logger.debug("MQTT client connected successfully.")
# If a reconnect task was running, it means we successfully reconnected.
# Cancel it as we are now connected.
if self._reconnect_task:
Expand All @@ -196,7 +196,7 @@ def _on_connect(self, client, userdata, flags, result_code):
self._loop,
)
elif result_code == 5:
_logger.warning(
_logger.debug(
"MQTT connection failed: Token expired. Attempting to refresh token and reconnect."
)
# Schedule the token refresh and reconnect in the main event loop
Expand All @@ -217,7 +217,7 @@ async def _handle_token_refresh_and_reconnect(self):
self._auth.household_id,
self._mqtt_token,
)
_logger.info("MQTT token refreshed. Attempting to reconnect.")
_logger.debug("MQTT token refreshed. Attempting to reconnect.")
# Call connect. If it fails, _on_disconnect will be triggered,
# and the _reconnect_loop will take over.
await self.connect()
Expand All @@ -228,7 +228,7 @@ async def _handle_token_refresh_and_reconnect(self):
if not self._disconnect_requested and (
not self._reconnect_task or self._reconnect_task.done()
):
_logger.info(
_logger.debug(
"Scheduling MQTT reconnect after token refresh/connect failure."
)
self._reconnect_task = asyncio.create_task(self._reconnect_loop())
Expand Down Expand Up @@ -256,15 +256,15 @@ def _on_disconnect(self, client, userdata, result_code):
"""
_logger.warning("MQTT disconnected with result code: %s", result_code)
if not self._disconnect_requested:
_logger.info("Unexpected MQTT disconnection. Initiating reconnect loop.")
_logger.debug("Unexpected MQTT disconnection. Initiating reconnect loop.")
if not self._reconnect_task or self._reconnect_task.done():
self._reconnect_task = asyncio.run_coroutine_threadsafe(
self._reconnect_loop(), self._loop
)
else:
_logger.debug("Reconnect loop already active.")
else:
_logger.info("MQTT disconnected as requested.")
_logger.debug("MQTT disconnected as requested.")

async def _reconnect_loop(self):
"""Manages the MQTT reconnection process with exponential backoff."""
Expand All @@ -285,7 +285,7 @@ async def _reconnect_loop(self):
await asyncio.sleep(delay)

try:
_logger.info("Attempting MQTT reconnect...")
_logger.debug("Attempting MQTT reconnect...")
await self.connect()
# If connect() succeeds, _on_connect will be called, which will cancel this task.
# If connect() fails, _on_disconnect will be called again, and this loop continues.
Expand Down