litinoveweedle / hass-template-climate

❄️Templatable Climate Device for Home Assistant, Supports Running Actions On Service Calls.
MIT License
23 stars 1 forks source link

Last update broken all my thermostat #12

Closed devildant closed 3 months ago

devildant commented 4 months ago

The problem

hello,

with the last update when i change the mode, fan speed, swing nothing work. the automation are not call

- platform: climate_template
  name: Climatisation Salon Climate Template
  unique_id: climatisation_salon_climate_template
  # unique id not working but mendatory for working
  icon_template: mdi:air-conditioner
  mode_action: "parallel"
  max_action: 10
  hvac_modes:
    - "dry"
    - "off"
    - "cool"
    - "fan_only"
  fan_modes:
    - "Auto"
    - "20%"
    - "40%"
    - "60%"
    - "80%"
    - "100%"
    - "Silencieux"
    - "Turbo"
  swing_modes:
    - "Position 1"
    - "Position 2"
    - "Position 3"
    - "Position 4"
    - "Position 5"
    - "Activé"
    - "Désactivé"
  min_temp: 16
  max_temp: 31
  availability_template: "{{ states('switch.localtuya_integration_climatisation_salon_power') in ['on', 'off'] }}"
  current_temperature_template: "{{ states('sensor.localtuya_integration_climatisation_salon_temperature_courante') }}"
  set_hvac_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_hvac_mode
  set_fan_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_fan_mode
  set_swing_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_swing_mode
  set_temperature:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_temperature

What version of Template Climate has the issue?

0.7.0

What version of Home Assistant are you running?

12.2

What type of installation are you running?

Home Assistant OS

Example YAML snippet

No response

Anything in the logs that might be useful for us?

No response

Additional information

No response

devildant commented 4 months ago

if i rollback to 0.6.4 it's work perfectly

devildant commented 4 months ago

well the automation is well executed but all my conditions are false, I don't understand what changed between the two versions of the plugin

devildant commented 4 months ago

after debugging

here is my logic

tuya cloud => change detected => boolean set to true and calls my climate template to change the value

my climate template => if boolean activated do nothing, otherwise call tuya cloud to change the value

In 0.6.4 1) action on my climate template

2) climate template call tuya cloud

3) tuya cloud sets the boolean to true and calls climate template

4) my climate template receives the command and ignores the command because the boolean is activated and sets it to false

In 0.7.0: 1) action on my climate template

2) climate template call tuya cloud

3) tuya cloud sets the boolean to true and calls climate template

4) my climate template does not receive the command and the boolean remains true

5) new action on my climate template

6) nothing happens because the command was ignored because the boolean is true

To make it operational again, I removed the boolean protection and compared the data between my climate model with tuya cloud to determine whether or not I should perform the action.

it works.

I just hope it doesn't change again :p

litinoveweedle commented 4 months ago

Hi, I am sorry to hear this. Would you please be able to switch debug mode:

logger:
  default: warning
  logs:
    custom_components.climate_template.climate: debug

and try to execute action which is causing issue? I added a lot of debug messages, but there is also changed logic to prevent looping from template to action - see #9 .

This means, it the attributes is not changed (i.e. temperature) from the internal entity held state, than action is not executed. You will see this from the debug logs.

If I understand correctly, you use thermostat card in HA GUI to set some devices using automation. So there are no templates to feed back the status of given attribute to entity. It that case, if internal attribute of the entity is already at some value change it to the same value will not re-trigger corresponding action. I can probably improve on the logic in #9 and use it only if the template for attribute is also configured.

Would you be able to test it (manually replace climate.py) on you HA?

litinoveweedle commented 4 months ago

You can try the proposed fix easily by replacing line number 1067 in your climate.py

if getattr(self, "_attr_" + attr) == attributes[attr]["value"]:

by (EDITED! please use this version)

if getattr(self, "_template_" + attr) and getattr(self, "_attr_" + attr) == attributes[attr]["value"]:

Then enable debug, restart HA an test it.

devildant commented 4 months ago

Ha sorry if I wasn't clear in my last message. I solved my problem by changing my logic (deleting the booleans and adding a some checks in my automations, to check that the thermostat does not already have the requested modification.

I just hope you don't change the logic again :)

I left the issue open to notify you of the problem I encountered. in case another user encounters a similar problem

