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

because it’s the ultimate do-nothing script. You can call it in templates, like you do, and have it do nothing.

OK, thanks.

I would use a python_script to replace all of the scripts (up_1X, down 1X, up_2X, down_2X, etc).

The automation’s template wouldn’t change much but now it would simply calculate the number of repetitions to pass on to the python_script. For example, repetitions: -7 would instruct the python_script.brightness_controller to transmit a dim command 7 times. Repetitions=0 would mean to simply turn the light off.

  action:
  - service: python_script.brightness_controller
    data_template:
      repetitions: `<your template>`

However, if what you created works for you, then I wouldn’t bother with a python_script (unless you wanted to learn something new).

Thanks @123. I am always open to learn something new if you have a time to explain more detail what you have in mind.

I’m kind late to the topic but just to add a idea. Instead of trying to keep the state of device, why not just bring it to a initial know state and then set the new state from there? If I got it right, when you press the “moon button” the brightness goes to 10%, so after pressing it you know the state, then you just have to send N-1 “dimm_up” commands to match the brightness to your input slider value. It may or may not be a little disturbing for the people in the room when the brightness goes to 10%…

Here is an example of a python_script that accepts one parameter (command) that specifies the number of times to transmit dimm_up or dimm_down.

This python_script accepts a command in the range from -10 to 11.

If command is:

  • -5 the python_script will send dimm_down 5 times to the light.
  • 3 will send dimm_up 3 times to the light.
  • 0 means to turn off the light.
  • 11 means to turn on the light.

To permit Home Assistant to support python_scripts, you must add the following line to configuration.yaml:

python_script:

In your config directory, create a sub-directory called python_scripts then create a new file in it called dimm_control.py containing the following python code:

rf = { "ON":"JgBQAAABJZMSExE3EhMRExE4ETgRExE4ETgRExI3EjcSEhISEjcSEhISEjcSEhISEhISExETETgRNhMTETgROBE4ETgROBETEgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "OFF":"JgBQAAABJpITERM2ExESEhM2EzYTERM2EzYTERM2EjcTERMSEjcSEhETERMROBI3EjcSEhI3EjcSNxI3EhISEhISEjcTERMREgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "UP":"JgBQAAABKJMSEhI3EhISExE4ETgRExE4ETgRExE4ETgRExETEjcSEhISEjcSEhI3EhIUEBQ1FDUUNRQQFDUUEBQ1FDUUEBQREwAFJAABKEQUAA0FAAAAAAAAAAA=",
       "DOWN":"JgBQAAABJpIUEBQ1FBAUEBQ1FDUUEBQ1FDUUEBQ1EzYUERISEjcSEhISEjYTEhMREzYTERM2EzYTNhMREzYTNhMREzYTERMREwAFJQABJ0UUAA0FAAAAAAAAAAA="
     }

cmd = data.get('command')

if cmd is not None:
  cmd = int(cmd)
  if -10 <= cmd <= 11:
    if cmd == 0:
      loop = 1
      rfc = rf['OFF']
    elif cmd == 11:
      loop = 1
      rfc = rf['ON']
    else:
      if cmd > 0:
        rfc = rf['UP']
      else:
        rfc = rf['DOWN']
      loop = abs(cmd)

    service_data = {'packet':'{}'.format(rfc)}
    for i in range(loop):
      hass.services.call('switch', 'broadlink_send_packet_192_168_2_1', service_data, False)

Now restart Home Assistant.

To test it:

  • Go to Home Assistant’s Services page
  • Set Service to python_script.dimm_control
  • To turn the light on, set Service Data to {"command":11}
  • click the CALL SERVICE button

To dimm the light down 2 steps, set Service Data to {"command":-2} and click CALL SERVICE.

Screenshot%20from%202019-04-22%2021-10-05

To use it in an automation, call the service python_script.dimm_control and use a data_template to set command to a value between -10 and 11. For example:

- alias: 'kitchen_light_set_dimm'
  trigger:
    platform: state
    entity_id: input_number.kitchen_light_dimm
  action:
    service: python_script.dimm_control
    data_template:
      command: >-
        {% 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) %}
        {% set step = diff / 10 | round(0) %}
        {% if slider == 0 %}
          0
        {% elif slider == 100 %}
          11
        {% else %}
          {{step}}
        {% endif %}

… and if it doesn’t work, oh well. :man_shrugging:

Thanks for script @123

I try today but there is something wrong with python script.

Here is an error:

Error executing script: (ServiceNotFound(...), 'Service switch.broadlink_send_packet_192_168_2_1 not found')
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/homeassistant/components/python_script/__init__.py", line 159, in execute
    exec(compiled.code, restricted_globals, local)
  File "dimm_control.py", line 27, in <module>
  File "/usr/local/lib/python3.7/site-packages/homeassistant/core.py", line 1082, in call
    self._hass.loop
  File "/usr/local/lib/python3.7/concurrent/futures/_base.py", line 432, in result
    return self.__get_result()
  File "/usr/local/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/usr/local/lib/python3.7/site-packages/homeassistant/core.py", line 1115, in async_call
    raise ServiceNotFound(domain, service) from None
