mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Add dhcp discovery to Roborock (#141148)
* Add discovery to Roborock * Update homeassistant/components/roborock/config_flow.py Co-authored-by: Allen Porter <allen.porter@gmail.com> * MR comments * go back to removing the ":" * change method of getting devices --------- Co-authored-by: Allen Porter <allen.porter@gmail.com>
This commit is contained in:
parent
ddd67a7e58
commit
e2e80a850c
@ -28,7 +28,9 @@ from homeassistant.config_entries import (
|
||||
)
|
||||
from homeassistant.const import CONF_USERNAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
|
||||
from .const import (
|
||||
CONF_BASE_URL,
|
||||
@ -137,6 +139,22 @@ class RoborockFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_dhcp(
|
||||
self, discovery_info: DhcpServiceInfo
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow started by a dhcp discovery."""
|
||||
device_registry = dr.async_get(self.hass)
|
||||
device = device_registry.async_get_device(
|
||||
connections={
|
||||
(dr.CONNECTION_NETWORK_MAC, dr.format_mac(discovery_info.macaddress))
|
||||
}
|
||||
)
|
||||
if device is not None and any(
|
||||
identifier[0] == DOMAIN for identifier in device.identifiers
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_reauth(
|
||||
self, entry_data: Mapping[str, Any]
|
||||
) -> ConfigFlowResult:
|
||||
|
@ -129,7 +129,9 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]):
|
||||
self.current_map: int | None = None
|
||||
|
||||
if mac := self.roborock_device_info.network_info.mac:
|
||||
self.device_info[ATTR_CONNECTIONS] = {(dr.CONNECTION_NETWORK_MAC, mac)}
|
||||
self.device_info[ATTR_CONNECTIONS] = {
|
||||
(dr.CONNECTION_NETWORK_MAC, dr.format_mac(mac))
|
||||
}
|
||||
# Maps from map flag to map name
|
||||
self.maps: dict[int, RoborockMapInfo] = {}
|
||||
self._home_data_rooms = {str(room.id): room.name for room in home_data_rooms}
|
||||
|
@ -3,6 +3,17 @@
|
||||
"name": "Roborock",
|
||||
"codeowners": ["@Lash-L", "@allenporter"],
|
||||
"config_flow": true,
|
||||
"dhcp": [
|
||||
{
|
||||
"macaddress": "249E7D*"
|
||||
},
|
||||
{
|
||||
"macaddress": "B04A39*"
|
||||
},
|
||||
{
|
||||
"hostname": "roborock-*"
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/roborock",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["roborock"],
|
||||
|
@ -34,9 +34,7 @@ rules:
|
||||
# Gold
|
||||
devices: done
|
||||
diagnostics: done
|
||||
discovery:
|
||||
status: todo
|
||||
comment: Determine if these devices can support discovery
|
||||
discovery: done
|
||||
discovery-update-info:
|
||||
status: exempt
|
||||
comment: Devices do not support discovery.
|
||||
|
12
homeassistant/generated/dhcp.py
generated
12
homeassistant/generated/dhcp.py
generated
@ -498,6 +498,18 @@ DHCP: Final[list[dict[str, str | bool]]] = [
|
||||
"hostname": "ring*",
|
||||
"macaddress": "341513*",
|
||||
},
|
||||
{
|
||||
"domain": "roborock",
|
||||
"macaddress": "249E7D*",
|
||||
},
|
||||
{
|
||||
"domain": "roborock",
|
||||
"macaddress": "B04A39*",
|
||||
},
|
||||
{
|
||||
"domain": "roborock",
|
||||
"hostname": "roborock-*",
|
||||
},
|
||||
{
|
||||
"domain": "roomba",
|
||||
"hostname": "irobot-*",
|
||||
|
@ -229,7 +229,13 @@ async def setup_entry(
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def cleanup_map_storage(
|
||||
async def cleanup_map_storage(cleanup_map_storage_manual) -> Generator[pathlib.Path]:
|
||||
"""Test cleanup, remove any map storage persisted during the test."""
|
||||
return cleanup_map_storage_manual
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def cleanup_map_storage_manual(
|
||||
hass: HomeAssistant, mock_roborock_entry: MockConfigEntry
|
||||
) -> Generator[pathlib.Path]:
|
||||
"""Test cleanup, remove any map storage persisted during the test."""
|
||||
|
@ -1120,10 +1120,10 @@ PROP = DeviceProp(
|
||||
)
|
||||
|
||||
NETWORK_INFO = NetworkInfo(
|
||||
ip="123.232.12.1", ssid="wifi", mac="ac:cc:cc:cc:cc", bssid="bssid", rssi=90
|
||||
ip="123.232.12.1", ssid="wifi", mac="ac:cc:cc:cc:cc:cc", bssid="bssid", rssi=90
|
||||
)
|
||||
NETWORK_INFO_2 = NetworkInfo(
|
||||
ip="123.232.12.2", ssid="wifi", mac="ac:cc:cc:cc:cd", bssid="bssid", rssi=90
|
||||
ip="123.232.12.2", ssid="wifi", mac="ac:cc:cc:cc:cd:cc", bssid="bssid", rssi=90
|
||||
)
|
||||
|
||||
MULTI_MAP_LIST = MultiMapsList.from_dict(
|
||||
|
@ -19,8 +19,9 @@ from homeassistant.components.roborock.const import CONF_ENTRY_CODE, DOMAIN, DRA
|
||||
from homeassistant.const import CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
|
||||
from .mock_data import MOCK_CONFIG, USER_DATA, USER_EMAIL
|
||||
from .mock_data import MOCK_CONFIG, NETWORK_INFO, USER_DATA, USER_EMAIL
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -281,3 +282,68 @@ async def test_account_already_configured(
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured_account"
|
||||
|
||||
|
||||
async def test_discovery_not_setup(
|
||||
hass: HomeAssistant,
|
||||
bypass_api_fixture,
|
||||
) -> None:
|
||||
"""Handle the config flow and make sure it succeeds."""
|
||||
with (
|
||||
patch("homeassistant.components.roborock.async_setup_entry", return_value=True),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_DHCP},
|
||||
data=DhcpServiceInfo(
|
||||
ip=NETWORK_INFO.ip,
|
||||
macaddress=NETWORK_INFO.mac.replace(":", ""),
|
||||
hostname="roborock-vacuum-a72",
|
||||
),
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
with patch(
|
||||
"homeassistant.components.roborock.config_flow.RoborockApiClient.request_code"
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {CONF_USERNAME: USER_EMAIL}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "code"
|
||||
assert result["errors"] == {}
|
||||
with patch(
|
||||
"homeassistant.components.roborock.config_flow.RoborockApiClient.code_login",
|
||||
return_value=USER_DATA,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_ENTRY_CODE: "123456"}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == USER_EMAIL
|
||||
assert result["data"] == MOCK_CONFIG
|
||||
assert result["result"]
|
||||
|
||||
|
||||
async def test_discovery_already_setup(
|
||||
hass: HomeAssistant,
|
||||
bypass_api_fixture,
|
||||
mock_roborock_entry: MockConfigEntry,
|
||||
cleanup_map_storage_manual,
|
||||
) -> None:
|
||||
"""Handle aborting if the device is already setup."""
|
||||
await hass.config_entries.async_setup(mock_roborock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_DHCP},
|
||||
data=DhcpServiceInfo(
|
||||
ip=NETWORK_INFO.ip,
|
||||
macaddress=NETWORK_INFO.mac.replace(":", ""),
|
||||
hostname="roborock-vacuum-a72",
|
||||
),
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
|
Loading…
x
Reference in New Issue
Block a user