[OPEN] Unable to get the attribute value through script

Hi, I’m trying to call service - xiaomi_miot.call_action which requires aiid as part of the data parameter. If I set static values, the service call works. ex -

              tap_action:
                  action: call-service
                  service: xiaomi_miot.call_action
                  service_data:
                    entity_id: vacuum.mimop
                    siid: 2
                    aiid: 3 

But if try to make it dynamic with a script, the script doesnt works. I’ve tried multiple scripts:

                   aiid: >
                      {% if is_state(entity, 'docked') | is_state(entity, 'paused') | is_state(entity, 'idle') | is_state(entity, 'returning') %}
                        {% set mode = state_attr(entity, 'vacuum.mode') | int(default=0) %}
                          {% if mode == 0 %}
                            {% set id = 3 | int(default=2) %}
                          {% elif mode == 1 %}
                            {% set id = 5 | int(default=2) %}
                          {% elif mode == 2 %}
                            {% set id = 6 | int(default=2) %}
                          {% else %}
                            {% set id = 2 | int(default=2) %}
                          {% endif %}
                          {{id}}
                      {% else %}
                        {% set id = 2 | int(default=2) %}
                          {{id}}
                      {% endif %}

^ this gives an error ‘expected int for dictionary value @ data[‘aiid’]’

                   aiid: >
                      [[[
                        return `[[[
                          if(entity.state === 'docked' || entity.state === 'paused' || entity.state === 'idle' || entity.state === 'returning') {
                            if (entity.attributes.vaccum.mode) {
                              if (entity.attributes.vaccum.mode == 0)
                                return 3
                              else if (entity.attributes.vaccum.mode == 1)
                                return 5
                              else if (entity.attributes.vaccum.mode == 2)
                                return 6
                              else
                                return 2
                            } else {
                              return 2
                            }
                          } else {
                            return 2
                          }
                        ]]]`
                      ]]]

this doesnt work with error stating unknow parameter - mode.

Any help to correct the script would be appreciated.

Also, is there any way that i can use 2 entities in the script? Something like -

                   aiid: >
                      [[[
                        return `[[[
                          if(entity.state === 'docked' || entity.state === 'paused' || entity.state === 'idle' || entity.state === 'returning') {
                            if (select.mimop_mode === 'Sweep')
                              return 3
                            else if (select.mimop_mode === 'Mop')
                              return 6
                            else if (select.mimop_mode === 'Sweep And Mop')
                              return 5
                            else
                              return 2
                          } else {
                            return 2
                          }
                        ]]]`
                      ]]]

Update: Even this doesnt works:

                  aiid: >
                      [[[
                        return `[[[
                          if(states['vacuum.mimop'] === 'docked' || states['vacuum.mimop'] === 'paused' || states['vacuum.mimop'] === 'idle' || states['vacuum.mimop'] === 'returning') {
                            if (states['select.mimop_mode'] === 'Sweep')
                              return 3
                            else if (states['select.mimop_mode'] === 'Mop')
                              return 6
                            else if (states['select.mimop_mode'] === 'Sweep And Mop')
                              return 5
                            else
                              return 2
                          } else {
                            return 2
                          }
                        ]]]`
                      ]]]

Any help would be appreciated :upside_down_face:

The development category is for making integrations and addons and the like.
It looks like this might be an issue with a configuration and should therefore be placed there.
The development category is not visited by many of the viewers on the forum, so you might miss a lot of possible help by having it using that category.

Moved the post to configurations category

This is the first one to solve.
Try to open up HA Developer Tools and click the Service tab. Then make the service call work there and click then the Goto YAML view button to see how the service call looks in YAML.
You need this to get the script right.

Sevice call works.

service: xiaomi_miot.call_action
data:
  throw: false
  entity_id: vacuum.mimop
  siid: 2
  aiid: 2

As I mentioned, it works from the dashboard as well if I dont use the script.

If I check the below code in Developer tools > Template I get the proper output = 6. But I get the error - ‘expected int for dictionary value @ data[‘aiid’]’ if I execute it through dashboard

                 aiid: >
                     {% if is_state(entity, 'docked') | is_state(entity, 'paused') | is_state(entity, 'idle') | is_state(entity, 'returning') %}
                        {% set mode = state_attr(entity, 'vacuum.mode') | int(default=0) %}
                          {% if mode == 0 %}
                            {% set id = 3 | int(default=2) %}
                          {% elif mode == 1 %}
                            {% set id = 5 | int(default=2) %}
                          {% elif mode == 2 %}
                            {% set id = 6 | int(default=2) %}
                          {% else %}
                            {% set id = 2 | int(default=2) %}
                          {% endif %}
                          {{id}}
                      {% else %}
                        {% set id = 2 | int(default=2) %}
                          {{id}}
                      {% endif %}

