Help converting multiple elif's to something less ugly

I’ve created this sensor using 6 binary inputs to generate a single int output. I know there has to be a smarter way to go about this but my searching hasn’t helped me out. Could someone point me in the right direction?

template:
  - sensor:
      - name: Current Displayed Channel
        state: >
          {% if is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'off') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'off') %}
            1
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'on') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'on') %}
            2
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'on') %}
            3
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'off') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'on') %}
            4
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'off') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            5
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'off') and is_state('binary_sensor.digit2_e', 'on') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            6
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'off') %}
            7
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'on') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            8
          {% elif is_state('binary_sensor.digit1', 'off') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            9
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'on') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'off') %}
            10
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'off') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'off') %}
            11
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'on') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'on') %}
            12
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'off') and is_state('binary_sensor.digit2_g', 'on') %}
            13
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'off') and is_state('binary_sensor.digit2_b', 'on') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            14
          {% elif is_state('binary_sensor.digit1', 'on') and is_state('binary_sensor.digit2_a', 'on') and is_state('binary_sensor.digit2_b', 'off') and is_state('binary_sensor.digit2_e', 'off') and is_state('binary_sensor.digit2_f', 'on') and is_state('binary_sensor.digit2_g', 'on') %}
            15
          {% else %}
            0
          {% endif %}

You are converting an arbitrary display (7 segment) into a number. There isn’t really an easier way. This is more compact but less readable:

        state: >
          {% set d1 = states('binary_sensor.digit1')|bool(0)|int %}
          {% set a = states('binary_sensor.digit2_a')|bool(0)|int %}
          {% set b = states('binary_sensor.digit2_b')|bool(0)|int %}
          {% set e = states('binary_sensor.digit2_e')|bool(0)|int %}
          {% set f = states('binary_sensor.digit2_f')|bool(0)|int %}
          {% set g = states('binary_sensor.digit2_g')|bool(0)|int %}
          {% set bin = (a ~ b ~ e ~ f ~ g)|string %}
          {% if bin == '01000' %}
            {{ (d1 ~ 1)|int }}
          {% elif bin == '11101' %}
            {{ (d1 ~ 2)|int }}
          {% elif bin == '11001' %}
            {{ (d1 ~ 3)|int }}
          {% elif bin == '01001' %}
            {{ (d1 ~ 4)|int }}
          {% elif bin == '10011' %}
            {{ (d1 ~ 5)|int }}
          {% elif bin == '10111' %}
            {{ (d1 ~ 6)|int }}
          {% elif bin == '11000' %}
            {{ (d1 ~ 7)|int }}
          {% elif bin == '11111' %}
            {{ (d1 ~ 8)|int }}
          {% elif bin == '11011' %}
            {{ (d1 ~ 9)|int }}
          {% else %}
            0
          {% endif %}

Or if your numbers displayed don’t go above 15:

        state: >
          {% set d1 = states('binary_sensor.digit1')|bool(0)|int %}
          {% set a = states('binary_sensor.digit2_a')|bool(0)|int %}
          {% set b = states('binary_sensor.digit2_b')|bool(0)|int %}
          {% set e = states('binary_sensor.digit2_e')|bool(0)|int %}
          {% set f = states('binary_sensor.digit2_f')|bool(0)|int %}
          {% set g = states('binary_sensor.digit2_g')|bool(0)|int %}
          {% set bin = (a ~ b ~ e ~ f ~ g)|string %}
          {% if bin == '01000' %}
            {{ (d1 ~ 1)|int }}
          {% elif bin == '11101' %}
            {{ (d1 ~ 2)|int }}
          {% elif bin == '11001' %}
            {{ (d1 ~ 3)|int }}
          {% elif bin == '01001' %}
            {{ (d1 ~ 4)|int }}
          {% elif bin == '10011' %}
            {{ (d1 ~ 5)|int }}
          {% elif bin == '10111' %}
            6
          {% elif bin == '11000' %}
            7
          {% elif bin == '11111' %}
            8
          {% elif bin == '11011' %}
            9
          {% else %}
            0
          {% endif %}
1 Like

Not even knowing what you want with this but in reality you have 64 combinations, as Tom said your first one is more readable but a possible (?) alternative is that you combine certain settings

1 Like

There are actually less than that if they only expect the digits 0 to 15 to be displayed on the 7 segment displays, which is what it looks like from the original template.

Even if they wanted 0 to 99 there are only 10 combinations to decode (twice) if you decode it digit by digit then concatenate them into decimal.

1 Like

If your goal is to get rid of the elif’s, you could take the first half of Tom’s template then use a map…

state: >
  {% set d1 = states('binary_sensor.digit1')|bool(0)|int %}
  {% set a = states('binary_sensor.digit2_a')|bool(0)|int %}
  {% set b = states('binary_sensor.digit2_b')|bool(0)|int %}
  {% set e = states('binary_sensor.digit2_e')|bool(0)|int %}
  {% set f = states('binary_sensor.digit2_f')|bool(0)|int %}
  {% set g = states('binary_sensor.digit2_g')|bool(0)|int %}
  {% set bin = (a ~ b ~ e ~ f ~ g)|string %}
  {% set mapper = {
    '01000': '1', '11101': '2', '11001': '3',
    '01001': '4', '10011': '5', '10111': '6',
    '11000': '7', '11111': '8', '11011': '9' } %}
  {% if bin in mapper.keys() %}
    {{ (d1 ~ mapper.get(bin)) | int }}
  {% else %} 0 {% endif %}
2 Likes
template:
  - sensor:
      - name: Current Displayed Channel
        state: >
          {% set i = expand('binary_sensor.digit2_a', 'binary_sensor.digit2_b', 'binary_sensor.digit2_e',
            'binary_sensor.digit2_f', 'binary_sensor.digit2_g') | map(attribute='state')
            | map('bool', false) | map('int', 0) | join | int(0, 2) %}
          {% set d = {8: 1, 29: 2, 25: 3, 9: 4, 19: 5, 23: 6, 24: 7, 31: 8, 27: 9} %}
          {{ (states('binary_sensor.digit1') | bool(false) | int(0) ~ d.get(i)) | int(0) if i in d.keys() else 0 }}
3 Likes

Thanks for all the great suggestions. As some background, I’m interfacing with a 15 channel 433 RF remote that uses rolling codes. Using the RasbPi GPIO I’m going to read in the two 7 seg displays to determine which channel it is currently set to then output back to the remote buttons to change channels and perform other functions (it’s a remote for numerous roller shutters).

Using the original posted code with all the elsif’s works but I thought there must be a better way and it’s a good opportunity to improve my skills by working on a real world example.

It’s going to take me a bit to digest the solutions you have all so kindly contributed but from the outset they look interesting and I’m curious to work through each one.