Interfacing 'generic_thermostat' help please

I currently manage two room heaters via the generic_thermostat, one is on all the time (bedroom) and the lounge heater enabled / disabled manually via my phone or PC HA dashboards.

I would like to expand it two ways if possible (or this could be the tail wagging the dog etc).

  1. To have a remote physical displ(ay/ies) of what generic_thermostat considers the target and actual temperatures are (maybe a LillyGo TFT / ESP32) and

  2. some form of physical Up / Down temperature control buttons or a rotary encoder etc (could also be the same hardware as the display etc)?

My issue is Iā€™m not a coder so donā€™t really have any idea what I would need to do with the existing code to be able to provide such things?

climate:
  - platform: generic_thermostat
    name: Lounge
    heater: switch.lounge_heater
    target_sensor: sensor.meter_1676_temperature    
    min_temp: 10
    max_temp: 28
    ac_mode: false
    target_temp: 12
    cold_tolerance: 0.3
    hot_tolerance: 0
    min_cycle_duration:
      seconds: 5
    keep_alive:
      minutes: 3
    initial_hvac_mode: "heat"
    precision: 0.5

Iā€™ve tried to test an Ikea ZigBee pushbutton to allow the Up / Down function to impact the target temperature but am not sure if that feature is available with the above code or what to look for if it is?

Would I need to add code to ā€˜revealā€™ externally things like the current temp, the target temp and if itā€™s heating or idle or should they already be present please?

Thanks for reading etc. Iā€™d love to diy these features and may be able to copy / paste some code from my CO2 monitor re the TTGO display etc.

display:
  - platform: st7789v
    model: TTGO TDisplay 135x240  # added bit
    id: my_display
    backlight_pin: GPIO4
    # allow_other_uses: true
    cs_pin: GPIO5
    dc_pin: GPIO16
    reset_pin: GPIO23
    rotation: 270

(Note, Iā€™ve just flipped the display 180 Deg to save having the turn the display module upside down and it worked first time!)

They are available in climate.lounge.

  • You can access the value of its state and attributes using templates employing the states() and state_attr() functions.

  • You can set its mode and target temperature using service calls described in the Climate integrationā€™s documentation.

Thanks for that.

So the temperatures (as seen by generic_thermostat) are not something I can can just find / select from the card editor as an entity etc?

