Trigger on event state_change -- any way to filter?

I have the below automation that works fine. It uses conditions to only trigger on the desired state events.

But is there a better way to do this? I tried using a template trigger (the condition that counts the lights on) and use that as a trigger when it changes but that didn’t work well – too much lag.

It just seems dirty to trigger on all state changes but perhaps I am over-thinking this.

##########################################################
## Update brightness when light turned on
##########################################################
- alias: Adjust brightness as lights are turned on
  initial_state: True

  trigger:
    - platform: event
      event_type: state_changed
    
  condition:
    # Only look at lights going off to on
    - condition: template
      value_template: "{{ trigger.event.data is defined }}"

    - condition: template
      value_template: "{{ trigger.event.data.entity_id.split('.')[0] == 'light' }}"
    
    - condition: template
      value_template: "{{ trigger.event.data.new_state.state == 'on' }}"
      
    - condition: template
      value_template: "{{ trigger.event.data.old_state.state == 'off' }}"
   
    # Don't change these lights.
    #   - condition: template
    #     value_template: >-
    #       {{ trigger.event.data.entity_id != 'switch.outdoor_front_switch' }}
   
    - condition: template
      value_template: "{{ states.sensor.target_brightness_inside.state is defined }}"

    - condition: template
      value_template: "{{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | list | count >= 1 }}"

  action:
    - service: light.turn_on
      data_template:
        entity_id: >-
          {{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | join(',') }}
        brightness_pct: >-
          {{ states('sensor.target_brightness_inside')|int }}
        transition: 2

Templates used to monitor things (such as in template sensors and template triggers) have to know what to monitor. I.e., they have to know what entities to watch for state changes. Normally they try to figure that out by parsing the template for entity_id’s. But your template for counting the number of lights that are on does not contain any entity_id’s, so it won’t know what to watch for. Hence, it won’t trigger when you want it to.

Given what it appears you’re trying to do, I think the way you’re doing it is reasonable. Still, I think you can make some simplifications:

##########################################################
## Update brightness when light turned on
##########################################################
- alias: Adjust brightness as lights are turned on
  initial_state: True

  trigger:
    - platform: event
      event_type: state_changed
      # Only look at lights going off to on
      event_data:
        new_state:
          state: 'on'
        old_state:
          state: 'off'
    
  condition:
    - condition: template
      value_template: "{{ trigger.event.data.entity_id.startswith('light.') }}"
   
    # Don't change these lights.
    #   - condition: template
    #     value_template: >-
    #       {{ trigger.event.data.entity_id != 'switch.outdoor_front_switch' }}
   
    - condition: template
      value_template: "{{ states('sensor.target_brightness_inside') != 'unknown' }}"

    - condition: template
      value_template: "{{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | list | count >= 1 }}"

  action:
    - service: light.turn_on
      data_template:
        entity_id: >-
          {{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | join(',') }}
        brightness_pct: >-
          {{ states('sensor.target_brightness_inside')|int }}
        transition: 2

I’m not 100% sure about the trigger (I haven’t actually tried anything exactly like that), but I’m pretty sure it will work.

Thanks, giving it a shot now… Isn’t triggering with the event_data added to the trigger so trying to debug and see why.

This seems really complicated.
I’m out at the moment but I do what you are trying to do.
I have ‘groups’ of lights (not real groups but you could do that too)
The groups are based on usage and bulb type. I have only 4 types of bulb in my house (all bulbs installed have a number as do the spares in the ‘bulb box’ (so the wife can replace like with like))
The bulbs are split across 6 usage subsets each with their own brightness profile through the day.
Any time a bulb switches on in a group it come on at minimum setting (set in the switch hardware), HA sees the switch ‘on’ and sets the brightness to the current group profile setting for the time of day.
If I then switch the bulb off and on quickly the hardware sees that and adjusts brightness to 100% HA also sees the switch off and prevents brightness adjustment (for the next 5 seconds) so the bulb stays at 100% If I switch off, count 2 and switch on, it comes on at minimum and as the prevent adjustment is running, I just get minimum brightness. Anything other than that I have to use the UI. (I hate have to use the UI as a remote control). The wife can also control all the lights without the UI and even without HA if necessary (though that would be without the profile).
My system is predicated on the fact my hardware (fibaro dimmers) can set a switch on brightness and respond to double switch - to set to maximum. Its also a single harmonious hareware platform.
Individually it’s a lot simpler than the code above (It also uses packages so a lot of the code I wrote once then just copied). But it is an integrated solution with complex interactions, so now that I’ve explained it, it seems a bigger hill to climb.
Sorry, I don’t think I’ve added much here.

