Skip to Content

← All functionalities

Automated agricultural irrigationRaspberry Pi (Docker)HTTPControl

Weather-conditioned irrigation with OpenWeather and Node-RED

Watering right before a storm wastes energy and drowns the crop. This smart irrigation flow for Node-RED on a Raspberry Pi queries the OpenWeather API before each cycle: morning and evening schedulers (cron-plus) trigger a forecast request, and a function node cancels the cycle if rain is expected in the next 24 hours or temperatures approach frost. A manual mode lets the farmer override the weather check. It is the decision core of a real automated irrigation deployment.

Two schedulers, one decision pipeline

Two cron-plus nodes (07:00 and 19:00) and a manual inject all converge on the same chain — build the forecast URL, call OpenWeather, decide. The function node sums forecast rain across eight 3-hour blocks and tracks the minimum predicted temperature. Above 2 mm of expected rain or below 1 °C, msg.regar is false and the cycle is skipped with an explicit reason.

Manual mode respects the human

When the trigger arrives from the manual inject (or the Telegram /regar command), msg.modo is set to manual and the rain check is bypassed: the farmer decided, the system obeys. The weather data still travels in msg.meteo, so the dashboard and notifications show what the forecast said even when it was overridden — useful for building trust in the automation.

Reasons, not just booleans

Every decision carries a human-readable msg.motivo ("Rain forecast: 5.2 mm in 24 h") that ends up in the node status, the Telegram notification and the cycle log. Cycle duration depends on the time slot — longer in the morning, shorter in the evening — and the start order is handed to the Modbus tab that drives the Schneider Altivar 320.

A snippet from the implementation

Straight from the example as deployed on the Raspberry Pi (Docker) — copy it freely:

const LAT = 41.6000;                       // latitude of the farm (placeholder)
const LON = 1.8000;                        // longitude of the farm (placeholder)
const API_KEY = env.get("OPENWEATHER_API_KEY");

msg.mode = msg.mode || "auto";             // "auto" (scheduler) or "manual"
msg.url =
    "https://api.openweathermap.org/data/2.5/forecast" +
    `?lat=${LAT}&lon=${LON}&appid=${API_KEY}&units=metric&cnt=8`;
// cnt=8 -> next 24 h in 3-hour blocks

return msg;


// ===========================================================================
// FUNCTION 2 — "Decide irrigation"
// Analyzes the OpenWeather response: cancels if rain is forecast or there
// is frost risk. Manual mode ignores the rain (the farmer's decision).
// ===========================================================================
/*
const RAIN_THRESHOLD_MM = 2.0;    // mm accumulated in 24 h that cancel the cycle
const FROST_THRESHOLD_C = 1.0;    // forecast minimum in ºC that cancels the cycle

const blocks = msg.payload.list || [];
let totalRain = 0;
let minTemp = 99;

for (const b of blocks) {
    totalRain += (b.rain && b.rain["3h"]) ? b.rain["3h"] : 0;
    minTemp = Math.min(minTemp, b.main.temp_min);
}

The full example is a complete program — wiring header, setup and main loop — ready to adapt to your application.

Frequently asked questions

Which OpenWeather endpoint does the flow use?

The 5-day/3-hour forecast endpoint with cnt=8, which covers the next 24 hours and is available on the free tier. The API key is read from the OPENWEATHER_API_KEY environment variable of the Node-RED container, never stored in the flow.

What happens if the OpenWeather API is unreachable?

The http request node returns an error and the decision function never sets msg.regar, so the safe default is to skip the automatic cycle and notify by Telegram. The farmer can always force a manual cycle.

Can I change the thresholds without editing the flow?

In the example they are constants at the top of the function node for clarity. In production we move them to flow context or environment variables so the rain and frost thresholds are editable from the dashboard.

Related functionalities