home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
71.11k stars 29.79k forks source link

Script converting string into array for the value field #100635

Closed bfg100k closed 11 months ago

bfg100k commented 11 months ago

The problem

In my script I am making the service call using the value of a variable input_text.viomi_s9_script_helper that contains x,y coordinates as a string. When it runs, the value is getting converted into an array instead.

 service: xiaomi_miot.set_miot_property
 data:
   entity_id: vacuum.viomi_v18_155a_robot_cleaner
   siid: 6
   piid: 1
   value: '{{ states(''input_text.viomi_s9_script_helper'')|string }}'

Log shows

2023-08-08 12:28:01.238 WARNING (SyncWorker_4) [custom_components.xiaomi_miot.vacuum] Viomi S9(viomi.vacuum.v18): Set miot property {'did': '378455517', 'siid': 6, 'piid': 1, 'value': (0.596, -0.431)} failed: No response from the device

When I hardcode the entry for value, it works as expected.

 service: xiaomi_miot.set_miot_property
 data:
   entity_id: vacuum.viomi_v18_155a_robot_cleaner
   siid: 6
   piid: 1
   value: 0.676,-0.217

Log shows

2023-08-08 12:19:50.069 DEBUG (SyncWorker_14) [custom_components.xiaomi_miot.vacuum] Viomi S9(viomi.vacuum.v18): Set miot property {'did': '378455517', 'siid': 6, 'piid': 1, 'value': '0.676,-0.217'}, result: {'code': 0, 'did': '378455517', 'piid': 1, 'siid': 6}

Not sure if this is specific to the custom integration or is this a standard script behaviour?

What version of Home Assistant Core has the issue?

core-2023.8.4

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Container

Integration causing the issue

xiaomi_miot

Link to integration documentation on our website

https://github.com/al-one/hass-xiaomi-miot

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

No response

Additional information

No response

tdejneka commented 11 months ago

or is this a standard script behaviour?

It's standard behaviour.

For a template, the type of the value it produces is inferred from its appearance. For example, a comma-delimited string looks like a tuple (or list) so the end-result is a tuple (or list).

The inclusion of the final string filter in your template doesn't serve to influence Home Assistant's ultimate interpretation of the value's type.

This 'auto type' feature usually works to one's advantage but not always.

bfg100k commented 11 months ago

Thanks for the insight. Is there any workaround to force it to output a string instead?

tdejneka commented 11 months ago

Any use of a template to produce a comma-delimited string will make the final result a tuple (or list). However, you can try this untested workaround which uses two templates where each one simply produces a string.

   value: >
     {% set x = states('input_text.viomi_s9_script_helper').split(',') %}
     {{x[0]}},{{x[1]}}

If the two values in your Input Text are separated by a comma and a space, change split(',') to split(', ')

bfg100k commented 11 months ago

No that didn't work. "value" still gets converted into a list in the output. If I can't fix it here, is my next step to hack up the integration code (i.e. in the set_miot_property method of xiaomi_miot)?

Executed: 21 September 2023 at 13:58:18
Result:
params:
  domain: xiaomi_miot
  service: set_miot_property
  service_data:
    entity_id: vacuum.viomi_v18_155a_robot_cleaner
    siid: 6
    piid: 1
    value:
      - 0.5690000000000001
      - -1.3980000000000001
tdejneka commented 11 months ago

No that didn't work

Then there's no way to avoid Home Assistant's native typing from automatically inferring the data's type from its appearance (short of modifying the code that implements native typing).

bfg100k commented 11 months ago

Is there a way to make a generic service call passing in all the variables as a json string? That should get around the formatting issue.

tdejneka commented 11 months ago

How do you plan to get the value of your Input Text helper into the JSON string? With a template?

bfg100k commented 11 months ago

Is there a way to make a generic service call passing in all the variables as a json string? That should get around the formatting issue.

Managed to get some help from the author of the component regarding this and got the following to work so all good now. Thanks for your help too @tdejneka

 service: xiaomi_miot.set_miot_property
 data: |-
    {{ {
      'entity_id': 'vacuum.viomi_v18_155a_robot_cleaner',
      'siid': 6,
      'piid': 1,
      'value': states('input_text.viomi_s9_script_helper')|string,
    } }}