A plant tells you it’s thirsty before it wilts: its canopy runs warmer than the air as stomata close. This node reads canopy temperature with a no-contact infrared thermometer and reports the canopy-minus-air gap, the raw ingredient of the Crop Water Stress Index.
What it does.
An ESP32 + a non-contact MLX90614 infrared thermometer pointed at the canopy, reporting canopy temperature, air temperature, and the canopy-minus-air gap as oat-ods.
That’s the Collect layer for one more kind of sensor: it reads the instrument, shapes each reading into the one oat-ods message every Open Agriculture Technology device speaks, and pushes it to a place you own. The value is what you do with the reading later; this just gets it flowing.
What it reads.
Each reading goes out as its own oat-ods message, filed under the place you name, so swapping the hardware later never breaks the record:
What you need.
Wiring. The MLX90614 is I²C (3.3 V): SDA, SCL, 3V3, GND. Aim it at the canopy (not the soil or pot) and keep direct sun from glinting into the sensor.
What it sends.
It pushes to wherever you point it (Webhook (HTTP POST) or MQTT) as
oat-ods/0.3. One measurement per message; here’s a reading from this node:
{
"schema": "oat-ods/0.3",
"observed_at": "2026-06-25T14:30:00Z",
"stream": { "id": "gh2-canopy", "name": "…", "location": "…" },
"measurement": "canopy_air_delta",
"value": -2.4,
"unit": "Cel",
"source": { "tier": "oat-cwsi-node", "gateway_id": "…", "physical_id": "mlx90614" }
}
That’s the same envelope the whole library speaks. Point it at your webhook, an Home Assistant broker, or Open Agriculture Technology; the receiver can’t tell which node produced it. The developer reference has the full spec.
Get it & build it.
The project downloads whole: the sketch plus the shared oat_ods library it needs, so it
builds as-is:
Full PlatformIO project (.zip) Just the sketch (.ino)
Two ways to put it on a board, both free:
- PlatformIO (builds all four ESP32 chips): unzip, then
cd oat-cwsi-node && pio run -t upload. The bundledlib/oat_ods/resolves automatically. - Arduino IDE: open the
.ino, install the libraries below from the Library Manager, pick your ESP32 board, and upload.
Compile-verified on our side (it builds clean with the pinned toolchain), but not yet run on the bench with real sensors, so it ships as source rather than a browser image. If you run it, tell the collective how it went; that’s what turns it into a flash-from-browser sketch.
Set it up.
Setup happens on the device’s own page: nothing to install, works with no internet:
- Power the node from any USB charger or your computer.
- Join its Wi-Fi network
OAT-CWSI-XXXX, and the setup page opens (or visithttp://192.168.4.1). - Sign in, set your Wi-Fi, where the readings go, and the sensor details above, then save.
- Point delivery at the test endpoint and watch your first reading arrive, checked against the standard.
Settings persist across reboots; a fresh flash wipes them, on purpose, so a re-used board never carries the last owner’s Wi-Fi or endpoint.
Notes.
- A cool canopy (negative delta) = transpiring, well-watered; a warm canopy (positive delta) = stomata closing, water stress.
- CWSI itself is derived downstream where vapor-pressure deficit (from air temp + RH) is known; this node provides the canopy ingredient.
For makers & trainers.
Frequently asked questions.
How do you measure crop water stress with a sensor?
Point a non-contact infrared thermometer at the canopy and compare leaf temperature to air temperature. A canopy warmer than the air indicates closing stomata and water stress; a cooler canopy indicates active transpiration. Combined with vapor-pressure deficit, the canopy–air difference yields the Crop Water Stress Index (CWSI).
What sensor reads leaf or canopy temperature?
A non-contact infrared thermometer such as the MLX90614 reads surface temperature from a short distance without touching the leaf. Aimed at the canopy it reports the canopy surface temperature, and its onboard ambient sensor gives a nearby air-temperature reference.