Compare commits

..

7 Commits

Author SHA1 Message Date
Jean-Marc Collin cf2098bd88 Release 4.0.0 2023-11-06 12:53:28 +01:00
Jean-Marc Collin 0c8d80f378 Issue #168 - Adds slow auto-new_slow_regulation (#170)
Issue #169 - Adds support for Versatile Thermostat UI Card

Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
2023-11-06 12:31:45 +01:00
Jean-Marc Collin 69a05725c9 Update the template for issue. 2023-11-05 09:38:28 +00:00
adi90x 9abcd98f52 Mean power Update (#150)
* Mean power should not multiply power setup + Documentation

* Update test to use device_power
2023-11-03 23:31:41 +01:00
Andrea Nicotra 5e6b477174 switch from HEAT to COOL mode (#144)
* support both HEAT and COOL mode

* update unit test to support both HEAT and COOL mode
2023-11-02 00:40:48 +01:00
Jean-Marc Collin 89b6f0523b FIX is_device_active 2023-11-01 23:08:01 +00:00
Jean-Marc Collin 8282b69209 FIX issue #145 2023-11-01 12:43:39 +01:00
23 changed files with 260 additions and 96 deletions
+2
View File
@@ -212,6 +212,8 @@ switch:
entity_id: select.seche_serviettes_sdb_rdc_cable_outlet_mode
frontend:
extra_module_url:
- /config/www/community/versatile-thermostat-ui-card/versatile-thermostat-ui-card.js
themes:
versatile_thermostat_theme:
state-binary_sensor-safety-on-color: "#FF0B0B"
+4 -2
View File
@@ -10,7 +10,9 @@
"postCreateCommand": "./container dev-setup",
"mounts": [
"source=/Users/jmcollin/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached"
"source=/Users/jmcollin/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
// uncomment this to get the versatile-thermostat-ui-card
"source=${localEnv:HOME}/SugarSync/Projets/home-assistant/versatile-thermostat-ui-card/dist,target=/workspaces/versatile_thermostat/config/www/community/versatile-thermostat-ui-card,type=bind,consistency=cached"
],
"customizations": {
@@ -22,7 +24,7 @@
"ms-python.vscode-pylance"
],
// "mounts": [
// "source=${localWorkspaceFolder}/.devcontainer/configuration.yaml,target=/home/vscode/core/config/configuration.yaml,type=bind,consistency=cached",
// "source=${localWorkspaceFolder}/.devcontainer/configuration.yaml,target=${localWorkspaceFolder}/config/www/community/,type=bind,consistency=cached",
// "source=${localWorkspaceFolder}/custom_components,target=/home/vscode/core/config/custom_components,type=bind,consistency=cached"
// ],
"settings": {
+103 -5
View File
@@ -6,10 +6,11 @@ about: Create a report to help us improve
<!-- Before you open a new issue, search through the existing issues to see if others have had the same problem.
If you have a simple question or you are not sure this is an issue, don't open an issue but open a new discussion [here](https://github.com/jmcollin78/versatile_thermostat/discussions).
Issues not containing the minimum requirements will be closed:
- Issues without a description (using the header is not good enough) will be closed.
- Issues without debug logging will be closed.
- Issues without configuration will be closed
-->
@@ -21,19 +22,116 @@ If you are unsure about the version check the const.py file.
## Configuration
<!-- Copy / paste the attributes of the VTherm here. You can go to Development Tool / States, find and select your VTherm and the copy/paste the attributes.
Without these attribute support is impossible due to the number of configuration attributes the VTherm have (more than 60). -->
My VTherm attributes are the following:
```yaml
Add your logs here.
hvac_modes:
- heat
- 'off'
min_temp: 7
max_temp: 35
preset_modes:
- none
- eco
- comfort
- boost
- activity
current_temperature: 18.9
temperature: 22
hvac_action: 'off'
preset_mode: security
hvac_mode: 'off'
type: null
eco_temp: 17
boost_temp: 20
comfort_temp: 19
eco_away_temp: 16.1
boost_away_temp: 16.3
comfort_away_temp: 16.2
power_temp: 13
ext_current_temperature: 11.6
ac_mode: false
current_power: 450
current_power_max: 910
saved_preset_mode: none
saved_target_temp: 22
saved_hvac_mode: heat
window_state: 'on'
motion_state: 'off'
overpowering_state: false
presence_state: 'on'
window_auto_state: false
window_bypass_state: false
security_delay_min: 2
security_min_on_percent: 0.5
security_default_on_percent: 0.1
last_temperature_datetime: '2023-11-05T00:48:54.873157+01:00'
last_ext_temperature_datetime: '2023-11-05T00:48:53.240122+01:00'
security_state: true
minimal_activation_delay_sec: 1
device_power: 300
mean_cycle_power: 30
total_energy: 137.5
last_update_datetime: '2023-11-05T00:51:54.901140+01:00'
timezone: Europe/Paris
window_sensor_entity_id: input_boolean.fake_window_sensor1
window_delay_sec: 20
window_auto_open_threshold: null
window_auto_close_threshold: null
window_auto_max_duration: null
motion_sensor_entity_id: input_boolean.fake_motion_sensor1
presence_sensor_entity_id: input_boolean.fake_presence_sensor1
power_sensor_entity_id: input_number.fake_current_power
max_power_sensor_entity_id: input_number.fake_current_power_max
is_over_switch: true
underlying_switch_0: input_boolean.fake_heater_switch1
underlying_switch_1: null
underlying_switch_2: null
underlying_switch_3: null
on_percent: 0.1
on_time_sec: 6
off_time_sec: 54
cycle_min: 1
function: tpi
tpi_coef_int: 0.6
tpi_coef_ext: 0.01
friendly_name: Thermostat switch 1
supported_features: 17
```
<!-- Please do not send an image but a copy / paste of the attributes in yaml format. -->
## Describe the bug
A clear and concise description of what the bug is.
I'm trying to:
<!-- compleete the description -->
And I expect:
<!-- complete the expectations -->
But I observe this ....
<!-- complete what you observe and why you think it is erroneous. -->
I read the documentation on the README.md file and I don't find any relevant information about this issue.
## Debug log
<!-- To enable debug logs check this https://www.home-assistant.io/components/logger/ -->
<!-- To enable debug logs check this https://www.home-assistant.io/components/logger/
Add the following configuration into your `configuration.yaml` (or `logger.yaml` if you have one) to enable logs: -->
```yaml
logger:
default: info
logs:
custom_components.versatile_thermostat: info
```
<!-- You can also switch to debug mode but be careful, in debug mode, the logs are verbose.
Please copy/paste the releveant logs (around the failure) below: -->
```text
+2 -1
View File
@@ -107,4 +107,5 @@ dist
custom_components/__init__.py
__pycache__
config/**
config/**
custom_components/hacs
+14 -2
View File
@@ -8,6 +8,7 @@
> ![Tip](https://github.com/jmcollin78/versatile_thermostat/blob/main/images/tips.png?raw=true) Cette intégration de thermostat vise à simplifier considérablement vos automatisations autour de la gestion du chauffage. Parce que tous les événements autour du chauffage classiques sont gérés nativement par le thermostat (personne à la maison ?, activité détectée dans une pièce ?, fenêtre ouverte ?, délestage de courant ?), vous n'avez pas à vous encombrer de scripts et d'automatismes compliqués pour gérer vos climats. ;-).
- [Changements majeurs dans la version 4.0.0](#changements-majeurs-dans-la-version-400)
- [Merci pour la bière buymecoffee](#merci-pour-la-bière-buymecoffee)
- [Quand l'utiliser et ne pas l'utiliser](#quand-lutiliser-et-ne-pas-lutiliser)
- [Incompatibilités](#incompatibilités)
@@ -50,6 +51,7 @@
- [Attributs personnalisés](#attributs-personnalisés)
- [Quelques résultats](#quelques-résultats)
- [Encore mieux](#encore-mieux)
- [Bien mieux avec le Veersatile Thermostat UI Card](#bien-mieux-avec-le-veersatile-thermostat-ui-card)
- [Encore mieux avec le composant Scheduler !](#encore-mieux-avec-le-composant-scheduler-)
- [Encore bien mieux avec la custom:simple-thermostat front integration](#encore-bien-mieux-avec-la-customsimple-thermostat-front-integration)
- [Toujours mieux avec Apex-chart pour régler votre thermostat](#toujours-mieux-avec-apex-chart-pour-régler-votre-thermostat)
@@ -61,13 +63,14 @@ Ce composant personnalisé pour Home Assistant est une mise à niveau et est une
> ![Nouveau](https://github.com/jmcollin78/versatile_thermostat/blob/main/images/new-icon.png?raw=true) _*Nouveautés*_
> * **Release 4.0** : Ajout de la prise en charge de la **Versatile Thermostat UI Card**. Voir [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card). Ajout d'un mode de régulation **Slow** pour les appareils de chauffage à latence lente [#168](https://github.com/jmcollin78/versatile_thermostat/issues/168). Changement de la façon dont **la puissance est calculée** dans le cas de VTherm avec des équipements multi-sous-jacents [#146](https://github.com/jmcollin78/versatile_thermostat/issues/146). Ajout de la prise en charge de AC et Heat pour VTherm via un interrupteur également [#144](https://github.com/jmcollin78/versatile_thermostat/pull/144)
> * **Release 3.8**: Ajout d'une **fonction d'auto-régulation** pour les thermostats `over climate` dont la régulation est faite par le climate sous-jacent. Cf. [L'auto-régulation](#lauto-régulation) et [#129](https://github.com/jmcollin78/versatile_thermostat/issues/129). Ajout de la **possibilité d'inverser la commande** pour un thermostat `over switch` pour adresser les installations avec fil pilote et diode [#124](https://github.com/jmcollin78/versatile_thermostat/issues/124).
> * **Release 3.7**: Ajout du type de **Versatile Thermostat `over valve`** pour piloter une vanne TRV directement ou tout autre équipement type gradateur pour le chauffage. La régulation se fait alors directement en agissant sur le pourcentage d'ouverture de l'entité sous-jacente : 0 la vanne est coupée, 100 : la vanne est ouverte à fond. Cf. [#131](https://github.com/jmcollin78/versatile_thermostat/issues/131). Ajout d'une fonction permettant le bypass de la détection d'ouverture [#138](https://github.com/jmcollin78/versatile_thermostat/issues/138). Ajout de la langue Slovaque
> * **Release 3.6**: Ajout du paramètre `motion_off_delay` pour améliorer la gestion de des mouvements [#116](https://github.com/jmcollin78/versatile_thermostat/issues/116), [#128](https://github.com/jmcollin78/versatile_thermostat/issues/128). Ajout du mode AC (air conditionné) pour un VTherm over switch. Préparation du projet Github pour faciliter les contributions [#127](https://github.com/jmcollin78/versatile_thermostat/issues/127)
> * **Release 3.5**: Plusieurs thermostats sont possibles en "thermostat over climate" mode [#113](https://github.com/jmcollin78/versatile_thermostat/issues/113)
<details>
<summary>Autres versions</summary>
> * **Release 3.5**: Plusieurs thermostats sont possibles en "thermostat over climate" mode [#113](https://github.com/jmcollin78/versatile_thermostat/issues/113)
> * **Release 3.4**: bug fix et exposition des preset temperatures pour le mode AC [#103](https://github.com/jmcollin78/versatile_thermostat/issues/103)
> * **Release 3.3**: ajout du mode Air Conditionné (AC). Cette fonction vous permet d'utiliser le mode AC de votre thermostat sous-jacent. Pour l'utiliser, vous devez cocher l'option "Uitliser le mode AC" et définir les valeurs de température pour les presets et pour les presets en cas d'absence
> * **Release 3.2** : ajout de la possibilité de commander plusieurs switch à partir du même thermostat. Dans ce mode, les switchs sont déclenchés avec un délai pour minimiser la puissance nécessaire à un instant (on minimise les périodes de recouvrement). Voir [Configuration](#sélectionnez-des-entités-pilotées)
@@ -78,6 +81,9 @@ Ce composant personnalisé pour Home Assistant est une mise à niveau et est une
> * **release majeure 2.0** : ajout du thermostat "over climate" permettant de transformer n'importe quel thermostat en Versatile Thermostat et lui ajouter toutes les fonctions de ce dernier.
</details>
# Changements majeurs dans la version 4.0.0
La puissance de l'appareil doit maintenant être la puissance totale de tous les appareils controlée par le VTherm. Cela permet d'avoir des équipements hétérogènes de puissance différente. Dans le cas de plusieurs appareils contrôlés par un seul VTherm, vous devrez éditer et changer la valeur `device_power`. Vous devez configurer la puissance totale de tous les appareils.
# 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 pour les bières. Ca fait très plaisir et ça m'encourage à continuer !
@@ -344,6 +350,7 @@ Cela vous permet de modifier la puissance maximale au fil du temps à l'aide d'u
> 2. Je l'utilise pour éviter de dépasser la limite de mon contrat d'électricité lorsqu'un véhicule électrique est en charge. Cela crée une sorte d'autorégulation.
> 3. Gardez toujours une marge, car la puissance max peut être brièvement dépassée en attendant le calcul du prochain cycle typiquement ou par des équipements non régulés.
> 4. Si vous ne souhaitez pas utiliser cette fonctionnalité, laissez simplement l'identifiant des entités vide
> 5. Si vous controlez plusieurs radiateurs, la **consommation électrique de votre chauffage** renseigné doit correspondre à la somme des puissances.
## Configurer la présence ou l'occupation
Si sélectionnée en première page, cette fonction vous permet de modifier dynamiquement la température de tous les préréglages du thermostat configurés lorsque personne n'est à la maison ou lorsque quelqu'un rentre à la maison. Pour cela, vous devez configurer la température qui sera utilisée pour chaque préréglage lorsque la présence est désactivée. Lorsque le capteur de présence s'éteint, ces températures seront utilisées. Lorsqu'il se rallume, la température "normale" configurée pour le préréglage est utilisée. Voir [gestion des préréglages](#configure-the-preset-temperature).
@@ -385,7 +392,7 @@ Voir [exemple de réglages](#examples-tuning) pour avoir des exemples de réglag
> 2. Attention, deux températures sont nécessaires : la température interne et la température externe et chacune doit donner la température, sinon le thermostat sera en préréglage "security",
> 3. Un service est disponible qui permet de régler les 3 paramètres de sécurité. Ca peut servir à adapter la fonction de sécurité à votre usage,
> 4. Pour un usage naturel, le ``security_default_on_percent`` doit être inférieur à ``security_min_on_percent``,
> 5. Lorsqu'un thermostat de type ``thermostat_over_climate`` passe en mode ``security`` il est éteint. Les paramètres ``security_min_on_percent`` et ``security_default_on_percent`` ne sont alors pas utilisés.
> 5. Les thermostats de type ``thermostat_over_climate`` ne sont pas concernés par le mode security.
## Synthèse des paramètres
@@ -728,6 +735,11 @@ Enjoy !
# Encore mieux
## Bien mieux avec le Veersatile Thermostat UI Card
Une carte spéciale pour le Versatile Thermostat a été développée (sur la base du Better Thermostat). Elle est dispo ici [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card) et propose une vision moderne de tous les status du VTherm :
![image](https://github.com/jmcollin78/versatile-thermostat-ui-card/blob/master/assets/1.png?raw=true)
## Encore mieux avec le composant Scheduler !
Afin de profiter de toute la puissance du Versatile Thermostat, je vous invite à l'utiliser avec https://github.com/nielsfaber/scheduler-component
+17 -7
View File
@@ -8,6 +8,7 @@
> ![Tip](https://github.com/jmcollin78/versatile_thermostat/blob/main/images/tips.png?raw=true) This thermostat integration aims to drastically simplify your automations around climate management. Because all classical events in climate are natively handled by the thermostat (nobody at home ?, activity detected in a room ?, window open ?, power shedding ?), you don't have to build over complicated scripts and automations to manage your climates ;-).
- [Breaking changes in 4.0.0](#breaking-changes-in-400)
- [Thanks for the beer buymecoffee](#thanks-for-the-beer-buymecoffee)
- [When to use / not use](#when-to-use--not-use)
- [Incompatibilities](#incompatibilities)
@@ -29,7 +30,6 @@
- [Auto mode](#auto-mode)
- [Configure the activity mode or motion detection](#configure-the-activity-mode-or-motion-detection)
- [Configure the power management](#configure-the-power-management)
- [Configure the presence or occupancy](#configure-the-presence-or-occupancy)
- [Advanced configuration](#advanced-configuration)
- [Parameters synthesis](#parameters-synthesis)
- [Examples tuning](#examples-tuning)
@@ -50,6 +50,7 @@
- [Custom attributes](#custom-attributes)
- [Some results](#some-results)
- [Even better](#even-better)
- [Much better with the Veersatile Thermostat UI Card](#much-better-with-the-veersatile-thermostat-ui-card)
- [Even Better with Scheduler Component !](#even-better-with-scheduler-component-)
- [Even-even better with custom:simple-thermostat front integration](#even-even-better-with-customsimple-thermostat-front-integration)
- [Even better with Apex-chart to tune your Thermostat](#even-better-with-apex-chart-to-tune-your-thermostat)
@@ -60,13 +61,14 @@
This custom component for Home Assistant is an upgrade and is a complete rewrite of the component "Awesome thermostat" (see [Github](https://github.com/dadge/awesome_thermostat)) with addition of features.
>![New](https://github.com/jmcollin78/versatile_thermostat/blob/main/images/new-icon.png?raw=true) _*News*_
> * **Release 4.0**: Added the support of **Versatile Thermostat UI Card**. See [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card). Added a **Slow** regulation mode for slow latency heating devices [#168](https://github.com/jmcollin78/versatile_thermostat/issues/168). Change the way **the power is calculated** in case of VTherm with multi-underlying equipements [#146](https://github.com/jmcollin78/versatile_thermostat/issues/146). Added the support of AC and Heat for VTherm over switch alse [#144](https://github.com/jmcollin78/versatile_thermostat/pull/144)
> * **Release 3.8**: Added a **self-regulation function** for `over climate` thermostats whose regulation is done by the underlying climate. See [Self-regulation](#self-regulation) and [#129](https://github.com/jmcollin78/versatile_thermostat/issues/129). Added the possibility of **inverting the command** for an `over switch` thermostat to address installations with pilot wire and diode [#124](https://github.com/jmcollin78/versatile_thermostat/issues/124).
> * **Release 3.7**: Addition of the **Versatile Thermostat type `over valve`** to control a TRV valve directly or any other dimmer type equipment for heating. Regulation is then done directly by acting on the opening percentage of the underlying entity: 0 the valve is cut off, 100: the valve is fully opened. See [#131](https://github.com/jmcollin78/versatile_thermostat/issues/131). Added a function allowing the bypass of opening detection [#138](https://github.com/jmcollin78/versatile_thermostat/issues/138). Added Slovak language
> * **Release 3.6**: Added the `motion_off_delay` parameter to improve motion management [#116](https://github.com/jmcollin78/versatile_thermostat/issues/116), [#128](https://github.com/jmcollin78/versatile_thermostat/issues/128). Added AC (air conditioning) mode for a VTherm over switch. Preparing the Github project to facilitate contributions [#127](https://github.com/jmcollin78/versatile_thermostat/issues/127)
> * **Release 3.5**: Multiple thermostats when using "thermostat over another thermostat" mode [#113](https://github.com/jmcollin78/versatile_thermostat/issues/113)
<details>
<summary>Others releases</summary>
> * **Release 3.5**: Multiple thermostats when using "thermostat over another thermostat" mode [#113](https://github.com/jmcollin78/versatile_thermostat/issues/113)
> * **Release 3.4**: bug fixes and expose preset temperatures for AC mode [#103](https://github.com/jmcollin78/versatile_thermostat/issues/103)
> * **Release 3.3**: add the Air Conditionned mode (AC). This feature allow to use the eventual AC mode of your underlying climate entity. You have to check the "Use AC mode" checkbox in configuration and give preset temperature value for AC mode and AC mode when absent if absence is configured
> * **Release 3.2**: add the ability to control multiple switches from the same thermostat. In this mode, the switches are triggered with a delay to minimize the power required at one time (we minimize the recovery periods). See [Configuration](#select-the-driven-entity)
@@ -77,6 +79,9 @@ This custom component for Home Assistant is an upgrade and is a complete rewrite
> * **major release 2.0**: addition of the "over climate" thermostat allowing you to transform any thermostat into a Versatile Thermostat and add all the functions of the latter.
</details>
# Breaking changes in 4.0.0
The power of the device should now be the total power of all controler devices by the VTherm. This allow to have eterogeneous equipment with different power. In case of multi-devices controlled by a single VTherm you will have to edit and change the `device_power` value. Set the total power of all devices.
# Thanks for the beer [buymecoffee](https://www.buymeacoffee.com/jmcollin78)
Many thanks to @salabur, @pvince83, @bergoglio, @EPicLURcher, @ecolorado66, @Kriss1670, @maia, @f.maymil, @moutte69, @Jerome for the beers. It's very nice and encourages me to continue!
@@ -331,8 +336,8 @@ This allows you to change the max power along time using a Scheduler or whatever
> 2. I use this to avoid exceeded the limit of my electrical power contract when an electrical vehicle is charging. This makes a kind of auto-regulation.
> 3. Always keep a margin, because max power can be briefly exceeded while waiting for the next cycle calculation typically or by not regulated equipement.
> 4. If you don't want to use this feature, just leave the entities id empty
> 5. If you control several heaters, the **power consumption of your heater** setup should be the sum of the power.
## Configure the presence or occupancy
If you choose the ```Presence management``` feature, this feature allows you to dynamically changes the temperature of all configured Versatile thermostat's presets when nobody is at home or when someone comes back home. For this, you have to configure the temperature that will be used for each preset when presence is off. When the occupancy sensor turns to off, those tempoeratures will be used. When it turns on again the "normal" temperature configured for the preset is used. See [preset management](#configure-the-preset-temperature).
To configure presence fills this form:
@@ -372,7 +377,7 @@ See [example tuning](#examples-tuning) for common tuning examples
> 2. Attention, two temperatures are needed: internal temperature and external temperature and each must give the temperature, otherwise the thermostat will be in "security" preset,
> 3. A service is available that allows you to set the 3 security parameters. This can be used to adapt the security function to your use.
> 4. For natural usage, the ``security_default_on_percent`` should be less than ``security_min_on_percent``,
> 5. When a ``thermostat_over_climate`` type thermostat goes into ``security`` mode it is turned off. The ``security_min_on_percent`` and ``security_default_on_percent`` parameters are then not used.
> 5. Thermostat of type ``thermostat_over_climate`` are not concerned by the security feature.
## Parameters synthesis
@@ -433,9 +438,9 @@ See [example tuning](#examples-tuning) for common tuning examples
| ``comfort_ac_away_temp`` | Temperature in Comfort preset when no presence in AC mode | X | X | X |
| ``boost_ac_away_temp`` | Temperature in Boost preset when no presence in AC mode | X | X | X |
| ``minimal_activation_delay`` | Minimal activation delay | X | - | X |
| ``security_delay_min`` | Security delay (in minutes) | X | X | X |
| ``security_min_on_percent`` | Minimal power percent to enable security mode | X | X | X |
| ``security_default_on_percent`` | Power percent to use in security mode | X | X | X |
| ``security_delay_min`` | Security delay (in minutes) | X | - | X |
| ``security_min_on_percent`` | Minimal power percent to enable security mode | X | - | X |
| ``security_default_on_percent`` | Power percent to use in security mode | X | - | X |
| ``auto_regulation_mode`` | Le mode d'auto-régulation | - | X | - |
| ``auto_regulation_dtemp`` | La seuil d'auto-régulation | - | X | - |
| ``auto_regulation_period_min`` | La période minimale d'auto-régulation | - | X | - |
@@ -714,6 +719,11 @@ Enjoy !
# Even better
## Much better with the Veersatile Thermostat UI Card
A special card for the Versatile Thermostat has been developed (based on the Better Thermostat). It is available here [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card) and offers a modern vision of all the VTherm statuses:
![image](https://github.com/jmcollin78/versatile-thermostat-ui-card/blob/master/assets/1.png?raw=true)
## Even Better with Scheduler Component !
In order to enjoy the full power of Versatile Thermostat, I invite you to use it with https://github.com/nielsfaber/scheduler-component
@@ -338,7 +338,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
self._presence_on = self._presence_sensor_entity_id is not None
if self._ac_mode:
self._hvac_list = [HVACMode.COOL, HVACMode.OFF]
self._hvac_list = [HVACMode.HEAT, HVACMode.COOL, HVACMode.OFF]
else:
self._hvac_list = [HVACMode.HEAT, HVACMode.OFF]
@@ -621,7 +621,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
STATE_UNAVAILABLE,
STATE_UNKNOWN,
):
self._window_state = window_state.state
self._window_state = (window_state.state == STATE_ON)
_LOGGER.debug(
"%s - Window state have been retrieved: %s",
self,
@@ -934,8 +934,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
return None
return float(
self.nb_underlying_entities
* self._device_power
self._device_power
* self._prop_algorithm.on_percent
)
@@ -955,12 +954,12 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
return self._overpowering_state
@property
def window_state(self) -> bool | None:
def window_state(self) -> str | None:
"""Get the window_state"""
return self._window_state
return STATE_ON if self._window_state else STATE_OFF
@property
def window_auto_state(self) -> bool | None:
def window_auto_state(self) -> str | None:
"""Get the window_auto_state"""
return STATE_ON if self._window_auto_state else STATE_OFF
@@ -1308,33 +1307,33 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
_LOGGER.debug(
"Window delay condition is not satisfied. Ignore window event"
)
self._window_state = old_state.state
self._window_state = (old_state.state == STATE_ON)
return
_LOGGER.debug("%s - Window delay condition is satisfied", self)
# if not self._saved_hvac_mode:
# self._saved_hvac_mode = self._hvac_mode
if self._window_state == new_state.state:
if self._window_state == (new_state.state == STATE_ON):
_LOGGER.debug("%s - no change in window state. Forget the event")
return
self._window_state = new_state.state
self._window_state = (new_state.state == STATE_ON)
#PR - Adding Window ByPass
_LOGGER.debug("%s - Window ByPass is : %s", self, self._window_bypass_state)
if self._window_bypass_state:
_LOGGER.info("%s - Window ByPass is activated. Ignore window event", self)
else:
if self._window_state == STATE_OFF:
if not self._window_state:
_LOGGER.info(
"%s - Window is closed. Restoring hvac_mode '%s'",
self,
self._saved_hvac_mode,
)
await self.restore_hvac_mode(True)
elif self._window_state == STATE_ON:
elif self._window_state:
_LOGGER.info(
"%s - Window is open. Set hvac_mode to '%s'", self, HVACMode.OFF
)
@@ -1828,7 +1827,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
self._device_power,
)
ret = self._current_power + self._device_power >= self._current_power_max
ret = (self._current_power + self._device_power) >= self._current_power_max
if not self._overpowering_state and ret and self._hvac_mode != HVACMode.OFF:
_LOGGER.warning(
"%s - overpowering is detected. Heater preset will be set to 'power'",
@@ -2125,11 +2124,11 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
"saved_preset_mode": self._saved_preset_mode,
"saved_target_temp": self._saved_target_temp,
"saved_hvac_mode": self._saved_hvac_mode,
"window_state": self._window_state,
"window_state": self.window_state,
"motion_state": self._motion_state,
"overpowering_state": self._overpowering_state,
"overpowering_state": self.overpowering_state,
"presence_state": self._presence_state,
"window_auto_state": self._window_auto_state,
"window_auto_state": self.window_auto_state,
#PR - Adding Window ByPass
"window_bypass_state": self._window_bypass_state,
"security_delay_min": self._security_delay_min,
@@ -2259,11 +2258,11 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
"""
_LOGGER.info("%s - Calling service_set_window_bypass, window_bypass: %s", self, window_bypass)
self._window_bypass_state = window_bypass
if not self._window_bypass_state and self._window_state == STATE_ON:
if not self._window_bypass_state and self._window_state:
_LOGGER.info("%s - Last window state was open & ByPass is now off. Set hvac_mode to '%s'", self, HVACMode.OFF)
self.save_hvac_mode()
await self.async_set_hvac_mode(HVACMode.OFF)
if self._window_bypass_state and self._window_state == STATE_ON:
if self._window_bypass_state and self._window_state:
_LOGGER.info("%s - Last window state was open & ByPass is now on. Set hvac_mode to last available mode", self)
await self.restore_hvac_mode(True)
self.update_custom_attributes()
@@ -111,7 +111,7 @@ async def async_setup_entry(
platform.async_register_entity_service(
SERVICE_SET_AUTO_REGULATION_MODE,
{
vol.Required("auto_regulation_mode"): vol.In(["None", "Light", "Medium", "Strong"]),
vol.Required("auto_regulation_mode"): vol.In(["None", "Light", "Medium", "Strong", "Slow"]),
},
"service_set_auto_regulation_mode",
)
@@ -85,6 +85,7 @@ CONF_VALVE_3 = "valve_entity3_id"
CONF_VALVE_4 = "valve_entity4_id"
CONF_AUTO_REGULATION_MODE= "auto_regulation_mode"
CONF_AUTO_REGULATION_NONE= "auto_regulation_none"
CONF_AUTO_REGULATION_SLOW= "auto_regulation_slow"
CONF_AUTO_REGULATION_LIGHT= "auto_regulation_light"
CONF_AUTO_REGULATION_MEDIUM= "auto_regulation_medium"
CONF_AUTO_REGULATION_STRONG= "auto_regulation_strong"
@@ -207,7 +208,7 @@ CONF_FUNCTIONS = [
PROPORTIONAL_FUNCTION_TPI,
]
CONF_AUTO_REGULATION_MODES = [CONF_AUTO_REGULATION_NONE, CONF_AUTO_REGULATION_LIGHT, CONF_AUTO_REGULATION_MEDIUM, CONF_AUTO_REGULATION_STRONG]
CONF_AUTO_REGULATION_MODES = [CONF_AUTO_REGULATION_NONE, CONF_AUTO_REGULATION_LIGHT, CONF_AUTO_REGULATION_MEDIUM, CONF_AUTO_REGULATION_STRONG, CONF_AUTO_REGULATION_SLOW]
CONF_THERMOSTAT_TYPES = [CONF_THERMOSTAT_SWITCH, CONF_THERMOSTAT_CLIMATE, CONF_THERMOSTAT_VALVE]
@@ -225,6 +226,16 @@ DEFAULT_SECURITY_DEFAULT_ON_PERCENT = 0.1
ATTR_TOTAL_ENERGY = "total_energy"
ATTR_MEAN_POWER_CYCLE = "mean_cycle_power"
# A special regulation parameter suggested by @Maia here: https://github.com/jmcollin78/versatile_thermostat/discussions/154
class RegulationParamSlow:
""" Light parameters for slow latency regulation"""
kp:float = 0.2 # 20% of the current internal regulation offset are caused by the current difference of target temperature and room temperature
ki:float = 0.8 / 288.0 # 80% of the current internal regulation offset are caused by the average offset of the past 24 hours
k_ext:float = 1.0 / 25.0 # this will add 1°C to the offset when it's 25°C colder outdoor than indoor
offset_max:float = 2.0 # limit to a final offset of -2°C to +2°C
stabilization_threshold:float = 0.0 # this needs to be disabled as otherwise the long term accumulated error will always be reset when the temp briefly crosses from/to below/above the target
accumulated_error_threshold:float = 2.0 * 288 # this allows up to 2°C long term offset in both directions
class RegulationParamLight:
""" Light parameters for regulation"""
kp:float = 0.2
@@ -14,6 +14,6 @@
"quality_scale": "silver",
"requirements": [],
"ssdp": [],
"version": "3.8.0",
"version": "4.0.0",
"zeroconf": []
}
@@ -55,7 +55,8 @@ class PITemperatureRegulator:
offset = self.kp * error + self.ki * self.accumulated_error
# Calculate the exterior offset
offset_ext = self.k_ext * (self.target_temp - external_temp)
# For Maia tests - use the internal_temp vs external_temp and not target_temp - external_temp
offset_ext = self.k_ext * (internal_temp - external_temp)
# Capping of offset_ext
total_offset = offset + offset_ext
@@ -159,3 +159,4 @@ set_auto_regulation_mode:
- "Light"
- "Medium"
- "Strong"
- "Slow"
@@ -20,11 +20,13 @@ from .const import (
CONF_CLIMATE_4,
CONF_AUTO_REGULATION_MODE,
CONF_AUTO_REGULATION_NONE,
CONF_AUTO_REGULATION_SLOW,
CONF_AUTO_REGULATION_LIGHT,
CONF_AUTO_REGULATION_MEDIUM,
CONF_AUTO_REGULATION_STRONG,
CONF_AUTO_REGULATION_DTEMP,
CONF_AUTO_REGULATION_PERIOD_MIN,
RegulationParamSlow,
RegulationParamLight,
RegulationParamMedium,
RegulationParamStrong
@@ -176,6 +178,15 @@ class ThermostatOverClimate(BaseThermostat):
RegulationParamStrong.offset_max,
RegulationParamStrong.stabilization_threshold,
RegulationParamStrong.accumulated_error_threshold)
elif self._auto_regulation_mode == CONF_AUTO_REGULATION_SLOW:
self._regulation_algo = PITemperatureRegulator(
self.target_temperature,
RegulationParamSlow.kp,
RegulationParamSlow.ki,
RegulationParamSlow.k_ext,
RegulationParamSlow.offset_max,
RegulationParamSlow.stabilization_threshold,
RegulationParamSlow.accumulated_error_threshold)
else:
# A default empty algo (which does nothing)
self._regulation_algo = PITemperatureRegulator(
@@ -666,6 +677,8 @@ class ThermostatOverClimate(BaseThermostat):
self.choose_auto_regulation_mode(CONF_AUTO_REGULATION_MEDIUM)
elif auto_regulation_mode == "Strong":
self.choose_auto_regulation_mode(CONF_AUTO_REGULATION_STRONG)
elif auto_regulation_mode == "Slow":
self.choose_auto_regulation_mode(CONF_AUTO_REGULATION_SLOW)
await self._send_regulated_temperature()
self.update_custom_attributes()
@@ -227,7 +227,7 @@ class UnderlyingSwitch(UnderlyingEntity):
def is_device_active(self):
"""If the toggleable device is currently active."""
real_state = self._hass.states.is_state(self._entity_id, STATE_ON)
return self.is_inversed and not real_state
return (self.is_inversed and not real_state) or (not self.is_inversed and real_state)
# @overrides this breaks some unit tests TypeError: object MagicMock can't be used in 'await' expression
async def turn_off(self):
+1 -1
View File
@@ -3,5 +3,5 @@
"content_in_root": false,
"render_readme": true,
"hide_default_branch": false,
"homeassistant": "2023.10.3"
"homeassistant": "2023.11.0"
}
+4 -4
View File
@@ -110,7 +110,7 @@ async def test_over_climate_regulation(hass: HomeAssistant, skip_hass_states_is_
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp
):
await send_temperature_change_event(entity, 22, event_timestamp)
await send_temperature_change_event(entity, 23, event_timestamp)
await send_ext_temperature_change_event(entity, 19, event_timestamp)
# the regulated temperature should be under
@@ -212,14 +212,14 @@ async def test_over_climate_regulation_ac_mode(hass: HomeAssistant, skip_hass_st
# the regulated temperature should be under
assert entity.regulated_target_temp < entity.target_temperature
assert entity.regulated_target_temp == 25-2.5 # +2.3 without round_to_nearest
assert entity.regulated_target_temp == 25-2 # +2.3 without round_to_nearest
# change temperature so that the regulated temperature should slow down
event_timestamp = now - timedelta(minutes=3)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp
):
await send_temperature_change_event(entity, 20, event_timestamp)
await send_temperature_change_event(entity, 18, event_timestamp)
await send_ext_temperature_change_event(entity, 25, event_timestamp)
# the regulated temperature should be greater
@@ -331,4 +331,4 @@ async def test_over_climate_regulation_limitations(hass: HomeAssistant, skip_has
# the regulated should have been done
assert entity.regulated_target_temp != old_regulated_temp
assert entity.regulated_target_temp > entity.target_temperature
assert entity.regulated_target_temp == 17 + 1 # 0.7 without round_to_nearest
assert entity.regulated_target_temp == 17 + 1.5 # 0.7 without round_to_nearest
+1 -1
View File
@@ -241,7 +241,7 @@ async def test_window_binary_sensors(
await entity.async_set_preset_mode(PRESET_COMFORT)
await entity.async_set_hvac_mode(HVACMode.HEAT)
await send_temperature_change_event(entity, 15, now)
assert entity.window_state is None
assert entity.window_state is STATE_OFF
await window_binary_sensor.async_my_climate_changed()
assert window_binary_sensor.state is STATE_OFF
+1 -1
View File
@@ -243,7 +243,7 @@ async def test_bug_66(
assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Open the window and let the thermostat shut down
with patch(
+5 -5
View File
@@ -69,7 +69,7 @@ async def test_one_switch_cycle(
assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 15, event_timestamp)
@@ -282,7 +282,7 @@ async def test_multiple_switchs(
assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 15, event_timestamp)
@@ -418,7 +418,7 @@ async def test_multiple_climates(
assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 15, event_timestamp)
@@ -443,7 +443,7 @@ async def test_multiple_climates(
assert entity.hvac_mode is HVACMode.OFF
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 15, event_timestamp)
@@ -518,7 +518,7 @@ async def test_multiple_climates_underlying_changes(
assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_BOOST
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 15, event_timestamp)
+34 -34
View File
@@ -26,15 +26,15 @@ def test_pi_algorithm_basics():
# to reset the accumulated error
the_algo.reset_accumulated_error()
assert the_algo.calculate_regulated_temperature(18, 10) == 21.5 # +1.5
assert the_algo.calculate_regulated_temperature(18.1, 10) == 21.6 # +1.6
assert the_algo.calculate_regulated_temperature(18.3, 10) == 21.6 # +1.6
assert the_algo.calculate_regulated_temperature(18.5, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(18.7, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(19, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(18, 10) == 21.3 # +1.5
assert the_algo.calculate_regulated_temperature(18.1, 10) == 21.4 # +1.6
assert the_algo.calculate_regulated_temperature(18.3, 10) == 21.4 # +1.6
assert the_algo.calculate_regulated_temperature(18.5, 10) == 21.5 # +1.7
assert the_algo.calculate_regulated_temperature(18.7, 10) == 21.6 # +1.7
assert the_algo.calculate_regulated_temperature(19, 10) == 21.6 # +1.7
assert the_algo.calculate_regulated_temperature(20, 10) == 21.5 # +1.5
assert the_algo.calculate_regulated_temperature(21, 10) == 20.8 # +0.8
assert the_algo.calculate_regulated_temperature(21, 10) == 20.7 # +0.7
assert the_algo.calculate_regulated_temperature(21, 10) == 20.9 # +0.8
assert the_algo.calculate_regulated_temperature(21, 10) == 20.8 # +0.7
assert the_algo.calculate_regulated_temperature(20, 10) == 20.9 # +0.7
# Test temperature external
@@ -54,15 +54,15 @@ def test_pi_algorithm_light():
# to reset the accumulated erro
the_algo.set_target_temp(20)
assert the_algo.calculate_regulated_temperature(18, 10) == 21.5 # +1.5
assert the_algo.calculate_regulated_temperature(18.1, 10) == 21.6 # +1.6
assert the_algo.calculate_regulated_temperature(18.3, 10) == 21.6 # +1.6
assert the_algo.calculate_regulated_temperature(18.5, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(18.7, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(19, 10) == 21.7 # +1.7
assert the_algo.calculate_regulated_temperature(18, 10) == 21.3 # +1.5
assert the_algo.calculate_regulated_temperature(18.1, 10) == 21.4 # +1.6
assert the_algo.calculate_regulated_temperature(18.3, 10) == 21.4 # +1.6
assert the_algo.calculate_regulated_temperature(18.5, 10) == 21.5 # +1.7
assert the_algo.calculate_regulated_temperature(18.7, 10) == 21.6 # +1.7
assert the_algo.calculate_regulated_temperature(19, 10) == 21.6 # +1.7
assert the_algo.calculate_regulated_temperature(20, 10) == 21.5 # +1.5
assert the_algo.calculate_regulated_temperature(21, 10) == 20.8 # +0.8
assert the_algo.calculate_regulated_temperature(21, 10) == 20.7 # +0.7
assert the_algo.calculate_regulated_temperature(21, 10) == 20.9 # +0.8
assert the_algo.calculate_regulated_temperature(21, 10) == 20.8 # +0.7
assert the_algo.calculate_regulated_temperature(20, 10) == 20.9 # +0.7
# Test temperature external
@@ -81,15 +81,15 @@ def test_pi_algorithm_medium():
# to reset the accumulated erro
the_algo.set_target_temp(20)
assert the_algo.calculate_regulated_temperature(18, 10) == 22.2
assert the_algo.calculate_regulated_temperature(18.1, 10) == 22.3
assert the_algo.calculate_regulated_temperature(18.3, 10) == 22.4
assert the_algo.calculate_regulated_temperature(18.5, 10) == 22.5
assert the_algo.calculate_regulated_temperature(18.7, 10) == 22.5
assert the_algo.calculate_regulated_temperature(19, 10) == 22.4
assert the_algo.calculate_regulated_temperature(18, 10) == 22.0
assert the_algo.calculate_regulated_temperature(18.1, 10) == 22.1
assert the_algo.calculate_regulated_temperature(18.3, 10) == 22.2
assert the_algo.calculate_regulated_temperature(18.5, 10) == 22.3
assert the_algo.calculate_regulated_temperature(18.7, 10) == 22.4
assert the_algo.calculate_regulated_temperature(19, 10) == 22.3
assert the_algo.calculate_regulated_temperature(20, 10) == 21.9
assert the_algo.calculate_regulated_temperature(21, 10) == 20.5
assert the_algo.calculate_regulated_temperature(21, 10) == 20.4
assert the_algo.calculate_regulated_temperature(21, 10) == 20.3
assert the_algo.calculate_regulated_temperature(20, 10) == 20.8
# Test temperature external
@@ -107,6 +107,7 @@ def test_pi_algorithm_medium():
the_algo.set_target_temp(20)
the_algo.reset_accumulated_error()
# Test the error acculation effect
assert the_algo.calculate_regulated_temperature(19, 5) == 22.0
assert the_algo.calculate_regulated_temperature(19, 5) == 22.1
assert the_algo.calculate_regulated_temperature(19, 5) == 22.2
assert the_algo.calculate_regulated_temperature(19, 5) == 22.3
@@ -119,7 +120,6 @@ def test_pi_algorithm_medium():
assert the_algo.calculate_regulated_temperature(19, 5) == 23
assert the_algo.calculate_regulated_temperature(19, 5) == 23
assert the_algo.calculate_regulated_temperature(19, 5) == 23
assert the_algo.calculate_regulated_temperature(19, 5) == 23
def test_pi_algorithm_strong():
""" Test the PI algorithm """
@@ -131,20 +131,20 @@ def test_pi_algorithm_strong():
# to reset the accumulated erro
the_algo.set_target_temp(20)
assert the_algo.calculate_regulated_temperature(18, 10) == 23.6
assert the_algo.calculate_regulated_temperature(18.1, 10) == 23.9
assert the_algo.calculate_regulated_temperature(18.3, 10) == 24.0
assert the_algo.calculate_regulated_temperature(18, 10) == 23.2
assert the_algo.calculate_regulated_temperature(18.1, 10) == 23.5
assert the_algo.calculate_regulated_temperature(18.3, 10) == 23.8
assert the_algo.calculate_regulated_temperature(18.5, 10) == 24
assert the_algo.calculate_regulated_temperature(18.7, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(20, 10) == 23.9
assert the_algo.calculate_regulated_temperature(21, 10) == 21.4
assert the_algo.calculate_regulated_temperature(21, 10) == 21.2
assert the_algo.calculate_regulated_temperature(21, 10) == 21
assert the_algo.calculate_regulated_temperature(21, 10) == 20.8
assert the_algo.calculate_regulated_temperature(21, 10) == 20.6
assert the_algo.calculate_regulated_temperature(21, 10) == 20.4
assert the_algo.calculate_regulated_temperature(21, 10) == 20.2
assert the_algo.calculate_regulated_temperature(21, 10) == 20
# Test temperature external
assert the_algo.calculate_regulated_temperature(20, 8) == 21.0
@@ -161,14 +161,14 @@ def test_pi_algorithm_strong():
the_algo.set_target_temp(20)
the_algo.reset_accumulated_error()
# Test the error acculation effect
assert the_algo.calculate_regulated_temperature(19, 10) == 22.6
assert the_algo.calculate_regulated_temperature(19, 10) == 22.8
assert the_algo.calculate_regulated_temperature(19, 10) == 23
assert the_algo.calculate_regulated_temperature(19, 10) == 23.0
assert the_algo.calculate_regulated_temperature(19, 10) == 23.2
assert the_algo.calculate_regulated_temperature(19, 10) == 23.4
assert the_algo.calculate_regulated_temperature(19, 10) == 23.6
assert the_algo.calculate_regulated_temperature(19, 10) == 23.8
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24
assert the_algo.calculate_regulated_temperature(19, 10) == 24.0
assert the_algo.calculate_regulated_temperature(19, 10) == 24.0
assert the_algo.calculate_regulated_temperature(19, 10) == 24.0
assert the_algo.calculate_regulated_temperature(19, 10) == 24.0
+3 -1
View File
@@ -256,6 +256,7 @@ async def test_power_management_energy_over_switch(
CONF_USE_POWER_FEATURE: True,
CONF_USE_PRESENCE_FEATURE: False,
CONF_HEATER: "switch.mock_switch",
CONF_HEATER_2: "switch.mock_switch2",
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_TPI_COEF_INT: 0.3,
CONF_TPI_COEF_EXT: 0.01,
@@ -278,6 +279,7 @@ async def test_power_management_energy_over_switch(
assert tpi_algo
assert entity.total_energy == 0
assert entity.nb_underlying_entities == 2
# set temperature to 15 so that on_percent will be set
with patch(
@@ -297,7 +299,7 @@ async def test_power_management_energy_over_switch(
assert entity.current_temperature == 15
assert tpi_algo.on_percent == 1
assert entity.mean_cycle_power == 100.0
assert entity.device_power == 100.0
assert mock_send_event.call_count == 2
assert mock_heater_on.call_count == 1
+13 -1
View File
@@ -56,7 +56,7 @@ async def test_over_switch_ac_full_start(hass: HomeAssistant, skip_hass_states_i
assert entity.ac_mode is True
assert entity.hvac_action is HVACAction.OFF
assert entity.hvac_mode is HVACMode.OFF
assert entity.hvac_modes == [HVACMode.COOL, HVACMode.OFF]
assert entity.hvac_modes == [HVACMode.HEAT, HVACMode.COOL, HVACMode.OFF]
assert entity.target_temperature == entity.max_temp
assert entity.preset_modes == [
PRESET_NONE,
@@ -138,3 +138,15 @@ async def test_over_switch_ac_full_start(hass: HomeAssistant, skip_hass_states_i
assert entity.hvac_mode is HVACMode.COOL
assert (entity.hvac_action is HVACAction.OFF or entity.hvac_action is HVACAction.IDLE)
assert entity.target_temperature == 27 # eco_ac_away
await entity.async_set_hvac_mode(HVACMode.HEAT)
assert entity.hvac_mode is HVACMode.HEAT
await entity.async_set_preset_mode(PRESET_COMFORT)
assert entity.preset_mode is PRESET_COMFORT
assert entity.target_temperature == 26
# switch to Eco
await entity.async_set_preset_mode(PRESET_ECO)
assert entity.preset_mode is PRESET_ECO
assert entity.target_temperature == 27
+8 -8
View File
@@ -64,7 +64,7 @@ async def test_window_management_time_not_enough(
assert entity.overpowering_state is None
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Open the window, but condition of time is not satisfied and check the thermostat don't turns off
with patch(
@@ -152,7 +152,7 @@ async def test_window_management_time_enough(
assert entity.overpowering_state is None
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# change temperature to force turning on the heater
with patch(
@@ -294,7 +294,7 @@ async def test_window_auto_fast(hass: HomeAssistant, skip_hass_states_is_state):
assert entity.overpowering_state is None
assert entity.target_temperature == 21
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Make the temperature down
with patch(
@@ -478,7 +478,7 @@ async def test_window_auto_auto_stop(hass: HomeAssistant, skip_hass_states_is_st
assert entity.overpowering_state is None
assert entity.target_temperature == 21
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Make the temperature down
with patch(
@@ -623,7 +623,7 @@ async def test_window_auto_no_on_percent(
assert entity.overpowering_state is None
assert entity.target_temperature == 21
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Make the temperature down
with patch(
@@ -728,7 +728,7 @@ async def test_window_bypass(
assert entity.overpowering_state is None
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# change temperature to force turning on the heater
with patch(
@@ -866,7 +866,7 @@ async def test_window_auto_bypass(hass: HomeAssistant, skip_hass_states_is_state
assert entity.overpowering_state is None
assert entity.target_temperature == 21
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# Make the temperature down
with patch(
@@ -973,7 +973,7 @@ async def test_window_bypass_reactivate(hass: HomeAssistant, skip_hass_states_is
assert entity.overpowering_state is None
assert entity.target_temperature == 19
assert entity.window_state is None
assert entity.window_state is STATE_OFF
# change temperature to force turning on the heater
with patch(