Automation template - how to detect slider last and new state and compare it in action template

How to detect slider last and new state and compare it in action template?

for example: if I move slider called input_number_dimmer from 0 to 5 and then from 5 - 2 automation must first run script.dimm_up five times and then script.dimm_down three times?

You may want to investigate how the Trigger State Object works. The trigger can report the to_state as well as the from_state.

  • trigger.from_state will return the previous state object of the entity.
  • trigger.to_state will return the new state object that triggered trigger.

That might be useful for your requirement to know the input_number’s current and previous state.

Thanks @123. I see that, but I don’t know how to use in automation to work as I described in example.

Question for you: Why do you want to run a script multiple times to change the light’s brightness?

Instead of stepping the brightness in increments, why not just set it to the desired value?

Because I have IR controled light. And I learned all codes from remote and put them to script:

script:

  kitchen_light_sun:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBUAAABJZITEhI3EhISEhI3EjcSEhI3EjcSEhI3EjcSEhMREzYTERMREzYTNhM2ExETERM2EzYTNhMRExISEhI3EjcSEhISEgAFJgABJUYTAAWLFwANBQAAAAA="

  kitchen_light_moon:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJJQRExE4ERMRExI3EjcSEhI3EjcSEhI3EjcSEhISEjcSEhISEhISExETERMRExETETgROBE4ETgROBE4ETgROBETEgAFJgABJEcSAA0FAAAAAAAAAAA="

  kitchen_light_dimm_up:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABKJMSEhI3EhISExE4ETgRExE4ETgRExE4ETgRExETEjcSEhISEjcSEhI3EhIUEBQ1FDUUNRQQFDUUEBQ1FDUUEBQREwAFJAABKEQUAA0FAAAAAAAAAAA="

  kitchen_light_dimm_down:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJpIUEBQ1FBAUEBQ1FDUUEBQ1FDUUEBQ1EzYUERISEjcSEhISEjYTEhMREzYTERM2EzYTNhMREzYTNhMREzYTERMREwAFJQABJ0UUAA0FAAAAAAAAAAA="

  kitchen_light_ct_up:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJpIUEBQ1FBAUEBQ1FDUUERM1FDUUERQ1FDUUEBQQFDUUEBQ1FBAUEBQ1FDUUEBQQFDUUEBQ1FDUUEBQQFDUUNRQQFAAFJAABJ0UUAA0FAAAAAAAAAAA="

  kitchen_light_ct_down:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJ5EUEBQ1FBAUEBQ1FDUUERM1FDUVEBQ1FDUUEBQQFDUUEBQ1FBAUEBQQFBAUEBQ1FDUUEBQ1FDUUNRQ1FDUUERMRFAAFJAABJ0QUAA0FAAAAAAAAAAA="

  kitchen_light_on:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJZMSExE3EhMRExE4ETgRExE4ETgRExI3EjcSEhISEjcSEhISEjcSEhISEhISExETETgRNhMTETgROBE4ETgROBETEgAFJgABJUYSAA0FAAAAAAAAAAA="

  kitchen_light_off:
    sequence:
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 
            - "JgBQAAABJpITERM2ExESEhM2EzYTERM2EzYTERM2EjcTERMSEjcSEhETERMROBI3EjcSEhI3EjcSNxI3EhISEhISEjcTERMREgAFJgABJUYSAA0FAAAAAAAAAAA="

I see. You cannot issue a command to set the light’s brightness and can only increase/decrease it.

I suspect you also have no way of knowing if the light is on or off or it’s current brightness.

  • What happens if the light is off and you send a command to increase brightness? Does it turn on to full brightness?

  • What happens if the light is off and you send a command to decrease brightness? Does it turn on then dim itself?

The reason I ask these questions is because I know how to create the solution you want but I also know it will be fragile. Without the ability to receive information from the light, or to set it’s brightness to a specific value, any solution will have a very weak grasp of the light’s actual state.


EDIT
The situation you described is like the original X10 lighting protocol. You could only turn the light on/off and increase/decrease its brightness in steps. However, you had no way of knowing the light’s current state. Whatever solution devised to control it is easily derailed by someone manually turning the light on or off or changing its brightness.

I suspect you also have no way of knowing if the light is on or off or it’s current brightness.

No there is no way to know.

What happens if the light is off and you send a command to increase brightness? Does it turn on to full brightness?

If I do that light stays off. I must first press on and then set brightness. Light also memorise last brightness level when I turn light off.

What happens if the light is off and you send a command to decrease brightness? Does it turn on then dim itself?

Same as previous.

Without the ability to receive information from the light

I only know if light is on and I press moon button light goes to brightness 10% and if I press sun light goes to 100%. I also have script for moon and sun button. from 10% to 100% I must press button on remote nine times.

I think you understand that, given the way the light works, any attempt to have Home Assistant keep track of the light’s current state or brightness can be easily derailed. All it takes is someone using the remote-control to change the light’s state and brightness and now it’s out of sync with Home Assistant.

Like I said, this works like the original X10 protocol. Actually, it’s worse because if an X10 light is off and I increase its brightness, it will turn on (this won’t).

