Need help with sensor templates

All these do is tell you if the yaml is valid. They might also look at the schema and see if it matches, I forget. However they do not look at the Jinja templates in fields and see if those are valid, only the config check in dev tools does that.

And your templates are not valid.

This isnt a valid template. {{% isn’t a valid symbol in Jinja. If a template does not result in output you surround it in {% %}. If it does you surround it in {{ }}. {{% is neither and is just a syntax error. Same with that closing }} you threw on at the bottom.

In dev tools there’s a template tab. Test your templates there. If they work you’ll see a result, if not you’ll see an error and a reason. In addition I would suggest reading this and this as it explains how it works and is chock full of examples

Okay, I don’t know what Jinja is. I started with the example provided in the blog post, and I’m presuming this is valid configuration. It has the {% openings and closings, and dev tools accepts it. I’m really struggling to understand what the difference is between the two. I understand the duplicate mapping for template, and I can’t use that again, but shouldn’t I just be able to remove that and keep adding sensors? Why is it valid alone, but not when I try and group sensors together?

I have looked over those two links, but I’m still not understanding the subtle differences. I’m not being lazy and trying to get someone else to fix my problem. I’ve been working on this for the past day, and trying to get it to work, but it’s not making sense to me.

Okay, I’m getting much closer. The Dev Tools Template tester is giving me positive results.

sensor:
  - platform: tank_utility
    email: !secret tank_username
    password: !secret tank_password
    devices:
      - "0022001b3638383015473830"

  - platform: template
    sensors:
      nextsunrise:
        friendly_name: "Next Sunrise"
        value_template: >
          {{ as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom(' %I:%M %p') | replace(" 0", "") }}
        icon_template: mdi:weather-sunset-up
      nextsunset:
        friendly_name: "Next Sunset"
        value_template: >
          {{ as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom(' %I:%M %p') | replace(" 0", "") }}
        icon_template: mdi:weather-sunset-down
      dryer:
        state: >
          {% if states("sensor.dryer_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.dryer_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Drying
          {% endif %}
        icon: >
          {% if states("sensor.dryer_switch_0_power") == "off"  %}
          mdi:tumble-dryer-alert
          {% elif states("sensor.dryer_switch_0_power")|float <= 2  %}
          mdi:tumble-dryer-off
          {% else %}
          mdi:tumble-dryer
          {% endif %}
      washing_machine:
        state: >
          {% if states("sensor.washer_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.washer_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Drying
          {% endif %}
        icon: >
          {% if states("sensor.washer_switch_0_power") == "off"  %}
          mdi:tumble-dryer-alert
          {% elif states("sensor.washer_switch_0_power")|float <= 2  %}
          mdi:tumble-dryer-off
          {% else %}
          mdi:tumble-dryer
          {% endif %}
      dishwasher:
        state: >
          {% if states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Washing
          {% endif %}
        icon: >
          {% if states("sensor.shelly_dishwasher_switch_0_power") == "off"  %}
          mdi:dishwasher-alert
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2  %}
          mdi:dishwasher-off
          {% else %}
          mdi:dishwasher
          {% endif %}

Result type: string
sensor:
  - platform: tank_utility
    email: !secret tank_username
    password: !secret tank_password
    devices:
      - "0022001b3638383015473830"

  - platform: template
    sensors:
      nextsunrise:
        friendly_name: "Next Sunrise"
        value_template: >
          7:26 AM
        icon_template: mdi:weather-sunset-up
      nextsunset:
        friendly_name: "Next Sunset"
        value_template: >
          4:57 PM
        icon_template: mdi:weather-sunset-down
      dryer:
        state: >
          
            Off
          
        icon: >
          
          mdi:tumble-dryer-off
          
      washing_machine:
        state: >
          
            Off
          
        icon: >
          
          mdi:tumble-dryer-off
          
      dishwasher:
        state: >
          
            Off
          
        icon: >
          
          mdi:dishwasher-off

Again, File Editor is giving me a green check (valid yaml).

When I go to check configuration, I receive a configuration invalid error that’s not extremely helpful.

Invalid config for [sensor.template]: [state] is an invalid option for [sensor.template]. Check: sensor.template->sensors->dryer->state. (See ?, line ?).

So I think I’m getting there, but even though the template checker says it’s fine, an returns the results I’m looking for, config checker doesn’t like “state” as an option for sensor templates.

Finally figured it out. Simple sensors seem to make more sense, but when you are doing multiple sensors, it really does get confusing. I guess it’ll make more sense as I progress.

sensor:
  - platform: tank_utility
    email: !secret tank_username
    password: !secret tank_password
    devices:
      - "0022001b3638383015473830"

  - platform: template
    sensors:
      nextsunrise:
        friendly_name: "Next Sunrise"
        value_template: >
          {{ as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom(' %I:%M %p') | replace(" 0", "") }}
        icon_template: mdi:weather-sunset-up
      nextsunset:
        friendly_name: "Next Sunset"
        value_template: >
          {{ as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom(' %I:%M %p') | replace(" 0", "") }}
        icon_template: mdi:weather-sunset-down
      dryer:
        friendly_name: "Dryer"
        value_template: >
          {% if states("sensor.dryer_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.dryer_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Drying
          {% endif %}
        icon_template: >
          {% if states("sensor.dryer_switch_0_power") == "off"  %}
          mdi:tumble-dryer-alert
          {% elif states("sensor.dryer_switch_0_power")|float <= 2  %}
          mdi:tumble-dryer-off
          {% else %}
          mdi:tumble-dryer
          {% endif %}
      washing_machine:
        friendly_name: "Washing Machine"
        value_template: >
          {% if states("sensor.washer_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.washer_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Washing
          {% endif %}
        icon_template: >
          {% if states("sensor.washer_switch_0_power") == "off"  %}
          mdi:washing-machine-alert
          {% elif states("sensor.washer_switch_0_power")|float <= 2  %}
          mdi:washing-machine-off
          {% else %}
          mdi:washing-machine
          {% endif %}
      dishwasher:
        friendly_name: "Dishwasher"
        value_template: >
          {% if states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
            Standby
          {% else %}
            Washing
          {% endif %}
        icon_template: >
          {% if states("sensor.shelly_dishwasher_switch_0_power") == "off"  %}
          mdi:dishwasher-alert
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2  %}
          mdi:dishwasher-off
          {% else %}
          mdi:dishwasher
          {% endif %}

You should learn the new template sensor format. The legacy template sensor format you are using does not support new features.

Tom,
I’m struggling learning any format :slight_smile:

Seriously, if there is a better way to do it, I’m all for it. I’m not a coder. I’ve been on HA for 4 months now after being on the Vera platform for 7 years, where the only coding I did was the logic in Reactor, which was pretty straight forward.

I’ve been using what’s out there, and the blog/youtube (link at the top) that I based this Shelly integration was done this year, so I wasn’t aware this was a legacy format. Is there a good tutorial on how to transfer the code from legacy to the current format?

I still want to enhance what I have (at least for the dishwasher sensor), so I can make an If then statement for the value to change if the power state is in a certain range, after it was in another range for X amount of time, to indicate it’s in the drying cycle. First I needed HA to stop screaming at the code I was working with.

My basic thought for the drying cycle, based on the power readings from my last run of the dishwasher (not code correct, just logic)

If sensor.shelly_dishwasher_switch_0_power > 5 W and < 6 W for > 5 minutes
and then
If sensor.shelly_dishwasher_switch_0_power > 545 W and < 840 W

Then state (dishwasher) is Drying

The less than 2 W is still valid for cycle complete.

I’m not sure if I can do an if then condition in the current value template or not. I was looking at this thread from last year, which suggested using a numeric state trigger for a similar purpose, but I can’t figure out how to set the sensor state as an action.

I guess that answers my question from before. File editor is just confirming it’s valid yaml, nothing else. Not looking at the schema or your templates.

So everything starts from configuration.yaml. it’s giving you directions from there. It says start from there then go to the template sensors (so go find the ones with platform: template under sensor, then to field sensors, then to the field dryer and finally to the field state. That last field is wrong.

The reason it’s wrong is because as Tom notes you’re trying to use the newer fields like state in the legacy config format.

We know it’s legacy for reference because the config starts with this:

sensor:
- platform: template
  sensors:
    dryer:
      ...

The current config for the template integration starts like this:

template:
  - sensor:
      - name: dryer
         ...

If you look at the examples in the doc you can see how it looks now.

You can’t. Sensors are created by integrations and their state is managed by that integration. You cannot set the state of a sensor in a script or automation.

If you want an entity with a state that isn’t set by an integration and is set by you in the UI or in automations/scripts then make an input helper. In this case the helper you would want to add is an input number. Clicking that link will initiate the process of making one from the UI.

Although it is worthwhile to spend some time figuring out template entities. They are quite powerful and can vastly simplify your automation logic. Instead of having many helpers and multistep automations to manage their state you just have a template entities that take care of themselves

Okay, I see what you’re saying. So it’s the original sensor: tag at the beginning of all of this for my sensors that is setting everything else up in the legacy format, so when I was trying to integrate the code from the blog, it was’t working. Good grief! :smiley: Had that original sensor been out of the picture, I wouldn’t be having an issue with the code from the blog. That’s a hard lesson.

The code in that sensor is straight from the document pages for the Tank Utility integration. I guess it hasn’t been updated in some time.

Though a triggered template sensor comes close.

Wait hold on, lets not blend things. It is currently considered legacy for an integration to put its config under the type of entity (like sensor) as opposed to its integration key (like template). That being said, there are over 2000 integration in HA so not all have made this transition.

Template has. So putting this in your config:

sensor:
  - platform: template
    ...

Sets you on the legacy config format for that particular integration. Which is problematic because then you are missing out on newer features, unable to follow most of the examples in the doc, etc.

Tank Utility has not made that transition. This is still the correct and only way to configure the tank utility integration:

# Example configuration.yaml entry
sensor:
  - platform: tank_utility
    email: YOUR_EMAIL_ADDRESS
    password: YOUR_PASSWORD
    devices:
      - "000000000000000000000000"

Maybe I misunderstood but it sounded like you were planning to change the tank utility config too by this comment:

The doc is up to date for both of these integrations. They are just configured a bit differently because Template was given a major update relatively recently to leverage the current best practices (and add a whole bunch of new features).

Not yet. I just got it working without throwing any errors.

My understanding of what you were saying is that the legacy config format is incompatible with the new template config, and it had to be one or other other. Is this an over simplification or incorrect? Is this why I when I originally put the newly formatted sensors from the blog post, it passed the config checker and relayed correct values, but the file editor and Studio Code Server gave me fits?

1 Like

For the dryer, if you give me a list of powers and times above/below/between the power level(s) I may be able to give you an example of a triggered template sensor or template sensor. e.g.

power < 1W for 1 minute = off
2W < power < 10W for 30 seconds = standby
power > 10W = drying.

Correct. Sorry I think I misunderstood. I went to the tank utility documentation and didn’t see any mention of template sensors. So I thought you were going to change how you configured the tank utility sensor.

Sounds like you found a blog post that talked about both together and the template part was out of date. That makes more sense.

This is the screen shot I took from the History last night. Essentially, the dishwasher goes into a hold mode at 1:10 am @ 5.1 W for 6 minutes. The 5.1 W for 6 minutes is unique from what I can tell from the graph. It then ramps up to 831.5 W briefly, then tapers off and stays around 640 W. It pulses 7 times in this manner, going into a hold mode around 5.3 W for 3 minutes at a time, then repeating. It ends @ 1.8 W.

The range of the heat is also unique. Pretty much all of the other power readings are higher (900W +), or much lower (150 W) when not in a hold mode. I found one other very brief instance where power dropped to 4.9W, but not for a significant period of time.

I think my best bet for a “drying” state would be a range between 550W and 840W, marking the start, and the under 2 W completing the cycle.

I was playing with this code, but still getting there. Obviously still in the old format, but hopefully the elif logic stands in the new format.

        value_template: >
          {% if states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
            Standby
          **{% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 545 and states("sensor.shelly_dishwasher_switch_0_power")|float => 840 %}**  
            Drying
          {% else %}
            Washing
          {% endif %}

edit: the ** around the second elif state was supposed to be bold. Doesn’t look like the forum editor liked that. That line is the one I’m currently working on.

No, it was just trying to get them all to cooperate in my yaml file nicely. The sensors are unrelated, just different sensors in my home. I think you can see how it’s confusing to a relative noob when there are two different formats.

It’s very easy to convert that to the new format:

configuration.yaml

template:
  - sensor:
      - name: "Dryer"
        state: >
          {% if states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
            Off
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
            Standby
          {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 545 and states("sensor.shelly_dishwasher_switch_0_power")|float => 840 %}
            Drying
          {% else %}
            Washing
          {% endif %}
        icon: >
          {% if states("sensor.dryer_switch_0_power") == "off"  %}
            mdi:tumble-dryer-alert
          {% elif states("sensor.dryer_switch_0_power")|float <= 2  %}
            mdi:tumble-dryer-off
          {% else %}
            mdi:tumble-dryer
          {% endif %}

      - name: "Some other template sensor"
        state: etc...

That worked, with the exception of my "and on the elif state…

TemplateSyntaxError: expected token 'end of statement block', got '='

I’m going to have to play with that some more.

Need a little more advise. The Dryer state is flapping because of the idle period between the pulses. Currently the idle phases are being identified as Washing phases.

  - name: "Dishwasher"
    state: >
      {% if states("sensor.shelly_dishwasher_switch_0_power")|float >= 550 and states("sensor.shelly_dishwasher_switch_0_power")|float <= 840 %}
        Drying
      {% elif states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
        Off
      {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
        Standby
      {% else %}
        Washing
      {% endif %}

I’d like for the Drying phase to be identified for that whole period. Is there a way to identify the idle period as a follow up to the range condition I have in the drying “if” line? In other words, The first drying phase has to happen first between a and b, then a idle phase between c and d, and of course the repeat? I’ve looked at the history for 3 nights, and each night this pulsing has happened 7 times.
The end of the drying phase is always below 2 W. The idle phases are between 3 and 5 W.

I’m thinking maybe some sort of counter that starts at 0 at the beginning of the whole washing cycle, and once the dyer phase starts, the counter advances, or perhaps a T/F boolean changes from false to true, so the idle phase could be an OR as part of the Drying phase.

I think I have a solution, but I’ll know for sure tonight after the washing machine runs.

I created an input boolean called “drying”. It’s simply off/on or F/T or 0/1.

I then created two automations.

Drying Cycle on:

alias: drying cycle on
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.shelly_dishwasher_switch_0_power
    above: 2
condition:
  - condition: or
    conditions:
      - condition: numeric_state
        entity_id: sensor.shelly_dishwasher_switch_0_power
        above: 550
        below: 840
      - condition: and
        conditions:
          - condition: state
            entity_id: input_boolean.drying
            state: "on"
            for:
              hours: 0
              minutes: 1
              seconds: 0
          - condition: numeric_state
            entity_id: sensor.shelly_dishwasher_switch_0_power
            above: 3
            below: 6
action:
  - condition: state
    entity_id: input_boolean.drying
    state: "on"
mode: single

And Drying Cycle Off

alias: drying cycle off
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.shelly_dishwasher_switch_0_power
    below: 2
condition:
  - condition: and
    conditions:
      - condition: state
        entity_id: input_boolean.drying
        state: "on"
      - condition: numeric_state
        entity_id: sensor.shelly_dishwasher_switch_0_power
        below: 2
        above: 0
action:
  - condition: state
    entity_id: input_boolean.drying
    state: "off"
mode: single

This drying cycle automation incorporates the more complex power measurements, including some and conditions, and self refences the binary boolean state to see if it’s on, and then if the idle phase power requirements are met, it keeps the binary boolean in the on state.

The off automation checks to see if the binary boolean is on, and then the power goes below 2 W, and resets the binary boolean to off. This way, when the next load is run, it’s not starting in the “on” binary state.

I then changed my original sensor state to reference the state of input boolean, and make the state of the Dishwasher sensor as Drying. The other elif statements remain the same.

  - name: "Dishwasher"
    state: >
      {% if states("input_boolean.drying") == "on" %}
        Drying
      {% elif states("sensor.shelly_dishwasher_switch_0_power")|float == 0  %}
        Off
      {% elif states("sensor.shelly_dishwasher_switch_0_power")|float <= 2 %}
        Standby
      {% else %}
        Washing
      {% endif %}  

I believe this should work, but if anyone sees anything glaring in my logic, please let me know.

1 Like

Out of curiosity, what’s the brand of dishwasher? Its power consumption graph is eerily similar to my dishwasher.