Custom Button-Card Template for EVOHOME_CC / RAMSES_RF

I’ve put together a template for displaying Evohome heating zones from entities created by the evohome_cc / RAMSES_RF custom component integration. It’s easy to tweak and reasonably compact, whilst displaying a lot of information. It’s designed to be used in a Lovelace grid of two columns for optimum mobile viewing, but will work in a single column too.

Firstly, make sure you have the evohome_cc and the button-card components installed. HACS is the easiest way to do this in my opinion…
evohome_cc / RAMSES_RF: GitHub - zxdavb/evohome_cc: (WIP) HA custom component for evohome_rf
Button Card: GitHub - custom-cards/button-card: ❇️ Lovelace button-card for home assistant

Secondly, edit your Lovelace UI configuration. If you’ve never done this before here are some basic steps:

  • I suggest you do this from a regular web desktop/laptop web browser and not a tablet / mobile.
  • On the Home Assistant dashboard, click on the three-dots icon in the top-right and choose ‘Edit Dashboard’
  • Go and find those three-dots again in the top-right and click a second time on it, this time choosing ‘Raw configuration editor’
  • Did I mention to make sure you’ve already taken a backup?
  • The first row in this file is usually ‘title: SERVER-NAME’, you copy and paste my whole template under this, starting on line 2.

This goes in your Lovelace-UI YAML file:

button_card_templates:
  evohome_tile:
    variables:
      entity_climate: climate.living_room
      entity_heat_demand: sensor.04_029854_heat_demand
      entity_battery: binary_sensor.04_029854_battery_2
      entity_window: binary_sensor.04_029854_window_2
    triggers_update:
      - '[[[ return variables.entity_climate ]]]'
      - '[[[ return variables.entity_heat_demand ]]]'
      - '[[[ return variables.entity_battery ]]]'
      - '[[[ return variables.entity_window ]]]'
    action: more-info
    show_icon: false
    show_name: true
    styles:
      card:
        - padding: 2%
        - background-color: |
            [[[
              var entity_name = variables.entity_climate
              if (entity_name == 'water_heater.stored_hw')
                if(states[entity_name].state == 'off')
                  return "#dddddd"; // grey
                else
                  return "#ff5252"; // red
              if (states[entity_name].attributes['hvac_action'] == 'heating')
                return "#ff5252"; // red
              if (states[entity_name].attributes['preset_mode'] == 'away')
                return "#dec362"; // yellow
              if ((states[entity_name].attributes['heating_type'] == 'electric_heat') && (states[entity_name].state != 'off'))
                return "#73d16b"; // green
              if (states[entity_name].attributes['hvac_action'] == 'idle')
                return "#73d16b"; // green
              if (states[entity_name].state == 'off')
                return "#dddddd"; // grey
              if (states[variables.entity_climate].attributes['hvac_action'] == null)
                return "#6ba5d1"; // blue
              return "#ffffff"; // white
            ]]]
      grid:
        - grid-template-areas: >-
            "n n n" "current_temperature current_temperature setpoint_title"
            "current_temperature current_temperature setpoint_value" "status
            status status" "mode mode mode" "demand demand demand" "battery
            battery battery" "window window window"
        - grid-template-columns: auto
        - grid-template-rows: min-content
      name:
        - color: black
        - font-size: 12px
        - justify-self: start
      custom_fields:
        current_temperature:
          - color: black
          - font-size: 30px
          - font-weight: bold
          - justify-self: start
        setpoint_title:
          - color: black
          - font-size: 10px
          - font-weight: normal
          - justify-self: start
          - font-style: italics
        setpoint_value:
          - color: black
          - margin-top: '-6px'
          - font-size: 17px
          - font-weight: normal
          - justify-self: start
          - font-style: italics
        status:
          - color: black
          - margin-top: 1px
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        mode:
          - color: black
          - font-style: italics
          - margin-top: 1px
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        demand:
          - color: black
          - font-size: 14px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        battery:
          - color: black
          - font-size: 14px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        window:
          - color: black
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
    custom_fields:
      current_temperature: |
        [[[
          return states[variables.entity_climate].attributes['current_temperature'] + "°C"
        ]]]
      setpoint_title: |
        [[[
          return "Setpoint"
        ]]]
      setpoint_value: |
        [[[
          return states[variables.entity_climate].attributes['temperature'] + "°C"
        ]]]
      status: |
        [[[
          var outputtext
          if (variables.entity_climate == 'water_heater.stored_hw')
            outputtext = states[variables.entity_climate].state + " - " + states[variables.entity_climate].attributes['operation_mode']
          else if (states[variables.entity_climate].attributes['heating_type'] == 'electric_heat')
            outputtext = states[variables.entity_climate].state + " - " + states[variables.entity_climate].attributes['preset_mode']
          //else if (states[variables.entity_climate].attributes['hvac_action'] == null)
          //  outputtext = "On - " + states[variables.entity_climate].attributes['preset_mode'] 
          else
            outputtext = states[variables.entity_climate].attributes['hvac_action'] + " - " + states[variables.entity_climate].attributes['preset_mode']
          return outputtext
        ]]]
      mode: |
        [[[
          if ((states[variables.entity_climate].attributes['preset_mode'] != null) && (states[variables.entity_climate].attributes['preset_mode'] == "temporary") )
            if ((states[variables.entity_climate].attributes['mode'] != null))
              return "Until: " + states[variables.entity_climate].attributes['mode']['until']
            else
              return "No Mode Data"
          else
            if ((states[variables.entity_climate].attributes['mode'] != null))
              return states[variables.entity_climate].attributes['mode']['mode'].split('_').join(' ')
            else
              return "No Mode Data"
        ]]]
      demand: |
        [[[
          var returnstring = "<br><ha-icon icon='mdi:fire' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if (states[variables.entity_heat_demand].state == null)
            return returnstring + "?"
          else
            return returnstring + Math.round(states[variables.entity_heat_demand].state) + "%"
        ]]]
      battery: |
        [[[
          var returnstring = "<ha-icon icon='mdi:battery-high' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if (states[variables.entity_battery].attributes['battery_level'] == null)
            return returnstring + "?"
          else
            return returnstring + states[variables.entity_battery].attributes['battery_level']*100 + "%"
        ]]]
      window: |
        [[[
          var returnstring = "<ha-icon icon='mdi:window-open' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if ( (states[variables.entity_window].attributes['device_id'] == null) || (variables.entity_climate == 'water_heater.stored_hw') || (states[variables.entity_climate].attributes['heating_type'] == 'electric_heat'))
            return "<br>"
          else
            if(states[variables.entity_window].state == 'on')
              return returnstring + 'Open'
            else
              return returnstring + 'Closed'
        ]]]