It should work, but maybe it is the {{id}} that does not get interpreted as an int.
Try to remove the | int(default=2) from the set id line and add it to the {{id}} ones.

Also show the entire script.
It might be an indentation error.

Tried your suggestion, didnt work.

          card:
            type: horizontal-stack
            cards:
              - type: custom:button-card
                entity: vacuum.mimop
                icon: mdi:play-pause
                tap_action:
                  action: call-service
                  service: xiaomi_miot.call_action
                  service_data:
                    entity_id: vacuum.mimop
                    siid: 2
                    aiid: >
                      {% if is_state(entity, 'docked') | is_state(entity, 'paused') | is_state(entity, 'idle') | is_state(entity, 'returning') %}
                        {% set mode = state_attr(entity, 'vacuum.mode') | int(default=0) %}
                        {% if mode == 0 %}
                          {% set id = 3 | int(default=2) %}
                        {% elif mode == 1 %}
                          {% set id = 5 | int(default=2) %}
                        {% elif mode == 2 %}
                          {% set id = 6 | int(default=2) %}
                        {% else %}
                          {% set id = 2 | int(default=2) %}
                        {% endif %}
                        {{id | int(default=3)}}
                      {% else %}
                        {% set id = 2 | int(default=2) %}
                        {{id | int(default=3)}}
                      {% endif %}

In jinja2 we can get attribute like - state_attr(entity, ‘vacuum.mode’) is there any equivalent way in js? as entity.attributes.vacuum.mode doesnt work

I have no idea with js, but I notice that you have aiid: > set.
Could you try to change that to aiid: >-

I think the minus refers to something with line feeds here and you might have extra line feeds, which makes it a multi-line variable and therefore not an int.
You could also replace {% with {%- and %} with -%} to achieve this.

Custom button card doesn’t support js templates inside the service_data. So this is a fruitless effort anyways. Make a script.

@WallyR that doesnt changes the error.

@petro it does work. previously I had this which worked perfectly. Now that I’m trying to add more conditions related to attributes, it has stopped working.

                    aiid: >
                      [[[
                          if(entity.state === 'docked' || entity.state === 'paused' || entity.state === 'idle' || entity.state === 'returning') {
                              return 3
                            } else {
                              return 2
                            }
                      ]]]

entity.attributes["vacuum.mode"]

but you’ll have to use all JS, you can’t use any jinja.

So I tried with this -

                    aiid: >
                      [[[
                          if(entity.state === 'docked' || entity.state === 'paused' || entity.state === 'idle' || entity.state === 'returning') {
                              if(entity.attributes["vacuum.mode"] == 2) {
                                  return 6
                                }
                              return 3
                            } else {
                              return 2
                            }
                      ]]]

3 is getting returned when ideally, 6 should be returned as the attribute value is 2

fan_speed_list:
  - Slient
  - Standard
  - Medium
  - Turbo
battery_level: 100
battery_icon: mdi:battery-charging-100
fan_speed: Turbo
model: ijai.vacuum.v15
lan_ip: 192.168.29.199
mac_address: c8:5c:cc:8d:70:67
entity_class: MiotVacuumEntity
exclude_miot_services:
  - order
exclude_miot_properties:
  - zone_points
  - restrict_points
  - target_point
miot_type: urn:miot-spec-v2:device:vacuum:0000A006:ijai-v15:1
vacuum.status: 4
vacuum.fault: 2105
vacuum.mode: 2
vacuum.sweep_type: 1
vacuum.on: "[1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1]"
disturb.dnd_enable: 1
disturb.dnd_start_hour: 23
disturb.dnd_start_minute: 0
disturb.dnd_end_hour: 7
disturb.dnd_end_minute: 0
disturb.multi_prop_dnd: "[1,23,0,7,0]"
map.remember_state: 1
map.cur_map_id: 1707459788
map.map_num: 5
map.cur_cleaning_path: null
map.build_map: 0
map.has_new_map: 1
sweep.repeat_state: 0
sweep.door_state: 1
sweep.cloth_state: 1
sweep.suction_state: 3
sweep.water_state: 2
sweep.mop_route: 0
sweep.side_brush_life: 88
sweep.side_brush_hours: 160
sweep.main_brush_life: 94
sweep.main_brush_hours: 340
sweep.hypa_life: 88
sweep.hypa_hours: 160
sweep.mop_life: 88
sweep.mop_hours: 160
sweep.time_zone: -19800
sweep.cur_lang: en_US
sweep.cleaning_time: 0
sweep.cleaning_area: 0
sweep.dirt_recognize: 0
sweep.pet_recognize: 0
sweep.ai_recognize: 0
sweep.carpet_booster: 0
sweep.multi_prop_vacuum: >-
  [0,1,1,3,2,0,-19800,0,0.0,0,"en_US","417952602307A00160","en_US",0,-1,40,0,1,2,1]
