Hass + sprinkler_pi

Last summer I installed a sprinkler_pi box for my sprinkler system.


I chose this over opensprinkler since this setup only required a cheap relay board. It is also faster to get up and running compared to building your own solution.
But of course, you want to integrate this with HASS :sunglasses:

It is possible to manually open/close the valves using the following url:
curl http://sprinkler:8080/bin/manual?zone=za&state=on (or off)
z a = zone number in sprinkler pi

So IĀ“ve started with this package in HASS:

switch:
 - platform: command_line
   switches:
     valve1:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zb&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zb&state=off\""
     valve2:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zc&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zc&state=off\""
     valve3:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zd&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zd&state=off\""
     valve4:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=ze&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=ze&state=off\""
     valve5:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zf&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zf&state=off\""
     valve6:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zg&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zg&state=off\""


input_slider:
  sprinklerhour:
    name: Sprinkler Hour
    icon: mdi:timer
    initial: 9
    min: 0
    max: 23
    step: 1
  sprinklerminutes:
    name: Sprinkler Minutes
    icon: mdi:timer
    initial: 0
    min: 0
    max: 55
    step: 5
  valve1:
    name: Road Duration
    initial: 60
    min: 0
    max: 120
    step: 5
  valve2:
    name: Play House Duration
    initial: 60
    min: 0
    max: 120
    step: 5
  valve3:
    name: Hedge Duration
    initial: 60
    min: 0
    max: 120
    step: 5
  valve4:
    name: Gate Duration
    name: Gate Duration
    initial: 60
    min: 0
    max: 120
    step: 5
  valve5:
    name: Lawn Duration
    initial: 60
    min: 0
    max: 120
    step: 5
  valve6:
    name: Rock Duration
    initial: 60
    min: 0
    max: 120
    step: 5
sensor:
  platform: template
  sensors:
    sprinklertime:
      friendly_name: 'Sprinkler Time'
      value_template: '{{ states.input_slider.sprinklerhour.state | int }}:{% if states.input_slider.sprinklerminutes.state|length == 1%}0{% endif %}{{ states.input_slider.sprinklerminutes.state |int }}'



automation:
  - alias: 'Sprinkler Schedule'
    initial_state: true
    trigger:
      - platform: time
        minutes: '/1'
        seconds: 10
    condition:
      - condition: template
        value_template: '{{ (now().strftime("%s") | int | timestamp_custom("%H:%M")) == states.sensor.sprinklertime.state }}'
    action:
#Valve1
      - service: homeassistant.turn_on
        data:
          entity_id:
            - switch.valve1
      - delay: '00:{{ states.input_slider.valve1.state | int }}:00'
      - service: homeassistant.turn_off
        data:
          entity_id:
            - switch.valve1
#Valve2
      - service: homeassistant.turn_on
        data:
          entity_id:
            - switch.valve2
      - delay: '00:{{ states.input_slider.valve2.state | int }}:00'
      - service: homeassistant.turn_off
        data:
          entity_id:
            - switch.valve2
      - service: notify.notify
        data:
          message: Sprinkler done.

Which gives me

Atm I can schedule the start time and the duration for each valve.
This can of course be combined with other services in HASS such as weather forecast and if you want to start at sunset, using Alexa(?) etc.

Using sprinkler_pi you can only have one valve open at the time. So if you have valve1 open and turn on valve2 it will automatically close valve1. This is not shown in HASS though and therefore am I using turn off after each delay in the automation.

The box:

So far it seems to work well, I have two questions though:

  1. If I set the duration for one valve to 0 I would like it to completely skip that valve instead turning it on/off. Is that possible with some condition? It should of course continue to the next valve.

  2. If IĀ“m not using the schedule but manually open valve1 using the switch and then (without turning it off again) turn on valve2 both valves are presented as on in HASS however only valve2 is actually open (as described above). Is it possible to fix this somehow?

Suggestions for improvements are most welcome :slight_smile:

Thanks

3 Likes

I think if you ditched the sprinkler_pi, and just ran enough ESP8266 chips running relays, using MQTT, and leave all the brains up to HA, you would be better off. Sorry to say.

https://www.amazon.com/LinkSprite-211201005-Arduino-Compatible-Wi-Fi-Controller/dp/B01N2ALK8X/ref=sr_1_1?ie=UTF8&qid=1491155752&sr=8-1&keywords=linknode+r8

1 Like

Thank you for your input.
In my case I canĀ“t use a esp8266 since I use my rPi for other tasks as well.
Sure, I could install a MQTT listener or even run a HASS slave with gpio switches.

But since I already got a fully working sprinkler_pi installation I went for this approach.
If it turns out to be unstable IĀ“ll change method.

Looks like a nice relay card! I might use it for other projects.

1 Like

