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