Now add a new card of type ‘Custom: Button-Card’ and paste the following example. You will need to replace the entity and variables with your appropriate sensor entities. Yes, I know you’ve got to put your climate entity in twice but I can’t figure out how to improve that at the moment.

type: custom:button-card
template: evohome_tile
entity: climate.living_room
variables:
  entity_climate: climate.living_room
  entity_heat_demand: sensor.04_029854_heat_demand
  entity_battery: binary_sensor.04_029854_battery_2
  entity_window: binary_sensor.04_029854_window_2

And this is an example of how to make it look nice in a Grid:

type: grid
cards:
  - type: custom:button-card
    template: evohome_tile
    entity: climate.living_room
    variables:
      entity_climate: climate.living_room
      entity_heat_demand: sensor.04_029854_heat_demand
      entity_battery: binary_sensor.04_029854_battery_2
      entity_window: binary_sensor.04_029854_window_2
  - type: custom:button-card
    template: evohome_tile
    entity: climate.guest_room
    variables:
      entity_climate: climate.guest_room
      entity_heat_demand: sensor.04_029850_heat_demand
      entity_battery: binary_sensor.04_029850_battery_2
      entity_window: binary_sensor.04_029850_window_2
  - type: custom:button-card
    template: evohome_tile
    entity: climate.en_suite
    variables:
      entity_climate: climate.en_suite
      entity_heat_demand: sensor.04_029880_heat_demand
      entity_battery: binary_sensor.04_029880_battery_2
      entity_window: binary_sensor.04_029880_window_2
  - type: custom:button-card
    template: evohome_tile
    entity: climate.main_bedroom
    variables:
      entity_climate: climate.main_bedroom
      entity_heat_demand: sensor.04_059705_heat_demand
      entity_battery: binary_sensor.04_059705_battery_2
      entity_window: binary_sensor.04_059705_window_2
