Compare commits

..

10 Commits

Author SHA1 Message Date
Jean-Marc Collin 8961a80086 UPdate README with release 5.0 2023-12-17 10:54:07 +00:00
Jean-Marc Collin 2f6c46ef11 Update strings.json and replace security by safety in README. 2023-12-17 10:03:57 +00:00
Jean-Marc Collin af817e74b7 Add reload VTherms when central configuration is changed 2023-12-17 09:41:22 +00:00
Jean-Marc Collin 46307286b1 With fixture for init_vtherm_api and init_central_config 2023-12-17 08:57:08 +00:00
Jean-Marc Collin c8398a48fe All testu ok 2023-12-17 08:16:37 +00:00
Jean-Marc Collin 5063ba3802 With central configuration testu ok 2023-12-17 06:57:06 +00:00
Jean-Marc Collin fb76a84bde Init data in base_thermostat ok 2023-12-16 15:24:11 +00:00
Jean-Marc Collin 03f6045d34 Ignore central confic in instanciate entities 2023-12-15 22:58:36 +00:00
Jean-Marc Collin aeb4b2fbbe Test manual of confif_flow ok 2023-12-15 22:37:40 +00:00
Jean-Marc Collin 47f5aa9595 Add central config into ConfigFlow 2023-12-15 18:37:25 +00:00
10 changed files with 20 additions and 55 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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,10 +404,6 @@ 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
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 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):
-5
View File
@@ -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,
} }
-10
View File
@@ -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
): ):
+5 -7
View File
@@ -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])