Sprinklers and drip: the open projects, where they meet this one, and what could flow each way#
Looked at on 2026-10-11. Licences and activity were read from each repository, and every claim about OpenSprinkler's messages from its firmware's source.
Who is out there#
| project | what it is | licence | state |
|---|---|---|---|
| OpenSprinkler | open-hardware irrigation controllers (ESP8266/ESP32, Raspberry Pi), firmware, a documented local HTTP API and MQTT | firmware GPL-3.0; app AGPL-3.0 | active: firmware pushed 2026-09-29 |
| OpenSprinkler Weather | the service a controller asks for its watering scale: manual, Zimmerman, rain delay or ETo, from public providers or a local weather station | none declared | active: 2026-08-16 |
| SIP (Sustainable Irrigation Platform) | a Raspberry Pi controller in Python 3, with plugins; also runs pumps and lights | "GNU GPL" in its README, no licence file, so the version is unstated | active: 2026-07-27 |
| Smart Irrigation for Home Assistant | run times per zone from evapotranspiration, rain and forecasts; a UI in 19 languages | MIT | active: 2026-10-11 |
| ESPHome sprinkler | a valve controller on an ESP chip: zones, cycles, a run-time multiplier, a pump or main valve upstream | GPL-3.0 for its C++ runtime, MIT for its Python | maintained with ESPHome, pushed 2026-10-11 |
| pyfao56 (USDA ARS) | FAO-56 dual crop coefficient water balance and irrigation scheduling; NWS forecasts; measured soil water profiles | public domain in the US, CC0 elsewhere | active: 2026-09-21 |
| AquaCrop-OSPy | FAO's AquaCrop crop-water model in Python: yield's response to irrigation strategies | Apache-2.0 | active: 2026-09-23 |
| Mycodo | environmental monitoring and regulation, PID loops, irrigation among them | GPL-3.0 | active |
| FarmBot | a CNC garden robot that waters by plant and reads soil moisture | MIT | active |
| farmOS | farm records; water applied can be an input log | GPL-2.0 | active |
For the farm-scale end — centre pivots and variable-rate irrigation — the search found patents, not open projects. Pivot controllers are the manufacturers' own.
Where they meet what is here#
All of these are at the scale of the farms this project is for: drip zones in beds, a tunnel, a garden-sized field. Three things here touch them.
- The soil-moisture advisory (modules/soilwater/) decides whether and how much, from the farm's own probes, FAO-56's readily available water and the rain forecast. Its watering check says when a watering never reached the bed. The controllers above decide when the valves open, mostly by timer adjusted by weather. None of them reads a soil probe as its main input.
- The irrigation drill (sim/irrigation_drill.py) scores watering rules on recorded summers by the water applied, the water lost below the roots and the hours of crop stress: a timer, skip on forecast rain, the soil rule. It can run thirty summers. Nothing in the projects above publishes that kind of comparison for its own adjustment methods.
- The command contract (§6), deferred, is where an irrigation controller lives: a command that survives a reboot without running twice, an acknowledgement or an honest "unknown", and no overdrawing one well from two modules (§6.5, §15). The irrigation controller is the one of §15's three acceptance apps that waits on it.
What could flow each way, in the order worth doing#
-
Read the valves into the log: buildable now, no commands. Built 2026-10-11: an OpenSprinkler profile in the MQTT bridge, a
valve_openterm, and the watering check naming a blocked line or a bed nobody watered (modules/soilwater). OpenSprinkler publishes each valve's opening and closing over MQTT, under its configured prefix (firmwareservices/notifier.cpp):station/<n>,{"state":1,"duration":…}on opening;{"state":0,"duration":…,"flow":…}on closing, the flow from its flow sensor if one is fitted;sensor/flow,raindelay,weather, and alerts on flow and current;- from 2.2.1(6),
program/<n>as a program starts: run or skipped, and the weather, sensor and total scales it ran at (read since 2026-10-11).
The station flow is checked since 2026-10-11: each zone's runs against its usual flow and its heads, saying when a head is clogged or broken (modules/zoneflow).
An OpenSprinkler profile in the MQTT bridge (sdk/mqtt_bridge.py), beside its ESPHome and Home Assistant profiles, would put each watering in the log as an observation. The watering check could then tell apart the two things a probe cannot: the valve ran for 90 minutes and no water reached the bed (a blocked line or a leak) and nobody watered. The board could show the last watering beside each bed. ESPHome's sprinkler, and SIP and Home Assistant through MQTT, could be read the same way.
-
Score their methods on recorded summers, and give the numbers back. Scored 2026-10-11: the results are below. Giving them back is the maintainer's. Add OpenSprinkler's Zimmerman and ETo adjustments and Smart Irrigation's evapotranspiration bucket to the irrigation drill, beside the timer and the soil probe, over thirty McAllister summers. That gives water applied, drained and stress for each. It is a comparison none of those projects can easily make for itself, and the kind they could use to set defaults. Shared as a note and an issue in each project, it is a contribution of evidence, not code.
-
Take pyfao56's water balance where a bed has no probe. Scored 2026-10-11, its scheduler run as published: below. It is public domain and CC0, so it can be used in an AGPL module outright, with credit. Its dual crop coefficient and layered soil go further than the advisory's single bucket. It could advise beds without probes, and check the advisory's bucket where they have them.
-
Licence clarity, two small requests. OpenSprinkler Weather declares no licence, though the firmware and app beside it are GPL and AGPL. SIP says "GNU GPL" without a licence file, so which version is unclear. Without a licence, others cannot safely build on the code, and asking is a contribution in itself.
-
A soil-based watering scale for an OpenSprinkler, later. A controller asks the weather service at an address it is configured with (
SOPT_WEATHERURL, http or https) and takes a wateringscalefrom the answer. A farm's own fieldmesh could answer that request from its soil probes instead of the weather. The controller keeps its own schedule, valves, rain delay and limits, and fieldmesh would only say more or less. That is a command in all but name: it changes how much water flows. So it waits for §6 and the trust ramp (§11: advisory, then approval, then autonomous). Until then the same number can stand on the board as advice. -
Read their safeguards before freezing §6. OpenSprinkler's main valve, sequential groups, flow alerts and rain delay are a working controller's answers to the questions §6.5 asks about shared limits. They are worth reading alongside OGC Connected Systems (Q3b) before the contract is frozen.
-
Yield, not only water: AquaCrop-OSPy (Apache-2.0) could score the advice by what the crop yields under it, as GreenLight scores the tunnel (Q28). This is layer-3 work, after the irrigation module exists.
Items 1 to 3 are code that can be written here. Items 2 and 4 involve opening issues in other projects, which is the maintainer's to do. Item 5 waits on §6.
Their methods on thirty summers#
sim/irrigation_drill.py --summers 1991-2020 --controllers, on McAllister Farm's thirty
recorded summers (NASA POWER), puts one bed through each under every rule on identical
weather. The bed is a 30 cm root zone in silt loam under a full canopy. The controllers' rules
are written from their source:
- OpenSprinkler's Zimmerman (
ZimmermanAdjustmentMethod.ts) and ETo (EToAdjustmentMethod.ts) methods scale the timer's program, 12 mm every second morning, by the day before's weather; - Home Assistant's Smart Irrigation (
calculation.py, with its defaults: crop factor 1, a 24 mm bucket, surplus drained within the day) puts back each day's reference ET less its rain.
Reference ET is FAO-56 Penman–Monteith, from each day's recorded extremes, mean humidity and sunshine, with FAO-56's 2 m/s where no wind is recorded. On FAO-56's own Example 18 it gives 3.79 mm against the published 3.9; the gap is the mean humidity, where the example uses the day's maximum and minimum.
| rule | water applied | drained below the roots | transpired | hours seriously stressed, a summer |
|---|---|---|---|---|
| timer | 552 mm | 405 mm | 468 mm | 2 |
| OpenSprinkler ETo, default annual baseline | 612 | 464 | 468 | 0 |
| OpenSprinkler Zimmerman | 385 | 238 | 468 | 6 |
| OpenSprinkler ETo, a summer baseline | 367 | 220 | 468 | 0 |
| Home Assistant Smart Irrigation | 294 | 147 | 468 | 6 |
| pyfao56's scheduler, no probe | 322 | 177 | 468 | 5 |
| this project's soil probe rule | 294 | 148 | 468 | 3 |
Run again on 2026-10-16, when the simulator's crop began to use its water whole until half is gone, as FAO-56's does: every rule now transpires the same, and the differences are in water and stress.
The first five rows reproduce the timer's figures in forecasts.md exactly, and the soil probe's.
- OpenSprinkler's ETo method, left at its default baseline, waters more than the plain timer: 11% more, and 15% more lost below the roots. Its baseline is an annual figure, a year-round average day of 2.8 mm here, while summer runs at 4.8 mm. So every summer program is scaled up by about 1.7, against its cap of 2. Set to a summer baseline, the same method saves a third. The baseline matters more than the method, and the default works against a grower who set the program in summer. That is the finding worth giving back first. Here the annual mean of FAO-56 ET on POWER data stands in for its MOD16 dataset, so the exact factor is this place's estimate, not theirs.
- Zimmerman saves 30% in this humid climate, where its humidity term pulls the scale down, for 6 hours of stress a summer. Far drier air would push it the other way.
- Home Assistant's bucket saves 47%, as much as the soil probe, for 6 hours of stress a summer against the probe's 3: the closest a weather-only rule comes to it.
- The soil probe saves 47%, with 3 hours of stress a summer. (On the simulator before 2026-10-16, whose crop slowed as soon as its soil was below field capacity, 60%.)
One place, one soil and one crop, in a humid climate whose summers average 315 mm of rain. Over thirty summers the virtual bed's own water use averages 4.8 mm a day, the same as the reference ET the controllers compute, so none of them is scored against a demand it could not know. A drier place, a sandier soil or a crop factor other than 1 would move every row.
pyfao56 without a probe#
tools/pyfao56_schedules.py runs pyfao56 1.4.3's automatic
scheduler (Thorp, DeJonge and Kukal 2025) as published, in its own environment, on each of the
thirty summers. It is configured with the drill's bed: a 30 cm root zone, field capacity 0.30,
wilting point 0.12, a full canopy with a basal crop coefficient of 1.05. It waters when a third
of the available water is gone, the probe rule's refill point, back to field capacity. The
irrigation drill then waters the virtual bed on that schedule
(sim/data/pyfao56-mcallister-summers.csv, policy pyfao56): 12 waterings a summer of about
25 mm.
- With no probe it saves 42% of the timer's water, for 5 hours of stress a summer. That is more than Zimmerman's or the ETo method's savings and less than Home Assistant's bucket, which waters every day.
- It drains more than the probe rule, 177 mm against 148. It refills by its own model's
depletion, which runs ahead of what the virtual bed actually lost, so part of each 25 mm
goes below the roots. An open-loop water balance drifts from the soil. This is where the
two projects fit together: pyfao56 can update its balance from measured soil water content
(its
Updateclass), and the probes here, each reading with its quality verdict, are that input. A probe that is flagged need not reach it. - Our reference ET agrees with pyfao56's: over 10,958 days at McAllister,
sim/physics.fao56_etoran 0.013 mm a day above pyfao56's ASCE routine (refet.ascedaily) on average. The spread was 0.04 mm, and the worst single day differed by 0.35 mm. So the controllers above are fed the same ET a published implementation computes. - A bug worth reporting: pyfao56 1.4.3 divides by zero for a canopy whose basal crop
coefficient does not change over the season (
Kcbini == Kcbmid;model.py, the plant height step). A turf, a pasture, a bed already in full leaf all hit it. The script steps around it with 1.049 and says so.
Built since: the advisory for a bed without a probe, from the farm's own station
(by the weather). It
needs daily sunshine and humidity in the farm's log to compute ET from. The forecast collector keeps
humidity already. Sunshine it does not: NOAA's National Blend carries it (dswrf, which
tools/nbm_verify.py reads), or a station measures it (weather stations).
Soils the controllers do not see#
None of the open controllers above knows the soil it waters. OpenSprinkler scales a program by the weather, Smart Irrigation keeps a bucket of a size someone set, and pyfao56 takes field capacity and wilting point as given. In a yard that is often the wrong soil: topsoil brought in over a compacted subsoil, sod over the yard's own. Water soaks into the top layer, stalls at the dense one and perches, and the rest of a long run runs off. That is the "it just saturates" a weather-scaled timer produces.
The soil advisory now learns each probe's field capacity from the level it drains back to after a soaking. When two probes in one bed learn values far apart, it says the bed is layered and asks for each layer's values (modules/soilwater).
On the simulator's yard, 10 cm of sandy loam over compacted clay, set up with the soil survey's silt loam:
- One probe in the topsoil drowned it: 680 mm in the summer of 2013.
- With learning, it applied 178 mm, with no stressed hour.
- A probe in each layer needed each layer's values as well before its roots were never short in the 2012 drought.
This is what a probe gives that weather alone cannot. It is also what a controller's soil-based watering scale (item 5) would carry, once §6 allows one.
For a home lawn, the add-ons a system can take without being replaced (rain and soil sensors, weather-based adjustment, cycle and soak, rotary nozzles) are scored in lawn-sprinklers.