How to change icons based on state

Hi guys. I know this question comes up a lot, but I think I am stupid. I cannot find a solution to my simple problem. At least no solution I really understand…

So basically I just want to change the icon of an entity displayed at my dashboard based on an entity’s state. In this case I want to display an icon for my iPhone entity. The idea is:

  • Display mdi:battery-charging when the battery_state is Charging
  • Display the current battery level based on battery_level

For example, if the iPhone is connected to the charger and it has a battery level of 50 %, then display battery-charging-50. If it is not charging and it has around 70 %, then display battery-70.

Also it would be cool to know how I can also change the color of the icons based on the states.

The yaml of my frontend looks like this:

type: entities
entities:
  - entity: sensor.saschas_iphone_battery_level
    # This icon should change based on battery_state & battery_level    
    icon: mdi:battery
  - sensor.saschas_iphone_battery_state

So what do I need to do? I can find so many topics about this but each one is using different templates, yaml code or even plugins. How is it possible with just “vanilla” Home Assistant?

I appreciate every hint. Thanks!!

Templates are vanilla HA. The only way to achieve this with a sensor that doesn’t have these capabilities is to make a template sensor with an icon template.

Okay so basically I need to create a template sensor in my configuration.yaml and then use this one in the frontend?

How would this look like in my configuration.yaml?

There are a few possible ways to do that. :slight_smile:

One of them is using a template sensor, where you can set an icon and define what to show. This would be a systemwide solution, as you can use it everywhere.

But if you just have this in one place, in one dashboard, it could be an alternative to change only the display. This would be a solution, where you work your defintions into a card in the frontend. Mushroom cards for example can easily do that, button-cards as well (and a lot more). The disadvantage with this solution is, if you ever use this in more than one place, you’d duplicate code and would have to maintain two or more different places…

Choose what you like, it’s your choice! :slight_smile:

If you want to use the template sensor, see here for a few examples

New “modern” format (recommended):

Or the old, no longer recommended legacy template sensor

1 Like

Thanks! I think with your help I got it working. I have now added this to my configuration.yaml:

template:
  - trigger:
    - platform: state
      entity_id: sensor.saschas_iphone_battery_state
    binary_sensor:
      - name: iPhone Charging
        state: >
          {{ is_state("sensor.saschas_iphone_battery_state", "Charging") }}
        icon: >
          {% if is_state("binary_sensor.iphone_charging", "on") %}
            mdi:battery-charging-50
          {% else %}
            mdi:battery-50
          {% endif %}

One thing I don’t understand: Why is the icon mdi:battery-charging-50 showing when the state is Not Charging and mdi:battery-50 when it is Charging? Shouldn’t it be the other way around? What am I missing here? :smiley:

Because of

  - trigger:
    - platform: state
      entity_id: sensor.saschas_iphone_battery_state

When it triggered - you are processing PREV data.
Try with this only:

template:
  - binary_sensor:
1 Like

You need to remove the trigger in this sensor, as Ildar stated. :slight_smile: It is not only unnecessary, it is also breaking your sensor. If you add a trigger to your template, the template will only change, when this trigger goes from false to true, but not vice versa.

But it is unnecessary, as a template sensor always reacts on state changes from used entites.

This {{ is_state("sensor.saschas_iphone_battery_state", "Charging") }} is taking care of updates to the template sensor. This is enough in your case.
Just as a general note, trigger based template sensors are a very special kind of template sensors, that in reality are only necessary in one of ten cases.

Next thing, you can’t reference the sensor in this way in your icon template. This would be kind of a self reference.

You need to do it with the state of an already existing sensor.

template:
  - trigger:
    - platform: state
      entity_id: sensor.saschas_iphone_battery_state
    binary_sensor:
      - name: iPhone Charging
        state: >
          {{ is_state("sensor.saschas_iphone_battery_state", "Charging") }}
        icon: >
          {% if is_state("sensor.saschas_iphone_battery_state", "Charging") %}
            mdi:battery-charging-50
          {% else %}
            mdi:battery-50
          {% endif %}
1 Like

Okay, so first of all: Thank you @paddy0174, @Ildar_Gabdullin & @petro! :slight_smile:

@paddy0174:

Next thing, you can’t reference the sensor in this way in your icon template. This would be kind of a self reference.

I understand that, but they even use this in the official documentation:

template:
  - binary_sensor:
      - name: Sun Up
        ...
          {% if is_state("binary_sensor.sun_up", "on") %}
        ...

So, is it wrong to use it? It seems to work :smiley:

I noticed that I try to rebuild the built-in behavior of Home Assistant for the battery icons. However, I think this is a good practical experience. With your help I managed to get it working now. Here is my code in templates.yaml:

sensor:
  - name: iPhone Charging
    state: >
      {% if is_state("sensor.saschas_iphone_battery_state", ["Charging", "Full"]) %}
        Lädt
      {% else %}
        Lädt nicht
      {% endif %}
    icon: >
      {% set state = states("sensor.iphone_charging") | string %}
      {% set level = states("sensor.saschas_iphone_battery_level") | int %}

      {% if (state == "Lädt") and (level == 100) %}
        mdi:battery-charging-100
      {% elif (state == "Lädt") and (90 <= level < 100) %}
        mdi:battery-charging-90
      {% elif (state == "Lädt") and (80 <= level < 90) %}
        mdi:battery-charging-80
      ...
      {% else %}
        mdi:battery
      {% endif %}

However… is there a way to also change the color of the icon based on the states? I tried to do it like this, but it doesn’t seem to work like this:

sensor:
    ...
    icon_color: red

For reference, the standard entity supports this based on the battery level:

Once again, thank you for your help so far! I really appreciate it.

This template will be easier to manage:

    icon: >
      {% set state = states("sensor.iphone_charging") | string %}
      {% set state = iif(state == "Lädt", '-charging', '') %}
      {% set level = states("sensor.saschas_iphone_battery_level") | int(0) %}
      {% set level = (level // 10) * 10 %}
      mdi:battery{{ state }}-{{ level }}

Color requires modifying the theme or using card-mod which is a custom card.

1 Like

Ah thanks!

So, the colors & different icons showing for sensor.saschas_iphone_battery_level are coming from the Home Assistant default template? Is that correct? Because I have no card_mod or something like that installed, so this has to come out-of-the-box somewhere.

The colors come from the theme.

It’s a custom frontend card, you have to add it via HACS or manually.

1 Like

Oh okay… I just took a look at the available frontend cards and my installed integrations in HACS. Something is broken in there. I can see lots of cards for integrations I already removed days ago in HACS. That is why I thought this was a built-in card.

Edit: It is indeed a vanilla card, see: [Entities card - Home Assistant (home-assistant.io)](Entities card - Home Assistant

So propably the colors are coming from the theme.