[SOLVED] State_attr problem in value_template

Hi folks,

Having spent 3 evenings unsuccessfully trying to debug this config issue, I’m hoping you can help.

I have a whole raft of power monitoring switches and have sensors set up for each attribute on each switch, all configured long hand and working correctly. I’ve not been trying to make a template that I can use for each so that I can massively reduce the size of the yaml file.

The sample below is a work in progress towards a being able to fully template, but it’s as far as I’ve got with a working config as a test sensor:

sensor:
  - platform: template
    sensors:
      atest_current:
        friendly_name_template: >-
            aTest Current
        value_template: >-
            {% set dev_name = 'switch.sonoff_pow1' %}
            {% set dev_attr = 'Current'%} 
            {%- if state_attr(dev_name, dev_attr) != None %}
              {{ state_attr('switch.sonoff_pow1', dev_attr) }}        
            {% else %}
              {{ 99 | float }}
            {%- endif %}
        unit_of_measurement: 'Amps'

The sample above works and sets the sensor state correctly. The final step I need to complete is to substitute the final string value on the {{ state_attr('switch.sonoff_pow1', dev_attr) }} call, replacing it with the dev_name parameter as on the preceding {%- if state_attr(dev_name, dev_attr) != None %} statement.

The config with that change in place is shown below, however the change appears to cause the {% if } statement to start return false as the sensor starts picking up the dummy ‘99’ value.

sensor:
  - platform: template
    sensors:
      atest_current:
        friendly_name_template: >-
            aTest Current
        value_template: >-
            {% set dev_name = 'switch.sonoff_pow1' %}
            {% set dev_attr = 'Current'%} 
            {%- if state_attr(dev_name, dev_attr) != None %}
              {{ state_attr(dev_name, dev_attr) }}        
            {% else %}
              {{ 99 | float }}
            {%- endif %}
        unit_of_measurement: 'Amps'

I’m baffled why it’s not working as it’s based on the official example below:

Can you see what’s wrong?

EDIT: I should have stated originally that the last (broken) version of the config actually works in the Developers Tools Template editor.

Templating is not my strongest suit but something that stands out based on your stated goal is that you intend to re-use “dev_name” and “dev_attr” with other sensors to consolidate your templates.
Have you perhaps set “dev_name” and/or “dev_attr” already in another sensor template that may be conflicting with this one?

Can you explain how you intend to do that? Because the template you’ve presented appears to do the opposite; it seems needlessly wordy to me. Perhaps I’ve misunderstood what you’re trying to achieve.

This template produces the same result as the one above:

        value_template: >
            {% set x = state_attr('switch.sonoff_pow1', 'Current') %}
            {{ x if x != None else 99 }}        

The scope of variables created within a templated option is limited to that option. For example, the template above (for the value_template option) defines a variable called x. That variable is not accessible to other sensors, not even to other options within the same sensor.

1 Like

Thanks for clarifying, I’m learning all the time.

I don’t quite understand the use of the variables either. I like to use filters to handle possible missing values, so I would just use this:

        value_template: "{{ state_attr('switch.sonoff_pow1', 'Current') | float(99.0) }}"
1 Like

Thank you all for alternative suggestions for reducing the number of lines of code and simplifying the template, I’ll give those a try tonight.

My original thoughts were to ultimately move the logic into an include file, hence coded only once and just set the parameters specific to each sensor before doing the include. The config above was just me trying to get the logic correct before moving it to the include. Another part of the exercise was to get a better understanding of templates and Jninja and on that respect, mission accomplished :slightly_smiling_face:

While debugging this I did try a similar line of code to that posted by @123, and setting x=state_attr(...) but using the substitutes rather than strings. This also worked until I made that final change to substitute the variable into the first parameter, so I’m suspecting there’s a weird bug lurking in how the state_attr is handling the first parameter, it’s definitely not having a problem with the second substitution.

I’ll have another look at this tonight.

Thanks guys.

Hey guys,

Thank you for all your advice and help. Mission accomplished.

Final config for one of the devices is shown below:

sensor:
# Sonoff POW 1 sensors
  - platform: template
    sensors:
      sonoff_pow1_current:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Current"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Current') | float(0.0) }}"
        unit_of_measurement: 'Amps'

      sonoff_pow1_power:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Current Power"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Power') | float(0.0) }}"
        unit_of_measurement: 'Watts'
        device_class: power

      sonoff_pow1_total_consumption:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Total Consumption"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Total') | float(0.0) }}"
        unit_of_measurement: 'kWh'
        device_class: power
        
      sonoff_pow1_voltage:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Voltage"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Voltage') | float(0.0) }}"
        unit_of_measurement: 'Volts'

      sonoff_pow1_today_consumption:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Today's Consumption"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Today') | float(0.0) }}"
        unit_of_measurement: 'kWh'
        device_class: power

      sonoff_pow1_yesterday_consumption:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Yesterday's Consumption"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Yesterday') | float(0.0) }}"
        unit_of_measurement: 'kWh'
        device_class: power

      sonoff_pow1_apparentpower:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Apparent Power"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'ApparentPower') | float(0.0) }}"
        unit_of_measurement: 'Watts'
        device_class: power

      sonoff_pow1_reactivepower:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Reactive Power"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'ReactivePower') | float(0.0) }}"
        unit_of_measurement: 'Watts'
        device_class: power

      sonoff_pow1_factor:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Factor"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Factor') | float(0.0) }}"

      sonoff_pow1_period:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Period"
        value_template: "{{ state_attr('switch.sonoff_pow1', 'Period') | float(0.0) }}"
        unit_of_measurement: 'Hours'

      sonoff_pow1_cost_today:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Cost Today"
        value_template: "{{ (state_attr('switch.sonoff_pow1', 'Today') | float(0) * (states('input_number.cost_per_kwh') | float)) | round / 100 }}"
        unit_of_measurement: '£'

      sonoff_pow1_cost_yesterday:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Cost Yesterday"
        value_template: "{{ (state_attr('switch.sonoff_pow1', 'Yesterday') | float(0) * (states('input_number.cost_per_kwh') | float)) | round / 100 }}"
        unit_of_measurement: '£'

      sonoff_pow1_total_cost:
        friendly_name_template: "{{ states.switch.sonoff_pow1.name}} Total Cost"
        value_template: "{{ (state_attr('switch.sonoff_pow1', 'Total') | float(0) * (states('input_number.cost_per_kwh') | float)) | round / 100 }}"
        unit_of_measurement: '£'

I’ve another 8 to refactor to the same implementation, so you can see why I was trying to get a condensed format.

I’ll try to check out that strange behaviour on the first parameter in my original solution out of curiosity.

1 Like

Been trying to solve my own issue with this, your fix worked thanks!

Hi @Geoff571. How did you manage to get value_template: “{{ state_attr(‘switch.sonoff_pow1’, ‘Today’) attribute or " Yesterday” from sonoff. On my Pow 2 is not available.

Hi @robert5, check in the device console (assuming you’re running Tasmota on it) and check for a line in the logs like the one below:

MQT: sonoff-pow1/stat/STATUS10 = {"StatusSNS":{"Time":"2021-02-18T18:07:14","ENERGY":{"TotalStartTime":"2019-01-06T19:14:38","Total":395.364,"Yesterday":0.624,"Today":0.305,"Power":55.4,"ApparentPower":69.9,"ReactivePower":42.7,"Factor":0.79,"Voltage":241,"Current":0.29}}}

If you’re seeing that then you should be able to pick it up.

I am not using tasmota only Alexx integration.

1 Like