How to write less repetitive code? Is there a way to define a function?

Hey guys,
I’m trying to create a card that will show all my devices’ wifi signal (got a bunch of em as you imagine)
Some of them give their wifi str as DB so im trying to convert them to %, which i did with the following code:

sensor: 
  - platform: template
    sensors:
      sonoff_ewelink_rssi_irrigation:
        unit_of_measurement: '%'
        value_template: >-
          {% if is_state('switch.sonoff_1000_1', 'unavailable') %}
            Disconnected
          {% elif states.switch.sonoff_1000_1.attributes.rssi |int  <-100 %}
            0
          {% elif states.switch.sonoff_1000_1.attributes.rssi |int >-50 %}
           100
          {% else %}
           {{2* (( states.switch.sonoff_1000_1.attributes.rssi |int)+100)}}
          {% endif %} 
        icon_template: >-
          mdi:wifi

That’s great and it works fine.
Thing is i need to do it like 25 times to get my 25 different devices converted.

Is there a way to simplify this?

Something like

#somehow define the conversion as "predefined_function" then:
sensor: 
  - platform: template
    sensors:
      sonoff_ewelink_rssi_irrigation:
       predefined_function(switch.sonoff_1000_1)

Thanks In advance!

1 Like

YAML anchors.

1 Like

Hey, thanks once again!
I read it and also went through the full guide you have about yaml.
Some good examples there I didn’t even know

Unfortunately, I fail to see how I can simplify and multiply ~x15 the code above with anchors.

Could you give me an example perhaps?

I don’t know why it’s not much highlighted, it seems to be not much used, but I have just discovered you can pass arguments to scripts and use them in many automations. For exemple, you can have a same same script with same actions, and use it with different entity_id in your different automations.

Documentation : Passing variables to scripts

An exemple of a script I use to turn on my lights :

script:
    turn_on_circ:
      alias: "Turn on circacian light"
      sequence:
        - service: light.turn_on
          data_template :
            entity_id: "{{entity_id}}"
            brightness_pct: "{{[states.sensor.circadian_values.state|int+110, 100]|min}}"
            kelvin: "{{states.sensor.circadian_values.attributes.colortemp|int}}"
            transition: "{%if states[entity_id].state == 'on'%}{{states[entity_id].attributes.brightness|int//2}}{% else %}2{% endif %}"

And an example of an automation :

automation:
    - alias: eclairage_escalier_on
      id: eclairage_escalier_on
      initial_state: true
      trigger:
        - platform: state
          entity_id: binary_sensor.escalier_mvt, binary_sensor.mezzanine_mvt
          from: "off"
          to: "on"

      condition:
        - condition: numeric_state
          entity_id: sensor.salle_manger_lux
          below: 60

      action:
        - service: script.turn_on_circ
          data_template :
            entity_id: light.escalier
3 Likes

Functions in templates are called macros. For example here is one I use that adds minutes to a time.

{% macro add_time(time, add_minutes) %}
  {% if time|lower != "unavailable" %}
    {% set time = time.split(":") %}
    {% set hour = time[0]|int %}
    {% set minutes = time[1]|int %}
    {% if (minutes + add_minutes) < 60 %}
      {{ "%0.02d:%0.02d"|format(hour, minutes + add_minutes) }}
    {% else %}
      {{ "%0.02d:%0.02d"|format(hour + 1, (minutes + add_minutes) - 60) }}
    {% endif %}
  {% endif %}
{% endmacro %}

What time will it be in 30 minutes: {{ add_time(states("sensor.time"), 30) }}

However, that doesn’t solve your problem, because macros don’t exist globally.

Is what I think you really want is the decluttering_card component. Which can be installed via HACS.

Here is an example of how I reuse code to simplify my lovelace code.

- type: custom:decluttering-card
  template: button
  variables:
    - entity: switch.bedroom_fan
    - icon: mdi:fan
    - name: Bed Room

The template that creates the button looks like this:

default:
  - entity: light.dummy
  - icon: mdi:light-switch
  - name: dummy
  - lock: false
  - tap_action:
      action: toggle
  - hold_action:
      action: more-info
  - show_state: true
  - type: icon

card:
  type: custom:button-card
  color_type: "[[type]]"
  entity: "[[entity]]"
  name: "[[name]]"
  tap_action: "[[tap_action]]"
  hold_action: "[[hold_action]]"
  show_state: "[[show_state]]"
  icon: "[[icon]]"
  lock:
    enabled: "[[lock]]"
  styles:
    grid:
      - grid-template-areas: '"i" "n" "s"'
      - grid-template-columns: 1fr
      - grid-template-rows: 1fr min-content min-content
    img_cell:
      - align-self: start
      - text-align: start
    name:
      - justify-self: start
      - padding-left: 10px
      - font-weight: bold
      - text-transform: lowercase
    state:
      - justify-self: start
      - padding-left: 10px
  state:
    - value: unlocked
      icon: mdi:lock-open
    - value: locked
      icon: mdi:lock
      styles:
        card:
          - filter: opacity(50%)
        icon:
          - filter: grayscale(100%)
    - value: 'off'
      styles:
        card:
          - filter: opacity(50%)
        icon:
          - filter: grayscale(100%)
    - value: unavailable
      styles:
        card:
          - filter: opacity(25%)
        icon:
          - filter: grayscale(100%)
    - value: closed
      styles:
        card:
          - filter: opacity(50%)
        icon:
          - filter: grayscale(100%)
    - value: open
      icon: >
        [[[
          if (entity.entity_id == "cover.garage_door")
            return "mdi:garage-open";
          return "[[icon]]";
        ]]]
1 Like

Faced same problem - a lot of template sensors with common parts inside the value_template. Is it possible to use anchors inside the value_template: >- statement?