Need help controlling a shade using the window and room temperatures

I have an insulated shade with a motor that uses a momentary button press to open or close the shade and it automatically runs to the end stops. I installed an ESPhome board to control the shade from HA and that part works fine by pulsing the “shade_up” or “shade_down” outputs.

Now I want to add an automation to open the shade when the temperature by the window is higher than the room temperature and close it when it is a few degrees cooler by the window. The temperature sensors are setup and show the room and window temperatures correctly. I like the idea of the automation being in the ESPhome code rather than in HA.

I’m not sure where the automation code should go. I’ve tried adding code to the “sensor:” block with a lambda |- and under the “binary_sensor:” too but haven’t been successful. I also tries the interval trigger to check the states and run actions but that didn’t work either. I did finally get a new value of the difference between the room and window temps by adding the “-platform: template” section but can’t figure how to use it to create an action.

Here is my code so far:

esphome:
  name: shadecontroller

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: "xxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

# Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Shadecontroller Fallback Hotspot"
    password: "xxxxxx"

captive_portal:

i2c:
  scan: True

# room and window temp sensors
sensor:
  - platform: bme280
    temperature:
      name: "Diningroom temperature"
      id: dtemp
    pressure:
      name: "Diningroom Pressure"
    humidity:
      name: "Diningroom humidity"
    address: 0x77
    update_interval: 60s
  - platform: mcp9808
    name: "Window temperature"
    id: wtemp
    address: 0x18
    update_interval: 60s

# this value is the difference between the room and window temps
  - platform: template
    id: windowwarm
    update_interval: 60s
    lambda: 'return id(wtemp).state - id(dtemp).state;'

#    on_value:
#      then:
#        if (id(windowwarm).state) {
#        - cover.open: dining_room_shade
#        } else {
#        - cover.close: dining_room_shade
#        }

# limit switch input status (closed switch = full open)
binary_sensor:
  - platform: gpio
    pin: GPIO14
    name: "fullopen"
    id: full_open

# output pins used to electrically control shade
switch:
  - platform: gpio
    pin: GPIO12
    name: "shadeup"
    id: shade_up
  - platform: gpio
    pin: GPIO13
    name: "shadedown"
    id: shade_down

# user interface for shade control in HA
cover:
  - platform: template
    name: "Dining room shade"
    id: dining_room_shade
    optimistic: true
# this sections updates the state from the limit switch in case
#   the shade is moved with the local switches on the motor
    lambda: |-
      if (id(full_open).state) {
        return COVER_CLOSED;
      } else {
        return COVER_OPEN;
      }
    open_action:
      - switch.turn_on: shade_up
      - delay: 2s
      - switch.turn_off: shade_up
    close_action:
      - switch.turn_on: shade_down
      - delay: 2s
      - switch.turn_off: shade_down

Any help would be greatly appreciated. Or point me to further reading… I think I read all the ESPHome docs already.

If you want to be able to override the auto close/open you’ll need a switch.

switch:
  - platform: template
    name: "Enable Auto Shade"
    id: eas

Then under each temp sensor, this will check every time the sensors update. It also requires each condition to be true for 5 min before acting.

on_value:
  if:
    condition:
      switch.is_on: eas
    then:
      - if: 
          condition: 
            for:
              time: 5min
              condition:
                - lambda: |-
                    return (id(wtemp).state > id(dtemp).state) 
              then:
                 - cover.close: dining_room_shade
on_value:
  if:
    condition:
      switch.is_on: eas
    then:
      - if: 
          condition: 
            for:
              time: 5min
              condition:
                - lambda: |-
                    return (id(dtemp).state > id(wtemp).state) 
              then:
                 - cover.open: dining_room_shade

This is untested and I’m not sure if it will compile.

Thanks for the input. I have tried similar things but you are correct… it doesn’t pass validation. I tried different indentation and eliminating the switch section to keep it simple but I am not having any luck.

I tried putting the “on_value:” as the start of a new block (column 1) and under the “sensor:” block (column 4) after the “- platform: template” section but I get various errors in both places.

I assume the "on_value: should go under the “- platform: template” section, it that correct?

A couple of changes the switch

switch:
  - platform: template
    name: "Enable Auto Shade"
    id: eas
    optimistic: true

Then the lambda, just swap this for what you have under sensor.

sensor:
  - platform: bme280
    temperature:
      name: "Diningroom temperature"
      id: dtemp
      on_value:
        if:
          condition:
            switch.is_on: eas
          then:
            - if: 
                condition: 
                  for:
                    time: 5min
                    condition:
                      - lambda: 'return id(wtemp).state > id(dtemp).state;'
                then:
                  - cover.close: dining_room_shade
    pressure:
      name: "Diningroom Pressure"
    humidity:
      name: "Diningroom humidity"
    address: 0x77
    update_interval: 60s
  - platform: mcp9808
    name: "Window temperature"
    id: wtemp
    address: 0x18
    update_interval: 60s
    on_value:
      if:
        condition:
          switch.is_on: eas
        then:
          - if: 
              condition: 
                for:
                  time: 5min
                  condition:
                    - lambda: 'return id(dtemp).state > id(wtemp).state;'
              then:
                - cover.open: dining_room_shade

I will give this a try next week and let you know how it goes… thanks!

It’s been a long time but I now have an automation that works well.
I eliminated this section from the ESP code.

# this value is the difference between the room and window temps
  - platform: template
    id: windowwarm
    update_interval: 60s
    lambda: 'return id(wtemp).state - id(dtemp).state;'

Then used this code in an automation.

- id: 'xxxxxxxxxx'
  alias: Shade control for dining room shade
  description: ''
  trigger:
  - platform: template
    value_template: '{{ states(''sensor.window_temperature'') | int > states(''sensor.diningroom_temperature'')
      | int }}'
    id: Open dining room shade
  - platform: template
    value_template: '{{ states(''sensor.window_temperature'') | int +3 < states(''sensor.diningroom_temperature'')
      | int }}'
    id: Close dining room shade
  condition: []
  action:
  - choose:
    - conditions:
      - condition: trigger
        id: Open dining room shade
      - condition: state
        entity_id: cover.dining_room_shade
        state: closed
      sequence:
      - device_id: xxxxxxxxxxxxxxxx
        domain: cover
        entity_id: cover.dining_room_shade
        type: open
    - conditions:
      - condition: trigger
        id: Close dining room shade
      - condition: state
        entity_id: cover.dining_room_shade
        state: open
      sequence:
      - device_id: xxxxxxxxxxxxxxxxxxxxx
        domain: cover
        entity_id: cover.dining_room_shade
        type: close
  mode: single

Now I can adjust the hysteresis by changing the offset (+3 in this code). I used the history with the room temperature and window temperature sensors to watch the temperatures to fine tune the value and make sure it did not cycle close, open and close again as the sun went down.