Register MAC connection for Elgato devices (#64201)

* Register MAC connection for Elgato devices

* Add tests, fix name
pull/64213/head
Franck Nijhof 2022-01-16 22:18:46 +01:00 committed by GitHub
parent 32d4f104ff
commit 423674c0c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 16 deletions

View File

@ -7,6 +7,7 @@ from elgato import Elgato, ElgatoError, Info
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_MAC
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -25,15 +26,17 @@ async def async_setup_entry(
) -> None:
"""Set up Elgato button based on a config entry."""
data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id]
async_add_entities([ElgatoIdentifyButton(data.client, data.info)])
async_add_entities(
[ElgatoIdentifyButton(data.client, data.info, entry.data.get(CONF_MAC))]
)
class ElgatoIdentifyButton(ElgatoEntity, ButtonEntity):
"""Defines an Elgato identify button."""
def __init__(self, client: Elgato, info: Info) -> None:
def __init__(self, client: Elgato, info: Info, mac: str | None) -> None:
"""Initialize the button entity."""
super().__init__(client, info)
super().__init__(client, info, mac)
self.entity_description = ButtonEntityDescription(
key="identify",
name="Identify",

View File

@ -8,7 +8,7 @@ import voluptuous as vol
from homeassistant.components import zeroconf
from homeassistant.config_entries import ConfigFlow
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PORT
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
@ -24,6 +24,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
host: str
port: int
serial_number: str
mac: str | None = None
async def async_step_user(
self, user_input: dict[str, Any] | None = None
@ -47,6 +48,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
) -> FlowResult:
"""Handle zeroconf discovery."""
self.host = discovery_info.host
self.mac = discovery_info.properties.get("id")
self.port = discovery_info.port or 9123
try:
@ -89,6 +91,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
data={
CONF_HOST: self.host,
CONF_PORT: self.port,
CONF_MAC: self.mac,
},
)
@ -107,7 +110,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
info.serial_number, raise_on_progress=raise_on_progress
)
self._abort_if_unique_id_configured(
updates={CONF_HOST: self.host, CONF_PORT: self.port}
updates={CONF_HOST: self.host, CONF_PORT: self.port, CONF_MAC: self.mac}
)
self.serial_number = info.serial_number

View File

@ -1,7 +1,9 @@
"""Base entity for the Elgato integration."""
from __future__ import annotations
from elgato import Elgato, Info
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, format_mac
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import DOMAIN
@ -10,13 +12,17 @@ from .const import DOMAIN
class ElgatoEntity(Entity):
"""Defines an Elgato entity."""
def __init__(self, client: Elgato, info: Info) -> None:
def __init__(self, client: Elgato, info: Info, mac: str | None) -> None:
"""Initialize an Elgato entity."""
self.client = client
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, info.serial_number)},
manufacturer="Elgato",
model=info.product_name,
name=info.product_name,
name=info.display_name,
sw_version=f"{info.firmware_version} ({info.firmware_build_number})",
)
if mac is not None:
self._attr_device_info["connections"] = {
(CONNECTION_NETWORK_MAC, format_mac(mac))
}

View File

