Use HA `uuid` as `client_id` in BraviaTV (#79618)

* Use uuid as clientid/nickname

* Fixes after rebase

* Move gen_instance_ids() to utils

* Store client_id and nickname in config_entry

* Update tests

* Clean names

* Rename consts
This commit is contained in:
Maciej Bieniek 2022-10-05 08:24:52 +00:00 committed by GitHub
parent 33bdc67a61
commit 9dd9147343
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 20 deletions

View File

@ -7,11 +7,11 @@ from aiohttp import CookieJar
from pybravia import BraviaTV
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PIN, Platform
from homeassistant.const import CONF_HOST, CONF_MAC, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from .const import CONF_IGNORED_SOURCES, CONF_USE_PSK, DOMAIN
from .const import CONF_IGNORED_SOURCES, DOMAIN
from .coordinator import BraviaTVCoordinator
PLATFORMS: Final[list[Platform]] = [
@ -25,8 +25,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
"""Set up a config entry."""
host = config_entry.data[CONF_HOST]
mac = config_entry.data[CONF_MAC]
pin = config_entry.data[CONF_PIN]
use_psk = config_entry.data.get(CONF_USE_PSK, False)
ignored_sources = config_entry.options.get(CONF_IGNORED_SOURCES, [])
session = async_create_clientsession(
@ -36,8 +34,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
coordinator = BraviaTVCoordinator(
hass=hass,
client=client,
pin=pin,
use_psk=use_psk,
config=config_entry.data,
ignored_sources=ignored_sources,
)
config_entry.async_on_unload(config_entry.add_update_listener(update_listener))

View File

@ -15,6 +15,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, CONF_PIN
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import instance_id
from homeassistant.helpers.aiohttp_client import async_create_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.util.network import is_host_valid
@ -24,11 +25,12 @@ from .const import (
ATTR_CID,
ATTR_MAC,
ATTR_MODEL,
CLIENTID_PREFIX,
CONF_CLIENT_ID,
CONF_IGNORED_SOURCES,
CONF_NICKNAME,
CONF_USE_PSK,
DOMAIN,
NICKNAME,
NICKNAME_PREFIX,
)
@ -42,6 +44,8 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self.client: BraviaTV | None = None
self.device_config: dict[str, Any] = {}
self.entry: ConfigEntry | None = None
self.client_id: str = ""
self.nickname: str = ""
@staticmethod
@callback
@ -68,8 +72,10 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if use_psk:
await self.client.connect(psk=pin)
else:
self.device_config[CONF_CLIENT_ID] = self.client_id
self.device_config[CONF_NICKNAME] = self.nickname
await self.client.connect(
pin=pin, clientid=CLIENTID_PREFIX, nickname=NICKNAME
pin=pin, clientid=self.client_id, nickname=self.nickname
)
await self.client.set_wol_mode(True)
@ -110,6 +116,7 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
) -> FlowResult:
"""Authorize Bravia TV device."""
errors: dict[str, str] = {}
self.client_id, self.nickname = await self.gen_instance_ids()
if user_input is not None:
self.device_config[CONF_PIN] = user_input[CONF_PIN]
@ -126,7 +133,7 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
assert self.client
try:
await self.client.pair(CLIENTID_PREFIX, NICKNAME)
await self.client.pair(self.client_id, self.nickname)
except BraviaTVError:
return self.async_abort(reason="no_ip_control")
@ -190,6 +197,7 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
) -> FlowResult:
"""Dialog that informs the user that reauth is required."""
self.create_client()
client_id, nickname = await self.gen_instance_ids()
assert self.client is not None
assert self.entry is not None
@ -201,8 +209,10 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if use_psk:
await self.client.connect(psk=pin)
else:
self.device_config[CONF_CLIENT_ID] = client_id
self.device_config[CONF_NICKNAME] = nickname
await self.client.connect(
pin=pin, clientid=CLIENTID_PREFIX, nickname=NICKNAME
pin=pin, clientid=client_id, nickname=nickname
)
await self.client.set_wol_mode(True)
except BraviaTVError:
@ -215,7 +225,7 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
return self.async_abort(reason="reauth_successful")
try:
await self.client.pair(CLIENTID_PREFIX, NICKNAME)
await self.client.pair(client_id, nickname)
except BraviaTVError:
return self.async_abort(reason="reauth_unsuccessful")
@ -229,6 +239,11 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
),
)
async def gen_instance_ids(self) -> tuple[str, str]:
"""Generate client_id and nickname."""
uuid = await instance_id.async_get(self.hass)
return uuid, f"{NICKNAME_PREFIX} {uuid[:6]}"
class BraviaTVOptionsFlowHandler(config_entries.OptionsFlow):
"""Config flow options for Bravia TV."""

View File

