Rest_Command: How to format the payload in content_type "multipart/form-data"

The current documentation of the RESTful Command integration is a bit unclear about the different options for the content_type variable and how to form the payload variable concerning the different content-types.
I’d like to help updating that documentation to prevent further questions from noobs like me :wink:
Currently I try to POST three keys (user, password and value) via multipart/form-data type but have no clue how to format payload variable. I tried multiple options like

rest_command:
   set_temperatur:
     url: http://controme.local/set/json/v1/1/soll/1/
     method: post
     content_type: "multipart/form-data"
     payload: '"soll=27","user=user","password=password"'`

as well as
payload: '{"soll": "27","user": "user","password": "password"}'
or
payload: "soll=27&user=user&password=password
or
payload: "{'soll': '27','user': 'user','password': 'password'}"
et cetera, et cetera.
My first question: Is there an overview which options are possible for the content_type variable? I’d like to contribute that to the official docs.
And the second question: Shouldn’t we add some examples how to form the payload variable for the different content_types?

That’s not specific to HA.
multipart/form-data has a specific payload format that must be followed, defined in RFC2388

Something like:

--boundary
Content-Disposition: form-data; name="soll"

27
--boundary
Content-Disposition: form-data; name="user"

user
--boundary
Content-Disposition: form-data; name="password"

password

Thanks for the answer, I got your point. The RFC defines - as far as I understand - how the correct protocol request looks like, but there is no description about specific implementations.
Via source code view in postman, you have an excellent overview how to pass variables to lots of different implementations like http, curl or libraries like python requests or C libcurl. As far as I understand, the library or binary will build an request according to the RFC you mentioned with the given options/cli switches.
What I’d like to know is: Which library or binary is used by the RESTfull Command integration or more abstract: how do I have to format the payload as the library has to build the request?
As far as I understand, the integration will form the RFC-matching request with all variables like url and payload, following to the specific variable content_type - or do I get that totally wrong?

Nope. It’s up to you to format the payload according to the content-type you specify.
The library used, aiohttp, is low-level.

REST implies plain json or xml payloads, usually.

@Ener I have exact the same issue with my Controme system. Have you solved that issue?

Hi Markus, I’m actually still facing an issue that the sensors will not reliable publish their humidity values to the gateway - seems to be a physical issue with my cabeling.
Unfortunately I have currently very limited spare time to fix that and this should be done before I write values to the system. As a workaround you can use the following shell command. Add this to your configuration.yaml and adjust to your needs.

shell_command:
  heizungssteuerung_solltemperatur_setzen: 'curl --location --request POST ''http://<controme-ip>/set/json/v1/2/soll/"{{ states(''input_number.controme_hilfsvariable_raum_wunschtemperatur'') }}"/'' --form ''soll="{{ states(''input_number.controme_og_bad_wunschtemperatur'') }}"'' --form ''user="<login-username>"'' --form ''password="<api-password>"'''

I use the “hilfsvariable” to map the right room to the script and the “wunschtemperatur” (currently it’s hardcoded to the bathroom) to hand over the desired room temp. Substitute the “wunschtemperatur” by a more generic variable and that’s it.
I’ll give the RESTful command integration another try when winter has gone :wink:

1 Like

I do have the same system at home and wanted to take the integration further.
However I struggle to get the payload right. As the error message from the REST endpoint is pretty poor I can not use this for debugging what is wrong.

Is there a way to setup the logger in home-assistant to see what is sent over the wire?
I tried different things but without success. Either I get the logs flooded with debug information from all kind of rest calls, or I do not see anything meaningful.

Last thing I tried was

logger:
    default: critical
    logs:
        homeassistant.components.rest_command: info
        aiohttp: info

But all I can see in the logs is:

WARNING (MainThread) [homeassistant.components.rest_command] Error. Url: http://contromeminiserver.fritz.box/set/json/v1/1/ziel/5/. Status code 403. Payload: b'"boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="user" <my_username> ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="password" <my_password> ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="ziel" 22.25 ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="duration" default ----WebKitFormBoundary7MA4YWxkTrZu0gW"'

That tells you the request in unauthorized.

Hi,
I know that 403 means unauthorized.
The problem is that the API is build in a strange way. It returns 403 for any kind of malformed message.
Not only if the credentials, which are part of the payload, are invalid. Same error is returned if you have a typo in any other parameter.
Makes troubleshooting quite painful.

Therefore I need to see how the payload is exactly formatted to check what is wrong. This would allow me comparing it to working request in my Postman.

I struggled with various ways to pass the formatted payload through the restful command but none worked.
The shell/curl solution works flawlessly, thanks for the tip :wink:

U R welcome. Unfortunatly, it’s still on my list to investigate that further but without ETA.