Just finished a very similar implementation.
your notes were very helpful.
Thanks.

Hereā€™s a small improvement that letā€™s Home Assistant show the state of any valves that have been turned on or off by Sprinkler_Pi

   switches:
     valve1:
       command_on:  "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zb&state=on\""
       command_off: "/usr/bin/curl \"http://sprinkler:8080/bin/manual?zone=zb&state=off\""
       command_state: "/usr/bin/curl -s --connect-timeout 5 \"http://sprinkler:8080/json/zones\" | python3 -c \"import sys, json; print(json.load(sys.stdin)['zones'][0]['state'])\""
       value_template: '{{ value == "on" }}'
2 Likes

Great Treno, will implement that

1 Like

Iā€™ve played around with this a little more.
There is a web call that will cause the quick-schedule to run.
I think Iā€™m going to dispense with the HA timers, and just have a button to call the quickschedule.
That call looks like this:

curl http://sprinkler:8080/bin/setQSched?sched=0

This will run my first schedule. (since I only have one schedule, thatā€™s fine for my implementation)

Ah, that means you can actually create the schedule in sprinkler_pi instead of HASS right?
Can be useful, specially now when sprinkler_pi is more stable (version 1.x)

I am trying to implement something similar using RPI GPIO can you please help me with your code?
Error I am getting is
WARNING (MainThread) [homeassistant.components.sensor.template] Could not render template Sprinkler Time, the state is unknown.

platform: rpi_gpio
invert_logic: true
ports:
2: Zone 1
3: Zone 2
4: Zone 3
17: Zone 4
27: Zone 5
input_slider:
sprinklerhour:
name: Sprinkler Hour
icon: mdi:timer
initial: 9
min: 0
max: 23
step: 1
sprinklerminutes:
name: Sprinkler Minutes
icon: mdi:timer
initial: 0
min: 0
max: 55
step: 5
zone 1:
name: Road Duration
initial: 60
min: 0
max: 120
step: 5
zone_2:
name: Play House Duration
initial: 60
min: 0
max: 120
step: 5
zone_3:
name: Hedge Duration
initial: 60
min: 0
max: 120
step: 5
zone_4:
#name: Gate Duration
initial: 60
min: 0
max: 120
step: 5
zone_5:
name: Lawn Duration
initial: 60
min: 0
max: 120
step: 5

- alias: 'Sprinkler Schedule'
  initial_state: true
  trigger:
    - platform: time
      minutes: '/1'
      seconds: 10
  condition:
    - condition: template
      value_template: '{{ (now().strftime("%s") | int | timestamp_custom("%H:%M")) == states.sensor.sprinklertime.state }}'
  action:

    - service: homeassistant.turn_on
      data:
        entity_id:
          - switch.zone_1
    - delay: '00:{{ states.input_slider.zone_1.state | int }}:00'
    - service: homeassistant.turn_off
      data:
        entity_id:
          - switch.zone_1

    - service: homeassistant.turn_on
      data:
        entity_id:
          - switch.zone_2
    - delay: '00:{{ states.input_slider.zone_2.state | int }}:00'
    - service: homeassistant.turn_off
      data:
        entity_id:
          - switch.zone_2
    - service: notify.notify
      data:
        message: Sprinkler done.

        ##########################################
        ##### sensor.yaml
        ##########################################

        - platform: template
          sensors:
            sprinklertime:
              friendly_name: 'Sprinkler Time'
              value_template: '{{ states.input_slider.sprinklerhour.state | int }}:{% if states.input_slider.sprinklerminutes.state|length == 1%}0{% endif %}{{ states.input_slider.sprinklerminutes.state |int }}'

Any links/tutorials for reference?

one of your sliders might not be defined.
Hereā€™s what to do:

  1. remove the sensor from your code so HA can start up.
  2. look at the states <> section of the developer tools to see if you sliders exist
  3. go to the template section of the developer tools and paste in your template. You can play with it there until it works.

Iā€™m still playing with this. I have documented the rest of the apiā€™s (except the add and delete stuff) here it is:

ā€œbin/setQSchedā€ Initiates a quick schedule
Options : run one zone for a duration
http://sprinkler:8080/bin/setQSched?zb=5

Options : sched : 0 through x will run a current schedule as a quick schedule.
http://sprinkler:8080/bin/setQSched?sched=0

ā€œbin/manualā€ runs a zone manually. (turning on a manual zone, turns automation off)
http://sprinkler:8080/bin/manual?zone=zf&state=on\

ā€œbin/runā€ enables run schedules
http://sprinkler:8080/bin/run?system=on
http://sprinkler:8080/bin/run?system=off

ā€œjson/scheduleā€ shows the details of a schedule
options : id required: can be a to z
http://sprinkler:8080/json/schedule?id=a

