Nested 'if' conditions in ESPhome action?

Thought you wanted this ?

Sorry @QbaF I answered @ashscott

Thank you. I’m still getting the ‘expected primary-expression before ‘>=’’ error on compile though.

You don’t need the !lambda, see here https://esphome.io/components/text_sensor/template.html#template-text-sensor

I would note that template sensors only update every 60s or whatever you specify. They aren’t automatically updated from the underlying sensor changes.

Strange it compiles fine for me.

I think it will be fine for a wind direction sensor though

Can you paste you whole config ?

Maybe try adding brackets

text_sensor:
  - platform: template
    name: "Wind Direction"
    lambda: !lambda |-
      if ((id(wind_direction).state)>=0.000 and (id(wind_direction).state)<0.250) {
        return {"N"};
      }
      if ((id(wind_direction).state)>=0.250 and (id(wind_direction).state)<0.500) {
        return {"NE"};
      }
      if ((id(wind_direction).state)>=0.500 and (id(wind_direction).state)<0.750) {
        return {"E"};
      }
      if ((id(wind_direction).state)>=0.750 and (id(wind_direction).state)<1.000) {
        return {"SE"};
      }
      if ((id(wind_direction).state)>=1.000 and (id(wind_direction).state)<1.250) {
        return {"S"};
      }
      if (id(wind_direction).state)>=1.250 and (id(wind_direction).state)<1.500) {
        return {"SW"};
      }
      if ((id(wind_direction).state)>=1.500 and (id(wind_direction).state)<1.750) {
        return {"W"};
      }
      if ((id(wind_direction).state)>=1.750 and (id(wind_direction).state)<=2.000) {
        return {"NW"};
      } else {
        return {"NaN"};
      }
    update_interval: 60s

Here’s what I currently have:

text_sensor:
  - platform: template
    name: "Wind Direction"
    lambda: !lambda |-
      if (id(wind_direction).state)>=0.000 and (id(wind_direction).state)<0.250; {
        return {"N"};}
      if (id(wind_direction).state)>=0.250 and (id(wind_direction).state)<0.500 {
        return {"NE"};
      if (id(wind_direction).state)>=0.500 and (id(wind_direction).state)<0.750 {
        return {"E"};
      if (id(wind_direction).state)>=0.750 and (id(wind_direction).state)<1.000 {
        return {"SE"};
      if (id(wind_direction).state)>=1.000 and (id(wind_direction).state)<1.250 {
        return {"S"};
      if (id(wind_direction).state)>=1.250 and (id(wind_direction).state)<1.500 {
        return {"SW"};
      if (id(wind_direction).state)>=1.500 and (id(wind_direction).state)<1.750 {
        return {"W"};
      if (id(wind_direction).state)>=1.750 and (id(wind_direction ).state)<=2.000 {
        return {"NW"};
      } else {
        return NaN;
      }
    update_interval: 60s

I agree, but I wanted to point it out since it works differently than a template sensor in gone assistant.

text_sensor:
  - platform: template
    name: "Wind Direction"
    lambda: !lambda |-
      if (id(wind_direction).state)>=0.000 and (id(wind_direction).state)<0.250 {
        return {"N"};}
      if (id(wind_direction).state)>=0.250 and (id(wind_direction).state)<0.500 {
        return {"NE"};}
      if (id(wind_direction).state)>=0.500 and (id(wind_direction).state)<0.750 {
        return {"E"};}
      if (id(wind_direction).state)>=0.750 and (id(wind_direction).state)<1.000 {
        return {"SE"};}
      if (id(wind_direction).state)>=1.000 and (id(wind_direction).state)<1.250 {
        return {"S"};}
      if (id(wind_direction).state)>=1.250 and (id(wind_direction).state)<1.500 {
        return {"SW"};}
      if (id(wind_direction).state)>=1.500 and (id(wind_direction).state)<1.750 {
        return {"W"};}
      if (id(wind_direction).state)>=1.750 and (id(wind_direction).state)<=2.000 {
        return {"NW"};
      } else {
        return {"NaN"};}
    update_interval: 60s

Extra semi-colon after 0.250 in first line and missing closing curly brackets ?

In the docs:

Possible return values for the lambda:

  • return {"STRING LITERAL"}; the new value for the sensor of type std::string .
    Has to be in brackets {} !

Why not report the wind direction to home assistant and convert to the desired text there?

Nick can you give me an example of that or something close ?
My own home station reports wind direction to HA via weather underground in integer degrees, and I’d like to convert that to 16 point compass rose directions also…

I have struggled with just this question a few times. Then I realized that I wanted some functionality to exist on the ESPHome device that did not rely on Home Assistant connection.

Example:

I have an LED ring that acts as a clock (Lambda Lighting Effect on addressable LED ring). Because ESP devices do not have a Real Time Clock (RTC) by default you have to define a network time resource. ESPHome supports Home Assistant and SNTP (Simple Network Time Protocol) I ended up using the SNTP method to avoid depending on Home Assistant.

Another more practical example is having a fail safe routine on my irrigation controller. Where if either of the valve controls has been on for more than 4 hours it will be automatically shutoff. I did not want to rely on Home Assistant to stop it after I had incident where this happened. Home Assistant was restarted at just the right time, what luck I have, and the automation to turn off the irrigation values did not run because the timer was reset on restart of Home Assistant.

So, it depends on what you are trying to accomplish… :slight_smile: Personally, I like the challenge of implementing automation routines on the ESPHome devices as a way of offsetting some load from Home Assistant. All be it, arguably a small load, but that is relative to the size of the Home Assistant installation.

Just my random morning pre-coffee thoughts. :slight_smile:

Similar here Tony, I like to have local fallback logic in some of my devices.
I’d prefer to have ESPhome convert degrees to cardials too (and print text to the 16x2 LCD), but if it’s not a convoluted twisted series of scripts and the like I’d be happy to use HA to start with…

I also take the stance that each device should be as self contained as possible. Home assistant should be the glue and handle inter device automation. But in this case I think it is a matter of taste, since it is purely a display issue. For automations that occur entirely within the device, there is a strong argument for keeping the logic self contained.

Given the new piece of info, I would softly suggest doing it in esphome if the LCD is also on this device. Then it will still display if, who am I kidding, when your home assistant server is down while you are fixing some breaking change issue.

This is the device. It’s effectively a weather station repeater display that sits on the wall in my bedroom, but it evolved to have a RGB HA system status LED and local temp/humidity sensor tacked on…

As I had no luck with the ESPhome compile errors I took your advice.

Here’s the solution:

- platform: template
  sensors:
    wind_direction:
      friendly_name: 'Wind direction'
      value_template: >-
        {% if states('sensor.wind_direction_north') | float >= 0.00 and states('sensor.wind_direction_north') | float <= 0.08 %}
          N
        {% elif states('sensor.wind_direction_north') | float >= 0.08 and states('sensor.wind_direction_north') | float <= 0.16 %}
          NE
        {% elif states('sensor.wind_direction_north') | float >= 0.16 and states('sensor.wind_direction_north') | float <= 0.24 %}
          E
        {% elif states('sensor.wind_direction_north') | float >= 0.24 and states('sensor.wind_direction_north') | float <= 0.32 %}
          SE
        {% elif states('sensor.wind_direction_north') | float >= 0.32 and states('sensor.wind_direction_north') | float <= 0.40 %}
          S
        {% elif states('sensor.wind_direction_north') | float >= 0.40 and states('sensor.wind_direction_north') | float <= 0.48 %}
          SW
        {% elif states('sensor.wind_direction_north') | float >= 0.48 and states('sensor.wind_direction_north') | float <= 0.56 %}
          W
        {% elif states('sensor.wind_direction_north') | float >= 0.56 and states('sensor.wind_direction_north') | float <= 0.64 %}
          NW
        {% endif %}
1 Like

Does that work ? you have overlaps. If the float is 0.08 it can be N or NE, need to make either the >= to just > or <= to just <, except the last one

- platform: template
  sensors:
    wind_direction:
      friendly_name: 'Wind direction'
      value_template: >-
        {% if states('sensor.wind_direction_north') | float >= 0.00 and states('sensor.wind_direction_north') | float < 0.08 %}
          N
        {% elif states('sensor.wind_direction_north') | float >= 0.08 and states('sensor.wind_direction_north') | float < 0.16 %}
          NE
        {% elif states('sensor.wind_direction_north') | float >= 0.16 and states('sensor.wind_direction_north') | float < 0.24 %}
          E
        {% elif states('sensor.wind_direction_north') | float >= 0.24 and states('sensor.wind_direction_north') | float < 0.32 %}
          SE
        {% elif states('sensor.wind_direction_north') | float >= 0.32 and states('sensor.wind_direction_north') | float < 0.40 %}
          S
        {% elif states('sensor.wind_direction_north') | float >= 0.40 and states('sensor.wind_direction_north') | float < 0.48 %}
          SW
        {% elif states('sensor.wind_direction_north') | float >= 0.48 and states('sensor.wind_direction_north') | float < 0.56 %}
          W
        {% elif states('sensor.wind_direction_north') | float >= 0.56 and states('sensor.wind_direction_north') | float <= 0.64 %}
          NW
        {% endif %}

Yes, it works, but not very clean like that and you are correct. I’ve changed it. That’s copy/paste for you!

The esphome code should be in the form

lambda: |-
  if (expression){statement}
  else if (expression){statement}
  else {statement}

Exactly like the example. I think it might only be valid code without the !lambda

1 Like