columns: 2
square: false

Update 2021-11-10:

  • Merged the Window entity tweaks into this post.
  • Added some checking for null objects in the ‘Mode’ display. If you notice any more errors from this card caused by null entity objects please let me know. They manifest as a massive ugly blob of error text on your dashboard when you try and display the card.
2 Likes

That’s very nice looking but looks like it’s not working in your card template the variables bit has your own settings
can you recheck the code please ?

The template is fine, but for the cards you would need to substitute my entities for your own. The three variable values at the top of the template are default values. You can put your own default entities in there too.

1 Like

Thanks for this nice overview of the different heating zones. I’m wondering if you might add the open window binary_sensor to the card?

Yup, should be straightforward but I had my window entities disabled. They’re enabled now so once they’ve become available and populated with some data I’ll tweak the template.

Ok here it is then. Your updated template which supports the window open/close entity status too. The end result if embedded in a 2 column grid would look something like this (note that I rebooted Home Assistant recently so the status of some of my entities are currently unknown, hence the ? and blank spaces everywhere):

button_card_templates:
  evohome_tile:
    variables:
      entity_climate: climate.living_room
      entity_heat_demand: sensor.04_029854_heat_demand
      entity_battery: binary_sensor.04_029854_battery_2
      entity_window: binary_sensor.04_029854_window_2
    triggers_update:
      - '[[[ return variables.entity_climate ]]]'
      - '[[[ return variables.entity_heat_demand ]]]'
      - '[[[ return variables.entity_battery ]]]'
      - '[[[ return variables.entity_window ]]]'
    action: more-info
    show_icon: false
    show_name: true
    styles:
      card:
        - padding: 2%
        - background-color: |
            [[[
              var entity_name = variables.entity_climate
              if (entity_name == 'water_heater.stored_hw')
                if(states[entity_name].state == 'off')
                  return "#dddddd"; // grey
                else
                  return "#ff5252"; // red
              if (states[entity_name].attributes['hvac_action'] == 'heating')
                return "#ff5252"; // red
              if (states[entity_name].attributes['preset_mode'] == 'away')
                return "#dec362"; // yellow
              if ((states[entity_name].attributes['heating_type'] == 'electric_heat') && (states[entity_name].state != 'off'))
                return "#73d16b"; // green
              if (states[entity_name].attributes['hvac_action'] == 'idle')
                return "#73d16b"; // green
              if (states[entity_name].state == 'off')
                return "#dddddd"; // grey
              if (states[variables.entity_climate].attributes['hvac_action'] == null)
                return "#6ba5d1"; // blue
              return "#ffffff"; // white
            ]]]
      grid:
        - grid-template-areas: >-
            "n n n" "current_temperature current_temperature setpoint_title"
            "current_temperature current_temperature setpoint_value" "status
            status status" "mode mode mode" "demand demand demand" "battery
            battery battery" "window window window"
        - grid-template-columns: auto
        - grid-template-rows: min-content
      name:
        - color: black
        - font-size: 12px
        - justify-self: start
      custom_fields:
        current_temperature:
          - color: black
          - font-size: 30px
          - font-weight: bold
          - justify-self: start
        setpoint_title:
          - color: black
          - font-size: 10px
          - font-weight: normal
          - justify-self: start
          - font-style: italics
        setpoint_value:
          - color: black
          - margin-top: '-6px'
          - font-size: 17px
          - font-weight: normal
          - justify-self: start
          - font-style: italics
        status:
          - color: black
          - margin-top: 1px
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        mode:
          - color: black
          - font-style: italics
          - margin-top: 1px
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        demand:
          - color: black
          - font-size: 14px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        battery:
          - color: black
          - font-size: 14px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
        window:
          - color: black
          - font-size: 12px
          - font-weight: normal
          - justify-self: start
          - text-transform: capitalize
    custom_fields:
      current_temperature: |
        [[[
          return states[variables.entity_climate].attributes['current_temperature'] + "°C"
        ]]]
      setpoint_title: |
        [[[
          return "Setpoint"
        ]]]
      setpoint_value: |
        [[[
          return states[variables.entity_climate].attributes['temperature'] + "°C"
        ]]]
      status: |
        [[[
          var outputtext
          if (variables.entity_climate == 'water_heater.stored_hw')
            outputtext = states[variables.entity_climate].state + " - " + states[variables.entity_climate].attributes['operation_mode']
          else if (states[variables.entity_climate].attributes['heating_type'] == 'electric_heat')
            outputtext = states[variables.entity_climate].state + " - " + states[variables.entity_climate].attributes['preset_mode']
          //else if (states[variables.entity_climate].attributes['hvac_action'] == null)
          //  outputtext = "On - " + states[variables.entity_climate].attributes['preset_mode'] 
          else
            outputtext = states[variables.entity_climate].attributes['hvac_action'] + " - " + states[variables.entity_climate].attributes['preset_mode']
          return outputtext
        ]]]
      mode: |
        [[[
          if (states[variables.entity_climate].attributes['preset_mode'] == "temporary")
            return states[variables.entity_climate].attributes['mode']['until']
          else
            return states[variables.entity_climate].attributes['mode']['mode'].split('_').join(' ')
        ]]]
      demand: |
        [[[
          var returnstring = "<br><ha-icon icon='mdi:fire' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if (states[variables.entity_heat_demand].state == null)
            return returnstring + "?"
          else
            return returnstring + Math.round(states[variables.entity_heat_demand].state) + "%"
        ]]]
      battery: |
        [[[
          var returnstring = "<ha-icon icon='mdi:battery-high' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if (states[variables.entity_battery].attributes['battery_level'] == null)
            return returnstring + "?"
          else
            return returnstring + states[variables.entity_battery].attributes['battery_level']*100 + "%"
        ]]]
      window: |
        [[[
          var returnstring = "<ha-icon icon='mdi:window-open' style='width: 12px; height: 12px; color: black;'></ha-icon>&nbsp;"
          if ( (states[variables.entity_window].attributes['device_id'] == null) || (variables.entity_climate == 'water_heater.stored_hw') || (states[variables.entity_climate].attributes['heating_type'] == 'electric_heat'))
            return "<br>"
          else
            if(states[variables.entity_window].state == 'on')
              return returnstring + 'Open'
            else
              return returnstring + 'Closed'
        ]]]

