Values in variable are deleted again after for-loop

i have a series of ble sensors and would like to create a text sensor that will tell me which sensors are unavailable if needed.
But my problem is: I can find these sensors, but the variables are deleted again after the if or the for loop, so they are empty again. what am I doing wrong?

{% set sensors = [
    'sensor.klimasensor_1',
    'sensor.klimasensor_2',
    'sensor.klimasensor_3',
    'sensor.klimasensor_4',
    'sensor.klimasensor_5',
    'sensor.klimasensor_6',
    'sensor.klimasensor_7',
    'sensor.klimasensor_8',
] %}

{% set counter = 0 %}
{% set offline_sensors = [] %}

{% for sensor in sensors %}
  {% set voltage_state = states(sensor + '_voltage') %}
  {% set temperature_state = states(sensor + '_temperature') %}
  {% set humidity_state = states(sensor + '_humidity') %}
  {% if voltage_state == 'unavailable' or temperature_state == 'unavailable' or humidity_state == 'unavailable' %}
    {% set counter = counter + 1 %}
    {% set offline_sensors = offline_sensors + [sensor.object_id.split('_')[1]] %}
  {% endif %}
{% endfor %}

{% if counter > 0 %}
  {{ 'Die folgenden Sensoren sind offline: ' + ', '.join(offline_sensors) }}
{% else %}
  Alles Sensoren sind online.
{% endif %}

My understanding is variables is not available outside of the block they are defined, i.e. scope of variables.
You can try using namespace.

Example using namespace from @petro

Thank you for pointing that out, that is certainly the reason. I got it!

        {% set offline_sensors = namespace(latest=[], data=[]) %}
        {% for sensor in sensors %}
          {% set voltage_state = states(sensor + '_voltage') %}
          {% set temperature_state = states(sensor + '_temperature') %}
          {% set humidity_state = states(sensor + '_humidity') %}
          {% if voltage_state == 'unavailable' or temperature_state == 'unavailable' or humidity_state == 'unavailable' %}
            {% set offline_sensors.data = offline_sensors.data + [sensor.split('_')[1]] %}
          {% endif %}
        {% endfor %}
        {% set offline_sensors.latest = offline_sensors.data %}
        {% if offline_sensors.data | length > 0 %}
          {{ 'Die folgenden BLE-Sensoren sind offline: ' + ', '.join(offline_sensors.data) }}
        {% else %}
          Alle BLE-Sensoren sind aktuell online.
        {% endif %}

If I understood the purpose of your template correctly, I believe you can achieve your goal without using a for-loop.

{% set sensors = states.sensor
  | selectattr('object_id', 'match', 'klimasensor_[0-9]_(voltage|temperature|humidity)')
  | selectattr('state', 'eq', 'unavailable')
  | map(attribute='object_id')
  | map('regex_replace', '(klimasensor_|_voltage|_temperature|_humidity)', '')
  | unique | list %}
{% if sensors | count > 0 %}
  Die folgenden BLE-Sensoren sind offline: {{ sensors | join(', ') }}
{% else %}
  Alle BLE-Sensoren sind aktuell online.
{% endif %}

oh, cool, thank You! That’s even more elegant :+1:

1 Like

You’re welcome!

So what was your choice? Did you choose to continue using a for-loop, with a namespace variable, or what I suggested?

I have adopted your code. But the problem with the variables formulated in the title can indeed be solved by namespace. Both work, but I find the second solution easier.