Associate conditions to triggers groups

I keep writing the same trigger structure all the time: eg I want to close the blinds if sun is west, it is hot, someone is home and it is not cloudy.

I can have four triggers and repeat them as conditions. This is just repetitive code but not yet hard.

I then want to open the blinds when any of these is not true. This then begins to get clumsy, since the conditions need to be related to different trigger groups etc.

These days I am just creating template triggers, which does the job — but they could of course do any job. They are not very readable.

Alternatively I can do separate automations for closing and opening, but this multiplies the automations quickly and makes me write the same code many times.

It seems to me that some sort of trigger-condition group would be very helpful. The group trigger would fire only if all the triggers are true states satisfy their conditions. This wouldn’t work for everything (events) but for most - yes

I think that the easiest one is to create a binary or normal (text) template sensor where you put all this logic together and then use this template sensor state change in automation.

Or if you’d like to do everything in UI then define these “groups” as automations and fire events that your blind automation listen.

Post an example of how you envision it would appear in an automation.

1 Like

Actually I’m not sure if I understood your case when you ask it now…

With “same trigger structure” do you mean the same condition used in many automations? Or just the same entities that you compare but every automation check different combination?

My suggestion was for the first case. For example I’d like to see one of your automation code. I don;t have anything like that right now. My closest case is the the rule for electricity tariff (uses time and holiday sensors) that I later use in many places incl in automation.

For second case it depends on how many combinations you need to automate and what to do with remaining ones. Would you like to just ignore them or are there some defaults.

In pseudocode I mean this (it’s a bit extreme, but I think illustrative)

trigger:
  - platform: state
    entity_id: group. Inhabitants
    to: on
    variables:
     action: close
 - platform: numeric_state
   entity_id: sensor. Irradiance
   above: 400
   variables:
     action: close
- platform: state
  entity_id: timer.blinds_hold
  state: idle
  variables:
     action: close
- platform: state
  entity_id: sensor.sun_in_window
  state: "on"
  variables:
     action: close
condition:
  - condition: state
    entity_id: group. Inhabitants
    to: on
 - condition: numeric_state
   entity_id: sensor.irradiance
   above: 400
- condition: state
  entity_id: timer.blinds_hold
  state: idle
- condition: state
  entity_id: sensor.sun_in_window
  state: "on"
action:
  - service: "cover.{{action}}_cover"
    entity_id: cover. Room
  - service: timer.start
    entity_id: timer.blinds_hold
   data:
      time: 0:05:00

I only want the triggers to fire if all the other sensors are int the correct state, so I have to repeat the triggers as a condition. I then may want to add an automation for closing the blinds when any of the four entities goes to a false state, so I swap out the condition key for a choose action.

Like you say, I’m creating a fake binary_sensor inside the automation, but I don’t really want to define new sensors every time I want to do something complex like this (and then worry about not writing them to the database etc). So the way that I am actually dealing with this now is just by using a template trigger with the four conditions anded together:

trigger: 
  - platform: template
    value_template: "{{is_state('group,inhabitants','on') and state('sensor.irradiance')|float<400 
    and is_state('timer.blind_hold','idle') and is_state('sensor.sun_in_window','on')}}"
   ....

and then a notted version of the same for the closing.

This is fine for me at this level, but the moment you start adding time conditions (schedule), worrying about floats and defaults, etc this just gets very complex for the normal user and is the reason that other trigger platforms exist in the first place.

I think though that this level of complexity is kind of usual for many situations if you try not to have the same automation action code multiple times with different triggers/conditions. Maybe that’s my original sin. But I have a similar problem with my heating automations where the action is long, because I have to go through switching the radiators on/off in some particular sequence etc. You could say then that that should be an external script.

In any case, I would suggest that we could have a new platform that just tested if all conditions are satisfied and only fired when all are true. Something like

trigger:
  - platform: trigger_when_all
    trigger_conditions:
       - condtion1: 
       - condition2:
      - condtion3:
      ....

I believe what you want is a compact means of indicating that when one of several triggers is triggered, the other triggers should be evaluated like conditions. In other words, a new kind of condition that instructs Home Assistant to interpret all the Triggers like Conditions.