Can you post this code?

Okay, when I get back.
What switches are you using ?
ie do they have hardware settings you can leverage ?
I’m not like Petro (hiding all user setting from his users, mainly because I’ve not been bitten in the ass with that as yet) so I have a separate view detailing all the ‘back end’ lighting controls. You cab do the same or as Petro does, and adjust settings and restart or reload (depending on where the settings are).
All my bulbs have a delay off (not sure this actually helps as the wife now feels vindicated when she leaves the light on, and just gets angry when the light in the bathroom goes off after 90 mins - you can’t win ! :frowning_face: ) but anyone taking longer than 15 mins in the WC is clearly reading rather than just taking a dump !

Edit: and the biggest question ; do you currently use ‘packages’ ?

Hi I have various switches some support double tap

Yes using packages so whatever you have is appreciated

Ok. Well, I just tested it myself and sure enough, it doesn’t work. And now I think I know why. In any case, you’ll need to at least go back to checking the states via conditions:

##########################################################
## Update brightness when light turned on
##########################################################
- alias: Adjust brightness as lights are turned on
  initial_state: True

  trigger:
    - platform: event
      event_type: state_changed
    
  condition:
    - condition: template
      # Only look at lights going off to on
      value_template: >
        {{ trigger.event.data.entity_id.startswith('light.')
           and trigger.event.data.old_state is not none
           and trigger.event.data.old_state.state == 'off' 
           and trigger.event.data.new_state is not none
           and trigger.event.data.new_state.state == 'on' }}
   
    # Don't change these lights.
    #   - condition: template
    #     value_template: >-
    #       {{ trigger.event.data.entity_id != 'switch.outdoor_front_switch' }}
   
    - condition: template
      value_template: "{{ states('sensor.target_brightness_inside') != 'unknown' }}"

    - condition: template
      value_template: "{{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | list | count >= 1 }}"

  action:
    - service: light.turn_on
      data_template:
        entity_id: >-
          {{ states.light | selectattr('state','==','on') | map(attribute='entity_id') | join(',') }}
        brightness_pct: >-
          {{ states('sensor.target_brightness_inside')|int }}
        transition: 2
1 Like

Okay, will post some code tomorrow, explaining the aim of each package after it, with any premises.
Is there anything particularly you are interested in ?

@pnbruckner Phil, I’ve never used old_state / new_state before, the docs state that they are there and they do just as you’d expect.
Why should we use it and what is the difference between old_state and from: ‘off’ for example ? TIA

Thanks, found the same and back to the original. Thanks for the startswith as didn’t know that.

Also found out the new_state.domain and old_state.domain can be used as well.

1 Like

Because the OP wants an automation that triggers whenever any entity within a given domain (light in this case) changes from off to on. You can’t do that (easily) with a state trigger because you’d have to manually list every entity_id that is in the light domain, which also require maintenance down the road.

And new_state vs to_state? Just another inconsistency in a project developed by many volunteers over a long period of time I guess.

3 Likes

That’s one to add to my card index of stuff to explore.

But here he just needs to adjust light levels to a set value, that should only ever occur on a switch on or a transistion change and therefore should not require this complexity … or have I missed something ?

This should be taken as read now on any response I give you, Teras or Petro : - Many Thanks :+1:

Hi @pnbruckner I have another couple questions:

  1. I see you use ‘not none’ versus my ‘is defined’ to ensure the to/from states are populated. What is correct?

  2. For the condition on the brightness target you are explicit with != ‘unknown’ versus my ‘is defined’ – again is my ‘is defined’ wrong?

Thanks as these sorts of details don’t seem to be well documented anywhere.

I have a sensor that computes the target brightness for our interior lights based on output from @pnbruckner Illuminance sensor.

That sensor is used in 3 ways:

  1. If someone manually turns on a light the above automation will ensure the brightness is set correctly.
  2. Programatic turn on’s by HA are done to the right brightness.
  3. As the target brightness sensor changes it updates the lights that are on.

This works well, but was not happy with the one automation that in theory triggers on every state change. So was looking to improve on it but seems not a possibility right now.

Okay, maybe this is off topic, but I just can’t try to ignore questions that occur to me.
So you have a brightness sensor (from Phil). (the only stuff I use from Phil is his life360 and I’ve stolen just about every template he’s ever written :+1: :slight_smile: ) and you match that for your output ? Assuming it’s calibrated 1 to 100 percent
Then surely you just switch the light to that value as it changes and change it (the light) as it changes too.?
Not sure that works for me as if it goes cloudy I don’t want the lights dimming. On the other hand I don’t want dim lights during the day and bright lights at night.

All bulbs do not give the same output, further a 1200 lumen bulb in a big room may give less light than a 400 lumen in a small room. So a universal profile will need tweaking ??? Hence won’t be universal ?

Please educate me

Hi,

The Illuminance sensor gets me an idea how bright it is outside. From that I have worked out a table of target brightness values for our lights. Illuminance uses the cloud coverage so if overcast my targets are higher.

And as you point out ideally you do this for each room based on size, where the lights are, and amount of windows, and direction towards the sun. Lots of work to do it right. Or put a lux sensor in each room maybe.

What I have is an approximation that works good enough to get a more pleasant light profile in the house.

All events will have a data attribute, even it’s “empty.” So {{ trigger.event.data is defined }} will always be True. Try this in the Template Editor:

{% set trigger = {'event': {'data': {}}} %}
{{ trigger.event.data is defined }}

For state_changed events, it will always have .data.old_state and .data.new_state, although one or the other may be None. That’s why I test it with the “is not none” test.

1 Like

