Template in script does not work

Hi,

I have the following code in my scripts.yaml file:

'1593114678308':
  alias: Decrease Fan Speed
  sequence:
  - above: '0'
    condition: numeric_state
    entity_id: sensor.fave_level_air_purifier
  - data_template:
      entity_id: fan.air_purifier
      level: "{{ states('sensor.fave_level_air_purifier')|int - 1 }}"
    service: xiaomi_miio.fan_set_favorite_level

What I want is to decrease the favourite fan speed level by 1.
The following line:

{{ states('sensor.fave_level_air_purifier')|int - 1 }}

Works perfectly in the templates section of the developer tools and gives the output that I would expect.
However, when I try to run the script, I get the following error:

expected int for dictionary value @ data['level']

Anybody has an idea where this is going wrong? Help is greatly appreciated!

Try it like this:

  - data_template:
      entity_id: fan.air_purifier
      level: >
        {{ states('sensor.fave_level_air_purifier')|int - 1 }}

That shouldn’t make a difference. Both should result in the same string, which the service should coerce into an int. (I just checked the code and the service schema seems correct.)

I would have said I suspected the problem was that the state of sensor.fave_level_air_purifier was not interpretable as a number, but if that were the case then the condition that precedes it should abort the script.

For grins, try using a fixed number, but put it in quotes. E.g., try:

  - data_template:
      entity_id: fan.air_purifier
      level: "2"
    service: xiaomi_miio.fan_set_favorite_level

Does that work?

As much as I theoretically agree with @pnbruckner, @tom_l 's solution did solve the problem for some reason. I also don’t understand why, as the documentation says that these should be identical in function, but at least it works now! thanks!

I bet if you change it to the single line version enclosed with double quotes, and make sure you restart HA, it will work. I suspect you didn’t reload/restart when you needed to and got confused. I can guarantee both are the same in theory and in practice.

Double quotes like in the first snippet of my initial post?

With every edit I made to the script, I did a complete restart of HA before trying to execute it.

Yes.

I don’t know what else to tell you. The two should work the same. Unless I’m overlooking something, but if so, I really can’t imagine what it could be.

This is probably a good reason for enhancing the error message in cases like these to show what the parameters of the service call were to help users diagnose what’s wrong. Unfortunately, the call_service event is only logged (at debug level) if the service schema doesn’t find any problems. If it does find a problem (like here), it only says what the problem was, but doesn’t show the invalid data that was provided with the call.

2 Likes

I agree @pnbruckner, would have been helpful to see what it was doing.

These things are weird, but at this point there’s not much else to do I guess. Thanks for your help!

Well, you’ve put out there that one way doesn’t work like the other, when they should (and as far as I know always have.) This topic will be seen by others and it could cause unnecessary confusion down the road. It would be helpful if you could follow it through so either 1) we can verify that they are the same, and somehow somwhere along the way you did something you didn’t realize, or something like that (not to lay blame or anything, but just to clear things up), or 2) get to the bottom of why they don’t work the same in this case so it can be fixed and nobody else gets tripped up.

Unfortunately I don’t have one of these devices so I can’t test it myself, other than like this:

>>> from homeassistant.components.xiaomi_miio.fan import SERVICE_SCHEMA_FAVORITE_LEVEL
>>> SERVICE_SCHEMA_FAVORITE_LEVEL({"level": 2})
{'level': 2}
>>> SERVICE_SCHEMA_FAVORITE_LEVEL({"level": "2"})
{'level': 2}
>>> SERVICE_SCHEMA_FAVORITE_LEVEL({"level": "2\n"})
{'level': 2}
>>> SERVICE_SCHEMA_FAVORITE_LEVEL({"level": "not a number"})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/phil/repos/core/venv/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 272, in __call__
    return self._compiled([], data)
  File "/home/phil/repos/core/venv/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 594, in validate_dict
    return base_validate(path, iteritems(data), out)
  File "/home/phil/repos/core/venv/lib/python3.7/site-packages/voluptuous/schema_builder.py", line 432, in validate_mapping
    raise er.MultipleInvalid(errors)
voluptuous.error.MultipleInvalid: expected int for dictionary value @ data['level']

The first one shows using a number. The second one is equivalent to using a template on a single line that results in a string representation of a number. And the third way is equivalent to using the multiline YAML version (which causes an extra end of line character.) All work just fine and result in the same number. The fourth shows invalid input resulting in the error you saw. However, given your template, I can’t see how it would result in invalid input. Worst case it should result in "-1", which would just get clamped to 0. So clearly there is more going on than meets the eye.

1 Like

Alright, so after changing some things back and forth and restarting HA in between, I have the following code, where both fan_speed_up with YAML multiline and fan_speed_down work. As you can see, the only thing that’s different is the id of the script which was changed for the sake of legibility. This should not matter and I have tried these combinations earlier as well, but later regenerated the script through the GUI script editor.

fan_speed_up:
  alias: Increase Fan Speed
  sequence:
  - below: '16'
    condition: numeric_state
    entity_id: sensor.fave_level_air_purifier
  - data_template:
      entity_id: fan.air_purifier
      level: >
        {{ states('sensor.fave_level_air_purifier')|int + 1 }}
    service: xiaomi_miio.fan_set_favorite_level
fan_speed_down:
  alias: Decrease Fan Speed
  sequence:
  - above: '0'
    condition: numeric_state
    entity_id: sensor.fave_level_air_purifier
  - data_template:
      entity_id: fan.air_purifier
      level: "{{ states('sensor.fave_level_air_purifier')|int - 1 }}"
    service: xiaomi_miio.fan_set_favorite_level

I’m pretty sure but, I can’t say with 100% certainty that I restarted HA every single time, so it could have been just that.

Thanks for taking the extra time to clear that up! I was starting to question my own sanity. :wink:

1 Like

PR #37171 submitted. … and approved/merged.

2 Likes