State Trigger → State Condition
Numeric State Trigger → Numeric State Condition

trigger:
  - platform: state
    entity_id: group.something
    to: 'on'
  - platform: numeric_state
    entity_id: sensor.whatever
    above: 400
  - platform: state
    entity_id: timer.foo
    state: 'idle'
  - platform: state
    entity_id: binary_sensor.thing
    state: 'on'
condition:
  - condition: all_triggers_as_conditions
action:
  ... etc ...

What if it was there was an id/label, so you could have multiple groups…

trigger:
  - platform: state
    entity_id: group.something
    to: 'on'
    group_id: "On"
  - platform: numeric_state
    entity_id: sensor.whatever
    above: 400
    group_id: "On"
  - platform: state
    entity_id: group.something
    to: 'off'
    group_id: "Off"
  - platform: numeric_state
    entity_id: sensor.whatever
    below: 400
    group_id: "Off"
condition: []
action:
  - choose:
      - conditions:
          - condition: triggers_as_conditions
            group_id: "On"
        sequence:
        ... etc ...
      - conditions:
          - condition: triggers_as_conditions
            group_id: "Off"
        sequence:
        ... etc ...

Either way this is probably beyond a WTH…

There’s a subtle behavioral difference when conditions are shifted into action.

  1. If the triggers are evaluated as conditions in condition, and they’re not fulfilled, then the automation’s last_triggered is not updated (i.e. it’s not considered to be formally triggered). This is because the automation has successfully executed its trigger but if its condition is unfulfilled it stops.

  2. If the triggers are evaluated as conditions in action, regardless if they’re fulfilled or not, then the automation’s last_triggered is updated (i.e. it’s considered to be formally triggered). This is because the automation has successfully executed its trigger and condition sections and is now executing its action.

With the current technique, where each trigger has a matching condition, the automation behaves like #1.

1 Like

With that in mind, you could just Or the condition groups in condition, but it would be nice if they could be referenced in a Trigger condition for use in Choose or If/Then actions.

trigger:
  - platform: state
    entity_id: group.something
    to: 'on'
    group_id: "On"
  - platform: numeric_state
    entity_id: sensor.whatever
    above: 400
    group_id: "On"
  - platform: state
    entity_id: group.something
    to: 'off'
    group_id: "Off"
  - platform: numeric_state
    entity_id: sensor.whatever
    below: 400
    group_id: "Off"
condition:
  - or:
      - condition: triggers_as_conditions
        group_id: "On"
      - condition: triggers_as_conditions
        group_id: "Off"
action:
  - choose:
      - conditions:
          - condition: trigger
            group_id: "On"
        sequence:
        ... etc ...
      - conditions:
          - condition: trigger
            group_id: "Off"
        sequence:
        ... etc ...

Indeed this is the right way of putting it. And from my point of view I do not want the automation to trigger unless this has happened.

But it seems to me, in the abstract, that the trigger is defined as when a condition changes from false to true, so it seems to be more natural to me to define things from the conditions first. You create a bunch of condition groups with ids, and then have the triggers be derived from them as the group condition changing from false to true, or vice versa.

Maybe something like this:

condition:

  - condition: group
    id: group1
    conditions:
     - condition: state
       entity: sensor.happy
      state: "on"
    - conditions: numeric_state
      entity_id: sensor.irradiance
      above: 400
  - condition: group
    id: group2
    conditions:
      - condition: blabla
trigger:
  - platform: condition_trigger
    condition_id: group1
    id: operate_blind
    from: "off"
    to: "on"
    variables:
       action: close
  - platform: condition_trigger
    condition_id: group1
    id: operate_blind
    from: "on"
    to: "off"
    variables:
       action: open
  - platform: condition_trigger
    condition_id: group2
    id: start_timer
    from: "on"
    to: "off"
    variables:
       timer: xxx

And then I can choose my actions according to trigger id and the variables passed there.

A trigger instructs Home Assistant to monitor entities for state-changes. In other words, it waits for a state-change to occur. When the desired change occurs, the automation proceeds to evaluate its condition section. There’s no monitoring involved in condition; it doesn’t wait for a state-change and simply evaluates the entity’s current state.

