Skip to content

Commit

Permalink
Profile upate (#140)
Browse files Browse the repository at this point in the history
* ⬆️ Update channels list on profile update

* Fix no data when channel not in favorites
  • Loading branch information
Sholofly authored Oct 26, 2024
1 parent 574f245 commit 9b5a690
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 69 deletions.
13 changes: 8 additions & 5 deletions custom_components/lghorizon/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""The lghorizon integration."""

from __future__ import annotations

from homeassistant.config_entries import ConfigEntry
Expand All @@ -13,7 +14,8 @@
CONF_REFRESH_TOKEN,
API,
COUNTRY_CODES,
CONF_IDENTIFIER
CONF_IDENTIFIER,
CONF_PROFILE_ID,
)

from lghorizon import LGHorizonApi
Expand All @@ -28,8 +30,8 @@
vol.Optional(CONF_COUNTRY_CODE, default="nl"): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_IDENTIFIER):cv.string,
vol.Optional(CONF_REFRESH_TOKEN):cv.string
vol.Optional(CONF_IDENTIFIER): cv.string,
vol.Optional(CONF_REFRESH_TOKEN): cv.string,
}
)
},
Expand All @@ -45,14 +47,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

refresh_token = None
if CONF_REFRESH_TOKEN in entry.data:
refresh_token = entry.data[CONF_REFRESH_TOKEN]
refresh_token = entry.data[CONF_REFRESH_TOKEN]

api = LGHorizonApi(
entry.data[CONF_USERNAME],
entry.data[CONF_PASSWORD],
COUNTRY_CODES[entry.data[CONF_COUNTRY_CODE]],
telenet_identifier,
refresh_token,
profile_id=entry.data[CONF_PROFILE_ID],
)
await hass.async_add_executor_job(api.connect)
hass.data.setdefault(DOMAIN, {})
Expand Down
161 changes: 110 additions & 51 deletions custom_components/lghorizon/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Config flow for arrisdcx960 integration."""

from __future__ import annotations

import logging
Expand All @@ -11,98 +12,156 @@
from homeassistant.data_entry_flow import FlowResult
from homeassistant.exceptions import HomeAssistantError
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
from homeassistant.helpers.selector import (
SelectSelectorMode,
SelectOptionDict,
SelectSelector,
SelectSelectorConfig,
)

import homeassistant.helpers.config_validation as cv

from .const import DOMAIN, CONF_COUNTRY_CODE, CONF_REFRESH_TOKEN, COUNTRY_CODES, CONF_IDENTIFIER

from lghorizon import (
LGHorizonApi,
LGHorizonApiUnauthorizedError,
LGHorizonApiConnectionError,
LGHorizonApiLockedError,
LGHorizonCustomer,
)

_LOGGER = logging.getLogger(__name__)

STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_COUNTRY_CODE, default=list(COUNTRY_CODES.keys())[0]): vol.In(
list(COUNTRY_CODES.keys())
),
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_IDENTIFIER):cv.string,
vol.Optional(CONF_REFRESH_TOKEN):cv.string
}
from .const import (
DOMAIN,
CONF_COUNTRY_CODE,
CONF_REFRESH_TOKEN,
COUNTRY_CODES,
CONF_IDENTIFIER,
CONF_PROFILE_ID,
)


async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]:
"""Validate the user input allows us to connect."""
_LOGGER = logging.getLogger(__name__)

try:
telenet_identifier = None
if CONF_IDENTIFIER in data:
telenet_identifier = data[CONF_IDENTIFIER]

refresh_token = None
if CONF_REFRESH_TOKEN in data:
refresh_token = data[CONF_REFRESH_TOKEN]
class CannotConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""

api = LGHorizonApi(
data[CONF_USERNAME],
data[CONF_PASSWORD],
COUNTRY_CODES[data[CONF_COUNTRY_CODE]],
telenet_identifier,
refresh_token,
)
await hass.async_add_executor_job(api.connect)
await hass.async_add_executor_job(api.disconnect)
except LGHorizonApiUnauthorizedError:
raise InvalidAuth
except LGHorizonApiConnectionError:
raise CannotConnect
except Exception as ex:
_LOGGER.error(ex)
raise CannotConnect

return {"title": data[CONF_USERNAME]}
class InvalidAuth(HomeAssistantError):
"""Error to indicate there is invalid auth."""


