1 """Config flow for konnected.io integration."""
3 from __future__
import annotations
10 from typing
import Any
11 from urllib.parse
import urlparse
13 import voluptuous
as vol
17 DEVICE_CLASSES_SCHEMA,
18 BinarySensorDeviceClass,
58 from .errors
import CannotConnect
59 from .panel
import KONN_MODEL, KONN_MODEL_PRO, get_status
61 _LOGGER = logging.getLogger(__name__)
63 ATTR_KONN_UPNP_MODEL_NAME =
"model_name"
65 CONF_IO_DIS =
"Disabled"
66 CONF_IO_BIN =
"Binary Sensor"
67 CONF_IO_DIG =
"Digital Sensor"
68 CONF_IO_SWI =
"Switchable Output"
70 CONF_MORE_STATES =
"more_states"
74 CONF_OVERRIDE_API_HOST =
"override_api_host"
76 KONN_MANUFACTURER =
"konnected.io"
77 KONN_PANEL_MODEL_NAMES = {
78 KONN_MODEL:
"Konnected Alarm Panel",
79 KONN_MODEL_PRO:
"Konnected Alarm Panel Pro",
82 OPTIONS_IO_ANY = vol.In([CONF_IO_DIS, CONF_IO_BIN, CONF_IO_DIG, CONF_IO_SWI])
83 OPTIONS_IO_INPUT_ONLY = vol.In([CONF_IO_DIS, CONF_IO_BIN])
84 OPTIONS_IO_OUTPUT_ONLY = vol.In([CONF_IO_DIS, CONF_IO_SWI])
88 IO_SCHEMA = vol.Schema(
90 vol.Optional(
"1", default=CONF_IO_DIS): OPTIONS_IO_ANY,
91 vol.Optional(
"2", default=CONF_IO_DIS): OPTIONS_IO_ANY,
92 vol.Optional(
"3", default=CONF_IO_DIS): OPTIONS_IO_ANY,
93 vol.Optional(
"4", default=CONF_IO_DIS): OPTIONS_IO_ANY,
94 vol.Optional(
"5", default=CONF_IO_DIS): OPTIONS_IO_ANY,
95 vol.Optional(
"6", default=CONF_IO_DIS): OPTIONS_IO_ANY,
96 vol.Optional(
"7", default=CONF_IO_DIS): OPTIONS_IO_ANY,
97 vol.Optional(
"8", default=CONF_IO_DIS): OPTIONS_IO_ANY,
98 vol.Optional(
"9", default=CONF_IO_DIS): OPTIONS_IO_INPUT_ONLY,
99 vol.Optional(
"10", default=CONF_IO_DIS): OPTIONS_IO_INPUT_ONLY,
100 vol.Optional(
"11", default=CONF_IO_DIS): OPTIONS_IO_INPUT_ONLY,
101 vol.Optional(
"12", default=CONF_IO_DIS): OPTIONS_IO_INPUT_ONLY,
102 vol.Optional(
"out", default=CONF_IO_DIS): OPTIONS_IO_OUTPUT_ONLY,
103 vol.Optional(
"alarm1", default=CONF_IO_DIS): OPTIONS_IO_OUTPUT_ONLY,
104 vol.Optional(
"out1", default=CONF_IO_DIS): OPTIONS_IO_OUTPUT_ONLY,
105 vol.Optional(
"alarm2_out2", default=CONF_IO_DIS): OPTIONS_IO_OUTPUT_ONLY,
109 BINARY_SENSOR_SCHEMA = vol.Schema(
111 vol.Required(CONF_ZONE): vol.In(ZONES),
113 CONF_TYPE, default=BinarySensorDeviceClass.DOOR
114 ): DEVICE_CLASSES_SCHEMA,
115 vol.Optional(CONF_NAME): cv.string,
116 vol.Optional(CONF_INVERSE, default=
False): cv.boolean,
120 SENSOR_SCHEMA = vol.Schema(
122 vol.Required(CONF_ZONE): vol.In(ZONES),
123 vol.Required(CONF_TYPE, default=
"dht"): vol.All(
124 vol.Lower, vol.In([
"dht",
"ds18b20"])
126 vol.Optional(CONF_NAME): cv.string,
127 vol.Optional(CONF_POLL_INTERVAL, default=3): vol.All(
128 vol.Coerce(int), vol.Range(min=1)
133 SWITCH_SCHEMA = vol.Schema(
135 vol.Required(CONF_ZONE): vol.In(ZONES),
136 vol.Optional(CONF_NAME): cv.string,
137 vol.Optional(CONF_ACTIVATION, default=STATE_HIGH): vol.All(
138 vol.Lower, vol.In([STATE_HIGH, STATE_LOW])
140 vol.Optional(CONF_MOMENTARY): vol.All(vol.Coerce(int), vol.Range(min=10)),
141 vol.Optional(CONF_PAUSE): vol.All(vol.Coerce(int), vol.Range(min=10)),
142 vol.Optional(CONF_REPEAT): vol.All(vol.Coerce(int), vol.Range(min=-1)),
146 OPTIONS_SCHEMA = vol.Schema(
148 vol.Required(CONF_IO): IO_SCHEMA,
149 vol.Optional(CONF_BINARY_SENSORS): vol.All(
150 cv.ensure_list, [BINARY_SENSOR_SCHEMA]
152 vol.Optional(CONF_SENSORS): vol.All(cv.ensure_list, [SENSOR_SCHEMA]),
153 vol.Optional(CONF_SWITCHES): vol.All(cv.ensure_list, [SWITCH_SCHEMA]),
154 vol.Optional(CONF_BLINK, default=
True): cv.boolean,
155 vol.Optional(CONF_API_HOST, default=
""): vol.Any(
"", cv.url),
156 vol.Optional(CONF_DISCOVERY, default=
True): cv.boolean,
158 extra=vol.REMOVE_EXTRA,
161 CONFIG_ENTRY_SCHEMA = vol.Schema(
163 vol.Required(CONF_ID): cv.matches_regex(
"[0-9a-f]{12}"),
164 vol.Required(CONF_HOST): cv.string,
165 vol.Required(CONF_PORT): cv.port,
166 vol.Required(CONF_MODEL): vol.Any(*KONN_PANEL_MODEL_NAMES),
167 vol.Required(CONF_ACCESS_TOKEN): cv.matches_regex(
"[a-zA-Z0-9]+"),
168 vol.Required(CONF_DEFAULT_OPTIONS): OPTIONS_SCHEMA,
170 extra=vol.REMOVE_EXTRA,
175 """Handle a config flow for Konnected Panels."""
180 DISCOVERED_HOSTS: dict[str, dict[str, Any]] = {}
185 """Initialize the Konnected flow."""
186 self.data: dict[str, Any] = {}
190 """Populate self.data based on panel status.
192 This will raise CannotConnect if an error occurs
194 self.data[CONF_HOST] = host
195 self.data[CONF_PORT] = port
197 status = await
get_status(self.hass, host, port)
198 self.data[CONF_ID] = status.get(
"chipId", status[
"mac"].replace(
":",
""))
199 except (CannotConnect, KeyError)
as err:
200 raise CannotConnect
from err
202 self.data[CONF_MODEL] = status.get(
"model", KONN_MODEL)
203 self.data[CONF_ACCESS_TOKEN] =
"".join(
204 random.choices(f
"{string.ascii_uppercase}{string.digits}", k=20)
208 """Import a configuration.yaml config.
210 This flow is triggered by `async_setup` for configured panels.
212 _LOGGER.debug(import_data)
216 self.
optionsoptions = import_data[CONF_DEFAULT_OPTIONS]
219 if import_data.get(CONF_HOST):
223 CONF_HOST: import_data[CONF_HOST],
224 CONF_PORT: import_data[CONF_PORT],
233 self, user_input: dict[str, Any] |
None =
None
234 ) -> ConfigFlowResult:
235 """Confirm the user wants to import the config entry."""
236 if user_input
is None:
238 step_id=
"import_confirm",
239 description_placeholders={
"id": self.
unique_idunique_id},
243 if KonnectedFlowHandler.DISCOVERED_HOSTS.get(self.
unique_idunique_id):
246 CONF_HOST: KonnectedFlowHandler.DISCOVERED_HOSTS[self.
unique_idunique_id][
249 CONF_PORT: KonnectedFlowHandler.DISCOVERED_HOSTS[self.
unique_idunique_id][
257 self, discovery_info: ssdp.SsdpServiceInfo
258 ) -> ConfigFlowResult:
259 """Handle a discovered konnected panel.
261 This flow is triggered by the SSDP component. It will check if the
262 device is already configured and attempt to finish the config if not.
264 _LOGGER.debug(discovery_info)
267 if discovery_info.upnp[ssdp.ATTR_UPNP_MANUFACTURER] != KONN_MANUFACTURER:
271 name
in discovery_info.upnp[ssdp.ATTR_UPNP_MODEL_NAME]
272 for name
in KONN_PANEL_MODEL_NAMES
275 "Discovered unrecognized Konnected device %s",
276 discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NAME,
"Unknown"),
283 _LOGGER.error(
"Malformed Konnected SSDP info")
286 assert discovery_info.ssdp_location
287 netloc = urlparse(discovery_info.ssdp_location).netloc.split(
":")
289 {CONF_HOST: netloc[0], CONF_PORT:
int(netloc[1])}
293 status = await
get_status(self.hass, netloc[0],
int(netloc[1]))
294 except CannotConnect:
297 self.data[CONF_HOST] = netloc[0]
298 self.data[CONF_PORT] =
int(netloc[1])
299 self.data[CONF_ID] = status.get(
"chipId", status[
"mac"].replace(
":",
""))
300 self.data[CONF_MODEL] = status.get(
"model", KONN_MODEL)
302 KonnectedFlowHandler.DISCOVERED_HOSTS[self.data[CONF_ID]] = {
303 CONF_HOST: self.data[CONF_HOST],
304 CONF_PORT: self.data[CONF_PORT],
311 self, user_input: dict[str, Any] |
None =
None
312 ) -> ConfigFlowResult:
313 """Connect to panel and get config."""
317 self.data[CONF_HOST] = user_input[CONF_HOST]
318 self.data[CONF_PORT] = user_input[CONF_PORT]
321 await asyncio.sleep(0.1)
324 self.hass, self.data[CONF_HOST], self.data[CONF_PORT]
326 except CannotConnect:
327 errors[
"base"] =
"cannot_connect"
329 self.data[CONF_ID] = status.get(
330 "chipId", status[
"mac"].replace(
":",
"")
332 self.data[CONF_MODEL] = status.get(
"model", KONN_MODEL)
335 KonnectedFlowHandler.DISCOVERED_HOSTS[self.data[CONF_ID]] = {
336 CONF_HOST: self.data[CONF_HOST],
337 CONF_PORT: self.data[CONF_PORT],
343 description_placeholders={
344 "host": self.data.
get(CONF_HOST,
"Unknown"),
345 "port": self.data.
get(CONF_PORT,
"Unknown"),
347 data_schema=vol.Schema(
349 vol.Required(CONF_HOST, default=self.data.
get(CONF_HOST)): str,
350 vol.Required(CONF_PORT, default=self.data.
get(CONF_PORT)): int,
357 self, user_input: dict[str, Any] |
None =
None
358 ) -> ConfigFlowResult:
359 """Attempt to link with the Konnected panel.
361 Given a configured host, will ask the user to confirm and finalize
364 if user_input
is None:
368 updates=self.data, reload_on_update=
False
372 description_placeholders={
373 "model": KONN_PANEL_MODEL_NAMES[self.data[CONF_MODEL]],
375 "host": self.data[CONF_HOST],
376 "port": self.data[CONF_PORT],
381 self.data[CONF_DEFAULT_OPTIONS] = self.
optionsoptions
382 self.data[CONF_ACCESS_TOKEN] = self.hass.data.get(DOMAIN, {}).
get(
384 )
or "".join(random.choices(f
"{string.ascii_uppercase}{string.digits}", k=20))
387 title=KONN_PANEL_MODEL_NAMES[self.data[CONF_MODEL]],
394 config_entry: ConfigEntry,
395 ) -> OptionsFlowHandler:
396 """Return the Options Flow."""
401 """Handle a option flow for a Konnected Panel."""
403 def __init__(self, config_entry: ConfigEntry) ->
None:
404 """Initialize options flow."""
405 self.
modelmodel = config_entry.data[CONF_MODEL]
407 config_entry.options
or config_entry.data[CONF_DEFAULT_OPTIONS]
411 self.new_opt: dict[str, Any] = {CONF_IO: {}}
413 self.
io_cfgio_cfg: dict[str, Any] = {}
419 """Get the current zone config."""
424 if cfg[CONF_ZONE] == zone
430 self, user_input: dict[str, Any] |
None =
None
431 ) -> ConfigFlowResult:
432 """Handle options flow."""
436 self, user_input: dict[str, Any] |
None =
None
437 ) -> ConfigFlowResult:
438 """Configure legacy panel IO or first half of pro IO."""
439 errors: dict[str, str] = {}
442 if user_input
is not None:
444 for key, value
in user_input.items():
445 if value != CONF_IO_DIS:
446 self.new_opt[CONF_IO][key] = value
449 if self.
modelmodel == KONN_MODEL:
451 step_id=
"options_io",
452 data_schema=vol.Schema(
455 "1", default=current_io.get(
"1", CONF_IO_DIS)
458 "2", default=current_io.get(
"2", CONF_IO_DIS)
461 "3", default=current_io.get(
"3", CONF_IO_DIS)
464 "4", default=current_io.get(
"4", CONF_IO_DIS)
467 "5", default=current_io.get(
"5", CONF_IO_DIS)
470 "6", default=current_io.get(
"6", CONF_IO_DIS)
473 "out", default=current_io.get(
"out", CONF_IO_DIS)
474 ): OPTIONS_IO_OUTPUT_ONLY,
477 description_placeholders={
478 "model": KONN_PANEL_MODEL_NAMES[self.
modelmodel],
485 if self.
modelmodel == KONN_MODEL_PRO:
487 step_id=
"options_io",
488 data_schema=vol.Schema(
491 "1", default=current_io.get(
"1", CONF_IO_DIS)
494 "2", default=current_io.get(
"2", CONF_IO_DIS)
497 "3", default=current_io.get(
"3", CONF_IO_DIS)
500 "4", default=current_io.get(
"4", CONF_IO_DIS)
503 "5", default=current_io.get(
"5", CONF_IO_DIS)
506 "6", default=current_io.get(
"6", CONF_IO_DIS)
509 "7", default=current_io.get(
"7", CONF_IO_DIS)
513 description_placeholders={
514 "model": KONN_PANEL_MODEL_NAMES[self.
modelmodel],
520 return self.
async_abortasync_abort(reason=
"not_konn_panel")
523 self, user_input: dict[str, Any] |
None =
None
524 ) -> ConfigFlowResult:
525 """Allow the user to configure the extended IO for pro."""
526 errors: dict[str, str] = {}
529 if user_input
is not None:
531 for key, value
in user_input.items():
532 if value != CONF_IO_DIS:
533 self.new_opt[CONF_IO].
update({key: value})
534 self.
io_cfgio_cfg = copy.deepcopy(self.new_opt[CONF_IO])
537 if self.
modelmodel == KONN_MODEL:
538 self.
io_cfgio_cfg = copy.deepcopy(self.new_opt[CONF_IO])
541 if self.
modelmodel == KONN_MODEL_PRO:
543 step_id=
"options_io_ext",
544 data_schema=vol.Schema(
547 "8", default=current_io.get(
"8", CONF_IO_DIS)
550 "9", default=current_io.get(
"9", CONF_IO_DIS)
551 ): OPTIONS_IO_INPUT_ONLY,
553 "10", default=current_io.get(
"10", CONF_IO_DIS)
554 ): OPTIONS_IO_INPUT_ONLY,
556 "11", default=current_io.get(
"11", CONF_IO_DIS)
557 ): OPTIONS_IO_INPUT_ONLY,
559 "12", default=current_io.get(
"12", CONF_IO_DIS)
560 ): OPTIONS_IO_INPUT_ONLY,
562 "alarm1", default=current_io.get(
"alarm1", CONF_IO_DIS)
563 ): OPTIONS_IO_OUTPUT_ONLY,
565 "out1", default=current_io.get(
"out1", CONF_IO_DIS)
566 ): OPTIONS_IO_OUTPUT_ONLY,
569 default=current_io.get(
"alarm2_out2", CONF_IO_DIS),
570 ): OPTIONS_IO_OUTPUT_ONLY,
573 description_placeholders={
574 "model": KONN_PANEL_MODEL_NAMES[self.
modelmodel],
580 return self.
async_abortasync_abort(reason=
"not_konn_panel")
583 self, user_input: dict[str, Any] |
None =
None
584 ) -> ConfigFlowResult:
585 """Allow the user to configure the IO options for binary sensors."""
586 errors: dict[str, str] = {}
587 if user_input
is not None and self.
active_cfgactive_cfg
is not None:
589 zone.update(user_input)
590 self.new_opt[CONF_BINARY_SENSORS] = [
591 *self.new_opt.
get(CONF_BINARY_SENSORS, []),
600 step_id=
"options_binary",
601 data_schema=vol.Schema(
605 default=current_cfg.get(
606 CONF_TYPE, BinarySensorDeviceClass.DOOR
608 ): DEVICE_CLASSES_SCHEMA,
610 CONF_NAME, default=current_cfg.get(CONF_NAME, vol.UNDEFINED)
613 CONF_INVERSE, default=current_cfg.get(CONF_INVERSE,
False)
617 description_placeholders={
618 "zone": f
"Zone {self.active_cfg}"
626 for key, value
in self.
io_cfgio_cfg.items():
627 if value == CONF_IO_BIN:
631 step_id=
"options_binary",
632 data_schema=vol.Schema(
636 default=current_cfg.get(
637 CONF_TYPE, BinarySensorDeviceClass.DOOR
639 ): DEVICE_CLASSES_SCHEMA,
642 default=current_cfg.get(CONF_NAME, vol.UNDEFINED),
646 default=current_cfg.get(CONF_INVERSE,
False),
650 description_placeholders={
651 "zone": f
"Zone {self.active_cfg}"
661 self, user_input: dict[str, Any] |
None =
None
662 ) -> ConfigFlowResult:
663 """Allow the user to configure the IO options for digital sensors."""
664 errors: dict[str, str] = {}
665 if user_input
is not None and self.
active_cfgactive_cfg
is not None:
667 zone.update(user_input)
668 self.new_opt[CONF_SENSORS] = [*self.new_opt.
get(CONF_SENSORS, []), zone]
675 step_id=
"options_digital",
676 data_schema=vol.Schema(
679 CONF_TYPE, default=current_cfg.get(CONF_TYPE,
"dht")
680 ): vol.All(vol.Lower, vol.In([
"dht",
"ds18b20"])),
682 CONF_NAME, default=current_cfg.get(CONF_NAME, vol.UNDEFINED)
686 default=current_cfg.get(CONF_POLL_INTERVAL, 3),
687 ): vol.All(vol.Coerce(int), vol.Range(min=1)),
690 description_placeholders={
691 "zone": f
"Zone {self.active_cfg}"
699 for key, value
in self.
io_cfgio_cfg.items():
700 if value == CONF_IO_DIG:
704 step_id=
"options_digital",
705 data_schema=vol.Schema(
708 CONF_TYPE, default=current_cfg.get(CONF_TYPE,
"dht")
709 ): vol.All(vol.Lower, vol.In([
"dht",
"ds18b20"])),
712 default=current_cfg.get(CONF_NAME, vol.UNDEFINED),
716 default=current_cfg.get(CONF_POLL_INTERVAL, 3),
717 ): vol.All(vol.Coerce(int), vol.Range(min=1)),
720 description_placeholders={
721 "zone": f
"Zone {self.active_cfg}"
731 self, user_input: dict[str, Any] |
None =
None
732 ) -> ConfigFlowResult:
733 """Allow the user to configure the IO options for switches."""
734 errors: dict[str, str] = {}
735 if user_input
is not None and self.
active_cfgactive_cfg
is not None:
737 zone.update(user_input)
738 del zone[CONF_MORE_STATES]
739 self.new_opt[CONF_SWITCHES] = [*self.new_opt.
get(CONF_SWITCHES, []), zone]
747 if user_input[CONF_MORE_STATES] == CONF_NO:
754 step_id=
"options_switch",
755 data_schema=vol.Schema(
758 CONF_NAME, default=current_cfg.get(CONF_NAME, vol.UNDEFINED)
762 default=current_cfg.get(CONF_ACTIVATION, STATE_HIGH),
763 ): vol.All(vol.Lower, vol.In([STATE_HIGH, STATE_LOW])),
766 default=current_cfg.get(CONF_MOMENTARY, vol.UNDEFINED),
767 ): vol.All(vol.Coerce(int), vol.Range(min=10)),
770 default=current_cfg.get(CONF_PAUSE, vol.UNDEFINED),
771 ): vol.All(vol.Coerce(int), vol.Range(min=10)),
774 default=current_cfg.get(CONF_REPEAT, vol.UNDEFINED),
775 ): vol.All(vol.Coerce(int), vol.Range(min=-1)),
781 ): vol.In([CONF_YES, CONF_NO]),
784 description_placeholders={
785 "zone": f
"Zone {self.active_cfg}"
794 for key, value
in self.
io_cfgio_cfg.items():
795 if value == CONF_IO_SWI:
800 if cfg[CONF_ZONE] == self.
active_cfgactive_cfg
805 step_id=
"options_switch",
806 data_schema=vol.Schema(
810 default=current_cfg.get(CONF_NAME, vol.UNDEFINED),
814 default=current_cfg.get(CONF_ACTIVATION, STATE_HIGH),
815 ): vol.In([
"low",
"high"]),
818 default=current_cfg.get(CONF_MOMENTARY, vol.UNDEFINED),
819 ): vol.All(vol.Coerce(int), vol.Range(min=10)),
822 default=current_cfg.get(CONF_PAUSE, vol.UNDEFINED),
823 ): vol.All(vol.Coerce(int), vol.Range(min=10)),
826 default=current_cfg.get(CONF_REPEAT, vol.UNDEFINED),
827 ): vol.All(vol.Coerce(int), vol.Range(min=-1)),
833 ): vol.In([CONF_YES, CONF_NO]),
836 description_placeholders={
837 "zone": f
"Zone {self.active_cfg}"
848 self, user_input: dict[str, Any] |
None =
None
849 ) -> ConfigFlowResult:
850 """Allow the user to configure the LED behavior."""
852 if user_input
is not None:
855 if user_input[CONF_OVERRIDE_API_HOST]:
856 cv.url(user_input.get(CONF_API_HOST,
""))
858 user_input[CONF_API_HOST] =
""
860 errors[
"base"] =
"bad_host"
863 del user_input[CONF_OVERRIDE_API_HOST]
864 self.new_opt.
update(user_input)
868 step_id=
"options_misc",
869 data_schema=vol.Schema(
876 CONF_BLINK, default=self.
current_optcurrent_opt.
get(CONF_BLINK,
True)
879 CONF_OVERRIDE_API_HOST,
883 CONF_API_HOST, default=self.
current_optcurrent_opt.
get(CONF_API_HOST,
"")
ConfigFlowResult async_step_import_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_confirm(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_import(self, dict[str, Any] import_data)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
OptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
def async_gen_config(self, host, port)
ConfigFlowResult async_step_ssdp(self, ssdp.SsdpServiceInfo discovery_info)
ConfigFlowResult async_step_options_binary(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_options_io(self, dict[str, Any]|None user_input=None)
None __init__(self, ConfigEntry config_entry)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_options_digital(self, dict[str, Any]|None user_input=None)
def get_current_cfg(self, io_type, zone)
ConfigFlowResult async_step_options_io_ext(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_options_misc(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_options_switch(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_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
None _async_abort_entries_match(self, dict[str, Any]|None match_dict=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)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_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)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
web.Response get(self, web.Request request, str config_key)
IssData update(pyiss.ISS iss)
def get_status(hass, host, port)