Update xknx to 0.14.2 (#40304)
* Updates xknx to 0.14.0 * Review: Explicity add state attributes to weather device * Review: Remove state attributes from weather device * Review: Add `counter` as a state attribute to binary_sensors
This commit is contained in:
parent
0c077685b6
commit
45288431f9
8 changed files with 61 additions and 63 deletions
|
@ -6,7 +6,12 @@ from xknx import XKNX
|
|||
from xknx.devices import DateTime, ExposeSensor
|
||||
from xknx.dpt import DPTArray, DPTBase, DPTBinary
|
||||
from xknx.exceptions import XKNXException
|
||||
from xknx.io import DEFAULT_MCAST_PORT, ConnectionConfig, ConnectionType
|
||||
from xknx.io import (
|
||||
DEFAULT_MCAST_GRP,
|
||||
DEFAULT_MCAST_PORT,
|
||||
ConnectionConfig,
|
||||
ConnectionType,
|
||||
)
|
||||
from xknx.telegram import AddressFilter, GroupAddress, Telegram
|
||||
|
||||
from homeassistant.const import (
|
||||
|
@ -48,6 +53,9 @@ CONF_KNX_ROUTING = "routing"
|
|||
CONF_KNX_TUNNELING = "tunneling"
|
||||
CONF_KNX_FIRE_EVENT = "fire_event"
|
||||
CONF_KNX_FIRE_EVENT_FILTER = "fire_event_filter"
|
||||
CONF_KNX_INDIVIDUAL_ADDRESS = "individual_address"
|
||||
CONF_KNX_MCAST_GRP = "multicast_group"
|
||||
CONF_KNX_MCAST_PORT = "multicast_port"
|
||||
CONF_KNX_STATE_UPDATER = "state_updater"
|
||||
CONF_KNX_RATE_LIMIT = "rate_limit"
|
||||
CONF_KNX_EXPOSE = "expose"
|
||||
|
@ -72,6 +80,11 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
vol.Inclusive(CONF_KNX_FIRE_EVENT_FILTER, "fire_ev"): vol.All(
|
||||
cv.ensure_list, [cv.string]
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS
|
||||
): cv.string,
|
||||
vol.Optional(CONF_KNX_MCAST_GRP, default=DEFAULT_MCAST_GRP): cv.string,
|
||||
vol.Optional(CONF_KNX_MCAST_PORT, default=DEFAULT_MCAST_PORT): cv.port,
|
||||
vol.Optional(CONF_KNX_STATE_UPDATER, default=True): cv.boolean,
|
||||
vol.Optional(CONF_KNX_RATE_LIMIT, default=20): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
|
@ -130,17 +143,15 @@ async def async_setup(hass, config):
|
|||
hass.data[DATA_KNX].async_create_exposures()
|
||||
await hass.data[DATA_KNX].start()
|
||||
except XKNXException as ex:
|
||||
_LOGGER.warning("Can't connect to KNX interface: %s", ex)
|
||||
_LOGGER.warning("Could not connect to KNX interface: %s", ex)
|
||||
hass.components.persistent_notification.async_create(
|
||||
f"Can't connect to KNX interface: <br><b>{ex}</b>", title="KNX"
|
||||
f"Could not connect to KNX interface: <br><b>{ex}</b>", title="KNX"
|
||||
)
|
||||
|
||||
for platform in SupportedPlatforms:
|
||||
if platform.value in config[DOMAIN]:
|
||||
for device_config in config[DOMAIN][platform.value]:
|
||||
create_knx_device(
|
||||
hass, platform, hass.data[DATA_KNX].xknx, device_config
|
||||
)
|
||||
create_knx_device(platform, hass.data[DATA_KNX].xknx, device_config)
|
||||
|
||||
# We need to wait until all entities are loaded into the device list since they could also be created from other platforms
|
||||
for platform in SupportedPlatforms:
|
||||
|
@ -181,7 +192,10 @@ class KNXModule:
|
|||
self.xknx = XKNX(
|
||||
config=self.config_file(),
|
||||
loop=self.hass.loop,
|
||||
own_address=self.config[DOMAIN][CONF_KNX_INDIVIDUAL_ADDRESS],
|
||||
rate_limit=self.config[DOMAIN][CONF_KNX_RATE_LIMIT],
|
||||
multicast_group=self.config[DOMAIN][CONF_KNX_MCAST_GRP],
|
||||
multicast_port=self.config[DOMAIN][CONF_KNX_MCAST_PORT],
|
||||
)
|
||||
|
||||
async def start(self):
|
||||
|
@ -229,12 +243,10 @@ class KNXModule:
|
|||
def connection_config_tunneling(self):
|
||||
"""Return the connection_config if tunneling is configured."""
|
||||
gateway_ip = self.config[DOMAIN][CONF_KNX_TUNNELING][CONF_HOST]
|
||||
gateway_port = self.config[DOMAIN][CONF_KNX_TUNNELING].get(CONF_PORT)
|
||||
gateway_port = self.config[DOMAIN][CONF_KNX_TUNNELING][CONF_PORT]
|
||||
local_ip = self.config[DOMAIN][CONF_KNX_TUNNELING].get(
|
||||
ConnectionSchema.CONF_KNX_LOCAL_IP
|
||||
)
|
||||
if gateway_port is None:
|
||||
gateway_port = DEFAULT_MCAST_PORT
|
||||
return ConnectionConfig(
|
||||
connection_type=ConnectionType.TUNNELING,
|
||||
gateway_ip=gateway_ip,
|
||||
|
@ -267,7 +279,7 @@ class KNXModule:
|
|||
attribute = to_expose.get(ExposeSchema.CONF_KNX_EXPOSE_ATTRIBUTE)
|
||||
default = to_expose.get(ExposeSchema.CONF_KNX_EXPOSE_DEFAULT)
|
||||
address = to_expose.get(ExposeSchema.CONF_KNX_EXPOSE_ADDRESS)
|
||||
if expose_type in ["time", "date", "datetime"]:
|
||||
if expose_type.lower() in ["time", "date", "datetime"]:
|
||||
exposure = KNXExposeTime(self.xknx, expose_type, address)
|
||||
exposure.async_register()
|
||||
self.exposures.append(exposure)
|
||||
|
@ -313,29 +325,29 @@ class KNXModule:
|
|||
payload = calculate_payload(attr_payload)
|
||||
address = GroupAddress(attr_address)
|
||||
|
||||
telegram = Telegram()
|
||||
telegram.payload = payload
|
||||
telegram.group_address = address
|
||||
telegram = Telegram(group_address=address, payload=payload)
|
||||
await self.xknx.telegrams.put(telegram)
|
||||
|
||||
|
||||
class KNXExposeTime:
|
||||
"""Object to Expose Time/Date object to KNX bus."""
|
||||
|
||||
def __init__(self, xknx, expose_type, address):
|
||||
def __init__(self, xknx: XKNX, expose_type: str, address: str):
|
||||
"""Initialize of Expose class."""
|
||||
self.xknx = xknx
|
||||
self.type = expose_type
|
||||
self.expose_type = expose_type
|
||||
self.address = address
|
||||
self.device = None
|
||||
|
||||
@callback
|
||||
def async_register(self):
|
||||
"""Register listener."""
|
||||
broadcast_type_string = self.type.upper()
|
||||
broadcast_type = broadcast_type_string
|
||||
self.device = DateTime(
|
||||
self.xknx, "Time", broadcast_type=broadcast_type, group_address=self.address
|
||||
self.xknx,
|
||||
name=self.expose_type.capitalize(),
|
||||
broadcast_type=self.expose_type.upper(),
|
||||
localtime=True,
|
||||
group_address=self.address,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
"""Support for KNX/IP binary sensors."""
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from xknx.devices import BinarySensor as XknxBinarySensor
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.core import callback
|
||||
|
||||
from . import DATA_KNX
|
||||
from .const import ATTR_COUNTER, DATA_KNX
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
|
@ -27,7 +29,7 @@ class KNXBinarySensor(BinarySensorEntity):
|
|||
def async_register_callbacks(self):
|
||||
"""Register callbacks to update hass after device was changed."""
|
||||
|
||||
async def after_update_callback(device):
|
||||
async def after_update_callback(device: XknxBinarySensor):
|
||||
"""Call after device was updated."""
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -65,3 +67,8 @@ class KNXBinarySensor(BinarySensorEntity):
|
|||
def is_on(self):
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.device.is_on()
|
||||
|
||||
@property
|
||||
def device_state_attributes(self) -> Optional[Dict[str, Any]]:
|
||||
"""Return device specific state attributes."""
|
||||
return {ATTR_COUNTER: self.device.counter}
|
||||
|
|
|
@ -60,3 +60,5 @@ PRESET_MODES = {
|
|||
"Standby": PRESET_AWAY,
|
||||
"Comfort": PRESET_COMFORT,
|
||||
}
|
||||
|
||||
ATTR_COUNTER = "counter"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Factory function to initialize KNX devices from config."""
|
||||
from xknx import XKNX
|
||||
from xknx.devices import (
|
||||
ActionCallback as XknxActionCallback,
|
||||
BinarySensor as XknxBinarySensor,
|
||||
Climate as XknxClimate,
|
||||
ClimateMode as XknxClimateMode,
|
||||
|
@ -16,11 +15,9 @@ from xknx.devices import (
|
|||
)
|
||||
|
||||
from homeassistant.const import CONF_ADDRESS, CONF_DEVICE_CLASS, CONF_NAME, CONF_TYPE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.script import Script
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import DOMAIN, ColorTempModes, SupportedPlatforms
|
||||
from .const import ColorTempModes, SupportedPlatforms
|
||||
from .schema import (
|
||||
BinarySensorSchema,
|
||||
ClimateSchema,
|
||||
|
@ -34,7 +31,6 @@ from .schema import (
|
|||
|
||||
|
||||
def create_knx_device(
|
||||
hass: HomeAssistant,
|
||||
platform: SupportedPlatforms,
|
||||
knx_module: XKNX,
|
||||
config: ConfigType,
|
||||
|
@ -62,7 +58,7 @@ def create_knx_device(
|
|||
return _create_scene(knx_module, config)
|
||||
|
||||
if platform is SupportedPlatforms.binary_sensor:
|
||||
return _create_binary_sensor(hass, knx_module, config)
|
||||
return _create_binary_sensor(knx_module, config)
|
||||
|
||||
if platform is SupportedPlatforms.weather:
|
||||
return _create_weather(knx_module, config)
|
||||
|
@ -239,24 +235,9 @@ def _create_scene(knx_module: XKNX, config: ConfigType) -> XknxScene:
|
|||
)
|
||||
|
||||
|
||||
def _create_binary_sensor(
|
||||
hass: HomeAssistant, knx_module: XKNX, config: ConfigType
|
||||
) -> XknxBinarySensor:
|
||||
def _create_binary_sensor(knx_module: XKNX, config: ConfigType) -> XknxBinarySensor:
|
||||
"""Return a KNX binary sensor to be used within XKNX."""
|
||||
device_name = config[CONF_NAME]
|
||||
actions = []
|
||||
automations = config.get(BinarySensorSchema.CONF_AUTOMATION)
|
||||
if automations is not None:
|
||||
for automation in automations:
|
||||
counter = automation[BinarySensorSchema.CONF_COUNTER]
|
||||
hook = automation[BinarySensorSchema.CONF_HOOK]
|
||||
action = automation[BinarySensorSchema.CONF_ACTION]
|
||||
script_name = f"{device_name} turn ON script"
|
||||
script = Script(hass, action, script_name, DOMAIN)
|
||||
action = XknxActionCallback(
|
||||
knx_module, script.async_run, hook=hook, counter=counter
|
||||
)
|
||||
actions.append(action)
|
||||
|
||||
return XknxBinarySensor(
|
||||
knx_module,
|
||||
|
@ -265,8 +246,8 @@ def _create_binary_sensor(
|
|||
sync_state=config[BinarySensorSchema.CONF_SYNC_STATE],
|
||||
device_class=config.get(CONF_DEVICE_CLASS),
|
||||
ignore_internal_state=config[BinarySensorSchema.CONF_IGNORE_INTERNAL_STATE],
|
||||
context_timeout=config[BinarySensorSchema.CONF_CONTEXT_TIMEOUT],
|
||||
reset_after=config.get(BinarySensorSchema.CONF_RESET_AFTER),
|
||||
actions=actions,
|
||||
)
|
||||
|
||||
|
||||
|
@ -287,6 +268,9 @@ def _create_weather(knx_module: XKNX, config: ConfigType) -> XknxWeather:
|
|||
group_address_brightness_west=config.get(
|
||||
WeatherSchema.CONF_KNX_BRIGHTNESS_WEST_ADDRESS
|
||||
),
|
||||
group_address_brightness_north=config.get(
|
||||
WeatherSchema.CONF_KNX_BRIGHTNESS_NORTH_ADDRESS
|
||||
),
|
||||
group_address_wind_speed=config.get(WeatherSchema.CONF_KNX_WIND_SPEED_ADDRESS),
|
||||
group_address_rain_alarm=config.get(WeatherSchema.CONF_KNX_RAIN_ALARM_ADDRESS),
|
||||
group_address_frost_alarm=config.get(
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
"domain": "knx",
|
||||
"name": "KNX",
|
||||
"documentation": "https://www.home-assistant.io/integrations/knx",
|
||||
"requirements": ["xknx==0.13.0"],
|
||||
"requirements": ["xknx==0.14.2"],
|
||||
"codeowners": ["@Julius2342", "@farmio", "@marvin-w"]
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Voluptuous schemas for the KNX integration."""
|
||||
import voluptuous as vol
|
||||
from xknx.devices.climate import SetpointShiftMode
|
||||
from xknx.io import DEFAULT_MCAST_PORT
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_ADDRESS,
|
||||
|
@ -29,9 +30,9 @@ class ConnectionSchema:
|
|||
|
||||
TUNNELING_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_MCAST_PORT): cv.port,
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_KNX_LOCAL_IP): cv.string,
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -84,27 +85,14 @@ class BinarySensorSchema:
|
|||
CONF_STATE_ADDRESS = CONF_STATE_ADDRESS
|
||||
CONF_SYNC_STATE = CONF_SYNC_STATE
|
||||
CONF_IGNORE_INTERNAL_STATE = "ignore_internal_state"
|
||||
CONF_AUTOMATION = "automation"
|
||||
CONF_HOOK = "hook"
|
||||
CONF_DEFAULT_HOOK = "on"
|
||||
CONF_COUNTER = "counter"
|
||||
CONF_DEFAULT_COUNTER = 1
|
||||
CONF_ACTION = "action"
|
||||
CONF_CONTEXT_TIMEOUT = "context_timeout"
|
||||
CONF_RESET_AFTER = "reset_after"
|
||||
|
||||
DEFAULT_NAME = "KNX Binary Sensor"
|
||||
AUTOMATION_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_HOOK, default=CONF_DEFAULT_HOOK): cv.string,
|
||||
vol.Optional(CONF_COUNTER, default=CONF_DEFAULT_COUNTER): cv.port,
|
||||
vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA,
|
||||
}
|
||||
)
|
||||
|
||||
AUTOMATIONS_SCHEMA = vol.All(cv.ensure_list, [AUTOMATION_SCHEMA])
|
||||
|
||||
SCHEMA = vol.All(
|
||||
cv.deprecated("significant_bit"),
|
||||
cv.deprecated("automation"),
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
|
@ -113,11 +101,13 @@ class BinarySensorSchema:
|
|||
cv.boolean,
|
||||
cv.string,
|
||||
),
|
||||
vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=False): cv.boolean,
|
||||
vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=True): cv.boolean,
|
||||
vol.Optional(CONF_CONTEXT_TIMEOUT, default=1.0): vol.All(
|
||||
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_RESET_AFTER): cv.positive_int,
|
||||
vol.Optional(CONF_AUTOMATION): AUTOMATIONS_SCHEMA,
|
||||
}
|
||||
),
|
||||
)
|
||||
|
@ -350,6 +340,7 @@ class WeatherSchema:
|
|||
CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS = "address_brightness_south"
|
||||
CONF_KNX_BRIGHTNESS_EAST_ADDRESS = "address_brightness_east"
|
||||
CONF_KNX_BRIGHTNESS_WEST_ADDRESS = "address_brightness_west"
|
||||
CONF_KNX_BRIGHTNESS_NORTH_ADDRESS = "address_brightness_north"
|
||||
CONF_KNX_WIND_SPEED_ADDRESS = "address_wind_speed"
|
||||
CONF_KNX_RAIN_ALARM_ADDRESS = "address_rain_alarm"
|
||||
CONF_KNX_FROST_ALARM_ADDRESS = "address_frost_alarm"
|
||||
|
@ -374,6 +365,7 @@ class WeatherSchema:
|
|||
vol.Optional(CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_BRIGHTNESS_EAST_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_BRIGHTNESS_WEST_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_BRIGHTNESS_NORTH_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_WIND_SPEED_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_RAIN_ALARM_ADDRESS): cv.string,
|
||||
vol.Optional(CONF_KNX_FROST_ALARM_ADDRESS): cv.string,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Support for KNX/IP weather station."""
|
||||
|
||||
from xknx.devices import Weather as XknxWeather
|
||||
|
||||
from homeassistant.components.weather import WeatherEntity
|
||||
|
|
|
@ -2265,7 +2265,7 @@ xboxapi==2.0.1
|
|||
xfinity-gateway==0.0.4
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==0.13.0
|
||||
xknx==0.14.2
|
||||
|
||||
# homeassistant.components.bluesound
|
||||
# homeassistant.components.rest
|
||||
|
|
Loading…
Add table
Reference in a new issue