1 """Config flow for Landis+Gyr Heat Meter integration."""
3 from __future__
import annotations
10 from serial.tools
import list_ports
12 import voluptuous
as vol
20 from .const
import DOMAIN, ULTRAHEAT_TIMEOUT
22 _LOGGER = logging.getLogger(__name__)
24 CONF_MANUAL_PATH =
"Enter Manually"
26 STEP_USER_DATA_SCHEMA = vol.Schema(
28 vol.Required(CONF_DEVICE): str,
34 """Handle a config flow for Ultraheat Heat Meter."""
39 self, user_input: dict[str, Any] |
None =
None
40 ) -> ConfigFlowResult:
41 """Step when setting up serial configuration."""
44 if user_input
is not None:
45 if user_input[CONF_DEVICE] == CONF_MANUAL_PATH:
48 dev_path = await self.hass.async_add_executor_job(
49 usb.get_serial_by_id, user_input[CONF_DEVICE]
51 _LOGGER.debug(
"Using this path : %s", dev_path)
56 errors[
"base"] =
"cannot_connect"
59 ports[CONF_MANUAL_PATH] = CONF_MANUAL_PATH
61 schema = vol.Schema({vol.Required(CONF_DEVICE): vol.In(ports)})
65 self, user_input: dict[str, Any] |
None =
None
66 ) -> ConfigFlowResult:
67 """Set path manually."""
70 if user_input
is not None:
71 dev_path = user_input[CONF_DEVICE]
75 errors[
"base"] =
"cannot_connect"
77 schema = vol.Schema({vol.Required(CONF_DEVICE): str})
79 step_id=
"setup_serial_manual_path",
85 """Try to connect to the device path and return an entry."""
88 _LOGGER.debug(
"Got model %s and device_number %s", model, device_number)
92 CONF_DEVICE: dev_path,
94 "device_number": device_number,
102 """Validate the user input allows us to connect."""
104 reader = ultraheat_api.UltraheatReader(port)
105 heat_meter = ultraheat_api.HeatMeterService(reader)
107 async
with asyncio.timeout(ULTRAHEAT_TIMEOUT):
109 data = await self.hass.async_add_executor_job(heat_meter.read)
111 except (TimeoutError, serial.SerialException)
as err:
112 _LOGGER.warning(
"Failed read data from: %s. %s", port, err)
113 raise CannotConnect(f
"Error communicating with device: {err}")
from err
115 _LOGGER.debug(
"Successfully connected to %s. Got data: %s", port, data)
116 return data.model, data.device_number
120 """Return a dict of USB ports and their friendly names."""
121 ports = await hass.async_add_executor_job(list_ports.comports)
122 port_descriptions = {}
127 usb_device = usb.usb_device_from_port(port)
128 dev_path = usb.get_serial_by_id(usb_device.device)
129 human_name = usb.human_readable_device_name(
131 usb_device.serial_number,
132 usb_device.manufacturer,
133 usb_device.description,
137 port_descriptions[dev_path] = human_name
139 return port_descriptions
143 """Error to indicate we cannot connect."""
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
def validate_and_create_entry(self, dev_path)
tuple[str, str] validate_ultraheat(self, str port)
ConfigFlowResult async_step_setup_serial_manual_path(self, dict[str, Any]|None user_input=None)
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
ConfigEntry|None async_set_unique_id(self, str|None unique_id=None, *bool raise_on_progress=True)
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)
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_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
dict[str, str] get_usb_ports(HomeAssistant hass)