Creating sensors by loop possible?

Hey,
i’ve got a command_line sensor pulling an API for JSON data.
The sensor state is true/false and the attribute contains the data like shown below.

data:
  - id: 1111
    fullname: fullname1
    shortname: shortname1
    status: 1
    status_id: 1
    status_ts: 1606399678
  - id: 2222
    fullname: fullname2
    shortname: shortname2
    status: 2
    status_id: 2
    status_ts: 1606399678
  - id: 3333
    fullname: fullname3
    shortname: shortname3
    status: 3
    status_id: 3
    status_ts: 1606399678
...

I’d like to have a single sensor for each subset with the status as the value and additional info as attributes.
I create as many template sensors by hand as json data is assumed and only change the index of the array.

  - platform: template
    sensors:
      instance_0:
        entity_id: sensor.commandlinetest
        friendly_name_template: "{{ state_attr('sensor.commandlinetest', 'data')[0]['shortname'] }}"
        value_template: >-
          {% if state_attr('sensor.commandlinetest', 'data')[0]['status'] == 1 %}
            one
          {% elif state_attr('sensor.commandlinetest', 'data')[0]['status'] == 2 %}
            two
          {% elif state_attr('sensor.commandlinetest', 'data')[0]['status'] == 3 %}
            three
          {% elif state_attr('sensor.commandlinetest', 'data')[0]['status'] == 4 %}
            four
          {% elif state_attr('sensor.commandlinetest', 'data')[0]['status'] == 5 %}
            five
          {% elif state_attr('sensor.commandlinetest', 'data')[0]['status'] == 6 %}
            six
          {% else %}
            unknown
          {% endif %}
        attribute_templates:
          id: "{{ state_attr('sensor.commandlinetest', 'data')[0]['id'] }}"
          fullname: "{{ state_attr('sensor.commandlinetest', 'data')[0]['fullname'] }}"
          date: "{{ state_attr('sensor.commandlinetest', 'data')[0]['status_ts'] | timestamp_custom('%d.%m.%Y %H:%M:%S') }}"
      instance_1:
        entity_id: sensor.commandlinetest
        friendly_name_template: "{{ state_attr('sensor.commandlinetest', 'data')[1]['shortname'] }}"
        value_template: >-
          {% if state_attr('sensor.commandlinetest', 'data')[1]['status'] == 1 %}
            one
          {% elif state_attr('sensor.commandlinetest', 'data')[1]['status'] == 2 %}
            two
          {% elif state_attr('sensor.commandlinetest', 'data')[1]['status'] == 3 %}
            three
          {% elif state_attr('sensor.commandlinetest', 'data')[1]['status'] == 4 %}
            four
          {% elif state_attr('sensor.commandlinetest', 'data')[1]['status'] == 5 %}
            five
          {% elif state_attr('sensor.commandlinetest', 'data')[1]['status'] == 6 %}
            six
          {% else %}
            unknown
          {% endif %}
        attribute_templates:
          id: "{{ state_attr('sensor.commandlinetest', 'data')[1]['id'] }}"
          fullname: "{{ state_attr('sensor.commandlinetest', 'data')[1]['fullname'] }}"
          date: "{{ state_attr('sensor.commandlinetest', 'data')[1]['status_ts'] | timestamp_custom('%d.%m.%Y %H:%M:%S') }}"
...

Is there any way to solve this with a loop?
And what about a switch statement instead if/else?

1 Like

The best you can do is have the template editor write the yaml for you. But to be honest, the reason it’s so difficult is because of the way you wrote your template. If you use variables, then you’d only need to adjust a few fields in your template sensor. Also, you can use a dictionary or list to streamline those if statements.

  - platform: template
    sensors:
      instance_0:
        entity_id: sensor.commandlinetest
        friendly_name_template: "{{ state_attr('sensor.commandlinetest', 'data')[0]['shortname'] }}"
        value_template: >-
          {% set values = [ 'one', 'two', 'three', 'four', 'five', 'six' ] %}
          {% set status = state_attr('sensor.commandlinetest', 'data')[0]['status'] | int - 1 %}
          {{ values[status] if status in range(values | length) else 'unknown' }}
        attribute_templates:
          id: "{{ state_attr('sensor.commandlinetest', 'data')[0]['id'] }}"
          fullname: "{{ state_attr('sensor.commandlinetest', 'data')[0]['fullname'] }}"
          date: "{{ state_attr('sensor.commandlinetest', 'data')[0]['status_ts'] | timestamp_custom('%d.%m.%Y %H:%M:%S') }}"

and if you don’t understand dicts or lists… here’s what using a variable would look like with your if statements.

  - platform: template
    sensors:
      instance_0:
        entity_id: sensor.commandlinetest
        friendly_name_template: "{{ state_attr('sensor.commandlinetest', 'data')[0]['shortname'] }}"
        value_template: >-
          {% set status = state_attr('sensor.commandlinetest', 'data')[0]['status'] %}
          {% if status == 1 %}
            one
          {% elif status == 2 %}
            two
          {% elif status == 3 %}
            three
          {% elif status == 4 %}
            four
          {% elif status == 5 %}
            five
          {% elif status == 6 %}
            six
          {% else %}
            unknown
          {% endif %}
        attribute_templates:
          id: "{{ state_attr('sensor.commandlinetest', 'data')[0]['id'] }}"
          fullname: "{{ state_attr('sensor.commandlinetest', 'data')[0]['fullname'] }}"
          date: "{{ state_attr('sensor.commandlinetest', 'data')[0]['status_ts'] | timestamp_custom('%d.%m.%Y %H:%M:%S') }}"

in both cases, you’re making 5 edits instead of 11 with each copy/paste.

Okay, got it! I’ll optimize the template. Thank you.
But what about a loop for building these sensor/instances_x? No chance for avoiding copy/paste?

No way to avoid copy/paste.