Skip to content

Commit

Permalink
Issue_766-enhance_power_management (#778)
Browse files Browse the repository at this point in the history
* First implem + tests (not finished)

* With tests of calculate_shedding ok

* Commit for rebase

* All tests ok for central_feature_power_manager

* All tests not ok

* All tests ok

* integrattion tests - Do startup works

* enhance the overpowering algo if current_power > max_power

* Change shedding calculation delay to 20 sec (vs 60 sec)

* Integration tests ok

* Fix overpowering is set even if other heater have on_percent = 0

* Fix too much shedding in over_climate

* Add logs

* Add temporal filter for calculate_shedding
Add restore overpowering state at startup

* Fix restore overpowering_state

* Removes poweer_entity_id from vtherm non central config

* Release

* Add Sonoff TRVZB in creation.md

* Add comment on Sonoff TRVZB Closing degree

---------

Co-authored-by: Jean-Marc Collin <[email protected]>
  • Loading branch information
jmcollin78 and Jean-Marc Collin authored Jan 5, 2025
1 parent 9c8a965 commit 22b2b96
Show file tree
Hide file tree
Showing 50 changed files with 1,958 additions and 4,055 deletions.
1 change: 1 addition & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"python.analysis.autoSearchPaths": true,
"pylint.lintOnChange": false,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "180"],
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
Expand Down
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[FORMAT]
max-line-length=180
43 changes: 22 additions & 21 deletions README-fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,28 @@ Un grand merci à tous mes fournisseurs de bières pour leurs dons et leurs enco