@ -16,6 +16,7 @@ from homeassistant.components.light import (
LightEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_MAC
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import (
AddEntitiesCallback,
@ -40,7 +41,9 @@ async def async_setup_entry(
"""Set up Elgato Light based on a config entry."""
data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id]
settings = await data.client.settings()
async_add_entities([ElgatoLight(data.client, data.info, settings)], True)
async_add_entities(
[ElgatoLight(data.client, data.info, entry.data.get(CONF_MAC), settings)], True
)
platform = async_get_current_platform()
platform.async_register_entity_service(
@ -53,9 +56,11 @@ async def async_setup_entry(
class ElgatoLight(ElgatoEntity, LightEntity):
"""Defines an Elgato Light."""
def __init__(self, client: Elgato, info: Info, settings: Settings) -> None:
def __init__(
self, client: Elgato, info: Info, mac: str | None, settings: Settings
) -> None:
"""Initialize Elgato Light."""
super().__init__(client, info)
super().__init__(client, info, mac)
self._state: State | None = None
min_mired = 143

View File

@ -6,7 +6,7 @@ from elgato import Info, Settings, State
import pytest
from homeassistant.components.elgato.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PORT
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture
@ -19,7 +19,11 @@ def mock_config_entry() -> MockConfigEntry:
return MockConfigEntry(
title="CN11A1A00001",
domain=DOMAIN,
data={CONF_HOST: "127.0.0.1", CONF_PORT: 9123},
data={
CONF_HOST: "127.0.0.1",
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_PORT: 9123,
},
unique_id="CN11A1A00001",
)

View File

@ -5,9 +5,10 @@ from elgato import ElgatoError
import pytest
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.elgato.const import DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, ATTR_ICON, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity import EntityCategory
from tests.common import MockConfigEntry
@ -20,6 +21,7 @@ async def test_button_identify(
mock_elgato: MagicMock,
) -> None:
"""Test the Elgato identify button."""
device_registry = dr.async_get(hass)
entity_registry = er.async_get(hass)
state = hass.states.get("button.identify")
@ -32,6 +34,20 @@ async def test_button_identify(
assert entry.unique_id == "CN11A1A00001_identify"
assert entry.entity_category == EntityCategory.CONFIG
assert entry.device_id
device_entry = device_registry.async_get(entry.device_id)
assert device_entry
assert device_entry.configuration_url is None
assert device_entry.connections == {
(dr.CONNECTION_NETWORK_MAC, "aa:bb:cc:dd:ee:ff")
}
assert device_entry.entry_type is None
assert device_entry.identifiers == {(DOMAIN, "CN11A1A00001")}
assert device_entry.manufacturer == "Elgato"
assert device_entry.model == "Elgato Key Light"
assert device_entry.name == "Frenck"
assert device_entry.sw_version == "1.0.3 (192)"
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,

View File

@ -6,7 +6,7 @@ from elgato import ElgatoConnectionError
from homeassistant.components import zeroconf
from homeassistant.components.elgato.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SOURCE
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PORT, CONF_SOURCE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import (
RESULT_TYPE_ABORT,
@ -40,6 +40,7 @@ async def test_full_user_flow_implementation(
assert result2.get("title") == "CN11A1A00001"
assert result2.get("data") == {
CONF_HOST: "127.0.0.1",
CONF_MAC: None,
CONF_PORT: 9123,
}
assert "result" in result2
@ -63,7 +64,7 @@ async def test_full_zeroconf_flow_implementation(
hostname="example.local.",
name="mock_name",
port=9123,
properties={},
properties={"id": "AA:BB:CC:DD:EE:FF"},
type="mock_type",
),
)
@ -87,6 +88,7 @@ async def test_full_zeroconf_flow_implementation(
assert result2.get("title") == "CN11A1A00001"
assert result2.get("data") == {
CONF_HOST: "127.0.0.1",
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_PORT: 9123,
}
assert "result" in result2

View File

@ -25,7 +25,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import device_registry as dr, entity_registry as er
from tests.common import MockConfigEntry
@ -36,6 +36,7 @@ async def test_light_state_temperature(
mock_elgato: MagicMock,
) -> None:
"""Test the creation and values of the Elgato Lights in temperature mode."""
device_registry = dr.async_get(hass)
entity_registry = er.async_get(hass)
# First segment of the strip
@ -54,6 +55,20 @@ async def test_light_state_temperature(
assert entry
assert entry.unique_id == "CN11A1A00001"
assert entry.device_id
device_entry = device_registry.async_get(entry.device_id)
assert device_entry
assert device_entry.configuration_url is None
assert device_entry.connections == {
(dr.CONNECTION_NETWORK_MAC, "aa:bb:cc:dd:ee:ff")
}
assert device_entry.entry_type is None
assert device_entry.identifiers == {(DOMAIN, "CN11A1A00001")}
assert device_entry.manufacturer == "Elgato"
assert device_entry.model == "Elgato Key Light"
assert device_entry.name == "Frenck"
assert device_entry.sw_version == "1.0.3 (192)"
@pytest.mark.parametrize(
"mock_elgato", [{"settings": "color", "state": "color"}], indirect=True