Hi
I don’t know how you did it…
it doesn’t work for me or state.
or the time will be NaN:NaN
I have already released the location because it only places it in the original location, not where the circle is.
I can ask for help or the final code.
Hi
I don’t know how you did it…
it doesn’t work for me or state.
or the time will be NaN:NaN
I have already released the location because it only places it in the original location, not where the circle is.
I can ask for help or the final code.
hi @HACSSYSTEM
i’m happy to help out if you have issues but I can’t understand what you are saying.
can you provide the yaml and some screenshots that outline what your issue is?
I have posted a kitchen timer card that might help, depending on what you are trying to do.
I’ve tried searching but wasn’t able to find a definitive answer in this thread. Does the fanart for conditional media cards work with Google TV / Chromecast? I realize the conditional media data isn’t available with the android TV integration, but it is with the cast integration. However, the background image comes through as
background: url("undefined") center center / cover no-repeat rgba(115, 115, 115, 0.2);
The “Plex Recently Added” does work however.
Is there a workaround or have I missed some variables that need to be changed?
I think @Laffer has a shield, and he has made his config public. You could look at how he has set up conditional media cards with his shield. see this link
I don’t have google TV so I can assist you more but I can’t think of why it would not work, but it would depend on the app you have open.
I have added a custom background under background-image in button_card_templates/media.yaml
I show a custom Nintendo Switch image
- background-image: &media_background_image >
[[[
if (entity) {
if (variables.is_youtube) {
return `url(${states[this._config?.triggers_update].state})`;
} else if (variables.state === 'Nintendo Switch') {
return `url("/local/img/Switch.jpeg")`;
} else {
let data = entity.attributes.data;
return data && (data[variables.i].fanart || data[variables.i].poster)
? `url("${data[variables.i].fanart}"), url("${data[variables.i].poster}")`
: `url("${variables.entity_picture}")`;
}
}
]]]
I too would like the code for this icon please.
The thing I’m not understanding is where data[variables.i].fanart
comes from. Is that an attribute of the apple tv integration? Does it come from Plex Recently Added or is there another sensor / integration that needs to be installed? I’m under the impression that the Plex Recently Added integration is fairly new in the configuration.
Edit: BTW all the media being played is through plex on any device. I’d be perfectly happy if it worked just with plex.
the Plex Recently Added integration has been in uPreformatted text
se for well over a year, just changed dev recently.
Plex Recently Added should have nothing to do with what is currently playing.
this line is an if statement
return data && (data[variables.i].fanart || data[variables.i].poster)
? `url("${data[variables.i].fanart}"), url("${data[variables.i].poster}")`
: `url("${variables.entity_picture}")`;
it read like so
if we have data (data is the entity attributes)
and
if that data has an attribute called fanart or poster (Eg Plex recently added)
then use a url that consists of the fanart and poster
if we dont have any data
or
if we dont have an attribute called fanart or poster
then use the variables.entity_picture (set is base as entity.attributes.entity_picture)
so in short, if you dont have an entity_picture attribute you won’t have a background.
looking into @Laffer setup he has this
- type: conditional
conditions:
- entity: select.conditional_media
state: SHIELD
card:
type: custom:button-card
entity: sensor.shield_real_state
template:
- conditional_media
- icon_nvidia_shield
- media_volume
variables:
player: '[[[ return entity.attributes.player; ]]]'
entity_picture: sensor.active_media_players
volume_control: media_player.denon_receiver
triggers_update:
- sensor.active_media_players
see this line entity_picture: sensor.active_media_players
looks like he is setting a custom entity_picture like so
# SENSOR - CONDITIONAL MEDIA BACKGROUND
- unique_id: active_media_players
name: 'Active Media Players'
state: >
{% set media_players = [
states.media_player.apple_tv_1,
states.media_player.apple_tv_2,
states.sensor.shield_real_state,
states.media_player.plex_plex_for_windows_sagasdesktop
] %}
{{ media_players | selectattr('state','search','(playing|paused)') | list | count }}
attributes:
active: >
{% set media_players = [
states.media_player.apple_tv_1,
states.media_player.apple_tv_2,
states.sensor.shield_real_state,
states.media_player.plex_plex_for_windows_sagasdesktop
] %}
{%- set media_players_playing = media_players | selectattr('state','eq','playing') | list %}
{%- set media_player_id_playing = media_players_playing | map(attribute='entity_id') | join(', ') %}
{%- set media_players_paused = media_players | selectattr('state','eq','paused') | list %}
{%- set media_player_id_paused = media_players_paused | map(attribute='entity_id') | join(', ') %}
{%- if (media_players_playing | length > 0) -%}
{{ media_player_id_playing }}
{%- elif (media_players_paused | length > 0) -%}
{{ media_player_id_paused }}
{%- endif -%}
app: >
{%- if this.state not in ['unavailable','undefined','unknown','none','null', '0'] %}
{% set players = (state_attr('sensor.active_media_players', 'active')).split(', ') %}
{% if players[0] is defined %}
{% if 'plex' in players[0] %}
plex
{% else %}
{% set app = state_attr(players[0], 'app_name') | lower %}
{% if app not in ['unavailable','undefined','unknown','none','null'] %}
{{ app }}
{% else %}
{% set app = state_attr(players[0], 'app_id') | lower %}
{% if app not in ['unavailable','undefined','unknown','none','null'] %}
{{ app }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
media_title: >
{%- if this.state not in ['unavailable','undefined','unknown','none','null', '0'] %}
{% set players = (state_attr('sensor.active_media_players', 'active')).split(', ') %}
{% if players[0] is defined %}
{% if 'plex' in players[0] or state_attr('sensor.active_media_players', 'app') == 'plex' %}
{% if state_attr(players[0], 'media_content_type') == 'tvshow' %}
{{state_attr(players[0], 'media_series_title')}} - {{state_attr(players[0], 'media_title')}}
{% else %}
{{state_attr(players[0], 'media_title')}}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
media_content_type: >
{% if this.state not in ['unavailable','undefined','unknown','none','null', '0'] %}
{% set players = (state_attr('sensor.active_media_players', 'active')).split(', ') %}
{% if players[0] is defined %}
{% if 'plex' in players[0] or state_attr('sensor.active_media_players', 'app') == 'plex' %}
{% if state_attr(players[0], 'media_content_type') %}
{{ state_attr(players[0], 'media_content_type') }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
entity_picture: >
{%- if this.state not in ['unavailable','undefined','unknown','none','null', '0'] %}
{%- set players = (state_attr('sensor.active_media_players', 'active')).split(', ') %}
{% if players[0] is defined %}
{%- set entitypic = state_attr(players[0],'entity_picture') %}
{%- set app = state_attr('sensor.active_media_players','app') | lower %}
{%- if app is defined %}
{% if 'plex' in app %} /local/images/Plex_bg.png
{% elif 'infuse' in app %} /local/images/Plex_bg.png
{% elif 'com.apple.tvwatchlist' in app %} /local/images/ATVPlus_bg.jpg
{% elif 'airplay' in app %} /local/images/AirPlay_bg.jpg
{% elif 'com.amazon' in app %} /local/images/AmazonPrime_bg.jpg
{% elif 'disneyplus' in app %} /local/images/dp_bg.jpg
{% elif 'youtube' in app %} /local/images/yt_bg.jpg
{% elif 'tv2' in app %} /local/images/tv2play_bg.jpg
{% elif 'hbo' in app %} /local/images/HBOMax_bg.jpg
{% elif 'netflix' in app %} /local/images/netflix_bg.jpg
{% elif 'nrk' in app %} /local/images/nrk_bg.jpg
{% elif 'viasat' in app %} /local/images/ViaPlay_bg.jpg
{% elif 'viaplay' in app %} /local/images/ViaPlay_bg.jpg
{% elif 'viafree' in app %} /local/images/ViaFree_bg.jpg
{% elif 'kanal5' in app %} /local/images/discovery_bg.jpg
{% elif 'twitch' in app %} /local/images/twitch_bg.jpg
{% else %} null
{% endif %}
{%- elif 'plex' in players %}
{{ '/local/images/Plex_bg.png' }}
{%- endif %}
{%- endif %}
{%- endif %}
# SENSOR - SHIELD REAL STATE
- unique_id: shield_real_state
name: 'SHIELD Real State'
state: >
{% set players = [
states.media_player.plex_plex_for_android_tv_shield_android_tv,
states.media_player.shield
] %}
{% if players | selectattr('state','eq','playing') | list | count >= 1 %}
playing
{% elif players | selectattr('state','eq','paused') | list | count >= 1 %}
paused
{% elif players | selectattr('state','eq','idle') | list | count >= 1 %}
idle
{% else %}
off
{% endif %}
attributes:
player: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set app = state_attr('media_player.shield', 'app_name') %}
{%- if app is defined %}
media_player.shield
{% endif %}
{% endif %}
app_name: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set app = states.media_player.shield.attributes.app_name %}
{%- if app is defined %}
{%- if app != '' and app not in ['unknown','unavailable','none','off'] %}
{{ app | lower }}
{% endif %}
{% else %}
plex
{% endif %}
{% endif %}
app_id: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set app = states.media_player.shield.attributes.app_id %}
{%- if app is defined %}
{%- if app != '' and app not in ['unknown','unavailable','none','off'] %}
{{ app }}
{% endif %}
{% else %}
plex
{% endif %}
{% endif %}
entity_picture: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set current_app = states.sensor.shield_real_state.attributes.app_name %}
{% set picture = states.media_player.plex_plex_for_android_tv_shield_android_tv.attributes.entity_picture %}
{%- if picture is defined %}
{%- if picture != '' and picture not in ['unknown','unavailable','none'] %}
{%- if current_app is defined and current_app == 'plex' %}
{{- '/local/images/Plex_bg.png' if current_app == 'plex' else picture -}}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
media_artist: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set artist = states.media_player.shield.attributes.media_artist %}
{%- if artist is defined %}
{%- if artist != '' and artist not in ['unknown','unavailable','none'] %}
{{ artist }}
{% endif %}
{% endif %}
{% endif %}
media_title: >
{% if states.sensor.shield_real_state.state | lower not in ['unknown','unavailable','none','off'] %}
{% set media_title = states.media_player.shield.attributes.media_title %}
{%- if media_title is defined %}
{%- if media_title != '' and media_title not in ['unknown','unavailable','none'] %}
{{ media_title }}
{% endif %}
{% endif %}
{% endif %}
media_content_type: >
{% if this.state not in ['unavailable','undefined','unknown','none','null', '0'] %}
{% set app = state_attr('sensor.shield_real_state', 'app_name') %}
{% if app is defined and app == 'plex' %}
{% if state_attr('media_player.plex_plex_for_android_tv_shield_android_tv', 'media_content_type') %}
{{ state_attr('media_player.plex_plex_for_android_tv_shield_android_tv', 'media_content_type') }}
{% endif %}
{% endif %}
{% endif %}
So, the trick here is that the plex integration is required, and the plex media player entity must be used. Given that, the default config from Mattias works fine.
yes that will work when watching Plex, however, not only will you not get any image when using the shield for anything else, you also won’t get any info at all.
I would recommend following the approach @Laffer used and set the entity_picture to the entity_picture from Plex when the plex app is open on the shield.
I’m definitely going to look into that, however, the entity picture has been unreliable at best with the android tv integration (which doesn’t return media info, only app being used) and nonexistent with the cast integration. 99%+ of my viewing is with plex, so this is a pretty nice fit. I’ll probably alter the data being displayed, but the only other thing I’m planning is integrating a ps5 game image from sensor.ps5_activity.
Edit: got the PS5 sensor integrated
Hello,
I’ve been on HA for a while now and I’m trying to set up my dashboard correctly (the most complicated part for me ). Before I get into it, I’m wondering how you manage your other dashboards with this one.
I already have a dashboard for my phone and one for my computer and I would like to keep them in place while adding this one for my tablets.
I would like to know more about this…
Thanks in advance
Im using a USG, is there anyway to adapt your unifi router package to grab some info from it?
Since I have several devices for the “living room”, I wanted a swipe card here. Unfortunately, the layout of the first page does not fit. the second side, on the other hand, fits. What is wrong? Please help
- type: grid
title: Wohnzimmer
view_layout:
grid-area: vardagsrum
columns: 1
cards:
- type: custom:swipe-card
parameters:
speed: 550
spaceBetween: 40
threshold: 5
cards:
- type: grid
columne: 2
cards:
- type: custom:button-card
entity: light.deckenspots
name: Deckenspots
template:
- light
- icon_hue
- type: custom:button-card
entity: light.tischbeleuchtung_gruppe
name: 5 Freunde
template:
- light
- icon_shade
- type: custom:button-card
entity: media_player.samsung_frame_series_65
name: Tv
state_display: >
[[[
if (variables.state === 'playing') {
return 'På';
}
if (variables.state === true) {
return variables.translate_unknown;
}
]]]
double_tap_action:
!include popup/vardagsrum_tv.yaml
template:
- base
- icon_tv
- loader
- type: custom:button-card
entity: light.candela_wohnzimmer
name: Candela
double_tap_action:
!include popup/vardagsrum_balkong.yaml
template:
- base
- icon_hue
- loader
- type: grid
columns: 2
cards:
- type: custom:button-card
entity: media_player.vardagsrum
triggers_update: sensor.youtube_watching
name: Vardagsrum
template:
- media
- icon_apple_tv
- type: custom:button-card
entity: media_player.sovrum
triggers_update: sensor.youtube_watching
name: Sovrum
template:
- media
- icon_apple_tv
- type: custom:button-card
entity: media_player.spotify
name: Spotify
template:
- media
- icon_spotify
- type: custom:button-card
entity: media_player.kok
name: Nest Mini
template:
- media
- icon_nest_mini
try it with columns not columne
ui.yaml:
- type: custom:button-card
entity: timer.5min
name: Kert
tap_action:
action: call-service
service: timer.start
service_data:
entity_id: timer.5min
double_tap_action:
action: call-service
service: timer.cancel
service_data:
entity_id: timer.5min
template:
- base
- desk
- icon_christmas
custom_fields:
countdown: |
[[[
setTimeout(() => {
let elt = this.shadowRoot,
circle_stroke = elt.getElementById('circle_stroke'),
r = 22.1,
c = r * 2 * Math.PI,
now = new Date().getTime(),
endDate = new Date(entity.attributes.finishes_at),
remaining = entity.attributes.remaining.split(':'),
duration = entity.attributes.duration.split(':'),
startDate = new Date(endDate.getTime() - (remaining[0]*3600+remaining[1]*60)*1000),
percent = ((now - startDate) / (endDate - startDate)) * 100;
circle_stroke.style.strokeDashoffset = c - percent / 100 * c;
circle_stroke.style.strokeWidth = 1;
}, 0);
let r = 22.1,
c = r * 2 * Math.PI,
state = variables.state_on,
input = variables.circle_input || ' ',
input_text = new Date(entity.attributes.finishes_at),
hours = input_text.getHours(),
minutes = input_text.getMinutes();
return `
<svg viewBox="0 0 50 50">
<style>
circle {
transform: rotate(-90deg);
transform-origin: 50% 50%;
stroke-dasharray: ${c};
stroke-dashoffset: ${typeof input === 'number' && c - input / 100 * c};
stroke-width: 2.3;
stroke = variables.state === 'active' || variables.state === 'idle' ? '#b51a00' : 'none',
fill = variables.state === 'active' || variables.state === 'idle' ? 'rgba(255,255,255,0.04)' : 'none';
}
#circle_stroke{
stroke: #b0b0b0;
fill: none;
}
#circle_bg {
stroke: none;
fill: none;
}
text {
font-size: 14px;
font-weight: var(--c-font-weight);
letter-spacing: var(--c-letter-spacing);
fill: #97989c;
}
tspan {
font-size: 10.5px;
}
#circle_value, tspan {
text-anchor: middle;
dominant-baseline: central;
}
</style>
<circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
<circle id="circle_bg" cx="25" cy="25" r="${r}"/>
<text id="circle_value" x="50%" y="52%">${hours}:${minutes}</tspan></text>
</svg> `;
]]]
styles:
custom_fields:
countdown:
- display: initial
- width: 88%
- margin: -3% 2% 0 0
- justify-self: end
- opacity: 1
Start display:
91 / 5 000
star_border
Thank you very much for your help if you can. There was a post like this before, but I couldn’t find a definitive one.
Hello, I have searched but not found an answer.
Is it possible to add sensor data in grid title?
- type: grid
title: Hall {{ states.sensor.room_temperature_sensor.state }}°C
In short: No…
The slightly longer answer is that it is probably possible with a workaround
I have described a method here to make the Titles their own separate button, which can then contain about any text you want.
Keep in mind, the code is for a year old version of this dashboard, and won’t look correct on the latest version, so some manual tweaking would be needed, but the general idea is the same…
A vertical stack card or other type of grid, containing a button card (title) and the grid (for the 4 cards below the title)
its still not clear what your issue is, I’m assuming that you would like to remove the NaN:NaN when the timer is not running, if so try this
- type: custom:button-card
entity: timer.5min
name: Kert
tap_action:
action: call-service
service: timer.start
service_data:
entity_id: timer.5min
double_tap_action:
action: call-service
service: timer.cancel
service_data:
entity_id: timer.5min
template:
- base
- desk
- icon_christmas
custom_fields:
countdown: |
[[[
setTimeout(() => {
let elt = this.shadowRoot,
circle_stroke = elt.getElementById('circle_stroke'),
r = 22.1,
c = r * 2 * Math.PI,
now = new Date().getTime(),
endDate = new Date(entity.attributes.finishes_at),
remaining = entity.attributes.remaining.split(':'),
duration = entity.attributes.duration.split(':'),
startDate = new Date(endDate.getTime() - (remaining[0]*3600+remaining[1]*60)*1000),
percent = ((now - startDate) / (endDate - startDate)) * 100;
circle_stroke.style.strokeDashoffset = c - percent / 100 * c;
circle_stroke.style.strokeWidth = 1;
}, 0);
let r = 22.1,
c = r * 2 * Math.PI,
state = variables.state_on,
input = variables.circle_input || ' ',
input_text = new Date(entity.attributes.finishes_at),
hours = input_text.getHours(),
minutes = input_text.getMinutes();
return !state ? ‘’ :
<svg viewBox="0 0 50 50">
<style>
circle {
transform: rotate(-90deg);
transform-origin: 50% 50%;
stroke-dasharray: ${c};
stroke-dashoffset: ${typeof input === 'number' && c - input / 100 * c};
stroke-width: 2.3;
stroke = variables.state === 'active' || variables.state === 'idle' ? '#b51a00' : 'none',
fill = variables.state === 'active' || variables.state === 'idle' ? 'rgba(255,255,255,0.04)' : 'none';
}
#circle_stroke{
stroke: #b0b0b0;
fill: none;
}
#circle_bg {
stroke: none;
fill: none;
}
text {
font-size: 14px;
font-weight: var(--c-font-weight);
letter-spacing: var(--c-letter-spacing);
fill: #97989c;
}
tspan {
font-size: 10.5px;
}
#circle_value, tspan {
text-anchor: middle;
dominant-baseline: central;
}
</style>
<circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
<circle id="circle_bg" cx="25" cy="25" r="${r}"/>
<text id="circle_value" x="50%" y="52%">${hours}:${minutes}</tspan></text>
</svg> `;
]]]
styles:
custom_fields:
countdown:
- display: initial
- width: 88%
- margin: -3% 2% 0 0
- justify-self: end
- opacity: 1
there is only 1 return in the above code so I can’t understand what the issue was.
NOTE: the above code is not tested and may not work, I don’t have access to my home assistant currently
I’m trying a lot to get the last horizontal-stack to be aligned to the bottom of the sidebar, but no luck so far.
Tried making it a seperate grid idem, ( sidebar2) etc but no luck. Noting changes and stays always stuck to the weather card.
any idea’s?
views:
- type: custom:grid-layout
title: Home
layout:
#default
margin: 0
grid-gap: var(--custom-layout-card-padding)
grid-template-columns: repeat(4, 1fr) 0
grid-template-rows: 0 repeat(2, fit-content(100%)) 0fr
grid-template-areas: |
"sidebar . . . ."
"sidebar woonkamer leefkeuken bios ."
"sidebar media övrigt övrigt ."
"sidebar footer footer footer ."
mediaquery:
#phone
"(max-width: 800px)":
grid-gap: calc(var(--custom-layout-card-padding) * 1.7)
grid-template-columns: 0 repeat(2, 1fr) 0
grid-template-rows: 0 repeat(5, fit-content(100%)) 0fr
grid-template-areas: |
". . . ."
". sidebar sidebar ."
". woonkamer bios ."
". leefkeuken övrigt ."
". media tuin ."
". footer footer ."
". . . ."
#portrait
"(max-width: 1200px)":
grid-gap: var(--custom-layout-card-padding)
grid-template-columns: repeat(3, 1fr) 0
grid-template-rows: 0 repeat(3, fit-content(100%)) 0fr
grid-template-areas: |
"sidebar . . ."
"sidebar woonkamer bios ."
"sidebar leefkeuken övrigt ."
"sidebar media tuin ."
"sidebar footer footer ."
"sidebar . . ."
cards:
#extra_styles fix, do not remove
#also warn if theme is not set
- type: custom:button-card
view_layout:
grid-area: 1 / 2 / 2 / 5
name: SET THEME TO "tablet" IN PROFILE
tap_action:
action: navigate
navigation_path: /profile
styles:
card:
- display: >
[[[
return hass.themes.theme === 'tablet'
? 'none'
: 'initial';
]]]
name:
- z-index: 1
- overflow: visible
- color: red
- font-weight: bolder
- font-size: xxx-large
- background: yellow
#################################################
# #
# SIDEBAR #
# #
#################################################
- type: custom:layout-card
view_layout:
grid-area: sidebar
layout_type: grid
layout:
grid-template-columns: 5% 90% 5%
grid-template-rows: fit-content(400px) fit-content(400px) 1fr
grid-template-areas: |
"left center right"
cards:
# - type: custom:vertical-stack-in-card
- type: custom:layout-card
view_layout:
grid-area: center
mode: vertical
cards:
- type: custom:button-card
entity: sensor.template_sidebar
template: sidebar
- type: custom:simple-weather-card
entity: weather.thuis
name: ' '
custom:
- temp: sensor.wupws_temp
- precipitation: sensor.wupws_preciptotal
secondary_info:
- precipitation
card_mod:
style: |
ha-card {
width: 250px !important;
--primary-text-color: #6a7377;
}
- type: horizontal-stack
layout_type: horizontal
cards:
- type: picture-entity
entity: person.tim
image: /local/timkleur2.png
tap_action:
!include popup/tim.yaml
show_name: false
show_state: false
state_filter:
"home": grayscale(30%)
"not_home": grayscale(90%)
style: |
ha-card {
transform: scale(0.6,0.6)
}
- type: picture-entity
entity: person.mieke
image: /local/miekekleur2.png
show_name: false
show_state: false
tap_action:
!include popup/mieke.yaml
state_filter:
"home": grayscale(30%)
"not_home": grayscale(90%)
style: |
ha-card {
transform: scale(0.6,0.6)
}
[quote=“masoncrawford1994, post:4390, topic:162594”]
there is only 1 return in the above code so I can’t understand what the issue was.
NOTE: the above code is not tested and may not work, I don’t have access to my home assistant currently
Did you try to place it in space?
style:
left: 21.1%.
top: 72.2%