I would like to share my current dashboard setup for a 2021 Volkswagen ID3.
I have used these integrations and lovelace plugins:
This setup features a lot of information at a first glance such as:
- Current Range left in the battery
- State of Charge (with a progress bar)
- State of Home Socket
- Power Consumption of Home Socket
- Information about charge given by the car
- Speed of Charge in km/h
- Power of Charge in kW
- Minutes until target SoC is reached
Even more details can be seen when clicking on different things:
-
Clicking on the picture of the car opens a more-info popup, showing a graph of the last 24hrs and a tooltip of the place where you’re hovering the mouse:
-
Clicking & Holding on the picture of the car opens a more-info popup of a graph of the last 24hrs tooltip of the place where you’re hovering the mouse:
-
Clicking on the speedometer icon opens a custom popup with some information as text and controls for the AC Charge Speed:
-
Clicking on the target icon opens a custom popup with some information as text and controls for the Target SoC:
It also allows a few controls:
- Toggle Home Socket
- Change speed of Charge
- Change Target SoC
A small detail that I added is in the button of the home socket.
In its on state it shows its state “on” and the power draw “(2176.3W)” in this case:
I didn’t like the fact, that when the socket was off it was showing “Off (0.0W)”, so I changed it to just “Off”, like this:
This is what the interaction looks like:
If you want to replicate this, be warned! The code is not very clean yet and there are a lot of templates and such.
I want to see the code, even if it's not clean
Code of the card
type: vertical-stack
cards:
- type: custom:button-card
show_name: true
show_icon: true
show_state: true
triggers_update:
- sensor.denim_flash_state_of_charge
- sensor.denim_flash_max_charge_current_ac
- sensor.denim_flash_range_in_kilometers
- sensor.denim_flash_target_state_of_charge
custom_fields:
range: |
[[[
return states['sensor.denim_flash_range_in_kilometers'].state+" "+states['sensor.denim_flash_range_in_kilometers'].attributes.unit_of_measurement
]]]
progress_bar_soc: P
progress_bar_soc_bg: P
progress_bar_red: P
target_soc:
card:
type: custom:button-card
color: var(--secondary-text-color)
show_name: false
styles:
card:
- box-shadow: none
icon: mdi:target
size: 26px
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Target State of Charge
style: >
--popup-min-width: 400px;
--popup-max-width: 600px;
--popup-border-width: var(--ha-card-border-width, 2px);
--popup-border-color: var(--ha-card-border-color,
var(--divider-color, #eee));
--popup-border-radius: var(--ha-card-border-radius);
--popup-background-color: var(--ha-card-background,
var(--card-background-color, white));
--popup-padding-x: 1vw;
--popup-padding-y: 20px;
content:
type: vertical-stack
cards:
- type: markdown
card_mod:
style: |
ha-card {
margin-top: -30px;
}
ha-markdown.no-header {
padding-left: 0;
padding-right: 0;
}
content: >-
For best battery life, please select a target SoC of 80%
or lower.
After selecting your target SoC, it can take up to 1
minute for it to update.
- type: horizontal-stack
cards:
- type: custom:button-card
template: soc_target
variables:
target: 50
- type: custom:button-card
template: soc_target
variables:
target: 60
- type: custom:button-card
template: soc_target
variables:
target: 70
- type: custom:button-card
template: soc_target
variables:
target: 80
- type: custom:button-card
template: soc_target
variables:
target: 90
text_color: var(--label-badge-red)
- type: custom:button-card
template: soc_target
variables:
target: 100
text_color: var(--label-badge-red)
ac_charge_speed:
card:
type: custom:button-card
color: var(--secondary-text-color)
show_name: false
entity: sensor.denim_flash_max_charge_current_ac
styles:
card:
- box-shadow: none
icon: mdi:speedometer-medium
state:
- value: unavailable
icon: mdi:speedometer-medium
- value: maximum
icon: mdi:speedometer
- value: reduced
icon: mdi:speedometer-slow
size: 26px
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: AC Charge speed
style: >
--popup-min-width: 400px;
--popup-max-width: 600px;
--popup-border-width: var(--ha-card-border-width, 2px);
--popup-border-color: var(--ha-card-border-color,
var(--divider-color, #eee));
--popup-border-radius: var(--ha-card-border-radius);
--popup-background-color: var(--ha-card-background,
var(--card-background-color, white));
--popup-padding-x: 1vw;
--popup-padding-y: 20px;
content:
type: vertical-stack
cards:
- type: markdown
content: >-
Allows you to select the speed of charge on AC Chargers
only.
After selecting your AC Charge speed, it can take up to
1 minute for it to update.
card_mod:
style: |
ha-card {
margin-top: -30px;
}
ha-markdown.no-header {
padding-left: 0;
padding-right: 0;
}
- type: horizontal-stack
cards:
- type: custom:button-card
template: ac_charge_speed
variables:
speed: reduced
- type: custom:button-card
template: ac_charge_speed
variables:
speed: maximum
hold_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Range History
style: >
--popup-min-width: 400px;
--popup-max-width: 600px;
--popup-border-width: var(--ha-card-border-width, 2px);
--popup-border-color: var(--ha-card-border-color,
var(--divider-color, #eee));
--popup-border-radius: var(--ha-card-border-radius);
--popup-background-color: var(--ha-card-background,
var(--card-background-color, white));
--popup-padding-x: 1vw;
--popup-padding-y: 20px;
content:
type: custom:apexcharts-card
apex_config:
tooltip:
x:
show: true
format: HH:mm dd/MM/yyyy
xaxis:
tooltip:
enabled: false
series:
- entity: sensor.denim_flash_range_in_kilometers
curve: stepline
stroke_width: 2
name: Range
unit: km
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: State of Charge History
style: >
--popup-min-width: 400px;
--popup-max-width: 600px;
--popup-border-width: var(--ha-card-border-width, 2px);
--popup-border-color: var(--ha-card-border-color,
var(--divider-color, #eee));
--popup-border-radius: var(--ha-card-border-radius);
--popup-background-color: var(--ha-card-background,
var(--card-background-color, white));
--popup-padding-x: 1vw;
--popup-padding-y: 20px;
content:
type: custom:apexcharts-card
apex_config:
tooltip:
x:
show: true
format: HH:mm dd/MM/yyyy
xaxis:
tooltip:
enabled: false
series:
- entity: sensor.denim_flash_state_of_charge
curve: stepline
stroke_width: 2
name: State of Charge
unit: '%'
layout: icon_name_state2nd
entity: sensor.denim_flash_range_in_kilometers
name: State of Charge
state_display: |
[[[
return states['sensor.denim_flash_state_of_charge'].state+" "+states['sensor.denim_flash_state_of_charge'].attributes.unit_of_measurement;
]]]
styles:
card:
- pointer-events: inherit
custom_fields:
target_soc:
- position: absolute
- bottom: 34px
- right: 12px
- box-shadow: none
ac_charge_speed:
- position: absolute
- bottom: 70px
- right: 12px
- box-shadow: none
range:
- font-size: 3rem
- font-weight: 200
- padding-top: 20px
progress_bar_soc:
- position: absolute
- bottom: 20px
- box-sizing: content-box
- background-color: var(--label-badge-blue)
- color: blue
- font-size: 0px
- height: 2px
- width: >-
[[[return
"calc("+states['sensor.denim_flash_state_of_charge'].state+"%"+" -
("+ states['sensor.denim_flash_state_of_charge'].state /100+"
*3rem)"]]]
- z-index: 1
- margin: 0 1.5rem
- justify-self: start
progress_bar_soc_bg:
- position: absolute
- bottom: 20px
- box-sizing: content-box
- background-color: var(--label-badge-blue)
- color: blue
- opacity: 30%
- font-size: 0px
- height: 2px
- width: calc(80% - ( 0.8 * 3rem))
- margin: 0 1.5rem
- justify-self: start
progress_bar_red:
- position: absolute
- bottom: 20px
- box-sizing: content-box
- background-color: var(--label-badge-red)
- color: blue
- opacity: 50%
- font-size: 0px
- height: 2px
- width: calc(20% - ( 0.2 * 3rem))
- margin: 0 1.5rem
- justify-self: right
name:
- font-size: 0.9em
- justify-self: start
- padding-left: 1.5rem
- margin-top: 0.5rem
state:
- font-weight: bold
- font-size: 1.5rem
- justify-self: start
- padding-left: 1.5rem
entity_picture:
- width: 90%
- transform: scaleX(-1)
grid:
- grid-template-areas: >-
"range range range" "i i i" "n n n" "s s s" "progress_bar_soc
progress_bar_soc_bg progress_bar_soc_bg" "l l l"
- grid-template-columns: 1fr
- grid-template-rows: 1fr
- gap: 10px
entity_picture: /local/vw_id3.png
show_entity_picture: true
- type: vertical-stack
cards:
- type: custom:button-card
tap_action:
action: toggle
hold_action:
action: more-info
entity: switch.grid
layout: icon_name_state2nd
show_state: true
name: Home Socket
triggers_update:
- sensor.denim_flash_plug_power
- switch.grid
icon: |
[[[
if (entity.state === "on")
return "mdi:flash";
else
return "mdi:flash-off";
]]]
state_display: |
[[[
if (entity.state === "on")
if (states['sensor.denim_flash_plug_power'].state > 0)
return "On (" + states['sensor.denim_flash_plug_power'].state + " W)";
else
return "On";
else
return "Off";
]]]
styles:
name:
- font-size: 0.9em
state:
- font-weight: bold
- font-size: 1.1em
icon:
- width: 20%
grid:
- gap: 10px
- type: conditional
conditions:
- entity: sensor.denim_flash_charging_state
state: charging
card:
show_name: true
show_icon: false
type: custom:button-card
custom_fields:
charge_rate: |
[[[
return states['sensor.denim_flash_charge_rate'].state+" "+states['sensor.denim_flash_charge_rate'].attributes.unit_of_measurement
]]]
charge_power: |
[[[
return states['sensor.denim_flash_charge_power'].state+" "+states['sensor.denim_flash_charge_power'].attributes.unit_of_measurement
]]]
charge_eta: |
[[[
return states['sensor.denim_flash_remaining_charging_time'].state+" "+states['sensor.denim_flash_remaining_charging_time'].attributes.unit_of_measurement
]]]
tap_action:
action: none
layout: icon_name_state2nd
name: Charging
styles:
card:
- pointer-events: inherit
name:
- font-size: 0.9em
- justify-self: center
- align-self: center
- text-align: center
- font-weight: 500
- font-size: 1.5rem
grid:
- grid-template-areas: >-
"n n n" "range range range" "i i i" "charge_rate charge_power
charge_eta"
- grid-template-columns: repeat(3, 1fr)
- grid-template-rows: 1fr
- gap: 10px
view_layout:
grid-area: car
card_mod:
style: |
hui-vertical-stack-card {
max-width: 500px;
}
Button Card Templates
button_card_templates:
ac_charge_speed:
variables:
speed: maximum
entity: sensor.denim_flash_max_charge_current_ac
vin: YOUR_VIN
text_color: var(--primary-text-color)
name: >-
[[[ return variables.speed.charAt(0).toUpperCase() +
variables.speed.slice(1)]]]
show_name: true
show_icon: false
entity: sensor.denim_flash_max_charge_current_ac
tap_action:
action: call-service
service: volkswagen_we_connect_id.volkswagen_id_set_ac_charge_speed
service_data:
vin: '[[[ return variables.vin ]]]'
maximum_reduced: '[[[ return variables.speed ]]]'
hold_action:
action: more-info
state:
- value: '[[[ return variables.speed ]]]'
styles:
name:
- color: var(--primary-background-color)
card:
- background-color: var(--paper-item-icon-active-color)
styles:
card:
- box-shadow: 1px 1px 5px 0px var(--secondary-background-color)
- padding: 0
- height: auto
- padding: 0.85rem 0
name:
- color: '[[[ return variables.text_color ]]]'
- font-weight: bold
- font-size: 1rem
soc_target:
variables:
target: 50
text_color: var(--primary-text-color)
name: '[[[ return variables.target + "%" ]]]'
show_name: true
show_icon: false
entity: number.denim_flash_target_state_of_charge
tap_action:
action: call-service
service: number.set_value
service_data:
value: '[[[ return variables.target ]]]'
entity_id: number.denim_flash_target_state_of_charge
hold_action:
action: more-info
state:
- value: '[[[ return variables.target ]]]'
styles:
name:
- color: var(--primary-background-color)
card:
- background-color: var(--paper-item-icon-active-color)
styles:
card:
- box-shadow: 1px 1px 5px 0px var(--secondary-background-color)
- height: auto
- padding: 0.85rem 0
name:
- color: '[[[ return variables.text_color ]]]'
- font-weight: bold
- font-size: 1rem
To-do:
- Code cleanup
- Add AC controls
If you have any feedback or ideas on what I should add, it would be greatly appreciated