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 %}
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
It compiles ok for me, with or without. It’s the missing brackets and extra semi colon that would have made it fail.
I got the Lambda to compile fine (after a full hour of debugging syntax) and display on the LCD the text wind direction, converted inside ESPhome.
Values come from the internal wind direction sensor (which in turn comes from HA via WU). North required two ‘if’ conditions to handle wrapping past 0 degrees.
Just did four cardinal points for a test, now need to expand the else if’s to a full sixteen…
Any suggestions to streamline it welcome.
text_sensor:
- platform: template
id: internal_winddir_conversion
lambda: |-
if ((id(wupws_wind_dir).state >= 0) and (id(wupws_wind_dir).state <= 11)) {
return {"North"};}
else if ((id(wupws_wind_dir).state >= 12) and (id(wupws_wind_dir).state <= 33)) {
return {"N-N-E"};}
else if ((id(wupws_wind_dir).state >= 34) and (id(wupws_wind_dir).state <= 56)) {
return {"N-E"};}
else if ((id(wupws_wind_dir).state >= 57) and (id(wupws_wind_dir).state <= 78)) {
return {"E-N-E"};}
else if ((id(wupws_wind_dir).state >= 79) and (id(wupws_wind_dir).state <= 101)) {
return {"East"};}
else if ((id(wupws_wind_dir).state >= 102) and (id(wupws_wind_dir).state <= 123)) {
return {"E-S-E"};}
else if ((id(wupws_wind_dir).state >= 124) and (id(wupws_wind_dir).state <= 146)) {
return {"S-E"};}
else if ((id(wupws_wind_dir).state >= 147) and (id(wupws_wind_dir).state <= 168)) {
return {"S-S-E"};}
else if ((id(wupws_wind_dir).state >= 169) and (id(wupws_wind_dir).state <= 191)) {
return {"South"};}
else if ((id(wupws_wind_dir).state >= 192) and (id(wupws_wind_dir).state <= 213)) {
return {"S-S-W"};}
else if ((id(wupws_wind_dir).state >= 214) and (id(wupws_wind_dir).state <= 236)) {
return {"S-W"};}
else if ((id(wupws_wind_dir).state >= 237) and (id(wupws_wind_dir).state <= 258)) {
return {"W-S-W"};}
else if ((id(wupws_wind_dir).state >= 259) and (id(wupws_wind_dir).state <= 281)) {
return {"West"};}
else if ((id(wupws_wind_dir).state >= 282) and (id(wupws_wind_dir).state <= 303)) {
return {"W-N-W"};}
else if ((id(wupws_wind_dir).state >= 304) and (id(wupws_wind_dir).state <= 326)) {
return {"N-W"};}
else if ((id(wupws_wind_dir).state >= 327) and (id(wupws_wind_dir).state <= 348)) {
return {"N-N-W"};}
else if ((id(wupws_wind_dir).state >= 349) and (id(wupws_wind_dir).state <= 359)) {
return {"North"};}
else {
return {"invalid"};}
update_interval: 30s
The particular internal sensor (of many)
- platform: homeassistant
id: wupws_wind_dir
name: "Wind direction via WU-WH2900"
entity_id: sensor.wupws_winddir
internal: true
The LCD display code (just that line).
it.printf(0, 0, "Wind: %s", id(internal_winddir_conversion).state.c_str());
Glad its working, why are there some with and some without else
?
Yep that was an error, caused by my cut & pasting. Fixed it, still works fine…
You could replace both North if
with:
if ((id(wupws_wind_dir).state >= 0) and (id(wupws_wind_dir).state <= 11)) or
((id(wupws_wind_dir).state >= 349) and (id(wupws_wind_dir).state <= 359)) {
return {"North"};}
I also look at ESPHome devices as compartmentalized, meaning that if I need to translate the values from a connected device into human consumable values then I do so on the ESPHome device.
I want the device to look more like what it is supporting than have to glue things together on the Home Assistant side.
It’s also very hard for me get out of the habit of moving processing to the edge. So many years of performance optimizing large scaled services.
Cheers
hi,
i am trying to have two conditions for a sensor value below 1 . First program to check first condition and take action and then check other condition and take action. Irrespective of first condition result and action program must check the second condition and take action.
I am getting this error while compiling.
my code below.
sensor:
- platform: adc
pin: A0
name: "intercom_adc_value"
# unit_of_measurement: 'v'
update_interval: 100ms
filters:
- multiply: 3.3
on_value_range:
- above: 3
then:
- switch.turn_off: intercom_local_alerts
- switch.turn_off: intercom_remote_alerts
- below: 1.0
then:
if:
condition:
- switch.is_on: intercom_local_alerts_enable_disable
then:
- switch.turn_on: intercom_local_alerts
if:
condition:
- switch.is_on: intercom_remote_alerts_enable_disable
then:
- switch.turn_on: intercom_remote_alerts
hi Usman, I just saw your post, did you manage to get it running in the time between then and now.
I am by no means a programmer or esphome wizard but i did manage to get a temperature sensor to do different actions on different values. Maybe it will help you or somebody else along. btw i did use substitutions for most values and id’s so i can quickly multiply and only have to change names in the top bit of the yaml.
# Temperature sensor, met temperatuur activatie?
- platform: dallas
address: $dallas_id_1
name: "$temp_id"
accuracy_decimals: 1
id: $temp_id
on_value:
then:
- if:
condition:
and:
- lambda: return id($temp_id).state < $cold_temp;
- binary_sensor.is_on: esphome_fans_on_off
then:
- fan.turn_on:
id: $fan_id
speed: 15
- if:
condition:
and:
- lambda: return id($temp_id).state > $cold_temp;
- lambda: return id($temp_id).state < $low_temp;
- binary_sensor.is_on: esphome_fans_on_off
then:
- fan.turn_off:
id: $fan_id
- if:
condition:
and:
- lambda: return id($temp_id).state > $low_temp;
- lambda: return id($temp_id).state < $medium_temp;
- binary_sensor.is_on: esphome_fans_on_off
then:
- fan.turn_on:
id: $fan_id
speed: 44
- if:
condition:
and:
- lambda: return id($temp_id).state < $high_temp;
- lambda: return id($temp_id).state > $medium_temp;
- binary_sensor.is_on: esphome_fans_on_off
then:
- fan.turn_on:
id: $fan_id
speed: 50
- if:
condition:
and:
- lambda: return id($temp_id).state > $high_temp;
- binary_sensor.is_on: esphome_fans_on_off
then:
- fan.turn_on:
id: $fan_id
speed: 80
Back to the original question, is it possible to write nested if statements in YAML?
My use case is a service to water plants, where I want also to check if the pump is actually working:
services:
- service: water_plants
then:
if:
condition:
and:
- binary_sensor.is_off: esp32_garden_sensor_empty # tank empty sensor
- sensor.in_range:
id: ep32_garden_daily_flow # flow sensor (integration)
below: 4.0
then:
- switch.turn_on: esp32_garden_relay1 # pump supply
- delay: 10s
if:
condition:
- sensor.in_range:
id: ep32_garden_flow_rate # instant flow sensor
below: 0.2
then:
- switch.turn_off: esp32_garden_relay1
- homeassistant.service:
service: notify.mobile_app
data:
message: 'The pump is not pumping!'
- delay: 300s # time to water plants
- switch.turn_off: esp32_garden_relay1 # stop watering
This would be straightforward in C/C++ or any other languages, but I’m trying to stick to YAML as the whole house is automated with esphome & YAML.
I know I could do that with lambdas, but I would prefer to keep everything in YAML.
It looks like I just had to fix lists and indentations, this is working:
services:
- service: water_plants
then:
if:
condition:
and:
- binary_sensor.is_off: esp32_garden_sensor_empty # tank empty sensor
- sensor.in_range:
id: ep32_garden_daily_flow # flow sensor (integration)
below: 4.0
then:
- switch.turn_on: esp32_garden_relay1 # pump supply
- delay: 10s
- if:
condition:
- sensor.in_range:
id: ep32_garden_flow_rate # instant flow sensor
below: 0.2
then:
- switch.turn_off: esp32_garden_relay1
- homeassistant.service:
service: notify.mobile_app
data:
message: 'The pump is not pumping!'
- delay: 300s # time to water plants
- switch.turn_off: esp32_garden_relay1 # stop watering
Someone has opened an issue about this: Switch Case Algorithm · Issue #824 · esphome/feature-requests · GitHub
Maybe you all want to join and therefore show the developers that this feature is a interesting one?