teslamate-org / teslamate

A self-hosted data logger for your Tesla 🚘
https://docs.teslamate.org
MIT License
5.82k stars 728 forks source link

home-assistant template errors #4247

Open brianmay opened 1 day ago

brianmay commented 1 day ago

Is there an existing issue for this?

What happened?

Is starting to urk me that home-assistant is generating non-stop errors on my system. This aren't actually "errors" in the sense of something going wrong, just annoying to look at in the logs.

It would look appear the biggest culprit is the teslamate recommended config from https://docs.teslamate.org/docs/integrations/home_assistant/

Unfortunately, my home-assistant knowledge in fixing these isn't particularly great.

(on a semi-related note, would be really good id teslamate could send out discovery messages so that this can be auto-configured - see https://www.home-assistant.io/integrations/mqtt#mqtt-discovery - assuming this is possible)

Expected Behavior

No errors

Steps To Reproduce

Run home-assistant after adding settings from https://docs.teslamate.org/docs/integrations/home_assistant/

Relevant log output

Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.127 WARNING (MainThread) [homeassistant.components.mqtt.mixins] TypeError: Object of type LoggingUndefined is not JSON serializable rendering template for entity 'device_tracker.tesla_active_route_location', template: '{{ value_json.location | tojson }}' and payload: {"error":"No active route available"}
Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.127 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'destination' when rendering '{{ value_json.destination }}'
Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.127 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'energy_at_arrival' when rendering '{{ value_json.energy_at_arrival }}'
Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.128 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'miles_to_arrival' when rendering '{{ value_json.miles_to_arrival }}'
Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.128 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'minutes_to_arrival' when rendering '{{ value_json.minutes_to_arrival }}'
Oct 07 15:10:43 iot2 homeassistant[107792]: 2024-10-07 15:10:43.128 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'traffic_minutes_delay' when rendering '{{ value_json.traffic_minutes_delay }}'
Oct 07 15:10:45 iot2 homeassistant[107792]: 2024-10-07 15:10:45.723 ERROR (Thread-9) [pychromecast.socket_client] [Dining room TV(192.168.5.192):8009] Failed to connect to service MDNSServiceInfo(name='Chromecast-c6be7577e2d8f2215bf00c76a003635b._googlecast._tcp.local.'), retrying in 5.0s
Oct 07 15:10:46 iot2 homeassistant[107792]: 2024-10-07 15:10:46.176 ERROR (MainThread) [homeassistant.helpers.event] Error while processing template: Template<template=({{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}) renders=2>
Oct 07 15:10:46 iot2 homeassistant[107792]: homeassistant.exceptions.TemplateError: ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}' but no default was specified
Oct 07 15:10:46 iot2 homeassistant[107792]: 2024-10-07 15:10:46.179 ERROR (MainThread) [homeassistant.components.template.template_entity] TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_active_route_distance_to_arrival_km'


### Screenshots

_No response_

### Additional data

_No response_

### Type of installation

Manual

### Version

latest
JakobLichterfeld commented 22 hours ago

Nice find. Not using home-assistant atm. From what I see, this only occurs when you do not have an active navigation destination set in car. Then the MQTT values are empty. So the "error" handling could be improved.

@longzheng: can you please take a look into it? You introduced it with #3657. Ty.

longzheng commented 21 hours ago

I think https://github.com/teslamate-org/teslamate/pull/3923 is more relevant to this issue since that's where I defined/added the Home Assistant sensors.

I thought I had already handled this with the availability attribute on device_tracker

- device_tracker:
    name: Active route location
    object_id: tesla_active_route_location
    unique_id: teslamate_1_active_route_location
    availability: &teslamate_active_route_availability
      - topic: "teslamate/cars/1/active_route"
        value_template: "{{ 'offline' if value_json.error else 'online' }}"
    device: *teslamate_device_info
    json_attributes_topic: "teslamate/cars/1/active_route"
    json_attributes_template: "{{ value_json.location | tojson }}"
    icon: mdi:crosshairs-gps

And then each sensor references the availability: *teslamate_active_route_availability

- sensor:
    name: Active route energy at arrival
    object_id: tesla_active_route_energy_at_arrival
    unique_id: teslamate_1_active_route_energy_at_arrival
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: "{{ value_json.energy_at_arrival }}"
    unit_of_measurement: "%"
    icon: mdi:battery-80

But my Home Assistant sensor experience is very limited so maybe that's not right.

I had also assumed by setting the availability state that it wouldn't then try to parse the json_attributes_template, but maybe that's not quite right either.

longzheng commented 20 hours ago

OK after a bit more digging, it looks like availability has no impact on whether the MQTT integration tries to parse the json_attributes, it will try to parse it even if the device is unavailable from the availability.

I think an alternative is to define a conditional json_attributes_template like

- device_tracker:
    name: Active route location
    object_id: tesla_active_route_location
    unique_id: teslamate_1_active_route_location
    availability: &teslamate_active_route_availability
      - topic: "teslamate/cars/1/active_route"
        value_template: "{{ 'offline' if value_json.error else 'online' }}"
    device: *teslamate_device_info
    json_attributes_topic: "teslamate/cars/1/active_route"
    json_attributes_template: >
      {% if not value_json.error and value_json.location %}
        {{ value_json.location | tojson }}
      {% else %}
        {}
      {% endif %}
    icon: mdi:crosshairs-gps

Based on my testing this stops the warning.

And the other sensors would have something like

- sensor:
    name: Active route destination
    object_id: tesla_active_route_destination
    unique_id: teslamate_1_active_route_destination
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: >
      {% if not value_json.error and value_json.destination %}
        {{ value_json.destination }}
      {% endif %}
    icon: mdi:map-marker

- sensor:
    name: Active route energy at arrival
    object_id: tesla_active_route_energy_at_arrival
    unique_id: teslamate_1_active_route_energy_at_arrival
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: >
      {% if not value_json.error and value_json.energy_at_arrival %}
        {{ value_json.energy_at_arrival }}
      {% endif %}
    unit_of_measurement: "%"
    icon: mdi:battery-80

- sensor:
    name: Active route distance to arrival (mi)
    object_id: tesla_active_route_distance_to_arrival_mi
    unique_id: teslamate_1_active_route_distance_to_arrival_mi
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: >
      {% if not value_json.error and value_json.miles_to_arrival %}
        {{ value_json.miles_to_arrival }}
      {% endif %}
    unit_of_measurement: mi
    icon: mdi:map-marker-distance

- sensor:
    name: Active route minutes to arrival
    object_id: tesla_active_route_minutes_to_arrival
    unique_id: teslamate_1_active_route_minutes_to_arrival
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: >
      {% if not value_json.error and value_json.minutes_to_arrival %}
        {{ value_json.minutes_to_arrival }}
      {% endif %}
    unit_of_measurement: min
    icon: mdi:clock-outline

- sensor:
    name: Active route traffic minutes delay
    object_id: tesla_active_route_traffic_minutes_delay
    unique_id: teslamate_1_active_route_traffic_minutes_delay
    availability: *teslamate_active_route_availability
    device: *teslamate_device_info
    state_topic: "teslamate/cars/1/active_route"
    value_template: >
      {% if not value_json.error and value_json.traffic_minutes_delay %}
        {{ value_json.traffic_minutes_delay }}
      {% endif %}
    unit_of_measurement: min
    icon: mdi:clock-alert-outline
longzheng commented 20 hours ago

While we're on this topic I've also seen other actual errors reported by Home Assistant related to the Teslamate sensors

TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_tpms_fl') | float * 14.50377) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_tpms_fl') | float * 14.50377) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_tpms_pressure_fl_psi'
TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_tpms_fr') | float * 14.50377) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_tpms_fr') | float * 14.50377) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_tpms_pressure_fr_psi'
TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_tpms_rl') | float * 14.50377) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_tpms_rl') | float * 14.50377) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_tpms_pressure_rl_psi'
TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_tpms_rr') | float * 14.50377) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_tpms_rr') | float * 14.50377) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_tpms_pressure_rr_psi'
TemplateError('ValueError: Template error: float got invalid input 'unavailable' when rendering template '{{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}' but no default was specified') while processing template 'Template<template=({{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.tesla_active_route_distance_to_arrival_km'

I believe these are related to the fact that it's trying to convert the sensor values from one unit to another (e.g. kilometre to miles) when the MQTT sensors have no state/unavailable.

I wonder if we should have some similar availability_template and conditional value_template

    tesla_ideal_battery_range_mi:
      friendly_name: Ideal Range (mi)
      unit_of_measurement: mi
      icon_template: mdi:gauge
      availability_template: "{{ has_value('sensor.tesla_ideal_battery_range_km') }}"
      value_template: >
        {% if has_value('sensor.tesla_ideal_battery_range_km') %}
          {{ (states('sensor.tesla_ideal_battery_range_km') | float / 1.609344) | round(2) }}
        {% endif %}
JakobLichterfeld commented 18 hours ago

I think #3923 is more relevant to this issue since that's where I defined/added the Home Assistant sensors.

Yeah you are right.

I think an alternative is to define a conditional json_attributes_template like

Based on my testing this stops the warning.

Perfect.

@brianmay What do you think? Imo it is sufficient to handle it on Home Assistant side, only updating our docs.

JakobLichterfeld commented 18 hours ago

I believe these are related to the fact that it's trying to convert the sensor values from one unit to another (e.g. kilometre to miles) when the MQTT sensors have no state/unavailable.

I assume this is same reason, if car is asleep the Tire Pressure values are unavailable

longzheng commented 10 hours ago

I'll test a bit more and open a PR for this.

brianmay commented 8 hours ago

I think that solution needs expanding on:

Oct 08 09:00:56 iot2 homeassistant[118534]: homeassistant.exceptions.TemplateError: ValueError: Template error: float got invalid input 'unavailable' when rendering template '{% if has_value('sensor.tesla_ideal_battery_range_km') %}
Oct 08 09:00:56 iot2 homeassistant[118534]:   {{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}
Oct 08 09:00:56 iot2 homeassistant[118534]: {% endif %}' but no default was specified

Guessing this means all the sensor values need to have an else clause.

I think updating the docs will be sufficient for now. Once some of these other issues are resolved I might look at auto discovery a bit more.

longzheng commented 8 hours ago

I think that solution needs expanding on:


Oct 08 09:00:56 iot2 homeassistant[118534]: homeassistant.exceptions.TemplateError: ValueError: Template error: float got invalid input 'unavailable' when rendering template '{% if has_value('sensor.tesla_ideal_battery_range_km') %}

Oct 08 09:00:56 iot2 homeassistant[118534]:   {{ (states('sensor.tesla_active_route_distance_to_arrival_mi') | float * 1.609344) | round(2) }}

Oct 08 09:00:56 iot2 homeassistant[118534]: {% endif %}' but no default was specified

Guessing this means all the sensor values need to have an else clause.

Not sure if a typo but it looks like the tesla_ideal_battery_range_km got mixed up with tesla_active_route_distance_to_arrival_mi

brianmay commented 8 hours ago

Good catch.

Now getting this class of errors for all sensors:

Oct 08 09:15:50 iot2 homeassistant[119298]: ValueError: Sensor sensor.tesla_est_battery_range_mi has device class 'None', state class 'None' unit 'mi' and suggested precision 'None' thus indicating it has a numeric value; however, it has the non-numeric value: '' (<class 'str'>)