Lovelace: Button card

@RomRider immediately related to the post above, how can I use a top level variables:

variables:
  speed_color: >
    [[[ var speed = states['sensor.argon_one_addon_fan_speed'].state;
        var mapper = {0:'green',
                      1:'darkgreen',
                      3:'orange',
                      33:'orangered'
                      66:'maroon'}
        return mapper[speed] ? mapper[speed] : 'red' ; ]]]

in a custom fields style:

custom_fields:
  fan:
    >
      [[[ return `<ha-icon icon=mdi:fan style='width:15px;color: var(--speed-color);'> </ha-icon>
          <span style='color: var(--primary-color);'>
          ${states['sensor.argon_one_addon_fan_speed'].state} % </span>`; ]]]

replacing the color: var(--speed-color) which I use up to now, with color: variables.speed_color or even color: ${variables.speed_color} is unsuccessful unfortunately. Canā€™t this be done?

It would be very cool, because I would only need the 1 top variable, and use it in more places of course

UPDATE:
yes we can:

custom_fields:
  fan:
    >
      [[[ return `<ha-icon icon=mdi:fan style='width:15px;color: ` + variables.speed_color + `;'> </ha-icon>
          <span style='color: var(--primary-color);'>
          ${states['sensor.argon_one_addon_fan_speed'].state} % </span>`; ]]]

thanks to Ildar.

again typo - missing comma

I am still trying, wait a littleā€¦

no typo thereā€¦Color Theory

33:'orangered' COMMA
1 Like

oopsā€¦ :blush: sorryā€¦ also the closing third ] was missingā€¦

First, regarding color of fanā€™s icon:

variables:
  speed_color: |
    [[[ var speed = states['sensor.iiyama_ohm_fans_fan_1'].state;
        var mapper = {500:'green',
                      600:'darkgreen',
                      700:'orange',
                      800:'orangered',
                      900:'maroon'}
        return mapper[speed] ? mapper[speed] : 'yellow'; ]]]
...
custom_fields:
  fan: >
    [[[ return `<ha-icon icon=mdi:fan style='width:32px;color: ` + variables.speed_color + `;'> </ha-icon>
        <span style='color: var(--primary-color);'>
        ${states['sensor.iiyama_ohm_fans_fan_1'].state} rpm </span>`; ]]]

Note this:
color: ` + variables.speed_color + `;

Do not bother about ā€œ500,600,700ā€, ā€œrpmā€, that was for my testing case.

Also, note that your construction "mapper" works only for THESE values, i.e. for 500,600,700 - for 550, 650 it will return default value (this is not good)

A yes, that should work.

Thanks.
About the speeds: they are fixed in my fan add-on. So no worries about other speeds :wink:

Thatā€™s why I didnā€™t make a Template with <

1 Like

As for conditional rotation - add this style with card-mod, and define conditions for speeds:

type: custom:button-card
card_mod:
  style: |
    div#container > div#fan > ha-icon {
      animation: rotation 1s linear infinite;
    }
    @keyframes rotation {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }

aaaaa
Do not bother about colors & font-sizes - that was changed while reverse-engineering your code))

1 Like

can we replace the ā€˜1sā€™ with a variables.speed_rotation?

and encapsulate it in a template:

if (states['sensor.argon_one_addon_fan_speed'].state != 0) return

You can define "1s" by using usual ways like:

                        animation:
                          {% if states('input_number.servicewithhistory_value')|int <= 250|int -%}
                          rotation 4s
                          {%- elif states('input_number.servicewithhistory_value')|int > 250|int and states('input_number.servicewithhistory_value')|int <= 500|int -%}
                          rotation 2s
                          {%- elif states('input_number.servicewithhistory_value')|int > 500|int and states('input_number.servicewithhistory_value')|int <= 750|int -%}
                          rotation 1s
                          {%- else -%}
                          rotation 0.3s
                          {%- endif %}
                          linear infinite;

of course, thats the jinja we needā€¦

I was still trying to do this:

card_mod:
  style: |
    div#container > div#fan > ha-icon {
      animation: rotation **variables.speed-rotation** linear infinite;
    }
    @keyframes rotation {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }
variables:
  speed-rotation: >
      [[[ var speed = states['sensor.argon_one_addon_fan_speed'].state;
          var mapper = {0:'100s',
                        1:'4s',
                        3:'3s',
                        33:'2s',
                        66:'1s'}
          return mapper[speed] ? mapper[speed] : '0.3s' ; ]]]

are you sure we can not load a variable there? not even a jinja version like

animation:
 {% set speed  = states('sensor.argon_one_addon_fan_speed')|int %}
 {% if speed != 0 -%}                          
   {% if speed == 1 %} rotation 4s
   {% elif speed == 3 %} rotation 3s
   {% elif speed == 33 %} rotation 2s
   {% elif speed == 66 %} rotation 1s
   {% else %} rotation 0.3s
   {% endif %} linear infinite;
 {% else %} null
 {% endif %}

