1 """Config flow for Nibe Heat Pump integration."""
3 from __future__
import annotations
7 from nibe.connection.modbus
import Modbus
8 from nibe.connection.nibegw
import NibeGW
9 from nibe.exceptions
import (
10 AddressInUseException,
11 CoilNotFoundException,
12 CoilWriteSendException,
17 from nibe.heatpump
import HeatPump, Model
18 import voluptuous
as vol
28 CONF_CONNECTION_TYPE_MODBUS,
29 CONF_CONNECTION_TYPE_NIBEGW,
33 CONF_REMOTE_READ_PORT,
34 CONF_REMOTE_WRITE_PORT,
40 PORT_SELECTOR = vol.All(
41 selector.NumberSelector(
42 selector.NumberSelectorConfig(
43 min=1, step=1, max=65535, mode=selector.NumberSelectorMode.BOX
49 STEP_NIBEGW_DATA_SCHEMA = vol.Schema(
51 vol.Required(CONF_MODEL): vol.In(
list(Model.__members__)),
52 vol.Required(CONF_IP_ADDRESS): selector.TextSelector(),
53 vol.Required(CONF_LISTENING_PORT, default=9999): PORT_SELECTOR,
54 vol.Required(CONF_REMOTE_READ_PORT, default=9999): PORT_SELECTOR,
55 vol.Required(CONF_REMOTE_WRITE_PORT, default=10000): PORT_SELECTOR,
60 STEP_MODBUS_DATA_SCHEMA = vol.Schema(
62 vol.Required(CONF_MODEL): vol.In(
list(Model.__members__)),
63 vol.Required(CONF_MODBUS_URL): selector.TextSelector(),
64 vol.Required(CONF_MODBUS_UNIT, default=0): vol.All(
65 selector.NumberSelector(
66 selector.NumberSelectorConfig(
67 min=0, step=1, mode=selector.NumberSelectorMode.BOX
77 """Field with invalid data."""
79 def __init__(self, message: str, field: str, error: str) ->
None:
87 hass: HomeAssistant, data: dict[str, Any]
88 ) -> tuple[str, dict[str, Any]]:
89 """Validate the user input allows us to connect."""
91 heatpump = HeatPump(Model[data[CONF_MODEL]])
92 heatpump.word_swap =
True
93 await heatpump.initialize()
97 data[CONF_IP_ADDRESS],
98 data[CONF_REMOTE_READ_PORT],
99 data[CONF_REMOTE_WRITE_PORT],
100 listening_port=data[CONF_LISTENING_PORT],
104 await connection.start()
105 except AddressInUseException
as exception:
107 "Address already in use",
"listening_port",
"address_in_use"
111 await connection.verify_connectivity()
112 except (ReadSendException, CoilWriteSendException)
as exception:
113 raise FieldError(
str(exception), CONF_IP_ADDRESS,
"address")
from exception
114 except CoilNotFoundException
as exception:
115 raise FieldError(
"Coils not found",
"base",
"model")
from exception
116 except ReadException
as exception:
117 raise FieldError(
"Timeout on read from pump",
"base",
"read")
from exception
118 except WriteException
as exception:
119 raise FieldError(
"Timeout on writing to pump",
"base",
"write")
from exception
121 await connection.stop()
123 return f
"{data[CONF_MODEL]} at {data[CONF_IP_ADDRESS]}", {
125 CONF_WORD_SWAP: heatpump.word_swap,
126 CONF_CONNECTION_TYPE: CONF_CONNECTION_TYPE_NIBEGW,
131 hass: HomeAssistant, data: dict[str, Any]
132 ) -> tuple[str, dict[str, Any]]:
133 """Validate the user input allows us to connect."""
135 heatpump = HeatPump(Model[data[CONF_MODEL]])
136 await heatpump.initialize()
141 data[CONF_MODBUS_URL],
142 data[CONF_MODBUS_UNIT],
144 except ValueError
as exc:
145 raise FieldError(
"Not a valid modbus url", CONF_MODBUS_URL,
"url")
from exc
147 await connection.start()
150 await connection.verify_connectivity()
151 except (ReadSendException, CoilWriteSendException)
as exception:
152 raise FieldError(
str(exception), CONF_MODBUS_URL,
"address")
from exception
153 except CoilNotFoundException
as exception:
154 raise FieldError(
"Coils not found",
"base",
"model")
from exception
155 except ReadException
as exception:
156 raise FieldError(
"Timeout on read from pump",
"base",
"read")
from exception
157 except WriteException
as exception:
158 raise FieldError(
"Timeout on writing to pump",
"base",
"write")
from exception
160 await connection.stop()
162 host = yarl.URL(data[CONF_MODBUS_URL]).host
163 return f
"{data[CONF_MODEL]} at {host}", {
165 CONF_CONNECTION_TYPE: CONF_CONNECTION_TYPE_MODBUS,
170 """Handle a config flow for Nibe Heat Pump."""
175 self, user_input: dict[str, Any] |
None =
None
176 ) -> ConfigFlowResult:
177 """Handle the initial step."""
178 return self.
async_show_menuasync_show_menu(step_id=
"user", menu_options=[
"modbus",
"nibegw"])
181 self, user_input: dict[str, Any] |
None =
None
182 ) -> ConfigFlowResult:
183 """Handle the modbus step."""
184 if user_input
is None:
186 step_id=
"modbus", data_schema=STEP_MODBUS_DATA_SCHEMA
193 except FieldError
as exception:
194 LOGGER.debug(
"Validation error %s", exception)
195 errors[exception.field] = exception.error
197 LOGGER.exception(
"Unexpected exception")
198 errors[
"base"] =
"unknown"
203 step_id=
"modbus", data_schema=STEP_MODBUS_DATA_SCHEMA, errors=errors
207 self, user_input: dict[str, Any] |
None =
None
208 ) -> ConfigFlowResult:
209 """Handle the nibegw step."""
210 if user_input
is None:
212 step_id=
"nibegw", data_schema=STEP_NIBEGW_DATA_SCHEMA
219 except FieldError
as exception:
220 LOGGER.exception(
"Validation error")
221 errors[exception.field] = exception.error
223 LOGGER.exception(
"Unexpected exception")
224 errors[
"base"] =
"unknown"
229 step_id=
"nibegw", data_schema=STEP_NIBEGW_DATA_SCHEMA, errors=errors
None __init__(self, str message, str field, str error)
ConfigFlowResult async_step_modbus(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_nibegw(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
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_show_menu(self, *str|None step_id=None, Container[str] menu_options, Mapping[str, str]|None description_placeholders=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)
tuple[str, dict[str, Any]] validate_nibegw_input(HomeAssistant hass, dict[str, Any] data)
tuple[str, dict[str, Any]] validate_modbus_input(HomeAssistant hass, dict[str, Any] data)