Determine which condition is met, in the action section

Hello!

Not being happy with the naming of my automation I decided to reorganize them - naming them by the trigger and not using the actions being performed.
I reduced the number of automations and in general I like the current setup.

What I miss is the option to identify the condition. What I mean is that for automations that have single trigger but are meant to perform different action during different periods of the day you have to place conditions in the action.

It works despite not not looking good and as a result you cannot rely on the “last_triggered” attribute - the automation is being triggered every time the trigger expression is evaluated to true and the actions are “performed”, well not necessary.
Since the conditions are now present in the actions the logic might actually stop the automation and in reality no action is being performed.

Introducing condition_id, similar to the triggers id would allow moving the logic for the conditions to the logical sections - conditions, keeping the actions related to a single trigger in one place (without the need of creating additional entities and helpers) and the “last_triggered” attribute will reflect when the automation has indeed started any of defined actions.

Edit:
Here are the benefits, in some use cases:

Here is a preview, one way of achieving it:

alias: "Front door opened"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: a2d4121164bi8bbf6189e359e379ec42
    entity_id: 07069fi24f93c54e51003d3100b024f5
    domain: binary_sensor
condition:   
  - condition: or  
    id: dark  
    conditions:  
    - condition: sun  
      after: sunset  
    - condition: numeric_state  
      entity_id: sensor.front_door_sensor_illuminance  
      below: 810        
  - condition: time
    id: evening
    after: "17:00:00"
    before: "23:00:00"
  - condition: time  
    id: active_hours  
    after: "12:00:00"  
    before: "23:00:00"  
action:
  ## is it dark
  - if:
    condition_id:       
      - dark
      - evening
    then:
      - service: light.turn_on
        metadata: {}
        data: {}
        target:
          entity_id:
            - light.entrance_ceiling_lights
  ## is it during active hours
  - if:
    condition_id: active_hours
    then:
      - service: script.fresheners_spray_area
        data:
          spray_count: 2
          spray_in_areas: []

Hi @neohidra

Have you got an example automation that could be improved by your suggestion?

Most of the times when you have multiple triggers and multiple actions you also use the choose.
In the conditions of the choose you add the conditions you want and leave the “top level” conditions empty.

I do not believe it will be neater with condition_ids. I’d rather have the conditions in the choose and see both the trigger id and the additional conditions you want for this specific action.

Here is one example I have with trigger_id and conditions.

action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - dörren
          - condition: state
            entity_id: input_boolean.david_utrop
            state: "on"
          - condition: state
            entity_id: person.david
            state: home
          - condition: time
            after: "07:00:00"
            before: "09:00:00"
            weekday:
              - mon
              - tue
              - wed
              - thu
              - fri
        sequence:
          - service: tts.cloud_say
            metadata: {}
            data:
              entity_id: media_player.hela_huset
              message: David glöm inte låsa dörren när du går
              language: sv-SE

I am not having multiple triggers - just a single one. And would like to perform different actions.

How so it won’t be neater - conditions in the “actions” section, while there is a dedicated “conditions” section looks more logical to you? If so why are providing an example with trigger id?

This is not very different from what I have and if no condition is matched the “last_triggered” will indicate, false, that the automation has been triggered. Just go check when you automation is being triggered if you don’t believe.

Here is a sample:

alias: "Front door opened"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: a2d4121164bi8bbf6189e359e379ec42
    entity_id: 07069fi24f93c54e51003d3100b024f5
    domain: binary_sensor
condition: []
action:
  ## is it dark
  - if:
    - condition: or
      conditions:
      - condition: sun
        after: sunset
      - condition: numeric_state
        entity_id: sensor.front_door_sensor_illuminance
        below: 810
    - condition: time
      after: "17:00:00"
      before: "23:00:00"
    then:
      - service: light.turn_on
        metadata: {}
        data: {}
        target:
          entity_id:
            - light.entrance_ceiling_lights
            - light.kitchen_ceiling_lights
            - light.livingroom_ceiling_lights
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: light.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: light.entrance_ceiling_light
  ## is it dark and very late
  - if:
      - condition: or
        conditions:
          - condition: sun
            after: sunset
            before: sunrise
          - condition: numeric_state
            entity_id: sensor.front_door_sensor_illuminance
            below: 810
    then:
      - service: light.turn_on
        metadata: {}
        data:
          kelvin: 2000
          brightness_pct: 2
        target:
          entity_id: light.entrance_ceiling_lights
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: light.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: light.entrance_ceiling_lights
  ## is it during active hours
  - if:
    - condition: time
      after: "12:00:00"
      before: "23:00:00"
    then:
      - service: script.fresheners_spray_area
        data:
          spray_count: 2
          spray_in_areas: []

In short the trigger is just one - front door being opened. And dependent on the time:

  • if it is dark and before midnight - turn on the lights
  • if it is after midnight - turn on just the entrance light, very dim
  • if during the day, but not early in the morning - activate the fresheners

I still do not get what you want to achieve. Conditions must all match in order to continue. So there would be a list of id’s that were all met, or there won’t be an action at all to do something with the id’s. How would this help? The situation you describe is either a choose or a sequence of ifs, each having their own conditions.

