First observation - the code has been placed under the “sensor:” section. What happens when you place it under the “text_sensor:” section?
@bremby , Okay, I see what you’re doing now!
Your set this up under “sensor:” rather than “text_sensor”. In respect to your previous question, yes, dropping the troublesome line will work in that case. As a matter of fact, the line would have to be removed in order for the sensor to work.
I omitted that line and placed your code under the “sensor:” section of my code. In order for it to work in my setup, I changed “id(esp32_sprinkler_ctrlr)” to “id($devicename)”, which is the name of my device. Other than that, everything else was left alone. It works for me. Here’s the code I used;
# # Expose Progress Percent as a sensor.
- platform: template
id: progress_percent_valve
name: "Zone Progress"
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: $sensor_update_frequency
icon: "mdi:progress-clock"
lambda: |-
int valve_progress_percent = round(((id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0)) - id($devicename).time_remaining().value_or(0)) * 100 / id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0))));
return valve_progress_percent;
Were $devicename is the name of my device.
Nothing else jumps out at me. I’ll take a deeper look for you but won’t be able to do so until Monday afternoon or Tuesday,
@rcblackwell thank you so much for your patience and your support, I really appreciated the time you spent helping me. You are right, my mistake was the wrong placement of the sensor. Moving the configuration as text_sensor works as well as you described.
do you have any idea on how to “sum” the remaining time across all the valves? I would like to have the remaining time and the progress not for the single valve, but to measure the entire cycle
regards
@bremby , you’re welcome.
Not at this time. I’ve given it some thought though. There is a number of things to consider. How would total run time be calculated - is a single zone or are all zones being run? How would extended run times (Repeats) be handled? Should valve delay times be considered? And, possibly a couple of other things, yet unthought of.
for now I’m using this quick&dirty solution
I’m using an helper
then when the sprinkler start, there is an automation that does the math and set the value
{% set total = 0 %}
{% if states('switch.zone_1_enable') == 'on' %}
{% set total = total + (states('number.zone_1_duration')|int*60)%}
{% endif %}
{% if states('switch.zone_2_enable') == 'on' %}
{% set total = total + (states('number.zone_2_duration')|int*60)%}
{% endif %}
{% if states('switch.zone_3_enable') == 'on' %}
{% set total = total + (states('number.zone_3_duration')|int*60)%}
{% endif %}
{% if states('switch.zone_4_enable') == 'on' %}
{% set total = total + (states('number.zone_4_duration')|int*60)%}
{% endif %}
{% if states('switch.zone_5_enable') == 'on' %}
{% set total = total + (states('number.zone_5_duration')|int*60)%}
{% endif %}
{% if states('switch.zone_6_enable') == 'on' %}
{% set total = total + (states('number.zone_6_duration')|int*60)%}
{% endif %}
{% set total = total * (states('number.run_duration_multiplier')|int) %}
{{ total | timestamp_custom("%H:%M:%S",0)}}
next step, dynamically populate the list of the active zone and sum the corresponding values.
any idea is welcome
@rcblackwell I hope that your are going well, I’m trying to compile the code with ESPHome 2023.3.0 and I’m now stuck with this error, any ideas?
sprinkler-control.yaml:483:175:
error: ‘class esphome::sprinkler::Sprinkler’ has no member named ‘time_remaining’
This was a breaking change in sprinkler component v2. The item is now called time_remaining_active_valve
.
THANK YOU, I missed it. I will have a look to see if there are additional changes.
Thank you again
Hi @SebaVT
May I ask you to share a screenshot of your full Lovelace sprinkler/ irrigation dashboard and it’s code to get some inspiration?
Hey @olympia, I haven’t touched the code in a while and is still a work in progress with some bugs, but here IT is:
DISCLAIMER: I’m not a programmer so don’t expect a clean code. I learned how to code this while writing it.
Lovelace:
type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.sprinkler_controller_run
show_name: false
icon: mdi:play
styles:
card:
- width: 100px
- height: 80px
tap_action:
action: call-service
service: switch.turn_on
service_data:
entity_id: switch.sprinkler_controller_run
- type: custom:button-card
entity: switch.sprinkler_controller_pause
show_name: false
icon: mdi:pause
styles:
card:
- width: 100px
- height: 80px
tap_action:
action: call-service
service: switch.toggle
service_data:
entity_id: switch.sprinkler_controller_pause
- type: custom:button-card
entity: switch.sprinkler_controller_stop
show_name: false
icon: mdi:stop
styles:
card:
- width: 100px
- height: 80px
tap_action:
action: call-service
service: switch.turn_on
service_data:
entity_id: switch.sprinkler_controller_stop
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.run_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.sprinkler_controller_total_run_time_2
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 120px
- height: 40px
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.sprinkler_controller_previous_valve
show_name: false
icon: mdi:skip-previous
styles:
card:
- width: 154px
- height: 80px
tap_action:
action: call-service
service: switch.turn_on
service_data:
entity_id: switch.sprinkler_controller_previous_valve
- type: custom:button-card
entity: switch.sprinkler_controller_next_valve
show_name: false
icon: mdi:skip-next
styles:
card:
- width: 154px
- height: 80px
tap_action:
action: call-service
service: switch.turn_on
service_data:
entity_id: switch.sprinkler_controller_next_valve
- type: vertical-stack
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_1
show_name: false
icon: mdi:numeric-1-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_1
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_1_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_1_time_remaining_2
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- entity: number.zone_1_duration
type: custom:numberbox-card
border: false
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_2
show_name: false
icon: mdi:numeric-2-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_2
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_2_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_2_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- type: custom:numberbox-card
border: false
entity: number.zone_2_duration
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_3
show_name: false
icon: mdi:numeric-3-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_3
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_3_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_3_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- entity: number.zone_3_duration
type: custom:numberbox-card
border: false
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_4
show_name: false
icon: mdi:numeric-4-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_4
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_4_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_4_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- type: custom:numberbox-card
border: false
entity: number.zone_4_duration
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_5
show_name: false
icon: mdi:numeric-5-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_5
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_5_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_5_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- entity: number.zone_5_duration
type: custom:numberbox-card
border: false
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_6
show_name: false
icon: mdi:numeric-6-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_6
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_6_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_6_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- type: custom:numberbox-card
border: false
entity: number.zone_6_duration
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_7
show_name: false
icon: mdi:numeric-7-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_7
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_7_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_7_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- entity: number.zone_7_duration
type: custom:numberbox-card
border: false
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: horizontal-stack
cards:
- type: custom:button-card
entity: switch.enable_zone_8
show_name: false
icon: mdi:numeric-8-box-outline
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:button-card
entity: switch.zone_8
show_name: false
icon: mdi:sprinkler
size: 25px
styles:
card:
- width: 40px
- height: 40px
- type: custom:bar-card
height: 8px
entities:
- entity: sensor.zone_8_progress_percentage
positions:
icon: 'off'
indicator: 'off'
name: 'off'
value: 'off'
- type: custom:button-card
entity: sensor.zone_8_time_remaining
show_name: false
show_icon: false
show_state: true
styles:
card:
- width: 80px
- height: 40px
- type: custom:numberbox-card
border: false
entity: number.zone_8_duration
unit: time
name: false
speed: '200'
icon_plus: mdi:chevron-up
icon_minus: mdi:chevron-down
- type: entities
entities:
- entity: sensor.debug
- entity: sensor.lawn_sprinklers_status
- entity: switch.lawn_sprinklers
- entity: switch.lawn_sprinklers_auto_advance
- entity: switch.lawn_sprinklers_reverse
- entity: number.sprinkler_controller_multiplier
title: Controls
show_header_toggle: false
I have to separate the code in two because the forum won’t allow me to post it completely due its size.
ESPHome part 1:
esphome:
name: sprinkler-controller
platform: ESP32
board: esp32dev
on_boot:
priority: -100
then:
- sprinkler.set_multiplier:
id: lawn_sprinkler_ctrlr
multiplier: !lambda "return id(multiplier);"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 0
run_duration: !lambda "return id(z1_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 1
run_duration: !lambda "return id(z2_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 2
run_duration: !lambda "return id(z3_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 3
run_duration: !lambda "return id(z4_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 4
run_duration: !lambda "return id(z5_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 5
run_duration: !lambda "return id(z6_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 6
run_duration: !lambda "return id(z7_duration)* 60;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 7
run_duration: !lambda "return id(z8_duration)* 60;"
- text_sensor.template.publish:
id: lawn_sprinkler_ctrlr_status
state: "Idle"
preferences:
flash_write_interval: 0s
# Enable logging
logger:
# Enable Home Assistant API
api:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Sprinkler-Controller"
password: "jGIHokqBCBw1"
captive_portal:
globals:
- id: multiplier
type: float
restore_value: true
initial_value: '1'
- id: z1_duration
type: int
restore_value: true
initial_value: '15'
- id: z2_duration
type: int
restore_value: true
initial_value: '15'
- id: z3_duration
type: int
restore_value: true
initial_value: '15'
- id: z4_duration
type: int
restore_value: true
initial_value: '15'
- id: z5_duration
type: int
restore_value: true
initial_value: '15'
- id: z6_duration
type: int
restore_value: true
initial_value: '15'
- id: z7_duration
type: int
restore_value: true
initial_value: '15'
- id: z8_duration
type: int
restore_value: true
initial_value: '15'
- id: total_run_time
type: int
restore_value: false
initial_value: '0'
sprinkler:
- id: lawn_sprinkler_ctrlr
main_switch:
name: "Lawn Sprinklers"
auto_advance_switch: "Lawn Sprinklers Auto Advance"
reverse_switch: "Lawn Sprinklers Reverse"
valve_overlap: 1s
next_prev_ignore_disabled: True
valves:
- valve_switch: "Zone 1"
enable_switch: "Enable Zone 1"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw1
- valve_switch: "Zone 2"
enable_switch: "Enable Zone 2"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw2
- valve_switch: "Zone 3"
enable_switch: "Enable Zone 3"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw3
- valve_switch: "Zone 4"
enable_switch: "Enable Zone 4"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw4
- valve_switch: "Zone 5"
enable_switch: "Enable Zone 5"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw5
- valve_switch: "Zone 6"
enable_switch: "Enable Zone 6"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw6
- valve_switch: "Zone 7"
enable_switch: "Enable Zone 7"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw7
- valve_switch: "Zone 8"
enable_switch: "Enable Zone 8"
run_duration: 900s
valve_switch_id: lawn_sprinkler_valve_sw8
switch:
- platform: restart
name: "Reboot Sprinkler Controller"
- platform: gpio
id: lawn_sprinkler_valve_sw1
pin: 27
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw2
pin: 32
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw3
pin: 17
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw4
pin: 16
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw5
pin: 15
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw6
pin: 26
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw7
pin: 33
inverted: true
- platform: gpio
id: lawn_sprinkler_valve_sw8
pin: 14
inverted: true
- platform: template
id: lawn_sprinkler_ctrlr_run
name: "Sprinkler Controller Run"
optimistic: true
on_turn_on:
- text_sensor.template.publish:
id: lawn_sprinkler_ctrlr_status
state: "Running"
- sprinkler.resume_or_start_full_cycle: lawn_sprinkler_ctrlr
- switch.turn_off: lawn_sprinkler_ctrlr_pause
- platform: template
id: lawn_sprinkler_ctrlr_pause
name: "Sprinkler Controller Pause"
optimistic: true
turn_on_action:
- delay: 500ms
- lambda: |-
if(id(lawn_sprinkler_ctrlr_status).state != "Running")
{
id(lawn_sprinkler_ctrlr_pause).turn_off();
}
- lambda: |-
if(id(lawn_sprinkler_ctrlr_status).state == "Running")
{
id(lawn_sprinkler_ctrlr_status).publish_state("Paused");
id(lawn_sprinkler_ctrlr).pause();
}
on_turn_off:
lambda: |-
if(id(lawn_sprinkler_ctrlr_status).state == "Paused")
{
id(lawn_sprinkler_ctrlr_status).publish_state("Running");
id(lawn_sprinkler_ctrlr).resume();
}
- platform: template
id: lawn_sprinkler_ctrlr_stop
name: "Sprinkler Controller Stop"
turn_on_action:
- text_sensor.template.publish:
id: lawn_sprinkler_ctrlr_status
state: "Idle"
- sprinkler.resume: lawn_sprinkler_ctrlr
- delay: 25ms
- sprinkler.shutdown: lawn_sprinkler_ctrlr
- switch.turn_off: lawn_sprinkler_ctrlr_pause
- switch.turn_off: lawn_sprinkler_ctrlr_run
- platform: template
id: lawn_sprinkler_ctrlr_next_valve
name: "Sprinkler Controller Next Valve"
turn_on_action:
- sprinkler.next_valve: lawn_sprinkler_ctrlr
- delay: 25ms
- switch.turn_off: lawn_sprinkler_ctrlr_next_valve
- platform: template
id: lawn_sprinkler_ctrlr_previous_valve
name: "Sprinkler Controller Previous Valve"
turn_on_action:
- sprinkler.previous_valve: lawn_sprinkler_ctrlr
- delay: 25ms
- switch.turn_off: lawn_sprinkler_ctrlr_previous_valve
text_sensor:
- platform: template
id: lawn_sprinkler_ctrlr_status
name: "Lawn Sprinklers Status"
update_interval: 1s
- platform: template
id: zone_1_time_remaining
name: "Zone 1 Time Remaining"
- platform: template
id: zone_2_time_remaining
name: "Zone 2 Time Remaining"
- platform: template
id: zone_3_time_remaining
name: "Zone 3 Time Remaining"
- platform: template
id: zone_4_time_remaining
name: "Zone 4 Time Remaining"
- platform: template
id: zone_5_time_remaining
name: "Zone 5 Time Remaining"
- platform: template
id: zone_6_time_remaining
name: "Zone 6 Time Remaining"
- platform: template
id: zone_7_time_remaining
name: "Zone 7 Time Remaining"
- platform: template
id: zone_8_time_remaining
name: "Zone 8 Time Remaining"
- platform: template
id: debug
name: "Debug"
- platform: template
id: sprinkler_ctrlr_total_run_time
name: "Sprinkler Controller Total Run Time"
ESPHome Part 2:
sensor:
- platform: template
id: run_progress_percentage
name: "Run Progress Percentage"
update_interval: 1s
lambda: |-
int seconds = round(id(lawn_sprinkler_ctrlr).total_cycle_time_enabled_valves());
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(sprinkler_ctrlr_total_run_time).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
if (id(lawn_sprinkler_ctrlr).active_valve().has_value())
{
id(lawn_sprinkler_ctrlr_status).publish_state("Running");
}
else if(id(lawn_sprinkler_ctrlr).paused_valve().has_value())
{
id(lawn_sprinkler_ctrlr_status).publish_state("Paused");
}
else
{
id(lawn_sprinkler_ctrlr_status).publish_state("Idle");
id(lawn_sprinkler_ctrlr_pause).turn_off();
}
if(id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
return 0;
}
else
{
int persentage = (id(lawn_sprinkler_ctrlr).total_cycle_time_enabled_valves() - id(lawn_sprinkler_ctrlr).time_remaining_current_operation().value()) * 100 / id(lawn_sprinkler_ctrlr).total_cycle_time_enabled_valves();
if (persentage > 100)
{
return 0;
}
else
{
return (persentage);
}
}
- platform: template
id: zone1_progress_percentage
name: "Zone 1 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 0)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_1_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(0) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(0));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_1_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone1_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_1_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone2_progress_percentage
name: "Zone 2 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 1)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_2_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(1) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(1));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(1));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_2_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone2_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_2_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone3_progress_percentage
name: "Zone 3 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 2)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_3_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(2) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(2));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(2));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_3_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone3_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_3_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone4_progress_percentage
name: "Zone 4 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 3)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_4_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(3) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(3));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(3));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_4_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone4_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_4_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone5_progress_percentage
name: "Zone 5 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 4)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_5_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(4) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(4));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(4));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_5_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone5_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_5_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone6_progress_percentage
name: "Zone 6 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 5)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_6_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(5) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(5));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(5));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_6_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone6_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_6_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone7_progress_percentage
name: "Zone 7 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 6)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_7_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(6) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(6));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(7));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_7_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone7_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_7_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;
}
return {};
- platform: template
id: zone8_progress_percentage
name: "Zone 8 Progress Percentage"
update_interval: 1s
lambda: |-
if(id(lawn_sprinkler_ctrlr).active_valve().value_or(-1) == 7)
{
int seconds = round(id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_8_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return ((id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(7) - id(lawn_sprinkler_ctrlr).time_remaining_active_valve().value()) * 100 / id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(7));
}
if (id(lawn_sprinkler_ctrlr).active_valve().has_value() == false && id(lawn_sprinkler_ctrlr_status).state == "Idle")
{
int seconds = round(id(lawn_sprinkler_ctrlr).valve_run_duration_adjusted(7));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_8_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 0;
}
else if(id(zone8_progress_percentage).state > 1 && id(lawn_sprinkler_ctrlr_status).state != "Paused")
{
int seconds = 0;
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
id(zone_8_time_remaining).publish_state((
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str());
return 100;;
}
return {};
number:
- platform: template
id: sprinkler_ctrlr_multiplier
name: "Sprinkler Controller Multiplier"
min_value: 0.01
max_value: 3
step: 0.01
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).multiplier();"
set_action:
- globals.set:
id: multiplier
value: !lambda "return x;"
- sprinkler.set_multiplier:
id: lawn_sprinkler_ctrlr
multiplier: !lambda 'return x;'
- platform: template
id: sprinkler_valve_0_duration
name: "Zone 1 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(0) / 60;"
set_action:
- globals.set:
id: z1_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 0
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_1_duration
name: "Zone 2 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(1) / 60;"
set_action:
- globals.set:
id: z2_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 1
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_2_duration
name: "Zone 3 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(2) / 60;"
set_action:
- globals.set:
id: z3_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 2
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_3_duration
name: "Zone 4 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(3) / 60;"
set_action:
- globals.set:
id: z4_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 3
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_4_duration
name: "Zone 5 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(4) / 60;"
set_action:
- globals.set:
id: z5_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 4
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_5_duration
name: "Zone 6 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(5) / 60;"
set_action:
- globals.set:
id: z6_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 5
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_6_duration
name: "Zone 7 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(6) / 60;"
set_action:
- globals.set:
id: z7_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 6
run_duration: !lambda "return x * 60;"
- platform: template
id: sprinkler_valve_7_duration
name: "Zone 8 Duration"
min_value: 1
max_value: 240
step: 1.0
update_interval: 1s
lambda: "return id(lawn_sprinkler_ctrlr).valve_run_duration(7) / 60;"
set_action:
- globals.set:
id: z8_duration
value: !lambda "return x;"
- sprinkler.set_valve_run_duration:
id: lawn_sprinkler_ctrlr
valve_number: 7
run_duration: !lambda "return x * 60;"
Many thanks, I just wanted to got some inspirations what cards you were using.
Hello @olympia, I would like to thank you for working with the Sprinkler component developer. I see that you brought up some issues that I was battling for. My language barrier was impeding me to express the issues I’m having.
I’m also glad that you are using part of my code. Would you mind sharing your work here? I’m curious about what you are achieving and your dashboard.
Once again, many thanks!
Thank you for noting this!
I am actually in the same shoes as you: I am also not a developer and just learning as I want to achieve something new.
Regarding the dashboard, it’s still in heavy development (but I see the light at the end of the tunnel) and I will have no time in the next 1-1.5 weeks to continue. Still a lot to do both on the backend side (esphome code) and on the HA dashboard (still some design headache besides how I actually code it). Will definitely share the end result.
Some (not complete) teaser:
I have a single garden sprinkler, so nice and simple. I control runtime duration from HA (Helper “input_number.sprinkler_runtime”) it all works fine, however the text sensor that’s exposed to HA updates every 5 seconds (as it should) but does regardless of whether the sprinkler is running or not, so if not running it sends 0 seconds remaining, every 5 seconds, eg:
[14:03:36][D][text_sensor:064]: ‘Time Remaining’: Sending state ‘0s’
[14:03:41][D][text_sensor:064]: ‘Time Remaining’: Sending state ‘0s’
[14:03:46][D][text_sensor:064]: ‘Time Remaining’: Sending state ‘0s’
The code is fairly basic…
switch:
- platform: gpio
name: "Sprinkler Switch"
id: sprinkler_switch
pin: D1
internal: True
on_turn_off:
then:
- lambda: |-
id(time_remaining) = 0;
sensor:
- platform: homeassistant
id: runtime_mins
unit_of_measurement: "min"
accuracy_decimals: 0
entity_id: input_number.sprinkler_runtime
on_value:
- sprinkler.set_valve_run_duration:
id: garden_sprinkler_ctrlr
valve_number: 0
run_duration: !lambda "return x * 60;"
sprinkler:
- id: garden_sprinkler_ctrlr
valves:
- valve_switch: "Garden Sprinkler"
run_duration: 300s # default max
valve_switch_id: sprinkler_switch
text_sensor:
- platform: template
id: time_remaining
name: "Time Remaining"
update_interval: 5s
icon: "mdi:timer-sand"
lambda: |-
int seconds = round(id(garden_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return {
((days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str()};
To avoid always sending data back, I tried doing a simple if statement in the text_sensor:
lambda: |-
int seconds = round(id(garden_sprinkler_ctrlr).time_remaining_active_valve().value_or(0));
if (seconds > 0) {
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return {
((days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str()};
}
but it fails when compiling.
Compiling /data/sprinkler/.pioenvs/sprinkler/src/main.cpp.o
/config/esphome/sprinkler.yaml: In lambda function:
/config/esphome/sprinkler.yaml:90:3: error: control reaches end of non-void function [-Werror=return-type]
cc1plus: some warnings being treated as errors
*** [/data/sprinkler/.pioenvs/sprinkler/src/main.cpp.o] Error 1
========================== [FAILED] Took 7.82 seconds ==========================
What am I doing wrong?
Edit… actually no void function assume it always requires something to be returned then. What’s the alternative to avoid constant traffic from esp back to ha?
A template sensor must always return some value (text, float, etc) But if you give a sensor no name, it is an internal sensor and it won’t publish its state to HA. So remove the name:
line from your yaml for this text sensor.
Didn’t make a difference removing name. Also according to help pages name: is required .
Also I do want the time remaining sent to HA, but only when it’s running, not when it’s idle as there is no point sending “0 seconds remaining” every 5 seconds and is just more overhead for HA to deal with,
Sounds like you need a “text delta filter”.
Yep that worked thanks seems my C++ code in the lambda doing the return was initially wrong. But the filter is a much cleaner solution !!