1 """Config flow to configure the MJPEG IP Camera integration."""
3 from __future__
import annotations
5 from http
import HTTPStatus
6 from types
import MappingProxyType
10 from requests.auth
import HTTPBasicAuth, HTTPDigestAuth
11 from requests.exceptions
import HTTPError, Timeout
12 import voluptuous
as vol
26 HTTP_BASIC_AUTHENTICATION,
27 HTTP_DIGEST_AUTHENTICATION,
32 from .const
import CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, DOMAIN, LOGGER
37 defaults: dict[str, Any] | MappingProxyType[str, Any], show_name: bool =
False
39 """Return MJPEG IP Camera schema."""
41 vol.Required(CONF_MJPEG_URL, default=defaults.get(CONF_MJPEG_URL)): str,
44 description={
"suggested_value": defaults.get(CONF_STILL_IMAGE_URL)},
48 description={
"suggested_value": defaults.get(CONF_USERNAME)},
52 default=defaults.get(CONF_PASSWORD,
""),
56 default=defaults.get(CONF_VERIFY_SSL,
True),
62 vol.Required(CONF_NAME, default=defaults.get(CONF_NAME)): str,
66 return vol.Schema(schema)
74 authentication: str = HTTP_BASIC_AUTHENTICATION,
76 """Test if the given setting works as expected."""
77 auth: HTTPDigestAuth | HTTPBasicAuth |
None =
None
78 if username
and password:
79 if authentication == HTTP_DIGEST_AUTHENTICATION:
80 auth = HTTPDigestAuth(username, password)
82 auth = HTTPBasicAuth(username, password)
84 response = requests.get(
92 if response.status_code == HTTPStatus.UNAUTHORIZED:
94 if authentication == HTTP_BASIC_AUTHENTICATION:
96 url, username, password, verify_ssl, HTTP_DIGEST_AUTHENTICATION
100 response.raise_for_status()
103 return authentication
107 hass: HomeAssistant, user_input: dict[str, Any]
108 ) -> tuple[dict[str, str], str]:
109 """Manage MJPEG IP Camera options."""
112 authentication = HTTP_BASIC_AUTHENTICATION
114 for field
in (CONF_MJPEG_URL, CONF_STILL_IMAGE_URL):
115 if not (url := user_input.get(field)):
117 authentication = await hass.async_add_executor_job(
120 user_input.get(CONF_USERNAME),
121 user_input[CONF_PASSWORD],
122 user_input[CONF_VERIFY_SSL],
125 errors[
"username"] =
"invalid_auth"
126 except (OSError, HTTPError, Timeout):
127 LOGGER.exception(
"Cannot connect to %s", user_input[CONF_MJPEG_URL])
128 errors[field] =
"cannot_connect"
130 return (errors, authentication)
134 """Config flow for MJPEG IP Camera."""
141 config_entry: ConfigEntry,
142 ) -> MJPEGOptionsFlowHandler:
143 """Get the options flow for this handler."""
147 self, user_input: dict[str, Any] |
None =
None
148 ) -> ConfigFlowResult:
149 """Handle a flow initialized by the user."""
150 errors: dict[str, str] = {}
152 if user_input
is not None:
156 {CONF_MJPEG_URL: user_input[CONF_MJPEG_URL]}
162 title=user_input.get(CONF_NAME, user_input[CONF_MJPEG_URL]),
165 CONF_AUTHENTICATION: authentication,
166 CONF_MJPEG_URL: user_input[CONF_MJPEG_URL],
167 CONF_PASSWORD: user_input[CONF_PASSWORD],
168 CONF_STILL_IMAGE_URL: user_input.get(CONF_STILL_IMAGE_URL),
169 CONF_USERNAME: user_input.get(CONF_USERNAME),
170 CONF_VERIFY_SSL: user_input[CONF_VERIFY_SSL],
184 """Handle MJPEG IP Camera options."""
187 self, user_input: dict[str, Any] |
None =
None
188 ) -> ConfigFlowResult:
189 """Manage MJPEG IP Camera options."""
190 errors: dict[str, str] = {}
192 if user_input
is not None:
195 for entry
in self.hass.config_entries.async_entries(DOMAIN):
198 and entry.options[CONF_MJPEG_URL] == user_input[CONF_MJPEG_URL]
200 errors = {CONF_MJPEG_URL:
"already_configured"}
204 title=user_input.get(CONF_NAME, user_input[CONF_MJPEG_URL]),
206 CONF_AUTHENTICATION: authentication,
207 CONF_MJPEG_URL: user_input[CONF_MJPEG_URL],
208 CONF_PASSWORD: user_input[CONF_PASSWORD],
209 CONF_STILL_IMAGE_URL: user_input.get(CONF_STILL_IMAGE_URL),
210 CONF_USERNAME: user_input.get(CONF_USERNAME),
211 CONF_VERIFY_SSL: user_input[CONF_VERIFY_SSL],
225 """Error to indicate there is invalid auth."""
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
MJPEGOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_init(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)
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)
tuple[dict[str, str], str] async_validate_input(HomeAssistant hass, dict[str, Any] user_input)
vol.Schema async_get_schema(dict[str, Any]|MappingProxyType[str, Any] defaults, bool show_name=False)
str validate_url(str url, str|None username, str password, bool verify_ssl, str authentication=HTTP_BASIC_AUTHENTICATION)