How do you use service_template when different services use different attributes? SOLVED

Say that you use a service_template to use either light.turn_on or light.turn_off like this:

service_template: >
  {% if trigger.to_state.state|int > 0 %}
    light.turn_on
  {% else %}
    light.turn_off
  {% endif %}

if you then try to set the brightness for light.turn_on like this:

data_template:
  entity_id: light.kitchen1
  brightness: >
      {% if (trigger.to_state.state|int <= 255) %}                     
      {{ (trigger.to_state.state | int) }}
      {% elif (trigger.to_state.state|int < 301) %}
      {{ 255 }}            
      {% endif %}

…it will fail every time light.turn_off is used. How do you get around this? I tried to use jinja to remove the brightness part but I didn’t manage. Is that possible. Any help would be appreciated.

Can you pass it null?

Just tried it. No, null doesn’t work either. Thanks for the suggestion though.

1 Like

I think you’re stuck with workarounds then.

With lighting the easiest workaround is to use scenes.

This is why I don’t use service_templates. They just don’t work if you try to set any attribute. What we really need to do is get a PR going with an update that doesn’t push attributes if the attributes don’t exist in the device

Is there any reason why it shouldn’t be possible to use jinja to remove that part? This doesn’t work, but to get the idea across:

    data_template:
      entity_id: light.kitchen1
      {% if (trigger.to_state.state|int > 0) %}
      brightness: >
          {% if (trigger.to_state.state|int <= 255) %}                     
          {{ (trigger.to_state.state | int) }}
          {% elif (trigger.to_state.state|int < 301) %}
          {{ 255 }}            
          {% endif %}
      {% endif %}

the problem with that is jinja can only output one item at a time and it cannot output complex objects like dictionaries, lists, etc. You may not realize it, but what you are trying to do is essentially output a dictionary. I’ve spent hours trying to get service templates to work with turn_on / turn_off. Your best option is to have a series of scripts that you execute or move to appdeamon.

I definitely don’t. You might very well be right. I don’t really know what the limitations are. I can’t see the limitations you are talking about on the HA page on templating. How did you come to that conclusion?

I’ve tried everything I can think of to output a value_template as a json object. Whatever built-in HA uses just converts complex objects to string representations of said object.

If that is true, it seems to me to be a pretty serious shortcoming. I imagine that the scenario where you want to press a button to decrease a light incrementally until it turns itself off, is pretty common. It shouldn’t be this hard to implement.

The way I’ve worked around that issue is to send brightness of 0 to light.turn_on instead of calling light.turn_off service.

1 Like

That (i.e., light.turn_on with a brightness of 0) only works for some lights. It depends on the light platform. E.g., it can work for a Z-Wave dimmer, but I’ve been in discussions with people trying to do this where it didn’t work for their particular kind of light.

OK, I’ve solved it now. This is such basic functionality, so I’ve made it as simple to follow as possible for those who happen to come across this topic in the future. This is how I did it:

1: Enable Python scripts in the config file with: python_script: and create a python_scripts folder in your HA folder

2: put the following script in the python_scripts folder, call it brightness_adjust.py

entity_id = data.get('entity_id')
brightness = int(data.get( 'brightness' ))

if brightness == 0:
    service_data = {'entity_id': entity_id }
    hass.services.call('light', 'turn_off', service_data, False)
else:
    service_data = {'entity_id': entity_id, 'brightness': brightness }
    hass.services.call('light', 'turn_on', service_data, False)

then just call:

service: python_script.brightness_adjust

instead of light.turn_on or light.turn_off

brightness 0 will now turn off the lamp completely.

3 Likes

This could have also been done without python scripts and just normal scripts:

light_on.yaml:

      alias: Light On
      sequence:
        - service: light.turn_on
          data_template:
            entity_id: {{ entity_id }}
            brightness: {{ brightness }}

light_off.yaml:

      alias: Light Off
      sequence:
        - service: light.turn_off
          data_template:
            entity_id: {{ entity_id }}

example action:

      action:
        service_template: >
          {% if trigger.to_state.state|int > 0 %}
            script.light_off
          {% else %}
            script.light_on
          {% endif %}
        data_template:
          entity_id: light.kitchen1
          brightness: >
            {% if trigger.to_state.state | int <= 255 %}                     
              {{ trigger.to_state.state | int }}
            {% elif trigger.to_state.state | int < 301 %}
              255            
            {% endif %}
3 Likes

Thank for the sample code here.

I have attempted to implement this for use with a trigger based on a MQTT level message, but the script is returning a DICT error, as I am failing to correctly pass the entity_id to the service template

script:
  alias: Light On
  sequence:
    - service: light.turn_on
      data_template:
        entity_id: {{ entity_id }}
        brightness: {{ brightness }}

  alias: Light Off
  sequence:
    - service: light.turn_off
      data_template:
        entity_id: {{ entity_id }}

automation:
  - id: '2018122000000'
    alias: Match brightness CBUS to Hue with Scripts
    trigger:
    - platform: mqtt
      topic: 'cbus/read/254/56/16/level'
    action:
      service_tempalte: >
        {% if trigger.payload|int > 0 %}
          script.light_off
        {% else %}
          script.light_on
        {% endif %}
      data_template:
        entity_id: light.hue_office_desk
        brightness_pct: "{{ trigger.payload}}"

Any hints on what would be the best way to address this?

thank you

First, you aren’t passing brightness to the script. You are passing brightness_pct. The script isn’t looking for a brightness_pct variable, it’s looking for the brightness variable. Remember, this is not a light, it’s a script. It does not have all the helpers and functionality of a light, I.E. it doesn’t understand the concept of brightness_pct or brightness for that matter, we are just passing variables to the script.

For example, the data_template in the script could have been:

script:
  light_on:
    sequence:
      - service: light.turn_on
        data_template:
          entity_id: {{ my_entity_id_variable }}
          brightness: {{ my_brightness_variable }}

The action for the automation would need to look like this:

  action:
    - service_template: script.light_on
      data_template:
        my_entity_id_variable: light.hue_office_desk
        my_brightness_variable: "{{ trigger.payload }}"

Second, you have a spelling error on service_template. You spelled it: service_tempalte.

So to fix those issues, you need to use brightness as a variable, the number needs to be 0 to 255, not 0 to 100. And you need to rectify the spelling error.

1 Like

Thanks Petro;

You got back much faster than i expected; I had spotted the logic and spelling issues after posting, and with a little more tweaking my final working sample looks as follows:

script:
  light_on:
    alias: Light On
    sequence:
      - service: light.turn_on
        data_template:
          entity_id: "{{ light }}"
          brightness_pct: "{{ brightness }}"
      - service: mqtt.publish
        data_template:
          payload_template: "{{ brightness }}"
          topic: "hue/read/office_table_lamp/level"

  light_off:
    alias: Light Off
    sequence:
      - service: light.turn_off
        data_template:
          entity_id: "{{ light }}"
      - service: mqtt.publish
        data_template:
          payload_template: "0"
          topic: "hue/read/office_table_lamp/level"

automation:
  - id: '2018122000000'
    alias: Match brightness CBUS to Hue with Scripts
    trigger:
    - platform: mqtt
      topic: 'cbus/read/254/56/16/level'
    action:
      service_template: >
        {% if trigger.payload|int == 0 %}
          script.light_off
        {% else %}
          script.light_on
        {% endif %}
      data_template:
        light: light.hue_office_desk
        brightness: "{{ trigger.payload }}"

Your samples have really helped clean up the code.
Damian

1 Like