Skip to content

Commit

Permalink
Merge branch 'master' into feature/trigger_knx_event_on_outgoing
Browse files Browse the repository at this point in the history
  • Loading branch information
farmio committed Feb 16, 2021
2 parents 4d5bdc2 + afa30c7 commit 71d5467
Show file tree
Hide file tree
Showing 94 changed files with 1,396 additions and 740 deletions.
29 changes: 27 additions & 2 deletions changelog.md
@@ -1,11 +1,36 @@
# Changelog

## Unreleased
## Unreleased changes

### HA integration

- knx_event: fire also for outgoing telegrams

### Devices

- BinarySensor: return `None` for `BinarySensor.counter` when context timeout is not used (and don't calculate it)
- Climate: Add `create_temperature_sensors` option to create dedicated sensors for current and target temperature.
- Weather (breaking change!): Renamed `expose_sensors` to `create_sensors` to prevent confusion with the XKNX `expose_sensor` device type.

### Internals

- RemoteValue is Generic now accepting DPTArray or DPTBinary
- split RemoteValueClimateMode into RemoteValueControllerMode and RemoteValueOperationMode
- return the payload (or None) in RemoteValue.payload_valid(payload) instead of bool
- Light colors are represented as `Tuple[Tuple[int,int,int], int]` instead of `Tuple[List[int], int]` now
- DPT 3 payloads/values are not invertable anymore.

## 0.16.3 Fan contributions 2021-02-06

### Devices

- Fan: Add `max_step` attribute which defines the maximum amount of steps. If set, the fan is controlled by steps instead of percentage.
- Fan: Add `group_address_oscillation` and `group_address_oscillation_state` attributes to control the oscillation of a fan.

## 0.16.2 Bugfix for YAML loader 2021-01-24

### Internals

## 0.16.1 HA register services 2021-01-16

### HA integration
Expand Down Expand Up @@ -156,7 +181,7 @@
- Reset binary sensor counters after the context has been timed out in order to be able to use state change events within HA
- Code cleanups

## 0.14.0 New sensor types and refacoring of binary sensor automations
## 0.14.0 New sensor types and refactoring of binary sensor automations

### Breaking changes

Expand Down
59 changes: 59 additions & 0 deletions docs/fan.md
@@ -0,0 +1,59 @@
---
layout: default
title: Fan
parent: Devices
nav_order: 4
---

# [](#header-1)Fans

## [](#header-2)Overview

Fans are simple representations of KNX controlled fans. They support setting the speed and the oscillation.

## [](#header-2)Interface

- `xknx` XKNX object.
- `name` name of the device.
- `group_address` is the KNX group address of the fan speed. Used for sending. *DPT 5.001 / 5.010*
- `group_address_state` is the KNX group address of the fan speed state. Used for updating and reading state. *DPT 5.001 / 5.010*
- `group_address_oscillation` is the KNX group address of the oscillation. Used for sending. *DPT 1.001*
- `group_address_oscillation_state` is the KNX group address of the fan oscillation state. Used for updating and reading state. *DPT 1.001*
- `device_updated_cb` awaitable callback for each update.
- `max_step` Maximum step amount for fans which are controlled with steps and not percentage. If this attribute is set, the fan is controlled by sending the step value in the range `0` and `max_step`. In that case, the group address DPT changes from *DPT 5.001* to *DPT 5.010*. Default: None

## [](#header-2)Example

```python
fan = Fan(xknx,
'TestFan',
group_address='1/2/1',
group_address_state='1/2/2',
group_address_oscillation='1/2/3',
group_address_oscillation_state='1/2/4')

# Set the fan speed
await fan.set_speed(50)

# Accessing speed
print(fan.current_speed)

# Set the oscillation
await fan.set_oscillation(True)

# Accessing speed
print(fan.current_oscillation)

# Requesting state via KNX GroupValueRead
await fan.sync()
```

## [](#header-2)Configuration via **xknx.yaml**

Fans are usually configured via [`xknx.yaml`](/configuration):

```yaml
groups:
fan:
Livingroom.Fan_1: { group_address: '1/4/1', group_address_state: '1/4/2', group_address_oscillation: '1/4/3', group_address_oscillation_state: '1/4/4' }
```
7 changes: 4 additions & 3 deletions docs/home_assistant.md
Expand Up @@ -36,14 +36,16 @@ Run HA as usual either via service or by directly typing in `hass`.
Running HA with local XKNX library
------------------------------------

Even when running HA with the XKNX custom component, HA will automatically install a `xknx` library version within `.homeassistant/deps/lib/python[python-version]/site-packages` via pip. This very often causes the problem, that the manually checked out `xknx` library is not in sync with the `xknx` library version HA already contains and uses by default. But getting both in sync is easy:
When running HA with the KNX integrated component once, HA will automatically install a `xknx` library version within `[hass-dependency-directory]/lib/python[python-version]/site-packages` via pip. This very often causes the problem, that the manually checked out `xknx` library is not in sync with the `xknx` library version HA already contains and uses by default. But getting both in sync is easy:

Delete the automatically installed version:

```bash
rm .homeassistant/deps/lib/python[python-version]/site-packages/xknx*
rm [hass-dependency-directory]/lib/python[python-version]/site-packages/xknx*
```

Note: `[hass-dependency-directory]` is platform dependend (e.g. `/usr/local` for Docker image, `~/.homeassistant/deps` for macOS or `/srv/homeassistant` for Debian).

Ideally start HA from command line. Export the environment variable PYTHONPATH to your local `xknx` checkout:

```bash
Expand Down Expand Up @@ -80,4 +82,3 @@ Help

If you have problems, join the [XKNX chat on Discord](https://discord.gg/EuAQDXU). We are happy to help :-)


2 changes: 1 addition & 1 deletion docs/light.md
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Lights / Dimmer
parent: Devices
nav_order: 4
nav_order: 5
---

# [](#header-1)Light & Dimmer
Expand Down
2 changes: 1 addition & 1 deletion docs/sensor.md
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Sensor
parent: Devices
nav_order: 5
nav_order: 6
---

# [](#header-1)Sensor - Monitor values of KNX
Expand Down
2 changes: 1 addition & 1 deletion docs/switch.md
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Switches
parent: Devices
nav_order: 6
nav_order: 7
---

# [](#header-1)Switches
Expand Down
2 changes: 1 addition & 1 deletion docs/time.md
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Time
parent: Devices
nav_order: 7
nav_order: 8
---

# [](#header-1)Time
Expand Down
6 changes: 3 additions & 3 deletions docs/weather.md
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Weather
parent: Devices
nav_order: 8
nav_order: 9
---

# [](#header-1)Weather device
Expand Down Expand Up @@ -51,7 +51,7 @@ groups:
group_address_day_night: "7/0/8",
group_address_air_pressure: "7/0/9",
group_address_humidity: "7/0/10",
expose_sensors: True,
create_sensors: True,
sync_state: True,
}
```
Expand All @@ -71,7 +71,7 @@ groups:
- **group_address_day_night** KNX address for reading a day/night object.
- **group_address_air_pressure** KNX address reading current air pressure. **DPT 9.006**
- **group_address_humidity** KNX address for reading current humidity. **DPT 9.007**
- **expose_sensors** If true, also exposes all values as sensors to the xknx device list (useful for home assistant). Default: False
- **create_sensors** If true, also adds sensors for all values to the xknx device list (useful for Home Assistant). Default: False
- **sync_state** Periodically sync the state.
- **device_updated_cb** awaitable callback for each update.

Expand Down
Expand Up @@ -40,7 +40,9 @@ def is_on(self):
@property
def device_state_attributes(self) -> Optional[Dict[str, Any]]:
"""Return device specific state attributes."""
return {ATTR_COUNTER: self._device.counter}
if self._device.counter is not None:
return {ATTR_COUNTER: self._device.counter}
return None

@property
def force_update(self) -> bool:
Expand Down
5 changes: 4 additions & 1 deletion home-assistant-plugin/custom_components/xknx/factory.py
Expand Up @@ -259,6 +259,9 @@ def _create_climate(knx_module: XKNX, config: ConfigType) -> XknxClimate:
max_temp=config.get(ClimateSchema.CONF_MAX_TEMP),
mode=climate_mode,
on_off_invert=config[ClimateSchema.CONF_ON_OFF_INVERT],
create_temperature_sensors=config.get(
ClimateSchema.CONF_CREATE_TEMPERATURE_SENSORS
),
)


