Update xknx to 0.15.3 (#42026)

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
Marvin Wichmann 2020-11-13 09:37:45 +01:00 committed by GitHub
parent 1a888433cb
commit 899fc3d35a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 30 deletions

View File

@ -41,3 +41,13 @@ class KNXBinarySensor(KnxEntity, BinarySensorEntity):
def device_state_attributes(self) -> Optional[Dict[str, Any]]: def device_state_attributes(self) -> Optional[Dict[str, Any]]:
"""Return device specific state attributes.""" """Return device specific state attributes."""
return {ATTR_COUNTER: self._device.counter} return {ATTR_COUNTER: self._device.counter}
@property
def force_update(self) -> bool:
"""
Return True if state updates should be forced.
If True, a state change will be triggered anytime the state property is
updated, not just when the value changes.
"""
return self._device.ignore_internal_state

View File

@ -2,7 +2,7 @@
from typing import List, Optional from typing import List, Optional
from xknx.devices import Climate as XknxClimate from xknx.devices import Climate as XknxClimate
from xknx.dpt import HVACOperationMode from xknx.dpt import HVACControllerMode, HVACOperationMode
from homeassistant.components.climate import ClimateEntity from homeassistant.components.climate import ClimateEntity
from homeassistant.components.climate.const import ( from homeassistant.components.climate.const import (
@ -14,11 +14,11 @@ from homeassistant.components.climate.const import (
) )
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
from .const import DOMAIN, OPERATION_MODES, PRESET_MODES from .const import CONTROLLER_MODES, DOMAIN, PRESET_MODES
from .knx_entity import KnxEntity from .knx_entity import KnxEntity
OPERATION_MODES_INV = dict(reversed(item) for item in OPERATION_MODES.items()) CONTROLLER_MODES_INV = {value: key for key, value in CONTROLLER_MODES.items()}
PRESET_MODES_INV = dict(reversed(item) for item in PRESET_MODES.items()) PRESET_MODES_INV = {value: key for key, value in PRESET_MODES.items()}
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
@ -92,27 +92,27 @@ class KNXClimate(KnxEntity, ClimateEntity):
"""Return current operation ie. heat, cool, idle.""" """Return current operation ie. heat, cool, idle."""
if self._device.supports_on_off and not self._device.is_on: if self._device.supports_on_off and not self._device.is_on:
return HVAC_MODE_OFF return HVAC_MODE_OFF
if self._device.mode.supports_operation_mode: if self._device.mode.supports_controller_mode:
return OPERATION_MODES.get( return CONTROLLER_MODES.get(
self._device.mode.operation_mode.value, HVAC_MODE_HEAT self._device.mode.controller_mode.value, HVAC_MODE_HEAT
) )
# default to "heat" # default to "heat"
return HVAC_MODE_HEAT return HVAC_MODE_HEAT
@property @property
def hvac_modes(self) -> Optional[List[str]]: def hvac_modes(self) -> Optional[List[str]]:
"""Return the list of available operation modes.""" """Return the list of available operation/controller modes."""
_operations = [ _controller_modes = [
OPERATION_MODES.get(operation_mode.value) CONTROLLER_MODES.get(controller_mode.value)
for operation_mode in self._device.mode.operation_modes for controller_mode in self._device.mode.controller_modes
] ]
if self._device.supports_on_off: if self._device.supports_on_off:
if not _operations: if not _controller_modes:
_operations.append(HVAC_MODE_HEAT) _controller_modes.append(HVAC_MODE_HEAT)
_operations.append(HVAC_MODE_OFF) _controller_modes.append(HVAC_MODE_OFF)
_modes = list(set(filter(None, _operations))) _modes = list(set(filter(None, _controller_modes)))
# default to ["heat"] # default to ["heat"]
return _modes if _modes else [HVAC_MODE_HEAT] return _modes if _modes else [HVAC_MODE_HEAT]
@ -123,11 +123,11 @@ class KNXClimate(KnxEntity, ClimateEntity):
else: else:
if self._device.supports_on_off and not self._device.is_on: if self._device.supports_on_off and not self._device.is_on:
await self._device.turn_on() await self._device.turn_on()
if self._device.mode.supports_operation_mode: if self._device.mode.supports_controller_mode:
knx_operation_mode = HVACOperationMode( knx_controller_mode = HVACControllerMode(
OPERATION_MODES_INV.get(hvac_mode) CONTROLLER_MODES_INV.get(hvac_mode)
) )
await self._device.mode.set_operation_mode(knx_operation_mode) await self._device.mode.set_controller_mode(knx_controller_mode)
self.async_write_ha_state() self.async_write_ha_state()
@property @property

View File

@ -11,13 +11,16 @@ from homeassistant.components.climate.const import (
PRESET_AWAY, PRESET_AWAY,
PRESET_COMFORT, PRESET_COMFORT,
PRESET_ECO, PRESET_ECO,
PRESET_NONE,
PRESET_SLEEP, PRESET_SLEEP,
) )
DOMAIN = "knx" DOMAIN = "knx"
CONF_INVERT = "invert"
CONF_STATE_ADDRESS = "state_address" CONF_STATE_ADDRESS = "state_address"
CONF_SYNC_STATE = "sync_state" CONF_SYNC_STATE = "sync_state"
CONF_RESET_AFTER = "reset_after"
class ColorTempModes(Enum): class ColorTempModes(Enum):
@ -41,8 +44,8 @@ class SupportedPlatforms(Enum):
weather = "weather" weather = "weather"
# Map KNX operation modes to HA modes. This list might not be complete. # Map KNX controller modes to HA modes. This list might not be complete.
OPERATION_MODES = { CONTROLLER_MODES = {
# Map DPT 20.105 HVAC control modes # Map DPT 20.105 HVAC control modes
"Auto": HVAC_MODE_AUTO, "Auto": HVAC_MODE_AUTO,
"Heat": HVAC_MODE_HEAT, "Heat": HVAC_MODE_HEAT,
@ -54,6 +57,7 @@ OPERATION_MODES = {
PRESET_MODES = { PRESET_MODES = {
# Map DPT 20.102 HVAC operating modes to HA presets # Map DPT 20.102 HVAC operating modes to HA presets
"Auto": PRESET_NONE,
"Frost Protection": PRESET_ECO, "Frost Protection": PRESET_ECO,
"Night": PRESET_SLEEP, "Night": PRESET_SLEEP,
"Standby": PRESET_AWAY, "Standby": PRESET_AWAY,

View File

@ -164,6 +164,7 @@ def _create_climate(knx_module: XKNX, config: ConfigType) -> XknxClimate:
ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS
), ),
operation_modes=config.get(ClimateSchema.CONF_OPERATION_MODES), operation_modes=config.get(ClimateSchema.CONF_OPERATION_MODES),
controller_modes=config.get(ClimateSchema.CONF_CONTROLLER_MODES),
) )
return XknxClimate( return XknxClimate(
@ -202,6 +203,7 @@ def _create_switch(knx_module: XKNX, config: ConfigType) -> XknxSwitch:
name=config[CONF_NAME], name=config[CONF_NAME],
group_address=config[CONF_ADDRESS], group_address=config[CONF_ADDRESS],
group_address_state=config.get(SwitchSchema.CONF_STATE_ADDRESS), group_address_state=config.get(SwitchSchema.CONF_STATE_ADDRESS),
invert=config.get(SwitchSchema.CONF_INVERT),
) )
@ -212,6 +214,7 @@ def _create_sensor(knx_module: XKNX, config: ConfigType) -> XknxSensor:
name=config[CONF_NAME], name=config[CONF_NAME],
group_address_state=config[SensorSchema.CONF_STATE_ADDRESS], group_address_state=config[SensorSchema.CONF_STATE_ADDRESS],
sync_state=config[SensorSchema.CONF_SYNC_STATE], sync_state=config[SensorSchema.CONF_SYNC_STATE],
always_callback=config[SensorSchema.CONF_ALWAYS_CALLBACK],
value_type=config[CONF_TYPE], value_type=config[CONF_TYPE],
) )
@ -243,10 +246,11 @@ def _create_binary_sensor(knx_module: XKNX, config: ConfigType) -> XknxBinarySen
knx_module, knx_module,
name=device_name, name=device_name,
group_address_state=config[BinarySensorSchema.CONF_STATE_ADDRESS], group_address_state=config[BinarySensorSchema.CONF_STATE_ADDRESS],
invert=config.get(BinarySensorSchema.CONF_INVERT),
sync_state=config[BinarySensorSchema.CONF_SYNC_STATE], sync_state=config[BinarySensorSchema.CONF_SYNC_STATE],
device_class=config.get(CONF_DEVICE_CLASS), device_class=config.get(CONF_DEVICE_CLASS),
ignore_internal_state=config[BinarySensorSchema.CONF_IGNORE_INTERNAL_STATE], ignore_internal_state=config[BinarySensorSchema.CONF_IGNORE_INTERNAL_STATE],
context_timeout=config[BinarySensorSchema.CONF_CONTEXT_TIMEOUT], context_timeout=config.get(BinarySensorSchema.CONF_CONTEXT_TIMEOUT),
reset_after=config.get(BinarySensorSchema.CONF_RESET_AFTER), reset_after=config.get(BinarySensorSchema.CONF_RESET_AFTER),
) )