An automation can have a trigger without a condition but it can’t have a condition without a trigger (in that situation it’s effectively a script, not a proper automation).

Yes i know, but (Not knowing much about the actual internals) in the end the trigger is just some Boolean function with a list of entities, which when they change state, cause HA to reevaluate the function. That function may as well be the group of conditions.

Maybe I have missed the point but the example you posted doesn’t seem less verbose than the way it’s currently done (triggers with corresponding conditions).

By currently done do you as HA does currently, or our discussion above? I presume you mean latter.

To me it seems more logical to define from conditions and it gives the freedom to trigger on only some of the “state” changes of the conditions, i.e. I only define when the blinds should be closed as a group condition and can do two different triggers on when the condition goes from false->true and true->false.

I mean that the example you posted, demonstrating the configuration of the proposed “trigger-group” isn’t much shorter than the way it can currently be done by simply listing triggers with matching conditions. If the goal is to minimize code then the “trigger-group” concept, in the manner the example presents it, falls short of fulfilling it.

In the example I had posted, the triggers are listed as usual but it employs a new kind of condition that effectively says “use the listed triggers as conditions”. It spares the user from specifying a matching condition for each trigger.

You have much more experience so I may not be seeing it, but to me it seems it is shorter.

Let’s say I have four sensors I want to combine in some way to get “true” → cover should be closed, and “false” → cover should be open

  • Currently, I define a group of the four triggers going to “true” and group of same four changing to “false” (if they are state triggers, then it’s the same, but for numeric_states – I need them separate). I then do a choose action repeating the same four triggers as a combined condition, two times.

  • With my proposal I define one group condition with the four sensors, and have two group_condition triggers, one for false->true, one for true->false

  • With your proposal, for the close action, I define four triggers, and a group condition of all_triggers_true, which is the same amount of code. But if I now want to do the open_action when some of the conditions become false, I need to in principle create a second trigger group and have a new group condition.

I guess your proposal would end up the same as mine if we defined a group condition – not_all_triggers_true, which would trigger the opening action and if we could do a choose-action on that. But I do not see that it would be shorter?

The problem I see is that in your version, the automation triggers every time a state changes, even if the overall group condition continues to be true – e.g. it was sunny enough to close and is now even sunnier. I think that could be problematic.

First, do not mix trigger and condition functions. One is that fires the automation and another is to check if actions in this automation should be run or not. This is not gonna change as it is the bases how things work.

Here you can create a simple template sensor to combine all input sensors to three possible output states: one for “true” combination, one for “false” combination, and one for anything else. Idea is that you don’t change the template output if there is such a change that you don’t need to react.

Then you can use this one sensor as a trigger for every automation. You can use both the old and the new state to check only the change that you need in specific automation. You can still keep conditions as extra checks if needed (different checks for different automations).

If your trigger is binary then you don’t need to define both false->true and true->false. This means just any change.

I agree – I have ended up with template triggers which “and” all the required conditions. I could have made this a template binary_sensor and triggered off that (see my second pseudo-code excerpt).

So what I am asking for is not something that is not possible to do, but it is hard to do unless you want to get into defining templates. These are simple for simple things, but once you get into times/schedules, they become a mess. Having some kind of trigger when a bunch of conditions all turn true seems to me to be a pretty general use case that would help. In my case I am finding that as I get more devices, so that I can track more conditions in the house, I am converting many of my automations to template triggers because that’s the simplest way to express the complexity.

Maybe another way of looking at this, given what you say – I think it’s natural to want certain devices to be on when a set of conditions is satisfied – e.g. I am home and it’s morning, I want my coffee maker to be working. Currently, if I do not know how to use templates, I will start creating an automation which will trigger off presence and times and then be conditioned on the same presence and times.

Maybe the right thing would be to ask for a new type of “helper sensor”, which rather than just being an input_boolean, would allow the user to specify multiple conditions and would evaluate to on/off, allowing the simple triggering of automations? This way I could create a binary_sensor.coffee_maker_on_time helper and have a simple 10-line automation with one trigger?