The success of whatever solution you devise will be increased if you put the remote-control in a drawer to prevent anyone from manually controlling the light. This will help, but not guarantee, your solution can maintain synchronization with the light’s state and brightness. However, just to underline how fragile this is, it only takes one command failure (for example, you signal the light to turn on but it fails to receive the command) and now Home Assistant and the light are out of sync.

Yes I know about the sync problem. But I willing to try to make automation anyway. Can you put me to right path. Thx in advance.

I’ll only provide a high-level view of what’s required because, and no offense but, I don’t want to invest time in what I feel is ultimately an unstable solution.

Start by creating an automation that is triggered by changes to the state of the input_number. In the action section, you’ll want to create a template that calculates the numerical difference between trigger.from_state.state and trigger.to_state.state. This tells you the number of increments between its previous level and the new desired one. The sign of this value (positive or negative) tells you the desired direction (increase/decrease).

You’ll may need a separate automation to keep track of the number of times the script is called (perhaps using a counter to track the iterations).

Good luck!

I have one last question.

Can you show me how to make action template to find out if input_number increase or decrease?

I try like this but not working, no error: :frowning_face:

trigger:
  platform: state
  entity_id: input_number.kitchen_light_dimm

action:
  - service: script.toggle
    entity_id: >-
        {% if states('input_number.kitchen_light_dimm') == 0.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 0.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 10.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 10.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 20.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 20.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 30.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 30.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 40.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 40.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 50.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 50.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 60.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 60.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 70.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 70.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 80.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 80.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 90.0 and states('trigger.from_state.state - trigger.to_state.state') == -10.0 %}
         script.kitchen_light_dimm_up
        {% elif states('input_number.kitchen_light_dimm') == 90.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% elif states('input_number.kitchen_light_dimm') == 100.0 and states('trigger.from_state.state - trigger.to_state.state') == 10.0 %}
         script.kitchen_light_dimm_down

        {% endif %}

I overlooked to mention that the behavior you described (above) really complicates this project (as if it wasn’t complicated enough already).

Here’s why:

  • Assume the light is on at 60% and you turn it off by moving the input_number slider to 0%.
  • The light remembers it was at 60%.
  • Now you move the slider from 0% to 40%.
  • We perform a simple calculation to determine how many times we need to run the ‘increase brightness’ script. We subtract the slider’s previous brightness from the slider’s current brightness then divide by twenty. (40-0)/20 = 2 times.
  • HOWEVER, we are obliged to first send a command to turn on the light!
  • When we do that, the light remembers its previous brightness and automatically turns on to 60%.
  • Unfortunately, we don’t have a record of that anywhere so when the ‘increase brightness’ script runs 2 times, the light will change not from 0% to 40% but from 60% to 100%. That’s not the result we wanted. :-1:

To handle this properly we have to store the light’s previous brightness level (60%). We create another input_number, called ‘previous_brightness’ and store it there.

  • Now the calculation changes slightly. We must subtract the light’s previous brightness (stored in the input_number we created) from the slider’s current brightness then divide by twenty. (40-60)/20 = -1 time. That means the ‘decrease brightness’ script must run 1 time.
  • We send the command to turn the light on and it automatically changes to its previous value, 60%.
  • The ‘decrease_brightness’ script runs once, and the light is now set to 40%. Perfect, exactly what we wanted. :+1:

The problem is how can we know the light’s previous brightness level? The light doesn’t report anything about itself. :thinking:

One workaround is to take note of the light’s previous brightness then manually set the ‘previous_brightness’ slider to this value. Consider this to be a ‘calibration’ step that needs to be done just once before we start using the automation.

Are we done? Is it all solved? No! :man_facepalming:

If the light is currently at 80% and you move the slider to 0%, we do not want to run the ‘decrease_brightness’ script 4 times. No, we want to simply run the ‘light_off’ script. That means the automation needs additional logic. If the target brightness is 0% it chooses to run the ‘light_off’ script (instead of performing a calculation).

Done yet? Nope. There’s still the matter of running the scripts X number of times …

I don’t know if you’re familiar with the expression ‘The juice is not worth the squeeze.’ but this is one of those situations. Worst of all, despite all heroic efforts to devise a workable solution, all it takes is just one glitch, like someone using the remote-control to manually change the light’s state or brightness, or one of the transmitted commands fails to be received, and everything goes out of sync. Just one sneeze collapses this elaborate house of cards.


What I suggest you do is use a Template Switch. It’s easy to create and provides the ability to turn the light on/off (no brightness control).

switch:
  - platform: template
    switches:
      kitchen_light:
        friendly_name: "Kitchen Light"
        turn_on:
          service: script.kitchen_light_on
        turn_off:
          service: script.kitchen_light_off
1 Like

Thanks @123.

I know there is a lot of problem If you wanna know light status. But I thinking for more simple solution.

I wanna use light like this:

1.Always When I turn light on light alway start on dimm 10% to do that I must run first: script.kitchen_light_on and then script.kitchen_light_moon. And to prevent user on HA to change dimm until light is off I must have automation to disable dimmer when light is off and when light is on to put dimmer to 10%.
2. Then when light is on user can increse/decrese light form 10% to 100% if user decrise light to 0% light must go off and disable dimmer.

And for a start I try to make script to decrese/increse light when I move slider 0-10 or 10-0 and I have problem in template is_state('trigger.from_state.state - trigger.to_state.state','10.0'):

trigger:
  platform: state
  entity_id: input_number.kitchen_light_dimm

action:
  - service: script.toggle
    entity_id: >-
        {% if is_state('input_number.kitchen_light_dimm','10.0') and is_state('trigger.from_state.state - trigger.to_state.state','-10.0') %}
         script.kitchen_light_dimm_up
        {% elif is_state('input_number.kitchen_light_dimm','0.0') and is_state('trigger.from_state.state - trigger.to_state.state','10.0')  %}
         scipt.kitchen_light_dimm_down
        {% endif -%}

The following automation should work. I tested a slightly modified version of it on my system.

- alias: 'Slider Test'
  trigger:
    platform: state
    entity_id: input_number.kitchen_light_dimm
  action:
    service_template: >-
      {% set to = trigger.to_state.state | int %}
      {% set from = trigger.from_state.state | int %}
      {% set diff = (from - to) | round(0) %}
      {% if to == 10 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif to == 0 and diff == 10 %}
        script.kitchen_light_dimm_down
      {% else %}
        script.do_nothing
      {% endif -%}

Create another script called script.do_nothing. It doesn’t have to do anything, it only has to be available. If you read the template you’ll understand why it’s needed.


EDIT
Simplified the template. The variable called slider was not needed.

1 Like

Thanks again @123 , automation is working now. Step one checked :slight_smile:

here is complete automation file:

- alias: 'kitchen_light_dimm'
  trigger:
    platform: state
    entity_id: input_number.kitchen_light_dimm
  action:
    service_template: >-
      {% set to = trigger.to_state.state | int %}
      {% set from = trigger.from_state.state | int %}
      {% set diff = (from - to) | round(0) %}
      {% set slider = states('input_number.kitchen_light_dimm') | round(0) %}
      {% if slider == 10 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 0 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 20 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 10 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 30 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 20 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 40 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 30 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 50 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 40 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 60 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 50 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 70 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 60 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 80 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 70 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 90 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 80 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% elif slider == 100 and diff == -10 %}
        script.kitchen_light_dimm_up
      {% elif slider == 90 and diff == 10 %}
        script.kitchen_light_dimm_down

      {% else %}
        script.do_nothing
      {% endif -%}

Next steps:

  1. But only working correct if I do one step at time on slider. How to make automation if I move slider from 0 to 100 or 50 to 70 for example?

  2. How to disable slider and turn off light if I put slider to 0.

I can off light if I change this:

  {% elif to == 0 and diff == 10 %}
    script.kitchen_light_dimm_down

to this:

  {% elif to == 0 and diff == 10 %}
    script.kitchen_light_off
  1. With turn on/off light switch. When ON I must enable dimmer and set it to 10% using switch template?. When OFF I must disable dimmer and set it to 0.

    • platform: template
      switches:
      ir_kitchen_light:
      value_template: “{{ is_state(‘switch.kitchen_light_on_off’, ‘on’) }}”
      turn_on:
      service: switch.turn_on
      data:
      entity_id: switch.kitchen_light_on_off
      service: script.toggle
      entity_id: script.kitchen_light_moon
      MISSING: SLIDER ENABLE and SLIDER TO 10%
      turn_off:
      service: switch.turn_off
      data:
      entity_id: switch.kitchen_light_on_off
      MISSING: SLIDER DISABLE and SLIDER TO 0

You can’t with the approach you’ve chosen where the template tests for every possible change in brightness. That’s impractical.

The approach I suggested (in my overly-long post) calculates the number of levels the brightness must change. So if the brightness must change by +4 levels, it would call script.kitchen_light_dimm_up four times. If the change is -2 levels then it would call script.kitchen_light_dimm_down two times.

I also provided a solution to handle the other complication, namely the light’s “memory” effect where, when turned on, it automatically resumes its previous brightness level.

Sorry, but I can’t be of more help because, as I’ve stated several times already, this project requires a fair amount of effort and, despite best efforts, the end-result can be easily derailed. I won’t be dedicating any more time to this project. This community has over 38000 members so hopefully someone else, with more free time and interest, is willing to take up the challenge.

Good luck!

Ok, thanks for your time @123

1 Like

How can I call two or more different script or one script more then one time inside action template? Can I put delay between them?

I try like this:

{% if slider == 10 and diff == -10 %}
script.kitchen_light_dimm_on, script.kitchen_light_moon

Automation just call first script and error:

Invalid data for call_service at pos 1: Service script.kitchen_light_dimm_on, script.kitchen_light_moon does not match format domain.name

I also try with space and new line. Same error.

it’s not how you call a script.

Have a read, docs rule and answer all your questions above.