Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8961a80086 | |||
| 2f6c46ef11 | |||
| af817e74b7 | |||
| 46307286b1 | |||
| c8398a48fe | |||
| 5063ba3802 | |||
| fb76a84bde | |||
| 03f6045d34 | |||
| aeb4b2fbbe | |||
| 47f5aa9595 |
+1
-1
@@ -114,7 +114,7 @@ En conséquence toute la phase de paramètrage d'un VTherm a été profondemment
|
|||||||
**Note :** les copies d'écran de la configuration d'un VTherm n'ont pas été mises à jour.
|
**Note :** les copies d'écran de la configuration d'un VTherm n'ont pas été mises à jour.
|
||||||
|
|
||||||
# Merci pour la bière [buymecoffee](https://www.buymeacoffee.com/jmcollin78)
|
# Merci pour la bière [buymecoffee](https://www.buymeacoffee.com/jmcollin78)
|
||||||
Un grand merci à @salabur, @pvince83, @bergoglio, @EPicLURcher, @ecolorado66, @Kriss1670, @maia, @f.maymil, @moutte69, @Jerome, @Gunnar M, @Greg.o, @John Burgess, @abyssmal, @capinfo26, @Helge, @MattG @Mexx62, @Someone pour les bières. Ca fait très plaisir et ça m'encourage à continuer !
|
Un grand merci à @salabur, @pvince83, @bergoglio, @EPicLURcher, @ecolorado66, @Kriss1670, @maia, @f.maymil, @moutte69, @Jerome, @Gunnar M, @Greg.o, @John Burgess, @abyssmal, @capinfo26, @Helge, @MattG pour les bières. Ca fait très plaisir et ça m'encourage à continuer !
|
||||||
|
|
||||||
|
|
||||||
# Quand l'utiliser et ne pas l'utiliser
|
# Quand l'utiliser et ne pas l'utiliser
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ Consequently, the entire configuration phase of a VTherm has been profoundly mod
|
|||||||
**Note:** the VTherm configuration screenshots have not been updated.
|
**Note:** the VTherm configuration screenshots have not been updated.
|
||||||
|
|
||||||
# Thanks for the beer [buymecoffee](https://www.buymeacoffee.com/jmcollin78)
|
# Thanks for the beer [buymecoffee](https://www.buymeacoffee.com/jmcollin78)
|
||||||
Many thanks to @salabur, @pvince83, @bergoglio, @EPicLURcher, @ecolorado66, @Kriss1670, @maia, @f.maymil, @moutte69, @Jerome, @Gunnar M, @Greg.o, @John Burgess, @abyssmal, @capinfo26, @Helge, @MattG, @MattG, @Mexx62, @Someone for the beers. It's very nice and encourages me to continue!
|
Many thanks to @salabur, @pvince83, @bergoglio, @EPicLURcher, @ecolorado66, @Kriss1670, @maia, @f.maymil, @moutte69, @Jerome, @Gunnar M, @Greg.o, @John Burgess, @abyssmal, @capinfo26, @Helge, @MattG for the beers. It's very nice and encourages me to continue!
|
||||||
|
|
||||||
# When to use / not use
|
# When to use / not use
|
||||||
This thermostat can control 3 types of equipment:
|
This thermostat can control 3 types of equipment:
|
||||||
|
|||||||
@@ -86,10 +86,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
|
|
||||||
# VTherm API should have been initialized before arriving here
|
# VTherm API should have been initialized before arriving here
|
||||||
vtherm_api = VersatileThermostatAPI.get_vtherm_api()
|
vtherm_api = VersatileThermostatAPI.get_vtherm_api()
|
||||||
if vtherm_api is not None:
|
self._central_config = vtherm_api.find_central_configuration()
|
||||||
self._central_config = vtherm_api.find_central_configuration()
|
|
||||||
else:
|
|
||||||
self._central_config = None
|
|
||||||
|
|
||||||
self._init_feature_flags(infos)
|
self._init_feature_flags(infos)
|
||||||
self._init_central_config_flags(infos)
|
self._init_central_config_flags(infos)
|
||||||
@@ -122,7 +119,6 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
CONF_USE_WINDOW_CENTRAL_CONFIG,
|
CONF_USE_WINDOW_CENTRAL_CONFIG,
|
||||||
CONF_USE_MOTION_CENTRAL_CONFIG,
|
CONF_USE_MOTION_CENTRAL_CONFIG,
|
||||||
CONF_USE_POWER_CENTRAL_CONFIG,
|
CONF_USE_POWER_CENTRAL_CONFIG,
|
||||||
CONF_USE_PRESETS_CENTRAL_CONFIG,
|
|
||||||
CONF_USE_PRESENCE_CENTRAL_CONFIG,
|
CONF_USE_PRESENCE_CENTRAL_CONFIG,
|
||||||
CONF_USE_ADVANCED_CENTRAL_CONFIG,
|
CONF_USE_ADVANCED_CENTRAL_CONFIG,
|
||||||
):
|
):
|
||||||
@@ -171,7 +167,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Only one window detection method should be used. Use window_sensor or auto window open detection but not both"
|
"Only one window detection method should be used. Use window_sensor or auto window open detection but not both"
|
||||||
)
|
)
|
||||||
raise WindowOpenDetectionMethod(CONF_WINDOW_AUTO_OPEN_THRESHOLD)
|
raise WindowOpenDetectionMethod(CONF_WINDOW_SENSOR)
|
||||||
|
|
||||||
# Check that is USE_CENTRAL config is used, that a central config exists
|
# Check that is USE_CENTRAL config is used, that a central config exists
|
||||||
if self._central_config is None:
|
if self._central_config is None:
|
||||||
@@ -408,11 +404,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
next_step = self.async_step_motion
|
next_step = self.async_step_motion
|
||||||
# If comes from async_step_spec_window
|
# If comes from async_step_spec_window
|
||||||
elif self._infos.get(COMES_FROM) == "async_step_spec_window":
|
elif self._infos.get(COMES_FROM) == "async_step_spec_window":
|
||||||
# If we have a window sensor don't display the auto window parameters
|
schema = STEP_CENTRAL_WINDOW_DATA_SCHEMA
|
||||||
if self._infos.get(CONF_WINDOW_SENSOR) is not None:
|
|
||||||
schema = STEP_CENTRAL_WINDOW_WO_AUTO_DATA_SCHEMA
|
|
||||||
else:
|
|
||||||
schema = STEP_CENTRAL_WINDOW_DATA_SCHEMA
|
|
||||||
elif user_input and user_input.get(CONF_USE_WINDOW_CENTRAL_CONFIG) is False:
|
elif user_input and user_input.get(CONF_USE_WINDOW_CENTRAL_CONFIG) is False:
|
||||||
next_step = self.async_step_spec_window
|
next_step = self.async_step_spec_window
|
||||||
|
|
||||||
@@ -427,8 +419,6 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
schema = STEP_CENTRAL_WINDOW_DATA_SCHEMA
|
schema = STEP_CENTRAL_WINDOW_DATA_SCHEMA
|
||||||
if self._infos.get(CONF_WINDOW_SENSOR) is not None:
|
|
||||||
schema = STEP_CENTRAL_WINDOW_WO_AUTO_DATA_SCHEMA
|
|
||||||
|
|
||||||
self._infos[COMES_FROM] = "async_step_spec_window"
|
self._infos[COMES_FROM] = "async_step_spec_window"
|
||||||
|
|
||||||
|
|||||||
@@ -195,12 +195,6 @@ STEP_CENTRAL_WINDOW_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
STEP_CENTRAL_WINDOW_WO_AUTO_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
|
||||||
{
|
|
||||||
vol.Optional(CONF_WINDOW_DELAY, default=30): cv.positive_int,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
STEP_MOTION_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
STEP_MOTION_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_MOTION_SENSOR): selector.EntitySelector(
|
vol.Optional(CONF_MOTION_SENSOR): selector.EntitySelector(
|
||||||
|
|||||||
@@ -413,7 +413,6 @@
|
|||||||
"eco_away_temp": "Eco away preset",
|
"eco_away_temp": "Eco away preset",
|
||||||
"comfort_away_temp": "Comfort away preset",
|
"comfort_away_temp": "Comfort away preset",
|
||||||
"boost_away_temp": "Boost away preset",
|
"boost_away_temp": "Boost away preset",
|
||||||
"frost_away_temp": "Frost protection preset",
|
|
||||||
"eco_ac_away_temp": "Eco away preset in AC mode",
|
"eco_ac_away_temp": "Eco away preset in AC mode",
|
||||||
"comfort_ac_away_temp": "Comfort away preset in AC mode",
|
"comfort_ac_away_temp": "Comfort away preset in AC mode",
|
||||||
"boost_ac_away_temp": "Boost away preset in AC mode",
|
"boost_ac_away_temp": "Boost away preset in AC mode",
|
||||||
|
|||||||
@@ -413,7 +413,6 @@
|
|||||||
"eco_away_temp": "Eco away preset",
|
"eco_away_temp": "Eco away preset",
|
||||||
"comfort_away_temp": "Comfort away preset",
|
"comfort_away_temp": "Comfort away preset",
|
||||||
"boost_away_temp": "Boost away preset",
|
"boost_away_temp": "Boost away preset",
|
||||||
"frost_away_temp": "Frost protection preset",
|
|
||||||
"eco_ac_away_temp": "Eco away preset in AC mode",
|
"eco_ac_away_temp": "Eco away preset in AC mode",
|
||||||
"comfort_ac_away_temp": "Comfort away preset in AC mode",
|
"comfort_ac_away_temp": "Comfort away preset in AC mode",
|
||||||
"boost_ac_away_temp": "Boost away preset in AC mode",
|
"boost_ac_away_temp": "Boost away preset in AC mode",
|
||||||
|
|||||||
@@ -19,27 +19,26 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class VersatileThermostatAPI(dict):
|
class VersatileThermostatAPI(dict):
|
||||||
"""The VersatileThermostatAPI"""
|
"""The VersatileThermostatAPI"""
|
||||||
|
|
||||||
_hass: HomeAssistant = None
|
_hass: HomeAssistant
|
||||||
# _entries: Dict(str, ConfigEntry)
|
# _entries: Dict(str, ConfigEntry)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_vtherm_api(cls, hass=None):
|
def get_vtherm_api(cls, hass=None):
|
||||||
"""Get the eventual VTherm API class instance or
|
"""Get the eventual VTherm API class instance"""
|
||||||
instantiate it if it doesn't exists"""
|
|
||||||
if hass is not None:
|
if hass is not None:
|
||||||
VersatileThermostatAPI._hass = hass
|
VersatileThermostatAPI._hass = hass
|
||||||
|
else:
|
||||||
if VersatileThermostatAPI._hass is None:
|
if VersatileThermostatAPI._hass is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
domain = VersatileThermostatAPI._hass.data.get(DOMAIN)
|
domain = VersatileThermostatAPI._hass.data.get(DOMAIN)
|
||||||
if not domain:
|
if not domain:
|
||||||
VersatileThermostatAPI._hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
|
||||||
ret = VersatileThermostatAPI._hass.data.get(DOMAIN).get(VTHERM_API_NAME)
|
ret = VersatileThermostatAPI._hass.data.get(DOMAIN).get(VTHERM_API_NAME)
|
||||||
if ret is None:
|
if ret is None:
|
||||||
ret = VersatileThermostatAPI()
|
ret = VersatileThermostatAPI()
|
||||||
VersatileThermostatAPI._hass.data[DOMAIN][VTHERM_API_NAME] = ret
|
hass.data[DOMAIN][VTHERM_API_NAME] = ret
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -47,6 +46,7 @@ class VersatileThermostatAPI(dict):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._expert_params = None
|
self._expert_params = None
|
||||||
self._short_ema_params = None
|
self._short_ema_params = None
|
||||||
|
self._central_config = None
|
||||||
|
|
||||||
def find_central_configuration(self):
|
def find_central_configuration(self):
|
||||||
"""Search for a central configuration"""
|
"""Search for a central configuration"""
|
||||||
@@ -57,8 +57,8 @@ class VersatileThermostatAPI(dict):
|
|||||||
config_entry.data.get(CONF_THERMOSTAT_TYPE)
|
config_entry.data.get(CONF_THERMOSTAT_TYPE)
|
||||||
== CONF_THERMOSTAT_CENTRAL_CONFIG
|
== CONF_THERMOSTAT_CENTRAL_CONFIG
|
||||||
):
|
):
|
||||||
central_config = config_entry
|
self._central_config = config_entry
|
||||||
return central_config
|
return self._central_config
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def add_entry(self, entry: ConfigEntry):
|
def add_entry(self, entry: ConfigEntry):
|
||||||
|
|||||||
@@ -139,11 +139,6 @@ MOCK_PRESETS_AC_CONFIG = {
|
|||||||
|
|
||||||
MOCK_WINDOW_CONFIG = {
|
MOCK_WINDOW_CONFIG = {
|
||||||
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
||||||
# Not used normally only for tests to avoid rewrite all tests
|
|
||||||
CONF_WINDOW_DELAY: 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
MOCK_WINDOW_DELAY_CONFIG = {
|
|
||||||
CONF_WINDOW_DELAY: 10,
|
CONF_WINDOW_DELAY: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ from .commons import * # pylint: disable=wildcard-import, unused-wildcard-impor
|
|||||||
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
||||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
||||||
async def test_add_a_central_config(hass: HomeAssistant, skip_hass_states_is_state):
|
async def test_add_a_central_config(hass: HomeAssistant, skip_hass_states_is_state):
|
||||||
"""Tests the clean_central_config_doubon of base_thermostat"""
|
"""Tests the clean_central_config_doubon of base_thermostat"""
|
||||||
central_config_entry = MockConfigEntry(
|
central_config_entry = MockConfigEntry(
|
||||||
@@ -97,8 +95,6 @@ async def test_add_a_central_config(hass: HomeAssistant, skip_hass_states_is_sta
|
|||||||
assert central_configuration is not None
|
assert central_configuration is not None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
||||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
||||||
async def test_minimal_over_switch_wo_central_config(
|
async def test_minimal_over_switch_wo_central_config(
|
||||||
hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api
|
hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api
|
||||||
):
|
):
|
||||||
@@ -173,8 +169,6 @@ async def test_minimal_over_switch_wo_central_config(
|
|||||||
assert entity.is_inversed
|
assert entity.is_inversed
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
||||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
||||||
async def test_full_over_switch_wo_central_config(
|
async def test_full_over_switch_wo_central_config(
|
||||||
hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api
|
hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api
|
||||||
):
|
):
|
||||||
@@ -287,8 +281,6 @@ async def test_full_over_switch_wo_central_config(
|
|||||||
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
||||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
||||||
async def test_full_over_switch_with_central_config(
|
async def test_full_over_switch_with_central_config(
|
||||||
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
||||||
):
|
):
|
||||||
@@ -396,8 +388,6 @@ async def test_full_over_switch_with_central_config(
|
|||||||
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
||||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
||||||
async def test_over_switch_with_central_config_but_no_central_config(
|
async def test_over_switch_with_central_config_but_no_central_config(
|
||||||
hass: HomeAssistant, skip_hass_states_get, init_vtherm_api
|
hass: HomeAssistant, skip_hass_states_get, init_vtherm_api
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -472,17 +472,15 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input=MOCK_WINDOW_DELAY_CONFIG,
|
user_input=MOCK_WINDOW_AUTO_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Since issue #280 we cannot have the error because we only display the
|
|
||||||
# MOCK_WINDOW_DELAY_CONFIG form if we have a sensor configured
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
# We should stay on window with an error
|
# We should stay on window with an error
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {
|
||||||
# "window_sensor_entity_id": "window_open_detection_method"
|
"window_sensor_entity_id": "window_open_detection_method"
|
||||||
# }
|
}
|
||||||
assert result["step_id"] == "advanced"
|
assert result["step_id"] == "window"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
|||||||
Reference in New Issue
Block a user