Besides that - I do not understand the merits of your new aproach. When using one trigger per automation, you will likely need a lot of scripts to avoid duplicate action sequences. Because a situation that needs multiple conditions to be met, also requires multiple triggers (and duplication of all the condition). So you will have multiple automations doing (and testing) the same things. This could explode rapidly.

Also each trigger may do multiple things, each requiring slightly different conditions. So you get less automations, but a lot of added complexity. I get the feeling this request is origination from that problem slowly emerging as you proceed reorganizing automations.

And then, when you decide to change one trigger slightly, you’d need to split up the automation if other actions keep the old trigger.

If multiple triggers can lead to the same action, and actions with multiple conditions need multiple triggers, why would organizing by trigger be advantageous? I instead have one automation for a sequence of actions, listing all the triggers and conditions when it gets executed. If something unexpected happens (or fails to happen) I have only one place to look.

By default you are correct. But that is not the case if using something like this:

condition: or
conditions:
  - condition: time
    after: "14:00:00"
    before: "15:00:00"
  - condition: time
    after: "18:00:00"
    before: "19:00:00"

Will my suggestion impact automations with multiple triggers - No you should be able to write the automation as you like.
I am just stating my use case and if it will negatively impact users, by forcing them to apply this logic to their use case I would say fine forget about it - but I am not requesting such change.
I do not want to change the way things are. All I want is additional functionality, very similar to already existing one - the trigger ids.

Please provide an example. I just want to move the contidions from the “action” section to the “condition” section. This way we get accurate tracking of when the the automation has activated any action (in case no condition is met) and the conditions will be under the section named “conditions”.

I am not asking to remove the option to place conditions in the “action” section - there is a use case for them being used in the “action” section.

And again - if there are multiple triggers do not use conditions_id - I am not going to use them.

I want just to have option to assign an ID based on matched condition when there is a single trigger without the need to use additional entities and helpers.

The example of why you need multiple triggers if you have multiple conditions that need to be met at the same time I explained here, in the community guides, under “why does my automation does not always work”).

Assigning ids to conditions is not the same as having trigger ids. There’s always exactly one trigger activating an automation, while multiple conditions may be true. They are always all true if you get to the action block, unless you use an or clause. I left that out in order not to complicate the argument, but if you use an or, only one needs to be true. As soon as HA finds it, it stops evaluating the others. (for a condition a or b or c, if a is true, evaluation stops and the or returns true). So it would not add the id to the list of conditions that are true. It doesn’t know.

Then in the action bit, you still need conditions to map condition id’s to actions. So it is still not clear if actions will be performed when passing the condition block, which is in its nature an and condition.

So please provide a written example automation on how condition ids would work to solve a real life problem that does not conflict with how automations now work. Because the fact that last triggered is no longer of use, is not solved by the ids. And remember, the conditions that are met would be a list, not one single id. We’ll ignore for now id’s could be missing because they were never evaluated.

I do not want to combine multiple triggers and condition - please stop altering the meaning of this request.
This is not related to my request.

That I am not familiar with, it might be the case - I do not know.

Currently, when the all the conditions are in the actions section the automation reports that is has been triggered, while no action is executed.
Moving the conditions in the condition section, and in case that no condition is met - then the automation will not be triggered all all, nothing in the action section will be evaluated.

Since all I get is a complain what will happen if this… what if that…
Let me rephrase my request this way: Please provide a way to distinguish, in the actions section, which conditions, defined in the conditions section, has been evaluated to be true.

I posted my example ten minutes before you said you only had one trigger.

But regarding your example.
What would that look like if you could specify it yourself?

Something like this:

alias: "Front door opened"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: a2d4121164bi8bbf6189e359e379ec42
    entity_id: 07069fi24f93c54e51003d3100b024f5
    domain: binary_sensor
condition:   
  - condition: or  
    id: dark  
    conditions:  
    - condition: sun  
      after: sunset  
    - condition: numeric_state  
      entity_id: sensor.front_door_sensor_illuminance  
      below: 810        
  - condition: time
    id: evening
    after: "17:00:00"
    before: "23:00:00"
  - condition: and   
    id_dark_and_late  
    conditions:    
      - condition: sun    
        after: sunset    
        before: sunrise    
      - condition: numeric_state    
        entity_id: sensor.front_door_sensor_illuminance    
        below: 810    
  - condition: time  
    id: active_hours  
    after: "12:00:00"  
    before: "23:00:00"  
action:
  ## is it dark
  - if:
    condition_id:       
      - dark
      - evening
    then:
      - service: light.turn_on
        metadata: {}
        data: {}
        target:
          entity_id:
            - light.entrance_ceiling_lights
            - light.kitchen_ceiling_lights
            - light.livingroom_ceiling_lights
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: light.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: light.entrance_ceiling_light
  ## is it dark and very late
  - if:
    condition: dark_and_late
    then:
      - service: light.turn_on
        metadata: {}
        data:
          kelvin: 2000
          brightness_pct: 2
        target:
          entity_id: light.entrance_ceiling_lights
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: light.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: light.entrance_ceiling_lights
  ## is it during active hours
  - if:
    condition_id: active_hours
    then:
      - service: script.fresheners_spray_area
        data:
          spray_count: 2
          spray_in_areas: []