litinoveweedle commented 4 months ago

Hello,

thank you for reply, I am glad that you solve the issue.

I solved my problem by changing my logic (deleting the booleans and adding a some checks in my automations, to check that the thermostat does not already have the requested modification.

Just to be clear, the original aim of the logic changes was to fix 'Already running' error (being triggered by both template and action referring to same entity and causing loop). But I wanted also to improve climate_template to run without further external logic (for example using automations to check and set state of the climate_template entity), while keeping as much backward compatibility as possible.

To be able to achieve this I need you help. It is important to me to understand how other people using the climate_template. Without such understanding I can't prevent breaking the logic. While I can not promise to make breaking changes in the future, those shall be for integration improvements and not by accident.

I unfortunately still to not completely understand your setup, can you please describe it so I would get it? :-) In the original description I was especially confused by the 'boolean' logic. Can you can please try to describe how you interconnect your Tuya thermostat to the climate_template. Do you use any automation to check and set climate_template using services? Maybe to include full configuration setup?

While I am asking is also to improve documentation to include tested usage. I really think, that your intended usage is similar to mine, but you use different implementation. In my case, I have a gas boiler, which is controlled by Home assistant inputs (like number to set the desired target_temperature and select or switch to select operation mode - heat, off etc.). If I will set temperature or working mode on the physical boiler thermostat on my wall, those inputs in HA will after some time also change, to reflect the current boiler settings. To use this together with the climate_template it is not required to have any additional automation logic: If I will change target_temperature or hvac_mode in the HA, boiler is set using changed input value. If boiler is set directly using hardware thermostat, it reports changes via updates of the input back to HA and climate_entity is updated to reflect those new values using templates. If you Tuya thermostat provides sensors to reflect its current state, those can be use as a inputs directly in the climate_template templates as well (instead of inputs as in my case).

My example:

  - platform: climate_template
    name: "Heating DHW"
    unique_id: "climate_template_heating_dhw"
    mode_action: "queued"
    max_action: 3
    hvac_modes:
      - "heat"
      - "off"
    min_temp: 10
    max_temp: 60
    temp_step: 1
    availability_template: "{{ states('sensor.thrs19_dhw_status') not in [ 'unavailable', 'unknown', 'none' ] and states('switch.thrs19_dhw_operating_mode') not in [ 'unavailable', 'unknown', 'none' ] and states('number.thrs19_dhw_temperature_nominal_setpoint') not in [ 'unavailable', 'unknown', 'none' ] and states('number.thrs19_dhw_temperature_nominal_setpoint') not in [ 'unavailable', 'unknown', 'none' ] }}"
    current_temperature_template: "{{ states('sensor.thrs19_dhw_temperature_actual_value_top_b3') }}"
    hvac_mode_template: "{% if states('switch.thrs19_dhw_operating_mode') == 'on' %}heat{% else %}off{% endif %}"
    target_temperature_template: "{{ states('number.thrs19_dhw_temperature_nominal_setpoint') }}"
    hvac_action_template: "{% if states('switch.thrs19_dhw_operating_mode') != 'on' %}off{% elif states('sensor.thrs19_dhw_status') in [ 'Push, nominal setpoint', 'Charging, nominal setpoint' ] %}heating{% else %}idle{% endif %}"
    set_temperature:
      - service: number.set_value
        target:
          entity_id: number.thrs19_dhw_temperature_nominal_setpoint
        data:  
          value: "{{ temperature }}"
      - delay:
          milliseconds: 500
      - service: homeassistant.update_entity
        target:
          entity_id: number.thrs19_dhw_temperature_nominal_setpoint
      - delay:
          milliseconds: 500
      - condition: template
        value_template: "{{ hvac_mode is defined and (( hvac_mode == 'heat' and states('switch.thrs19_dhw_operating_mode') != 'on' ) or ( hvac_mode == 'off' and states('switch.thrs19_dhw_operating_mode') != 'off' )) }}"
      - service: switch.toggle
        target:
          entity_id: switch.thrs19_dhw_operating_mode
      - delay:
          milliseconds: 500
      - service: homeassistant.update_entity
        target:
          entity_id: switch.thrs19_dhw_operating_mode
      - delay:
          milliseconds: 500
    set_hvac_mode:
      - condition: template
        value_template: "{{ hvac_mode is defined and (( hvac_mode == 'heat' and states('switch.thrs19_dhw_operating_mode') != 'on' ) or ( hvac_mode == 'off' and states('switch.thrs19_dhw_operating_mode') != 'off' )) }}"
      - service: switch.toggle
        target:
          entity_id: switch.thrs19_dhw_operating_mode
      - delay:
          milliseconds: 500
      - service: homeassistant.update_entity
        target:
          entity_id: switch.thrs19_dhw_operating_mode
      - delay:
          milliseconds: 500 