Expand Down Expand Up @@ -327,7 +330,7 @@ def _create_weather(knx_module: XKNX, config: ConfigType) -> XknxWeather:
knx_module,
name=config[CONF_NAME],
sync_state=config[WeatherSchema.CONF_SYNC_STATE],
expose_sensors=config[WeatherSchema.CONF_XKNX_EXPOSE_SENSORS],
create_sensors=config[WeatherSchema.CONF_XKNX_CREATE_SENSORS],
group_address_temperature=config[WeatherSchema.CONF_XKNX_TEMPERATURE_ADDRESS],
group_address_brightness_south=config.get(
WeatherSchema.CONF_XKNX_BRIGHTNESS_SOUTH_ADDRESS
Expand Down
4 changes: 2 additions & 2 deletions home-assistant-plugin/custom_components/xknx/knx_entity.py
Expand Up @@ -40,12 +40,12 @@ async def async_added_to_hass(self) -> None:
"""Store register state change callback."""
self._device.register_device_updated_cb(self.after_update_callback)

if isinstance(self._device, XknxClimate):
if isinstance(self._device, XknxClimate) and self._device.mode is not None:
self._device.mode.register_device_updated_cb(self.after_update_callback)

async def async_will_remove_from_hass(self) -> None:
"""Disconnect device object when removed."""
self._device.unregister_device_updated_cb(self.after_update_callback)

if isinstance(self._device, XknxClimate):
if isinstance(self._device, XknxClimate) and self._device.mode is not None:
self._device.mode.unregister_device_updated_cb(self.after_update_callback)
8 changes: 6 additions & 2 deletions home-assistant-plugin/custom_components/xknx/schema.py
Expand Up @@ -240,6 +240,7 @@ class ClimateSchema:
CONF_ON_OFF_INVERT = "on_off_invert"
CONF_MIN_TEMP = "min_temp"
CONF_MAX_TEMP = "max_temp"
CONF_CREATE_TEMPERATURE_SENSORS = "create_temperature_sensors"

DEFAULT_NAME = "KNX Climate"
DEFAULT_SETPOINT_SHIFT_MODE = "DPT6010"
Expand Down Expand Up @@ -295,6 +296,9 @@ class ClimateSchema:
),
vol.Optional(CONF_MIN_TEMP): vol.Coerce(float),
vol.Optional(CONF_MAX_TEMP): vol.Coerce(float),
vol.Optional(
CONF_CREATE_TEMPERATURE_SENSORS, default=False
): cv.boolean,
}
),
)
Expand Down Expand Up @@ -403,7 +407,7 @@ class WeatherSchema:
CONF_XKNX_DAY_NIGHT_ADDRESS = "address_day_night"
CONF_XKNX_AIR_PRESSURE_ADDRESS = "address_air_pressure"
CONF_XKNX_HUMIDITY_ADDRESS = "address_humidity"
CONF_XKNX_EXPOSE_SENSORS = "expose_sensors"
CONF_XKNX_CREATE_SENSORS = "create_sensors"