I mean, for my additional TTGO TFT idea to display of the current temperature I can (someone should be able to ) read the lounge temperature sensor and display that value on said ESP32/TFT, like a repeater. It would be reading of the generic_thermostat target value would require said interfacing with this ā€˜softā€™ entity (and that appears to be way outside my skillset). ;-(

Iā€™ll see if my coding friend can make more sense of it for me. :wink:

The target temperature can be changed via a Thermostat card.

min_temp and max_temp are not adjustable via a service call or the UI.

Yes, I appreciate that (as thatā€™s how Iā€™m currently doing it), itā€™s just how to also change that via another ā€˜deviceā€™? Like an ESP32 with Up/Down buttons or for testing, an existing Ikea / Hue ZigBee remote?

With ESPHome.

With an automation.

I ā€˜getā€™ the ESPHome thing (conceptually, I donā€™t have the skills myself) but I tried creating an automation and was able to select the trigger (Ikea / Hue Up / down button presses as triggers) but then not what to select in the Action to make anything happen to the generic_thermostat?

So do I look for the state you suggested ( climate.lounge) or do I have to create some form of intermediate code?

FWIW Iā€™ve just set a Ikea Up/Down where the Up press sets the target temp to 1 DegC (as confirmed on my generic_thermostat Card) and that works but not what I really need, and that is to increment it by say 1 DegC?

You select a desired service call, like climate.set_temperature.

Itā€™s documented in the link I posted above.

If you want to increment/decrement the existing target temperature, use a template to compute it.

Post the automation you created and I can show you how to employ a template.

alias: New Ikea Up target temp
description: ""
trigger:
  - device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_long_press
    subtype: dim_up
condition: []
action:
  - service: climate.set_temperature
    metadata: {}
    data:
      temperature: 1
    target:
      entity_id: climate.lounge
mode: single
alias: New Ikea Up target temp
description: ""
trigger:
  - device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_long_press
    subtype: dim_up
condition: []
action:
  - service: climate.set_temperature
    metadata: {}
    data:
      temperature: "{{ state_attr('climate.lounge', 'temperature') + 1 }}"
    target:
      entity_id: climate.lounge
mode: single

Wahey! It worked, first time, thanks! (Very much).

So I would create a second automation that would allow me to set the target temperature so that bit is covered. The next bit would be reading the lounge temperature sensor and reporting that on a repeater display and also somehow displaying the target temperature for a few seconds as I change it.

That will have to be for another day, got to go visit my Mum in hospital as she had a stroke before xmas ā€¦ ;-(

Thanks again. :wink:

You can put more than one trigger into a single automation.

Iā€™m guessing that when you press the ā€œdownā€ part of the button it produces a dim_down subtype instead of dim_up. If my guess is correct then the following version should work (otherwise not).

alias: New Ikea Up Down target temp
description: ""
trigger:
  - id: '1'
    device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_long_press
    subtype: dim_up
  - id: '-1'
    device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_long_press
    subtype: dim_down
condition: []
action:
  - service: climate.set_temperature
    metadata: {}
    data:
      temperature: "{{ state_attr('climate.lounge', 'temperature') + trigger.id | int(0) }}"
    target:
      entity_id: climate.lounge
mode: single

You may also consider using an existing automation blueprint designed for your particular model of IKEA button. The blueprint understands all of the buttonā€™s events and makes it easier for you to compose the automation. I donā€™t know the model you have so hereā€™s a list of blueprints containing the word ā€œIkeaā€.
https://community.home-assistant.io/search?q=Ikea%20%23blueprints-exchange


Very sorry about your motherā€™s health. I hope she will be able to recover from the stroke.

Thanks once again, that works perfectly and is sufficient as the proof_of_concept for me and this project. :wink:

Itā€™s also fairly usable ITRW as I know a single up / down button press will increment the temperature one degree.

Now itā€™s just a matter of seeing if I can Frankenstein the CO2 monitor code to handle the display bit. :wink:

esphome:
  name: co2-sensor-2
  platform: ESP32
  board: "featheresp32"  

# Enable Home Assistant API
api:

ota:

wifi:
  ssid: !secret wifi_k_ssid
  password: !secret wifi_k_password
  
  #  use_address: 192.168.0.207
  
  manual_ip:
   static_ip: 192.168.0.198
   gateway: 192.168.0.100
   subnet: 255.255.255.0      
  

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Co2-Sensor-2 Fallback Hotspot"
    password: "secret"

captive_portal:

logger:
  level: DEBUG
  logs:
    component: ERROR

# CO2 sensor
uart:
  rx_pin: 27
  tx_pin: 26
  baud_rate: 9600

# Dipslay driver: ST7789
spi:
  clk_pin: GPIO18
  mosi_pin: GPIO19

font:
  - file: "Oswald-Light.ttf"
    id: font_70
    size: 70
    glyphs: 0123456789 # Only used for CO2 level

  - file: "Oswald-Light.ttf"
    id: font_30
    size: 30

color:
  - id: color_black
    red: 0%
    green: 0%
    blue: 0%
    white: 0%
  - id: color_green
    red: 0%
    green: 100%
    blue: 0%
  - id: color_yellow
    red: 100%
    green: 100%
    blue: 0%
  - id: color_orange
    red: 100%
    green: 55%
    blue: 0%
  - id: color_red
    red: 100%
    green: 0%
    blue: 0%
  - id: color_white
    red: 100%
    green: 100%
    blue: 100%

display:
  - platform: st7789v
    model: TTGO TDisplay 135x240  # added bit
    id: my_display
    backlight_pin: GPIO4
    # allow_other_uses: true
    cs_pin: GPIO5
    dc_pin: GPIO16
    reset_pin: GPIO23
 #   brightness: 100%
    rotation: 270
    pages:
      # Page 1: Current CO2 levels
      #    0    - 1000 -> Green
      #    1000 - 1600 -> Yellow
      #    1600 - 2000 -> Orange
      #    >2000       -> Red
      - id: page1
        lambda: |-
          if(!id(co2_sensor_2).has_state() ){
            it.print(
              it.get_width()/2,
              it.get_height()/2,
              id(font_70),
              color_white,
              TextAlign::CENTER,
              "Starting..."
            );
            return;
          }
         
          auto bg_color = id(color_black);
          auto text_color = id(color_green);
          auto co2 = id(co2_sensor_2).state;
          if(co2 > 1000) text_color = id(color_yellow);
          if(co2 > 1600) text_color = id(color_orange);
          if(co2 > 2000){
            text_color = id(color_white);
            bg_color = id(color_red);
          }
          it.filled_rectangle(0, 0, it.get_width(), it.get_height(), bg_color);
          it.printf(
            it.get_width()/2, 
            it.get_height()/2, 
            id(font_70), 
            text_color, 
            TextAlign::CENTER, 
            "%.0f",
            co2
          );
      # Page 2: WiFi information
      - id: page2
        lambda: |-
          it.print(
            0, 0,
            id(font_30),
            id(color_white),
            "WiFi details"
          );
          it.printf(
            0, 30,
            id(font_30),
            id(color_white),
            "%s",
            id(wifi_ssid).state.c_str()
          );
          it.printf(
            0, 60,
            id(font_30),
            id(color_white),
            "%s",
            id(wifi_ip_addr).state.c_str()
          );
#switch:
#  - platform: gpio
#    pin: GPIO4
#     allow_other_uses: true
#    id: backlight
#    internal: true

sensor:
  - platform: mhz19
    co2:
      name: "CO2 Sensor 2"
      id: "co2_sensor_2"
    temperature:
      name: "CO2 sensor 2 temperature"
      internal: true
    update_interval: 60s
    automatic_baseline_calibration: false
    
  - platform: wifi_signal
    name: "CO2 sensor 2 WiFi"
    update_interval: 60s   

text_sensor:
  - platform: wifi_info
    ip_address:
      internal: true
      id: wifi_ip_addr
    ssid:
      internal: true
      id: wifi_ssid

binary_sensor:
  # Button to cycle through pages on the display
  - platform: gpio
    pin:
      number: GPIO35
      inverted: true
    id: button_1
    on_click:
      then:
        - display.page.show_next: my_display
        - component.update: my_display

  # Button to toggle the backlight (for use at night)
  #- platform: gpio
  #  pin:
  #    number: GPIO0
  #    inverted: true
  #  id: button_2
  #  on_click:
  #    then:
  #      - switch.toggle: backlight
        
button:
  - platform: restart
    name: "CO2 sensor 2 restart"   

Youā€™re welcome!

Please consider marking my post above with the Solution tag. It will automatically place a check-mark next to the topicā€™s title which signals to other users that this topic has been resolved. This helps users find answers to similar questions.

For more information about the Solution tag, refer to guideline 21 in the FAQ.

I forgot to thanks you for your kind thoughts re my mum (93).

Whilst this stroke seems to have hit her quite hard, she has always been strong and Iā€™ve noticed the improvement in her left leg, since we started helping with the physio.

Itā€™s all just more things to have to deal with, my Mrs was diagnosed with dementia at the beginning of last year and me with prostate cancer soon after.

But at least we have all lived a reasonable and happy lives so far and are thankful we arenā€™t being bombed in our beds. :wink:

1 Like

HI,

I now have the current lounge temperature value being displayed on the Switchbot Meter temperature and humidity sensor (with inbuilt LCD display), on HA on the generic_thermostat card and now (with some help), on a TTGO ESP32 with integrated TFT display. :wink:

What I would like to do now is to also display the target temperature as set on the generic_thermostat but donā€™t really know where / how to approach that one?

This is the code I used to get the current temp on the display:

      - id: page1
        lambda: |-
            it.printf(
              it.get_width()/2,
              it.get_height()/2,
              id(font_40),
              color_red,
              TextAlign::CENTER,
              "%s  Ā°C",
              id(temp).state.c_str());

Along with:

text_sensor:   
  - platform: homeassistant
    name: "Lounge temperature test"
    id: temp
    entity_id: sensor.meter_1676_temperature 

This is the (your) automation I am currently using to adjust the generic_thermostat from an Ikea remote. I should be able to transfer that function to the same ESP32/display as mentioned above.

alias: New Ikea Up Down target temp
description: ""
trigger:
  - device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_short_press
    subtype: turn_on
    id: "1"
  - device_id: d7801919c3628a93bbb9bb67b76594eb
    domain: zha
    platform: device
    type: remote_button_short_press
    subtype: turn_off
    id: "-1"
condition: []
action:
  - service: climate.set_temperature
    metadata: {}
    data:
      temperature: "{{ state_attr('climate.lounge', 'temperature') + trigger.id | int(0) }}"
    target:
      entity_id: climate.lounge
mode: single

The last thing will be to see if I can change the colour of the thermostat text, depending on whatā€™s going on. Like with the generic_thermostat turned off it could just display the current temperature in white. If itā€™s on then the target temperature could be also there but in green if met and red when heating?

All just a pipe dream as far as my coding and understanding of it all is concerned ā€¦ :wink:

Maybe I have misunderstood your request but it seems like itā€™s related to ESPHome. If it is then I donā€™t have the expertise to help you with that.

Ah, thanks for the prompt reply anyway. :wink:

In answer to my own question and in case it helps anyone else, to ā€˜exposeā€™ the target temperature of the thermostat I added some code to configuration.yaml

sensor:
  - platform: template
    sensors:
     lounge_thermostat_target:
      friendly_name: "Lounge thermostat target temp"
      unit_of_measurement: 'degrees'
      value_template: "{{ state_attr('climate.lounge', 'temperature') }}"

And then in my ESP32/TTGO display:

sensor:
  - platform: homeassistant
    name: "Lounge temperature actual"
    id: temp
    entity_id: sensor.meter_1676_temperature  

  - platform: homeassistant
    name: "Lounge temperature target"
    id: target
    entity_id: sensor.lounge_thermostat_target

And to display it on the TTGO/ESP/TFT:

display:
  - platform: st7789v
    model: TTGO TDisplay 135x240
    id: my_display
    cs_pin: GPIO5
    dc_pin: GPIO16
    reset_pin: GPIO23
    rotation: 270
    pages:
      - id: page1
        lambda: |-
            it.printf(
              110, 0,
              id(font_50),
              color_white,
              "%.1f Ā°C", 
              id(target).state);

            it.printf(
              110, 60,
              id(font_50),
              color_white,
              "%.1f Ā°C", 
              id(actual).state);

Iā€™m not suggesting that this is a good solution or coding, just that it seems to work and is still a ā€˜work in progressā€™. :wink:

Thanks to all who helped me get this far. :wink: