Skip to content

Commit 53d2f6b

Browse files
authored
KNX: Use a ConfigExtractor helper class for value retrieval (home-assistant#147983)
1 parent 78c39f8 commit 53d2f6b

File tree

5 files changed

+150
-126
lines changed

5 files changed

+150
-126
lines changed

homeassistant/components/knx/binary_sensor.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
KNX_MODULE_KEY,
4040
)
4141
from .entity import KnxUiEntity, KnxUiEntityPlatformController, KnxYamlEntity
42-
from .storage.const import CONF_ENTITY, CONF_GA_PASSIVE, CONF_GA_SENSOR, CONF_GA_STATE
42+
from .storage.const import CONF_ENTITY, CONF_GA_SENSOR
43+
from .storage.util import ConfigExtractor
4344

4445

4546
async def async_setup_entry(
@@ -146,17 +147,17 @@ def __init__(
146147
unique_id=unique_id,
147148
entity_config=config[CONF_ENTITY],
148149
)
150+
knx_conf = ConfigExtractor(config[DOMAIN])
149151
self._device = XknxBinarySensor(
150152
xknx=knx_module.xknx,
151153
name=config[CONF_ENTITY][CONF_NAME],
152-
group_address_state=[
153-
config[DOMAIN][CONF_GA_SENSOR][CONF_GA_STATE],
154-
*config[DOMAIN][CONF_GA_SENSOR][CONF_GA_PASSIVE],
155-
],
156-
sync_state=config[DOMAIN][CONF_SYNC_STATE],
157-
invert=config[DOMAIN].get(CONF_INVERT, False),
158-
ignore_internal_state=config[DOMAIN].get(CONF_IGNORE_INTERNAL_STATE, False),
159-
context_timeout=config[DOMAIN].get(CONF_CONTEXT_TIMEOUT),
160-
reset_after=config[DOMAIN].get(CONF_RESET_AFTER),
154+
group_address_state=knx_conf.get_state_and_passive(CONF_GA_SENSOR),
155+
sync_state=knx_conf.get(CONF_SYNC_STATE),
156+
invert=knx_conf.get(CONF_INVERT, default=False),
157+
ignore_internal_state=knx_conf.get(
158+
CONF_IGNORE_INTERNAL_STATE, default=False
159+
),
160+
context_timeout=knx_conf.get(CONF_CONTEXT_TIMEOUT),
161+
reset_after=knx_conf.get(CONF_RESET_AFTER),
161162
)
162163
self._attr_force_update = self._device.ignore_internal_state

homeassistant/components/knx/cover.py

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from typing import Any, Literal
5+
from typing import Any
66

77
from xknx import XKNX
88
from xknx.devices import Cover as XknxCover
@@ -35,15 +35,13 @@
3535
from .storage.const import (
3636
CONF_ENTITY,
3737
CONF_GA_ANGLE,
38-
CONF_GA_PASSIVE,
3938
CONF_GA_POSITION_SET,
4039
CONF_GA_POSITION_STATE,
41-
CONF_GA_STATE,
4240
CONF_GA_STEP,
4341
CONF_GA_STOP,
4442
CONF_GA_UP_DOWN,
45-
CONF_GA_WRITE,
4643
)
44+
from .storage.util import ConfigExtractor
4745

4846

4947
async def async_setup_entry(
@@ -230,38 +228,24 @@ def __init__(self, knx_module: KNXModule, config: ConfigType) -> None:
230228
def _create_ui_cover(xknx: XKNX, knx_config: ConfigType, name: str) -> XknxCover:
231229
"""Return a KNX Light device to be used within XKNX."""
232230

233-
def get_address(
234-
key: str, address_type: Literal["write", "state"] = CONF_GA_WRITE
235-
) -> str | None:
236-
"""Get a single group address for given key."""
237-
return knx_config[key][address_type] if key in knx_config else None
238-
239-
def get_addresses(
240-
key: str, address_type: Literal["write", "state"] = CONF_GA_STATE
241-
) -> list[Any] | None:
242-
"""Get group address including passive addresses as list."""
243-
return (
244-
[knx_config[key][address_type], *knx_config[key][CONF_GA_PASSIVE]]
245-
if key in knx_config
246-
else None
247-
)
231+
conf = ConfigExtractor(knx_config)
248232

249233
return XknxCover(
250234
xknx=xknx,
251235
name=name,
252-
group_address_long=get_addresses(CONF_GA_UP_DOWN, CONF_GA_WRITE),
253-
group_address_short=get_addresses(CONF_GA_STEP, CONF_GA_WRITE),
254-
group_address_stop=get_addresses(CONF_GA_STOP, CONF_GA_WRITE),
255-
group_address_position=get_addresses(CONF_GA_POSITION_SET, CONF_GA_WRITE),
256-
group_address_position_state=get_addresses(CONF_GA_POSITION_STATE),
257-
group_address_angle=get_address(CONF_GA_ANGLE),
258-
group_address_angle_state=get_addresses(CONF_GA_ANGLE),
259-
travel_time_down=knx_config[CoverConf.TRAVELLING_TIME_DOWN],
260-
travel_time_up=knx_config[CoverConf.TRAVELLING_TIME_UP],
261-
invert_updown=knx_config.get(CoverConf.INVERT_UPDOWN, False),
262-
invert_position=knx_config.get(CoverConf.INVERT_POSITION, False),
263-
invert_angle=knx_config.get(CoverConf.INVERT_ANGLE, False),
264-
sync_state=knx_config[CONF_SYNC_STATE],
236+
group_address_long=conf.get_write_and_passive(CONF_GA_UP_DOWN),
237+
group_address_short=conf.get_write_and_passive(CONF_GA_STEP),
238+
group_address_stop=conf.get_write_and_passive(CONF_GA_STOP),
239+
group_address_position=conf.get_write_and_passive(CONF_GA_POSITION_SET),
240+
group_address_position_state=conf.get_state_and_passive(CONF_GA_POSITION_STATE),
241+
group_address_angle=conf.get_write(CONF_GA_ANGLE),
242+
group_address_angle_state=conf.get_state_and_passive(CONF_GA_ANGLE),
243+
travel_time_down=conf.get(CoverConf.TRAVELLING_TIME_DOWN),
244+
travel_time_up=conf.get(CoverConf.TRAVELLING_TIME_UP),
245+
invert_updown=conf.get(CoverConf.INVERT_UPDOWN, default=False),
246+
invert_position=conf.get(CoverConf.INVERT_POSITION, default=False),
247+
invert_angle=conf.get(CoverConf.INVERT_ANGLE, default=False),
248+
sync_state=conf.get(CONF_SYNC_STATE),
265249
)
266250

267251

homeassistant/components/knx/light.py

Lines changed: 64 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from .storage.const import (
3636
CONF_COLOR_TEMP_MAX,
3737
CONF_COLOR_TEMP_MIN,
38-
CONF_DPT,
3938
CONF_ENTITY,
4039
CONF_GA_BLUE_BRIGHTNESS,
4140
CONF_GA_BLUE_SWITCH,
@@ -45,17 +44,15 @@
4544
CONF_GA_GREEN_BRIGHTNESS,
4645
CONF_GA_GREEN_SWITCH,
4746
CONF_GA_HUE,
48-
CONF_GA_PASSIVE,
4947
CONF_GA_RED_BRIGHTNESS,
5048
CONF_GA_RED_SWITCH,
5149
CONF_GA_SATURATION,
52-
CONF_GA_STATE,
5350
CONF_GA_SWITCH,
5451
CONF_GA_WHITE_BRIGHTNESS,
5552
CONF_GA_WHITE_SWITCH,
56-
CONF_GA_WRITE,
5753
)
5854
from .storage.entity_store_schema import LightColorMode
55+
from .storage.util import ConfigExtractor
5956

6057

6158
async def async_setup_entry(
@@ -203,94 +200,92 @@ def individual_color_addresses(color: str, feature: str) -> Any | None:
203200
def _create_ui_light(xknx: XKNX, knx_config: ConfigType, name: str) -> XknxLight:
204201
"""Return a KNX Light device to be used within XKNX."""
205202

206-
def get_write(key: str) -> str | None:
207-
"""Get the write group address."""
208-
return knx_config[key][CONF_GA_WRITE] if key in knx_config else None
209-
210-
def get_state(key: str) -> list[Any] | None:
211-
"""Get the state group address."""
212-
return (
213-
[knx_config[key][CONF_GA_STATE], *knx_config[key][CONF_GA_PASSIVE]]
214-
if key in knx_config
215-
else None
216-
)
217-
218-
def get_dpt(key: str) -> str | None:
219-
"""Get the DPT."""
220-
return knx_config[key].get(CONF_DPT) if key in knx_config else None
203+
conf = ConfigExtractor(knx_config)
221204

222205
group_address_tunable_white = None
223206
group_address_tunable_white_state = None
224207
group_address_color_temp = None
225208
group_address_color_temp_state = None
209+
226210
color_temperature_type = ColorTemperatureType.UINT_2_BYTE
227-
if ga_color_temp := knx_config.get(CONF_GA_COLOR_TEMP):
228-
if ga_color_temp[CONF_DPT] == ColorTempModes.RELATIVE.value:
229-
group_address_tunable_white = ga_color_temp[CONF_GA_WRITE]
230-
group_address_tunable_white_state = [
231-
ga_color_temp[CONF_GA_STATE],
232-
*ga_color_temp[CONF_GA_PASSIVE],
233-
]
211+
if _color_temp_dpt := conf.get_dpt(CONF_GA_COLOR_TEMP):
212+
if _color_temp_dpt == ColorTempModes.RELATIVE.value:
213+
group_address_tunable_white = conf.get_write(CONF_GA_COLOR_TEMP)
214+
group_address_tunable_white_state = conf.get_state_and_passive(
215+
CONF_GA_COLOR_TEMP
216+
)
234217
else:
235218
# absolute uint or float
236-
group_address_color_temp = ga_color_temp[CONF_GA_WRITE]
237-
group_address_color_temp_state = [
238-
ga_color_temp[CONF_GA_STATE],
239-
*ga_color_temp[CONF_GA_PASSIVE],
240-
]
241-
if ga_color_temp[CONF_DPT] == ColorTempModes.ABSOLUTE_FLOAT.value:
219+
group_address_color_temp = conf.get_write(CONF_GA_COLOR_TEMP)
220+
group_address_color_temp_state = conf.get_state_and_passive(
221+
CONF_GA_COLOR_TEMP
222+
)
223+
if _color_temp_dpt == ColorTempModes.ABSOLUTE_FLOAT.value:
242224
color_temperature_type = ColorTemperatureType.FLOAT_2_BYTE
243225

244-
_color_dpt = get_dpt(CONF_GA_COLOR)
226+
color_dpt = conf.get_dpt(CONF_GA_COLOR)
227+
245228
return XknxLight(
246229
xknx,
247230
name=name,
248-
group_address_switch=get_write(CONF_GA_SWITCH),
249-
group_address_switch_state=get_state(CONF_GA_SWITCH),
250-
group_address_brightness=get_write(CONF_GA_BRIGHTNESS),
251-
group_address_brightness_state=get_state(CONF_GA_BRIGHTNESS),
252-
group_address_color=get_write(CONF_GA_COLOR)
253-
if _color_dpt == LightColorMode.RGB
231+
group_address_switch=conf.get_write(CONF_GA_SWITCH),
232+
group_address_switch_state=conf.get_state_and_passive(CONF_GA_SWITCH),
233+
group_address_brightness=conf.get_write(CONF_GA_BRIGHTNESS),
234+
group_address_brightness_state=conf.get_state_and_passive(CONF_GA_BRIGHTNESS),
235+
group_address_color=conf.get_write(CONF_GA_COLOR)
236+
if color_dpt == LightColorMode.RGB
254237
else None,
255-
group_address_color_state=get_state(CONF_GA_COLOR)
256-
if _color_dpt == LightColorMode.RGB
238+
group_address_color_state=conf.get_state_and_passive(CONF_GA_COLOR)
239+
if color_dpt == LightColorMode.RGB
257240
else None,
258-
group_address_rgbw=get_write(CONF_GA_COLOR)
259-
if _color_dpt == LightColorMode.RGBW
241+
group_address_rgbw=conf.get_write(CONF_GA_COLOR)
242+
if color_dpt == LightColorMode.RGBW
260243
else None,
261-
group_address_rgbw_state=get_state(CONF_GA_COLOR)
262-
if _color_dpt == LightColorMode.RGBW
244+
group_address_rgbw_state=conf.get_state_and_passive(CONF_GA_COLOR)
245+
if color_dpt == LightColorMode.RGBW
263246
else None,
264-
group_address_hue=get_write(CONF_GA_HUE),
265-
group_address_hue_state=get_state(CONF_GA_HUE),
266-
group_address_saturation=get_write(CONF_GA_SATURATION),
267-
group_address_saturation_state=get_state(CONF_GA_SATURATION),
268-
group_address_xyy_color=get_write(CONF_GA_COLOR)
269-
if _color_dpt == LightColorMode.XYY
247+
group_address_hue=conf.get_write(CONF_GA_HUE),
248+
group_address_hue_state=conf.get_state_and_passive(CONF_GA_HUE),
249+
group_address_saturation=conf.get_write(CONF_GA_SATURATION),
250+
group_address_saturation_state=conf.get_state_and_passive(CONF_GA_SATURATION),
251+
group_address_xyy_color=conf.get_write(CONF_GA_COLOR)
252+
if color_dpt == LightColorMode.XYY
270253
else None,
271-
group_address_xyy_color_state=get_write(CONF_GA_COLOR)
272-
if _color_dpt == LightColorMode.XYY
254+
group_address_xyy_color_state=conf.get_write(CONF_GA_COLOR)
255+
if color_dpt == LightColorMode.XYY
273256
else None,
274257
group_address_tunable_white=group_address_tunable_white,
275258
group_address_tunable_white_state=group_address_tunable_white_state,
276259
group_address_color_temperature=group_address_color_temp,
277260
group_address_color_temperature_state=group_address_color_temp_state,
278-
group_address_switch_red=get_write(CONF_GA_RED_SWITCH),
279-
group_address_switch_red_state=get_state(CONF_GA_RED_SWITCH),
280-
group_address_brightness_red=get_write(CONF_GA_RED_BRIGHTNESS),
281-
group_address_brightness_red_state=get_state(CONF_GA_RED_BRIGHTNESS),
282-
group_address_switch_green=get_write(CONF_GA_GREEN_SWITCH),
283-
group_address_switch_green_state=get_state(CONF_GA_GREEN_SWITCH),
284-
group_address_brightness_green=get_write(CONF_GA_GREEN_BRIGHTNESS),
285-
group_address_brightness_green_state=get_state(CONF_GA_GREEN_BRIGHTNESS),
286-
group_address_switch_blue=get_write(CONF_GA_BLUE_SWITCH),
287-
group_address_switch_blue_state=get_state(CONF_GA_BLUE_SWITCH),
288-
group_address_brightness_blue=get_write(CONF_GA_BLUE_BRIGHTNESS),
289-
group_address_brightness_blue_state=get_state(CONF_GA_BLUE_BRIGHTNESS),
290-
group_address_switch_white=get_write(CONF_GA_WHITE_SWITCH),
291-
group_address_switch_white_state=get_state(CONF_GA_WHITE_SWITCH),
292-
group_address_brightness_white=get_write(CONF_GA_WHITE_BRIGHTNESS),
293-
group_address_brightness_white_state=get_state(CONF_GA_WHITE_BRIGHTNESS),
261+
group_address_switch_red=conf.get_write(CONF_GA_RED_SWITCH),
262+
group_address_switch_red_state=conf.get_state_and_passive(CONF_GA_RED_SWITCH),
263+
group_address_brightness_red=conf.get_write(CONF_GA_RED_BRIGHTNESS),
264+
group_address_brightness_red_state=conf.get_state_and_passive(
265+
CONF_GA_RED_BRIGHTNESS
266+
),
267+
group_address_switch_green=conf.get_write(CONF_GA_GREEN_SWITCH),
268+
group_address_switch_green_state=conf.get_state_and_passive(
269+
CONF_GA_GREEN_SWITCH
270+
),
271+
group_address_brightness_green=conf.get_write(CONF_GA_GREEN_BRIGHTNESS),
272+
group_address_brightness_green_state=conf.get_state_and_passive(
273+
CONF_GA_GREEN_BRIGHTNESS
274+
),
275+
group_address_switch_blue=conf.get_write(CONF_GA_BLUE_SWITCH),
276+
group_address_switch_blue_state=conf.get_state_and_passive(CONF_GA_BLUE_SWITCH),
277+
group_address_brightness_blue=conf.get_write(CONF_GA_BLUE_BRIGHTNESS),
278+
group_address_brightness_blue_state=conf.get_state_and_passive(
279+
CONF_GA_BLUE_BRIGHTNESS
280+
),
281+
group_address_switch_white=conf.get_write(CONF_GA_WHITE_SWITCH),
282+
group_address_switch_white_state=conf.get_state_and_passive(
283+
CONF_GA_WHITE_SWITCH
284+
),
285+
group_address_brightness_white=conf.get_write(CONF_GA_WHITE_BRIGHTNESS),
286+
group_address_brightness_white_state=conf.get_state_and_passive(
287+
CONF_GA_WHITE_BRIGHTNESS
288+
),
294289
color_temperature_type=color_temperature_type,
295290
min_kelvin=knx_config[CONF_COLOR_TEMP_MIN],
296291
max_kelvin=knx_config[CONF_COLOR_TEMP_MAX],
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Utility functions for the KNX integration."""
2+
3+
from functools import partial
4+
from typing import Any
5+
6+
from homeassistant.helpers.typing import ConfigType
7+
8+
from .const import CONF_DPT, CONF_GA_PASSIVE, CONF_GA_STATE, CONF_GA_WRITE
9+
10+
11+
def nested_get(dic: ConfigType, *keys: str, default: Any | None = None) -> Any:
12+
"""Get the value from a nested dictionary."""
13+
for key in keys:
14+
if key not in dic:
15+
return default
16+
dic = dic[key]
17+
return dic
18+
19+
20+
class ConfigExtractor:
21+
"""Helper class for extracting values from a knx config store dictionary."""
22+
23+
__slots__ = ("get",)
24+
25+
def __init__(self, config: ConfigType) -> None:
26+
"""Initialize the extractor."""
27+
self.get = partial(nested_get, config)
28+
29+
def get_write(self, *path: str) -> str | None:
30+
"""Get the write group address."""
31+
return self.get(*path, CONF_GA_WRITE) # type: ignore[no-any-return]
32+
33+
def get_state(self, *path: str) -> str | None:
34+
"""Get the state group address."""
35+
return self.get(*path, CONF_GA_STATE) # type: ignore[no-any-return]
36+
37+
def get_write_and_passive(self, *path: str) -> list[Any | None]:
38+
"""Get the group addresses of write and passive."""
39+
write = self.get(*path, CONF_GA_WRITE)
40+
passive = self.get(*path, CONF_GA_PASSIVE)
41+
return [write, *passive] if passive else [write]
42+
43+
def get_state_and_passive(self, *path: str) -> list[Any | None]:
44+
"""Get the group addresses of state and passive."""
45+
state = self.get(*path, CONF_GA_STATE)
46+
passive = self.get(*path, CONF_GA_PASSIVE)
47+
return [state, *passive] if passive else [state]
48+
49+
def get_dpt(self, *path: str) -> str | None:
50+
"""Get the data point type of a group address config key."""
51+
return self.get(*path, CONF_DPT) # type: ignore[no-any-return]

homeassistant/components/knx/switch.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,8 @@
3636
)
3737
from .entity import KnxUiEntity, KnxUiEntityPlatformController, KnxYamlEntity
3838
from .schema import SwitchSchema
39-
from .storage.const import (
40-
CONF_ENTITY,
41-
CONF_GA_PASSIVE,
42-
CONF_GA_STATE,
43-
CONF_GA_SWITCH,
44-
CONF_GA_WRITE,
45-
)
39+
from .storage.const import CONF_ENTITY, CONF_GA_SWITCH
40+
from .storage.util import ConfigExtractor
4641

4742

4843
async def async_setup_entry(
@@ -142,15 +137,13 @@ def __init__(
142137
unique_id=unique_id,
143138
entity_config=config[CONF_ENTITY],
144139
)
140+
knx_conf = ConfigExtractor(config[DOMAIN])
145141
self._device = XknxSwitch(
146142
knx_module.xknx,
147143
name=config[CONF_ENTITY][CONF_NAME],
148-
group_address=config[DOMAIN][CONF_GA_SWITCH][CONF_GA_WRITE],
149-
group_address_state=[
150-
config[DOMAIN][CONF_GA_SWITCH][CONF_GA_STATE],
151-
*config[DOMAIN][CONF_GA_SWITCH][CONF_GA_PASSIVE],
152-
],
153-
respond_to_read=config[DOMAIN][CONF_RESPOND_TO_READ],
154-
sync_state=config[DOMAIN][CONF_SYNC_STATE],
155-
invert=config[DOMAIN][CONF_INVERT],
144+
group_address=knx_conf.get_write(CONF_GA_SWITCH),
145+
group_address_state=knx_conf.get_state_and_passive(CONF_GA_SWITCH),
146+
respond_to_read=knx_conf.get(CONF_RESPOND_TO_READ),
147+
sync_state=knx_conf.get(CONF_SYNC_STATE),
148+
invert=knx_conf.get(CONF_INVERT),
156149
)

0 commit comments

Comments
 (0)