Skip to content

Commit

Permalink
merge HA plugin from upstream 0.101.3 (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
farmio committed Nov 10, 2019
1 parent aaa07ba commit 616cc85
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 73 deletions.
30 changes: 7 additions & 23 deletions home-assistant-plugin/custom_components/xknx/__init__.py
Expand Up @@ -2,6 +2,12 @@
import logging

import voluptuous as vol
from xknx import XKNX
from xknx.devices import ActionCallback, DateTime, DateTimeBroadcastType, ExposeSensor
from xknx.dpt import DPTArray, DPTBinary
from xknx.exceptions import XKNXException
from xknx.io import DEFAULT_MCAST_PORT, ConnectionConfig, ConnectionType
from xknx.telegram import AddressFilter, GroupAddress, Telegram

from homeassistant.const import (
CONF_ENTITY_ID,
Expand Down Expand Up @@ -90,13 +96,10 @@

async def async_setup(hass, config):
"""Set up the KNX component."""
from xknx.exceptions import XKNXException

try:
hass.data[DATA_XKNX] = KNXModule(hass, config)
hass.data[DATA_XKNX].async_create_exposures()
await hass.data[DATA_XKNX].start()

except XKNXException as ex:
_LOGGER.warning("Can't connect to KNX interface: %s", ex)
hass.components.persistent_notification.async_create(
Expand Down Expand Up @@ -157,8 +160,6 @@ def __init__(self, hass, config):

def init_xknx(self):
"""Initialize of KNX object."""
from xknx import XKNX

self.xknx = XKNX(
config=self.config_file(),
loop=self.hass.loop,
Expand Down Expand Up @@ -198,17 +199,13 @@ def connection_config(self):

def connection_config_routing(self):
"""Return the connection_config if routing is configured."""
from xknx.io import ConnectionConfig, ConnectionType

local_ip = self.config[DOMAIN][CONF_XKNX_ROUTING].get(CONF_XKNX_LOCAL_IP)
return ConnectionConfig(
connection_type=ConnectionType.ROUTING, local_ip=local_ip
)

def connection_config_tunneling(self):
"""Return the connection_config if tunneling is configured."""
from xknx.io import ConnectionConfig, ConnectionType, DEFAULT_MCAST_PORT

gateway_ip = self.config[DOMAIN][CONF_XKNX_TUNNELING].get(CONF_HOST)
gateway_port = self.config[DOMAIN][CONF_XKNX_TUNNELING].get(CONF_PORT)
local_ip = self.config[DOMAIN][CONF_XKNX_TUNNELING].get(CONF_XKNX_LOCAL_IP)
Expand All @@ -224,8 +221,6 @@ def connection_config_tunneling(self):
def connection_config_auto(self):
"""Return the connection_config if auto is configured."""
# pylint: disable=no-self-use
from xknx.io import ConnectionConfig

return ConnectionConfig()

def register_callbacks(self):
Expand All @@ -234,8 +229,6 @@ def register_callbacks(self):
CONF_XKNX_FIRE_EVENT in self.config[DOMAIN]
and self.config[DOMAIN][CONF_XKNX_FIRE_EVENT]
):
from xknx.telegram import AddressFilter

address_filters = list(
map(AddressFilter, self.config[DOMAIN][CONF_XKNX_FIRE_EVENT_FILTER])
)
Expand Down Expand Up @@ -274,9 +267,6 @@ async def telegram_received_cb(self, telegram):

async def service_send_to_knx_bus(self, call):
"""Service for sending an arbitrary KNX message to the KNX bus."""
from xknx.dpt import DPTArray, DPTBinary
from xknx.telegram import GroupAddress, Telegram

attr_payload = call.data.get(SERVICE_XKNX_ATTR_PAYLOAD)
attr_address = call.data.get(SERVICE_XKNX_ATTR_ADDRESS)

Expand Down Expand Up @@ -305,9 +295,7 @@ def __init__(self, hass, device, hook, action, counter=1):
script_name = "{} turn ON script".format(device.get_name())
self.script = Script(hass, action, script_name)

import xknx

self.action = xknx.devices.ActionCallback(
self.action = ActionCallback(
hass.data[DATA_XKNX].xknx, self.script.async_run, hook=hook, counter=counter
)
device.actions.append(self.action)
Expand All @@ -326,8 +314,6 @@ def __init__(self, xknx, expose_type, address):
@callback
def async_register(self):
"""Register listener."""
from xknx.devices import DateTime, DateTimeBroadcastType

broadcast_type_string = self.type.upper()
broadcast_type = DateTimeBroadcastType[broadcast_type_string]
self.device = DateTime(
Expand All @@ -351,8 +337,6 @@ def __init__(self, hass, xknx, expose_type, entity_id, address):
@callback
def async_register(self):
"""Register listener."""
from xknx.devices import ExposeSensor

self.device = ExposeSensor(
self.xknx,
name=self.entity_id,
Expand Down
4 changes: 2 additions & 2 deletions home-assistant-plugin/custom_components/xknx/binary_sensor.py
@@ -1,5 +1,6 @@
"""Support for KNX/IP binary sensors."""
import voluptuous as vol
from xknx.devices import BinarySensor

from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorDevice
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
Expand Down Expand Up @@ -70,9 +71,8 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
def async_add_entities_config(hass, config, async_add_entities):
"""Set up binary senor for KNX platform configured within platform."""
name = config[CONF_NAME]
import xknx

binary_sensor = xknx.devices.BinarySensor(
binary_sensor = BinarySensor(
hass.data[DATA_XKNX].xknx,
name=name,
group_address_state=config[CONF_STATE_ADDRESS],
Expand Down
26 changes: 13 additions & 13 deletions home-assistant-plugin/custom_components/xknx/climate.py
@@ -1,20 +1,22 @@
"""Support for KNX/IP climate devices."""
from typing import Optional, List
from typing import List, Optional

import voluptuous as vol
from xknx.devices import Climate as XknxClimate, ClimateMode as XknxClimateMode
from xknx.dpt import HVACOperationMode

from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateDevice
from homeassistant.components.climate.const import (
HVAC_MODE_AUTO,
HVAC_MODE_COOL,
HVAC_MODE_DRY,
HVAC_MODE_FAN_ONLY,
HVAC_MODE_HEAT,
HVAC_MODE_OFF,
HVAC_MODE_COOL,
HVAC_MODE_AUTO,
PRESET_ECO,
PRESET_SLEEP,
PRESET_AWAY,
PRESET_COMFORT,
PRESET_ECO,
PRESET_SLEEP,
SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE,
)
Expand Down Expand Up @@ -44,13 +46,15 @@
CONF_OPERATION_MODES = "operation_modes"
CONF_ON_OFF_ADDRESS = "on_off_address"
CONF_ON_OFF_STATE_ADDRESS = "on_off_state_address"
CONF_ON_OFF_INVERT = "on_off_invert"
CONF_MIN_TEMP = "min_temp"
CONF_MAX_TEMP = "max_temp"

DEFAULT_NAME = "KNX Climate"
DEFAULT_SETPOINT_SHIFT_STEP = 0.5
DEFAULT_SETPOINT_SHIFT_MAX = 6
DEFAULT_SETPOINT_SHIFT_MIN = -6
DEFAULT_ON_OFF_INVERT = False
# Map KNX operation modes to HA modes. This list might not be full.
OPERATION_MODES = {
# Map DPT 201.105 HVAC control modes
Expand Down Expand Up @@ -102,6 +106,7 @@
vol.Optional(CONF_OPERATION_MODE_COMFORT_ADDRESS): cv.string,
vol.Optional(CONF_ON_OFF_ADDRESS): cv.string,
vol.Optional(CONF_ON_OFF_STATE_ADDRESS): cv.string,
vol.Optional(CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT): cv.boolean,
vol.Optional(CONF_OPERATION_MODES): vol.All(
cv.ensure_list, [vol.In(OPERATION_MODES)]
),
Expand Down Expand Up @@ -132,9 +137,7 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
@callback
def async_add_entities_config(hass, config, async_add_entities):
"""Set up climate for KNX platform configured within platform."""
import xknx

climate_mode = xknx.devices.ClimateMode(
climate_mode = XknxClimateMode(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME] + " Mode",
group_address_operation_mode=config.get(CONF_OPERATION_MODE_ADDRESS),
Expand Down Expand Up @@ -162,7 +165,7 @@ def async_add_entities_config(hass, config, async_add_entities):
)
hass.data[DATA_XKNX].xknx.devices.add(climate_mode)

climate = xknx.devices.Climate(
climate = XknxClimate(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address_temperature=config[CONF_TEMPERATURE_ADDRESS],
Expand All @@ -182,6 +185,7 @@ def async_add_entities_config(hass, config, async_add_entities):
min_temp=config.get(CONF_MIN_TEMP),
max_temp=config.get(CONF_MAX_TEMP),
mode=climate_mode,
on_off_invert=config[CONF_ON_OFF_INVERT],
)
hass.data[DATA_XKNX].xknx.devices.add(climate)

Expand Down Expand Up @@ -298,8 +302,6 @@ async def async_set_hvac_mode(self, hvac_mode: str) -> None:
elif self.device.supports_on_off and hvac_mode == HVAC_MODE_HEAT:
await self.device.turn_on()
elif self.device.mode.supports_operation_mode:
from xknx.dpt import HVACOperationMode

knx_operation_mode = HVACOperationMode(OPERATION_MODES_INV.get(hvac_mode))
await self.device.mode.set_operation_mode(knx_operation_mode)
await self.async_update_ha_state()
Expand Down Expand Up @@ -333,8 +335,6 @@ async def async_set_preset_mode(self, preset_mode: str) -> None:
This method must be run in the event loop and returns a coroutine.
"""
if self.device.mode.supports_operation_mode:
from xknx.dpt import HVACOperationMode

knx_operation_mode = HVACOperationMode(PRESET_MODES_INV.get(preset_mode))
await self.device.mode.set_operation_mode(knx_operation_mode)
await self.async_update_ha_state()
5 changes: 2 additions & 3 deletions home-assistant-plugin/custom_components/xknx/cover.py
@@ -1,5 +1,6 @@
"""Support for KNX/IP covers."""
import voluptuous as vol
from xknx.devices import Cover as XknxCover

from homeassistant.components.cover import (
ATTR_POSITION,
Expand Down Expand Up @@ -74,9 +75,7 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
@callback
def async_add_entities_config(hass, config, async_add_entities):
"""Set up cover for KNX platform configured within platform."""
import xknx

cover = xknx.devices.Cover(
cover = XknxCover(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address_long=config.get(CONF_MOVE_LONG_ADDRESS),
Expand Down
20 changes: 9 additions & 11 deletions home-assistant-plugin/custom_components/xknx/light.py
Expand Up @@ -2,6 +2,7 @@
from enum import Enum

import voluptuous as vol
from xknx.devices import Light as XknxLight

from homeassistant.components.light import (
ATTR_BRIGHTNESS,
Expand Down Expand Up @@ -98,8 +99,6 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
@callback
def async_add_entities_config(hass, config, async_add_entities):
"""Set up light for KNX platform configured within platform."""
import xknx

group_address_tunable_white = None
group_address_tunable_white_state = None
group_address_color_temp = None
Expand All @@ -111,7 +110,7 @@ def async_add_entities_config(hass, config, async_add_entities):
group_address_tunable_white = config.get(CONF_COLOR_TEMP_ADDRESS)
group_address_tunable_white_state = config.get(CONF_COLOR_TEMP_STATE_ADDRESS)

light = xknx.devices.Light(
light = XknxLight(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address_switch=config[CONF_ADDRESS],
Expand Down Expand Up @@ -181,13 +180,9 @@ def should_poll(self):
@property
def brightness(self):
"""Return the brightness of this light between 0..255."""
if self.device.supports_brightness:
return self.device.current_brightness
if (
self.device.supports_color or self.device.supports_rgbw
) and self.device.current_color:
return max(self.device.current_color)
return None
if not self.device.supports_brightness:
return None
return self.device.current_brightness

@property
def hs_color(self):
Expand Down Expand Up @@ -305,7 +300,10 @@ async def async_turn_on(self, **kwargs):
await self.device.set_color_temperature(kelvin)
elif self.device.supports_tunable_white and update_color_temp:
# calculate relative_ct from Kelvin to fit typical KNX devices
kelvin = int(color_util.color_temperature_mired_to_kelvin(mireds))
kelvin = min(
self._max_kelvin,
int(color_util.color_temperature_mired_to_kelvin(mireds)),
)
relative_ct = int(
255
* (kelvin - self._min_kelvin)
Expand Down
8 changes: 3 additions & 5 deletions home-assistant-plugin/custom_components/xknx/manifest.json
@@ -1,12 +1,10 @@
{
"domain": "xknx",
"name": "Knx",
"documentation": "https://www.home-assistant.io/components/knx",
"requirements": [
"xknx==0.11.1"
],
"documentation": "https://www.home-assistant.io/integrations/knx",
"requirements": [],
"dependencies": [],
"codeowners": [
"@Julius2342"
]
}
}
5 changes: 2 additions & 3 deletions home-assistant-plugin/custom_components/xknx/notify.py
@@ -1,5 +1,6 @@
"""Support for KNX/IP notification services."""
import voluptuous as vol
from xknx.devices import Notification as XknxNotification

from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationService
from homeassistant.const import CONF_ADDRESS, CONF_NAME
Expand Down Expand Up @@ -42,9 +43,7 @@ def async_get_service_discovery(hass, discovery_info):
@callback
def async_get_service_config(hass, config):
"""Set up notification for KNX platform configured within platform."""
import xknx

notification = xknx.devices.Notification(
notification = XknxNotification(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address=config[CONF_ADDRESS],
Expand Down
5 changes: 2 additions & 3 deletions home-assistant-plugin/custom_components/xknx/scene.py
@@ -1,5 +1,6 @@
"""Support for KNX scenes."""
import voluptuous as vol
from xknx.devices import Scene as XknxScene

from homeassistant.components.scene import CONF_PLATFORM, Scene
from homeassistant.const import CONF_ADDRESS, CONF_NAME
Expand Down Expand Up @@ -42,9 +43,7 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
@callback
def async_add_entities_config(hass, config, async_add_entities):
"""Set up scene for KNX platform configured within platform."""
import xknx

scene = xknx.devices.Scene(
scene = XknxScene(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address=config[CONF_ADDRESS],
Expand Down
5 changes: 2 additions & 3 deletions home-assistant-plugin/custom_components/xknx/sensor.py
@@ -1,5 +1,6 @@
"""Support for KNX/IP sensors."""
import voluptuous as vol
from xknx.devices import Sensor as XknxSensor

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, CONF_TYPE
Expand Down Expand Up @@ -44,9 +45,7 @@ def async_add_entities_discovery(hass, discovery_info, async_add_entities):
@callback
def async_add_entities_config(hass, config, async_add_entities):
"""Set up sensor for KNX platform configured within platform."""
import xknx

sensor = xknx.devices.Sensor(
sensor = XknxSensor(
hass.data[DATA_XKNX].xknx,
name=config[CONF_NAME],
group_address_state=config[CONF_STATE_ADDRESS],
Expand Down
12 changes: 8 additions & 4 deletions home-assistant-plugin/custom_components/xknx/services.yaml
@@ -1,5 +1,9 @@
group_write:
description: Turn a light on.
send:
description: "Send arbitrary data directly to the KNX bus."
fields:
address: {description: Group address(es) to write to., example: 1/1/0}
data: {description: KNX data to send., example: 1}
address:
description: "Group address(es) to write to."
example: "1/1/0"
payload:
description: "Payload to send to the bus. Integers are treated as DPT 1/2/3 payloads. For DPTs > 6 bits send a list. Each value represents 1 octet (0-255). Pad with 0 to DPT byte length."
example: "[0, 4]"

0 comments on commit 616cc85

Please sign in to comment.