homeassistant.exceptions.ServiceNotFound: (ServiceNotFound(...), 'Service switch.broadlink_send_packet_192_168_2_1 not found')

I have only service called broadlink.send?

Look at the code in your script, shown in this post.

  kitchen_light_sun:
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.kitchen_light_on_off
      - delay:
          milliseconds: 10
      - service: switch.broadlink_send_packet_192_168_2_1
        data:
          packet: 

It uses service: switch.broadlink_send_packet_192_168_2_1 which is the same one used in the python_script.

If you recently upgraded Home Assistant to 0.92 then it has a new Broadlink component with a completely different service: broadlink.send. As a result, everywhere you have used service: switch.broadlink_send_packet_192_168_2_1 will no longer work.

Yes I recently upgraded to 0.92.1.

If I understand I must adjust python script to work with new broadlink component. How?

this:

hass.services.call('switch', 'broadlink_send_packet_192_168_2_1', service_data, False)

to this: ???

hass.services.call('broadlink', 'send', service_data, False)

Yes, but the contents of service_data will now have to specify the host.

service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rfc)}

Your original scripts will also have to change because they still use switch.broadlink_send_packet_192_168_2_1.

If I understand correctly I must change:

this:

    service_data = {'packet':'{}'.format(rfc)}
    for i in range(loop):
      hass.services.call('switch', 'broadlink_send_packet_192_168_2_1', service_data, False)

to this:

service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rfc)}

    service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rfc)}
    for i in range(loop):
      hass.services.call('broadlink', 'send', service_data, False)

Python script is now working. Thanks :slight_smile:

When I add automation:

- alias: 'kitchen_light_set_dimm'
  trigger:
    platform: state
    entity_id: input_number.kitchen_light_dimm
  action:
    service: python_script.dimm_control
    data_template:
      command: >-
        {% 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) %}
        {% set step = diff / 10 | round(0) %}
        {% if slider == 0 %}
          0
        {% elif slider == 100 %}
          11
        {% else %}
          {{step}}
        {% endif %}

Only on and off working.

When I move slider from 10 to 0 light turns off when I move slider from 10-90 nothing hapeneds here is error:

Error executing script: invalid literal for int() with base 10: '1.0'
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/homeassistant/components/python_script/__init__.py", line 159, in execute
    exec(compiled.code, restricted_globals, local)
  File "dimm_control.py", line 10, in <module>
ValueError: invalid literal for int() with base 10: '1.0'

when I move slider from 90 to 100 light turns on.

Change this:

        {% set step = diff / 10 | round(0) %}

to this:

        {% set step = (diff / 10) | round(0) %}

Thanks. Now is working.

One more question. How can I call two commands at once with python script.

I try like this but not working and no error:

elif cmd == 1:
  loop = 1
  rfc = rf['ON'],
  rfc = rf['MOON']

I try to solve problem when I move slider from 0 to 10 not working. In this case python script must send two commands ON(turn on light) and MOON(set brightness to 10% or ON and 10xDOWN?

If you use elif cmd==1 to send ‘ON’ and ‘MOON’, you lose the ability to increase the brightness by just one step (cmd==1 represents an increase of one brightness step). If the light is already on and you press the button once to increment the brightness, it won’t do that, it will change to ‘MOON’ mode. Is that what you want?

If that’s the behavior you want, then the python_script changes to the following example. It adds a ‘MOON’ item to the list and adds a test for cmd==1 where it sends the ‘ON’ command before sending the ‘MOON’ command.

rf = { "ON":"JgBQAAABJZMSExE3EhMRExE4ETgRExE4ETgRExI3EjcSEhISEjcSEhISEjcSEhISEhISExETETgRNhMTETgROBE4ETgROBETEgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "OFF":"JgBQAAABJpITERM2ExESEhM2EzYTERM2EzYTERM2EjcTERMSEjcSEhETERMROBI3EjcSEhI3EjcSNxI3EhISEhISEjcTERMREgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "UP":"JgBQAAABKJMSEhI3EhISExE4ETgRExE4ETgRExE4ETgRExETEjcSEhISEjcSEhI3EhIUEBQ1FDUUNRQQFDUUEBQ1FDUUEBQREwAFJAABKEQUAA0FAAAAAAAAAAA=",
       "DOWN":"JgBQAAABJpIUEBQ1FBAUEBQ1FDUUEBQ1FDUUEBQ1EzYUERISEjcSEhISEjYTEhMREzYTERM2EzYTNhMREzYTNhMREzYTERMREwAFJQABJ0UUAA0FAAAAAAAAAAA=",
       "MOON":"JgBQAAABJJQRExE4ERMRExI3EjcSEhI3EjcSEhI3EjcSEhISEjcSEhISEhISExETERMRExETETgROBE4ETgROBE4ETgROBETEgAFJgABJEcSAA0FAAAAAAAAAAA="
     }

cmd = data.get('command')

if cmd is not None:
  cmd = int(cmd)
  if -10 <= cmd <= 11:
    if cmd == 0:
      loop = 1
      rfc = rf['OFF']
    elif cmd == 1:
      service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rf['ON'])}
      hass.services.call('broadlink', 'send', service_data, False)
      loop = 1
      rfc = rf['MOON']
    elif cmd == 11:
      loop = 1
      rfc = rf['ON']
    else:
      if cmd > 0:
        rfc = rf['UP']
      else:
        rfc = rf['DOWN']
      loop = abs(cmd)

    service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rfc)}
    for i in range(loop):
      hass.services.call('broadlink', 'send', service_data, False)

