diff --git a/README.md b/README.md index 2d9c70a..f2f7a22 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ Component for deep integration [LedFx](https://github.com/LedFx/LedFx) from [Hom **A.** You can, for this, enable the appropriate mode from the [PRO] section. The required objects will only be available when supported by the effect. +**Q. Is Basic Auth supported?** + +**A.** Yes, [OPTIONAL] support. + ## Install Installed through the custom repository [HACS](https://hacs.xyz/) - `dmamontov/hass-ledfx` @@ -42,6 +46,8 @@ For authorization, enter the ip address and port ledfx ledfx: ip_address: 127.0.0.1 port: 8888 + username: test # Username BasicAuth [OPTIONAL] + password: test # Password BasicAuth [OPTIONAL] scan_interval: 10 # Refresh rate in seconds [PRO] timeout: 5 # Request timeout in seconds [PRO] ext_effect_settings: False # Advanced effect settings [PRO] diff --git a/custom_components/ledfx/config_flow.py b/custom_components/ledfx/config_flow.py index 61e41b4..1dc677f 100644 --- a/custom_components/ledfx/config_flow.py +++ b/custom_components/ledfx/config_flow.py @@ -7,9 +7,12 @@ from homeassistant.const import ( CONF_IP_ADDRESS, CONF_PORT, + CONF_USERNAME, + CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_TIMEOUT ) +from httpx._client import USE_CLIENT_DEFAULT from homeassistant.helpers.httpx_client import get_async_client from .core.const import ( @@ -27,7 +30,9 @@ AUTH_SCHEMA = vol.Schema({ vol.Required(CONF_IP_ADDRESS): str, - vol.Required(CONF_PORT): str + vol.Required(CONF_PORT): str, + vol.Optional(CONF_USERNAME): str, + vol.Optional(CONF_PASSWORD): str, }) class LedFxFlowHandler(ConfigFlow, domain = DOMAIN): @@ -44,7 +49,21 @@ async def async_step_auth(self, user_input): if user_input is None: return self.cur_step - client = LedFx(get_async_client(self.hass, False), user_input[CONF_IP_ADDRESS], user_input[CONF_PORT]) + auth = USE_CLIENT_DEFAULT + if ( + user_input[CONF_USERNAME] + and len(user_input[CONF_USERNAME]) > 0 + and user_input[CONF_PASSWORD] + and len(user_input[CONF_PASSWORD]) > 0 + ): + auth = (user_input[CONF_USERNAME], user_input[CONF_PASSWORD]) + + client = LedFx( + get_async_client(self.hass, False), + user_input[CONF_IP_ADDRESS], + user_input[CONF_PORT], + auth + ) try: await client.info() @@ -85,6 +104,8 @@ async def async_step_settings(self, user_input = None): options_schema = vol.Schema({ vol.Required(CONF_IP_ADDRESS, default = self.config_entry.options.get(CONF_IP_ADDRESS, "")): str, vol.Required(CONF_PORT, default = self.config_entry.options.get(CONF_PORT, "")): str, + vol.Optional(CONF_USERNAME, default = self.config_entry.options.get(CONF_USERNAME, "")): str, + vol.Optional(CONF_PASSWORD, default = self.config_entry.options.get(CONF_PASSWORD, "")): str, vol.Optional( CONF_EXT_EFFECT_SETTINGS, default=self.config_entry.options.get(CONF_EXT_EFFECT_SETTINGS, False) @@ -104,7 +125,21 @@ async def async_step_settings(self, user_input = None): }) if user_input: - client = LedFx(get_async_client(self.hass, False), user_input[CONF_IP_ADDRESS], user_input[CONF_PORT]) + auth = USE_CLIENT_DEFAULT + if ( + user_input[CONF_USERNAME] + and len(user_input[CONF_USERNAME]) > 0 + and user_input[CONF_PASSWORD] + and len(user_input[CONF_PASSWORD]) > 0 + ): + auth = (user_input[CONF_USERNAME], user_input[CONF_PASSWORD]) + + client = LedFx( + get_async_client(self.hass, False), + user_input[CONF_IP_ADDRESS], + user_input[CONF_PORT], + auth + ) try: await client.info() diff --git a/custom_components/ledfx/core/ledfx.py b/custom_components/ledfx/core/ledfx.py index ca1a9bb..ec70cd8 100644 --- a/custom_components/ledfx/core/ledfx.py +++ b/custom_components/ledfx/core/ledfx.py @@ -1,7 +1,8 @@ import logging - import json +from httpx._client import USE_CLIENT_DEFAULT + from . import exceptions from .const import ( DOMAIN, @@ -18,6 +19,7 @@ def __init__( httpx_client, ip: str, port: str, + auth = USE_CLIENT_DEFAULT, options: dict = {} ) -> None: if ip.endswith("/"): @@ -26,6 +28,8 @@ def __init__( self.httpx_client = httpx_client self.base_url = BASE_RESOURCE.format(ip = ip, port = port) + self.auth = auth + _LOGGER.debug("Debug LedFx: Init {}".format(self.base_url)) self.timeout = options["timeout"] if "timeout" in options else DEFAULT_TIMEOUT @@ -35,7 +39,8 @@ async def get(self, path: str, is_check_status: bool = True): async with self.httpx_client as client: response = await client.get( "{}/{}".format(self.base_url, path), - timeout = self.timeout + timeout = self.timeout, + auth = self.auth ) data = json.loads(response.content) @@ -55,7 +60,8 @@ async def post(self, path: str, data: dict, is_check_status: bool = True): response = await client.post( "{}/{}".format(self.base_url, path), json = data, - timeout = POST_TIMEOUT + timeout = POST_TIMEOUT, + auth = self.auth ) data = json.loads(response.content) @@ -75,7 +81,8 @@ async def put(self, path: str, data: dict, is_check_status: bool = True): response = await client.put( "{}/{}".format(self.base_url, path), json = data, - timeout = POST_TIMEOUT + timeout = POST_TIMEOUT, + auth = self.auth ) data = json.loads(response.content) @@ -94,7 +101,8 @@ async def delete(self, path: str, is_check_status: bool = True): async with self.httpx_client as client: response = await client.delete( "{}/{}".format(self.base_url, path), - timeout = POST_TIMEOUT + timeout = POST_TIMEOUT, + auth = self.auth ) data = json.loads(response.content) diff --git a/custom_components/ledfx/core/worker.py b/custom_components/ledfx/core/worker.py index a525359..b6cfff9 100644 --- a/custom_components/ledfx/core/worker.py +++ b/custom_components/ledfx/core/worker.py @@ -8,10 +8,13 @@ from homeassistant.const import ( CONF_IP_ADDRESS, CONF_PORT, + CONF_USERNAME, + CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_TIMEOUT ) +from httpx._client import USE_CLIENT_DEFAULT from homeassistant.helpers.httpx_client import get_async_client from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.dispatcher import async_dispatcher_send @@ -54,6 +57,7 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry): get_async_client(hass, False), self.ip, self.port, + self.auth, {"timeout": self.timeout} ) @@ -84,6 +88,16 @@ def ip(self) -> str: def port(self) -> str: return self.config_entry.options[CONF_PORT] + @property + def auth(self): + username = self.config_entry.options.get(CONF_USERNAME, None) + password = self.config_entry.options.get(CONF_PASSWORD, None) + + if username and len(username) > 0 and password and len(password) > 0: + return (username, password) + + return USE_CLIENT_DEFAULT + @property def timeout(self) -> int: return self.config_entry.options.get(CONF_TIMEOUT, DEFAULT_TIMEOUT) diff --git a/custom_components/ledfx/manifest.json b/custom_components/ledfx/manifest.json index ee86619..4773c82 100644 --- a/custom_components/ledfx/manifest.json +++ b/custom_components/ledfx/manifest.json @@ -1,7 +1,7 @@ { "domain": "ledfx", "name": "LedFx", - "version": "1.1.4", + "version": "1.2.0", "documentation": "https://github.com/dmamontov/hass-ledfx", "issue_tracker": "https://github.com/dmamontov/hass-ledfx/issues", "config_flow": true, diff --git a/custom_components/ledfx/translations/en.json b/custom_components/ledfx/translations/en.json index 19fd24b..5a0222a 100644 --- a/custom_components/ledfx/translations/en.json +++ b/custom_components/ledfx/translations/en.json @@ -12,7 +12,9 @@ "description": "Enter the ip address and port of the LedFx server", "data": { "ip_address": "IP address", - "port": "Port" + "port": "Port", + "username": "Username BasicAuth [OPTIONAL]", + "password": "Password BasicAuth [OPTIONAL]" } } } @@ -31,6 +33,8 @@ "data": { "ip_address": "IP address", "port": "Port", + "username": "Username BasicAuth [OPTIONAL]", + "password": "Password BasicAuth [OPTIONAL]", "ext_effect_settings": "Advanced Effect Settings [PRO]", "ext_sensors": "Add sensors for device settings [PRO]", "scan_interval": "Scan interval in seconds [PRO]", diff --git a/custom_components/ledfx/translations/ru.json b/custom_components/ledfx/translations/ru.json index f878cc4..c8b0058 100644 --- a/custom_components/ledfx/translations/ru.json +++ b/custom_components/ledfx/translations/ru.json @@ -12,7 +12,9 @@ "description": "Введите ip адрес и порт сервера LedFx", "data": { "ip_address": "IP адрес", - "port": "Порт" + "port": "Порт", + "username": "Пользователь BasicAuth [OPTIONAL]", + "password": "Пароль BasicAuth [OPTIONAL]" } } } @@ -31,6 +33,8 @@ "data": { "ip_address": "IP адрес", "port": "Порт", + "username": "Пользователь BasicAuth [OPTIONAL]", + "password": "Пароль BasicAuth [OPTIONAL]", "ext_effect_settings": "Расширенные настройки эффектов [PRO]", "ext_sensors": "Добавить сенсоры настроек устройства [PRO]", "scan_interval": "Интервал сканирования в секундах [PRO]",