devildant commented 4 months ago

hello,

I can try to explain my use to you :) I use climate template to create virtual thermostats in HA. I have 2 use cases: 1) for heating, I use climate template to be able to control two thermostats, my heating is connected with tado, so I have two possible thermostats, either via the cloud or via homekit, except it may happen that one or the 'other is unavailable, in this case I can switch with a simple boolean which thermostat my climate template is on.

For this climate template, I bypassed the action part and I control everything via automations which monitors the climate template (I do this because for development or debugging, I can modify without having to restart HA)

example :

- platform: climate_template
  name: chauffage_salon_scheduler
  unique_id: chauffage_salon_scheduler
  icon_template: mdi:home-clock
  temp_step: 0.1
  hvac_modes:
    - "off"
    - "heat"
  min_temp: 5
  max_temp: 25
  current_temperature_template: "{% if states('switch.personnal_chauffage_salon_cloud_switch') == 'on' %} {{ state_attr('climate.chauffage_salon_cloud', 'current_temperature') | float }} {% else %} {{ states('sensor.chauffage_salon_homekit_current_temperature_wrapper') | float }} {% endif %}"
  current_humidity_template: "{% if states('switch.personnal_chauffage_salon_cloud_switch') == 'on' %} {{ state_attr('climate.chauffage_salon_cloud', 'current_humidity') | float }} {% else %} {{ states('sensor.chauffage_salon_homekit_current_humidity_wrapper')  | float }} {% endif %}"
  set_hvac_mode:
    - delay: '00:00:00.001'
  set_temperature:
    - delay: '00:00:00.001'

Note: this climate model was not affected by the last update

Note 2: the binding is unidirectional, that is to say, the climate template is master and ignores changes coming from the cloud or homekit

2) For air conditioning, I unfortunately have no choice but I have to go through Tuya if I want to have all the functionality, however I do not use the Tuya cloud (because it cannot create a climate entity correct), but I use local tuya, to do this I mapped each action of my air conditioner with select and boolean, and I use climate template to create a thermostat in HA. to do this I mapped each action (set temperature, swing, fan speed...) via automations (also to be able to intervene without having to restart HA)

however I also have a very limited backup solution to control my air conditioner, for this I use tado air conditioning v3, which is basically a connected infrared remote control, but the problem with this is that if I modify my air conditioner with the remote control supplied with it, I cannot retrieve the status of my air conditioner in HA.

For this I have a double binding, my climate template can send commands to local tuya, but my local tuya also sends commands to my climate template.

I am therefore obliged to manage the collisions.

this is why initially, I had created boulean which changes to true when the command comes from tuya local, in order to prevent the thermostat from sending the command to tuya local.... exemple:

- platform: climate_template
  name: Climatisation Salon Climate Template
  unique_id: climatisation_salon_climate_template
  # unique id not working but mendatory for working
  icon_template: mdi:air-conditioner
#   mode_action: "parallel"
#   max_action: 10
  hvac_modes:
    - "dry"
    - "off"
    - "cool"
    - "fan_only"
  fan_modes:
    - "Auto"
    - "20%"
    - "40%"
    - "60%"
    - "80%"
    - "100%"
    - "Silencieux"
    - "Turbo"
  swing_modes:
    - "Position 1"
    - "Position 2"
    - "Position 3"
    - "Position 4"
    - "Position 5"
    - "Activé"
    - "Désactivé"
  min_temp: 16
  max_temp: 31
  availability_template: "{{ states('switch.localtuya_integration_climatisation_salon_power') in ['on', 'off'] }}"
  current_temperature_template: "{{ states('sensor.localtuya_integration_climatisation_salon_temperature_courante') }}"
  set_hvac_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_hvac_mode
  set_fan_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_fan_mode
  set_swing_mode:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_swing_mode
  set_temperature:
    - service: automation.trigger
      data:
        skip_condition: false
      target:
        entity_id: automation.0009_climate_template_climatisation_salon_set_temperature

