Python script to correct Tado TRV temperature, how do I run it in HA?

Hello everyone, I’ve written a script in python (I’m quite new to it) to control the offset applied to a Tado Smart radiator valve; this way I can use an external DHT22 sensor hooked up to a sonoff switch to read the real room temperature and trick the valve into reading the right temperature (instead of it being affected by the heat from the radiator itself)

I’m currently running the script on Windows10, but I would like to run it on my Home assistant on the raspberry.
I chose Python because I thought a python script could be run in home assistant, but I’ve now realised that’s not the case, especially when I use libraries like “requests”, which I need to access the Tado API

What can I do?

The python_script integration runs Python code in a sandboxed environment that disallows importing libraries. However, a Command Line Sensor can call an external Python file which is unrestricted and able to import libraries.

Here’s an example:

1 Like

Thanks, I’ve configured the script and the command line sensor, but how do I know if it’s actually running?

The initial value of a sensor is unknown. If the sensor is now indicating a numeric value (representing the temperature) then that’s evidence that it is working. The default value of scan_interval' is 30 seconds. If the temperature being measured doesn't change frequently, you can increase scan_interval` to 60 seconds or more.

How do I configure it to show a temperature?

All I’ve done is adding this to sensors in configuration.yaml

  - platform: command_line
    name: Tado Offset
    command: 'python3 /config/Tado.py'
    scan_interval: 180

and created Tado.py in /config/

Add unit_of_measurement so that the temperature value will be graphed correctly.

  - platform: command_line
    name: Tado Offset
    command: 'python3 /config/Tado.py'
    unit_of_measurement: '°C'
    scan_interval: 180

If Tado.py returns a simple numeric value, then there’s nothing else to configure. However, if it returns something more complex, you will need to use value_template to extract the numeric value.

For example, let’s say Tado.py returns JSON data like this:

{ "ambient_temperature": 23.5 }

To extract 23.5 we need this:

    value_template: "{{value_json.ambient_temperature}}"

I don’t even see a new sensor showing “unknown”; the script doesn’t return anything (it just does stuff), maybe that’s why?

I’m quite new to python, how do I make it return a value?

You need to fix that first. Even if Tado.py doesn’t work, you should minimally see sensor.tado_offset listed in Developer Tools > States.

  1. Did you create the Command Line Sensor in configuration.yaml in the sensors: section?
  2. Did you restart Home Assistant after you saved configuration.yaml?

1.yes
2.yes

I had a lot of print statement in the script saying “I’m doing this”, “now I’m doing this other thing…”
I’ve removed them all and now the sensor is showing up at least

The script seems to work without triggering the exception, I can tell by looking at the Tado app on my phone that the offset is updated, so that’s good!

However the sensor always dsplays the value 100 (which is triggered by any exception)

Here’s a section of the script

try: #there is other stuff before and after this line
        if abs(NEW_OFFSET-OFFSET)>0.5:
                url="https://my.tado.com/api/v2/devices/"+SERIAL+"/temperatureOffset"
                response = requests.put(url=url, headers=headers, data=data)
                print(NEW_OFFSET)
        
except:
    print(100)
else:
    print(NEW_OFFSET)

Every executed print statement returns data to the Command Line Sensor. So if you had used print statements to debug your code, each one of them was reported to the sensor.

You have only shown a portion of the entire Python script so I don’t know where the variables NEW_OFFEST and OFFSET come from. The sensor calls the script every 30 seconds by default. I don’t know the state of those variables when they are evaluated every 30 seconds so I can’t help you debug it.

If the sensor’s value is always 100 then that means you need to review how the script works.

I think I found the problem; while the script worked on my laptop on windows, it didn’t work on the raspberry because there was a string that contained “hassio.local”; I’ve now replaced this with “localhost”

It would be nice if the sensor displayed the error thrown by the python script for future debugging, is there a way to do that?

As expected, it was due to an error in the python code that wasn’t revealed in the portion you shared. Glad to hear you found and fixed it.

The only way to do that is to make your python script return its data in JSON format. Then you would use the sensor’s json_attributes option to extract the error from the received JSON data and reveal it as an attribute. You would also have to use a value_template to extract the temperature.

For example, let’s say this is the JSON data normally reported by the script:

{ "ambient_temperature": 23.5, "error_message": "none" }

If the script encounters an error it would report it like this:

{ "ambient_temperature": null, "error_message": "your error message goes here" }

The Command Line Sensor’s configuration would be something like this:

  - platform: command_line
    name: Tado Offset
    command: 'python3 /config/Tado.py'
    value_template: "{{value_json.ambient_temperature}}"
    json_attributes:
      - error_message
    unit_of_measurement: '°C'
    scan_interval: 180

Did it work? Can you share the script?

Yes, it works; I can share the script if there is a way to make it public and version controlled

I’m glad to hear that the suggestion I offered helped to answer your original question.

Please mark my first post with the Solution tag. Only you, the author of this topic, can do that. It will automatically place a check-mark next to the topic’s title which signals to others that this topic has an accepted solution. It will also place a link below your first post that leads to the solution. All of this helps others, who may have the same question, to find the answer.