View File

@ -2,7 +2,7 @@
"domain": "knx", "domain": "knx",
"name": "KNX", "name": "KNX",
"documentation": "https://www.home-assistant.io/integrations/knx", "documentation": "https://www.home-assistant.io/integrations/knx",
"requirements": ["xknx==0.15.0"], "requirements": ["xknx==0.15.3"],
"codeowners": ["@Julius2342", "@farmio", "@marvin-w"], "codeowners": ["@Julius2342", "@farmio", "@marvin-w"],
"quality_scale": "silver" "quality_scale": "silver"
} }

View File

@ -15,9 +15,11 @@ from homeassistant.const import (
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from .const import ( from .const import (
CONF_INVERT,
CONF_RESET_AFTER,
CONF_STATE_ADDRESS, CONF_STATE_ADDRESS,
CONF_SYNC_STATE, CONF_SYNC_STATE,
OPERATION_MODES, CONTROLLER_MODES,
PRESET_MODES, PRESET_MODES,
ColorTempModes, ColorTempModes,
) )
@ -84,9 +86,10 @@ class BinarySensorSchema:
CONF_STATE_ADDRESS = CONF_STATE_ADDRESS CONF_STATE_ADDRESS = CONF_STATE_ADDRESS
CONF_SYNC_STATE = CONF_SYNC_STATE CONF_SYNC_STATE = CONF_SYNC_STATE
CONF_INVERT = CONF_INVERT
CONF_IGNORE_INTERNAL_STATE = "ignore_internal_state" CONF_IGNORE_INTERNAL_STATE = "ignore_internal_state"
CONF_CONTEXT_TIMEOUT = "context_timeout" CONF_CONTEXT_TIMEOUT = "context_timeout"
CONF_RESET_AFTER = "reset_after" CONF_RESET_AFTER = CONF_RESET_AFTER
DEFAULT_NAME = "KNX Binary Sensor" DEFAULT_NAME = "KNX Binary Sensor"
@ -101,12 +104,13 @@ class BinarySensorSchema:
cv.boolean, cv.boolean,
cv.string, cv.string,
), ),
vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=True): cv.boolean, vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=False): cv.boolean,
vol.Optional(CONF_CONTEXT_TIMEOUT, default=1.0): vol.All( vol.Required(CONF_STATE_ADDRESS): cv.string,
vol.Optional(CONF_CONTEXT_TIMEOUT): vol.All(
vol.Coerce(float), vol.Range(min=0, max=10) vol.Coerce(float), vol.Range(min=0, max=10)
), ),
vol.Required(CONF_STATE_ADDRESS): cv.string,
vol.Optional(CONF_DEVICE_CLASS): cv.string, vol.Optional(CONF_DEVICE_CLASS): cv.string,
vol.Optional(CONF_INVERT): cv.boolean,
vol.Optional(CONF_RESET_AFTER): cv.positive_int, vol.Optional(CONF_RESET_AFTER): cv.positive_int,
} }
), ),
@ -187,6 +191,7 @@ class ClimateSchema:
CONF_OPERATION_MODE_COMFORT_ADDRESS = "operation_mode_comfort_address" CONF_OPERATION_MODE_COMFORT_ADDRESS = "operation_mode_comfort_address"
CONF_OPERATION_MODE_STANDBY_ADDRESS = "operation_mode_standby_address" CONF_OPERATION_MODE_STANDBY_ADDRESS = "operation_mode_standby_address"
CONF_OPERATION_MODES = "operation_modes" CONF_OPERATION_MODES = "operation_modes"
CONF_CONTROLLER_MODES = "controller_modes"
CONF_ON_OFF_ADDRESS = "on_off_address" CONF_ON_OFF_ADDRESS = "on_off_address"
CONF_ON_OFF_STATE_ADDRESS = "on_off_state_address" CONF_ON_OFF_STATE_ADDRESS = "on_off_state_address"
CONF_ON_OFF_INVERT = "on_off_invert" CONF_ON_OFF_INVERT = "on_off_invert"
@ -240,7 +245,10 @@ class ClimateSchema:
CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT
): cv.boolean, ): cv.boolean,
vol.Optional(CONF_OPERATION_MODES): vol.All( vol.Optional(CONF_OPERATION_MODES): vol.All(
cv.ensure_list, [vol.In({**OPERATION_MODES, **PRESET_MODES})] cv.ensure_list, [vol.In({**PRESET_MODES})]
),
vol.Optional(CONF_CONTROLLER_MODES): vol.All(
cv.ensure_list, [vol.In({**CONTROLLER_MODES})]
), ),
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),
@ -252,6 +260,7 @@ class ClimateSchema:
class SwitchSchema: class SwitchSchema:
"""Voluptuous schema for KNX switches.""" """Voluptuous schema for KNX switches."""
CONF_INVERT = CONF_INVERT
CONF_STATE_ADDRESS = CONF_STATE_ADDRESS CONF_STATE_ADDRESS = CONF_STATE_ADDRESS
DEFAULT_NAME = "KNX Switch" DEFAULT_NAME = "KNX Switch"
@ -260,6 +269,7 @@ class SwitchSchema:
vol.Required(CONF_ADDRESS): cv.string, vol.Required(CONF_ADDRESS): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_STATE_ADDRESS): cv.string, vol.Optional(CONF_STATE_ADDRESS): cv.string,
vol.Optional(CONF_INVERT): cv.boolean,
} }
) )
@ -299,6 +309,7 @@ class NotifySchema:
class SensorSchema: class SensorSchema:
"""Voluptuous schema for KNX sensors.""" """Voluptuous schema for KNX sensors."""
CONF_ALWAYS_CALLBACK = "always_callback"
CONF_STATE_ADDRESS = CONF_STATE_ADDRESS CONF_STATE_ADDRESS = CONF_STATE_ADDRESS
CONF_SYNC_STATE = CONF_SYNC_STATE CONF_SYNC_STATE = CONF_SYNC_STATE
DEFAULT_NAME = "KNX Sensor" DEFAULT_NAME = "KNX Sensor"
@ -311,6 +322,7 @@ class SensorSchema:
cv.boolean, cv.boolean,
cv.string, cv.string,
), ),
vol.Optional(CONF_ALWAYS_CALLBACK, default=False): cv.boolean,
vol.Required(CONF_STATE_ADDRESS): cv.string, vol.Required(CONF_STATE_ADDRESS): cv.string,
vol.Required(CONF_TYPE): vol.Any(int, float, str), vol.Required(CONF_TYPE): vol.Any(int, float, str),
} }

View File

@ -41,3 +41,13 @@ class KNXSensor(KnxEntity, Entity):
if device_class in DEVICE_CLASSES: if device_class in DEVICE_CLASSES:
return device_class return device_class
return None return None
@property
def force_update(self) -> bool:
"""
Return True if state updates should be forced.
If True, a state change will be triggered anytime the state property is
updated, not just when the value changes.
"""
return self._device.always_callback

View File

@ -2304,7 +2304,7 @@ xboxapi==2.0.1
xfinity-gateway==0.0.4 xfinity-gateway==0.0.4
# homeassistant.components.knx # homeassistant.components.knx
xknx==0.15.0 xknx==0.15.3
# homeassistant.components.bluesound # homeassistant.components.bluesound
# homeassistant.components.rest # homeassistant.components.rest