or

 {% set speed  = states('sensor.argon_one_addon_fan_speed')|int %}
 {% if speed != 0 -%}                          
 {% set mapper = {1:'4',3:'3',33:'2',66:'1'} %}
 {% set rotation = mapper[speed] if speed in mapper else '0.3' %}
 {{'rotation ' + rotation + 's ' + 'linear infinite'}}
 {% else %} null
 {% endif %}

edit:
YES! this works fine:

card_mod:
  style: |
    div#container > div#fan > ha-icon {
      animation:
         {% set speed  = states('sensor.argon_one_addon_fan_speed')|int %}
         {% if speed != 0 %}
         {% set mapper = {1:'4',3:'3',33:'2',66:'1'} %}
         {% set rotation = mapper[speed] if speed in mapper else '0.3' %}
         {{'rotation ' + rotation + 's ' + 'linear infinite'}}
         {% else %} null
         {% endif %}

so cool ! thanks you once again @Ildar_Gabdullin

1 Like

Great, I gonna save this info for future))

yes, I was hoping so.
main reason for not using card-mod, would be using templates in button-card is done in the browser, opposed to the card-mod jinja template in the backend server.

So if you still have a suggestion, I would certainly appreciate thatā€¦

btw, I found another way to prevent using these messy html ticks:

toplevel

variables:
  state_color: >
    [[[ var state = entity.state;
        if (state < 50) return 'green';
        if (state < 60) return 'darkgreen';
        if (state < 70) return 'orange';
        if (state < 80) return 'maroon';
        return 'red'; ]]]

and then use an intermediary --state-color:

styles:
  custom_fields:
    temp:

      - --state-color: >
          [[[ return variables.state_color ]]]

  icon:
    - color: >
        [[[ return variables.state_color ]]]

as you can see you can reuse the same top level variable elsewhere

and finally the field itself:

custom_fields:
  temp: >
    [[[ return `<ha-icon icon=mdi:thermometer
                 style='width:15px; color: var(--state-color);'> </ha-icon>
                 ${entity.state}Ā°C</span>`; ]]]

nice.

BTW, for animations you may use extra_styles instead of "card_mod".
Something like this:

