Problem with leading '|-' in script when using templated string

I try to get my roborock to clean previously selected rooms (by setting appropriate helpers in the dashboard, then calling a script to evaluate them).

When creating a button “clean all”, I can sucessfully use this action to start the cleaning:

    tap_action:
      action: perform-action
      perform_action: vacuum.send_command
      target:
        entity_id: vacuum.s8_pro_ultra
      data:
        command: app_segment_clean
        params:
          - segments:
              - 16
              - 17
              - 18
              - 19
              - 20
              - 21
              - 22
            repeat: 1

so the idea for the script of selected rooms was to built a string of the selected segments and parse it to the action call. Here is my current script (I omitted all rooms except of 20/22 to make it shorter for this post):

alias: Roborock - Ausgewählte Räume reinigen
sequence:
  - action: input_text.set_value
    metadata: {}
    data:
      value: ""
    target:
      entity_id: input_text.roborock_raumstring
  - if:
      - condition: state
        entity_id: input_boolean.roborock_raummerker_kuche_eg
        state: "on"
    then:
      - if:
          - condition: state
            entity_id: input_boolean.roborock_raummerker_erster_raum
            state: "on"
        then:
          - action: input_text.set_value
            metadata: {}
            data:
              value: "- 20"
            target:
              entity_id: input_text.roborock_raumstring
          - action: input_boolean.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: input_boolean.roborock_raummerker_erster_raum
        else:
          - action: input_text.set_value
            metadata: {}
            data:
              value: |-
                {{ states('input_text.roborock_raumstring') ~ ('\n  ') ~ '- 22'}}
            target:
              entity_id: input_text.roborock_raumstring
  - if:
      - condition: state
        entity_id: input_boolean.roborock_raummerker_vorkuche
        state: "on"
    then:
      - if:
          - condition: state
            entity_id: input_boolean.roborock_raummerker_erster_raum
            state: "on"
        then:
          - action: input_text.set_value
            metadata: {}
            data:
              value: "- 22"
            target:
              entity_id: input_text.roborock_raumstring
          - action: input_boolean.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: input_boolean.roborock_raummerker_erster_raum
        else:
          - action: input_text.set_value
            metadata: {}
            data:
              value: |-
                {{ states('input_text.roborock_raumstring') ~ ('\n  ') ~ '- 22'}}
            target:
              entity_id: input_text.roborock_raumstring
  - action: vacuum.send_command
    target:
      device_id: f4936401a4e1341427a6b322db1f0d86
    data:
      command: app_segment_clean
      params: |-
        {{ '- segments:' ~ ('
            ') ~ states('input_text.roborock_raumstring') ~ ('
          ') ~ 'repeat: 1' }}
    enabled: true
description: ""
fields: {}

It generates the right string (based on selection of rooms, and runs without errors, but does not start the cleaning. When looking in the traces of the script, I see that there is an additionally “|-” added after the “params:”

and I guess this is the culprit causing that the command is not understood by the roborock. I tried different formatting of the template in the script, but do not get rid of the “|-”. Does anyone encounterd the same or has any suggestions for me?

Those hyphens in the segments section are not part of the value, they are YAML list item separators. You need to provide an actual list, not just a list-shaped string.

I would probably approach it a different way. Instead of stacking If’s and running them through an input, process the booleans and build your list of segments in variables:

sequence:
  - variables:
      bools:
        "16": input_boolean.roborock_raummerker_bad_eg
        "17": input_boolean.roborock_raummerker_schlazi_eg
        "18": input_boolean.roborock_raummerker_wozi_eg
        "19": input_boolean.roborock_raummerker_flur_eg
        "20": input_boolean.roborock_raummerker_kuche_eg
        "21": input_boolean.roborock_raummerker_esszi_eg
        "22": input_boolean.roborock_raummerker_vorkuche
      b_items: "{{ bools.items()|list }}"
      segs: "{{b_items|selectattr(1, 'is_state', 'on')|map(attribute=0)|list}}"
      ents: "{{b_items|selectattr(0, 'in', segs)|map(attribute=1)|list}}"
 - action: vacuum.send_command
    target:
      device_id: f4936401a4e1341427a6b322db1f0d86
    data:
      command: app_segment_clean
      params: |-
        {{ {'segments': segs|map('int')|list, 'repeat': 1} }}
    enabled: true
  - action: input_boolean.turn_off
    metadata: {}
    data: {}
    target:
      entity_id: "{{ ents }}"
description: ""
fields: {}

Please double check the correlations between segment ID numbers and input boolean entity IDs. I couldn’t tell if there was a typo in the original post or if I just didn’t understand exactly what you were going for…

EDIT: Fixed Typos

1 Like

Hey, thanks a lot!!! :smiley:

This is of course much more tidy solution! I think in general I can undestand what you are doing there (only starting with templating / more complex scripts), so you define first boolean variables for each room helper entitiy, then select only the ones in on state to the segs list, and only the onces in the seg list for the ents list (to turn them off at the end).

However, when I try to run the script, I get a error message:

UndefinedError: str object has no element 1

which seems to be caused by the “selectattr(1, …)” for the segs variable. Unfortunately don’t know how to fix/approach this (as said only starting with the templating :see_no_evil:).

I extended the code to contain all rooms (as in your version it’s short enough to include everything), but the error is already occuring even in the total unaltered version:

sequence:
  - variables:
      bools:
        "16": "input_boolean.roborock_raummerker_bad_eg"
        "17": "input_boolean.roborock_raummerker_schlazi_eg"
        "18": "input_boolean.roborock_raummerker_wozi_eg"
        "19": "input_boolean.roborock_raummerker_flur_eg"
        "20": "input_boolean.roborock_raummerker_kuche_eg"
        "21": "input_boolean.roborock_raummerker_esszi_eg"
        "22": "input_boolean.roborock_raummerker_vorkuche"
      b_items: "{{ bools.items() }}"
      segs: "{{ b_items | selectattr(1, 'is_state', 'on') | map(attribute=0) | list }}"
      ents: "{{ b_items | selectattr(0, 'in', segs | list ) | map(attribute=1) | list }}"
  - action: vacuum.send_command
    target:
      device_id: f4936401a4e1341427a6b322db1f0d86
    data:
      command: app_segment_clean
      params: "{{ {'segments': segs | map('int') | list  , 'repeat': 1 } }}"
    enabled: true
  - action: input_boolean.turn_off
    metadata: {}
    data: {}
    target:
      entity_id: "{{ ents }}"
description: ""
fields: {}

I should have applied the list filter in b_items:man_facepalming:

I have corrected it above.

Great thanks!! The script is now running exactly as it should and sends the right command as of the trace: :star_struck:

params:
  domain: vacuum
  service: send_command
  service_data:
    command: app_segment_clean
    params:
      segments:
        - 16
        - 20
        - 21
      repeat: 1
    entity_id:
      - vacuum.s8_pro_ultra
  target:
    entity_id:
      - vacuum.s8_pro_ultra

Strangely, the robot is still not starting (though it’s now exactly same format as what is behind the working buttons) - but I guess this is now not a script problem anymore! :sweat_smile:

Anyway, will then go on to figure that out. Thanks a lot again for the rapid answers and for letting me learn new things about templates and variables in scripts!!

For completeness: Now everything works - I still needed one change in the script to convince the roborock to start: The service is expecting the additional “-” before “segments” in the params. I missed this when initially evaluating the script trace. So after adding a “-” before the params template now the roborock gets it and starts cleaning of the selected rooms. Here the final script, and thanks once more to Didgeridrew!!

alias: Roborock - Ausgewählte Räume reinigen
sequence:
  - variables:
      bools:
        "16": input_boolean.roborock_raummerker_bad_eg
        "17": input_boolean.roborock_raummerker_schlazi_eg
        "18": input_boolean.roborock_raummerker_wozi_eg
        "19": input_boolean.roborock_raummerker_flur_eg
        "20": input_boolean.roborock_raummerker_kuche_eg
        "21": input_boolean.roborock_raummerker_esszi_eg
        "22": input_boolean.roborock_raummerker_vorkuche
      b_items: "{{ bools.items()|list }}"
      segs: >-
        {{ b_items | selectattr(1, 'is_state', 'on') | map(attribute=0) | list
        }}
      ents: >-
        {{ b_items | selectattr(0, 'in', segs | list ) | map(attribute=1) | list
        }}
  - action: vacuum.send_command
    target:
      device_id: f4936401a4e1341427a6b322db1f0d86
    data:
      command: app_segment_clean
      params:
        - "{{ {'segments': segs | map('int') | list  , 'repeat': 1 } }}"
  - action: input_boolean.turn_on
    metadata: {}
    data: {}
    target:
      entity_id: "{{ ents }}"
description: ""
fields: {}