Skip to content

Commit cc2360b

Browse files
authored
Fix config flow polling selector and HA compatibility warnings (#531)
1 parent 110b745 commit cc2360b

6 files changed

Lines changed: 56 additions & 17 deletions

File tree

custom_components/tplink_deco/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import voluptuous as vol
3232

3333
from .api import TplinkDecoApi
34+
from .api import normalize_name
3435
from .const import ATTR_DEVICE_TYPE
3536
from .const import CONF_CLIENT_POSTFIX
3637
from .const import CONF_CLIENT_PREFIX
@@ -145,11 +146,11 @@ async def async_create_config_data(hass: HomeAssistant, config_entry: ConfigEntr
145146
continue
146147
if device_type == DEVICE_TYPE_DECO:
147148
deco = TpLinkDeco(entry.unique_id)
148-
deco.name = entry.original_name
149+
deco.name = normalize_name(entry.original_name)
149150
deco_data.decos[entry.unique_id] = deco
150151
else:
151152
client = TpLinkDecoClient(entry.unique_id)
152-
client.name = entry.original_name
153+
client.name = normalize_name(entry.original_name)
153154
client_data[entry.unique_id] = client
154155

155156
return await async_create_and_refresh_coordinators(

custom_components/tplink_deco/api.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@
3737
PKCS1_v1_5_HEADER_BYTES = 11
3838

3939
_LOGGER: logging.Logger = logging.getLogger(__name__)
40+
LEGACY_ERROR_DECODING_PATTERN = re.compile(r"^<Error Decoding (.*)>$")
41+
42+
43+
def normalize_name(name: str):
44+
"""Normalize Deco/client names from current and legacy decoding behavior."""
45+
if not isinstance(name, str) or not name:
46+
return name
47+
48+
match = LEGACY_ERROR_DECODING_PATTERN.match(name)
49+
if match:
50+
return match.group(1)
51+
52+
return name
4053

4154

4255
def byte_len(n: int) -> int:
@@ -50,9 +63,9 @@ def decode_name_with_fallback(name: str):
5063

5164
try:
5265
decoded = base64.b64decode(name, validate=True)
53-
return decoded.decode("utf-8")
66+
return normalize_name(decoded.decode("utf-8"))
5467
except Exception:
55-
return name
68+
return normalize_name(name)
5669

5770

5871
def rsa_encrypt(n: int, e: int, plaintext: bytes) -> bytes:

custom_components/tplink_deco/config_flow.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from homeassistant.core import callback
1616
from homeassistant.exceptions import ConfigEntryAuthFailed
1717
from homeassistant.exceptions import ConfigEntryNotReady
18+
from homeassistant.helpers import selector
1819
import voluptuous as vol
1920

2021
from .__init__ import async_create_and_refresh_coordinators
@@ -36,6 +37,26 @@
3637
from .exceptions import TimeoutException
3738

3839
_LOGGER: logging.Logger = logging.getLogger(__name__)
40+
SCAN_INTERVAL_OPTIONS = [10, 30, 60, 120]
41+
SCAN_INTERVAL_SELECTOR_OPTIONS = [str(value) for value in SCAN_INTERVAL_OPTIONS]
42+
43+
44+
def _get_scan_interval(data: dict[str:Any]) -> str:
45+
scan_interval = data.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
46+
try:
47+
scan_interval = int(scan_interval)
48+
except (TypeError, ValueError):
49+
scan_interval = DEFAULT_SCAN_INTERVAL
50+
51+
if scan_interval not in SCAN_INTERVAL_OPTIONS:
52+
scan_interval = DEFAULT_SCAN_INTERVAL
53+
54+
return str(scan_interval)
55+
56+
57+
def _normalize_scan_interval(data: dict[str:Any]) -> None:
58+
if CONF_SCAN_INTERVAL in data:
59+
data[CONF_SCAN_INTERVAL] = int(data[CONF_SCAN_INTERVAL])
3960

4061

4162
def _get_auth_schema(data: dict[str:Any]):
@@ -51,10 +72,7 @@ def _get_schema(data: dict[str:Any]):
5172
if data is None:
5273
data = {}
5374
schema = _get_auth_schema(data)
54-
scan_interval = data.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
55-
56-
if scan_interval not in [10, 30, 60, 120]:
57-
scan_interval = DEFAULT_SCAN_INTERVAL
75+
scan_interval = _get_scan_interval(data)
5876

5977
schema.update(
6078
{
@@ -64,9 +82,11 @@ def _get_schema(data: dict[str:Any]):
6482
vol.Required(
6583
CONF_SCAN_INTERVAL,
6684
default=scan_interval,
67-
): vol.All(
68-
vol.Coerce(int),
69-
vol.In({10, 30, 60, 120}),
85+
): selector.SelectSelector(
86+
selector.SelectSelectorConfig(
87+
options=SCAN_INTERVAL_SELECTOR_OPTIONS,
88+
mode=selector.SelectSelectorMode.DROPDOWN,
89+
)
7090
),
7191
vol.Required(
7292
CONF_CONSIDER_HOME,
@@ -163,6 +183,7 @@ async def async_step_user(self, user_input=None):
163183
self._errors = {}
164184

165185
if user_input is not None:
186+
_normalize_scan_interval(user_input)
166187
self._errors = await _async_test_credentials(self.hass, user_input)
167188
if len(self._errors) == 0:
168189
_ensure_user_input_optionals(user_input)
@@ -226,6 +247,7 @@ async def async_step_init(self, user_input: dict[str:Any] = None):
226247

227248
if user_input is not None:
228249
_ensure_user_input_optionals(user_input)
250+
_normalize_scan_interval(user_input)
229251
self.data.update(user_input)
230252

231253
self._errors = await _async_test_credentials(self.hass, self.data)

custom_components/tplink_deco/coordinator.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from homeassistant.util import dt as dt_util
2020

2121
from .api import TplinkDecoApi
22+
from .api import normalize_name
2223
from .const import DOMAIN
2324
from .const import SIGNAL_CLIENT_ADDED
2425
from .const import SIGNAL_DECO_ADDED
@@ -88,9 +89,11 @@ def update(
8889
self.sw_version = data.get("software_ver")
8990
self.device_model = data.get("device_model")
9091

91-
self.name = data.get("custom_nickname") # Only set if custom value
92+
self.name = normalize_name(
93+
data.get("custom_nickname")
94+
) # Only set if custom value
9295
if self.name is None:
93-
self.name = snake_case_to_title_space(data.get("nickname"))
96+
self.name = normalize_name(snake_case_to_title_space(data.get("nickname")))
9497
self.ip_address = filter_invalid_ip(data.get("device_ip"))
9598
self.online = data.get("group_status") == "connected"
9699
inet = data.get("inet_status")
@@ -133,7 +136,7 @@ def update(
133136
utc_point_in_time: datetime,
134137
) -> None:
135138
self.deco_mac = deco_mac
136-
self.name = data.get("name")
139+
self.name = normalize_name(data.get("name"))
137140
self.ip_address = filter_invalid_ip(data.get("ip"))
138141
self.online = data.get("online")
139142
self.connection_type = data.get("connection_type")

custom_components/tplink_deco/device_tracker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
from typing import Any
55

6-
from homeassistant.components.device_tracker.config_entry import ScannerEntity
6+
from homeassistant.components.device_tracker import ScannerEntity
77
from homeassistant.components.device_tracker.const import ATTR_IP
88
from homeassistant.components.device_tracker.const import SourceType
99
from homeassistant.config_entries import ConfigEntry
@@ -29,7 +29,6 @@
2929
from .const import ATTR_MASTER
3030
from .const import ATTR_SIGNAL_BAND2_4
3131
from .const import ATTR_SIGNAL_BAND5
32-
from .const import ATTR_UI_DEVICE_NAME
3332
from .const import ATTR_UP_KILOBYTES_PER_S
3433
from .const import CONF_CLIENT_POSTFIX
3534
from .const import CONF_CLIENT_PREFIX
@@ -49,6 +48,7 @@
4948
from .device import create_device_info
5049

5150
_LOGGER: logging.Logger = logging.getLogger(__name__)
51+
ATTR_UI_DEVICE_NAME = "ui_device_name"
5252

5353

5454
def _generate_name(name: str, prefix: str, postfix: str):

custom_components/tplink_deco/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
"issue_tracker": "https://github.com/amosyuen/ha-tplink-deco/issues",
1111
"loggers": ["tplink_deco"],
1212
"requirements": ["pycryptodome>=3.12.0"],
13-
"version": "3.8.2"
13+
"version": "3.9.0"
1414
}

0 commit comments

Comments
 (0)