mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 08:47:10 +00:00
Update xknx to 3.1.0 and fix climate read only mode (#123776)
This commit is contained in:
parent
71e23e7849
commit
b3d1d79a49
@ -5,7 +5,11 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from xknx import XKNX
|
from xknx import XKNX
|
||||||
from xknx.devices import Climate as XknxClimate, ClimateMode as XknxClimateMode
|
from xknx.devices import (
|
||||||
|
Climate as XknxClimate,
|
||||||
|
ClimateMode as XknxClimateMode,
|
||||||
|
Device as XknxDevice,
|
||||||
|
)
|
||||||
from xknx.dpt.dpt_20 import HVACControllerMode
|
from xknx.dpt.dpt_20 import HVACControllerMode
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -241,12 +245,9 @@ class KNXClimate(KnxYamlEntity, ClimateEntity):
|
|||||||
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 HVACMode.OFF
|
return HVACMode.OFF
|
||||||
if self._device.mode is not None and self._device.mode.supports_controller_mode:
|
if self._device.mode is not None and self._device.mode.supports_controller_mode:
|
||||||
hvac_mode = CONTROLLER_MODES.get(
|
return CONTROLLER_MODES.get(
|
||||||
self._device.mode.controller_mode, self.default_hvac_mode
|
self._device.mode.controller_mode, self.default_hvac_mode
|
||||||
)
|
)
|
||||||
if hvac_mode is not HVACMode.OFF:
|
|
||||||
self._last_hvac_mode = hvac_mode
|
|
||||||
return hvac_mode
|
|
||||||
return self.default_hvac_mode
|
return self.default_hvac_mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -261,11 +262,15 @@ class KNXClimate(KnxYamlEntity, ClimateEntity):
|
|||||||
|
|
||||||
if self._device.supports_on_off:
|
if self._device.supports_on_off:
|
||||||
if not ha_controller_modes:
|
if not ha_controller_modes:
|
||||||
ha_controller_modes.append(self.default_hvac_mode)
|
ha_controller_modes.append(self._last_hvac_mode)
|
||||||
ha_controller_modes.append(HVACMode.OFF)
|
ha_controller_modes.append(HVACMode.OFF)
|
||||||
|
|
||||||
hvac_modes = list(set(filter(None, ha_controller_modes)))
|
hvac_modes = list(set(filter(None, ha_controller_modes)))
|
||||||
return hvac_modes if hvac_modes else [self.default_hvac_mode]
|
return (
|
||||||
|
hvac_modes
|
||||||
|
if hvac_modes
|
||||||
|
else [self.hvac_mode] # mode read-only -> fall back to only current mode
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self) -> HVACAction | None:
|
def hvac_action(self) -> HVACAction | None:
|
||||||
@ -354,3 +359,13 @@ class KNXClimate(KnxYamlEntity, ClimateEntity):
|
|||||||
self._device.mode.unregister_device_updated_cb(self.after_update_callback)
|
self._device.mode.unregister_device_updated_cb(self.after_update_callback)
|
||||||
self._device.mode.xknx.devices.async_remove(self._device.mode)
|
self._device.mode.xknx.devices.async_remove(self._device.mode)
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
|
|
||||||
|
def after_update_callback(self, _device: XknxDevice) -> None:
|
||||||
|
"""Call after device was updated."""
|
||||||
|
if self._device.mode is not None and self._device.mode.supports_controller_mode:
|
||||||
|
hvac_mode = CONTROLLER_MODES.get(
|
||||||
|
self._device.mode.controller_mode, self.default_hvac_mode
|
||||||
|
)
|
||||||
|
if hvac_mode is not HVACMode.OFF:
|
||||||
|
self._last_hvac_mode = hvac_mode
|
||||||
|
super().after_update_callback(_device)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"loggers": ["xknx", "xknxproject"],
|
"loggers": ["xknx", "xknxproject"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"xknx==3.0.0",
|
"xknx==3.1.0",
|
||||||
"xknxproject==3.7.1",
|
"xknxproject==3.7.1",
|
||||||
"knx-frontend==2024.8.9.225351"
|
"knx-frontend==2024.8.9.225351"
|
||||||
],
|
],
|
||||||
|
@ -2930,7 +2930,7 @@ xbox-webapi==2.0.11
|
|||||||
xiaomi-ble==0.30.2
|
xiaomi-ble==0.30.2
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==3.0.0
|
xknx==3.1.0
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknxproject==3.7.1
|
xknxproject==3.7.1
|
||||||
|
@ -2316,7 +2316,7 @@ xbox-webapi==2.0.11
|
|||||||
xiaomi-ble==0.30.2
|
xiaomi-ble==0.30.2
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==3.0.0
|
xknx==3.1.0
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknxproject==3.7.1
|
xknxproject==3.7.1
|
||||||
|
@ -231,6 +231,90 @@ async def test_climate_hvac_mode(
|
|||||||
assert hass.states.get("climate.test").state == "cool"
|
assert hass.states.get("climate.test").state == "cool"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_climate_heat_cool_read_only(
|
||||||
|
hass: HomeAssistant, knx: KNXTestKit
|
||||||
|
) -> None:
|
||||||
|
"""Test KNX climate hvac mode."""
|
||||||
|
heat_cool_state_ga = "3/3/3"
|
||||||
|
await knx.setup_integration(
|
||||||
|
{
|
||||||
|
ClimateSchema.PLATFORM: {
|
||||||
|
CONF_NAME: "test",
|
||||||
|
ClimateSchema.CONF_TEMPERATURE_ADDRESS: "1/2/3",
|
||||||
|
ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS: "1/2/4",
|
||||||
|
ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS: "1/2/5",
|
||||||
|
ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS: heat_cool_state_ga,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# read states state updater
|
||||||
|
# StateUpdater semaphore allows 2 concurrent requests
|
||||||
|
await knx.assert_read("1/2/3")
|
||||||
|
await knx.assert_read("1/2/5")
|
||||||
|
# StateUpdater initialize state
|
||||||
|
await knx.receive_response("1/2/3", RAW_FLOAT_20_0)
|
||||||
|
await knx.receive_response("1/2/5", RAW_FLOAT_20_0)
|
||||||
|
await knx.assert_read(heat_cool_state_ga)
|
||||||
|
await knx.receive_response(heat_cool_state_ga, True) # heat
|
||||||
|
|
||||||
|
state = hass.states.get("climate.test")
|
||||||
|
assert state.state == "heat"
|
||||||
|
assert state.attributes["hvac_modes"] == ["heat"]
|
||||||
|
assert state.attributes["hvac_action"] == "heating"
|
||||||
|
|
||||||
|
await knx.receive_write(heat_cool_state_ga, False) # cool
|
||||||
|
state = hass.states.get("climate.test")
|
||||||
|
assert state.state == "cool"
|
||||||
|
assert state.attributes["hvac_modes"] == ["cool"]
|
||||||
|
assert state.attributes["hvac_action"] == "cooling"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_climate_heat_cool_read_only_on_off(
|
||||||
|
hass: HomeAssistant, knx: KNXTestKit
|
||||||
|
) -> None:
|
||||||
|
"""Test KNX climate hvac mode."""
|
||||||
|
on_off_ga = "2/2/2"
|
||||||
|
heat_cool_state_ga = "3/3/3"
|
||||||
|
await knx.setup_integration(
|
||||||
|
{
|
||||||
|
ClimateSchema.PLATFORM: {
|
||||||
|
CONF_NAME: "test",
|
||||||
|
ClimateSchema.CONF_TEMPERATURE_ADDRESS: "1/2/3",
|
||||||
|
ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS: "1/2/4",
|
||||||
|
ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS: "1/2/5",
|
||||||
|
ClimateSchema.CONF_ON_OFF_ADDRESS: on_off_ga,
|
||||||
|
ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS: heat_cool_state_ga,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# read states state updater
|
||||||
|
# StateUpdater semaphore allows 2 concurrent requests
|
||||||
|
await knx.assert_read("1/2/3")
|
||||||
|
await knx.assert_read("1/2/5")
|
||||||
|
# StateUpdater initialize state
|
||||||
|
await knx.receive_response("1/2/3", RAW_FLOAT_20_0)
|
||||||
|
await knx.receive_response("1/2/5", RAW_FLOAT_20_0)
|
||||||
|
await knx.assert_read(heat_cool_state_ga)
|
||||||
|
await knx.receive_response(heat_cool_state_ga, True) # heat
|
||||||
|
|
||||||
|
state = hass.states.get("climate.test")
|
||||||
|
assert state.state == "off"
|
||||||
|
assert set(state.attributes["hvac_modes"]) == {"off", "heat"}
|
||||||
|
assert state.attributes["hvac_action"] == "off"
|
||||||
|
|
||||||
|
await knx.receive_write(heat_cool_state_ga, False) # cool
|
||||||
|
state = hass.states.get("climate.test")
|
||||||
|
assert state.state == "off"
|
||||||
|
assert set(state.attributes["hvac_modes"]) == {"off", "cool"}
|
||||||
|
assert state.attributes["hvac_action"] == "off"
|
||||||
|
|
||||||
|
await knx.receive_write(on_off_ga, True)
|
||||||
|
state = hass.states.get("climate.test")
|
||||||
|
assert state.state == "cool"
|
||||||
|
assert set(state.attributes["hvac_modes"]) == {"off", "cool"}
|
||||||
|
assert state.attributes["hvac_action"] == "cooling"
|
||||||
|
|
||||||
|
|
||||||
async def test_climate_preset_mode(
|
async def test_climate_preset_mode(
|
||||||
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user