Thanks for tip.

But still not working as I want.

here is my full dimm_control.py and automation:

rf = { "ON":"JgBQAAABJZMSExE3EhMRExE4ETgRExE4ETgRExI3EjcSEhISEjcSEhISEjcSEhISEhISExETETgRNhMTETgROBE4ETgROBETEgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "OFF":"JgBQAAABJpITERM2ExESEhM2EzYTERM2EzYTERM2EjcTERMSEjcSEhETERMROBI3EjcSEhI3EjcSNxI3EhISEhISEjcTERMREgAFJgABJUYSAA0FAAAAAAAAAAA=",
       "UP":"JgBQAAABKJMSEhI3EhISExE4ETgRExE4ETgRExE4ETgRExETEjcSEhISEjcSEhI3EhIUEBQ1FDUUNRQQFDUUEBQ1FDUUEBQREwAFJAABKEQUAA0FAAAAAAAAAAA=",
       "DOWN":"JgBQAAABJpIUEBQ1FBAUEBQ1FDUUEBQ1FDUUEBQ1EzYUERISEjcSEhISEjYTEhMREzYTERM2EzYTNhMREzYTNhMREzYTERMREwAFJQABJ0UUAA0FAAAAAAAAAAA=",
       "SUN":"JgBUAAABJZITEhI3EhISEhI3EjcSEhI3EjcSEhI3EjcSEhMREzYTERMREzYTNhM2ExETERM2EzYTNhMRExISEhI3EjcSEhISEgAFJgABJUYTAAWLFwANBQAAAAA=",
       "MOON":"JgBQAAABJJQRExE4ERMRExI3EjcSEhI3EjcSEhI3EjcSEhISEjcSEhISEhISExETERMRExETETgROBE4ETgROBE4ETgROBETEgAFJgABJEcSAA0FAAAAAAAAAAA="
     }

cmd = data.get('command')

if cmd is not None:
  cmd = int(cmd)
  if -10 <= cmd <= 12:
    if cmd == 0:
      loop = 1
      rfc = rf['OFF']
    elif cmd == 12:
      service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rf['ON'])}
      hass.services.call('broadlink', 'send', service_data, False)
      loop = 1
      rfc = rf['MOON']
    elif cmd == 11:
      service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rf['ON'])}
      hass.services.call('broadlink', 'send', service_data, False)
      loop = 1
      rfc = rf['SUN']
    else:
      if cmd > 0:
        rfc = rf['DOWN']
      else:
        rfc = rf['UP']
      loop = abs(cmd)

    service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rfc)}
    for i in range(loop):
      hass.services.call('broadlink', 'send', service_data, False)

- alias: 'kitchen_light_set_dimm'
  trigger:
    platform: state
    entity_id: input_number.kitchen_light_dimm
  action:
    service: python_script.dimm_control
    data_template:
      command: >-
        {% 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) %}
        {% set step = (diff / 10) | round(0) %}
        {% if slider == 0 %}
          0
        {% elif slider == 100 %}
          11
        {% elif slider == 10 %}
          12
        {% else %}
          {{step}}
        {% endif %}

I think this is part of py script that not working:

elif cmd == 12:
  service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rf['ON'])}
  hass.services.call('broadlink', 'send', service_data, False)
  loop = 1
  rfc = rf['MOON']

I try to call 12 as service:

python_script.dimm_control {"command":12}

I must call service two times to work properly. Whe I call first time light is ON and when I call second time light goes to MOON mode. Why?

I don’t know and I can’t test it because I don’t have this device.

Maybe the second command (‘MOON’) arrives while the first one (‘ON’) is still being transmitted so it’s ignored. Maybe there needs to be a slight delay between consecutive commands. Try inserting time.sleep(0.25) after each service call.

For example, here:

    elif cmd == 12:
      service_data = {'host':'192.168.2.1', 'packet':'{}'.format(rf['ON'])}
      hass.services.call('broadlink', 'send', service_data, False)
      time.sleep(0.25)
      loop = 1
      rfc = rf['MOON']

and here:

    for i in range(loop):
      hass.services.call('broadlink', 'send', service_data, False)
      time.sleep(0.25)

That will make the script pause for 250 milliseconds after each service call.

If that doesn’t work, I don’t know what else to suggest.

Yes. Sleep time is problem.

I must add:

time.sleep(0.50)

Now slider working as it should:)