mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Add MAC connection through DHCP discovery to Home Connect devices (#144611)
* Add MAC connection through DHCP discovery to Home Connect devices * Update snapshots
This commit is contained in:
parent
b5445c0061
commit
15a4514c7d
@ -8,7 +8,8 @@ import jwt
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
|
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow, device_registry as dr
|
||||||
|
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
@ -58,3 +59,22 @@ class OAuth2FlowHandler(
|
|||||||
)
|
)
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
return await super().async_oauth_create_entry(data)
|
return await super().async_oauth_create_entry(data)
|
||||||
|
|
||||||
|
async def async_step_dhcp(
|
||||||
|
self, discovery_info: DhcpServiceInfo
|
||||||
|
) -> ConfigFlowResult:
|
||||||
|
"""Handle a DHCP discovery."""
|
||||||
|
device_registry = dr.async_get(self.hass)
|
||||||
|
if device_entry := device_registry.async_get_device(
|
||||||
|
identifiers={
|
||||||
|
(DOMAIN, discovery_info.hostname),
|
||||||
|
(DOMAIN, discovery_info.hostname.split("-")[-1]),
|
||||||
|
}
|
||||||
|
):
|
||||||
|
device_registry.async_update_device(
|
||||||
|
device_entry.id,
|
||||||
|
new_connections={
|
||||||
|
(dr.CONNECTION_NETWORK_MAC, discovery_info.macaddress)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return await super().async_step_dhcp(discovery_info)
|
||||||
|
@ -97,7 +97,7 @@
|
|||||||
"connected": true,
|
"connected": true,
|
||||||
"type": "Hob",
|
"type": "Hob",
|
||||||
"enumber": "HCS000000/05",
|
"enumber": "HCS000000/05",
|
||||||
"haId": "BOSCH-HCS000000-D00000000005"
|
"haId": "BOSCH-HCS000000-68A40E000000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "CookProcessor",
|
"name": "CookProcessor",
|
||||||
@ -106,7 +106,7 @@
|
|||||||
"connected": true,
|
"connected": true,
|
||||||
"type": "CookProcessor",
|
"type": "CookProcessor",
|
||||||
"enumber": "HCS000000/06",
|
"enumber": "HCS000000/06",
|
||||||
"haId": "BOSCH-HCS000000-D00000000006"
|
"haId": "123456789012345678"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "DNE",
|
"name": "DNE",
|
||||||
|
@ -1,6 +1,26 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
# name: test_async_get_config_entry_diagnostics
|
# name: test_async_get_config_entry_diagnostics
|
||||||
dict({
|
dict({
|
||||||
|
'123456789012345678': dict({
|
||||||
|
'brand': 'BOSCH',
|
||||||
|
'connected': True,
|
||||||
|
'e_number': 'HCS000000/06',
|
||||||
|
'ha_id': '123456789012345678',
|
||||||
|
'name': 'CookProcessor',
|
||||||
|
'programs': list([
|
||||||
|
]),
|
||||||
|
'settings': dict({
|
||||||
|
}),
|
||||||
|
'status': dict({
|
||||||
|
'BSH.Common.Status.DoorState': 'BSH.Common.EnumType.DoorState.Closed',
|
||||||
|
'BSH.Common.Status.OperationState': 'BSH.Common.EnumType.OperationState.Ready',
|
||||||
|
'BSH.Common.Status.RemoteControlActive': True,
|
||||||
|
'BSH.Common.Status.RemoteControlStartAllowed': True,
|
||||||
|
'Refrigeration.Common.Status.Door.Refrigerator': 'BSH.Common.EnumType.DoorState.Open',
|
||||||
|
}),
|
||||||
|
'type': 'CookProcessor',
|
||||||
|
'vib': 'HCS000006',
|
||||||
|
}),
|
||||||
'BOSCH-000000000-000000000000': dict({
|
'BOSCH-000000000-000000000000': dict({
|
||||||
'brand': 'BOSCH',
|
'brand': 'BOSCH',
|
||||||
'connected': True,
|
'connected': True,
|
||||||
@ -21,6 +41,26 @@
|
|||||||
'type': 'DNE',
|
'type': 'DNE',
|
||||||
'vib': 'HCS000000',
|
'vib': 'HCS000000',
|
||||||
}),
|
}),
|
||||||
|
'BOSCH-HCS000000-68A40E000000': dict({
|
||||||
|
'brand': 'BOSCH',
|
||||||
|
'connected': True,
|
||||||
|
'e_number': 'HCS000000/05',
|
||||||
|
'ha_id': 'BOSCH-HCS000000-68A40E000000',
|
||||||
|
'name': 'Hob',
|
||||||
|
'programs': list([
|
||||||
|
]),
|
||||||
|
'settings': dict({
|
||||||
|
}),
|
||||||
|
'status': dict({
|
||||||
|
'BSH.Common.Status.DoorState': 'BSH.Common.EnumType.DoorState.Closed',
|
||||||
|
'BSH.Common.Status.OperationState': 'BSH.Common.EnumType.OperationState.Ready',
|
||||||
|
'BSH.Common.Status.RemoteControlActive': True,
|
||||||
|
'BSH.Common.Status.RemoteControlStartAllowed': True,
|
||||||
|
'Refrigeration.Common.Status.Door.Refrigerator': 'BSH.Common.EnumType.DoorState.Open',
|
||||||
|
}),
|
||||||
|
'type': 'Hob',
|
||||||
|
'vib': 'HCS000005',
|
||||||
|
}),
|
||||||
'BOSCH-HCS000000-D00000000001': dict({
|
'BOSCH-HCS000000-D00000000001': dict({
|
||||||
'brand': 'BOSCH',
|
'brand': 'BOSCH',
|
||||||
'connected': True,
|
'connected': True,
|
||||||
@ -114,46 +154,6 @@
|
|||||||
'type': 'Hood',
|
'type': 'Hood',
|
||||||
'vib': 'HCS000004',
|
'vib': 'HCS000004',
|
||||||
}),
|
}),
|
||||||
'BOSCH-HCS000000-D00000000005': dict({
|
|
||||||
'brand': 'BOSCH',
|
|
||||||
'connected': True,
|
|
||||||
'e_number': 'HCS000000/05',
|
|
||||||
'ha_id': 'BOSCH-HCS000000-D00000000005',
|
|
||||||
'name': 'Hob',
|
|
||||||
'programs': list([
|
|
||||||
]),
|
|
||||||
'settings': dict({
|
|
||||||
}),
|
|
||||||
'status': dict({
|
|
||||||
'BSH.Common.Status.DoorState': 'BSH.Common.EnumType.DoorState.Closed',
|
|
||||||
'BSH.Common.Status.OperationState': 'BSH.Common.EnumType.OperationState.Ready',
|
|
||||||
'BSH.Common.Status.RemoteControlActive': True,
|
|
||||||
'BSH.Common.Status.RemoteControlStartAllowed': True,
|
|
||||||
'Refrigeration.Common.Status.Door.Refrigerator': 'BSH.Common.EnumType.DoorState.Open',
|
|
||||||
}),
|
|
||||||
'type': 'Hob',
|
|
||||||
'vib': 'HCS000005',
|
|
||||||
}),
|
|
||||||
'BOSCH-HCS000000-D00000000006': dict({
|
|
||||||
'brand': 'BOSCH',
|
|
||||||
'connected': True,
|
|
||||||
'e_number': 'HCS000000/06',
|
|
||||||
'ha_id': 'BOSCH-HCS000000-D00000000006',
|
|
||||||
'name': 'CookProcessor',
|
|
||||||
'programs': list([
|
|
||||||
]),
|
|
||||||
'settings': dict({
|
|
||||||
}),
|
|
||||||
'status': dict({
|
|
||||||
'BSH.Common.Status.DoorState': 'BSH.Common.EnumType.DoorState.Closed',
|
|
||||||
'BSH.Common.Status.OperationState': 'BSH.Common.EnumType.OperationState.Ready',
|
|
||||||
'BSH.Common.Status.RemoteControlActive': True,
|
|
||||||
'BSH.Common.Status.RemoteControlStartAllowed': True,
|
|
||||||
'Refrigeration.Common.Status.Door.Refrigerator': 'BSH.Common.EnumType.DoorState.Open',
|
|
||||||
}),
|
|
||||||
'type': 'CookProcessor',
|
|
||||||
'vib': 'HCS000006',
|
|
||||||
}),
|
|
||||||
'BOSCH-HCS01OVN1-43E0065FE245': dict({
|
'BOSCH-HCS01OVN1-43E0065FE245': dict({
|
||||||
'brand': 'BOSCH',
|
'brand': 'BOSCH',
|
||||||
'connected': True,
|
'connected': True,
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
"""Test the Home Connect config flow."""
|
"""Test the Home Connect config flow."""
|
||||||
|
|
||||||
|
from collections.abc import Awaitable, Callable
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from unittest.mock import patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from aiohomeconnect.const import OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
from aiohomeconnect.const import OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
||||||
|
from aiohomeconnect.model import HomeAppliance
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import config_entries, setup
|
from homeassistant import config_entries, setup
|
||||||
@ -11,7 +13,7 @@ from homeassistant.components.home_connect.const import DOMAIN
|
|||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow, device_registry as dr
|
||||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||||
|
|
||||||
from .conftest import FAKE_ACCESS_TOKEN, FAKE_REFRESH_TOKEN
|
from .conftest import FAKE_ACCESS_TOKEN, FAKE_REFRESH_TOKEN
|
||||||
@ -337,17 +339,17 @@ async def test_zeroconf_flow_already_setup(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("current_request_with_host")
|
@pytest.mark.usefixtures("current_request_with_host")
|
||||||
@pytest.mark.parametrize("dchp_discovery", DHCP_DISCOVERY)
|
@pytest.mark.parametrize("dhcp_discovery", DHCP_DISCOVERY)
|
||||||
async def test_dhcp_flow(
|
async def test_dhcp_flow(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client_no_auth: ClientSessionGenerator,
|
hass_client_no_auth: ClientSessionGenerator,
|
||||||
aioclient_mock: AiohttpClientMocker,
|
aioclient_mock: AiohttpClientMocker,
|
||||||
dchp_discovery: DhcpServiceInfo,
|
dhcp_discovery: DhcpServiceInfo,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test DHCP discovery."""
|
"""Test DHCP discovery."""
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dchp_discovery
|
DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dhcp_discovery
|
||||||
)
|
)
|
||||||
state = config_entry_oauth2_flow._encode_jwt(
|
state = config_entry_oauth2_flow._encode_jwt(
|
||||||
hass,
|
hass,
|
||||||
@ -391,8 +393,6 @@ async def test_dhcp_flow(
|
|||||||
@pytest.mark.usefixtures("current_request_with_host")
|
@pytest.mark.usefixtures("current_request_with_host")
|
||||||
async def test_dhcp_flow_already_setup(
|
async def test_dhcp_flow_already_setup(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client_no_auth: ClientSessionGenerator,
|
|
||||||
aioclient_mock: AiohttpClientMocker,
|
|
||||||
config_entry: MockConfigEntry,
|
config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test DHCP discovery with already setup device."""
|
"""Test DHCP discovery with already setup device."""
|
||||||
@ -403,3 +403,56 @@ async def test_dhcp_flow_already_setup(
|
|||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == "already_configured"
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("current_request_with_host")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("dhcp_discovery", "appliance"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
DhcpServiceInfo(
|
||||||
|
ip="1.1.1.1",
|
||||||
|
hostname="bosch-cookprocessor-123456789012345678",
|
||||||
|
macaddress="c8:d7:78:00:00:00",
|
||||||
|
),
|
||||||
|
"CookProcessor",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
DhcpServiceInfo(
|
||||||
|
ip="1.1.1.1",
|
||||||
|
hostname="BOSCH-HCS000000-68A40E000000",
|
||||||
|
macaddress="68:a4:0e:00:00:00",
|
||||||
|
),
|
||||||
|
"Hob",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
indirect=["appliance"],
|
||||||
|
)
|
||||||
|
async def test_dhcp_flow_complete_device_information(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
client: MagicMock,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||||
|
dhcp_discovery: DhcpServiceInfo,
|
||||||
|
appliance: HomeAppliance,
|
||||||
|
) -> None:
|
||||||
|
"""Test DHCP discovery with complete device information."""
|
||||||
|
assert await integration_setup(client)
|
||||||
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||||
|
assert device
|
||||||
|
assert device.connections == set()
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dhcp_discovery
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||||
|
assert device
|
||||||
|
assert device.connections == {
|
||||||
|
(dr.CONNECTION_NETWORK_MAC, dhcp_discovery.macaddress)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user