Nerwyn/service-call-tile-feature

Select Selector based on rules, make it stay selected; z-index of tooltip off

Closed this issue · 8 comments

Is your feature request related to a problem? Please describe.
I want to make a selector row with different speed steps for a fan. When I press f.e. the middle button the fan speed turns to 50%. What doesn't work is the highlighting: when I reload the page it is gone. My end goal is that I define a specific range (f.e. 26-50% = Level 2, 51-75% = Level 3 etc.), so when I change the percentage on the slider the highlighted Level is selected accordingly. Also it seems like the tool-tip with the percentage of the slider has the wrong z-index, because it is behind the selectors.

CleanShot 2024-07-26 at 10 05 08

My current working setup was this, but it does't look so nice in the mushroom setup:
CleanShot 2024-07-26 at 10 09 54

Describe the solution you'd like
I would like a more detailed description in the documentation on how I can "set the button highlighted".

Describe alternatives you've considered
I tried to change the CSS (because I saw that it is changed to "selected-option" from "option"), but I'm not so advanced so I gave up.

Additional context
New Setup Code:
`features:

  • type: custom:service-call
    entries:
    • type: selector
      entity_id: fan.ventilator
      options:
      • icon: mdi:weather-night
        tap_action:
        action: call-service
        service: fan.set_percentage
        target:
        entity_id: fan.ventilator
        data:
        percentage: 1
        autofill_entity_id: true
        haptics: false
        type: button
        styles: |-
        :host {
        --control-select-color: #484a4e !important;
        --control-select-background: #050505 !important;
        --label-color: red;
        #--color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 3 %} black !important; {% else %} none; {% endif %}
        }
      • icon: mdi:fan-speed-1
        tap_action:
        action: call-service
        service: fan.set_percentage
        target:
        entity_id: fan.ventilator
        data:
        percentage: 25
        autofill_entity_id: true
        haptics: false
        type: button
        styles: |
        --color: var(--green-color);
      • icon: mdi:fan-speed-2
        tap_action:
        action: call-service
        service: fan.set_percentage
        target:
        entity_id: fan.ventilator
        data:
        percentage: 50
        autofill_entity_id: true
        haptics: false
        type: button
        styles: |
        --color: var(--green-color);
      • icon: mdi:fan-speed-3
        tap_action:
        action: call-service
        service: fan.set_percentage
        target:
        entity_id: fan.ventilator
        data:
        percentage: 75
        autofill_entity_id: true
        haptics: false
        type: button
        styles: |
        --color: var(--green-color);
      • icon: mdi:fan
        tap_action:
        action: call-service
        service: fan.set_percentage
        target:
        entity_id: fan.ventilator
        data:
        percentage: 100
        autofill_entity_id: true
        haptics: false
        type: button
        styles: |
        --color: var(--green-color);
        value_attribute: percentage
        styles: ''
  • type: fan-speed
    type: tile
    entity: fan.ventilator
    show_entity_picture: false
    vertical: false
    layout_options:
    grid_columns: 4
    grid_rows: ''
    card_mod:
    style:
    ha-tile-info$: |
    .secondary:after {
    visibility: visible;
    content: " ⸱ {{ states('sensor.front_door_battery_level') }}%";
    }`

