I have been really pleased with how my compact climate button turned out, so I decided to share with the community. This uses the custom button card and is designed to be used on a picture elements card, but it can be used by itself if you don’t mind the fixed sizing. I created it for my pool control UI, which you can read about here. That post was before I created this new climate button, so it is using a much simpler template for the various temperatures.
Example 1: four compact climate buttons on a picture elements card:
Example 2: five compact climate buttons used directly as a card in 2 horizontal-stacks:
If you use this, you may need to adjust a few things to fit your specific devices. I think it will work fine in most cases, but some of the states and attributes I watch for may be specific to my Venstar thermostats and Aqualink pool system.
Aside: if you have an Aqualink system, check out the aqualinkd project to interface it with Home Assistant. I’m happy to share my config if you decide to do it.
Some notable design features:
- large display of current temperature
- spinning fan icon behind temperature while actively cooling or heating
- current setpoint at bottom right corner
- green indicates idle
- blue indicates cooling in progress
- red indicates heating in progress
- yellow indicates waiting (my Venstar thermostats do this to prevent short-cycling the HVAC)
- 2 setpoint temperatures displayed if appropriate (auto cool/heat)
- icon above setpoint indicates the operation mode (snowflake for cooling, flame for heating)
- not shown while idle when 2 setpoint temperatures are applicable because the system can both heat and cool, but when actively cooling or heating the appropriate icon will appear along with the appropriate color
- current humidity at bottom left corner, if available
- alternate entity and attribute for humidity can be specified
- signle-tap shows more-info dialog for making adjustments or viewing history
- supports hiding the card with a variable, which can be set with a javascript template
- various colors can be set with variables
A simple usage example:
- type: 'custom:button-card'
template: bigtemp
entity: climate.upstairs
It expects a climate entity. You can certainly change the template if you need it to work with different devices. I figure this is a good starting point for anyone and you can change it any way you like.
There are a few variables you can use to adjust colors and a few behaviors:
variable | default | description |
---|---|---|
hide | false | conditionally hide with a javascript template |
color | rgba(0,0,0,0.3) | background color of the card |
device_name | “Set at” | text at bottom between humidity and setpoint |
alt_humidity_entity | null | a different device to get humidity value from |
alt_humidity_attr | null | attribute of the device to get humidity value from |
icon_mode_disabled | false | set this true to hide the idle icon for setpoint |
{item}_setpoint_{mode} | various | {item} is one of [color, text, icon] and mode is one of [off, idle, cool, heat, wait]; use to set background color, text color & icon for the setpoint for each of the operational modes |
I have the template and example yaml folded below for reference.
yaml for the template
#put this in your button_card_templates section of your dashboard (raw configuration)
bigtemp:
variables:
hide: false
color: 'rgba(0,0,0,0.3)'
device_name: Set at
alt_humidity_entity: null
alt_humidity_attr: null
color_setpoint_off: 'rgba(0,0,0,0.4)'
color_setpoint_idle: 'rgba(144,238,144,0.6)'
color_setpoint_cool: 'rgba(0,0,255,0.6)'
color_setpoint_heat: 'rgba(255,0,0,0.6)'
color_setpoint_wait: 'rgba(255,255,0,0.6)'
icon_setpoint_off: 'mdi:thermometer-off'
icon_setpoint_idle: null
icon_setpoint_cool: 'mdi:snowflake'
icon_setpoint_heat: 'mdi:fire'
icon_setpoint_wait: 'mdi:timer-sand'
text_setpoint_off: white
text_setpoint_idle: black
text_setpoint_cool: white
text_setpoint_heat: white
text_setpoint_wait: black
icon_mode_disabled: false
show_icon: true
icon: 'mdi:fan'
show_state: true
state_display: |-
[[[
return Math.trunc(entity.attributes.current_temperature).toString()+"°"
]]]
custom_fields:
device: |
[[[
return `<div style="line-height:1">${variables.device_name}</div>`;
]]]
humidity:
card:
type: 'custom:button-card'
show_icon: true
icon: 'mdi:water-percent'
show_name: false
show_state: true
state_display: |
[[[
if (entity.attributes.current_humidity)
return entity.attributes.current_humidity;
var alt = variables.alt_humidity_entity && states[variables.alt_humidity_entity];
var attr = alt && alt.attributes[variables.alt_humidity_attr];
return attr;
]]]
styles:
grid:
- grid-template-areas: '"s i"'
img_cell:
- display: contents
state:
- font-size: 0.8em
- align-self: flex-end
card:
- padding: 0
- padding-left: 2px
- background-color: 'rgba(0,0,0,0.6)'
icon:
- width: 18px
- height: 15px
- margin-top: '-4px'
- margin-left: '-4px'
- margin-right: '-3px'
mode:
card:
type: 'custom:button-card'
show_icon: true
show_name: false
show_state: false
icon: |
[[[
if(variables.icon_setpoint_idle || variables.icon_mode_disabled) return '';
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
case "heat":
case "heating":
return '';
default:
if (entity.attributes.hvac_mode == 3)
return '';
switch(entity.state){
case "heat":
return variables.icon_setpoint_heat;
case "cool":
return variables.icon_setpoint_cool;
}
}
]]]
styles:
card:
- background-color: transparent
icon:
- width: 18px
- color: white
setpoint:
card:
type: 'custom:button-card'
show_icon: true
show_name: true
show_state: true
state_display: |
[[[
return entity.attributes.temperature
? entity.attributes.temperature + "°"
: entity.attributes.target_temp_low
? entity.attributes.target_temp_low + "°"
: ''
]]]
name: |
[[[
return entity.attributes.target_temp_high
? entity.attributes.target_temp_high + "°"
: ''
]]]
icon: |
[[[
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
return variables.icon_setpoint_cool;
case "heat":
case "heating":
return variables.icon_setpoint_heat;
default:
if (entity.attributes.hvac_mode == 3)
return variables.icon_setpoint_wait;
return entity.state != "off"
? variables.icon_setpoint_idle
: entity.attributes.temperature
? ''
: variables.icon_setpoint_off
}
]]]
styles:
icon:
- width: 18px
- color: |
[[[
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
return variables.text_setpoint_cool;
case "heat":
case "heating":
return variables.text_setpoint_heat;
default:
if (entity.attributes.hvac_mode == 3)
return variables.text_setpoint_wait;
return entity.state == "off"
? variables.text_setpoint_off
: variables.text_setpoint_idle
}
]]]
state:
- font-size: 0.8em
- color: |
[[[
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
return variables.text_setpoint_cool;
case "heat":
case "heating":
return variables.text_setpoint_heat;
default:
if (entity.attributes.hvac_mode == 3)
return variables.text_setpoint_wait;
return entity.state == "off"
? variables.text_setpoint_off
: variables.text_setpoint_idle
}
]]]
name:
- font-size: 0.8em
- color: |
[[[
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
return variables.text_setpoint_cool;
case "heat":
case "heating":
return variables.text_setpoint_heat;
default:
if (entity.attributes.hvac_mode == 3)
return variables.text_setpoint_wait;
return entity.state == "off"
? variables.text_setpoint_off
: variables.text_setpoint_idle
}
]]]
card:
- padding: 0 2px
- background-color: |
[[[
switch(entity.attributes.hvac_action) {
case "cool":
case "cooling":
return variables.color_setpoint_cool;
case "heat":
case "heating":
return variables.color_setpoint_heat;
default:
if (entity.attributes.hvac_mode == 3)
return variables.color_setpoint_wait;
return entity.state == "off"
? variables.color_setpoint_off
: variables.color_setpoint_idle
}
]]]
state:
- id: value_any
operator: '!='
value: all
spin: true
styles:
card:
- background-color: '[[[ return variables.color || "transparent" ]]]'
- overflow: visible
- box-shadow: none
- padding: 2px 0 5px 2px
- display: '[[[ return variables.hide ? "none" : "flex" ]]]'
- width: fit-content
- margin-right: 15px
grid:
- display: contents
img_cell:
- display: contents
icon:
- width: 70%
- position: absolute
- left: 3px
- color: silver
- display: >-
[[[ return entity.attributes.fan_state &&
entity.attributes.fan_state == 1 ? "block" : "none" ]]]
state:
- color: var(--primary-text-color)
- font-size: 3.5em
- text-shadow: 0 0 2px black
- overflow: visible
- z-index: 1
- margin-top: '-10px'
name:
- color: var(--primary-text-color)
- text-shadow: 0 0 2px black
- overflow: visible
- font-size: 0.75em
- font-weight: 600
- position: absolute
- transform: rotate(90deg)
- transform-origin: right bottom
- bottom: 0
- right: 0
- z-index: 10
custom_fields:
device:
- text-shadow: 0 0 0.2em black
- overflow: visible
- font-size: 0.6em
- position: absolute
- bottom: 1px
- right: 28px
- z-index: 1
mode:
- position: absolute
- bottom: 18px
- right: 2px
setpoint:
- position: absolute
- bottom: 0
- right: 0
- z-index: 1
humidity:
- z-index: 2
- position: absolute
- bottom: 0
- left: 0
- display: |
[[[
return entity.attributes.current_humidity == undefined
&& !variables.alt_humidity_entity
? "none"
: "flex"
]]]
yaml for example 1
type: picture-elements
image: >-
https://beautifulcoolwallpapers.files.wordpress.com/2011/08/naturewallpaper.jpg
elements:
- type: 'custom:button-card'
template: bigtemp
entity: climate.upstairs
variables:
device_name: HVAC
style:
top: 30%
left: 30%
- type: 'custom:button-card'
template: bigtemp
entity: climate.downstairs
variables:
device_name: HVAC
style:
top: 30%
left: 70%
- type: 'custom:button-card'
template: bigtemp
entity: climate.freeze_protect
name: Outside
variables:
device_name: Run at
alt_humidity_entity: weather.home
alt_humidity_attr: humidity
color_setpoint_cool: 'rgba(255,255,0,0.6)'
icon_setpoint_cool: 'mdi:shield-alert'
text_setpoint_cool: green
icon_mode_disabled: true
style:
top: 70%
left: 30%
- type: 'custom:button-card'
template: bigtemp
entity: climate.pool_heater
name: Pool
variables:
device_name: Heater
hide: >-
[[[ return states["switch.filter_pump"].state == "off" ||
states["switch.spa_mode"].state == "on" ]]]
style:
top: 70%
left: 70%
yaml for example 2
type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: 'custom:button-card'
template: bigtemp
entity: climate.upstairs
variables:
color: 'rgba(255,0,0,0.5)'
device_name: HVAC
- type: 'custom:button-card'
template: bigtemp
entity: climate.downstairs
variables:
color: 'rgba(0,255,0,0.5)'
device_name: HVAC
- type: 'custom:button-card'
template: bigtemp
entity: climate.freeze_protect
name: Outside
variables:
color: 'rgba(0,0,255,0.5)'
device_name: Run at
alt_humidity_entity: weather.home
alt_humidity_attr: humidity
color_setpoint_cool: 'rgba(255,255,0,0.6)'
icon_setpoint_cool: 'mdi:shield-alert'
text_setpoint_cool: green
icon_mode_disabled: true
- type: horizontal-stack
cards:
- type: 'custom:button-card'
template: bigtemp
entity: climate.pool_heater
name: Pool
variables:
color: 'rgba(255,0,255,0.5)'
device_name: Heater
- type: 'custom:button-card'
template: bigtemp
entity: climate.spa_heater
name: Spa
variables:
color: 'rgba(0,255,255,0.5)'
device_name: Heater