And an example of how you’d call it from a card:

type: custom:button-card
template: evohome_tile
entity: climate.living_room
variables:
  entity_climate: climate.living_room
  entity_heat_demand: sensor.04_029854_heat_demand
  entity_battery: binary_sensor.04_029854_battery_2
  entity_window: binary_sensor.04_029854_window_2

Update 2021-10-18: I’ve just tweaked the code slightly so as the window status doesn’t show on electric heating zone or DHW cards.

3 Likes

Thanks looks great

Many thanks. I used a lot of your code to do the same approach for mine. More of understanding the concept of Variables and grid as well

1 Like

Would you be able to perhaps share a screenshot of your chosen layout please? I’m just curious as to how other people are presenting their heating systems in HA.

Sure, will do, but I’m working on the design step by step slowly. I’ll share it here by the end

Do you plan on adding boost button for 1 hour?

I’m sorry but I don’t plan on doing that, I like the clean information view and never personally use boost for heating. I’m sure it’s possible if you wanted to play - my starting point would be trying to embed a button-card for calling the boost service as an entity within my existing button-card’s grid layout. It’s probably easiest to create the new button-card first to get it working, and then try embedding it afterwards.

Update - I thought about this for a few more seconds and I’m not certain you can actually embed a button-card in a button-card. I think you’d have to totally change the approach and instead implement a vertical stack instead containing two button cards, and then you’d have to change the logic to control the background colour and make it look like a single tile. It’s basically a very different solution to the one I have built. Happy to be proven wrong though!