ā€œjson/schedulesā€ shows basic information on all schedules
http://sprinkler:8080/json/schedules

ā€œjson/zonesā€ shows for each zone: name, enabled, pump, state
http://sprinkler:8080/json/zones

ā€œjson/settingsā€ returns web port, and weather underground settings.
http://sprinkler:8080/json/settings

ā€œjson/stateā€ returns system state values
http://sprinkler:8080/json/state
returns
{ ā€œversionā€ : ā€œ1.0.9ā€,
ā€œrunā€ : ā€œonā€,
ā€œzonesā€ : ā€œ5ā€,
ā€œschedulesā€ : ā€œ1ā€,
ā€œtimenowā€ : ā€œ1500903690ā€,
ā€œeventsā€ : ā€œ6ā€
}

ā€œjson/wcheckā€ returns weather underground data.
http://sprinkler:8080/json/wcheck

ā€œjson/logsā€
parameters:
sdate : unix epoch representing the start date of the report
edate : unix epoch representing the end date of the report
g : grooupin values h, d, or m (hourly, daily, monthly)
(params : sdate(start_date), edate(end_date), g(grouping))
http://sprinkler:8080/json/logs?sdate=1500834540&g=m

ā€œjson/tlogsā€ JSONtLogs(key_value_pairs, pFile);
same options as logs, but returns logs with text descriptors

ā€œShowSchedā€
options : none
shows details for all schedules

ā€œShowZonesā€
options : none
shows all zone configuration

ā€œShowEventā€
options : none
Shows an event log

And here is my current config:

#input_boolean 
run_sprinklers_now:
  name: Run Sprinklers Now
  initial: off
#sensor  
- platform: command_line
    name: sprinkler last run
    command: python3 ~/.homeassistant/scripts/getSprinklerLastRun.py
    scan_interval: 3600
#automation
- alias: autoSprinklers
  trigger:
    - platform: state
      entity_id: input_boolean.run_sprinklers_now
      to: 'on'
  action:
    - service: shell_command.rsprinklers
    - service: input_boolean.turn_off
      entity_id: input_boolean.run_sprinklers_now
     
#shell command  
  rsprinklers: curl http://sprinkler:8080/bin/setQSched?sched=0
#getsprinklerLastRun.py
import requests, time
from datetime import datetime, timedelta
startDate = (datetime.today() - timedelta(days=5)).strftime('%s');
endDate = datetime.today().strftime('%s');
url = 'http://sprinkler:8080/json/tlogs?sdate=' + startDate + '&edate=' + endDate
r = requests.get(url);
logs = r.json()['logs'];
maxdate = 0;
#iterate through all the entries finding the oldest one that was more than 5 minutes
for z in range(0, len(logs)):
    for e in range (0, len(logs[z]['entries'])):
        duration = logs[z]['entries'][e]['duration'];
        rundate = logs[z]['entries'][e]['date'];
        
        if (duration > 300 ) and (rundate > maxdate):
            maxdate = rundate;
diff = datetime.today() - datetime.fromtimestamp(maxdate)
print (diff.days)

Hope this gives you guys some ideas.

1 Like

This is great!
I might switch over to your setup.
Would it be possible to present the scheduled defined in sprinkler pi in HASS somehow?

it would be pretty tough. If you donā€™t have H.A. running under SSL, you could do it as an panel_iframe.
I am using ssl though, so that wonā€™t work. Thereā€™s just a ton of information to present using the limited controls in H.A.

I thought about adding a weblink, but it would only work when I was at home, so thatā€™s probably not a great idea.

Thanks for the help treno.

1 Like

Thinking about this a little more, itā€™s entirely possible to have your current sliders display the information from a single schedule on sprinkler_pi.

You would implement each item as a command line item that makes a call to http://sprinkler:8080/json/schedule?id=a

Then in the value_template for each item you would parse out what you were looking for.
So, for example to get the duration of the first zone, your template would be :

{{value_json['zones'][0]['duration']}}

You could work out the time as well using this same method.

@treno, Is this still working for you in the latest dev (.54.0)

My log is spamming with

2017-09-14 18:08:04 ERROR (Thread-12) [homeassistant.components.switch.command_line] Command failed: /usr/bin/curl -s --connect-timeout 5 ā€œhttp://sprinkler:8080/json/zonesā€ | python3 -c ā€œimport sys, json; print(json.load(sys.stdin)[ā€˜zonesā€™][3][ā€˜stateā€™])ā€

Even though if I run the command in bash it still works fine

Iā€™m on 0.53 and no issues

OK, strange. Thanks for confirmation.

I had to disable it for now

Hi i have two greeniq gen2, is it possible to use google agenda event to activate a sprinkler zone ? much easy to schedule with 10 zones.