It's more clearer ?

litinoveweedle commented 4 months ago

It's more clearer ?

Much more, thank you for very detailed explanation.

I see some future potential issues.

  1. Calling automation from the action script assume, that climate_template has already set its internal state. (as you need to retrieve climate_template entity state or attribute in the automation). The problem is, that climate_template set its state only after triggering action, and call is done asynchronously so it is hard to estimate when climate_entity state is really updated (to be fetched in automation). So if you prefer to have automation over climate_template native action script, it would be better to trigger automation by climate_entity state or attribute state change. This statement was wrong ( I checked code and HA sync call is always done before executing any script/action). But automation trigger would probably not be working for you right now anyway. The problem is, that I didn't thought there is any usage of climate_template to control given attribute if neither template nor action is defined. So if neither template nor action is set in version 0.7.0, than given climate capability is disabled. This causes services like set_hvac_mode, set_temperature, etc. to not being available, but may also cause automation triggers based on the climate_template entity change to not be executed (just assumption, I didn't tested this.) Now I understand that this is probably fully legal usage and I will try not to be smarted than users. I would probably only keep warning message during the start for such configuration.

  2. The other issue is the one I already mentioned. If there is only unidirectional communication, than climate_template only assume state of the controlled device. Therefore if the device state diverges, there is no way to detect it from climate_template. Than there is the question if there should be a way to re-trigger update of the controlled device even if attribute value is already set/same in climate_template entity in HA. Like clicking on thermostat card on the mode "heat" even it is already set to heat mode should fire the action. The only issue is, that this trigger is not executed by HA GUI for state changes (click/set same hvac_mode), while it is executed for attributes changes (set same temperature). As a workaround it is possible to re-trigger same state (hvac_mode), by using service set_hvac_mode from any automation as it would re-trigger the change successfully. But currently is will not re-trigger action, as the internal state of the climate_template is not changing. So to fix this I will implement the change as proposed before. If template for given attribute is not configured, than execute action trigger always.

Please let me know what do you think about such modifications. Thank you.

litinoveweedle commented 4 months ago

I prepared both changes, will you be please able to test them?

devildant commented 4 months ago

As it stands, modifications are not necessary.

in my first case (heating with tado), the climate template carries the information, and that's what I want, I have automation which compares the climate template and the cloud data, if there is a difference then I align the cloud with the values ​​of the climate template.

I don't want to directly link the climate template and my tado thermostat, for a simple reason, I have 3 and if I trigger all 3 simultaneously tado does not follow. so I can defer the propagation of the modification.

for my second use case, actually before your modifications, if we modified via script the status of the climatic entity, the action was recalled, it is also because of this that I had to protect with booleans.

normally with the modification that I made to my scripts, as I compare the status of the climate template before executing the rest of the action I am protected and I can do the double binding.

This allowed me to make the configuration cleaner by deleting my 4 booleans from climate template. I didn't understand the proposed change?

otherwise whatever happens the climate template is modified before execution, and fortunately otherwise it would be hell

devildant commented 4 months ago

you mean that if for example hvac_mode_template is not defined then always execute the action?

if yes in this case make a parameter, so the user will have the choice of behavior.

whatever happens I cannot feed these templates because they do not correspond to my needs, it would only complicate my code, it’s my automations that manages everything.

as I told you I use climate template as a virtual thermostat. in one case (case 1) it is the master thermostat (climate template) which controls the cloud thermostats (slave)

and in the other (case 2) there is a double binding via automations. the reason for this is simple, I receive two separate entities for the on/off and the mode, which forces me to switch the mode and then we have 2 commands, I have not found any other solution.

and last point as I have already mentioned, it is much simpler to intervene and modify using automation, than having to restart HA for each modification :)

devildant commented 4 months ago

don't hesitate to tell me if you don't understand, English is not my native language

litinoveweedle commented 3 months ago

Hi thank you again for all the explanation and help. As discussed the issue was caused by different philosophy over original integration. I will try to keep this logic as long as suitable. ;-) In the new release I also loosened configuration check to allow for less usual use cases like yours.