Skip to content

Commit

Permalink
Added options flow (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmakeev authored Dec 16, 2022
1 parent 4cc5dfa commit 0e89356
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 34 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ Copy `tplink_easy_smart` folder from [latest release](https://github.com/vmakeev

Configuration > [Integrations](https://my.home-assistant.io/redirect/integrations/) > Add Integration > [TP-Link Easy Smart](https://my.home-assistant.io/redirect/config_flow_start/?domain=tplink_easy_smart)

### Advanced options

You can perform advanced component configuration by clicking the `CONFIGURE` button after adding it. Advanced settings include:
* Data update interval
* Enabling or disabling [port state switches](#port-state)

## Sensors

Expand Down Expand Up @@ -97,7 +102,9 @@ _Note: The sensor will be unavailable if the port is not enabled (see [port stat

The component allows you to enable and disable each port.

There are several switches that are always present:
By default, adding these switches is disabled, but you can add them via [options](#advanced-options).

There are several switches:
* `switch.<integration_name>_port_<port_number>_enabled`

_Note: these switches are not enabled by default. If you need to use this feature, please enable it manually. Don't use this feature if you don't know what you are doing._
_Note: don't use this feature if you don't know what you are doing._
79 changes: 71 additions & 8 deletions custom_components/tplink_easy_smart/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import voluptuous as vol

from homeassistant.config_entries import CONN_CLASS_LOCAL_POLL, ConfigFlow
from homeassistant.config_entries import CONN_CLASS_LOCAL_POLL, ConfigFlow, OptionsFlow
from homeassistant.const import (
CONF_HOST,
CONF_NAME,
Expand All @@ -19,10 +19,12 @@

from .client.coreapi import AuthenticationError, TpLinkWebApi
from .const import (
CONF_PORT_STATE_SWITCHES,
DEFAULT_HOST,
DEFAULT_NAME,
DEFAULT_PASS,
DEFAULT_PORT,
DEFAULT_PORT_STATE_SWITCHES,
DEFAULT_SCAN_INTERVAL,
DEFAULT_SSL,
DEFAULT_USER,
Expand Down Expand Up @@ -56,6 +58,12 @@ class TpLinkControllerConfigFlow(ConfigFlow, domain=DOMAIN):
def __init__(self):
"""Initialize."""

@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return TpLinkControllerOptionsFlowHandler(config_entry)

async def async_step_import(self, user_input=None):
"""Occurs when a previous entry setup fails and is re-initiated."""
return await self.async_step_user(user_input)
Expand Down Expand Up @@ -104,7 +112,6 @@ async def async_step_user(self, user_input=None):
CONF_PORT: DEFAULT_PORT,
CONF_SSL: DEFAULT_SSL,
CONF_VERIFY_SSL: DEFAULT_VERIFY_SSL,
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
},
errors=errors,
)
Expand All @@ -122,15 +129,71 @@ def _show_config_form(self, user_input, errors=None):
vol.Required(CONF_HOST, default=user_input[CONF_HOST]): str,
vol.Required(CONF_USERNAME, default=user_input[CONF_USERNAME]): str,
vol.Required(CONF_PASSWORD, default=user_input[CONF_PASSWORD]): str,
vol.Optional(CONF_PORT, default=user_input[CONF_PORT]): int,
vol.Optional(CONF_SSL, default=user_input[CONF_SSL]): bool,
vol.Optional(
vol.Required(CONF_PORT, default=user_input[CONF_PORT]): int,
vol.Required(CONF_SSL, default=user_input[CONF_SSL]): bool,
vol.Required(
CONF_VERIFY_SSL, default=user_input[CONF_VERIFY_SSL]
): bool,
vol.Optional(
CONF_SCAN_INTERVAL, default=user_input[CONF_SCAN_INTERVAL]
): int,
}
),
errors=errors,
)


# ---------------------------
# TpLinkControllerOptionsFlowHandler
# ---------------------------
class TpLinkControllerOptionsFlowHandler(OptionsFlow):
"""Handle options."""

def __init__(self, config_entry):
"""Initialize options flow."""
self.config_entry = config_entry
self.options = dict(config_entry.options)

async def async_step_init(self, user_input=None):
"""Manage the options."""
return await self.async_step_basic_options(user_input)

async def async_step_basic_options(self, user_input=None):
"""Manage the basic options options."""
if user_input is not None:
self.options.update(user_input)
return await self.async_step_features_select()

return self.async_show_form(
step_id="basic_options",
data_schema=vol.Schema(
{
vol.Required(
CONF_SCAN_INTERVAL,
default=self.config_entry.options.get(
CONF_SCAN_INTERVAL,
self.config_entry.data.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
),
),
): int,
}
),
)

async def async_step_features_select(self, user_input=None):
"""Manage the controls select options."""
if user_input is not None:
self.options.update(user_input)
return self.async_create_entry(title="", data=self.options)

return self.async_show_form(
step_id="features_select",
data_schema=vol.Schema(
{
vol.Required(
CONF_PORT_STATE_SWITCHES,
default=self.config_entry.options.get(
CONF_PORT_STATE_SWITCHES, DEFAULT_PORT_STATE_SWITCHES
),
): bool,
},
),
)
3 changes: 3 additions & 0 deletions custom_components/tplink_easy_smart/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
DEFAULT_NAME: Final = "TP-Link Switch"
DEFAULT_VERIFY_SSL: Final = False
DEFAULT_SCAN_INTERVAL: Final = 30
DEFAULT_PORT_STATE_SWITCHES: Final = False

CONF_PORT_STATE_SWITCHES = "port_state_switches"

DATA_KEY_COORDINATOR = "coordinator"

Expand Down
1 change: 1 addition & 0 deletions custom_components/tplink_easy_smart/helpers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Helpful common functions."""

from homeassistant.helpers.entity import generate_entity_id as hass_generate_id

from .update_coordinator import TpLinkDataUpdateCoordinator


Expand Down
2 changes: 1 addition & 1 deletion custom_components/tplink_easy_smart/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"requirements": [
"json5==0.9.10"
],
"version": "0.1.0",
"version": "0.1.1",
"config_flow": true
}
39 changes: 23 additions & 16 deletions custom_components/tplink_easy_smart/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DATA_KEY_COORDINATOR, DOMAIN
from .const import (
CONF_PORT_STATE_SWITCHES,
DATA_KEY_COORDINATOR,
DEFAULT_PORT_STATE_SWITCHES,
DOMAIN,
)
from .helpers import generate_entity_id, generate_entity_name, generate_entity_unique_id
from .update_coordinator import TpLinkDataUpdateCoordinator

Expand Down Expand Up @@ -66,22 +71,25 @@ async def async_setup_entry(

sensors = []

for port_number in range(1, coordinator.ports_count + 1):
sensors.append(
TpLinkPortStateSwitch(
coordinator,
TpLinkPortSwitchEntityDescription(
key=f"port_{port_number}_enabled",
icon="mdi:ethernet",
port_number=port_number,
device_name=coordinator.get_switch_info().name,
function_uid=_FUNCTION_UID_PORT_STATE_FORMAT.format(port_number),
function_name=_FUNCTION_DISPLAYED_NAME_PORT_STATE_FORMAT.format(
port_number
if config_entry.options.get(CONF_PORT_STATE_SWITCHES, DEFAULT_PORT_STATE_SWITCHES):
for port_number in range(1, coordinator.ports_count + 1):
sensors.append(
TpLinkPortStateSwitch(
coordinator,
TpLinkPortSwitchEntityDescription(
key=f"port_{port_number}_enabled",
icon="mdi:ethernet",
port_number=port_number,
device_name=coordinator.get_switch_info().name,
function_uid=_FUNCTION_UID_PORT_STATE_FORMAT.format(
port_number
),
function_name=_FUNCTION_DISPLAYED_NAME_PORT_STATE_FORMAT.format(
port_number
),
),
),
)
)
)

async_add_entities(sensors)

Expand Down Expand Up @@ -174,7 +182,6 @@ def __init__(
self._attr_extra_state_attributes = {}
self._port_number = description.port_number
self._attr_icon = "mdi:ethernet"
self._attr_entity_registry_enabled_default = False

async def _go_to_state(self, state: bool):
info = self._port_info
Expand Down
22 changes: 19 additions & 3 deletions custom_components/tplink_easy_smart/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,35 @@
"username": "Username",
"password": "Password",
"ssl": "Use SSL",
"verify_ssl": "Verify SSL cert",
"scan_interval": "Update interval"
"verify_ssl": "Verify SSL cert"
}
}
},
"error": {
"name_exists": "The name already used.",
"auth_general": "Can not authenticate.",
"auth_invalid_csrf": "CSRF error, try again.",
"auth_invalid_credentials": "Invalid username or password.",
"auth_user_blocked": "The user is not allowed to login.",
"auth_too_many_users": "The number of the user that allowed to login has been full.",
"auth_session_timeout": "The session is timeout."
}
},
"options": {
"step": {
"basic_options": {
"data": {
"scan_interval": "Update interval"
},
"title": "TP-Link easy smart switch setup (1\/2)",
"description": "Basic options"
},
"features_select": {
"data": {
"port_state_switches": "Port state switches"
},
"title": "TP-Link easy smart switch setup (2\/2)",
"description": "Controls"
}
}
}
}
21 changes: 19 additions & 2 deletions custom_components/tplink_easy_smart/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"username": "Имя пользователя",
"password": "Пароль",
"ssl": "Использовать SSL",
"verify_ssl": "Проверять сертификат",
"scan_interval": "Период обновления"
"verify_ssl": "Проверять сертификат"
}
}
},
Expand All @@ -24,5 +23,23 @@
"auth_too_many_users": "Слишком много активных пользователей.",
"auth_session_timeout": "Таймаут сессии истек."
}
},
"options": {
"step": {
"basic_options": {
"data": {
"scan_interval": "Период обновления"
},
"title": "Настройка интеграции TP-Link Easy Smart (1\/2)",
"description": "Базовые настройки"
},
"features_select": {
"data": {
"port_state_switches": "Выключатели портов"
},
"title": "Настройка интеграции TP-Link Easy Smart (2\/2)",
"description": "Элементы управления"
}
}
}
}
9 changes: 7 additions & 2 deletions custom_components/tplink_easy_smart/update_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from .client.classes import TpLinkSystemInfo
from .client.tplink_api import PortSpeed, PortState, TpLinkApi
from .const import ATTR_MANUFACTURER, DOMAIN
from .const import ATTR_MANUFACTURER, DEFAULT_SCAN_INTERVAL, DOMAIN

_LOGGER = logging.getLogger(__name__)

Expand All @@ -43,12 +43,17 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
self._switch_info: TpLinkSystemInfo | None = None
self._port_states: list[PortState] = []

update_interval = config_entry.options.get(
CONF_SCAN_INTERVAL,
config_entry.data.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL),
)

super().__init__(
hass,
_LOGGER,
name=config_entry.data[CONF_NAME],
update_method=self.async_update,
update_interval=timedelta(seconds=config_entry.data[CONF_SCAN_INTERVAL]),
update_interval=timedelta(seconds=update_interval),
)

@property
Expand Down

0 comments on commit 0e89356

Please sign in to comment.