Data_template in automations to output number array

Hello fellas.
I have an issue with my data_template that i want to use for calling my robot vacuumer to start cleaning specific rooms based on some GUI layout in home assistant, everything is working fine except the last step with calling the automation correctly.

I fear that the data_template in automation seem to only return strings and can’t convert to a number array. I have tried all I can think off, hope anyone if more experienced. Thank you in advance!

Here’s my code:

- alias: Vacuum Selected Rooms
  trigger:
    platform: state
    entity_id: input_boolean.vacuum_startrooms
    to: 'on'
  action:
  - service: vacuum.send_command
    data_template:
      command: app_segment_clean
      entity_id: vacuum.shiny
      params: >-
        [ 
        {%- set rooms = {
          "25": "input_boolean.vacuum_kitchen",
          "17": "input_boolean.vacuum_bedroom",
          "21": "input_boolean.vacuum_livingroom",
          "19": "input_boolean.vacuum_hallway"
        } -%}
        {%- for id in rooms %}
          {%- if is_state(rooms[id], 'on') %}
            {{ id }},
          {%- endif %}
        {%- endfor -%}
        ]

So i want the output to be something like: [17,19] e.g. in number format.
I’ve tried to use | int even after the {{ id }} and also around it all, doesnt seem to work.
The only thing that actually works is if i hardcode "params: [17,19] then it works…
I suspect as mention it is due to a string and somehow not converted correctly…

I get the following error no matter what:
Unable to send command to the vacuum: {'code': -10000, 'message': 'data for segment is not a number'}

Does it work if you remove the quotes from around the numbers?

Correct. A template always produces a string.

This works:

params: [ "{{template1}}", "{{template2}}", "{{template3}}" ]

It has fixed number of list items and each one has its own template.

However, it will fail if you attempt to use a template to dynamically generate a variable number of list items.

If the value 0 can be used to instruct your vacuum to ‘skip this room’ (i.e. ‘do nothing’) then you can use this template which has a fixed number of list items:

      params:
        - "{{ '25' if is_state('input_boolean.vacuum_kitchen', 'on') else '0'}}"
        - "{{ '17' if is_state('input_boolean.vacuum_bedroom', 'on') else '0'}}"
        - "{{ '21' if is_state('input_boolean.vacuum_livingroom', 'on') else '0'}}"
        - "{{ '19' if is_state('input_boolean.vacuum_hallway', 'on') else '0'}}"

If 0 can’t be used that way then I don’t know how you can achieve your goal.

You should check if your vacuum platform has a specific service for this, which might be better for what you’re trying to do.

Barring that, you could easily do this in a Python Script:

rooms = {
    "kitchen": 25,
    "bedroom": 17,
    "livingroom": 21,
    "hallway": 19,
}

params = []
for room_name, room_number in rooms.items():
    if hass.states.get("input_boolean.vacuum_" + room_name).state == 'on':
        params.append(room_number)

service_data = {
    'command': 'app_segment_clean',
    'entity_id': 'vacuum.shiny',
    'params': params,
}
hass.services.call('vacuum', 'send_command', service_data)

EDIT: Fixed above code per discussion below.

1 Like

Thank you for all your replies.
I thought your suggestion @pnbruckner was worth a shot so I tried making my first python script(s).

However the comparison to “on” doesnt seem to work and i can’t figure out what is wrong, i’ve use the “logger” option to see some output of my script running.
I tried with the following code:

rooms = {
    "kitchen": 25,
    "bedroom": 17,
    "livingroom": 21,
    "hallway": 19,
}

params = []
for room_name, room_number in rooms.items():
    if hass.states.get("input_boolean.vacuum_" + room_name) == 'on':
        params.append(room_number)
logger.info("params: %s", params)
logger.info("The State call: %s", hass.states.get("input_boolean.vacuum_" + room_name))
logger.info("Is state on?: %s", hass.states.get("input_boolean.vacuum_" + room_name) == 'on')
logger.info("Room number: %s", room_number)

service_data = {
    'command': 'app_segment_clean',
    'entity_id': 'vacuum.shiny',
    'params': params,
}

and the output from Home assistint in the docker view was:


2020-05-27 22:22:30 INFO (SyncWorker_10) [homeassistant.components.python_script.rooms_to_vacuum.py] params: [],
2020-05-27 22:22:30 INFO (SyncWorker_10) [homeassistant.components.python_script.rooms_to_vacuum.py] The State call: <state input_boolean.vacuum_hallway=on; editable=False, friendly_name=Hallway @ 2020-05-27T22:08:12.177876+02:00>,
2020-05-27 22:22:30 INFO (SyncWorker_10) [homeassistant.components.python_script.rooms_to_vacuum.py] Is state on?: False,
2020-05-27 22:22:30 INFO (SyncWorker_10) [homeassistant.components.python_script.rooms_to_vacuum.py] Room number: 19

Is it most likely my lack of python knowledge, but what’s wrong with that comparison?
If i toggle the hallway boolean it correcly states “off”, so i know that part works at least.

Ah, that’s because I forgot something. D’oh! This:

hass.states.get("input_boolean.vacuum_" + room_name)

should be this:

hass.states.get("input_boolean.vacuum_" + room_name).state

I’ll update my previous post accordingly.

@pnbruckner - fantastic… it works like a charm. Thank you very much for teaching me a bit of Python, guess it’s not so bad :smiley:
Appreciate the help!

1 Like

This forum needs a Design Patterns or Best Practices section where solutions to common challenges can be posted. For example, creating templates for rgb_color and params. Whereas rgb_color can be handled with a template (albeit not very elegantly), creating a dynamic list for params is beyond a template’s abilities. Your python_script is the best alternative I’ve seen and definitely a prime candidate for a Design Patterns section.