Template sensor will fail in certain scenarios

Dear friends, I am new to HA and programming overall, but as I believe is the case for most, IA is a good helper.
Context: I have a bidirectional power meter, but that meter will not separately report incoming and exporting power. This is signaled using the 3rd digit of current measurement.
I have prepared a code that will isolate incoming and exporting power, but you will see that it will fail in certain circumstances, despite current signal being present and stable.
Can you help me pinpointing what is the cause and solution? Thanks in advance.

template:
  - sensor:
      - name: "PotĂȘncia importada"
        unique_id: "potencia_importada"
        state: >
          {% set valor_original = states('sensor.medidor_bidirecional_corrente_da_fase_a') | float %}
          {% set parte_decimal = (valor_original * 1000) | int % 10 %}
          {% if parte_decimal == 0 %}
            {{ states('sensor.medidor_bidirecional_potencia_da_fase_a') | float }}
          {% else %}
            0
          {% endif %}
        unit_of_measurement: "kW"
        device_class: power
  - sensor:
      - name: "PotĂȘncia exportada"
        unique_id: "potencia_exportada"
        state: >
          {% set valor_original = states('sensor.medidor_bidirecional_corrente_da_fase_a') | float %}
          {% set parte_decimal = (valor_original * 1000) | int % 10 %}
          {% if parte_decimal == 1 %}
            {{ states('sensor.medidor_bidirecional_potencia_da_fase_a') | float }}
          {% else %}
            0
          {% endif %}
        unit_of_measurement: "kW"
        device_class: power

Hello marcoshenz,

just looking at the surface, my guess would be that sometimes it finds unknown or unavailable. That would have to be screened out. Perhaps adding a (0) to your float might help or whatever value you like there. Perhaps you need to test the variables to make sure they are numeric before doing math on them. Not sure what would work best, you would have to try stuff.

It doesn’t appear to be failing, it is going to zero, presumably because the third decimal place of the current sensor is not zero.

Why don’t you zoom into a time when the template sensor drops to zero and see what the value is of the current sensor at that exact time?

Dear @Sir_Goodenough and @mekaneck, I have taken your comments in consideration and have the following response:
1 - I could not find deviations for the value from the current sensor in the third decimal place. I have observed the dashboard in critical moments, in History graph and downloaded data (csv).
2 - I could not understand what would be “adding a (0) to your float”. If you can further explain, I would be thankful.
3 - I have added verification steps to the variables, but there was no improvement to the main issue. If the sensor becomes unavailable, there is a small chunk of data missing and power is not updated, which is good. You can see the new code below.

template:
  - sensor:
      - name: "PotĂȘncia importada" # User-friendly name for the sensor (original name)
        unique_id: "potencia_importada" # Unique identifier for the sensor (original ID)
        state: >
          {# Define sensor IDs for easier reference and readability #}
          {% set current_sensor_id = 'sensor.medidor_bidirecional_corrente_da_fase_a' %}
          {% set power_sensor_id = 'sensor.medidor_bidirecional_potencia_da_fase_a' %}

          {# Attempt to get the current sensor's state and convert it to a float. #}
          {# Use default=0.0 so valor_corrente always has a numeric value, even if input is invalid. #}
          {% set valor_corrente = states(current_sensor_id) | float(default=0.0) %}

          {# Calculate the 'decimal part' (the third decimal digit). #}
          {# If valor_corrente is 0.0 (due to error or actual reading), parte_decimal will also be 0. #}
          {% set parte_decimal = (valor_corrente * 1000) | int % 10 %}

          {# First, check if the current sensor is valid (not none, is a number, and greater than 0). #}
          {# This prevents '0' from an unavailable/unknown sensor state from incorrectly triggering the condition. #}
          {% if states(current_sensor_id) is not none and states(current_sensor_id) | is_number and valor_corrente > 0 %}
            {% if parte_decimal == 0 %} # Condition: if the third decimal digit of current is 0
              {# If the condition is met, attempt to get the power sensor's value. #}
              {# Ensure the power sensor is also numeric and valid. #}
              {% if states(power_sensor_id) is not none and states(power_sensor_id) | is_number %}
                {{ states(power_sensor_id) | float(default=0.0) }}
              {% else %}
                {# If current is OK but power sensor is not valid, return 'unknown' to indicate a data source issue. #}
                {{ 'unknown' }} 
              {% endif %}
            {% else %}
              {# If the decimal part is not 0, return 0 (as per your original logic). #}
              0
            {% endif %}
          {% else %}
            {# If the current sensor is not valid (unavailable, unknown, or 0), #}
            {# return 'unknown' to indicate a problem with the current data source. #}
            {{ 'unknown' }} 
          {% endif %}
        unit_of_measurement: "kW" # Unit of measurement for the sensor
        device_class: power # Device class for proper display and functionality in Home Assistant

---

  - sensor:
      - name: "PotĂȘncia exportada" # User-friendly name for the sensor (original name)
        unique_id: "potencia_exportada" # Unique identifier for the sensor (original ID)
        state: >
          {# Define sensor IDs for easier reference and readability #}
          {% set current_sensor_id = 'sensor.medidor_bidirecional_corrente_da_fase_a' %}
          {% set power_sensor_id = 'sensor.medidor_bidirecional_potencia_da_fase_a' %} # Both power sensors use the same source

          {# Attempt to get the current sensor's state and convert it to a float. #}
          {% set valor_corrente = states(current_sensor_id) | float(default=0.0) %}

          {# Calculate the 'decimal part' (the third decimal digit). #}
          {% set parte_decimal = (valor_corrente * 1000) | int % 10 %}

          {# First, check if the current sensor is valid (not none, is a number, and greater than 0). #}
          {% if states(current_sensor_id) is not none and states(current_sensor_id) | is_number and valor_corrente > 0 %}
            {% if parte_decimal == 1 %} # Condition: if the third decimal digit of current is 1 (for Exported Power)
              {# If the condition is met, attempt to get the power sensor's value. #}
              {# Ensure the power sensor is also numeric and valid. #}
              {% if states(power_sensor_id) is not none and states(power_sensor_id) | is_number %}
                {{ states(power_sensor_id) | float(default=0.0) }}
              {% else %}
                {# If current is OK but power sensor is not valid, return 'unknown' to indicate a data source issue. #}
                {{ 'unknown' }} 
              {% endif %}
            {% else %}
              {# If the decimal part is not 1, return 0 (as per your original logic). #}
              0
            {% endif %}
          {% else %}
            {# If the current sensor is not valid (unavailable, unknown, or 0), #}
            {# return 'unknown' to indicate a problem with the current data source. #}
            {{ 'unknown' }} 
          {% endif %}
        unit_of_measurement: "kW" # Unit of measurement for the sensor
        device_class: power # Device class for proper display and functionality in Home Assistant

https://jinja.palletsprojects.com/en/latest/templates/#jinja-tests.float

You do it here in the verbose form


You should not return unknown to numerical sensors. That will cause the system to error. Instead you should use an availability template.

If you want the numerical sensor to go unknown, you should return None from your template.

1 Like