La documentation est maintenant découpée en plusieurs pages pour faciliter la lecture et la recherche d'informations :
1. [présentation](documentation/fr/presentation.md),
2. [choisir un type de VTherm](documentation/fr/creation.md),
3. [les attributs de base](documentation/fr/base-attributes.md)
3. [configurer un VTherm sur un `switch`](documentation/fr/over-switch.md)
3. [configurer un VTherm sur un `climate`](documentation/fr/over-climate.md)
3. [configurer un VTherm sur une vanne](documentation/fr/over-valve.md)
4. [les pré-régages (preset)](documentation/fr/feature-presets.md)
5. [la gestion des ouvertures](documentation/fr/feature-window.md)
6. [la gestion de la présence](documentation/fr/feature-presence.md)
7. [la gestion de mouvement](documentation/fr/feature-motion.md)
8. [la gestion de la puissance](documentation/fr/feature-power.md)
9. [l'auto start and stop](documentation/fr/feature-auto-start-stop.md)
10. [la contrôle centralisé de tous vos VTherms](documentation/fr/feature-central-mode.md)
11. [la commande du chauffage central](documentation/fr/feature-central-boiler.md)
12. [aspects avancés, mode sécurité](documentation/fr/feature-advanced.md)
12. [l'auto-régulation](documentation/fr/self-regulation.md)
13. [exemples de réglages](documentation/fr/tuning-examples.md)
14. [les différents algorithmes](documentation/fr/algorithms.md)
15. [documentation de référence](documentation/fr/reference.md)
16. [exemple de réglages](documentation/fr/tuning-examples.md)
17. [dépannage](documentation/fr/troubleshooting.md)
18. [notes de version](documentation/fr/releases.md)
2. [Installation](documentation/fr/installation.md),
3. [choisir un type de VTherm](documentation/fr/creation.md),
4. [les attributs de base](documentation/fr/base-attributes.md)
5. [configurer un VTherm sur un `switch`](documentation/fr/over-switch.md)
6. [configurer un VTherm sur un `climate`](documentation/fr/over-climate.md)
7. [configurer un VTherm sur une vanne](documentation/fr/over-valve.md)
8. [les pré-régages (preset)](documentation/fr/feature-presets.md)
9. [la gestion des ouvertures](documentation/fr/feature-window.md)
10. [la gestion de la présence](documentation/fr/feature-presence.md)
11. [la gestion de mouvement](documentation/fr/feature-motion.md)
12. [la gestion de la puissance](documentation/fr/feature-power.md)
13. [l'auto start and stop](documentation/fr/feature-auto-start-stop.md)
14. [la contrôle centralisé de tous vos VTherms](documentation/fr/feature-central-mode.md)
15. [la commande du chauffage central](documentation/fr/feature-central-boiler.md)
16. [aspects avancés, mode sécurité](documentation/fr/feature-advanced.md)
17. [l'auto-régulation](documentation/fr/self-regulation.md)
18. [exemples de réglages](documentation/fr/tuning-examples.md)
19. [les différents algorithmes](documentation/fr/algorithms.md)
20. [documentation de référence](documentation/fr/reference.md)
21. [exemple de réglages](documentation/fr/tuning-examples.md)
22. [dépannage](documentation/fr/troubleshooting.md)
23. [notes de version](documentation/fr/releases.md)


# Quelques résultats
Expand Down
10 changes: 7 additions & 3 deletions custom_components/versatile_thermostat/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
class BaseFeatureManager:
"""A base class for all feature"""

def __init__(self, vtherm: Any, hass: HomeAssistant):
def __init__(self, vtherm: Any, hass: HomeAssistant, name: str = None):
"""Init of a featureManager"""
self._vtherm = vtherm
self._name = vtherm.name
self._name = vtherm.name if vtherm else name
self._active_listener: list[CALLBACK_TYPE] = []
self._hass = hass

def post_init(self, entry_infos: ConfigData):
"""Initialize the attributes of the FeatureManager"""
raise NotImplementedError()

def start_listening(self):
async def start_listening(self):
"""Start listening the underlying entity"""
raise NotImplementedError()

Expand All @@ -38,6 +38,10 @@ def stop_listening(self) -> bool:

self._active_listener = []

async def refresh_state(self):
"""Refresh the state and return True if a change have been made"""
return False

def add_listener(self, func: CALLBACK_TYPE) -> None:
"""Add a listener to the list of active listener"""
self._active_listener.append(func)
Expand Down
64 changes: 40 additions & 24 deletions custom_components/versatile_thermostat/base_thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
ATTR_TEMPERATURE,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
STATE_ON,
)

from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
Expand Down Expand Up @@ -99,7 +98,6 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
"comfort_away_temp",
"power_temp",
"ac_mode",
"current_max_power",
"saved_preset_mode",
"saved_target_temp",
"saved_hvac_mode",
Expand Down Expand Up @@ -191,7 +189,6 @@ def __init__(

self._ema_temp = None
self._ema_algo = None
self._now = None

self._attr_fan_mode = None

Expand Down Expand Up @@ -446,10 +443,6 @@ async def async_added_to_hass(self):
)
)

# start listening for all managers
for manager in self._managers:
manager.start_listening()

self.async_on_remove(self.remove_thermostat)

# issue 428. Link to others entities will start at link
Expand Down Expand Up @@ -482,6 +475,10 @@ async def async_startup(self, central_configuration):
_LOGGER.debug("%s - Calling async_startup_internal", self)
need_write_state = False

# start listening for all managers
for manager in self._managers:
await manager.start_listening()

await self.get_my_previous_state()

await self.init_presets(central_configuration)
Expand Down Expand Up @@ -1454,7 +1451,7 @@ async def async_underlying_entity_turn_off(self):
control_heating to turn all off"""

for under in self._underlyings:
await under.turn_off()
await under.turn_off_and_cancel_cycle()

def save_preset_mode(self):
"""Save the current preset mode to be restored later
Expand All @@ -1466,15 +1463,15 @@ def save_preset_mode(self):
):
self._saved_preset_mode = self._attr_preset_mode

async def restore_preset_mode(self):
async def restore_preset_mode(self, force=False):
"""Restore a previous preset mode
We never restore a hidden preset mode. Normally that is not possible
"""
if (
self._saved_preset_mode not in HIDDEN_PRESETS
and self._saved_preset_mode is not None
):
await self.async_set_preset_mode_internal(self._saved_preset_mode)
await self.async_set_preset_mode_internal(self._saved_preset_mode, force=force)

def save_hvac_mode(self):
"""Save the current hvac-mode to be restored later"""
Expand Down Expand Up @@ -1582,15 +1579,6 @@ def save_all():
await self.async_set_hvac_mode(HVACMode.OFF)
return

def _set_now(self, now: datetime):
"""Set the now timestamp. This is only for tests purpose"""
self._now = now

@property
def now(self) -> datetime:
"""Get now. The local datetime or the overloaded _set_now date"""
return self._now if self._now is not None else NowClass.get_now(self._hass)

@property
def is_initialized(self) -> bool:
"""Check if all underlyings are initialized
Expand Down Expand Up @@ -1620,11 +1608,8 @@ async def async_control_heating(self, force=False, _=None) -> bool:
return False

# Check overpowering condition
# Not necessary for switch because each switch is checking at startup
overpowering = await self._power_manager.check_overpowering()
if overpowering == STATE_ON:
_LOGGER.debug("%s - End of cycle (overpowering)", self)
return True
# Not usefull. Will be done at the next power refresh
# await VersatileThermostatAPI.get_vtherm_api().central_power_manager.refresh_state()

safety: bool = await self._safety_manager.refresh_state()
if safety and self.is_over_climate:
Expand Down Expand Up @@ -1965,3 +1950,34 @@ async def async_turn_on(self) -> None:
def is_preset_configured(self, preset) -> bool:
"""Returns True if the preset in argument is configured"""
return self._presets.get(preset, None) is not None

# For testing purpose
# @deprecated
def _set_now(self, now: datetime):
"""Set the now timestamp. This is only for tests purpose
This method should be replaced by the vthermAPI equivalent"""
VersatileThermostatAPI.get_vtherm_api(self._hass)._set_now(now) # pylint: disable=protected-access

# @deprecated
@property
def now(self) -> datetime:
"""Get now. The local datetime or the overloaded _set_now date
This method should be replaced by the vthermAPI equivalent"""
return VersatileThermostatAPI.get_vtherm_api(self._hass).now

@property
def power_percent(self) -> float | None:
"""Get the current on_percent as a percentage value. valid only for Vtherm with a TPI algo
Get the current on_percent value"""
if self._prop_algorithm and self._prop_algorithm.on_percent is not None:
return round(self._prop_algorithm.on_percent * 100, 0)
else:
return None

@property
def on_percent(self) -> float | None:
"""Get the current on_percent value. valid only for Vtherm with a TPI algo"""
if self._prop_algorithm and self._prop_algorithm.on_percent is not None:
return self._prop_algorithm.on_percent
else:
return None
Loading

0 comments on commit 22b2b96

Please sign in to comment.