Current Setup Code:
- type: horizontal-stack cards: - type: custom:layout-card layout_type: grid cards: - type: custom:mushroom-template-card layout: vertical icon: mdi:weather-night tap_action: action: call-service service: fan.set_percentage service_data: entity_id: fan.ventilator percentage: 1 view_layout: grid-area: button0 card_mod: style: | ha-card { height: 44px !important; box-shadow: none; } mushroom-shape-icon { --icon-color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 0 %} black !important; {% else %} none; {% endif %} --shape-color: none !important; --icon-symbol-size: 20px; } - type: custom:mushroom-template-card layout: vertical icon: mdi:circle-slice-2 tap_action: action: call-service service: fan.set_percentage service_data: entity_id: fan.ventilator percentage: 25 view_layout: grid-area: button1 card_mod: style: | ha-card { height: 44px !important; box-shadow: none; } mushroom-shape-icon { --icon-color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 1 %} black !important; {% else %} none; {% endif %} --shape-color: none !important; --icon-symbol-size: 20px; } - type: custom:mushroom-template-card layout: vertical icon: mdi:circle-slice-4 tap_action: action: call-service service: fan.set_percentage service_data: entity_id: fan.ventilator percentage: 50 view_layout: grid-area: button2 card_mod: style: | ha-card { height: 44px !important; box-shadow: none; } mushroom-shape-icon { --icon-color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 2 %} black !important; {% else %} none; {% endif %} --shape-color: none !important; --icon-symbol-size: 20px; } - type: custom:mushroom-template-card layout: vertical icon: mdi:circle-slice-6 tap_action: action: call-service service: fan.set_percentage service_data: entity_id: fan.ventilator percentage: 75 view_layout: grid-area: button3 card_mod: style: | ha-card { height: 44px !important; box-shadow: none; } mushroom-shape-icon { --icon-color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 3 %} black !important; {% else %} none; {% endif %} --shape-color: none !important; --icon-symbol-size: 20px; } - type: custom:mushroom-template-card layout: vertical icon: mdi:circle-slice-8 tap_action: action: call-service service: fan.set_percentage service_data: entity_id: fan.ventilator percentage: 100 view_layout: grid-area: button4 card_mod: style: | ha-card { height: 44px !important; box-shadow: none; } mushroom-shape-icon { --icon-color: {% if ((states.fan.ventilator.attributes.percentage / 100 * 4) | int) == 4 %} black !important; {% else %} none; {% endif %} --shape-color: none !important; --icon-symbol-size: 20px; 4 layout: grid-template-rows: auto grid-template-areas: | "button0 button1 button2 button3 button4"

Per the README, You have to set the selector attribute to the field to track and the option field in each selector option so it knows what to compare against when checking which option is active. In this case it would be the fan speed/percentage.

type: selector
entity_id: fan.sunroom_air_purifier
options:
  - type: button
    entity_id: fan.sunroom_air_purifier
    option: '0'
    tap_action:
      action: call-service
      service: fan.turn_off
      target:
        entity_id:
          - fan.sunroom_air_purifier
    icon: mdi:fan-off
    value_attribute: percentage
  - type: button
    entity_id: fan.sunroom_air_purifier
    option: '25'
    tap_action:
      action: call-service
      service: fan.set_percentage
      target:
        entity_id:
          - fan.sunroom_air_purifier
      data:
        percentage: '{{ config.option | int }}'
    icon: mdi:fan-chevron-down
  - type: button
    entity_id: fan.sunroom_air_purifier
    option: '50'
    tap_action:
      action: call-service
      service: fan.set_percentage
      target:
        entity_id:
          - fan.sunroom_air_purifier
      data:
        percentage: '{{ config.option | int }}'
    icon: mdi:fan-speed-1
  - type: button
    entity_id: fan.sunroom_air_purifier
    option: '75'
    tap_action:
      action: call-service
      service: fan.set_percentage
      target:
        entity_id:
          - fan.sunroom_air_purifier
      data:
        percentage: '{{ config.option | int }}'
    icon: mdi:fan-speed-2
  - type: button
    entity_id: fan.sunroom_air_purifier
    option: '100'
    tap_action:
      action: call-service
      service: fan.set_percentage
      target:
        entity_id:
          - fan.sunroom_air_purifier
      data:
        percentage: '{{ config.option | int }}'
    icon: mdi:fan-speed-3
value_attribute: percentage

That being said there seems to be a bug in selector value option comparison logic due to the configuration UI always setting option to a string even when it's numerical, which I'll have to fix.

The slider tooltip under the selector option is definitely a bug but it doesn't appear for me. Are you using the built in fan speed tile feature or a custom one?

@justspacedog if you could update your config and try the 4.0.2 alpha, it should fix non-string selector value option comparisons.

My end goal is that I define a specific range (f.e. 26-50% = Level 2, 51-75% = Level 3 etc.), so when I change the percentage on the slider the highlighted Level is selected accordingly.

Sorry just noticed this bit. The selector doesn't support ranges, just discrete values. I don't think supporting inexplicit option values is a good idea for this feature, but you can get this behavior by creating a helper input_select entity, and then creating an automation that sets it's value based on fan percentage ranges.

Better solutions below!

Would it be more approiate to let the option be templatable? Detect if the option is a literal non-templated string, if so, compare against that.

If not, evaluate the template to highlight whichever is true. If multiple evaluates to true, just return the first one or say it may cause unexpacted behaviour.

This also suits the spirit of customizability.

but you can get this behavior by creating a helper input_select entity, and then creating an automation that sets it's value based on fan percentage ranges

I recently found out that you can template a select entity that is not input_select. This way you can programme 1 less automation. For your reference, here's my templated select to handle fan oscillation angles, remapping 150 to 140 degrees. You can adapt this for fan speeds.

- select:
  - name: "Fan1 Oscillation angle"
    state: "{% if not state_attr('fan.fan1', 'oscillating')  %}{{0}}{% elif states('number.fan_oscillation_angle')|int > 130 %}{{150}}{% else %}{{states('number.fan_oscillation_angle')|int}}{% endif %}"
#    state: "{{ states('number.fan_oscillation_angle')|int if state_attr('fan.fan1', 'oscillating') else '0'}}"
    unique_id: b66f737e-0a21-4aec-ac46-704c28ea0ced
    options: "{{ [0, 30, 60, 90, 120, 150] }}"
    select_option:
      - service: fan.oscillate
        target:
          entity_id: fan.fan1
        data:
          oscillating: "{{ option|int > 0 }}"
      - service: number.set_value
        target:
          entity_id: number.fan_oscillation_angle
        data:
          value: "{% if option|int > 140 %}{{140}}{% elif option|int > 0 %}{{ option|int }}{% else %}{{states('number.fan_oscillation_angle')|int}}{% endif %}"

https://www.home-assistant.io/integrations/template/

option is templatable! I don't want to change the logic behind how option comparisons work, but you could use a template to dynamically set option to either a max or min based on the range you want it to represent.

option: |
  {% set min = 25 %}
  {% set max = 49 %}
  {% if value <= min %}
    {{ min }}
  {% elif value >= max %}
    {{ max }}
  {% else %}
    {{ value }}
  {% endif %}

option is templatable! I don't want to change the logic behind how option comparisons work, but you could use a template to dynamically set option to either a max or min based on the range you want it to represent.

option: |
  {% set min = 25 %}
  {% set max = 49 %}
  {% if value <= min %}
    {{ min }}
  {% elif value >= max %}
    {{ max }}
  {% else %}
    {{ value }}
  {% endif %}

Works like charm - thank you so much!

Fixed the selector option comparison and tooltip layer issues in 4.0.2.