@ -8,9 +8,11 @@ ATTR_MAC: Final = "macAddr"
ATTR_MANUFACTURER: Final = "Sony"
ATTR_MODEL: Final = "model"
CONF_CLIENT_ID: Final = "client_id"
CONF_IGNORED_SOURCES: Final = "ignored_sources"
CONF_NICKNAME: Final = "nickname"
CONF_USE_PSK: Final = "use_psk"
CLIENTID_PREFIX: Final = "HomeAssistant"
DOMAIN: Final = "braviatv"
NICKNAME: Final = "Home Assistant"
LEGACY_CLIENT_ID: Final = "HomeAssistant"
NICKNAME_PREFIX: Final = "Home Assistant"

View File

@ -5,6 +5,7 @@ from collections.abc import Awaitable, Callable, Coroutine, Iterable
from datetime import timedelta
from functools import wraps
import logging
from types import MappingProxyType
from typing import Any, Final, TypeVar
from pybravia import (
@ -19,12 +20,20 @@ from pybravia import (
from typing_extensions import Concatenate, ParamSpec
from homeassistant.components.media_player import MediaType
from homeassistant.const import CONF_PIN
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import CLIENTID_PREFIX, DOMAIN, NICKNAME
from .const import (
CONF_CLIENT_ID,
CONF_NICKNAME,
CONF_USE_PSK,
DOMAIN,
LEGACY_CLIENT_ID,
NICKNAME_PREFIX,
)
_BraviaTVCoordinatorT = TypeVar("_BraviaTVCoordinatorT", bound="BraviaTVCoordinator")
_P = ParamSpec("_P")
@ -61,15 +70,16 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]):
self,
hass: HomeAssistant,
client: BraviaTV,
pin: str,
use_psk: bool,
config: MappingProxyType[str, Any],
ignored_sources: list[str],
) -> None:
"""Initialize Bravia TV Client."""
self.client = client
self.pin = pin
self.use_psk = use_psk
self.pin = config[CONF_PIN]
self.use_psk = config.get(CONF_USE_PSK, False)
self.client_id = config.get(CONF_CLIENT_ID, LEGACY_CLIENT_ID)
self.nickname = config.get(CONF_NICKNAME, NICKNAME_PREFIX)
self.ignored_sources = ignored_sources
self.source: str | None = None
self.source_list: list[str] = []
@ -119,7 +129,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]):
await self.client.connect(psk=self.pin)
else:
await self.client.connect(
pin=self.pin, clientid=CLIENTID_PREFIX, nickname=NICKNAME
pin=self.pin, clientid=self.client_id, nickname=self.nickname
)
self.connected = True

View File

@ -12,12 +12,16 @@ import pytest
from homeassistant import data_entry_flow
from homeassistant.components import ssdp
from homeassistant.components.braviatv.const import (
CONF_CLIENT_ID,
CONF_IGNORED_SOURCES,
CONF_NICKNAME,
CONF_USE_PSK,
DOMAIN,
NICKNAME_PREFIX,
)
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_SSDP, SOURCE_USER
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PIN
from homeassistant.helpers import instance_id
from tests.common import MockConfigEntry
@ -93,6 +97,7 @@ async def test_show_form(hass):
async def test_ssdp_discovery(hass):
"""Test that the device is discovered."""
uuid = await instance_id.async_get(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_SSDP},
@ -129,6 +134,8 @@ async def test_ssdp_discovery(hass):
CONF_PIN: "1234",
CONF_USE_PSK: False,
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_CLIENT_ID: uuid,
CONF_NICKNAME: f"{NICKNAME_PREFIX} {uuid[:6]}",
}
@ -270,6 +277,8 @@ async def test_duplicate_error(hass):
async def test_create_entry(hass):
"""Test that the user step works."""
uuid = await instance_id.async_get(hass)
with patch("pybravia.BraviaTV.connect"), patch("pybravia.BraviaTV.pair"), patch(
"pybravia.BraviaTV.set_wol_mode"
), patch(
@ -297,11 +306,15 @@ async def test_create_entry(hass):
CONF_PIN: "1234",
CONF_USE_PSK: False,
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_CLIENT_ID: uuid,
CONF_NICKNAME: f"{NICKNAME_PREFIX} {uuid[:6]}",
}
async def test_create_entry_with_ipv6_address(hass):
"""Test that the user step works with device IPv6 address."""
uuid = await instance_id.async_get(hass)
with patch("pybravia.BraviaTV.connect"), patch("pybravia.BraviaTV.pair"), patch(
"pybravia.BraviaTV.set_wol_mode"
), patch(
@ -331,6 +344,8 @@ async def test_create_entry_with_ipv6_address(hass):
CONF_PIN: "1234",
CONF_USE_PSK: False,
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_CLIENT_ID: uuid,
CONF_NICKNAME: f"{NICKNAME_PREFIX} {uuid[:6]}",
}