diff --git a/homeassistant/components/onewire/config_flow.py b/homeassistant/components/onewire/config_flow.py index b9f6ba77c2e..9ab8dc32f68 100644 --- a/homeassistant/components/onewire/config_flow.py +++ b/homeassistant/components/onewire/config_flow.py @@ -13,6 +13,7 @@ from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import config_validation as cv, device_registry as dr from homeassistant.helpers.device_registry import DeviceEntry +from homeassistant.helpers.service_info.hassio import HassioServiceInfo from .const import ( DEFAULT_HOST, @@ -51,6 +52,7 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN): """Handle 1-Wire config flow.""" VERSION = 1 + _discovery_data: dict[str, Any] async def async_step_user( self, user_input: dict[str, Any] | None = None @@ -100,6 +102,40 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN): errors=errors, ) + async def async_step_hassio( + self, discovery_info: HassioServiceInfo + ) -> ConfigFlowResult: + """Handle hassio discovery.""" + await self._async_handle_discovery_without_unique_id() + + self._discovery_data = { + "title": discovery_info.config["addon"], + CONF_HOST: discovery_info.config[CONF_HOST], + CONF_PORT: discovery_info.config[CONF_PORT], + } + return await self.async_step_discovery_confirm() + + async def async_step_discovery_confirm( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Confirm discovery.""" + errors: dict[str, str] = {} + if user_input is not None: + data = { + CONF_HOST: self._discovery_data[CONF_HOST], + CONF_PORT: self._discovery_data[CONF_PORT], + } + await validate_input(self.hass, data, errors) + if not errors: + return self.async_create_entry( + title=self._discovery_data["title"], data=data + ) + + return self.async_show_form( + step_id="discovery_confirm", + errors=errors, + ) + @staticmethod @callback def async_get_options_flow( diff --git a/homeassistant/components/onewire/quality_scale.yaml b/homeassistant/components/onewire/quality_scale.yaml index 9e706c16607..b64bfb775ce 100644 --- a/homeassistant/components/onewire/quality_scale.yaml +++ b/homeassistant/components/onewire/quality_scale.yaml @@ -66,8 +66,10 @@ rules: entity-category: done entity-disabled-by-default: done discovery: - status: todo - comment: mDNS should be possible - https://owfs.org/index_php_page_avahi-discovery.html + status: done + comment: | + hassio discovery implemented, mDNS/zeroconf should also be possible + https://owfs.org/index_php_page_avahi-discovery.html (see PR 135295) stale-devices: status: done comment: > diff --git a/tests/components/onewire/test_config_flow.py b/tests/components/onewire/test_config_flow.py index 0c7daf2aeff..09a7cdfcbb0 100644 --- a/tests/components/onewire/test_config_flow.py +++ b/tests/components/onewire/test_config_flow.py @@ -11,14 +11,22 @@ from homeassistant.components.onewire.const import ( INPUT_ENTRY_DEVICE_SELECTION, MANUFACTURER_MAXIM, ) -from homeassistant.config_entries import SOURCE_USER +from homeassistant.config_entries import SOURCE_HASSIO, SOURCE_USER from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType from homeassistant.helpers import device_registry as dr +from homeassistant.helpers.service_info.hassio import HassioServiceInfo from tests.common import MockConfigEntry +_HASSIO_DISCOVERY = HassioServiceInfo( + config={"host": "1302b8e0-owserver", "port": 4304, "addon": "owserver (1-wire)"}, + name="owserver (1-wire)", + slug="1302b8e0_owserver", + uuid="e3fa56560d93458b96a594cbcea3017e", +) + pytestmark = pytest.mark.usefixtures("mock_setup_entry") @@ -190,6 +198,58 @@ async def test_reconfigure_duplicate( assert other_config_entry.data == {CONF_HOST: "2.3.4.5", CONF_PORT: 2345} +async def test_hassio_flow(hass: HomeAssistant) -> None: + """Test HassIO discovery flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_HASSIO}, + data=_HASSIO_DISCOVERY, + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "discovery_confirm" + assert not result["errors"] + + # Cannot connect to server => retry + with patch( + "homeassistant.components.onewire.onewirehub.protocol.proxy", + side_effect=protocol.ConnError, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={}, + ) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "discovery_confirm" + assert result["errors"] == {"base": "cannot_connect"} + + # Connect OK + with patch( + "homeassistant.components.onewire.onewirehub.protocol.proxy", + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={}, + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + new_entry = result["result"] + assert new_entry.title == "owserver (1-wire)" + assert new_entry.data == {CONF_HOST: "1302b8e0-owserver", CONF_PORT: 4304} + + +@pytest.mark.usefixtures("config_entry") +async def test_hassio_duplicate(hass: HomeAssistant) -> None: + """Test HassIO discovery duplicate flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_HASSIO}, + data=_HASSIO_DISCOVERY, + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + + @pytest.mark.usefixtures("filled_device_registry") async def test_user_options_clear( hass: HomeAssistant, config_entry: MockConfigEntry