Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New option for climate device to expose temperture sensors #595

Merged
merged 10 commits into from
Feb 16, 2021
13 changes: 10 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
# Changelog

## 0.xx

### Devices

- 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.

## 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
## 0.16.2 Bugfix for YAML loader 2021-01-24

### Internals

- fix conflict with HA Yaml loader
- fix conflict with HA YAML loader

## 0.16.1 HA register services 2021-01-16

Expand Down Expand Up @@ -163,7 +170,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
4 changes: 2 additions & 2 deletions docs/weather.md
Original file line number Diff line number Diff line change
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
5 changes: 4 additions & 1 deletion home-assistant-plugin/custom_components/xknx/factory.py
Original file line number Diff line number Diff line change
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
8 changes: 6 additions & 2 deletions home-assistant-plugin/custom_components/xknx/schema.py
Original file line number Diff line number Diff line change
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
4 changes: 2 additions & 2 deletions test/config_tests/config_v1_test.py
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
2 changes: 1 addition & 1 deletion test/config_tests/resources/xknx/invalid_3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,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/valid_1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,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/valid_2.yaml
Original file line number Diff line number Diff line change
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/valid_3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ weather:
humidity:
state_address: "7/0/10"
state_update: "expire 60"
expose_sensors: True
create_sensors: True
datetime:
- name: "Generaltime"
time:
Expand Down
25 changes: 25 additions & 0 deletions test/devices_tests/climate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1456,3 +1456,28 @@ def test_power_on_off(self):
payload=GroupValueWrite(DPTBinary(True)),
),
)

#
# Create temperature sensor tests
#
def test_create_sensor(self):
"""Test default state mapping."""
xknx = XKNX()
Climate(
name="climate",
xknx=xknx,
group_address_temperature="5/1/1",
group_address_target_temperature="5/1/4",
)

self.assertEqual(len(xknx.devices), 1)

Climate(
name="climate",
xknx=xknx,
group_address_temperature="5/1/1",
group_address_target_temperature="5/1/4",
create_temperature_sensors=True,
)

self.assertEqual(len(xknx.devices), 3)
6 changes: 3 additions & 3 deletions test/devices_tests/weather_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,9 @@ def test_weather_default(self):
self.assertEqual(weather.ha_current_state(), WeatherCondition.exceptional)

#
# Expose Sensor tests
# Create sensor tests
#
def test_expose_sensor(self):
def test_create_sensor(self):
"""Test default state mapping."""
xknx = XKNX()
Weather(
Expand All @@ -313,7 +313,7 @@ def test_expose_sensor(self):
group_address_brightness_south="1/3/6",
group_address_brightness_west="1/3/7",
group_address_wind_alarm="1/5/4",
expose_sensors=True,
create_sensors=True,
)

self.assertEqual(len(xknx.devices), 6)
Expand Down
2 changes: 1 addition & 1 deletion test/str_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def test_weather(self):
group_address_day_night="7/0/7",
group_address_rain_alarm="7/0/0",
group_address_frost_alarm="7/0/8",
expose_sensors=True,
create_sensors=True,
group_address_air_pressure="7/0/9",
group_address_humidity="7/0/9",
group_address_wind_alarm="7/0/10",
Expand Down
4 changes: 2 additions & 2 deletions xknx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,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,
}
Remote:
Expand All @@ -304,6 +304,6 @@ groups:
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,
}
6 changes: 4 additions & 2 deletions xknx/config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ class ClimateSchema:
CONF_HEAT_COOL = "heat_cool"
CONF_OPERATION_MODES = "operation_modes"
CONF_ON_OFF = "on_off"
CONF_CREATE_TEMPERATURE_SENSORS = "create_temperature_sensors"

CONF_FROST_PROTECTION_ADDRESS = "frost_protection_address"
CONF_NIGHT_ADDRESS = "night_address"
Expand Down Expand Up @@ -416,6 +417,7 @@ class ClimateSchema:
vol.Optional(CONF_OPERATION_MODES): vol.All(
ensure_list, [vol.In({**OPERATION_MODES, **PRESET_MODES})]
),
vol.Optional(CONF_CREATE_TEMPERATURE_SENSORS, default=False): boolean,
}
)

Expand All @@ -435,7 +437,7 @@ class WeatherSchema:
CONF_DAY_NIGHT = "day_night"
CONF_AIR_PRESSURE = "air_pressure"
CONF_HUMIDITY = "humidity"
CONF_EXPOSE_SENSORS = "expose_sensors"
CONF_CREATE_SENSORS = "create_sensors"

SCHEMA = BaseDeviceSchema.SCHEMA.extend(
{
Expand Down Expand Up @@ -511,7 +513,7 @@ class WeatherSchema:
vol.Required(CONF_STATE_ADDRESS): ensure_group_address,
}
),
vol.Optional(CONF_EXPOSE_SENSORS, default=False): boolean,
vol.Optional(CONF_CREATE_SENSORS, default=False): boolean,
}
)

Expand Down
29 changes: 28 additions & 1 deletion xknx/devices/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from .climate_mode import ClimateMode
from .device import Device, DeviceCallbackType
from .sensor import Sensor

if TYPE_CHECKING:
from xknx.remote_value import RemoteValue
Expand Down Expand Up @@ -62,6 +63,7 @@ def __init__(
min_temp: Optional[float] = None,
max_temp: Optional[float] = None,
mode: Optional[ClimateMode] = None,
create_temperature_sensors: bool = False,
device_updated_cb: Optional[DeviceCallbackType] = None,
):
"""Initialize Climate class."""
Expand All @@ -78,7 +80,7 @@ def __init__(
xknx,
group_address_state=group_address_temperature,
device_name=self.name,
feature_name="Current Temperature",
feature_name="Current temperature",
after_update_cb=self.after_update,
)

Expand Down Expand Up @@ -125,6 +127,9 @@ def __init__(

self.mode = mode

if create_temperature_sensors:
self.create_temperature_sensors()

def _iter_remote_values(self) -> Iterator["RemoteValue"]:
"""Iterate the devices RemoteValue classes."""
yield from (
Expand All @@ -134,6 +139,28 @@ def _iter_remote_values(self) -> Iterator["RemoteValue"]:
self.on,
)

def create_temperature_sensors(self) -> None:
"""Create temperature sensors."""
for suffix, group_address, value_type in (
(
"temperature",
self.temperature.group_address_state,
"temperature",
),
(
"target temperature",
self.target_temperature.group_address_state,
"temperature",
),
):
if group_address is not None:
Sensor(
self.xknx,
name=self.name + " " + suffix,
group_address_state=group_address,
value_type=value_type,
)

@classmethod
def from_config(cls, xknx: "XKNX", name: str, config: Any) -> "Climate":
"""Initialize object from configuration structure."""
Expand Down