HASS sprinkler

@ronvl yeah i found that error.
Now I’m stuck with the next one…
If I set a day, I get this error:

Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/usr/lib/python3.5/site-packages/homeassistant-0.36.0.dev0-py3.5.egg/homeassistant/helpers/entity.py", line 212, in async_update_ha_state
    yield from self.async_update()
  File "/usr/lib/python3.5/asyncio/coroutines.py", line 206, in coro
    res = func(*args, **kw)
  File "/usr/lib/python3.5/site-packages/homeassistant-0.36.0.dev0-py3.5.egg/homeassistant/components/sensor/template.py", line 114, in async_update
    self._state = self._template.async_render()
  File "/usr/lib/python3.5/site-packages/homeassistant-0.36.0.dev0-py3.5.egg/homeassistant/helpers/template.py", line 99, in async_render
    return self._compiled.render(kwargs).strip()
  File "/usr/lib/python3.5/site-packages/jinja2/environment.py", line 989, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/lib/python3.5/site-packages/jinja2/environment.py", line 754, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python3.5/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 66, in top-level template code
  File "/usr/lib/python3.5/site-packages/jinja2/sandbox.py", line 355, in call
    return __context.call(__obj, *args, **kwargs)
  File "/usr/lib/python3.5/site-packages/homeassistant-0.36.0.dev0-py3.5.egg/homeassistant/util/dt.py", line 79, in as_timestamp
    raise ValueError("not a valid date/time.")
ValueError: not a valid date/time.

