How do I convert a string into a "number"?

well… it works on the service call directly :slight_smile: just not via script

can you show what you use as a service call?

^^ this one

can you give this script a try then

I would have said that Home Assistant native typing converted the string "1,11" into a tuple (1, 11). However, I hesitate to say that because I can’t explain why it only happens when the script executes the service call versus when the service call is executed from Developer Tools > Services.

I see it now.

The direct service call uses this:

params: [0,1,"1,11"]

whereas the script uses this:

params: [0, 1, "{{ rooms.get(divisao, '') }}"]

The result of the template within the list is this string '1,11' and to native typing that looks like a tuple and so it gets converted to a tuple.

That would explain the appearance of the tuple in the error message:

{'piid': 38, 'value': (1, 11)}]}
                      ^^^^^^^

Yeah, it was my first thought too, but since I’m a n00b on this I wanted to be sure here.

@petro
The metioned script is missing a “>” after div: right? (otherwise it just has a ton of errors)

Anyway, with the “>” I have this error when it executes:

aspirar: Error executing script. Error rendering template for variables at pos 1: TypeError: can only concatenate list (not "str") to list

that’s possible

that’s not possible, there are no string + [] concatenations. Are you using the one I linked or a previous one

The linked one:

@123
Any idea on how to fool the “guy” ? :wink:

ah ok, then use this config instead. Apparently it does not type corredor

aspirar:
  fields:
    divisao:
      description: "Divisão a aspirar"
  sequence:
    - variables:
        rooms:
          corredor: [1, 11]
          pais: 3
          sala: 6
          meninos: 7
          gonçalo: 8
          cozinha: 9
          escritório: 12
        div:
          {% set which = divisao if divisao is iterable and divisao is not string else [ divisao ] %}
          {% set ns = namespace(ret=[]) %}
          {% for x in rooms.items() | list | selectattr('0', 'in', which) | map(attribute='1') | list %}
            {% set v = [ x ] if x is is_number else x %}
            {% set ns.ret = ns.ret + v %}
          {% endfor %}
          {{ ns.ret }}
    - service: xiaomi_miot.call_action
      target:
        entity_id: vacuum.viomi_v18_e271_robot_cleaner
      data:
        siid: 4
        aiid: 13
        params: [0, 1, "{{ div | join(', ') }}"]
1 Like

Home Assistant’s native typing is based on “If it looks like a duck, it’s a duck” and 1,11 looks like a tuple so it’s a tuple.

oh shit… so i’m doomed on this one? :frowning:

back to the same error message (coverted to a tuple)

Try petro’s suggestion.

… and the same result. Native typing made it a duck again. :slight_smile:

1 Like

ok, i know how to fix it gimme a minute

Ok, to get around the typing applied by templates you have to force a complex structure through the template and it won’t adjust the internal items.

aspirar:
  fields:
    divisao:
      description: "Divisão a aspirar"
  sequence:
    - variables:
        rooms:
          corredor: [1, 11]
          pais: 3
          sala: 6
          meninos: 7
          gonçalo: 8
          cozinha: 9
          escritório: 12
        div:
          {% set which = divisao if divisao is iterable and divisao is not string else [ divisao ] %}
          {% set ns = namespace(ret=[]) %}
          {% for x in rooms.items() | list | selectattr('0', 'in', which) | map(attribute='1') | list %}
            {% set v = [ x ] if x is is_number else x %}
            {% set ns.ret = ns.ret + v %}
          {% endfor %}
          {{ ns.ret }}
    - service: xiaomi_miot.call_action
      target:
        entity_id: vacuum.viomi_v18_e271_robot_cleaner
      data:
        siid: 4
        aiid: 13
        params: "{{ [0, 1, div | join(', ')] }}"
1 Like

fyi @123 you can do this too with the entire data field if you try to force a number to be a string…

data: "{{ {'foo': '123'} }}"

foo will be templateable and still be a string and the entire service data field is templated.

It’s the only way to circumvent the typing from the template engine.

Interesting how the Template Editor handles the first version of the template. It’s not even a tuple; the list ends up having four items.

Compared to your revised version of the template:

yah, it’s because its because the resolver is not recursive. Keeping the returned value from {{ }} a complex type (list or dict) and you’ll be good to go. Data expects a dict, so it’s always a suitable work around.

2 Likes

I couldn’t reply anymore yesterday guys (first day is limited to 21 replies)

Thanks to both of you @petro and @123.

As a side note, that last join on the params has to be join(',') (without space). The vacuum will execute the order but only the first room will be vacuumed. Removing the space fixed it :wink: