How to use template in service_data?

Hi guys,
I was trying to write a template for a call-service, in particular I would pass dinamically the content parameter:

          tap_action:
          action: call-service
          service: vacuum.send_command
          service_data:
            command: clean
            entity_id: vacuum.robi
            params:
              act: start
              content:  '' #<----- here the dynamic content: ex:'1' or '2,2' 
              count: 1
              type: spotArea

I’m using different input boolean in order to build the template, but it does not work:

      tap_action:
      action: call-service
      service: vacuum.send_command
      service_data:
        command: clean
        entity_id: vacuum.robi
        params:
          act: start
          content: >
            {%- set x = "" %} {% if
            is_state('input_boolean.clean_bedroom_boolean', 'on') %} {% set x =
            x + "6," %} {% endif %} {{x[:-1]}}   
          count: 1
          type: spotArea
    type: 'custom:button-card'

How can I use it?

Thanks

If you want to use templates in lovelace directly, you’ll have to get a custom card.

So here are 2 options:

  1. Create a script that is called on button press. This will handle the templates: No need for custom cards. (I didn’t validate your yaml template fyi)
script:
  lovelace_robot_tap:
    sequence:
      - service: vacuum.send_command
        data_template:
          command: "{{ command }}"
          entity_id: "{{ entity_id }}"
          params:
            act: start
            content: >
              {%- set x = "" %} 
              {% if is_state('input_boolean.clean_bedroom_boolean', 'on') %} 
                {% set x = x + "6," %} 
              {% endif %} 
              {{x[:-1]}}
            count: "{{count}}"
            type: "{{type}}"

Then your tap action is just

          type: entity-button # Standard card
          tap_action:
            action: call-service
            service: script.lovelace_robot_tap
            service_data:
              command: clean
              entity_id: vacuum.robi
              count: 1
              type: spotArea

  1. Use a custom card. I see you have type ‘custom:button-card’.

I can only guess as to which card it is. The first thing that showed up in google was

So good chance that is it. The templates are in javascript there. It’s not YAML. This is card specific!

So your custom button template would be:

  tap_action:
  action: call-service
  service: vacuum.send_command
  service_data:
    command: clean
    entity_id: vacuum.robi
    params:
      act: start
      content: >
        [[[ 
          if (states['input_boolean.clean_bedroom_boolean'].state === 'on')
            return "6";
          return "";
        ]]]
      count: 1
      type: spotArea
type: 'custom:button-card'

Keep in mind, I do not understand the template. You are setting x to “”, then appending “6,” if the boolean is on, then returning only the first part (6). So I just return “6” if the boolean is on…

2 Likes

You’re right, he most likely uses button-card (and maybe lovelace_gen).
The former uses JS templates, not jinja as per OP.

So TS need to read the docs as I have to agree that the logic is a bit unclear and it needs to be redesigned as I’m not sure at all if it’s possible to combine JS template’s output with lovelace_gen (which operated python’s data).

Thanks for the solution! I used the first one with script:

vacuum_clean_zone:
  alias: Pulisci zona
  sequence:
  - service: vacuum.send_command
    data_template:
      command: "{{command}}"
      entity_id: "{{entity_id}}"
      params:
        act: start
        content: >
            {%- set x = "" %} 
            {% if is_state('input_boolean.clean_kitchen_boolean', 'on') %} 
            {% set x = x + "0," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_living_boolean', 'on') %} 
            {% set x = x + "2," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_lunch_boolean', 'on') %} 
            {% set x = x + "10," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_disimpegno_boolean', 'on') %} 
            {% set x = x + "3," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_little_bathroom_boolean', 'on') %} 
            {% set x = x + "5," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_bathroom_boolean', 'on') %} 
            {% set x = x + "4," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_bedroom_boolean', 'on') %} 
            {% set x = x + "6," %} 
            {% endif %} 
            {% if is_state('input_boolean.clean_little_bedroom_boolean', 'on') %} 
            {% set x = x + "9," %} 
            {% endif %} 
            {{x[:-1]}}
        count: "{{count}}"
        type: "{{type}}"
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_kitchen_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_living_boolean 
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_lunch_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_disimpegno_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_little_bathroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_bathroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_bedroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_little_bedroom_boolean

The template is needed in order to build a string (1,2,3) with the concatenation of all room numbers that the service needs in order to do a spot clean. I’m using this UI in order to do that:

image

Firstlly I select the room and then I click to “Pulisci” button (it means clean :slight_smile: )

Oh, you just shortened it for us :P. It seemed odd :stuck_out_tongue:

I just got a robot vacuum…and that card looks awesome! Now I want NEED that card in my HA…

1 Like

:grinning: yes sorry for the previous abbreviation!

Here you will find all our discussions about that card and the integration with Deebot vacuums … but the card can be used for all brands

1 Like

@jocnnor solution 1 is interesting, love the idea! :+1:

@Gabriele_Mandalari and Jim: it looks like the command parameter is unnecessary as it’s not used in the code so I’d suggest to remove it

Also, I believe you can avoid using that long content template by putting all your input_booleans in a group and then filtering it by state and producing a list. Haven’t tried it but I think it’s an option.
That will possibly make your system easier to expand/modify as you’ll mainly need to add a new input_boolean in that group to have a new room cleaned (I know you don’t get a new one every month but still… :wink: )

1 Like

ahah thanks for the suggestion!

1 Like

In script.vacuum_clean_zone, you can reduce the size of the content template like this:

vacuum_clean_zone:
  alias: Pulisci zona
  sequence:
  - service: vacuum.send_command
    data_template:
      command: "{{command}}"
      entity_id: "{{entity_id}}"
      params:
        act: start
        content: >
            {% set rooms = [ ['kitchen', 0],
                             ['living', 2],
                             ['lunch', 10],
                             ['disimpegno', 3],
                             ['little_bathroom', 5],
                             ['bathroom', 4],
                             ['bedroom', 6],
                             ['little_bedroom', 9] ] %}
            {% set ns = namespace(x = '') %}
            {% for room in rooms if is_state('input_boolean.clean_' ~ room[0] ~ '_boolean', 'on') %}
                {% set ns.x = ns.x ~ room[1] ~ (',' if not loop.last else '') %}
            {% endfor %}
            {{ ns.x }}
        count: "{{count}}"
        type: "{{type}}"
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_kitchen_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_living_boolean 
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_lunch_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_disimpegno_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_little_bathroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_bathroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_bedroom_boolean
  - service: input_boolean.turn_off
    data:
       entity_id: input_boolean.clean_little_bedroom_boolean

How it works:

  • It defines a list called rooms where each item in the list is yet another list containing the room’s name and value.
  • It defines a global variable ns.x to store the selected room values.
  • It iterates through the rooms list but only for items whose corresponding input_boolean is on.
  • An eligible room has its value appended to ns.x. A comma is appended to the value but not if it’s the last value.
  • It reports the variable ns.x.

NOTE:
The tilde character (~) is used to indicate concatenation. The plus character (+) can be ambiguous because it can add numbers or, if one of the values is a string, concatenate them. Ideally, use tilde when you want concatenation and use plus when you want addition.

2 Likes

@123 Thanks for the code,

I just have a question, I would like my vacuum cleaner to vacuum the rooms in the order I choose, by clicking on the buttons(inputs boolean) of the rooms in the order I want.

However, your code always puts the part numbers in ascending order, even if I click on the parts (numbers) that are not in ascending order.

How can I get it to clear them in the order I selected?

Thanks