mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Register MAC connection for Elgato devices (#64201)
* Register MAC connection for Elgato devices * Add tests, fix name
This commit is contained in:
parent
32d4f104ff
commit
423674c0c9
@ -7,6 +7,7 @@ from elgato import Elgato, ElgatoError, Info
|
|||||||
|
|
||||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_MAC
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
@ -25,15 +26,17 @@ async def async_setup_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Elgato button based on a config entry."""
|
"""Set up Elgato button based on a config entry."""
|
||||||
data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id]
|
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):
|
class ElgatoIdentifyButton(ElgatoEntity, ButtonEntity):
|
||||||
"""Defines an Elgato identify button."""
|
"""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."""
|
"""Initialize the button entity."""
|
||||||
super().__init__(client, info)
|
super().__init__(client, info, mac)
|
||||||
self.entity_description = ButtonEntityDescription(
|
self.entity_description = ButtonEntityDescription(
|
||||||
key="identify",
|
key="identify",
|
||||||
name="Identify",
|
name="Identify",
|
||||||
|
@ -8,7 +8,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.components import zeroconf
|
from homeassistant.components import zeroconf
|
||||||
from homeassistant.config_entries import ConfigFlow
|
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.core import callback
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
@ -24,6 +24,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
host: str
|
host: str
|
||||||
port: int
|
port: int
|
||||||
serial_number: str
|
serial_number: str
|
||||||
|
mac: str | None = None
|
||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
@ -47,6 +48,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Handle zeroconf discovery."""
|
"""Handle zeroconf discovery."""
|
||||||
self.host = discovery_info.host
|
self.host = discovery_info.host
|
||||||
|
self.mac = discovery_info.properties.get("id")
|
||||||
self.port = discovery_info.port or 9123
|
self.port = discovery_info.port or 9123
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -89,6 +91,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
data={
|
data={
|
||||||
CONF_HOST: self.host,
|
CONF_HOST: self.host,
|
||||||
CONF_PORT: self.port,
|
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
|
info.serial_number, raise_on_progress=raise_on_progress
|
||||||
)
|
)
|
||||||
self._abort_if_unique_id_configured(
|
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
|
self.serial_number = info.serial_number
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Base entity for the Elgato integration."""
|
"""Base entity for the Elgato integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from elgato import Elgato, Info
|
from elgato import Elgato, Info
|
||||||
|
|
||||||
|
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, format_mac
|
||||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
@ -10,13 +12,17 @@ from .const import DOMAIN
|
|||||||
class ElgatoEntity(Entity):
|
class ElgatoEntity(Entity):
|
||||||
"""Defines an Elgato 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."""
|
"""Initialize an Elgato entity."""
|
||||||
self.client = client
|
self.client = client
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
identifiers={(DOMAIN, info.serial_number)},
|
identifiers={(DOMAIN, info.serial_number)},
|
||||||
manufacturer="Elgato",
|
manufacturer="Elgato",
|
||||||
model=info.product_name,
|
model=info.product_name,
|
||||||
name=info.product_name,
|
name=info.display_name,
|
||||||
sw_version=f"{info.firmware_version} ({info.firmware_build_number})",
|
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))
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@ from homeassistant.components.light import (
|
|||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_MAC
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import (
|
from homeassistant.helpers.entity_platform import (
|
||||||
AddEntitiesCallback,
|
AddEntitiesCallback,
|
||||||
@ -40,7 +41,9 @@ async def async_setup_entry(
|
|||||||
"""Set up Elgato Light based on a config entry."""
|
"""Set up Elgato Light based on a config entry."""
|
||||||
data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id]
|
||||||
settings = await data.client.settings()
|
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_get_current_platform()
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
@ -53,9 +56,11 @@ async def async_setup_entry(
|
|||||||
class ElgatoLight(ElgatoEntity, LightEntity):
|
class ElgatoLight(ElgatoEntity, LightEntity):
|
||||||
"""Defines an Elgato Light."""
|
"""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."""
|
"""Initialize Elgato Light."""
|
||||||
super().__init__(client, info)
|
super().__init__(client, info, mac)
|
||||||
self._state: State | None = None
|
self._state: State | None = None
|
||||||
|
|
||||||
min_mired = 143
|
min_mired = 143
|
||||||
|
@ -6,7 +6,7 @@ from elgato import Info, Settings, State
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.elgato.const import DOMAIN
|
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 homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, load_fixture
|
from tests.common import MockConfigEntry, load_fixture
|
||||||
@ -19,7 +19,11 @@ def mock_config_entry() -> MockConfigEntry:
|
|||||||
return MockConfigEntry(
|
return MockConfigEntry(
|
||||||
title="CN11A1A00001",
|
title="CN11A1A00001",
|
||||||
domain=DOMAIN,
|
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",
|
unique_id="CN11A1A00001",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,9 +5,10 @@ from elgato import ElgatoError
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
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.const import ATTR_ENTITY_ID, ATTR_ICON, STATE_UNKNOWN
|
||||||
from homeassistant.core import HomeAssistant
|
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 homeassistant.helpers.entity import EntityCategory
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
@ -20,6 +21,7 @@ async def test_button_identify(
|
|||||||
mock_elgato: MagicMock,
|
mock_elgato: MagicMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the Elgato identify button."""
|
"""Test the Elgato identify button."""
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
state = hass.states.get("button.identify")
|
state = hass.states.get("button.identify")
|
||||||
@ -32,6 +34,20 @@ async def test_button_identify(
|
|||||||
assert entry.unique_id == "CN11A1A00001_identify"
|
assert entry.unique_id == "CN11A1A00001_identify"
|
||||||
assert entry.entity_category == EntityCategory.CONFIG
|
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(
|
await hass.services.async_call(
|
||||||
BUTTON_DOMAIN,
|
BUTTON_DOMAIN,
|
||||||
SERVICE_PRESS,
|
SERVICE_PRESS,
|
||||||
|
@ -6,7 +6,7 @@ from elgato import ElgatoConnectionError
|
|||||||
from homeassistant.components import zeroconf
|
from homeassistant.components import zeroconf
|
||||||
from homeassistant.components.elgato.const import DOMAIN
|
from homeassistant.components.elgato.const import DOMAIN
|
||||||
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
|
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.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import (
|
from homeassistant.data_entry_flow import (
|
||||||
RESULT_TYPE_ABORT,
|
RESULT_TYPE_ABORT,
|
||||||
@ -40,6 +40,7 @@ async def test_full_user_flow_implementation(
|
|||||||
assert result2.get("title") == "CN11A1A00001"
|
assert result2.get("title") == "CN11A1A00001"
|
||||||
assert result2.get("data") == {
|
assert result2.get("data") == {
|
||||||
CONF_HOST: "127.0.0.1",
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_MAC: None,
|
||||||
CONF_PORT: 9123,
|
CONF_PORT: 9123,
|
||||||
}
|
}
|
||||||
assert "result" in result2
|
assert "result" in result2
|
||||||
@ -63,7 +64,7 @@ async def test_full_zeroconf_flow_implementation(
|
|||||||
hostname="example.local.",
|
hostname="example.local.",
|
||||||
name="mock_name",
|
name="mock_name",
|
||||||
port=9123,
|
port=9123,
|
||||||
properties={},
|
properties={"id": "AA:BB:CC:DD:EE:FF"},
|
||||||
type="mock_type",
|
type="mock_type",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -87,6 +88,7 @@ async def test_full_zeroconf_flow_implementation(
|
|||||||
assert result2.get("title") == "CN11A1A00001"
|
assert result2.get("title") == "CN11A1A00001"
|
||||||
assert result2.get("data") == {
|
assert result2.get("data") == {
|
||||||
CONF_HOST: "127.0.0.1",
|
CONF_HOST: "127.0.0.1",
|
||||||
|
CONF_MAC: "AA:BB:CC:DD:EE:FF",
|
||||||
CONF_PORT: 9123,
|
CONF_PORT: 9123,
|
||||||
}
|
}
|
||||||
assert "result" in result2
|
assert "result" in result2
|
||||||
|
@ -25,7 +25,7 @@ from homeassistant.const import (
|
|||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
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
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
@ -36,6 +36,7 @@ async def test_light_state_temperature(
|
|||||||
mock_elgato: MagicMock,
|
mock_elgato: MagicMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the creation and values of the Elgato Lights in temperature mode."""
|
"""Test the creation and values of the Elgato Lights in temperature mode."""
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
# First segment of the strip
|
# First segment of the strip
|
||||||
@ -54,6 +55,20 @@ async def test_light_state_temperature(
|
|||||||
assert entry
|
assert entry
|
||||||
assert entry.unique_id == "CN11A1A00001"
|
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(
|
@pytest.mark.parametrize(
|
||||||
"mock_elgato", [{"settings": "color", "state": "color"}], indirect=True
|
"mock_elgato", [{"settings": "color", "state": "color"}], indirect=True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user