Have a look as this is my latest code that is still working :slight_smile: :slight_smile:

   next_run_valve_1:
     friendly_name: 'Next Run'
     entity_id:
       - input_slider.valve_1_hour
       - input_slider.valve_1_minutes
       - input_select.valve_1_schedule
       - switch.valve_1
     value_template: >
        {# runDay set to 9 = Not Set #}
        {% set runDay = 9 |int %}
        {# Set todays day #}
        {% set currentDay = now().weekday() |int %}
        {%- macro monthu() -%}
            {%- if currentDay == 0 -%}
                {{0}}  
            {%- elif  currentDay <= 3 -%}
                {{3}}
            {%- else -%}	
                {{0}}
            {%- endif -%}
        {%- endmacro -%}
        {%- macro monwedfrisun() -%}
            {%- if currentDay == 0 -%}
                {{0}}  
            {%- elif  currentDay <= 2 -%}
                {{2}}
            {%- elif  currentDay <= 4 -%}
                {{4}}
            {%- elif  currentDay <= 6 -%}
                {{6}}	
            {%- endif -%}
        {%- endmacro -%}
        {# set configured runDay from input_select #}
        {% if states.input_select.valve_1_schedule.state == "Monday" %}
            {% set runDay = 0 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Tuesday" %}
            {% set runDay = 1 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Wednesday" %}
            {% set runDay = 2 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Thursday" %}
            {% set runDay = 3 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Friday" %}
            {% set runDay = 4 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Saturday" %}
            {% set runDay = 5 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Sunday" %}
            {% set runDay = 6 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Mon/Thu" %}
            {% set runDay = monthu() |int -%}
        {% elif states.input_select.valve_1_schedule.state == "Mon/Wed/Fri/Sun" %}
            {% set runDay = monwedfrisun() |int %}  
        {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
            {% set runDay = currentDay |int %}     
        {% endif %} 
        {# determine the next runday #}
        {% if runDay == 9 %}
            {# schedule not active #}
            {% set runDate = "Not set" %}
        {% else %}
            {# schedule is active so determine next run #}
            {# first check if runDay = today #}
            {% if currentDay == runDay %}
                {# are we passed the scheduled time? #}
                {% if states.sensor.starttime_valve_1.state < now().time().strftime("%H:%M") %}
                    {# than we need to fake tomorrow #}
                    {% set currentDay = (currentDay + 1) |int %}
                    {# and calculate new runDay in case we have a list of multiple run days in in a week #}
                    {% if states.input_select.valve_1_schedule.state == "Mon/Thu" %}
                        {% set runDay = monthu() |int -%}
                    {% elif states.input_select.valve_1_schedule.state == "Mon/Wed/Fri/Sun" %}
                        {% set runDay = monwedfrisun() |int %} 
                    {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
                        {% set runDay = currentDay |int %} 
                    {% endif %}
                {% endif %}
            {% endif %}
            {# Now we can determine next runDate base on now().weekday() and not currentDay as that can be set to fake tomorrow #}	
            {% if currentDay <= runDay %}
                {% set Days = runDay - now().weekday() |int %}
            {% else %}
                {% set Days = runDay + 7 - now().weekday() |int %}
            {% endif %}
            {% set runDate = ((as_timestamp(now()) + (86400 * Days)) | timestamp_local) %}
            {# we also want to show the weekday of the next date #}
            {% set weekdayList = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] %}
            {% if now().weekday()+ Days < 7 %}
                {% set weekday = weekdayList[(now().weekday()+ Days)] %}
            {% else %}
                {% set weekday = weekdayList[(now().weekday()+ Days)- 7] %}
            {% endif %} 
        {% endif %}
        {# all done #}
        {# set states.sensor.next_run_date_valve_1.state = runDate #}
        {% if runDay == 9 %}
            {# schedule not active #}
            {{runDate}}
        {% else %}  
            {{weekday}}, {{runDate[8:10]}}-{{runDate[5:7]}}-{{runDate[0:4]}} at {{states.sensor.starttime_valve_1.state}}
        {% endif %}
1 Like

Hi @ronvl, I copied some of your code a while back and was never able to get it to work properly. I read that home assistant does all of it’s time calculations at timezone +0 GMT and then converts it to your local time after when displaying on the UI. The problem I’m having is getting the following to not use the internal time and use my local time when displaying on the sensor. I’m in timezone +8 so it always displays 8 hours behind. If you can help that would be much appreciated!

  sensor:
      - platform: template
    sensors:
      sprinklers_last_run:
        friendly_name: 'Last Run'
        entity_id: script.run_all_sprinklers
        value_template: "{{states.script.run_all_sprinklers.last_changed.strftime('%a')}}, {{states.script.run_all_sprinklers.last_changed.strftime('%d-%m')}} at {{states.script.run_all_sprinklers.last_changed.strftime('%H:%M:%S')}}"

I see you added the time as well as I don’t have that in my display. But try to use the filter timestamp_local see https://home-assistant.io/topics/templating/

so {{states.script.run_all_sprinklers.last_changed.strftime(’%H:%M:%S’) | timestamp_local}}

Try first in the developer tools if that makes a difference

also did you set the correct time zone in your hass config?

Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

time_zone: Europe/Berlin

Can you run the following in developer tools and share the output:

  1. ‘{{ (now().strftime("%s") | int | timestamp_custom("%H:%M %z%Z")) }}’
  2. ‘{{ (now().strftime("%s") | int | timestamp_local()) }}’
  3. ‘{{ (now().strftime("%Z") ) }}’
  4. {{ now().strftime("%s") | int | timestamp_utc }}
  5. {{now().strftime("%H:%M")}}

Thanks for the reply @ronvl !

The timestamp_local doesn’t appear to make any difference:

sensor:
  - platform: template
    sensors:
      sprinklers_last_run:
        friendly_name: 'Last Run'
        entity_id: script.run_all_sprinklers
        value_template: "{{states.script.run_all_sprinklers.last_changed.time().strftime('%a') | timestamp_local}}, {{states.script.run_all_sprinklers.last_changed.time().strftime('%d-%m') | timestamp_local}} at {{states.script.run_all_sprinklers.last_changed.time().strftime('%H:%M:%S') | timestamp_local}}"

I definitely have the right timezone set in the configuration.yaml:
time_zone: Australia/Perth

I can also see the timezone changes working for other sensors when tailing the log file:

INFO:homeassistant.core:Bus:Handling <Event state_changed[L]: new_state=<state sensor.since_last_boot=5 days, 2:31:55.913602; icon=mdi:clock, friendly_name=Since Last Boot @ 2017-01-31T17:50:17.936740+08:00>, entity_id=sensor.since_last_boot, old_state=<state sensor.since_last_boot=5 days, 2:31:24.863087; icon=mdi:clock, friendly_name=Since Last Boot @ 2017-01-31T17:49:46.874592+08:00>>

I don’t know how to run those in developer tools, what Domain and Service do i use? I’m assuming that list is supposed to go under the Service Data (JSON, optional)?

Hi ronvl!

Thank you so much for this amazing automation.

Im using Home Assistant 0.36.1 and have some problems in trigger part of your automation script.
Can you plase help? Id appreciate it very much.

this part of automation actually gets nothing triggered:

- alias: "Turn on valve based on schedule"
  trigger:
    platform: template
    value_template: >
      {{ states.sensor.starttime_valve_1.state == now().time().strftime("%H:%M") }}

input sliders set variables:

INFO:homeassistant.core:Bus:Handling <Event state_changed[L]: old_state=<state sensor.next_run_valve_1=Fri, 03-02-2017 at 15:40; icon=mdi:calendar-clock, friendly_name=Next Run @ 2017-02-03T08:43:55.094526+01:00>, entity_id=sensor.next_run_valve_1, new_state=<state sensor.next_run_valve_1=Fri, 10-02-2017 at 08:40; icon=mdi:calendar-clock, friendly_name=Next Run @ 2017-02-03T08:44:03.580557+01:00>>
INFO:homeassistant.core:Bus:Handling <Event state_changed[L]: old_state=<state sensor.starttime_valve_1=08:40; icon=mdi:clock, friendly_name=Start Time @ 2017-02-03T08:44:00.373083+01:00>, entity_id=sensor.starttime_valve_1, new_state=<state sensor.starttime_valve_1=08:45; icon=mdi:clock, friendly_name=Start Time @ 2017-02-03T08:44:03.600672+01:00>>

but nothing triggers event

nwm. got it working by adding sensor.time and changing trigger to

  trigger:
    platform: template
    value_template: '{{ states.sensor.time.state == states.sensor.starttime_valve_1.state }}'
1 Like

Nice project!

I’m starting to think about a garden project ready for the summer. At the moment I have no hardware for the garden at all but I have experience with ESP8266/Arduino (currently using some for PIR/Temp Sensors in HASS).

If you were to start from scratch, what hardware would you use? At the moment I have an outside tap and a water butt and NOTHING else. Would be interested to hear what people would recommend.

What I’d like to do is… water my veg patch, borders and grass.

I’m using Dark Sky to predict weather in HASS today. And I have a weather station linked to Wunderground which is then imported into HASS for live weather of my garden also (temp, wind direction, speed and rain)

Cheers! :slight_smile:

1 Like

Working on same. Got a LinkNode R4 controlled by HA/MQTT but would like to see HA code for nice UI to set and run an irrigation schedule.
Did you finish your project?
Any chance of sharing on GitHub?

I agree this looks awesome and exactly what I am trying to do. Would love to see any source code you are willing to share!

Hey revz
The code is all there in the postings. HASS has moved on a lot and things might not all work anymore but the basics still does. I have started to add and change things a bit since as well so I can’t realy share this any more as it was shown here.
If I had to do it again I would use python scripts, custom_ui and make a custom sprinkler component based on the switch component. That is the problem with HASS it is sooo flexible :smiley:

Ah, yes ok I see that now. Good advice re: python scripts and custom UI, I’ve seen that approach recommended elsewhere. Agreed re: HASS- flexibility is its strength but can be a problem too!

@ronvl By the way, the as_timestamp(now) should now be as_timestamp(now())

Do you have your config online we could see :slight_smile:

@ronvl
What sort of sensor is sensor.next_run_date_valve_1 as it’s definition is not in your example?

It is a sensor that calculates th ethe next rundate based on the various settings on the valve

  next_run_valve_1:
     friendly_name: 'Next Run'
     value_template: >
        {# runDay set to 9 = Not Set #}
        {% set runDay = 9 |int %}
        {# Set todays day #}
        {% set currentDay = now().weekday() |int %}
        {# calculate starttime #}
        {%- macro starttime() -%}
            {%- if states.input_number.valve_1_hour.state|length < 4-%}
                {{0}}
            {%- endif -%}
            {{states.input_number.valve_1_hour.state | int  }}{{':'}}
            {%- if states.input_number.valve_1_minutes.state|length < 4 -%}
               {{0}}
            {%- endif -%}
            {{ states.input_number.valve_1_minutes.state | int }}
        {%- endmacro -%}
        {% set StartTime = starttime() %}
        {%- macro monthu() -%}
            {%- if currentDay == 0 -%}
                {{0}}  
            {%- elif  currentDay <= 3 -%}
                {{3}}
            {%- else -%}	
                {{0}}
            {%- endif -%}
        {%- endmacro -%}
        {%- macro monwedfrisun() -%}
            {%- if currentDay == 0 -%}
                {{0}}  
            {%- elif  currentDay <= 2 -%}
                {{2}}
            {%- elif  currentDay <= 4 -%}
                {{4}}
            {%- elif  currentDay <= 6 -%}
                {{6}}	
            {%- endif -%}
        {%- endmacro -%}
        {# set configured runDay from input_select #}
        {% if states.input_select.valve_1_schedule.state == "Monday" %}
            {% set runDay = 0 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Tuesday" %}
            {% set runDay = 1 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Wednesday" %}
            {% set runDay = 2 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Thursday" %}
            {% set runDay = 3 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Friday" %}
            {% set runDay = 4 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Saturday" %}
            {% set runDay = 5 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Sunday" %}
            {% set runDay = 6 |int %}
        {% elif states.input_select.valve_1_schedule.state == "Mon Thu" %}
            {% set runDay = monthu() |int -%}
        {% elif states.input_select.valve_1_schedule.state == "Mon Wed Fri Sun" %}
            {% set runDay = monwedfrisun() |int %}  
        {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
            {% set runDay = currentDay |int %}     
        {% endif %} 
        {# determine the next runday #}
        {% if runDay == 9 %}
            {# schedule not active #}
            {% set runDate = "Not set" %}
        {% else %}
            {# schedule is active so determine next run #}
            {# first check if runDay = today #}
            {% if currentDay == runDay %}
                {# are we passed the scheduled time? #}
                {% if starttime() < now().time().strftime("%H:%M") %}
                    {# than we need to fake tomorrow #}
                    {% set currentDay = (currentDay + 1) |int %}
                    {# and calculate new runDay in case we have a list of multiple run days in in a week #}
                    {% if states.input_select.valve_1_schedule.state == "Mon Thu" %}
                        {% set runDay = monthu() |int -%}
                    {% elif states.input_select.valve_1_schedule.state == "Mon Wed Fri Sun" %}
                        {% set runDay = monwedfrisun() |int %} 
                    {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
                        {% set runDay = currentDay |int %} 
                    {% endif %}
                {% endif %}
            {% endif %}
            {# Now we can determine next runDate base on now().weekday() and not currentDay as that can be set to fake tomorrow #}	
            {% if currentDay <= runDay %}
                {% set Days = runDay - now().weekday() |int %}
            {% else %}
                {% set Days = runDay + 7 - now().weekday() |int %}
            {% endif %}
            {% set runDate = ((as_timestamp(now()) + (86400 * Days)) | timestamp_local) %}
            {# we also want to show the weekday of the next date #}
            {% set weekdayList = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] %}
            {% if now().weekday()+ Days < 7 %}
                {% set weekday = weekdayList[(now().weekday()+ Days)] %}
            {% else %}
                {% set weekday = weekdayList[(now().weekday()+ Days)- 7] %}
            {% endif %} 
        {% endif %}
        {# all done #}
        {# set states.sensor.next_run_date_valve_1.state = runDate #}
        {% if runDay == 9 %}
            {# schedule not active #}
            {{runDate}}
        {% else %}  
            {{weekday}}, {{runDate[8:10]}}-{{runDate[5:7]}}-{{runDate[0:4]}} at {{starttime()}}
        {% endif %}

To be fair I don’t know if it is all still running (as there where a few HASS updates) as it is winter here and I haven’t been using it since September. I guess in a couple of months I need to get it up and running again.

1 Like

Just a note, I found with the new home assistant updates the templated sensor for the:

status_valve_1:
friendly_name: ‘Status’
value_template: “{% if states.switch.valve_1.state == ‘on’%}Opened {{as_timestamp(now) - as_timestamp(states.switch.valve_1.last_changed)) / 60) | round(0) }} minutes ago{% else %}Closed{% endif %}”

Will not update and remains “Opened 0 minutes ago”.

Looking online this seems due to template sensor values not updating with now().
Fix: Link. Create a new Time & Date sensor then use that in place of “Now()”

I.E. Replace “now()” with “strptime(states.sensor.date__time.state, ‘%Y-%m-%d, %H:%M’”

status_valve_1:
friendly_name: ‘Status’
value_template: “{% if states.switch.valve_1.state == ‘on’%}Opened {{((as_timestamp(strptime(states.sensor.date__time.state, ‘%Y-%m-%d, %H:%M’) - as_timestamp(states.switch.valve_1.last_changed)) / 60) | round(0) }} minutes ago{% else %}Closed{% endif %}”

I have an example on my github config:
Root: Home-Assistant-Configuration
File: mqtt_irrigation.yaml

Hey guys, had quite a struggle to get this working on 0.94.0. I’m experiencing issues when setting the schedule to include more than one day, for instance, Mon,Tue,Wednesday. The next runtime will change to “Not Set” Is this normal? The next runtime on any other static day like just “Monday” works without an issue.

  next_run_valve_1:
    friendly_name: 'Next Run'
    value_template: >
      {# runDay set to 9 = Not Set #}
      {% set runDay = 9 |int %}
      {# Set todays day #}
      {% set currentDay = now().weekday() |int %}
      {# calculate starttime #}
      {%- macro starttime() -%}
        {%- if states.input_number.valve_1_hour.state|length < 4-%}
            {{0}}
        {%- endif -%}
        {{states.input_number.valve_1_hour.state | int  }}{{':'}}
        {%- if states.input_number.valve_1_minutes.state|length < 4 -%}
           {{0}}
        {%- endif -%}
        {{ states.input_number.valve_1_minutes.state | int }}
      {%- endmacro -%}
      {% set StartTime = starttime() %}
      {%- macro monthu() -%}
        {%- if currentDay == 0 -%}
            {{0}}  
        {%- elif  currentDay <= 3 -%}
            {{3}}
        {%- else -%}	
            {{0}}
        {%- endif -%}
      {%- endmacro -%}
      {%- macro monwedfrisun() -%}
        {%- if currentDay == 0 -%}
            {{0}}  
        {%- elif  currentDay <= 2 -%}
            {{2}}
        {%- elif  currentDay <= 4 -%}
            {{4}}
        {%- elif  currentDay <= 6 -%}
            {{6}}	
        {%- endif -%}
      {%- endmacro -%}
      {# set configured runDay from input_select #}
      {% if states.input_select.valve_1_schedule.state == "Monday" %}
        {% set runDay = 0 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Tuesday" %}
        {% set runDay = 1 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Wednesday" %}
        {% set runDay = 2 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Thursday" %}
        {% set runDay = 3 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Friday" %}
        {% set runDay = 4 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Saturday" %}
        {% set runDay = 5 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Sunday" %}
        {% set runDay = 6 |int %}
      {% elif states.input_select.valve_1_schedule.state == "Mon Thu" %}
        {% set runDay = monthu() |int -%}
      {% elif states.input_select.valve_1_schedule.state == "Mon Wed Fri Sun" %}
        {% set runDay = monwedfrisun() |int %}  
      {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
        {% set runDay = currentDay |int %}     
      {% endif %} 
      {# determine the next runday #}
      {% if runDay == 9 %}
        {# schedule not active #}
        {% set runDate = "Not set" %}
      {% else %}
        {# schedule is active so determine next run #}
        {# first check if runDay = today #}
        {% if currentDay == runDay %}
            {# are we passed the scheduled time? #}
            {% if starttime() < now().time().strftime("%H:%M") %}
                {# than we need to fake tomorrow #}
                {% set currentDay = (currentDay + 1) |int %}
                {# and calculate new runDay in case we have a list of multiple run days in in a week #}
                {% if states.input_select.valve_1_schedule.state == "Mon Thu" %}
                    {% set runDay = monthu() |int -%}
                {% elif states.input_select.valve_1_schedule.state == "Mon Wed Fri Sun" %}
                    {% set runDay = monwedfrisun() |int %} 
                {% elif states.input_select.valve_1_schedule.state == "Every Day" %}
                    {% set runDay = currentDay |int %} 
                {% endif %}
            {% endif %}
        {% endif %}
        {# Now we can determine next runDate base on now().weekday() and not currentDay as that can be set to fake tomorrow #}	
        {% if currentDay <= runDay %}
            {% set Days = runDay - now().weekday() |int %}
        {% else %}
            {% set Days = runDay + 7 - now().weekday() |int %}
        {% endif %}
        {% set runDate = ((as_timestamp(now()) + (86400 * Days)) | timestamp_local) %}
        {# we also want to show the weekday of the next date #}
        {% set weekdayList = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] %}
        {% if now().weekday()+ Days < 7 %}
            {% set weekday = weekdayList[(now().weekday()+ Days)] %}
        {% else %}
            {% set weekday = weekdayList[(now().weekday()+ Days)- 7] %}
        {% endif %} 
      {% endif %}
      {# all done #}
      {# set states.sensor.next_run_date_valve_1.state = runDate #}
      {% if runDay == 9 %}
        {# schedule not active #}
        {{runDate}}
      {% else %}  
        {{weekday}}, {{runDate[8:10]}}-{{runDate[5:7]}}-{{runDate[0:4]}} at {{starttime()}}
      {% endif %}

Any help or advice will be appreicated

Please ignore, had to change “Mon Wed Fri Sun” to “Mon/Wed/Fri/Sun”

My project uses only sonoff Flashed with Tasmota. In Hass have UI and one scene, some automation only for emergency stop and notifications to phone apk. Base is on Node-Red.

link: https://github.com/marian790/irrigation

1 Like