esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 34 forks source link

Bang Bang Climate action is not updated when Template Switch changes state #1368

Closed muxa closed 4 years ago

muxa commented 4 years ago

Operating environment/Installation: Home Assistant via Docker

ESP8266: Wemos D1 Mini

ESPHome version (latest production, beta, dev branch) 1.14.5

Affected component: Bang Band Climate

Description of problem: I have a Bang Band Climate component which is linked to a Template Switch. When Template Switch changes state it does not update Climate actions.

E.g. When in Auto mode and heating and action is showing Heating, as expected. However then Switch is turned off, the action remains as Heating.

Template Switch controls a momentary power button on a heater, and there's a sensor to detect if the heater is on or off. This allows to still use the heater power button and HASS in parallel.

Problem-relevant YAML-configuration entries:

substitutions:
  room: Kitchen

esphome:
  name: gas_heater
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  manual_ip:
    static_ip: 192.168.30.233
    gateway: 192.168.30.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Gas-Heater"
    password: !secret ap_password

captive_portal:

# Enable logging
logger:
  level: DEBUG
  logs:
    adc: INFO

# Enable Home Assistant API
switch:
  - platform: gpio
    pin: D0
    id: pwr_out
  - platform: template
    name: "Gas Heater"
    id: heater
    icon: "mdi:radiator"
    lambda: |-
      if (id(cb5).state > 0.7) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
    - switch.turn_on: pwr_out
    - delay: 200ms
    - switch.turn_off: pwr_out
    turn_off_action:
    - switch.turn_on: pwr_out
    - delay: 200ms
    - switch.turn_off: pwr_out

sensor:
  - platform: adc
    pin: A0
    id: cb5
    name: "Gas Heater Power Indicator"
    update_interval:
      milliseconds: 100
    internal: true
    filters:
      - multiply: 3.3
      - exponential_moving_average:
          alpha: 0.1
          send_every: 20
  - platform: dht
    pin: D7
    model: DHT11
    temperature:
      id: temperature
      name: "Kitchen Temperature"
    humidity:
      id: humidity
      name: "Kitchen Humidity"
    update_interval: 60s

climate:
  - platform: bang_bang
    id: gas_thermostat
    name: "Gas Heater Thermostat"
    sensor: temperature
    default_target_temperature_low: 22 °C
    default_target_temperature_high: 25 °C
    away_config:
      default_target_temperature_low: 18 °C
      default_target_temperature_high: 20 °C
    visual:
      min_temperature: 15 °C
      max_temperature: 27 °C
      temperature_step: 1 °C

    heat_action:
      - switch.turn_on: heater
    idle_action:
      - switch.turn_off: heater 

Logs (if applicable): This is when the switch is off:

[19:03:44][D][climate:172]: 'Gas Heater Thermostat' - Sending state:
[19:03:44][D][climate:175]:   Mode: AUTO
[19:03:44][D][climate:177]:   Action: HEATING
[19:03:44][D][climate:180]:   Current Temperature: 23.00°C
[19:03:44][D][climate:184]:   Target Temperature: Low: 22.00°C High: 24.00°C
[19:03:44][D][climate:189]:   Away: OFF

Additional information and things you've tried:

Do I need to manually update Action of the climate control when the switch toggles? I could not find documentation how to do that.

OttoWinter commented 4 years ago

Correct you need to manually tell the climate device of the switch update (it doesn't deduce what is triggered from the heat_/idle_action).

You should make the switch internal and use the climate device as the only way to switch the heater on/off. Alternatively you can add a second template switch that itself controls the climate device with climate.control

muxa commented 4 years ago

I managed to get it working by handling heater switch actions and synchronising thermostat state to it:

    on_turn_on:
    - lambda: |-
        if (id(gas_thermostat).action != CLIMATE_ACTION_HEATING) {
          // not HEATING, thus either OFF or AUTO, but action is IDLE
          // this means that heater was manually switched on by its power button.
          // force HEAT mode
          auto thermostat = id(gas_thermostat);
          thermostat->mode = CLIMATE_MODE_HEAT;
          thermostat->action = CLIMATE_ACTION_HEATING;
          thermostat->publish_state();
        }
    on_turn_off:
    - lambda: |-
        if (id(gas_thermostat).action != CLIMATE_ACTION_OFF) {
          // not OFF, thus either HEATING or AUTO, but action is HEATING
          // this means that heater was manually switched off by its power button.
          // force OFF mode
          auto thermostat = id(gas_thermostat);
          thermostat->mode = CLIMATE_MODE_OFF;
          thermostat->action = CLIMATE_ACTION_OFF;
          thermostat->publish_state();
        }