Okay, as promised : -
Notes,

  1. the day segments are basically repeated code to ensure they never clash (I’ll combine these into one sensor, when I can be bothered)
  2. the ‘groups’ are just lists of light (I like to see what I’m working with and can move them easily (cut/paste & reload)
homeassistant:
  customize:
    input_number.in_aalight_day:
      unit_of_measurement: '°'
    input_number.in_aalight_evening:
      unit_of_measurement: '°'

binary_sensor:
  - platform: template
    sensors:
    ## day segment bs
      bs_light_day:
        entity_id: sensor.time
        value_template: >
          {% set rising = state_attr('sun.sun', 'rising') %}
          {% set elevation = state_attr('sun.sun', 'elevation') | float %}
          {% set daystart = states('input_number.in_aalight_day') | float %}
          {% set eveningstart = states('input_number.in_aalight_evening') | float %}
          {% set day = (rising and elevation > daystart) or (not rising and elevation > eveningstart) %}
          {{ day }}
        friendly_name: Day Lights
        icon_template: "{{ 'mdi:white-balance-sunny' }}"
    ## evening segment bs
      bs_light_evening:
        entity_id: sensor.time
        value_template: >
          {% set time = states('sensor.time') %}
          {% set rising = state_attr('sun.sun', 'rising') %}
          {% set elevation = state_attr('sun.sun', 'elevation') | float %}
          {% set daystart = states('input_number.in_aalight_day') | float %}
          {% set eveningstart = states('input_number.in_aalight_evening') | float %}
          {% set nightstart = states('input_datetime.id_aalight_night') [0:5] %}
          {% set nightstart = '23:59' if nightstart == '00:00' else nightstart %}
          {% set day = (rising and elevation > daystart) or (not rising and elevation > eveningstart) %}
          {% if '12:00' < nightstart <= '24:00' %}
            {% set r1 = time >= nightstart %}
            {% set r2 = elevation <= daystart and time < '12:00'%}
          {% else %}
            {% set r1 = false %}
            {% set r2 = elevation <= daystart and time >= nightstart %}
          {% endif %}
          {% set night = r1 or r2 %}
          {% set evening = not (day or night) %}
          {{ evening }}
        friendly_name: Evening Lights
        icon_template: "{{ 'mdi:weather-sunset-down' }}"
    ## night segment bs
      bs_light_night:
        entity_id: sensor.time, binary_sensor.bs_light_day, binary_sensor.bs_light_evening
        value_template: >
          {% set time = states('sensor.time') %}
          {% set elevation = state_attr('sun.sun', 'elevation') | float %}
          {% set daystart = states('input_number.in_aalight_day') | float %}
          {% set nightstart = states('input_datetime.id_aalight_night') [0:5] %}
          {% set nightstart = '23:59' if nightstart == '00:00' else nightstart %}
          {% if '12:00' < nightstart <= '24:00' %}
            {% set r1 = time >= nightstart %}
            {% set r2 = elevation <= daystart and time < '12:00'%}
          {% else %}
            {% set r1 = false %}
            {% set r2 = elevation <= daystart and time >= nightstart %}
          {% endif %}
          {% set night = r1 or r2 %}
          {{ night }}
        friendly_name: Night Lights
        icon_template: "{{ 'mdi:weather-night' }}"
    ## night slot for external lights
      bs_aalight_extlights_nightslot:
        entity_id: sensor.time
        value_template: >
          {% set elevation = state_attr('sun.sun', 'elevation') | float %}
          {% set nightstart = states('input_number.in_light_flood_on_elev_offset') | float %}
          {% set nightstop = states('input_number.in_light_flood_off_elev_offset') | float %}
          {{ elevation <= nightstart and not rising or elevation <= nightstop and rising }}
        friendly_name: External Light Night Slot
        icon_template: "{{ 'mdi:weather-night' }}"
    #### end of template stuff

input_boolean:
  ib_aalight_transition_enable:
    name: Segment Transition Enable
    #initial: off
    icon: mdi:power
  ib_aalight_stop_adjust:
    name: Stop Level Adjustment
    initial: off
    icon: mdi:lightbulb-off

input_datetime:
  id_aalight_night:
    name: Night Transition (time)
    has_time: true
    #initial: 0
    icon: mdi:transition

input_number:
  in_aalight_normal_transition:
    name: Normal Transition Time (s)
    #initial: 0
    min: 1
    max: 10
    step: 1
    mode: box
    icon: mdi:transition
  in_aalight_segment_transition:
    name: Segment Transition Time (s)
    #initial: 0
    min: 1
    max: 200
    step: 1
    mode: box
    icon: mdi:transition
  in_aalight_all_lvl:
    name: All Remaining Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    #mode: box
    icon: mdi:numeric
  in_aalight_all_dlvl:
    name: All Remaining Day Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_all_elvl:
    name: All Remaining Evening Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_all_nlvl:
    name: All Remaining Night Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_bed4_lvl:
    name: Bed 4 Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    #mode: box
    icon: mdi:numeric
  in_aalight_bth_lvl:
    name: Bath Room Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    #mode: box
    icon: mdi:numeric
  in_aalight_bth_dlvl:
    name: Bath Room Day Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_bth_elvl:
    name: Bath Room Evening Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_bth_nlvl:
    name: Bath Room Night Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_out_lvl:
    name: Outside Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    #mode: box
    icon: mdi:numeric
  in_aalight_out_alvl:
    name: Outside Level All Segments
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_day:
    name: Day Transition (horizon ° offset)
    #initial: 0
    min: -12
    max: 12
    step: 0.1
    mode: box
    icon: mdi:transition
  in_aalight_evening:
    name: Evening Transition (horizon ° offset)
    #initial: 0
    min: -12
    max: 12
    step: 0.1
    mode: box
    icon: mdi:transition
  in_aalight_kit_lvl:
    name: Kitchen Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    #mode: box
    icon: mdi:numeric
  in_aalight_kit_dlvl:
    name: Kitchen Day Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_kit_elvl:
    name: Kitchen Evening Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric
  in_aalight_kit_nlvl:
    name: Kitchen Night Level
    #initial: 0
    min: 1
    max: 100
    step: 1
    mode: box
    icon: mdi:numeric

input_select:
  is_aalight_segment:
    name: Light Level Selector
    options:
      - Day
      - Evening
      - Night

automation:
    #name: Check Light 'Just' Switched OFF
  - alias: au_aalight_light_swoff_que
    trigger:
      - platform: state
        entity_id: light.fibdim2_kitf_level, light.fibdim2_kitr_level, light.fibdim2_bath_level, light.fibdim2_ensu_level, light.fibdim2_wc_level, light.fibdim2_bed4_level, light.fibdim2_bed1_level, light.fibdim2_bed2_level, light.fibdim2_bed3_level, light.fibdim2_frtr_level, light.fibdim2_hall_level, light.fibdim2_ldg1_level, light.fibdim2_ldg2_level, light.fibdim2_lvgr_level, light.fibdim2_ptio_level, light.fibdim2_prch_level, light.fibdim2_lmp1_level
        from: 'on'
        to: 'off'
    action:
      - service: input_boolean.turn_on
        entity_id: input_boolean.ib_aalight_stop_adjust
      - delay: "00:00:05"
      - service: input_boolean.turn_off
        entity_id: input_boolean.ib_aalight_stop_adjust

    #name: Light Transition To Day
  - alias: au_aalight_to_day
    trigger:
      - platform: state
        entity_id: binary_sensor.bs_light_day
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_transition_enable
        state: 'on'
    action:
      - service: input_select.select_option
        data:
          entity_id: input_select.is_aalight_segment
          option: 'Day'
    #name: Light Transition To Evening
  - alias: au_aalights_to_evening
    trigger:
      - platform: state
        entity_id: binary_sensor.bs_light_evening
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_transition_enable
        state: 'on'
    action:
      - service: input_select.select_option
        data:
          entity_id: input_select.is_aalight_segment
          option: 'Evening'
    #name: Light Transition To Night
  - alias: au_aalights_to_night
    trigger:
      - platform: state
        entity_id: binary_sensor.bs_light_night
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_transition_enable
        state: 'on'
    action:
      - service: input_select.select_option
        data:
          entity_id: input_select.is_aalight_segment
          option: 'Night'
    #name: Light Day Segment
  - alias: au_aalight_dayseg
    trigger:
      - platform: state
        entity_id: input_select.is_aalight_segment
        to: 'Day'
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_kit_lvl
          value: "{{ states('input_number.in_aalight_kit_dlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bth_lvl
          value: "{{ states('input_number.in_aalight_bth_dlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_all_lvl
          value: "{{ states('input_number.in_aalight_all_dlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_out_lvl
          value: "{{ states('input_number.in_aalight_out_alvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bed4_lvl
          value: "{{ states('input_number.in_aalight_bed4_alvl') | int }}"
    #name: Light Evening Segment
  - alias: au_aalight_eveseg
    trigger:
      - platform: state
        entity_id: input_select.is_aalight_segment
        to: 'Evening'
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_kit_lvl
          value: "{{ states('input_number.in_aalight_kit_elvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bth_lvl
          value: "{{ states('input_number.in_aalight_bth_elvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_all_lvl
          value: "{{ states('input_number.in_aalight_all_elvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_out_lvl
          value: "{{ states('input_number.in_aalight_out_alvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bed4_lvl
          value: "{{ states('input_number.in_aalight_bed4_alvl') | int }}"
    #name: Light Night Segment
  - alias: au_aalight_ngtseg
    trigger:
      - platform: state
        entity_id: input_select.is_aalight_segment
        to: 'Night'
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_kit_lvl
          value: "{{ states('input_number.in_aalight_kit_nlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bth_lvl
          value: "{{ states('input_number.in_aalight_bth_nlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_all_lvl
          value: "{{ states('input_number.in_aalight_all_nlvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_out_lvl
          value: "{{ states('input_number.in_aalight_out_alvl') | int }}"
      - service: input_number.set_value
        data_template:
          entity_id: input_number.in_aalight_bed4_lvl
          value: "{{ states('input_number.in_aalight_bed4_alvl') | int }}"
    #name: if any kitchen light turns on
  - alias: au_aalight_lghtonkit
    trigger:
      - platform: state
        entity_id: light.fibdim2_kitf_level, light.fibdim2_kitr_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_stop_adjust
        state: 'off'
    action:
      - service: light.turn_on
        data_template:
          entity_id: "{{ trigger.entity_id }}"
          brightness_pct: "{{ states('input_number.in_aalight_kit_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_normal_transition') | int }}"
    #name: if any bathroom light turns on
  - alias: au_aalight_lghtonbth
    trigger:
      - platform: state
        entity_id: light.fibdim2_bath_level, light.fibdim2_ensu_level, light.fibdim2_wc_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_stop_adjust
        state: 'off'
    action:
      - service: light.turn_on
        data_template:
          entity_id: "{{ trigger.entity_id }}"
          brightness_pct: "{{ states('input_number.in_aalight_bth_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_normal_transition') | int }}"
    #name: if bed 4 light turns on
  - alias: au_aalight_lghtonbed4
    trigger:
      - platform: state
        entity_id: light.fibdim2_bed4_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_stop_adjust
        state: 'off'
    action:
      - service: light.turn_on
        data_template:
          entity_id: light.fibdim2_bed4_level
          brightness_pct: "{{ states('input_number.in_aalight_bed4_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_normal_transition') | int }}"
    #name: if an outside light turns on
  - alias: au_aalight_lghtonout
    trigger:
      - platform: state
        entity_id: light.fibdim2_ptio_level, light.fibdim2_prch_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_stop_adjust
        state: 'off'
    action:
      - service: light.turn_on
        data_template:
          entity_id: "{{ trigger.entity_id }}"
          brightness_pct: "{{ states('input_number.in_aalight_out_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_normal_transition') | int }}"
    #name: if any remaining light turns on
  - alias: au_aalight_lghtonall
    trigger:
      - platform: state
        entity_id: light.fibdim2_bed1_level, light.fibdim2_bed2_level, light.fibdim2_bed3_level, light.fibdim2_frtr_level, light.fibdim2_hall_level, light.fibdim2_ldg1_level, light.fibdim2_ldg2_level, light.fibdim2_lvgr_level, light.fibdim2_lmp1_level
            ####, light.fibdim2_ptio_level, light.fibdim2_prch_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_aalight_stop_adjust
        state: 'off'
    action:
      - service: light.turn_on
        data_template:
          entity_id: "{{ trigger.entity_id }}"
          brightness_pct: "{{ states('input_number.in_aalight_all_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_normal_transition') | int }}"

Then here’s an example of the lights, this is bath room (a slightly different profile), it also includes a delay off timer

input_boolean:
  ib_light_bath_timer_enable:
    name: Bath Timer Enable
    #initial: on
    icon: mdi:timer

input_number:
  in_light_bath_timer:
    name: Bath On Timer (mins)
    #initial: 80
    min: 10
    max: 120
    step: 1
    mode: box
    icon: mdi:alarm
  in_switch_bath_fan_timer:
    name: Bath Fan On Timer (mins)
    #initial: 10
    min: 1
    max: 30
    step: 1
    mode: box
    icon: mdi:alarm

automation:
    #name: Light Bath Off Delay
  - alias: au_light_bath_offdelay
    trigger:
      - platform: state
        entity_id: light.fibdim2_bath_level
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ib_light_bath_timer_enable
        state: 'on'
    action:
      - service: light.turn_on
        entity_id: light.fibdim2_bath_level
        data_template:
          brightness_pct: >
            {{ states('input_number.in_aalight_bth_lvl') | int }}
          transition: >
            {{ states('input_number.in_aalight_segment_transition') | int }}
      - service: script.turn_off
        entity_id: script.sc_light_bath_timer
      - service: script.sc_light_bath_timer
    #name: Switch Bath Off Cancels Timer
  - alias: au_switch_bath_offcancelstimer
    trigger:
      - platform: state
        entity_id: light.fibdim2_bath_level
        to: 'off'
    action:
      - service: script.turn_off
        entity_id: script.sc_light_bath_timer

    #force fan off
  - alias: au_bath_fan_force_off
    trigger:
      - platform: state
        entity_id: binary_sensor.bs_global_noise_permissive
        to: 'off'
    action:
      - service: script.turn_off
        entity_id: script.sc_switch_bath_fan_timer
      - service: switch.turn_off
        entity_id: switch.fibsw_bthf_sw
    #fan on link to light on
  - alias: au_switch_bath_fan_on
    trigger:
      - platform: state
        entity_id: light.fibdim2_bath_level
        to: 'on'
    condition:
      - condition: state
        entity_id: binary_sensor.bs_global_noise_permissive
        state: 'on'
    action:
      - service: switch.turn_on
        entity_id: switch.fibsw_bthf_sw
    #fan off link to light off
  - alias: au_switch_bath_fan_off
    trigger:
      - platform: state
        entity_id: light.fibdim2_bath_level
        to: 'off'
    action:
      - service: script.turn_off
        entity_id: script.sc_switch_bath_fan_timer
      - service: script.sc_switch_bath_fan_timer
    #name: Adjust Brightness On Segment Change
  - alias: au_light_adjust_brightness_bthr
    trigger:
      - platform: state
        entity_id: input_number.in_aalight_bth_lvl
    condition:
      - condition: state
        entity_id: light.fibdim2_bath_level
        state: 'on'
    action:
      - service: light.turn_on
        entity_id: light.fibdim2_bath_level
        data_template:
          brightness_pct: "{{ states('input_number.in_aalight_bth_lvl') | int }}"
          transition: "{{ states('input_number.in_aalight_segment_transition') | int }}"

script:
  sc_light_bath_timer:
    alias: Light Bath Timer Script
    sequence:
    - delay: "00:{{ states('input_number.in_light_bath_timer') | int }}:00"
    - service: light.turn_off
      entity_id: light.fibdim2_bath_level
  sc_switch_bath_fan_timer:
    alias: Switch Bath Fan Timer Script
    sequence:
    - delay: "00:{{ states('input_number.in_switch_bath_fan_timer') | int }}:00"
    - service: switch.turn_off
      entity_id: switch.fibsw_bthf_sw

You will see that most of the settings are adjustable from the front end (but hidden away on a maintenance tab)

1 Like