Toggling an icon based on a sensor's state

I’ve read dozens of posts related to this topic, and I’ve tried many things. According to multiple posts, the following syntax should work … but it is not working for me. I’m obviously missing something …

My sensor is defined in my sensors.yaml file as:

  - platform: mqtt
    state_topic: "doorminder/data"
    name: garage_door1_state
    value_template: "{{ value_json.gnode.doors.0.state }}"
    retain: true

My customization.yaml file attempts to toggle the icon with the following lines:

 sensor.garage_door1_state:
    friendly_name: "Door  #1"
    templates:
      icon: "if (state === 'Closed') return 'mdi:garage'; else return 'mdi:garage_open';"
      icon_color: "if (state === 'Closed') return 'rgb[0,255,0]'; else return 'rgb[255,0,0]';"

This is how the sensor’s current state displays in the developer tools <>:

Unfortunately, this is how the sensor displays on the front-end:
image

I hope someone can tell me what I’m doing wrong…

The first part of my configuration.yaml file is listed below … in case the problem is somewhere in there.

###############################################
#             configuration.yaml              #
###############################################
homeassistant:
  name: Home                  # Name of the location where Home Assistant is running
  latitude: !secret latitude         # Location required to calculate the time the sun rises and sets
  longitude: !secret longitude
  elevation: 75               # Impacts weather/sunrise data (altitude above sea level in meters)
  unit_system: imperial       # (metric or imperial)
  time_zone: America/Chicago  # Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones


###############################################
#           included yaml files               #
###############################################
  customize: !include customize.yaml
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
sensor: !include sensors.yaml
binary_sensor: !include binary_sensors.yaml
#media_player: !include media_players.yaml


###############################################
#           optional components               #
############################################### 
#introduction:                 # Show links to resources in log and frontend
config:                       # Enables configuration UI
updater:                      # Checks for available updates
api:                          # Enables the API
cloud:                        # Cloud
conversation:                 # Allows you to issue voice commands from the frontend in enabled browsers
#discovery:                    # Discover some devices automatically
history:                      # Enables support for tracking state changes over time
logbook:                      # View all events in a logbook
#map:                         # Enables a map showing the location of tracked devices
sun:                            Track the sun


###############################################
#                 frontend                    #
###############################################
frontend:
  extra_html_url:
    - /local/custom_ui/state-card-hline.html
  extra_html_url_es5:
    - /local/custom_ui/state-card-hline_es5.html


###############################################

Is that a copy-paste error or does your configuration.yaml really have _two spaces in front of customize: !include customize.yaml? If they really are there, remove them. (My mistake)

Your templates section looks fine to me.

Unrelated to your question but I noticed you have retain: true in the sensor’s configuration. That’s an invalid option for an MQTT Sensor (check the documentation). Sensors receive data from the MQTT Broker, they don’t publish to it (retain is for publishing, not subscribing). Versions prior to 0.87 will just ignore invalid options but 0.87+ will flag them and refuse to load the entity.

that’ll only work if you are using custom UI. This won’t work without the customUI:

 sensor.garage_door1_state:
    friendly_name: "Door  #1"
    templates:
      icon: "if (state === 'Closed') return 'mdi:garage'; else return 'mdi:garage_open';"
      icon_color: "if (state === 'Closed') return 'rgb[0,255,0]'; else return 'rgb[255,0,0]';"

The two spaces are required because customize: must be declared within homeassistant:. The other optional components are declared outside of homeassistant:. This tripped me up when I reorganized the default configuration.yaml file.

Thanks for the tip about the retain: true lines. I saw this in some sample code and I wondered why it was there… I thought it might be telling HA that the MQTT broker was retaining the message … which it is in this case. Now, I know that’s not the case, so I will remove those lines from my MQTT sensors.

I looked at custom UI, and I’m not anxious to install it.

Is there another way to dynamically set the icon and/or icon color that is native to Home Assistant?

So instead of using an mqtt sensor, swap it to the binary_sensor section and add device_class: garage_door.

binary_sensor:
  - platform: mqtt
    state_topic: "doorminder/data"
    name: garage_door1_state
    value_template: "{{ value_json.gnode.doors.0.state }}"
    retain: true
    device_class: garage_door

Doh! You’re right! I just checked my config and it’s indented under homeassistant:

I assumed you were using Custom UI but apparently you are not. I have it installed (installation is easy) and it allows you (among many other things) to customize how icons, and their colors, behave dynamically. Here’s an example from my own configuration in customize.yaml:

climate.thermostat:
  templates:
    icon: >
      if (state === 'heat') return 'mdi:fire';
      if (state === 'cool') return 'mdi:snowflake';
      if (state === 'auto') return 'mdi:autorenew';
      if (state === 'idle') return 'mdi:sleep';
      return 'mdi:power-off';
    icon_color: >
      if (state === 'heat') return 'red';
      if (state === 'cool') return 'blue';
      if (state === 'auto') return 'green';
      if (state === 'idle') return 'black';
1 Like

My garage door controller returns multiple states “closed”, “opening”, “open”, “closing”, “stopped”, and “unknown”, so I don’t want a binary_sensor for this purpose. That said, I did create this binary_sensor to reflect the “closed” and “not-closed” states with the hope that I could use it to trigger automations. That binary_sensor displays perfectly, and my automation works perfectly with I trigger it manually, but I have been unable to trigger the automation from the binary_sensor. Do you see anything wrong with the following?

from my binary_sensors.yaml

  - platform: mqtt
    state_topic: "doorminder/data"
    name: garage_door1_secure
    value_template: "{% if value_json.gnode.doors.0.state == 'Closed' %}on{% else %}off{% endif %}"
    payload_on: "on"
    payload_off: "off"

from my automations.yaml

  - alias: garage_door1_opening
    trigger:
    - platform: state
      entity_id: binary_sensor.garage_door1_secure
      from: 'Off'
      to: 'On'
    action:
      - service: tts.google_say
        data:
          entity_id: media_player.office_display
          message: 'garage door one is opening'

One thing seems odd to me: Automations appear to have an alias, but don’t have a name.

Oh, then why don’t you implement it as a mqtt cover? Then specify garage as the device class.

This is exactly what I want to do …

My reluctance to install something like custom_ui is that everything I install may need to be updated or even removed at some point. I come from a background where each module has an install and an uninstall, and where updates can be backed out easily. I don’t see that in the Home Assistant ecosystem.

Thanks for publishing your thermostat logic. That adds weight to the argument for installing custom_ui.

I think also custom-ui does not play nice with Lovelace so I think you’re smart not to rely on it…

1 Like

My doorsensor send only out one signal for open as for close. == 101
how can use this for automation.
So default state would be closed if window is openend (signal is send) switch toggle.
And if the window is being closed (signal is send again) switch toggle.

Within this example it would be open when the first is send and closed when the second is send.

any ideas how integrate this within home assistant?