"""Config flow for Modbus RTU Monitor integration.""" from __future__ import annotations import asyncio import logging from typing import Any import voluptuous as vol from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_HOST, CONF_PORT import homeassistant.helpers.config_validation as cv from .const import DEFAULT_PORT, DOMAIN _LOGGER = logging.getLogger(__name__) class ModbusRTUMonitorConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for Modbus RTU Monitor.""" VERSION = 1 MINOR_VERSION = 1 async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle the initial step.""" errors: dict[str, str] = {} if user_input is not None: # Validate connection by attempting to connect try: await self._test_connection( user_input[CONF_HOST], user_input[CONF_PORT], ) except asyncio.TimeoutError: errors["base"] = "cannot_connect" except Exception: _LOGGER.exception("Unexpected exception during connection test") errors["base"] = "unknown" else: # Prevent duplicate entries for same host:port self._async_abort_entries_match( { CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT], } ) title = f"Modbus RTU Monitor ({user_input[CONF_HOST]}:{user_input[CONF_PORT]})" return self.async_create_entry(title=title, data=user_input) data_schema = vol.Schema( { vol.Required(CONF_HOST): str, vol.Required(CONF_PORT, default=DEFAULT_PORT): cv.port, } ) return self.async_show_form( step_id="user", data_schema=data_schema, errors=errors, ) async def _test_connection(self, host: str, port: int) -> None: """Test TCP connection to Modbus gateway.""" reader, writer = await asyncio.wait_for( asyncio.open_connection(host, port), timeout=5.0, ) writer.close() await writer.wait_closed()