Select working weather sensor automatically: automation creates an infinite loop

My automation causes an infinite loop in some cases if “mode: queued”.
In case of “mode: single” this does not happen.

There are 3 weather sensors for 3 different providers:

weather.home_met
weather.home_openweathermap
weather.home_gismeteo

I have a Weather card on Lovelace showing a weather from some of those sensors.
To select a weather sensor I use an input_select with 3 options:

input_select:
  weather_provider:
    options:
      - "Met"
      - "OpenWeatherMap"
      - "Gismeteo"
    icon: mdi:weather-pouring

If “Met” is selected then the Weather card uses “weather.home_met” sensor and so on.

Initially I decided to use 3 providers because sometimes some sensors are “unknown” or “unavailable”.
So, if I observe an absence of data on the Weather card, I usually switch to another sensor.

Once I decided to automate this selection using this algorithm:

  1. If the selected weather sensor becomes “unknown” or “unavailable” - then try to select another sensor (service: input_select.select_next).
  2. If the next selected weather sensor is also “unknown” or “unavailable” - then try to select another sensor - until the first initial sensor is selected (means “all sensors are not working”).
  3. If some not-selected weather sensor becomes working - then select this sensor.
  4. The same steps Nos 1-2 are to be executed in case of manually selecting an option in the input_select field.

Here is the code:

automation:
  - alias: "weather: Select available provider"
    id: "weather_select_available_provider"
    description: ''
    mode: single

    variables:
      USER_SELECTED_PROVIDER: '{{ states("input_select.weather_provider") | lower }}'

    trigger:
      - platform: state
        entity_id: input_select.weather_provider

      - platform: state
        entity_id: weather.home_met
        # from: &ref_from_to
        #   - "unknown"
        #   - "unavailable"
        # to: *ref_from_to

      - platform: state
        entity_id: weather.home_openweathermap
        # from: *ref_from_to
        # to: *ref_from_to

      - platform: state
        entity_id: weather.home_gismeteo
        # from: *ref_from_to
        # to: *ref_from_to

    condition:
      - condition: template
        value_template: >-
          {% set WEATHER_SENSOR = "weather.home_" + USER_SELECTED_PROVIDER -%}
          {{ states(WEATHER_SENSOR) in ['unavailable','unknown'] or
             trigger.from_state.state in ['unavailable','unknown'] or
             trigger.to_state.state in ['unavailable','unknown'] }}

    action:
      - repeat:
          while:
            - condition: template
              value_template: >-
                {% set PROVIDER = states("input_select.weather_provider") | lower -%}
                {%- set WEATHER_SENSOR = "weather.home_" + PROVIDER -%}
                {{ states(WEATHER_SENSOR) in ['unavailable','unknown'] and repeat.index <= 3 }}

          sequence:
            - service: input_select.select_next
              entity_id: input_select.weather_provider
            - delay:
                milliseconds: 100

      - service: notify.telegram_chat_weather
        data:
          message: |-
            weather: default provider changed:
            {{ USER_SELECTED_PROVIDER }} -> {{ states("input_select.weather_provider") | lower }}

Note that “for:” & “to:” options are commented since the same is achieved by the templated conditions.
Also, the “delay:” was added just in case - and may I remove it?

So, the automation seems to work smooth:

  1. If I manually try to select a non-working sensor - it will be replaced with the 1st working sensor - or it will stay if all sensors are not working.
  2. If the selected sensor becomes not-working - it will be replaced with the 1st working sensor - or it will stay if all sensors are not working.

But I am not sure that I should use the “mode: single” option. May be it should be “queued”?

If the last case I observe an infinite loop in this scenario:

  1. All three sensors are working, the 1st sensor is selected.
  2. The selected sensor becomes “unknown” - then the 2nd sensor is selected.
  3. The selected sensor becomes “unknown” - then the 3rd sensor is selected.
  4. The selected sensor becomes “unknown” - then the 3rd sensor is still selected.
  5. The 1st sensor becomes working - then I see an infinite loop instead of selecting the 1st sensor.

My questions are:

  1. The question about the “delay:”.
  2. Should I stay with the “mode: single” option?
  3. What could cause the infinity loop?

I haven’t explored your automation in depth but this stands out:

The automation’s action employs a repeat that changes the value of an input_select. It’s the same input_select that is monitored by the automation’s State Trigger. Every time the repeat changes the input_select’s value it triggers the automation and, because its mode is queued, spawns another instance of itself.

Taras, thanks for a quick reply!
So, changing the input_select triggers the same automation - then we get a loop.
I think I will stay with the “mode: single” then.

Also, I optimized the script a bit:

    condition:
      - condition: template
        value_template: >-
          {% set WEATHER_SENSOR = "weather.home_" + USER_SELECTED_PROVIDER -%}
          {{ states(WEATHER_SENSOR) in ['unavailable','unknown'] or
             (trigger.from_state.state in ['unavailable','unknown'] and
              not trigger.to_state.state in ['unavailable','unknown']) }}

Now the script is running a bit less often:

  1. If the selected sensor becomes bad.
  2. If some sensor (selected or another) becomes working.

When using queued mode, you have to be careful when designing actions that will re-trigger the automation.

If used judiciously, it can be useful. For example, the automation for the following multi-zone irrigation controller is designed to call itself:

The automation changes value that are monitored by all three of its triggers.

Thank for a learning example!

The final edition of the condition:

    condition:
      - condition: template
        value_template: >-
          {% set WEATHER_SENSOR = "weather.home_" + USER_SELECTED_PROVIDER -%}
          {{
            states(WEATHER_SENSOR) in ['unavailable','unknown'] and
            (
              (
                trigger.from_state.state in ['unavailable','unknown'] and
                not trigger.to_state.state in ['unavailable','unknown'] and
                not trigger.entity_id | regex_match("input_select",ignorecase=False)
              )
              or
              (
                not trigger.from_state.state in ['unavailable','unknown'] and
                trigger.to_state.state in ['unavailable','unknown'] and
                trigger.entity_id | regex_match(WEATHER_SENSOR,ignorecase=False)
              )
              or
                trigger.entity_id | regex_match("input_select",ignorecase=False)
            )
          }}