HA denies REST API Request when it comes from inside its own docker container

Hello there,

I need to send a float32 value to something via the modbus integration. There exists a limitation within the modbus integration which requires to send the float32 value as two float16 values to work around that limitation. I’ll include the specifics for the off chance, that I missed something and don’t the to use the REST API after all.

The transformation works as follows:

  1. Convert the float32 value of, for example, 1.3, to the hexadecimal notation compliant with the IEEE 754 standard: 0x3fa66666
  2. Split the string into two 4 character strings and add a 0x before the second one, resulting in: 0x3fa6, 0x6666
  3. Send those values via the modbus integration

Performing those operations doesn’t seem possible with the script syntax used by Home Assistant(JINJA?) alone, therefore I defined a shell_command integration in the configuration.yaml, which calls a python script that performs those operations and need a way to return those values:

shell_command:
    convert_float_script: 'python3 convertfloat32tofloat16.py {{ float32_value }}'

The script gets called, the path isn’t an issue here.

According to the docs (Shell Command - Home Assistant) for shell commands, the output of that python script is supposed to be usable by defining a response_variable in the script that calls that shell_command and using {{ custom_response[‘stdout’] }} in another service defined in that same script. This simply doesn’t output anything for me, though {{ custom_response[‘returncode’] }} works.

This is my test script:

test_convert_float32:
    sequence:
      - service: shell_command.convert_float_script
        data_template:
          float32_value: 1.3
        response_variable: custom_response
      - service: input_text.set_value
        data:
          value: "{{ custom_response['stdout'] }}"
        target:
          entity_id: input_text.float32test

I created a text helper (input_text.float32test) to serve as a temporary display with the capabilty to track changes.

So, since the response_variable approach didn’t work, I tried to go the API route. I reduced the above script to

test_convert_float32:
    sequence:
      # This is Home Assistant Script Syntax
      - service: shell_command.convert_float_script
        data_template:
          float32_value: 3.6

and modified the python script to not return the values, but to post them to the REST API and change the value of input_text.float32test that way:

 url = "http://HOSTIP:8123/api/services/input_text/set_value"
    headers = {
        "Authorization": "Bearer myToken",
        "content-type": "application/json",
    }
    data = {"entity_id": "input_text.float32test", "value": str(result1) + ", " + str(result2)}

    response = post(url, headers=headers, json=data)

This works great when running the python script from a different computer, but doesn’t work when run by the shell command integration. It results in this log entry:

WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from localhost.localdomain (127.0.0.1). Requested URL: '/api/services'. (Python-urllib/3.9)

The token is valid, the script works from a different computer and I even added

http:
  use_x_forwarded_for: true
  trusted_proxies: 127.0.0.1

to the configuration.yaml in an unsuccessful try to resolve this issue. I also tried to replace the HOSTIP with localhost, same issue. Note that HA is running inside a docker container.

I’m honestly at my wits end here, I simply want to send a float32 value via the modbus integration. Any ideas? What am I overlooking?

Maybe this?

headers:
      Authorization: "Bearer myToken"
      Content-Type: "application/json"

Going back to your initial issue, you don’t say which installation you run, but it’s unlikely python3 convertfloat32tofloat16.py, without the script path, will work.

/config/python_scripts/convertfloat32tofloat16.py

import sys

print('0x3fa6 0x6666 ' + sys.argv[1])

convert_float_script: 'python3 /config/python_scripts/convertfloat32tofloat16.py {{ float32_value }}'
test_convert_float32:
  sequence:
    - service: shell_command.convert_float_script
      data:
        float32_value: 1.3
      response_variable: custom_response
    - service: input_text.set_value
      data:
        value: "{{ custom_response['stdout'] }}"
      target:
        entity_id: input_text.float32test  

image

1 Like

Thank you so much for taking the time to test this out, turns out I’m simply a bit stupid.

The path as originally defined works fine, but I wrapped my python code in a function. And guess what? I never called the function. Ugh. I debugged everything I could find, but didn’t catch that rookie mistake.

response_variable works as expected, maybe this thread can help somebody trying to archive something similar in the future.