Create KNX climate entity directly from config (#49638)

* create climate entities directly from config

* deprecate create_temperature_sensors

* move create staticmethod to module level

* use get() fro optional CONF_SETPOINT_SHIFT_MODE

* Fix deprecated version comment

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Matthias Alphart 2021-05-20 12:23:41 +02:00 committed by GitHub
parent 953e6ebe62
commit be6a1bf096
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 102 deletions

View File

@ -3,7 +3,8 @@ from __future__ import annotations
from typing import Any from typing import Any
from xknx.devices import Climate as XknxClimate from xknx import XKNX
from xknx.devices import Climate as XknxClimate, ClimateMode as XknxClimateMode
from xknx.dpt.dpt_hvac_mode import HVACControllerMode, HVACOperationMode from xknx.dpt.dpt_hvac_mode import HVACControllerMode, HVACOperationMode
from xknx.telegram.address import parse_device_group_address from xknx.telegram.address import parse_device_group_address
@ -15,7 +16,7 @@ from homeassistant.components.climate.const import (
SUPPORT_PRESET_MODE, SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
) )
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.const import ATTR_TEMPERATURE, CONF_NAME, TEMP_CELSIUS
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -36,24 +37,26 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None, discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up climate(s) for KNX platform.""" """Set up climate(s) for KNX platform."""
_async_migrate_unique_id(hass, discovery_info) if not discovery_info or not discovery_info["platform_config"]:
return
platform_config = discovery_info["platform_config"]
xknx: XKNX = hass.data[DOMAIN].xknx
_async_migrate_unique_id(hass, platform_config)
entities = [] entities = []
for device in hass.data[DOMAIN].xknx.devices: for entity_config in platform_config:
if isinstance(device, XknxClimate): entities.append(KNXClimate(xknx, entity_config))
entities.append(KNXClimate(device))
async_add_entities(entities) async_add_entities(entities)
@callback @callback
def _async_migrate_unique_id( def _async_migrate_unique_id(
hass: HomeAssistant, discovery_info: DiscoveryInfoType | None hass: HomeAssistant, platform_config: list[ConfigType]
) -> None: ) -> None:
"""Change unique_ids used in 2021.4 to include target_temperature GA.""" """Change unique_ids used in 2021.4 to include target_temperature GA."""
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
if not discovery_info or not discovery_info["platform_config"]:
return
platform_config = discovery_info["platform_config"]
for entity_config in platform_config: for entity_config in platform_config:
# normalize group address strings - ga_temperature_state was the old uid # normalize group address strings - ga_temperature_state was the old uid
ga_temperature_state = parse_device_group_address( ga_temperature_state = parse_device_group_address(
@ -88,18 +91,90 @@ def _async_migrate_unique_id(
entity_registry.async_update_entity(entity_id, new_unique_id=new_uid) entity_registry.async_update_entity(entity_id, new_unique_id=new_uid)
def _create_climate(xknx: XKNX, config: ConfigType) -> XknxClimate:
"""Return a KNX Climate device to be used within XKNX."""
climate_mode = XknxClimateMode(
xknx,
name=f"{config[CONF_NAME]} Mode",
group_address_operation_mode=config.get(
ClimateSchema.CONF_OPERATION_MODE_ADDRESS
),
group_address_operation_mode_state=config.get(
ClimateSchema.CONF_OPERATION_MODE_STATE_ADDRESS
),
group_address_controller_status=config.get(
ClimateSchema.CONF_CONTROLLER_STATUS_ADDRESS
),
group_address_controller_status_state=config.get(
ClimateSchema.CONF_CONTROLLER_STATUS_STATE_ADDRESS
),
group_address_controller_mode=config.get(
ClimateSchema.CONF_CONTROLLER_MODE_ADDRESS
),
group_address_controller_mode_state=config.get(
ClimateSchema.CONF_CONTROLLER_MODE_STATE_ADDRESS
),
group_address_operation_mode_protection=config.get(
ClimateSchema.CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS
),
group_address_operation_mode_night=config.get(
ClimateSchema.CONF_OPERATION_MODE_NIGHT_ADDRESS
),
group_address_operation_mode_comfort=config.get(
ClimateSchema.CONF_OPERATION_MODE_COMFORT_ADDRESS
),
group_address_operation_mode_standby=config.get(
ClimateSchema.CONF_OPERATION_MODE_STANDBY_ADDRESS
),
group_address_heat_cool=config.get(ClimateSchema.CONF_HEAT_COOL_ADDRESS),
group_address_heat_cool_state=config.get(
ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS
),
operation_modes=config.get(ClimateSchema.CONF_OPERATION_MODES),
controller_modes=config.get(ClimateSchema.CONF_CONTROLLER_MODES),
)
return XknxClimate(
xknx,
name=config[CONF_NAME],
group_address_temperature=config[ClimateSchema.CONF_TEMPERATURE_ADDRESS],
group_address_target_temperature=config.get(
ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS
),
group_address_target_temperature_state=config[
ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS
],
group_address_setpoint_shift=config.get(
ClimateSchema.CONF_SETPOINT_SHIFT_ADDRESS
),
group_address_setpoint_shift_state=config.get(
ClimateSchema.CONF_SETPOINT_SHIFT_STATE_ADDRESS
),
setpoint_shift_mode=config.get(ClimateSchema.CONF_SETPOINT_SHIFT_MODE),
setpoint_shift_max=config[ClimateSchema.CONF_SETPOINT_SHIFT_MAX],
setpoint_shift_min=config[ClimateSchema.CONF_SETPOINT_SHIFT_MIN],
temperature_step=config[ClimateSchema.CONF_TEMPERATURE_STEP],
group_address_on_off=config.get(ClimateSchema.CONF_ON_OFF_ADDRESS),
group_address_on_off_state=config.get(ClimateSchema.CONF_ON_OFF_STATE_ADDRESS),
min_temp=config.get(ClimateSchema.CONF_MIN_TEMP),
max_temp=config.get(ClimateSchema.CONF_MAX_TEMP),
mode=climate_mode,
on_off_invert=config[ClimateSchema.CONF_ON_OFF_INVERT],
)
class KNXClimate(KnxEntity, ClimateEntity): class KNXClimate(KnxEntity, ClimateEntity):
"""Representation of a KNX climate device.""" """Representation of a KNX climate device."""
def __init__(self, device: XknxClimate) -> None: def __init__(self, xknx: XKNX, config: ConfigType) -> None:
"""Initialize of a KNX climate device.""" """Initialize of a KNX climate device."""
self._device: XknxClimate self._device: XknxClimate
super().__init__(device) super().__init__(_create_climate(xknx, config))
self._unique_id = ( self._unique_id = (
f"{device.temperature.group_address_state}_" f"{self._device.temperature.group_address_state}_"
f"{device.target_temperature.group_address_state}_" f"{self._device.target_temperature.group_address_state}_"
f"{device.target_temperature.group_address}_" f"{self._device.target_temperature.group_address}_"
f"{device._setpoint_shift.group_address}" # pylint: disable=protected-access f"{self._device._setpoint_shift.group_address}" # pylint: disable=protected-access
) )
self._unit_of_measurement = TEMP_CELSIUS self._unit_of_measurement = TEMP_CELSIUS

View File

@ -3,8 +3,6 @@ from __future__ import annotations
from xknx import XKNX from xknx import XKNX
from xknx.devices import ( from xknx.devices import (
Climate as XknxClimate,
ClimateMode as XknxClimateMode,
Device as XknxDevice, Device as XknxDevice,
Sensor as XknxSensor, Sensor as XknxSensor,
Weather as XknxWeather, Weather as XknxWeather,
@ -14,7 +12,7 @@ from homeassistant.const import CONF_NAME, CONF_TYPE
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import SupportedPlatforms from .const import SupportedPlatforms
from .schema import ClimateSchema, SensorSchema, WeatherSchema from .schema import SensorSchema, WeatherSchema
def create_knx_device( def create_knx_device(
@ -23,9 +21,6 @@ def create_knx_device(
config: ConfigType, config: ConfigType,
) -> XknxDevice | None: ) -> XknxDevice | None:
"""Return the requested XKNX device.""" """Return the requested XKNX device."""
if platform is SupportedPlatforms.CLIMATE:
return _create_climate(knx_module, config)
if platform is SupportedPlatforms.SENSOR: if platform is SupportedPlatforms.SENSOR:
return _create_sensor(knx_module, config) return _create_sensor(knx_module, config)
@ -35,81 +30,6 @@ def create_knx_device(
return None return None
def _create_climate(knx_module: XKNX, config: ConfigType) -> XknxClimate:
"""Return a KNX Climate device to be used within XKNX."""
climate_mode = XknxClimateMode(
knx_module,
name=f"{config[CONF_NAME]} Mode",
group_address_operation_mode=config.get(
ClimateSchema.CONF_OPERATION_MODE_ADDRESS
),
group_address_operation_mode_state=config.get(
ClimateSchema.CONF_OPERATION_MODE_STATE_ADDRESS
),
group_address_controller_status=config.get(
ClimateSchema.CONF_CONTROLLER_STATUS_ADDRESS
),
group_address_controller_status_state=config.get(
ClimateSchema.CONF_CONTROLLER_STATUS_STATE_ADDRESS
),
group_address_controller_mode=config.get(
ClimateSchema.CONF_CONTROLLER_MODE_ADDRESS
),
group_address_controller_mode_state=config.get(
ClimateSchema.CONF_CONTROLLER_MODE_STATE_ADDRESS
),
group_address_operation_mode_protection=config.get(
ClimateSchema.CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS
),
group_address_operation_mode_night=config.get(
ClimateSchema.CONF_OPERATION_MODE_NIGHT_ADDRESS
),
group_address_operation_mode_comfort=config.get(
ClimateSchema.CONF_OPERATION_MODE_COMFORT_ADDRESS
),
group_address_operation_mode_standby=config.get(
ClimateSchema.CONF_OPERATION_MODE_STANDBY_ADDRESS
),
group_address_heat_cool=config.get(ClimateSchema.CONF_HEAT_COOL_ADDRESS),
group_address_heat_cool_state=config.get(
ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS
),
operation_modes=config.get(ClimateSchema.CONF_OPERATION_MODES),
controller_modes=config.get(ClimateSchema.CONF_CONTROLLER_MODES),
)
return XknxClimate(
knx_module,
name=config[CONF_NAME],
group_address_temperature=config[ClimateSchema.CONF_TEMPERATURE_ADDRESS],
group_address_target_temperature=config.get(
ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS
),
group_address_target_temperature_state=config[
ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS
],
group_address_setpoint_shift=config.get(
ClimateSchema.CONF_SETPOINT_SHIFT_ADDRESS
),
group_address_setpoint_shift_state=config.get(
ClimateSchema.CONF_SETPOINT_SHIFT_STATE_ADDRESS
),
setpoint_shift_mode=config.get(ClimateSchema.CONF_SETPOINT_SHIFT_MODE),
setpoint_shift_max=config[ClimateSchema.CONF_SETPOINT_SHIFT_MAX],
setpoint_shift_min=config[ClimateSchema.CONF_SETPOINT_SHIFT_MIN],
temperature_step=config[ClimateSchema.CONF_TEMPERATURE_STEP],
group_address_on_off=config.get(ClimateSchema.CONF_ON_OFF_ADDRESS),
group_address_on_off_state=config.get(ClimateSchema.CONF_ON_OFF_STATE_ADDRESS),
min_temp=config.get(ClimateSchema.CONF_MIN_TEMP),
max_temp=config.get(ClimateSchema.CONF_MAX_TEMP),
mode=climate_mode,
on_off_invert=config[ClimateSchema.CONF_ON_OFF_INVERT],
create_temperature_sensors=config[
ClimateSchema.CONF_CREATE_TEMPERATURE_SENSORS
],
)
def _create_sensor(knx_module: XKNX, config: ConfigType) -> XknxSensor: def _create_sensor(knx_module: XKNX, config: ConfigType) -> XknxSensor:
"""Return a KNX sensor to be used within XKNX.""" """Return a KNX sensor to be used within XKNX."""
return XknxSensor( return XknxSensor(

View File

@ -159,7 +159,6 @@ class ClimateSchema:
CONF_ON_OFF_INVERT = "on_off_invert" CONF_ON_OFF_INVERT = "on_off_invert"
CONF_MIN_TEMP = "min_temp" CONF_MIN_TEMP = "min_temp"
CONF_MAX_TEMP = "max_temp" CONF_MAX_TEMP = "max_temp"
CONF_CREATE_TEMPERATURE_SENSORS = "create_temperature_sensors"
DEFAULT_NAME = "KNX Climate" DEFAULT_NAME = "KNX Climate"
DEFAULT_SETPOINT_SHIFT_MODE = "DPT6010" DEFAULT_SETPOINT_SHIFT_MODE = "DPT6010"
@ -171,6 +170,8 @@ class ClimateSchema:
SCHEMA = vol.All( SCHEMA = vol.All(
# deprecated since September 2020 # deprecated since September 2020
cv.deprecated("setpoint_shift_step", replacement_key=CONF_TEMPERATURE_STEP), cv.deprecated("setpoint_shift_step", replacement_key=CONF_TEMPERATURE_STEP),
# deprecated since 2021.6
cv.deprecated("create_temperature_sensors"),
vol.Schema( vol.Schema(
{ {
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
@ -228,9 +229,6 @@ class ClimateSchema:
), ),
vol.Optional(CONF_MIN_TEMP): vol.Coerce(float), vol.Optional(CONF_MIN_TEMP): vol.Coerce(float),
vol.Optional(CONF_MAX_TEMP): vol.Coerce(float), vol.Optional(CONF_MAX_TEMP): vol.Coerce(float),
vol.Optional(
CONF_CREATE_TEMPERATURE_SENSORS, default=False
): cv.boolean,
} }
), ),
) )