class AccountLocked(HomeAssistantError):
"""Error to indicate account is locked."""


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for lghorizon."""

VERSION = 1
CONFIG_DATA: dict[str, Any] = {}
customer: LGHorizonCustomer = None

async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""

user_schema = vol.Schema(
{
vol.Required(
CONF_COUNTRY_CODE, default=list(COUNTRY_CODES.keys())[0]
): vol.In(list(COUNTRY_CODES.keys())),
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_IDENTIFIER): cv.string,
vol.Optional(CONF_REFRESH_TOKEN): cv.string,
}
)

if user_input is None:
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA
)
return self.async_show_form(step_id="user", data_schema=user_schema)

errors = {}

try:
info = await validate_input(self.hass, user_input)
await self.validate_input(self.hass, user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except InvalidAuth:
errors["base"] = "invalid_auth"
except AccountLocked:
errors["base"] = "account_locked"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
return self.async_create_entry(title=info["title"], data=user_input)
self.CONFIG_DATA.update(user_input)
profile_step = await self.async_step_profile(user_input=user_input)
return profile_step

return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
return await self.async_show_form(
step_id="user", data_schema=user_schema, errors=errors
)

async def validate_input(self, hass: HomeAssistant, data: dict[str, Any]):
"""Validate the user input allows us to connect."""

class CannotConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""

try:
telenet_identifier = None
if CONF_IDENTIFIER in data:
telenet_identifier = data[CONF_IDENTIFIER]

refresh_token = None
if CONF_REFRESH_TOKEN in data:
refresh_token = data[CONF_REFRESH_TOKEN]

api = LGHorizonApi(
data[CONF_USERNAME],
data[CONF_PASSWORD],
COUNTRY_CODES[data[CONF_COUNTRY_CODE]],
telenet_identifier,
refresh_token,
)
await hass.async_add_executor_job(api.connect)
# store customer for profile extraction
self.customer = api.customer
await hass.async_add_executor_job(api.disconnect)
except LGHorizonApiUnauthorizedError:
raise InvalidAuth
except LGHorizonApiConnectionError:
raise CannotConnect
except LGHorizonApiLockedError:
raise AccountLocked
except Exception as ex:
_LOGGER.error(ex)
raise CannotConnect

async def async_step_profile(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
profile_selectors = []
for profile in self.customer.profiles.values():
profile_selectors.append(
SelectOptionDict(value=profile.profile_id, label=profile.name),
)
profile_schema = vol.Schema(
{
vol.Required(CONF_PROFILE_ID): SelectSelector(
SelectSelectorConfig(
options=profile_selectors, mode=SelectSelectorMode.DROPDOWN
),
),
}
)

class InvalidAuth(HomeAssistantError):
"""Error to indicate there is invalid auth."""
if (
user_input is None
or CONF_PROFILE_ID not in user_input
or not user_input[CONF_PROFILE_ID]
):
return self.async_show_form(step_id="profile", data_schema=profile_schema)
self.CONFIG_DATA.update(user_input)
return self.async_create_entry(
title=self.CONFIG_DATA[CONF_USERNAME], data=self.CONFIG_DATA
)
2 changes: 2 additions & 0 deletions custom_components/lghorizon/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
CONF_REFRESH_TOKEN = "refresh_token"
CONF_REMOTE_KEY = "remote_key"
CONF_IDENTIFIER = "identifier"
CONF_PROFILE_ID = "profile_id"


RECORD = "record"
REWIND = "rewind"
Expand Down
4 changes: 2 additions & 2 deletions custom_components/lghorizon/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"iot_class": "cloud_push",
"issue_tracker": "https://github.com/Sholofly/lghorizon/issues",
"requirements": [
"lghorizon>=0.7.2"
"lghorizon>=0.7.4"
],
"version": "0.6.3"
"version": "0.6.4"
}
23 changes: 12 additions & 11 deletions custom_components/lghorizon/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,20 +123,20 @@ def device_info(self):
"model": self._box.model or "unknown",
}

def __init__(self, box: LGHorizonBox, api: LGHorizonApi, hass: HomeAssistant, entry: ConfigEntry):
def __init__(
self,
box: LGHorizonBox,
api: LGHorizonApi,
hass: HomeAssistant,
entry: ConfigEntry,
):
"""Init the media player."""
self._box = box
self.api = api
self.hass = hass
self.entry = entry
self.box_id = box.deviceId
self.box_name = box.deviceFriendlyName
self._create_channel_map()

def _create_channel_map(self):
self._channels = {}
for channel in self.api._channels.values():
self._channels[channel.title] = channel.title

async def async_added_to_hass(self):
"""Use lifecycle hooks."""
Expand All @@ -157,9 +157,7 @@ def _save_refresh_token(self):
_LOGGER.info("New JWT stored (2): %s", self.api.refresh_token)
new_data = {**self.entry.data}
new_data[CONF_REFRESH_TOKEN] = self.api.refresh_token
self.hass.config_entries.async_update_entry(
self.entry, data=new_data
)
self.hass.config_entries.async_update_entry(self.entry, data=new_data)

async def async_update(self):
"""Update the box."""
Expand Down Expand Up @@ -256,7 +254,10 @@ def source(self):
@property
def source_list(self):
"""Return a list with available sources."""
return [channel for channel in self._channels.keys()]
channel_list = []
for channel in self.api.get_display_channels():
channel_list.append(channel.title)
return channel_list

@property
def media_duration(self) -> int | None:
Expand Down
8 changes: 8 additions & 0 deletions custom_components/lghorizon/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@
"identifier": "DTV identifier",
"refresh_token": "Refresh Token (GB)"
}
},
"profile": {
"title": "LG Horizon - Select profile",
"description":"Select your profile to show it's favorite channels only",
"data": {
"profile_id": "Profile"
}
}
},
"error": {
"cannot_connect": "Can't connect",
"invalid_auth": "Invalid credentials",
"account_locked": "Your account is locked. Please wait 10 minutes and try again.",
"unknown": "Unknown error"
},
"abort": {
Expand Down
8 changes: 8 additions & 0 deletions custom_components/lghorizon/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@
"identifier": "DTV identifier",
"refresh_token": "Refresh Token (GB)"
}
},
"profile": {
"title": "LG Horizon - Selecteer profiel",
"description":"Selecteer het profiel waarvan je de favoriete kanalen wilt tonen",
"data": {
"profile_id": "Profiel"
}
}
},
"error": {
"cannot_connect": "Kan niet verbinden",
"invalid_auth": "Ongeldige logingegevens",
"account_locked": "Je account is geblokkeerd. Wacht 10 minuten voor je het weer probeert.",
"unknown": "Onbekende fout"
},
"abort": {
Expand Down

0 comments on commit 9b5a690

Please sign in to comment.