DEFAULT_NAME = "KNX Weather Station"

Expand All @@ -415,7 +419,7 @@ class WeatherSchema:
cv.boolean,
cv.string,
),
vol.Optional(CONF_XKNX_EXPOSE_SENSORS, default=False): cv.boolean,
vol.Optional(CONF_XKNX_CREATE_SENSORS, default=False): cv.boolean,
vol.Required(CONF_XKNX_TEMPERATURE_ADDRESS): cv.string,
vol.Optional(CONF_XKNX_BRIGHTNESS_SOUTH_ADDRESS): cv.string,
vol.Optional(CONF_XKNX_BRIGHTNESS_EAST_ADDRESS): cv.string,
Expand Down
2 changes: 1 addition & 1 deletion home-assistant-plugin/custom_components/xknx/sensor.py
Expand Up @@ -30,7 +30,7 @@ def state(self):
return self._device.resolve_state()

@property
def unit_of_measurement(self):
def unit_of_measurement(self) -> str:
"""Return the unit this state is expressed in."""
return self._device.unit_of_measurement()

Expand Down
2 changes: 1 addition & 1 deletion requirements/production.txt
@@ -1,3 +1,3 @@
netifaces==0.10.9
pyyaml==5.3.1
pyyaml==5.4.1
voluptuous==0.12.1
10 changes: 5 additions & 5 deletions requirements/testing.txt
@@ -1,15 +1,15 @@
-r production.txt
pre-commit==2.9.3
pre-commit==2.10.1
isort==5.7.0
coveralls==3.0.0
flake8==3.8.4
flake8-isort==4.0.0
pydocstyle==5.1.1
pylint==2.6.0
pylint-strict-informational==0.1
pytest==6.2.1
pytest==6.2.2
pytest-cov==2.11.1
pytest-timeout==1.4.2
setuptools==51.3.3
tox==3.21.2
mypy==0.790
setuptools==53.0.0
tox==3.21.4
mypy==0.800
10 changes: 1 addition & 9 deletions setup.cfg
Expand Up @@ -43,15 +43,7 @@ warn_unused_configs = true

