Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions homeassistant/components/knx/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from xknx import XKNX
from xknx.devices import BinarySensor as XknxBinarySensor

from homeassistant.components.binary_sensor import DEVICE_CLASSES, BinarySensorEntity
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
Expand Down Expand Up @@ -64,9 +64,7 @@ def __init__(self, xknx: XKNX, config: ConfigType) -> None:
@property
def device_class(self) -> str | None:
"""Return the class of this sensor."""
if self._device_class in DEVICE_CLASSES:
return self._device_class
return None
return self._device_class

@property
def is_on(self) -> bool:
Expand Down
3 changes: 1 addition & 2 deletions homeassistant/components/knx/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
ATTR_POSITION,
ATTR_TILT_POSITION,
DEVICE_CLASS_BLIND,
DEVICE_CLASSES,
SUPPORT_CLOSE,
SUPPORT_CLOSE_TILT,
SUPPORT_OPEN,
Expand Down Expand Up @@ -127,7 +126,7 @@ async def after_update_callback(self, device: XknxDevice) -> None:
@property
def device_class(self) -> str | None:
"""Return the class of this device, from component DEVICE_CLASSES."""
if self._device_class in DEVICE_CLASSES:
if self._device_class:
return self._device_class
if self._device.supports_angle:
Comment thread
janiversen marked this conversation as resolved.
return DEVICE_CLASS_BLIND
Expand Down
34 changes: 24 additions & 10 deletions homeassistant/components/knx/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@

import voluptuous as vol
from xknx.devices.climate import SetpointShiftMode
from xknx.dpt import DPTBase
from xknx.exceptions import CouldNotParseAddress
from xknx.io import DEFAULT_MCAST_PORT
from xknx.telegram.address import IndividualAddress, parse_device_group_address

from homeassistant.components.binary_sensor import (
DEVICE_CLASSES as BINARY_SENSOR_DEVICE_CLASSES,
)
from homeassistant.components.cover import DEVICE_CLASSES as COVER_DEVICE_CLASSES
from homeassistant.const import (
CONF_DEVICE_CLASS,
CONF_ENTITY_ID,
Expand Down Expand Up @@ -44,7 +49,8 @@ def ga_validator(value: Any) -> str | int:
except CouldNotParseAddress:
pass
raise vol.Invalid(
f"value '{value}' is not a valid KNX group address '<main>/<middle>/<sub>', '<main>/<sub>' or '<free>' (eg.'1/2/3', '9/234', '123'), nor xknx internal address 'i-<string>'."
f"value '{value}' is not a valid KNX group address '<main>/<middle>/<sub>', '<main>/<sub>' "
"or '<free>' (eg.'1/2/3', '9/234', '123'), nor xknx internal address 'i-<string>'."
)


Expand All @@ -56,15 +62,20 @@ def ga_validator(value: Any) -> str | int:
msg="value does not match pattern for KNX individual address '<area>.<line>.<device>' (eg.'1.1.100')",
)


def sensor_type_validator(value: Any) -> str | int:
"""Validate that value is parsable as sensor type."""
if isinstance(value, (str, int)) and DPTBase.parse_transcoder(value) is not None:
return value
raise vol.Invalid(f"value '{value}' is not a valid sensor type.")


sync_state_validator = vol.Any(
vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)),
cv.boolean,
cv.matches_regex(r"^(init|expire|every)( \d*)?$"),
)

sensor_type_validator = vol.Any(int, str)


##############
# CONNECTION
##############
Expand Down Expand Up @@ -119,7 +130,7 @@ class BinarySensorSchema:
vol.Optional(CONF_CONTEXT_TIMEOUT): vol.All(
vol.Coerce(float), vol.Range(min=0, max=10)
),
vol.Optional(CONF_DEVICE_CLASS): cv.string,
vol.Optional(CONF_DEVICE_CLASS): vol.In(BINARY_SENSOR_DEVICE_CLASSES),
vol.Optional(CONF_RESET_AFTER): cv.positive_float,
}
),
Expand Down Expand Up @@ -222,10 +233,10 @@ class ClimateSchema:
CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT
): cv.boolean,
vol.Optional(CONF_OPERATION_MODES): vol.All(
cv.ensure_list, [vol.In({**PRESET_MODES})]
cv.ensure_list, [vol.In(PRESET_MODES)]
),
vol.Optional(CONF_CONTROLLER_MODES): vol.All(
cv.ensure_list, [vol.In({**CONTROLLER_MODES})]
cv.ensure_list, [vol.In(CONTROLLER_MODES)]
),
vol.Optional(CONF_MIN_TEMP): vol.Coerce(float),
vol.Optional(CONF_MAX_TEMP): vol.Coerce(float),
Expand Down Expand Up @@ -280,7 +291,7 @@ class CoverSchema:
): cv.positive_float,
vol.Optional(CONF_INVERT_POSITION, default=False): cv.boolean,
vol.Optional(CONF_INVERT_ANGLE, default=False): cv.boolean,
vol.Optional(CONF_DEVICE_CLASS): cv.string,
vol.Optional(CONF_DEVICE_CLASS): vol.In(COVER_DEVICE_CLASSES),
}
),
)
Expand All @@ -291,6 +302,7 @@ class ExposeSchema:

CONF_KNX_EXPOSE_TYPE = CONF_TYPE
CONF_KNX_EXPOSE_ATTRIBUTE = "attribute"
CONF_KNX_EXPOSE_BINARY = "binary"
CONF_KNX_EXPOSE_DEFAULT = "default"
EXPOSE_TIME_TYPES = [
"time",
Expand All @@ -308,14 +320,16 @@ class ExposeSchema:
)
EXPOSE_SENSOR_SCHEMA = vol.Schema(
{
vol.Required(CONF_KNX_EXPOSE_TYPE): sensor_type_validator,
vol.Required(CONF_KNX_EXPOSE_TYPE): vol.Any(
CONF_KNX_EXPOSE_BINARY, sensor_type_validator
),
vol.Required(KNX_ADDRESS): ga_validator,
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_KNX_EXPOSE_ATTRIBUTE): cv.string,
vol.Optional(CONF_KNX_EXPOSE_DEFAULT): cv.match_all,
}
)
SCHEMA = vol.Any(EXPOSE_TIME_SCHEMA, EXPOSE_SENSOR_SCHEMA)
SCHEMA = vol.Any(EXPOSE_SENSOR_SCHEMA, EXPOSE_TIME_SCHEMA)


class FanSchema:
Expand Down