there is a jinja template card that does the same thing as my config-template-card. with jinja though, each time you use it, you create a new websocket connection to the backend to render your templates, while javascript is all client side
Thatâs probably why Thomas said âJinja comes at costâ⌠Thanks for the explanation!
Does it mean that any card that supports Jinja templates does that and itâs impossible to create a lightweight custom card with Jinja templates?
Doubt it is impossible, but I donât know of anyone doing it
Hi Ian,
this was never explained anywhere, and might be such valuable information!
Could it be that these websocket connections, (which for some appear very frequently in the logs without further explanation) cause timing issues in the I/O for Ha? I am searching for over 2 years now to find cause for these errors, and even more importantly, to find the origin of the timing issues causing Hue lights/sensors to go unavailable.
Iâve always been steered at finding other integrations the âhammer the hubâ, and havent been able to find them⌠this however might very well be possible in my setup, since I use these template sensors quite often throughout the setup, and have more than a couple of Markdown cards eg that use these jinja templates.
using websocket: debug in the logger doesnât help much, so if you could say anything more on this subject, it would be very much appreciated.
extra question: would using jinja cards in Lovelace cause this websockets also even if not on the actual view where the card is used? Ive always believed only the load of the current view would be calculated in LL. (thatâs why I dont have template cards on my Hue viewâŚ) still lights go unavailable regularly, so maybe the LL cards with jinja add to that, even though not in view at the time? could that be?
Did you just simply check the load of the machine where home assistant is running? Is it a raspberry pi?
Stuff like top
/htop
, iotop
should help in this case. If you cpu is maxed out (or if your load average is too high), no wonder you have issues.
Using jinja (in the frontend) just creates more load on the system where HA is running and will be less fast than javascript (in the frontend) but doesnât create I/O on the disk/sdcard of the system where HA is running.
weâre going a bit off topic here but can you roughly explain whatâs the difference?
As Ian said, to use Jinja templates web socket connections are used so I understand why it increases load on the machine running HA.
Whatâs happening when we use JS templates?
Edited my question to avoid unnecessary confusion.
What exactly do you âneedâ to hear? Both Ian and Romrider (devs) have said it is so⌠what more do you need to hear? Certainly I have never heard js was better than ninja as itâs never previously been stated that I can remember but them saying it is good enough for me and means Iâm not switching from us any time soon in the frontend.
Iâve always learned (back in the days when starting with custom-ui, see home-assistant-custom-ui/docs/templates.md at 5274c9b1e51d8a4ba409cbf510d286472d42c328 ¡ andrey-git/home-assistant-custom-ui ¡ GitHub) that jinja is backend server side, and js is frontend browser side. As is stated by both Romrider and Ian here. no confusion on that.
What was new to me now, was the Ian above stated that Lovelace cards create web sockets to the backend, and, added to that, Lovelace cards with Jinja (only a few around) add to the load.
Not sure if I understand Romrider correctly here, but he seems to state that is not the case ? :
Anyways, my question here was if these Lovelace cards with Jinja, cause traffic, even if they are not in the current view. JS cards are computed per view, they are frontend browser side templates, but these Lovelace cards using Jinja are using backend server side computingâŚ
I am running HA on a Rpi4 4Gb mem, and it is never maxed out, though never as low as I see fellow members report back. Lets say between 5-20% roughly.
Since the latest beta version of custom card (getting back to topic here ) Iâve noticed a significantly better responsiveness of my views with buttons. For me that indicates Frontend and backend are tightly knit together. As I have reported since starting using Lovelace: refreshing Lovelace causing Hue lights to go âunavailableâ.
It could also be the reason eg @mayker 's Custom Header, which I use extensively with templates, adds to the load, simply because it uses Jinja. Not sure if CH could be made using JSâŚ
So I am very glad with this new beta Button card, each step taking out processor strain, is one step closer to an optimal systemâŚ
Is the spin: true working for anyone else? If so what is your config?
The latest beta of button-card just doesnât refresh any time any entity is updated. Say you have an entity that is updated every second (or in your thousand entity, some of them are updated creating an average of 1 update/sec):
- With the current button-card: all the buttons of the view are re-rendered every time (compute intensive on the frontend, ie. your browser)
- With the beta button card: only the entities that are part of the button triggers a render of the button
Which means that instead of refreshing all the buttons 1 time per sec, it might not do anything because no button needs an update because no entity in your displayed buttons did actually need an update. Which in the end means that the frontend is way more responsive (and this is what you see )
No if a card is not in the current view, it wonât do anything.
This is what happens when you have a jinja card:
- I have a jinja template
- card request the backend through the websocket to evaluate the template
- backend evaluates the template
- backend sends back the result over the websocket
- card takes the result and does something with it
For javascript everything happens in the browser:
- Card has some javascript templates
- browser evaluates the javascript (donât forget the whole frontend and all the cards are also developed in javascript, core and custom ).
- Done
If you want to compare that with something else is it like playing a game on your own computer (instant response time wit your own computer doing the calculations) versus playing a game with a server in the cloud where your own computer is just used to display the image (network latency in between you and the actual computer doing the calculations)
Lights going unavailable is in the backend (loosing connection to the hue hub for whatever reason load, bad network, poor wifi, packet loss, hub updating, lights updating, etcâŚ) , the frontend just renders the fact that the state of your light is unavailable
as per the docs, just add something like
- type: custom:button-card
entity: switch.1st_floor_bathroom_extractor_fan
show_state: true
state:
- value: 'on'
spin: true
I canât reproduce, could you post your full config (the template used and the actual button) please?
This will be fixed in the next release of button-card
Here you go. First the template config:
button_card_templates:
power_button:
color_type: icon
double_tap_action:
action: none
entity: remote.harmony_hub
hold_action:
action: none
icon: 'mdi:power'
layout: icon_name
name: '[[[ return variables.var_name; ]]]'
state:
- styles:
icon:
- color: 'rgb(249,65,55)'
value: 'on'
styles:
grid:
- grid-template-areas: i n
- grid-template-columns: 1fr 1fr
- grid-template-rows: min-content
icon:
- color: 'rgb(239,239,239)'
tap_action:
action: none
service: remote.turn_on
service_data:
entity_id: '[[[ return entity.entity_id; ]]]'
variables:
var_name: Power Off
And now the button card config. This actually has multiple horizontal stacks of buttons, but the one in question is only in the first row, so I only included that to save space.
color: 'rgb(32,32,32)'
color_type: label-card
custom_fields:
vs1:
card:
cards:
- cards:
- color: var(paper-card-background-color)
color_type: label-card
double_tap_action:
action: none
hold_action:
action: none
icon: 'mdi:stairs-up'
layout: icon_name
name: Upstairs
styles:
card:
- padding: 0
- height: 100%
grid:
- grid-template-areas: i n
- grid-template-columns: 1fr 1fr
- grid-template-rows: 100%
tap_action:
action: none
type: 'custom:button-card'
- tap_action:
action: |
[[[
console.log("power button data");
let retVal = 'none';
console.log(variables !== undefined ? variables : 'variables is undefined');
if (entity && variables && states[entity.entity_id].state === 'on') {
retVal = 'call-service';
}
let entity_state = (entity && entity.state ? entity.state : 'entity undefined e_s');
let state_state = (entity && states[entity.entity_id].state ? states[entity.entity_id].state : 'entity undefined s_s');
console.log(entity ? entity : 'entity undefined log');
console.log(states);
console.log("entity state: " + entity_state + ", state state: " + state_state);
console.log("tap-action returning: " + retVal);
return (retVal);
]]]
template: power_button
type: 'custom:button-card'
type: horizontal-stack
title: Harmony Master Bedroom
type: vertical-stack
name: Label Card
show_label: true
styles:
card:
- padding: 0 10px
grid:
- grid-template-areas: vs1
- grid-template-columns: 1fr
- grid-template-rows: min-content
type: 'custom:button-card'
The debug code is currently in the card config as shown above. When I do my test, I try it this way, then move that exact code to the tap-action
of the power_button
template and remove the tap-action
completely from the card config.
Hi all. As i have continued to try to search and find what my problem has been with my card setup i finaly found whats making my card transparent.
The Entities sektion were i use a input_select to be able to select a channel is whats causing my problem.
If i change the entity to a switch or anything allse it does not go transparent no matter how many time i reload homeassistant.
As soon as i go back to the input_select it start going transparent in first load when i use it in this card setup when in the middle of all the custom buttons. Ive removed all the custom code with css thing and its still fails and goes transparent. Allso worth noting that it only happens on the first page. If i use it in a seperated view together with my bedroom remote it wont fail.
cards:
- content: |
## <ha-icon icon="mdi:remote"></ha-icon> Vardagsrum
type: markdown
- cards:
- color: var(--secondary-text-color)
color_type: icon
entity: switch.appletv
icon: 'mdi:apple'
name: ' '
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.turn_on
service_data:
activity: Apple tv
entity_id: remote.vardagsrum
type: 'custom:button-card'
- color: var(--secondary-text-color)
color_type: icon
entity: switch.htpc
icon: 'mdi:desktop-classic'
name: ' '
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.turn_on
service_data:
activity: Htpc
entity_id: remote.vardagsrum
type: 'custom:button-card'
- color: var(--secondary-text-color)
color_type: icon
entity: switch.tv
icon: 'mdi:television'
name: ' '
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.turn_on
service_data:
activity: Tv
entity_id: remote.vardagsrum
type: 'custom:button-card'
- color: var(--secondary-text-color)
color_type: icon
entity: switch.ps4
icon: 'mdi:playstation'
name: ' '
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.turn_on
service_data:
activity: PS4
entity_id: remote.vardagsrum
type: 'custom:button-card'
- color: '#b93829'
color_off: var(--primary-text-color)
color_type: icon
icon: 'mdi:power'
name: ' '
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.turn_off
service_data:
entity_id: remote.vardagsrum
type: 'custom:button-card'
type: horizontal-stack
- type: entities
entities:
- entity: input_select.freetoair
- cards:
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:exit-to-app'
name: HDMI 1
show_icon: false
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-weight: bold
- font-size: 15px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.hdmi1
- card: null
type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:chevron-up'
name: HDMI 2
show_icon: false
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-weight: bold
- font-size: 15px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.hdmi2
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:menu'
name: HDMI 3
show_icon: false
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-weight: bold
- font-size: 15px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.hdmi3
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:volume-plus'
name: HDMI 4
show_icon: false
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-weight: bold
- font-size: 15px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.hdmi4
type: horizontal-stack
- cards:
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:exit-to-app'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_exit
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:chevron-up'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_upp
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:menu'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_menu
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
double_tap_action:
action: call-service
service: remote.send_command
service_data:
command: VolumeUp
device: 52940343
entity_id: remote.vardagsrum
icon: 'mdi:volume-plus'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.send_command
service_data:
command: VolumeUp
device: 52940343
entity_id: remote.vardagsrum
type: horizontal-stack
- cards:
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:chevron-left'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_left
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:smoke-detector'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_ok
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:chevron-right'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_right
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
double_tap_action:
action: call-service
service: remote.send_command
service_data:
command: VolumeDown
device: 52940343
entity_id: remote.vardagsrum
icon: 'mdi:volume-minus'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: remote.send_command
service_data:
command: VolumeDown
device: 52940343
entity_id: remote.vardagsrum
type: horizontal-stack
- cards:
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:volume-off'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_mute
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:chevron-down'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_ner
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:keyboard-return'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_prev
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:arrow-up-bold'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_channel_up
type: horizontal-stack
- cards:
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:gamepad-variant'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.gamemode
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:play-pause'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_play
- type: 'custom:button-card'
color: var(--secondary-text-color)
color_type: icon
icon: 'mdi:television-guide'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_guide
- type: 'custom:button-card'
color: var(--primary-text-color)
color_type: icon
icon: 'mdi:arrow-down-bold'
size: 25%
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
styles:
card:
- border-radius: 30px
- height: 53px
label:
- color: gray
- font-size: 9px
- justify-self: start
- padding: 0px 5px
name:
- font-size: 12px
- padding: 0px 0px
tap_action:
action: call-service
service: script.turn_on
service_data:
entity_id: script.harmony_channel_down
type: horizontal-stack
type: vertical-stack
If anyone can please try to help me out with why this happens when i use the input_select i would be most greatfull sins i been at this now for monthsâŚ
Thanks. I had temporarily moved to setting the entity to a fake one, and then just applying the state information using templates to the card to stop the error stream in the logs. Will switch back and try it after the update.
itâs a vertical stack. are you saying that even with that input_select
alone it remains transparent?
could you post a screenshot when it happens?
what is it?
Shouldnât that:
style: |
:active
ha-card {
background-color: var(--paper-item-icon-active-color);
transition: .05s;
}
Be:
style: |
ha-card:active {
background-color: var(--paper-item-icon-active-color) !important;
transition: .05s;
}
Everywhere?
Also arenât you using a vertical-stack-in-card
or a stack-in-card
somewhere in this view, like as a parent of all this config you pasted?
So the reason it doesnât work while the config is in the main config and not in the template is because the javascript template from your action
field is evaluated while assigning the config to the burried cards (since the card
field supports javascript templates), which means it uses the values from the main button-card for variables
, entity
, etc⌠not the values from the burried button-card as you would probably expect.
Iâm not sure what would be a good way to fix this though as I canât really know what you have inside the card
field, nor how deep a potential button-card
would be
The only way for now is to put that part of the config in a button-card template, because this is not evaluated while assigning the config to a burried card, but evaluated only once the card is created by the burried card itself
Thanks for the investigation and explanation. For my purposes, so far I havenât absolutely required code in the card config or Iâve worked around it. Now that I know for sure how it works, Iâll be aware of it and do what I need to do. So, for my stuff Iâm doing now, the beta looks good.