Script with multiple conditional actions

Hi,
I’ve searched the forum for solutions to this but haven’t found any.

I have a input text helper that I continously update with different values (based on sensors etc. in HA). The helper is mirrored to a dot matrix display powered via ESPHome. It serves as an information display that shows “crucial” information for the household. I have solved this with a script does the following:

  • Show outside temperature + pause for 3 seconds
  • Show weather forecast + pause for 3 seconds
  • Show car battery percent + pause for 3 seconds
  • Show car battery charging status + pause for 3 seconds
  • Show car preheating status + pause for 3 seconds
  • …etc
  • Repeat sequence

But, let’s say that I only want to show certain info during certain conditions, for example:

  • Show outside temperature + pause for 3 seconds
  • Show weather forecast + pause for 3 seconds
  • Show car battery percent + pause for 3 seconds
  • Show car battery charging status + pause for 3 seconds Only if car battery is charging
  • Show car preheating status + pause for 3 seconds Only if car is preheating
  • …etc
  • Repeat sequence

Is that possible, and in that case how? Maybe there are other ways to get the same result?

Yes, it’s possible with a choose statement.

Post the script you have created and I can help you modify it.


EDIT

There’s another way to do it (without using choose) but I would first have to see your script to confirm it can be implemented.

1 Like

Ok, thank you!

Here it is. For information the script usually is initiated by an automation that starts it on HA startup, and it repeats while an input boolean is set to true (if that condition causes problems, it can be removed)

repeat:
  while:
    - condition: state
      entity_id: input_boolean.max7219_aktiv
      state: 'on'
  sequence:
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: '{{ states("sensor.time") | string }}'
    - wait_template: ''
      timeout: '4'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: '{{ states("sensor.date") | string }}'
    - wait_template: ''
      timeout: '4'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: >-
          {{ states("sensor.vader_svenska") | string }}, {{
          states("sensor.thermiq_mqtt_outdoor_t") | string }}°C
    - wait_template: ''
      timeout: '8'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: 'Bilbatteri: {{ states("sensor.grandland_battery_autonomy") | int }} %'
    - wait_template: ''
      timeout: '5'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: 'Bil, laddning: {{ states("sensor.grandland_charging_status")}}'
    - wait_template: ''
      timeout: '8'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: >-
          Bil, förvärmning: {{
          states("sensor.grandland_preconditioning_status")}}
    - wait_template: ''
      timeout: '8'

How were you planning to check for:

  • Only if car battery is charging
  • Only if car is preheating

For example, were you planning to check if the value of sensor.grandland_charging_status is above a certain threshold to indicate if the car battery is charging or not?

Hi,

Sorry, i missed that. Almost like that, I will look at sensor.grandland_preconditioning_status and sensor.grandland_charging_status has a certain state (“Pågår”, which basically means “on”). I will try to describe them with pseudo-code below:

if (sensor.grandland_charging_status == "Pågår")
{
   show  'Bil, laddning: {{ states("sensor.grandland_charging_status")}}'
   pause 8 seconds
}
if (sensor.grandland_preconditioning_status == "Pågår")
{
   show  'Bil, förvärmning: {{"states("sensor.grandland_preconditioning_status")}}
   pause for 8 seconde
}

I recommend defining a list called items where each one of its elements is a dictionary consisting of an item and delay. Templates define the values of each item. If the item should not be displayed, the template produces a value of OMIT. Another template produces a list called display that rejects all items containing OMIT.

A repeat-count loops through all elements in the display list, writing each item's value to the input_text (and waiting for whatever number of seconds specified by its associated delay value). An outer repeat-while continues repeating the inner repeat-count while the input_boolean is on.

script:
  show_items:
    sequence:
      - variables:
          items:
            - item: "{{ states('sensor.time') }}"
              delay: 4
            - item: "{{ states('sensor.date') }}"
              delay: 4
            - item: "{{ states('sensor.vader_svenska') }}, {{ states('sensor.thermiq_mqtt_outdoor_t') }}°C"
              delay: 8
            - item: "Bilbatteri: {{ states('sensor.grandland_battery_autonomy') }} %"
              delay: 5
            - item: >
                {% set x = states('sensor.grandland_charging_status') %}
                {{ iif(x == 'Pågår', 'Bil, laddning: ' ~ x, 'OMIT') }}
              delay: 8
            - item: >
                {% set x = states('sensor.grandland_preconditioning_status') %}
                {{ iif(x == 'Pågår', 'Bil, förvärmning: ' ~ x, 'OMIT') }}
              delay: 8
          display: "{{ items | rejectattr('item', 'eq', 'OMIT') | list }}"
      - repeat:
          while: "{{ is_state('input_boolean.max7219_aktiv', 'on') }}"
          sequence:
            - repeat:
                count: '{{ display | count }}'
                sequence:
                  - service: input_text.set_value
                    target:
                      entity_id: input_text.max7219_feed
                    data:
                      value: '{{ display[repeat.index - 1].item }}'
                  - delay:
                      seconds: '{{ display[repeat.index - 1].delay }}'