# add the modules below once we add typing for them so that we fail the build in the future if someone changes something without updating the typings
# fully typechecked modules
[mypy-xknx.xknx,xknx.core.*,xknx.devices.*,xknx.exceptions.*,xknx.io.*,xknx.knxip.*,xknx.telegram.*,]
strict = true
ignore_errors = false
warn_unreachable = true
# TODO: turn these off, address issues
implicit_reexport = true

# partly typechecked modules (extra block for better overview)
[mypy-xknx.remote_value.remote_value,xknx.remote_value.remote_value_climate_mode]
[mypy-xknx.xknx,xknx.core.*,xknx.devices.*,xknx.dpt.*,xknx.exceptions.*,xknx.io.*,xknx.knxip.*,xknx.remote_value.*,xknx.telegram.*,]
strict = true
ignore_errors = false
warn_unreachable = true
Expand Down
4 changes: 2 additions & 2 deletions test/config_tests/config_v1_test.py
Expand Up @@ -587,12 +587,12 @@ def test_config_weather(self):
group_address_day_night="7/0/8",
group_address_air_pressure="7/0/9",
group_address_humidity="7/0/10",
expose_sensors=False,
create_sensors=False,
sync_state=True,
),
)

def test_config_weather_expose_sensor(self):
def test_config_weather_create_sensor(self):
"""Test reading weather from config file."""
self.assertTrue(isinstance(TestConfig.xknx.devices["Home_temperature"], Sensor))
self.assertTrue(
Expand Down
2 changes: 1 addition & 1 deletion test/config_tests/resources/weather/invalid_1.yaml
Expand Up @@ -33,4 +33,4 @@ air_pressure:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
2 changes: 1 addition & 1 deletion test/config_tests/resources/weather/invalid_2.yaml
Expand Up @@ -34,4 +34,4 @@ air_pressure:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
2 changes: 1 addition & 1 deletion test/config_tests/resources/weather/valid_1.yaml
Expand Up @@ -36,4 +36,4 @@ air_pressure:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
2 changes: 1 addition & 1 deletion test/config_tests/resources/weather/valid_2.yaml
Expand Up @@ -3,4 +3,4 @@ friendly_name: "Home"
temperature:
state_address: "7/0/0"
state_update: "expire 60"
expose_sensors: "off"
create_sensors: "off"
2 changes: 1 addition & 1 deletion test/config_tests/resources/xknx/invalid_1.yaml
Expand Up @@ -157,7 +157,7 @@ weather:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
datetime:
- name: "Generaltime"
time:
Expand Down
2 changes: 1 addition & 1 deletion test/config_tests/resources/xknx/invalid_2.yaml
Expand Up @@ -155,7 +155,7 @@ weather:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
datetime:
- name: "Generaltime"
time:
Expand Down

0 comments on commit 71d5467

Please sign in to comment.