extra_styles: |
  @keyframes rotation {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
custom_fields:
  fan: |
    [[[ return `<ha-icon
                  icon=mdi:fan
                  style='width: 32px;
                         color: red;
                         animation: rotation 4s linear infinite;'
                >
                </ha-icon>
                <span
                  style='color: var(--primary-color);'
                >
                ${states['sensor.iiyama_ohm_fans_fan_1'].state} rpm
                </span>
               `;
    ]]]

But for "extra_styles" there is an issue in the docs:

Note: extra_styles MUST NOT be used on the first button-card of the current view, else it will be applied to all the cards in all Lovelace. It is not possible to fix this behaviour.

of course! I keep forgetting the extra_styles!

great, now we can use it all in the frontend browser. only thing left to find is the correct syntax to include my top level variables.speed_rotationā€¦ will requires some extra tweaking, always a challenge :wink:

found it:

extra_styles: |
  @keyframes rotation {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
variables:
  speed_rotation: >
    [[[ var speed = states['sensor.argon_one_addon_fan_speed'].state;
        var mapper = {1:'4s',3:'3s',33:'2s',66:'1s'}
        if (speed != 0)
          return mapper[speed] ? mapper[speed] : '0.3s';
          return null; ]]]

and

custom_fields:
  fan:
    >
      [[[ return `<ha-icon
                     icon=mdi:fan
                     style='width:15px;
                            color: ` + variables.speed_color + `;
                            animation: rotation ` + variables.speed_rotation + ` linear infinite;'
                   > </ha-icon>
          <span style='color: var(--primary-color);'>
          ${states['sensor.argon_one_addon_fan_speed'].state} % </span>`; ]]]

although technically it now does

animation: rotation null linear infinite;

on speed 0. so I need to improve the template on that. Does work though :wink:

EDIT:
this is better

variables:
  speed_rotation: >
    [[[ var speed = states['sensor.argon_one_addon_fan_speed'].state;
        var mapper = {1:'4s',3:'3s',33:'2s',66:'1s'};
        var motion = mapper[speed] ? mapper[speed] : '0.3s';
        if (speed != 0) return 'rotation ' + motion +  ' linear infinite';
        return null; ]]]

custom_fields:
  fan:
    >
      [[[ return `<ha-icon
                     icon=mdi:fan
                     style='width:15px;
                            color: `+ variables.speed_color +`;
                            animation: `+ variables.speed_rotation +`;'
                   > </ha-icon>
          <span style='color: var(--primary-color);'>
          ${states['sensor.argon_one_addon_fan_speed'].state} % </span>`; ]]]

Jun-25-2021 18-45-05

seems the frame rate isnt high enough for the 100% speedā€¦

so hereā€™s a small gif in HD

Jun-25-2021 18-48-48

4 Likes

btw, and believe it or not, but this is the first card-mod on a regular entity I (have to) use, (because the entity is made by an add-on, and custom-ui cant customize theseā€¦)

so please let me ask, if this is the correct way I can do that (it is working as expected):

      - entity: sensor.argon_one_addon_fan_speed
        secondary_info: last-changed
        card_mod:
          style:
            hui-generic-entity-row:
              $:
                state-badge:
                  $:
                    ha-icon:
                      $: |
                        ha-svg-icon {
                          color:
                            {% set speed = states('sensor.argon_one_addon_fan_speed')|int %}
                            {% set mapper = {0:'green',1:'darkgreen',3:'orange',
                            33:'orangered',66:'maroon'} %}
                            {{ mapper[speed] if speed in mapper else 'red'}}
                        }

in the set speed I need to call the entity completely dont I? I cant use something like entity.state or states(config.entity) ā€¦

Yep, confirmed, states(config.entity) does the trick. Nice, great for yaml anchors :wink:
o heck, this is not a button-card, sorry for the wrong thread, continuing from above thoughā€¦

Hello, Iā€™m breaking my head here.
Iā€™m trying to build a card similar to grid example listed in the documentation. So bring together multiple data parts into one small card.
The problem Iā€™m facing I want to change icons if I detect motion (different state) use mdi:motion-sensor and if not mdi:motion-sensor-off.
My code looks like

title: Master Test
path: master_test
icon: "mdi:account-supervisor-circle"
cards:
  - type: vertical-stack
    cards:
      - type: horizontal-stack
        cards:
          - type: "custom:button-card"
            triggers_update:
              - sun.sun
            icon: "zeus:shower"
            styles:
              card:
                #                - aspect_ratio: 1/1
                - width: 120px
                - height: 100px
                - margin: 3px
                - padding: 5px
                - border-radius: 15px
                - background-color: var(--primary-background-color)
                - box-shadow: >
                    [[[
                      if (states['sun.sun'].state == "below_horizon")
                        return '-5px -5px 15px #2c2c2c, 5px 5px 15px #191919';
                      else if (states['sun.sun'].state == "above_horizon")
                        return '-5px -5px 15px #ffffff, 5px 5px 15px #ebebeb';
                    ]]]
              grid:
                - grid-template-areas: '"i Motion" "i Window" "i Water"'
                - grid-template-columns: 4fr 1fr
                - grid-template-rows: 1fr 1fr 1fr
              img_cell:
                - justify-content: start
                - align-items: start
              icon:
                - width: 50%
                - color: deepskyblue
              custom_fields:
                Motion:
                  - align-self: middle
                  - justify-self: end
                  - font-size: 10px
                  - --text-color-sensor: '[[[ if (states["binary_sensor.motion_sensor_master_bathroom_occupancy"].state == "on") return "red"; ]]]'
                  - --icon-type: >
                      [[[
                        if (states["binary_sensor.motion_sensor_master_bathroom_occupancy"].state == "on") return "mdi:motion-sensor";
                        else return "mdi:motion-sensor-off";
                      ]]]
                Window:
                  - align-self: middle
                  - justify-self: end
                  - font-size: 10px
                  - --text-color-sensor: '[[[ if (states["binary_sensor.motion_sensor_master_bathroom_occupancy"].state == "off") return "red"; ]]]'
                Water:
                  - align-self: middle
                  - justify-self: end
                  - font-size: 10px
                  - --text-color-sensor: '[[[ if (states["sensor.processor_use_percent"].state > 60) return "red"; ]]]'
            custom_fields:
              Motion: >
                [[[
                  return `<ha-icon
                    icon= var(--icon-type)
                    style="width: 20px; height: 20px;">
                    </ha-icon><span> <span style="color: var(--text-color-sensor);">${states["sensor.disk_use_percent_home"].state}%</span></span>`
                ]]]
              Window: >
                [[[
                  return `<ha-icon
                    icon= "mdi:memory"
                    style="width: 25px; height: 25px;">
                    </ha-icon><span> <span style="color: var(--text-color-sensor);">${Math.round(states["sensor.memory_free"].state /1000)}GB</span></span>`
                ]]]
              Water: >
                [[[
                  return `<ha-icon
                    icon= "mdi:cpu-64-bit"
                    style="width: 25px; height: 25px;">
                    </ha-icon><span> <spanstyle="color: var(--text-color-sensor);">${states["sensor.processor_use_percent"].state}%</span></span>`
                ]]]

Can someone help me figure out what Iā€™m missing? Currently I have this template for confirmation on tap_action, which works (copied from the docs).

      confirmation:
        text: '[[[ return `Hiermee wordt ${entity.attributes.friendly_name} aan/uitgezet, doorgaan?` ]]]'   

Now I want the text to say either A or B depending on the state of the entity. So I have this, but it doesnā€™t work:

      confirmation:
        text: '[[[ if (entity.state === on) return "Hiermee wordt ${entity.attributes.friendly_name} uitgezet, doorgaan?"; else return "Hiermee wordt ${entity.attributes.friendly_name} aangezet, doorgaan?" ]]]'

I think Iā€™m missing something obvious or am combing templates the wrong way.

try for starters:

        [[[ if (entity.state == 'on')
           return `Hiermee wordt ${entity.attributes.friendly_name} uitgezet, doorgaan?`;
           return `Hiermee wordt ${entity.attributes.friendly_name} aangezet, doorgaan?` ]]]

1 Like