core/tests/components/knx/test_climate.py

243 lines
8.2 KiB
Python

"""Test KNX climate."""
from homeassistant.components.climate import PRESET_ECO, PRESET_SLEEP, HVACMode
from homeassistant.components.knx.schema import ClimateSchema
from homeassistant.const import CONF_NAME, STATE_IDLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from .conftest import KNXTestKit
from tests.common import async_capture_events
RAW_FLOAT_20_0 = (0x07, 0xD0)
RAW_FLOAT_21_0 = (0x0C, 0x1A)
RAW_FLOAT_22_0 = (0x0C, 0x4C)
async def test_climate_basic_temperature_set(
hass: HomeAssistant, knx: KNXTestKit
) -> None:
"""Test KNX climate basic."""
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",
}
}
)
events = async_capture_events(hass, "state_changed")
# read temperature
await knx.assert_read("1/2/3")
# read target temperature
await knx.assert_read("1/2/5")
# StateUpdater initialize state
await knx.receive_response("1/2/3", RAW_FLOAT_21_0)
await knx.receive_response("1/2/5", RAW_FLOAT_22_0)
events.clear()
# set new temperature
await hass.services.async_call(
"climate",
"set_temperature",
{"entity_id": "climate.test", "temperature": 20},
blocking=True,
)
await knx.assert_write("1/2/4", RAW_FLOAT_20_0)
assert len(events) == 1
async def test_climate_hvac_mode(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test KNX climate hvac mode."""
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_CONTROLLER_MODE_ADDRESS: "1/2/6",
ClimateSchema.CONF_CONTROLLER_MODE_STATE_ADDRESS: "1/2/7",
ClimateSchema.CONF_ON_OFF_ADDRESS: "1/2/8",
ClimateSchema.CONF_OPERATION_MODES: ["Auto"],
}
}
)
async_capture_events(hass, "state_changed")
await hass.async_block_till_done()
# read states state updater
await knx.assert_read("1/2/7")
await knx.assert_read("1/2/3")
# StateUpdater initialize state
await knx.receive_response("1/2/7", (0x01,))
await knx.receive_response("1/2/3", RAW_FLOAT_20_0)
# StateUpdater semaphore allows 2 concurrent requests
# read target temperature state
await knx.assert_read("1/2/5")
await knx.receive_response("1/2/5", RAW_FLOAT_22_0)
# turn hvac off
await hass.services.async_call(
"climate",
"set_hvac_mode",
{"entity_id": "climate.test", "hvac_mode": HVACMode.OFF},
blocking=True,
)
await knx.assert_write("1/2/8", False)
# turn hvac on
await hass.services.async_call(
"climate",
"set_hvac_mode",
{"entity_id": "climate.test", "hvac_mode": HVACMode.HEAT},
blocking=True,
)
await knx.assert_write("1/2/8", True)
await knx.assert_write("1/2/6", (0x01,))
async def test_climate_preset_mode(
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
) -> None:
"""Test KNX climate preset mode."""
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_OPERATION_MODE_ADDRESS: "1/2/6",
ClimateSchema.CONF_OPERATION_MODE_STATE_ADDRESS: "1/2/7",
}
}
)
events = async_capture_events(hass, "state_changed")
await hass.async_block_till_done()
# read states state updater
await knx.assert_read("1/2/7")
await knx.assert_read("1/2/3")
# StateUpdater initialize state
await knx.receive_response("1/2/7", (0x01,))
await knx.receive_response("1/2/3", RAW_FLOAT_21_0)
# StateUpdater semaphore allows 2 concurrent requests
# read target temperature state
await knx.assert_read("1/2/5")
await knx.receive_response("1/2/5", RAW_FLOAT_22_0)
events.clear()
# set preset mode
await hass.services.async_call(
"climate",
"set_preset_mode",
{"entity_id": "climate.test", "preset_mode": PRESET_ECO},
blocking=True,
)
await knx.assert_write("1/2/6", (0x04,))
assert len(events) == 1
events.pop()
# set preset mode
await hass.services.async_call(
"climate",
"set_preset_mode",
{"entity_id": "climate.test", "preset_mode": PRESET_SLEEP},
blocking=True,
)
await knx.assert_write("1/2/6", (0x03,))
assert len(events) == 1
events.pop()
assert len(knx.xknx.devices) == 2
assert len(knx.xknx.devices[0].device_updated_cbs) == 2
assert len(knx.xknx.devices[1].device_updated_cbs) == 2
# test removing also removes hooks
entity_registry.async_remove("climate.test")
await hass.async_block_till_done()
# If we remove the entity the underlying devices should disappear too
assert len(knx.xknx.devices) == 0
async def test_update_entity(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test update climate entity for KNX."""
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_OPERATION_MODE_ADDRESS: "1/2/6",
ClimateSchema.CONF_OPERATION_MODE_STATE_ADDRESS: "1/2/7",
}
}
)
assert await async_setup_component(hass, "homeassistant", {})
await hass.async_block_till_done()
async_capture_events(hass, "state_changed")
await hass.async_block_till_done()
# read states state updater
await knx.assert_read("1/2/7")
await knx.assert_read("1/2/3")
# StateUpdater initialize state
await knx.receive_response("1/2/7", (0x01,))
await knx.receive_response("1/2/3", RAW_FLOAT_21_0)
# StateUpdater semaphore allows 2 concurrent requests
await knx.assert_read("1/2/5")
await knx.receive_response("1/2/5", RAW_FLOAT_22_0)
# verify update entity retriggers group value reads to the bus
await hass.services.async_call(
"homeassistant",
"update_entity",
target={"entity_id": "climate.test"},
blocking=True,
)
await knx.assert_read("1/2/3")
await knx.assert_read("1/2/5")
await knx.assert_read("1/2/7")
async def test_command_value_idle_mode(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test KNX climate command_value."""
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_COMMAND_VALUE_STATE_ADDRESS: "1/2/6",
}
}
)
await hass.async_block_till_done()
# read states state updater
await knx.assert_read("1/2/3")
await knx.assert_read("1/2/5")
# StateUpdater initialize state
await knx.receive_response("1/2/5", RAW_FLOAT_22_0)
await knx.receive_response("1/2/3", RAW_FLOAT_21_0)
# StateUpdater semaphore allows 2 concurrent requests
await knx.assert_read("1/2/6")
await knx.receive_response("1/2/6", (0x32,))
knx.assert_state("climate.test", HVACMode.HEAT, command_value=20)
await knx.receive_write("1/2/6", (0x00,))
knx.assert_state(
"climate.test", HVACMode.HEAT, command_value=0, hvac_action=STATE_IDLE
)