sweep.tank_shake: 1
sweep.shake_shift: 2
sweep.map_encrypt: 1
alarm: false
alarm.volume: 0
state_updater: lan
vacuum.status_desc: Charging
sub_entities:
  - vacuum-2.status-1
  - sweep-7.side_brush_life-8
  - sweep-7.main_brush_life-10
  - sweep-7.hypa_life-12
  - sweep-7.mop_life-14
  - alarm-4.alarm-1
  - sweep-7.repeat_state-1
  - vacuum-2.mode-4
  - vacuum-2.sweep_type-8
  - sweep-7.water_state-6
  - battery-3.battery_level-1
miot_action_result:
  code: 0
friendly_name: Xiaomi Robot Vacuum-Mop 2 Pro Robot Cleaner
supported_features: 12539
icon: cil:roborock-vacuum

I think entity.attributes[“vacuum.mode”] works with python and not js

that should work fine, look at the developer tools (F12 in chrome) and use js to output values to the console. That’s your only way to debug JS templates.

Also, you could just make this a script with jinja and be done with it instead of dealing with js. There’s no reason to use JS here to do this. You’re still calling a single service.

Initially I tried creating the script with jinja, but it didnt work out

                    aiid: >
                      {% if is_state(entity, 'docked') | is_state(entity, 'paused') | is_state(entity, 'idle') | is_state(entity, 'returning') %}
                        {% set mode = state_attr(entity, 'vacuum.mode') | int(default=0) %}
                        {% if mode == 0 %}
                          {% set id = 3 | int(default=2) %}
                        {% elif mode == 1 %}
                          {% set id = 5 | int(default=2) %}
                        {% elif mode == 2 %}
                          {% set id = 6 | int(default=2) %}
                        {% else %}
                          {% set id = 2 | int(default=2) %}
                        {% endif %}
                        {{id | int(default=3)}}
                      {% else %}
                        {% set id = 2 | int(default=2) %}
                        {{id | int(default=3)}}
                      {% endif %}

but got this error - expected int for dictionary value @ data[‘aiid’]

well you aren’t providing an entity to is_state. You just provided the word entity, which isn’t defined anywhere.

Let me give it a try. In the meantime, i added logs to the js and it confirms the flow is correct.

                    aiid: |-
                      [[[
                                  if(entity.state === 'docked' || entity.state === 'paused' || entity.state === 'idle' || entity.state === 'returning') {
                                      console.log("\nAfter if States:\n");
                                      console.log(entity.state);
                                      console.log("\n\nBefore if attribute vaccum.mode: \n");
                                      console.log(entity.attributes["vacuum.mode"]);
                                      if(entity.attributes["vacuum.mode"] == 2) {
                                          console.log("\n\nAfter if attribute vaccum.mode: \n");
                                          console.log(entity.attributes["vacuum.mode"]);
                                          return 6;
                                        }
                                      console.log("\n\nCheck failed\n");
                                      return 3;
                                    } else {
                                      console.log("\n\nElse\n");
                                      return 2;
                                    }
                      ]]]

I can see - After if attribute vaccum.mode: getting logged in console and value of entity.attributes[“vacuum.mode”] is 2

But the service call is not happening not sure why :sweat_smile:

check your logs, homeassistant.log file.

Nothing in log too. weird.

With this though -

                    aiid: >
                      {% set vacmode = state_attr('vacuum.mimop', 'vacuum.mode') | trim | int(default=0) %}
                        {% if vacmode == 0 %}
                          {% set id = 3 | int(default=2) %}
                        {% elif vacmode == 1 %}
                          {% set id = 5 | int(default=2) %}
                        {% elif vacmode == 2 %}
                          {% set id = 6 | int(default=2) %}
                        {% else %}
                          {% set id = 2 | int(default=2) %}
                        {% endif %}
                      {{id | int(default=2)}}

i’m still getting this error - expected int for dictionary value @ data[‘aiid’]

in template I’m getting correct value - 6

id won’t be defined outside your if statements. Jinja does not have the ability to scope like that. You have to use namespace. There’s no reason to do that anyways. Just output the value.

                        {% set vacmode = state_attr('vacuum.mimop', 'vacuum.mode') %}
                        {% if vacmode == 0 %}
                          3
                        {% elif vacmode == 1 %}
                          5
                        {% elif vacmode == 2 %}
                          6
                        {% else %}
                          2
                        {% endif %}

or if you want to be fancy…

                        {{ {0:3, 1:5, 2:6}.get(state_attr('vacuum.mimop', 'vacuum.mode'), 2) }}