Testus 2
This commit is contained in:
@@ -85,6 +85,12 @@ class PropAlgorithm:
|
||||
def _calculate_internal(self):
|
||||
"""Finish the calculation to get the on_percent in seconds"""
|
||||
|
||||
# calculated on_time duration in seconds
|
||||
if self._calculated_on_percent > 1:
|
||||
self._calculated_on_percent = 1
|
||||
if self._calculated_on_percent < 0:
|
||||
self._calculated_on_percent = 0
|
||||
|
||||
if self._security:
|
||||
_LOGGER.debug(
|
||||
"Security is On using the default_on_percent %f",
|
||||
@@ -98,11 +104,6 @@ class PropAlgorithm:
|
||||
)
|
||||
self._on_percent = self._calculated_on_percent
|
||||
|
||||
# calculated on_time duration in seconds
|
||||
if self._on_percent > 1:
|
||||
self._on_percent = 1
|
||||
if self._on_percent < 0:
|
||||
self._on_percent = 0
|
||||
self._on_time_sec = self._on_percent * self._cycle_min * 60
|
||||
|
||||
# Do not heat for less than xx sec
|
||||
|
||||
@@ -1,16 +1,58 @@
|
||||
""" Some common resources """
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components.climate import ClimateEntity
|
||||
from homeassistant.const import UnitOfTemperature
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
|
||||
from ..climate import VersatileThermostat
|
||||
from ..const import DOMAIN
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ClimateEntity,
|
||||
DOMAIN as CLIMATE_DOMAIN,
|
||||
ATTR_PRESET_MODE,
|
||||
HVACMode,
|
||||
HVACAction,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TPI_CONFIG,
|
||||
MOCK_PRESETS_CONFIG,
|
||||
MOCK_WINDOW_CONFIG,
|
||||
MOCK_MOTION_CONFIG,
|
||||
MOCK_POWER_CONFIG,
|
||||
MOCK_PRESENCE_CONFIG,
|
||||
MOCK_ADVANCED_CONFIG,
|
||||
# MOCK_DEFAULT_FEATURE_CONFIG,
|
||||
)
|
||||
|
||||
FULL_SWITCH_CONFIG = (
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
||||
| MOCK_PRESETS_CONFIG
|
||||
| MOCK_WINDOW_CONFIG
|
||||
| MOCK_MOTION_CONFIG
|
||||
| MOCK_POWER_CONFIG
|
||||
| MOCK_PRESENCE_CONFIG
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
|
||||
PARTIAL_CLIMATE_CONFIG = (
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
||||
| MOCK_TH_OVER_CLIMATE_TYPE_CONFIG
|
||||
| MOCK_PRESETS_CONFIG
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
|
||||
|
||||
class MockClimate(ClimateEntity):
|
||||
"""A Mock Climate class used for Underlying climate mode"""
|
||||
@@ -28,3 +70,26 @@ class MockClimate(ClimateEntity):
|
||||
self._attr_hvac_mode = HVACMode.OFF
|
||||
self._attr_hvac_modes = [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT]
|
||||
self._attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
|
||||
async def create_thermostat(
|
||||
hass: HomeAssistant, entry: MockConfigEntry, entity_id: str
|
||||
) -> VersatileThermostat:
|
||||
"""Creates and return a TPI Thermostat"""
|
||||
with patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat.send_event"
|
||||
):
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
def find_my_entity(entity_id) -> ClimateEntity:
|
||||
"""Find my new entity"""
|
||||
component: EntityComponent[ClimateEntity] = hass.data[CLIMATE_DOMAIN]
|
||||
for entity in component.entities:
|
||||
if entity.entity_id == entity_id:
|
||||
return entity
|
||||
|
||||
entity = find_my_entity(entity_id)
|
||||
|
||||
return entity
|
||||
|
||||
@@ -15,41 +15,7 @@ from ..climate import VersatileThermostat
|
||||
|
||||
from ..const import DOMAIN, EventType
|
||||
|
||||
from .const import (
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TPI_CONFIG,
|
||||
MOCK_PRESETS_CONFIG,
|
||||
MOCK_WINDOW_CONFIG,
|
||||
MOCK_MOTION_CONFIG,
|
||||
MOCK_POWER_CONFIG,
|
||||
MOCK_PRESENCE_CONFIG,
|
||||
MOCK_ADVANCED_CONFIG,
|
||||
# MOCK_DEFAULT_FEATURE_CONFIG,
|
||||
)
|
||||
|
||||
from .commons import MockClimate
|
||||
|
||||
FULL_SWITCH_CONFIG = (
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
||||
| MOCK_PRESETS_CONFIG
|
||||
| MOCK_WINDOW_CONFIG
|
||||
| MOCK_MOTION_CONFIG
|
||||
| MOCK_POWER_CONFIG
|
||||
| MOCK_PRESENCE_CONFIG
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
|
||||
PARTIAL_CLIMATE_CONFIG = (
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
||||
| MOCK_TH_OVER_CLIMATE_TYPE_CONFIG
|
||||
| MOCK_PRESETS_CONFIG
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
from .commons import MockClimate, FULL_SWITCH_CONFIG, PARTIAL_CLIMATE_CONFIG
|
||||
|
||||
|
||||
async def test_over_switch_full_start(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
@@ -76,7 +42,7 @@ async def test_over_switch_full_start(hass: HomeAssistant, skip_hass_states_is_s
|
||||
if entity.entity_id == entity_id:
|
||||
return entity
|
||||
|
||||
entity = find_my_entity("climate.theoverswitchmockname")
|
||||
entity: VersatileThermostat = find_my_entity("climate.theoverswitchmockname")
|
||||
|
||||
assert entity
|
||||
|
||||
@@ -90,6 +56,7 @@ async def test_over_switch_full_start(hass: HomeAssistant, skip_hass_states_is_s
|
||||
assert entity._window_state is None
|
||||
assert entity._motion_state is None
|
||||
assert entity._presence_state is None
|
||||
assert entity._prop_algorithm is not None
|
||||
|
||||
# should have been called with EventType.PRESET_EVENT and EventType.HVAC_MODE_EVENT
|
||||
assert mock_send_event.call_count == 2
|
||||
|
||||
81
custom_components/versatile_thermostat/tests/test_tpi.py
Normal file
81
custom_components/versatile_thermostat/tests/test_tpi.py
Normal file
@@ -0,0 +1,81 @@
|
||||
""" Test the TPI algorithm """
|
||||
|
||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||
|
||||
|
||||
async def test_tpi_calculation(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
"""Test the TPI calculation"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="TheOverSwitchMockName",
|
||||
unique_id="uniqueId",
|
||||
data={
|
||||
"name": "TheOverSwitchMockName",
|
||||
"thermostat_type": "thermostat_over_switch",
|
||||
"temperature_sensor_entity_id": "sensor.mock_temp_sensor",
|
||||
"external_temperature_sensor_entity_id": "sensor.mock_ext_temp_sensor",
|
||||
"cycle_min": 5,
|
||||
"temp_min": 15,
|
||||
"temp_max": 30,
|
||||
"use_window_feature": False,
|
||||
"use_motion_feature": False,
|
||||
"use_power_feature": False,
|
||||
"use_presence_feature": False,
|
||||
"heater_entity_id": "switch.mock_switch",
|
||||
"proportional_function": "tpi",
|
||||
"tpi_coef_int": 0.3,
|
||||
"tpi_coef_ext": 0.01,
|
||||
"minimal_activation_delay": 30,
|
||||
"security_delay_min": 5,
|
||||
"security_default_on_percent": 0.3,
|
||||
},
|
||||
)
|
||||
|
||||
entity: VersatileThermostat = await create_thermostat(
|
||||
hass, entry, "climate.theoverswitchmockname"
|
||||
)
|
||||
assert entity
|
||||
|
||||
tpi_algo = entity._prop_algorithm
|
||||
assert tpi_algo
|
||||
|
||||
tpi_algo.calculate(15, 10, 7)
|
||||
assert tpi_algo.on_percent == 1
|
||||
assert tpi_algo.calculated_on_percent == 1
|
||||
assert tpi_algo.on_time_sec == 300
|
||||
assert tpi_algo.off_time_sec == 0
|
||||
|
||||
tpi_algo.calculate(15, 14, 5)
|
||||
assert tpi_algo.on_percent == 0.4
|
||||
assert tpi_algo.calculated_on_percent == 0.4
|
||||
assert tpi_algo.on_time_sec == 120
|
||||
assert tpi_algo.off_time_sec == 180
|
||||
|
||||
tpi_algo.set_security(0.1)
|
||||
tpi_algo.calculate(15, 14, 5)
|
||||
assert tpi_algo.on_percent == 0.1
|
||||
assert tpi_algo.calculated_on_percent == 0.4
|
||||
assert tpi_algo.on_time_sec == 30 # >= minimal_activation_delay (=30)
|
||||
assert tpi_algo.off_time_sec == 270
|
||||
|
||||
tpi_algo.unset_security()
|
||||
tpi_algo.calculate(15, 14, 5)
|
||||
assert tpi_algo.on_percent == 0.4
|
||||
assert tpi_algo.calculated_on_percent == 0.4
|
||||
assert tpi_algo.on_time_sec == 120
|
||||
assert tpi_algo.off_time_sec == 180
|
||||
|
||||
# Test minimal activation delay
|
||||
tpi_algo.calculate(15, 14.7, 15)
|
||||
assert tpi_algo.on_percent == 0.09
|
||||
assert tpi_algo.calculated_on_percent == 0.09
|
||||
assert tpi_algo.on_time_sec == 0
|
||||
assert tpi_algo.off_time_sec == 300
|
||||
|
||||
tpi_algo.set_security(0.09)
|
||||
tpi_algo.calculate(15, 14.7, 15)
|
||||
assert tpi_algo.on_percent == 0.09
|
||||
assert tpi_algo.calculated_on_percent == 0.09
|
||||
assert tpi_algo.on_time_sec == 0
|
||||
assert tpi_algo.off_time_sec == 300
|
||||
Reference in New Issue
Block a user