This script is untested so let me know if you encounter any errors and I’ll help you correct them.

If you dislike the idea of replacing your existing script with what I proposed above, you can add two choose statements to your existing script as shown below:

repeat:
  while:
    - condition: state
      entity_id: input_boolean.max7219_aktiv
      state: 'on'
  sequence:
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: '{{ states("sensor.time") | string }}'
    - wait_template: ''
      timeout: '4'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: '{{ states("sensor.date") | string }}'
    - wait_template: ''
      timeout: '4'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: >-
          {{ states("sensor.vader_svenska") | string }}, {{
          states("sensor.thermiq_mqtt_outdoor_t") | string }}°C
    - wait_template: ''
      timeout: '8'
    - service: input_text.set_value
      data_template:
        entity_id: input_text.max7219_feed
        value: 'Bilbatteri: {{ states("sensor.grandland_battery_autonomy") | int }} %'
    - wait_template: ''
      timeout: '5'
    - choose:
        - conditions: '{{ is_state("sensor.grandland_charging_status", "Pågår") }}'
          sequence:
            - service: input_text.set_value
              data_template:
                entity_id: input_text.max7219_feed
                value: 'Bil, laddning: Pågår'
            - wait_template: ''
              timeout: '8'
      default: []
    - choose:
        - conditions: '{{ is_state("sensor.grandland_preconditioning_status", "Pågår") }}'
          sequence:
            - service: input_text.set_value
              data_template:
                entity_id: input_text.max7219_feed
                value: 'Bil, förvärmning: Pågår'
            - wait_template: ''
              timeout: '8'
      default: []

This looks like a very clean solution that makes it easy to add items. Thank you for the suggestion!

However, I get an error: Message malformed: Unable to determine action @ data['sequence'][0]. Is this because there are 2 sequence blocks?

To test the script, I replaced your entities with my own and it produced no errors and worked the way you want (display information in sequence except for excluded information).

If you received an error message then I can only guess that you either modified it or made some sort of copy-paste error.

You were right, there were a copy-paste error. Now i can run it. Thanks!

However, there is one problem: If one of the “conditional” sensors change state when the script is running, the change isn’t taken care of correctly. For example, i changed sensor.grandland_preconditioning_status to “Pågår” when the script was running, but the script didn’t invoke the change (although, I think that maybe the delay was invoked?). However, when i restarted the script while the sensor was in that state, it was invoked correctly.

Maybe the items needs to be updated in the repeat while-loop?

Move variables into the outer loop (repeat-while).

script:
  show_items:
    sequence:
      - repeat:
          while: "{{ is_state('input_boolean.max7219_aktiv', 'on') }}"
          sequence:
            - variables:
                items:
                  - item: "{{ states('sensor.time') }}"
                    delay: 4
                  - item: "{{ states('sensor.date') }}"
                    delay: 4
                  - item: "{{ states('sensor.vader_svenska') }}, {{ states('sensor.thermiq_mqtt_outdoor_t') }}°C"
                    delay: 8
                  - item: "Bilbatteri: {{ states('sensor.grandland_battery_autonomy') }} %"
                    delay: 5
                  - item: >
                      {% set x = states('sensor.grandland_charging_status') %}
                      {{ iif(x == 'Pågår', 'Bil, laddning: ' ~ x, 'OMIT') }}
                    delay: 8
                  - item: >
                      {% set x = states('sensor.grandland_preconditioning_status') %}
                      {{ iif(x == 'Pågår', 'Bil, förvärmning: ' ~ x, 'OMIT') }}
                    delay: 8
                display: "{{ items | rejectattr('item', 'eq', 'OMIT') | list }}"
            - repeat:
                count: '{{ display | count }}'
                sequence:
                  - service: input_text.set_value
                    target:
                      entity_id: input_text.max7219_feed
                    data:
                      value: '{{ display[repeat.index - 1].item }}'
                  - delay:
                      seconds: '{{ display[repeat.index - 1].delay }}'

Thank you. Works like a charm!

1 Like