fieldmesh

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.

What could flow each way, in the order worth doing#

  1. Read the valves into the log: buildable now, no commands. Built 2026-10-11: an OpenSprinkler profile in the MQTT bridge, a valve_open term, 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 (firmware services/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.

  2. 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.

  3. 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.

  4. 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.

  5. 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 watering scale from 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.

  6. 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.

  7. 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:

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.

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.

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:

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.