From 540fb991b1b29c253a210faae6e885a0b0ddb6b2 Mon Sep 17 00:00:00 2001 From: Rudolf Offereins Date: Tue, 3 Feb 2026 20:21:01 +0000 Subject: [PATCH] Export country settings --- lghorizon/__init__.py | 3 + lghorizon/const.py | 89 ++++-------------------------- lghorizon/lghorizon_mqtt_client.py | 16 +++--- 3 files changed, 23 insertions(+), 85 deletions(-) diff --git a/lghorizon/__init__.py b/lghorizon/__init__.py index 1156804..a6753d0 100644 --- a/lghorizon/__init__.py +++ b/lghorizon/__init__.py @@ -35,6 +35,8 @@ LGHorizonApiLockedError, ) +from .const import COUNTRY_SETTINGS + __all__ = [ "LGHorizonApi", "LGHorizonDevice", @@ -68,4 +70,5 @@ "LGHorizonServicesConfig", "LGHorizonRecording", "LGHorizonShowRecordingList", + "COUNTRY_SETTINGS", ] diff --git a/lghorizon/const.py b/lghorizon/const.py index 94caa71..086f50a 100644 --- a/lghorizon/const.py +++ b/lghorizon/const.py @@ -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)", }, } diff --git a/lghorizon/lghorizon_mqtt_client.py b/lghorizon/lghorizon_mqtt_client.py index 1d8e695..7b31260 100644 --- a/lghorizon/lghorizon_mqtt_client.py +++ b/lghorizon/lghorizon_mqtt_client.py @@ -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, @@ -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: @@ -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 @@ -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() @@ -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()) @@ -256,7 +256,7 @@ 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 @@ -264,7 +264,7 @@ def _on_disconnect(self, client, userdata, result_code): 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.""" @@ -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.