I suggest you put a simplified version of your automation example into your first post.

I believe it serves to clarify how you envision a condition_id would help to:

  1. Minimize code redundancy by defining conditions once within the condition section and not repeating them (in full) in the action section.

  2. Ensure the action section is executed only if one of the conditions is fulfilled. If the conditions are exclusively in the action section then, like you pointed out, there’s a possibility none are fulfilled and the automation executes no actions (yet last_triggered is updated).

I have a hard time seeing how this should work with different triggers.
I see how it can function with one trigger as in your example but as soon as there are more triggers then you need a trigger_id in conditions as “input” and a condition_id as output.

Perhaps it works… It needs a lot of consideration to not break everyone’s automations.

In case you’re interested, here’s a way to achieve the advantages of your proposal using existing methods. I’m not saying your FR is unnecessary, just showing another way to achieve the same goals.

First I want to say that the example shown below employs templating so that makes it more challenging to use for new users. Your FR would not require templating and all conditions could be created using the UI. That’s the primary advantage of your FR.

  • A trigger variable named category (the name can be whatever you want) uses a template to compute whether it is currently dark, evening, dark_and_late, active_hours or unknown.

  • The automation’s condition ensures the value of category is not unknown.

  • The automation’s action uses a choose to determine what actions to perform based on the value of the category variable.

alias: "Front door opened"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: a2d4121164bi8bbf6189e359e379ec42
    entity_id: 07069fi24f93c54e51003d3100b024f5
    domain: binary_sensor
    variables:
      category: >
        {% set is_night = is_state('sun.sun', 'below_horizon') %}
        {% set is_dark = states('sensor.front_door_sensor_illuminance') | int(1000) < 810  %}
        {% if is_night or is_dark %} dark
        {% elif 17 <= now().hour < 23 %} evening
        {% elif is_night and is_dark %} dark_and_late
        {% elif 12 <= now().hour < 23 %} active_hours
        {% else %} unknown
        {% endif %}
condition:   
  - condition: template
    value_template: "{{ category != 'unknown' }}"  
action:
  - choose:
      - conditions: "{{ category in ['dark', 'evening'] }}"
        sequence:
          - service: light.turn_on
            target:
              entity_id:
                - light.entrance_ceiling_lights
                - light.kitchen_ceiling_lights
                - light.livingroom_ceiling_lights
          - delay:
              minutes: 5
          - service: light.turn_off
             target:
              entity_id: light.entrance_ceiling_lights
      - conditions: "{{ category == 'dark_and_late' }}"
        sequence:
          - service: light.turn_on
            data:
              kelvin: 2000
              brightness_pct: 2
            target:
              entity_id: light.entrance_ceiling_lights
          - delay:
              minutes: 5
          - service: light.turn_off
            target:
              entity_id: light.entrance_ceiling_lights
      - conditions: "{{ category == 'active_hours' }}"
        sequence:
          - service: script.fresheners_spray_area
            data:
              spray_count: 2
              spray_in_areas: []
    default: []
1 Like

Nice use of variables!

Thank for this suggestion, which is an alternative.

1 Like

Sorry, but you asked “please provide an example” - don’t get angry at me if I then give it. I’m trying to help you. If IDs were implemented, and you could not use them the way you want, that would be a shame.

So I simply want to understand how you think IDs will solve your problem. The example helps to understand what you mean. Unfortunately, the way the conditions block currently works, all id’s need to be true to even get to the action block. So HA would need to drastically change the way the condition block works in order for you to be able to use the IDs the way you want them to. It would be more then just add ids to conditions. That was what I was afraid of.

So the variables approach given above seems to be the best way for you to implement your example.

Good point. The four conditions in neohidra’s example are logically ANDed by default. They would need to be explicitly ORed in order for the example to work as intended for the FR. Something like this:

condition:   
  - condition: or
    id: all
    conditions:
      - condition: or  
        id: dark  
        conditions:  
          - condition: sun  
            after: sunset  
          - condition: numeric_state  
            entity_id: sensor.front_door_sensor_illuminance  
            below: 810        
      - condition: time
        id: evening
        after: "17:00:00"
        before: "23:00:00"
      - condition: and   
        id: dark_and_late  
        conditions:    
          - condition: sun    
            after: sunset    
            before: sunrise    
          - condition: numeric_state    
            entity_id: sensor.front_door_sensor_illuminance    
            below: 810    
      - condition: time  
        id: active_hours  
        after: "12:00:00"  
        before: "23:00:00"  

Now the question becomes, what value should be reported for condition_id if one of the conditions is fulfilled such as the one evaluating dark? Two conditions are fulfilled, the top level OR and one of the four conditions so should it report all or dark?

What if a condition that is fulfilled does not have an explicit id value set? Should condition_id report an empty string?

As always, the devil is in the details.