|
1 | | -"""Config flow to setup component.""" |
2 | | - |
3 | 1 | import logging |
4 | | - |
5 | 2 | import voluptuous as vol |
| 3 | +import asyncio |
| 4 | +from homeassistant import config_entries, exceptions |
| 5 | +from homeassistant.core import callback |
6 | 6 |
|
7 | | -from homeassistant.config_entries import CONN_CLASS_LOCAL_POLL, ConfigFlow |
8 | | -from homeassistant.exceptions import HomeAssistantError |
9 | | - |
10 | | -from . import APsystemsECUProxyInvalidData |
11 | 7 | from .const import DOMAIN |
12 | 8 |
|
13 | 9 | _LOGGER = logging.getLogger(__name__) |
14 | 10 |
|
15 | | -# Schema contains name of host only |
16 | | -DATA_SCHEMA = vol.Schema({"host": str}) |
| 11 | +class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): |
| 12 | + VERSION = 1 |
| 13 | + CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH |
17 | 14 |
|
| 15 | + @staticmethod |
| 16 | + @callback |
| 17 | + def async_get_options_flow(config_entry): |
| 18 | + return OptionsFlowHandler(config_entry) |
18 | 19 |
|
19 | | -async def validate_input(data): |
20 | | - """Validate the user input allows us to connect.""" |
21 | | - _LOGGER.debug("step 1: validate_input from config_flow.py data = %s", data) |
22 | | - try: |
23 | | - pass |
24 | | - except APsystemsECUProxyInvalidData as err: |
25 | | - # raise friendly error after wrong input |
26 | | - raise CannotConnect from err |
27 | | - return {"title": "APsystems ECU Proxy"} |
| 20 | + async def async_step_user(self, user_input=None): |
| 21 | + schema = vol.Schema({ |
| 22 | + vol.Required("EMA host", default="3.67.1.32"): str, |
| 23 | + vol.Required("Message ignore age", default="1800"): str, |
| 24 | + vol.Required("Max stub interval", default="300"): str, |
| 25 | + vol.Required("No update timeout", default="600"): str, |
| 26 | + vol.Optional("Send to EMA", default=True): bool, |
| 27 | + }) |
28 | 28 |
|
| 29 | + if user_input is not None: |
| 30 | + ema_host = user_input["ema_host"] |
| 31 | + if await OptionsFlowHandler.validate_ip(ema_host): |
| 32 | + return self.async_create_entry(title="", data=user_input) |
| 33 | + else: |
| 34 | + return self.async_show_form( |
| 35 | + step_id="user", |
| 36 | + data_schema=schema, |
| 37 | + errors={"base": "Could not connect to the specified EMA host."}, |
| 38 | + ) |
29 | 39 |
|
30 | | -class DomainConfigFlow(ConfigFlow, domain=DOMAIN): |
31 | | - """Handle a config flow.""" |
| 40 | + return self.async_show_form(step_id="user", data_schema=schema) |
32 | 41 |
|
33 | | - VERSION = 1 |
34 | | - CONNECTION_CLASS = CONN_CLASS_LOCAL_POLL |
| 42 | +class OptionsFlowHandler(config_entries.OptionsFlow): |
| 43 | + def __init__(self, config_entry: config_entries.ConfigEntry) -> None: |
| 44 | + self.config_entry = config_entry |
| 45 | + |
| 46 | + async def async_step_init(self, user_input=None): |
| 47 | + current_options = self.config_entry.options or {} |
| 48 | + schema = vol.Schema({ |
| 49 | + vol.Optional("EMA host", default=current_options.get("ema_host", "3.67.1.32")): str, |
| 50 | + vol.Optional("Message ignore age", default=current_options.get("Message ignore age", "1800")): str, |
| 51 | + vol.Optional("Max stub interval", default=current_options.get("Max stub interval", "300")): str, |
| 52 | + vol.Optional("No update timeout", default=current_options.get("No update timeout", "600")): str, |
| 53 | + vol.Optional("Send to EMA", default=current_options.get("Send to EMA", True)): bool, |
| 54 | + }) |
35 | 55 |
|
36 | | - async def async_step_user(self, user_input=None): |
37 | | - """Handle the initial step.""" |
38 | | - errors = {} |
39 | | - # Validate user input |
40 | 56 | if user_input is not None: |
41 | | - try: |
42 | | - info = await validate_input(user_input) |
43 | | - return self.async_create_entry(title=info["title"], data=user_input) |
44 | | - except CannotConnect: |
45 | | - errors["base"] = "cannot_connect" |
46 | | - except Exception: # pylint: disable=broad-except |
47 | | - _LOGGER.exception("Unexpected exception") |
48 | | - errors["base"] = "unknown" |
| 57 | + ema_host = user_input["EMA host"] |
| 58 | + if await self.validate_ip(ema_host): |
| 59 | + updated_options = current_options.copy() |
| 60 | + updated_options.update(user_input) |
| 61 | + return self.async_create_entry(title="", data=updated_options) |
| 62 | + else: |
| 63 | + return self.async_show_form( |
| 64 | + step_id="init", |
| 65 | + data_schema=schema, |
| 66 | + errors={"base": "Could not connect to the specified EMA host."}, |
| 67 | + ) |
49 | 68 |
|
50 | | - return self.async_show_form( |
51 | | - step_id="user", data_schema=DATA_SCHEMA, errors=errors |
52 | | - ) |
| 69 | + return self.async_show_form(step_id="init", data_schema=schema) |
53 | 70 |
|
| 71 | + @staticmethod |
| 72 | + async def validate_ip(ip_address: str) -> bool: |
| 73 | + try: |
| 74 | + await asyncio.wait_for(asyncio.open_connection(ip_address, 8995), timeout=5.0) |
| 75 | + return True |
| 76 | + except (OSError, asyncio.TimeoutError): |
| 77 | + return False |
54 | 78 |
|
55 | | -class CannotConnect(HomeAssistantError): |
| 79 | +class CannotConnect(exceptions.HomeAssistantError): |
56 | 80 | """Error to indicate we cannot connect.""" |
0 commit comments