1 """Config flow for Matter integration."""
3 from __future__
import annotations
8 from matter_server.client
import MatterClient
9 from matter_server.client.exceptions
import CannotConnect, InvalidServerVersion
10 import voluptuous
as vol
29 from .addon
import get_addon_manager
32 CONF_INTEGRATION_CREATED_ADDON,
38 ADDON_SETUP_TIMEOUT = 5
39 ADDON_SETUP_TIMEOUT_ROUNDS = 40
40 DEFAULT_URL =
"ws://localhost:5580/ws"
41 DEFAULT_TITLE =
"Matter"
42 ON_SUPERVISOR_SCHEMA = vol.Schema({vol.Optional(CONF_USE_ADDON, default=
True): bool})
46 """Return a schema for the manual step."""
47 default_url = user_input.get(CONF_URL, DEFAULT_URL)
48 return vol.Schema({vol.Required(CONF_URL, default=default_url): str})
52 """Validate the user input allows us to connect."""
53 client = MatterClient(data[CONF_URL], aiohttp_client.async_get_clientsession(hass))
54 await client.connect()
58 """Return the websocket address."""
59 return f
"ws://{host}:{port}/ws"
63 """Handle a config flow for Matter."""
68 """Set up flow instance."""
73 self.
install_taskinstall_task: asyncio.Task |
None =
None
74 self.
start_taskstart_task: asyncio.Task |
None =
None
78 self, user_input: dict[str, Any] |
None =
None
79 ) -> ConfigFlowResult:
80 """Install Matter Server add-on."""
86 step_id=
"install_addon",
87 progress_action=
"install_addon",
93 except AddonError
as err:
108 self, user_input: dict[str, Any] |
None =
None
109 ) -> ConfigFlowResult:
110 """Add-on installation failed."""
114 """Install the Matter Server add-on."""
116 await addon_manager.async_schedule_install_addon()
119 """Return add-on discovery info."""
122 discovery_info_config = await addon_manager.async_get_addon_discovery_info()
123 except AddonError
as err:
125 raise AbortFlow(
"addon_get_discovery_info_failed")
from err
127 return discovery_info_config
130 self, user_input: dict[str, Any] |
None =
None
131 ) -> ConfigFlowResult:
132 """Start Matter Server add-on."""
137 step_id=
"start_addon",
138 progress_action=
"start_addon",
144 except (FailedConnect, AddonError, AbortFlow)
as err:
157 self, user_input: dict[str, Any] |
None =
None
158 ) -> ConfigFlowResult:
159 """Add-on start failed."""
163 """Start the Matter Server add-on."""
166 await addon_manager.async_schedule_start_addon()
168 for _
in range(ADDON_SETUP_TIMEOUT_ROUNDS):
169 await asyncio.sleep(ADDON_SETUP_TIMEOUT)
171 if not (ws_address := self.
ws_addressws_address):
174 discovery_info[
"host"], discovery_info[
"port"]
177 except (AbortFlow, CannotConnect)
as err:
179 "Add-on not ready yet, waiting %s seconds: %s",
186 raise FailedConnect(
"Failed to start Matter Server add-on: timeout")
189 """Return Matter Server add-on info."""
192 addon_info: AddonInfo = await addon_manager.async_get_addon_info()
193 except AddonError
as err:
195 raise AbortFlow(
"addon_info_failed")
from err
200 self, user_input: dict[str, Any] |
None =
None
201 ) -> ConfigFlowResult:
202 """Handle the initial step."""
209 self, user_input: dict[str, Any] |
None =
None
210 ) -> ConfigFlowResult:
211 """Handle a manual configuration."""
212 if user_input
is None:
221 except CannotConnect:
222 errors[
"base"] =
"cannot_connect"
223 except InvalidServerVersion:
224 errors[
"base"] =
"invalid_server_version"
226 LOGGER.exception(
"Unexpected exception")
227 errors[
"base"] =
"unknown"
229 self.
ws_addressws_address = user_input[CONF_URL]
238 self, discovery_info: ZeroconfServiceInfo
239 ) -> ConfigFlowResult:
240 """Handle zeroconf discovery."""
245 user_input={CONF_USE_ADDON:
True}
250 self, discovery_info: HassioServiceInfo
251 ) -> ConfigFlowResult:
252 """Receive configuration from add-on discovery info.
254 This flow is triggered by the Matter Server add-on.
256 if discovery_info.slug != ADDON_SLUG:
262 discovery_info.config[
"host"], discovery_info.config[
"port"]
268 self, user_input: dict[str, Any] |
None =
None
269 ) -> ConfigFlowResult:
270 """Confirm the add-on discovery."""
271 if user_input
is not None:
273 user_input={CONF_USE_ADDON:
True}
279 self, user_input: dict[str, Any] |
None =
None
280 ) -> ConfigFlowResult:
281 """Handle logic when on Supervisor host."""
282 if user_input
is None:
284 step_id=
"on_supervisor", data_schema=ON_SUPERVISOR_SCHEMA
286 if not user_input[CONF_USE_ADDON]:
293 if addon_info.state == AddonState.RUNNING:
296 if addon_info.state == AddonState.NOT_RUNNING:
302 self, user_input: dict[str, Any] |
None =
None
303 ) -> ConfigFlowResult:
304 """Prepare info needed to complete the config entry."""
308 discovery_info[
"host"], discovery_info[
"port"]
313 except CannotConnect:
319 """Return a config entry for the flow or abort if already configured."""
323 config_entry = existing_config_entries[0]
324 self.hass.config_entries.async_update_entry(
334 await self.hass.config_entries.async_reload(config_entry.entry_id)
335 raise AbortFlow(
"reconfiguration_successful")
339 self.hass.config_entries.flow.async_abort(progress[
"flow_id"])
352 """Failed to connect to the Matter Server."""
ConfigFlowResult async_step_hassio(self, HassioServiceInfo discovery_info)
ConfigFlowResult async_step_zeroconf(self, ZeroconfServiceInfo discovery_info)
None _async_install_addon(self)
dict _async_get_addon_discovery_info(self)
AddonInfo _async_get_addon_info(self)
None _async_start_addon(self)
ConfigFlowResult async_step_install_failed(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_install_addon(self, dict[str, Any]|None user_input=None)
integration_created_addon
ConfigFlowResult async_step_finish_addon_setup(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_start_failed(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_manual(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_on_supervisor(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_hassio_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_start_addon(self, dict[str, Any]|None user_input=None)
ConfigFlowResult _async_create_entry_or_abort(self)
None _async_handle_discovery_without_unique_id(self)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=None)
list[ConfigFlowResult] _async_in_progress(self, bool include_uninitialized=False, dict[str, Any]|None match_context=None)
ConfigFlowResult _async_step_discovery_without_unique_id(self)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_progress(self, *str|None step_id=None, str progress_action, Mapping[str, str]|None description_placeholders=None, asyncio.Task[Any]|None progress_task=None)
_FlowResultT async_show_progress_done(self, *str next_step_id)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
bool is_hassio(HomeAssistant hass)
str build_ws_address(str host, int port)
None validate_input(HomeAssistant hass, dict[str, Any] data)
vol.Schema get_manual_schema(dict[str, Any] user_input)
bool async_is_onboarded(HomeAssistant hass)
AddonManager get_addon_manager(HomeAssistant hass, str slug)