Complete watering system based on openHAB

I found the error, a constant got dropped when it was transposed. I’ve updated a few things as well updating the min/max temps to a QuantityType Number:Temperature.

import java.lang.Math

/** 
 * Rules for calculating reference evapotranspiration ETo for
 * grass using the Hargreaves equation
 * see http://www.civil.uwaterloo.ca/watflood/Manual/02_03_2.htm
*/


var double solar_const = 0.0820

var double latitude = XX.XXXX  //Latitude of location in decimal degrees

rule "Hargreaves ETo"  //evapotranspiration in mm / day
when
	Time cron "0 59 23 * * ?"		//runs just before midnight

then
	var double tmin = (Temp_Min.state as QuantityType<Number>).doubleValue
	var double tmax = (Temp_Max.state as QuantityType<Number>).doubleValue
	var tDiff = tmax - tmin			//difference between max and min temperatures
	var tmean = (tmax + tmin) / 2	//mean temperature
    var doy = now().getDayOfYear()
	var lat_rad = Math.toRadians(latitude)
	var sd = 0.409 * Math.sin(((2 * Math.PI / 365) * doy - 1.39).doubleValue())	// solar declination (rad)
	var sha = Math.acos((-Math.tan((lat_rad).doubleValue()) * Math.tan(sd.doubleValue())).doubleValue())  //sunset hour angle
	var irl = 1 + (0.033 * Math.cos(((2 * Math.PI / 365)* doy).doubleValue()))   //inverse relative distance earth-sun [dimensionless]
    //the next three lines break down the incoming solar energy equation so I could read it in my text editor
	var tmp2 = sha * Math.sin(lat_rad.doubleValue()) * Math.sin(sd.doubleValue())                   
	var tmp3 = Math.cos(lat_rad.doubleValue()) * Math.cos(sd.doubleValue()) * Math.sin(sha)  
	var Ra = (1440 / Math.PI) * solar_const * irl * (tmp2 + tmp3)  //incoming solar energy
	var hETo = 0.0023 * (tmean.doubleValue() + 17.8) * Math.pow(tDiff.doubleValue(),0.5) * 0.408 * Ra
	ETo.postUpdate(hETo.doubleValue())
end

Trying the above code with QuantityType returns this error:

2020-08-26 12:52:12.651 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Hargreaves ETo’: Could not cast 17.22 to org.eclipse.smarthome.core.library.types.QuantityType; line 27, column 21, length 38

Are you temperature items Number:Temperature? ie:

Number:Temperature Temp_Min
Number:Temperature Temp_Max

No they wern’t. That fixed it!

This is awesome. I ran yesterday’s values though it and compared the value returned vs the website i was using (ET - Farmwest)

Famwest returned 4.63mm and your code returned 4.44.

I like it lot! Thanks!

Hi @Michal_Szymanski ,
have you managed to migrate the rule to OH3?
I was trying to port starting with java.date etc, however it looks like a bigger task.
Currently i git stuck on [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'irrigation-6' failed: Text '2021-APRIL-WEDNESDAYT09:00:00' could not be parsed at index 5 in irrigation
and other things like empty command.
Have you managed to transform to OH3 or are you still running OH2?

EDIT: the error above is due to new ZoneDateTime function. Using:

var userStartTime = ZonedDateTime.now()

does the trick. However i need to find a way to manipulate the hour in userStartTime
to set the irrigation time accordingly. So basically a new version of:

//var ZonedDateTime userStartTime = parse(now.getYear() + "-" + now.getMonth.getValue() + "-" + now.getDayOfWeek.getValue() + "T" + WtrStartTime.state + ":00")

However the next error that follows is:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'irrigation-5' failed: The argument 'command' must not be null. in irrigation

Any thoughts?

Hi @pking ,

See this post. I use it for my irrigation system which is quite modified version

Hi @DarkoG ,

nice. Thanks for pointing me to it. Will check on it now.
Would you mind share your full rule as well or did you just fix the time issue?

EDIT: i tested with:

val userStartTime = parse(now.getYear() + "-" + now.getMonthValue() + "-" + now.getDayOfMonth() + "T" + WtrStartTime.state + ":00.000+01:00").withZoneSameInstant(ZoneId.systemDefault())
	

and get this similar error:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'irrigation-6' failed: Text '2021-4-28T09:00:00.000+01:00' could not be parsed at index 5 in irrigation

To be honest I’ve tried to migrate to 3.0, but I had many different problems e.g with InffluxDB and strange errors in log file. When I find a time I will make second attempt :slight_smile:

I guess I have a solution for time problem.
This is:

is creating a single digit value of the month.
In this case a “4”. However a leading 0 is required to get “04” for the month.

now.getMonthValue().toString()

does the trick. The rules runs now further down the lines. I’ll keep you updated on the progress

Here is my rule (this was my first ever rule in OpenHab when switching from Smarrthngs so I admit it could have been done better). I have rain sensor and Mi Flora sensor installed in the garden which is one of the conditions to check the start of the cyclus:

/*
 * Irrigation rules
 */
import java.util.Date
//import java.time.ZonedDateTime

var int maxNoWtrDays = 4	        		// maximum No water days
var java.time.ZonedDateTime lastWtrDate 	// Date last watering or rain
var Number minimumReqRainfall = 5         	// minimum required rainfall
var Number rainfallMm = 0.0			    	// Current day reain forecast 
var Number missingRainfall = 0.0           	// missing rainfall in mm 
var isWatering = false 						// watering active

// Define watering timers
var Timer tmrIrrigationTerrace_Start
var Timer tmrIrrigationTerrace_Stop
var Timer tmrIrrigationGardenHouse_Start
var Timer tmrIrrigationGardenHouse_Stop
var Timer tmrIrrigationEntrance_Start
var Timer tmrIrrigationEntrance_Stop
var Timer tmrIrrigationFront_Start
var Timer tmrIrrigationFront_Stop
var Timer tmrIrrigationDripHose_Start
var Timer tmrIrrigationDripHose_Stop
var Timer tmrIrrigationPump_Stop
var Timer tmrIrrigation_Stop

var String FallbackStartTime = "01:00"
var Number FallbackDurationSprinklersGardenHouse = 5
var Number FallbackDurationSprinklersTerrace = 5
var Number FallbackDurationSprinklersEntrance = 3
var Number FallbackDurationSprinklersFront = 5
var Number FallbackDurationDripHose = 30
var Number FallbackDurationFilterFlush = 1
var Number FallbackScaleFactor = 100
var Number FallbackMinimumReqRainfallCfg = 5
var Number FallbackMinimumSoilHumidity = 22


// Define logic variables
val OnOffType  ON_R  
val OnOffType  OFF_R 
// Debug 
val checkUserStartTime = true  
val checkWtrRainSensor = true  

// Initialise
rule "irrigation:initialise"
	when
		System started		
	then
		logInfo( "irrigation:initialise","====================================================-Initialise-============================================")
		ON_R = ON
		OFF_R = OFF
    	isWatering = false
		
		logInfo( "irrigation:initialise","Close valves")
    	itmIrrigationSprinklersTerraceCmd.sendCommand(OFF_R)
    	itmIrrigationSprinklersGardenHouseCmd.sendCommand(OFF_R) 
    	itmIrrigationSprinklersEntranceCmd.sendCommand(OFF_R)
		itmIrrigationSprinklersFrontCmd.sendCommand(OFF_R)
    	itmIrrigationDripHoseCmd.sendCommand(OFF_R) 
    	itmIrrigationPumpCmd.sendCommand(OFF_R)
		itmIrrigationRainwaterFilterFlushCmd.sendCommand(OFF_R)

		if(itmIrrigationStartTime.state==NULL) {
			itmIrrigationStartTime.sendCommand(FallbackStartTime)
			logInfo( "irrigation:initialise","itmIrrigationStartTime SET TO 						" + FallbackStartTime )
		} else {
			logInfo( "irrigation:initialise","itmIrrigationStartTime       						" + itmIrrigationStartTime.state + " min")
		}	

		if(itmIrrigationDurationSprinklersTerrace.state==NULL) {
			itmIrrigationDurationSprinklersTerrace.sendCommand(FallbackDurationSprinklersTerrace)
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersTerrace SET TO		"+ FallbackDurationSprinklersTerrace + " min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersTerrace       		" + itmIrrigationDurationSprinklersTerrace.state + " min")
		}
		if(itmIrrigationDurationSprinklersGardenHouse.state==NULL) {
			itmIrrigationDurationSprinklersGardenHouse.sendCommand(FallbackDurationSprinklersGardenHouse)
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersGardenHouse SET TO "+ FallbackDurationSprinklersGardenHouse +" min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersGardenHouse    	" + itmIrrigationDurationSprinklersGardenHouse.state + " min")
		}
		if(itmIrrigationDurationSprinklersEntrance.state==NULL) {
			itmIrrigationDurationSprinklersEntrance.sendCommand(FallbackDurationSprinklersEntrance)
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersEntrance SET TO 	" + FallbackDurationSprinklersEntrance  + " min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersEntrance       	" + itmIrrigationDurationSprinklersEntrance.state + " min")
		}
		if(itmIrrigationDurationSprinklersFront.state==NULL) {
			itmIrrigationDurationSprinklersFront.sendCommand(FallbackDurationSprinklersFront)
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersFront SET TO 		"+ FallbackDurationSprinklersFront +" min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationSprinklersFront       		" + itmIrrigationDurationSprinklersFront.state + " min")
		}
		if(itmIrrigationDurationDripHose.state==NULL) {
			itmIrrigationDurationDripHose.sendCommand(FallbackDurationDripHose)
			logInfo( "irrigation:initialise","itmIrrigationDurationDripHose SET TO 				" + FallbackDurationDripHose +" min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationDripHose       				" + itmIrrigationDurationDripHose.state + " min")
		}	
		if(itmIrrigationDurationFilterFlush.state==NULL) {
			itmIrrigationDurationFilterFlush.sendCommand(FallbackDurationFilterFlush)
			logInfo( "FILE", "itmIrrigationDurationFilterFlush: itmIrrigationDurationDripHose SET TO 	" + FallbackDurationFilterFlush + " min")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationDurationFilterFlush       			" + itmIrrigationDurationFilterFlush.state + " min")
		}
		if(itmIrrigationScaleFactor.state==NULL) {
			itmIrrigationScaleFactor.sendCommand(FallbackScaleFactor)
			logInfo( "irrigation:initialise","itmIrrigationScaleFactor SET TO 					" + FallbackScaleFactor + " %")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationScaleFactor       					" + itmIrrigationScaleFactor.state + " %")
		}			

		if(itmIrrigationMinimumReqRainfallCfg.state==NULL) {
			itmIrrigationMinimumReqRainfallCfg.sendCommand(FallbackMinimumReqRainfallCfg)
			logInfo( "irrigation:initialise","itmIrrigationMinimumReqRainfallCfg SET TO 		" + FallbackMinimumReqRainfallCfg + " mm")
		} else {
			logInfo( "irrigation:initialise","itmIrrigationMinimumReqRainfallCfg       			" + itmIrrigationMinimumReqRainfallCfg.state + " mm")
		}	

		if(itmMinimumSoilMoisture.state==NULL) {
			itmMinimumSoilMoisture.sendCommand(FallbackMinimumSoilHumidity)
			logInfo( "irrigation:initialise","itmMinimumSoilMoisture SET TO 		" + FallbackMinimumSoilHumidity + " %")
		} else {
			logInfo( "irrigation:initialise","itmMinimumSoilMoisture       			" + itmMinimumSoilMoisture.state + " %")
		}			

		logInfo( "irrigation:initialise","=========================== Irrigation parameters initialization =============================")
		logInfo( "irrigation:initialise","itmIrrigationAuto            							" + itmIrrigationAuto.state )
		logInfo( "irrigation:initialise","Rain Sensor      										" + WaterLeakDetectedRainSensor.state )
		logInfo( "irrigation:initialise","checkWtrRainSensor 									" + checkWtrRainSensor )
		logInfo( "irrigation:initialise","checkUserStartTime 									" + checkUserStartTime )
		logInfo( "irrigation:initialise","isWatering         									" + isWatering )
		logInfo( "irrigation:initialise","Water source is rain tank 							" + itmIrrigationFromRainTank.state )
		
end 

rule "irrigation:Manual initialise"
	when
		Item    test12     changed from OFF to ON 		
	then
		logInfo( "irrigation:Manual initialise","====================================================-Initialise-============================================")
                itmIrrigationStartTime.sendCommand(FallbackStartTime)
                logInfo( "irrigation:Manual initialise","itmIrrigationStartTime SET TO 						" + FallbackStartTime )
                itmIrrigationDurationSprinklersTerrace.sendCommand(FallbackDurationSprinklersTerrace)
                logInfo( "irrigation:Manual initialise","itmIrrigationDurationSprinklersTerrace SET TO		"+ FallbackDurationSprinklersTerrace + " min")
                itmIrrigationDurationSprinklersGardenHouse.sendCommand(FallbackDurationSprinklersGardenHouse)
                logInfo( "irrigation:Manual initialise","itmIrrigationDurationSprinklersGardenHouse SET TO "+ FallbackDurationSprinklersGardenHouse +" min")
                itmIrrigationDurationSprinklersEntrance.sendCommand(FallbackDurationSprinklersEntrance)
                logInfo( "irrigation:Manual initialise","itmIrrigationDurationSprinklersEntrance SET TO 	" + FallbackDurationSprinklersEntrance  + " min")
                itmIrrigationDurationSprinklersFront.sendCommand(FallbackDurationSprinklersFront)
                logInfo( "irrigation:Manual initialise","itmIrrigationDurationSprinklersFront SET TO 		"+ FallbackDurationSprinklersFront +" min")
                itmIrrigationDurationDripHose.sendCommand(FallbackDurationDripHose)
                logInfo( "irrigation:Manual initialise","itmIrrigationDurationDripHose SET TO 				" + FallbackDurationDripHose +" min")
                itmIrrigationDurationFilterFlush.sendCommand(FallbackDurationFilterFlush)
                logInfo( "FILE", "itmIrrigationDurationFilterFlush: itmIrrigationDurationDripHose SET TO 	" + FallbackDurationFilterFlush + " min")
                itmIrrigationScaleFactor.sendCommand(FallbackScaleFactor)
                logInfo( "irrigation:Manual initialise","itmIrrigationScaleFactor SET TO 					" + FallbackScaleFactor + " %")
                itmIrrigationMinimumReqRainfallCfg.sendCommand(FallbackMinimumReqRainfallCfg)
                logInfo( "irrigation:Manual initialise","itmIrrigationMinimumReqRainfallCfg SET TO 		" + FallbackMinimumReqRainfallCfg + " mm")
                itmMinimumSoilMoisture.sendCommand(FallbackMinimumSoilHumidity)
                logInfo( "irrigation:Manual initialise","itmMinimumSoilMoisture SET TO 		" + FallbackMinimumSoilHumidity + " %")
		logInfo( "irrigation:Manual initialise","=========================== Irrigation parameters initialization =============================")
		logInfo( "irrigation:Manual initialise","itmIrrigationAuto            							" + itmIrrigationAuto.state )
		logInfo( "irrigation:Manual initialise","Rain Sensor      										" + WaterLeakDetectedRainSensor.state )
		logInfo( "irrigation:Manual initialise","checkWtrRainSensor 									" + checkWtrRainSensor )
		logInfo( "irrigation:Manual initialise","checkUserStartTime 									" + checkUserStartTime )
		logInfo( "irrigation:Manual initialise","isWatering         									" + isWatering )
		logInfo( "irrigation:Manual initialise","Water source is rain tank 							" + itmIrrigationFromRainTank.state )
		
end 

rule "irrigation:Rain_sensor_rain_activated"
    when
	    Item WaterLeakDetectedRainSensor changed  to ON 
    then
    	logInfo( "irrigation:Rain_sensor_rain_activated","Rain detected, stopping watering if running")
    	EventHist.sendCommand("Rain sensor is wet")
    	itmIrrigationNotification_Proxy.sendCommand("STOP")
end

rule "irrigation:Rain_sensor_rain_deactivated"
    when
	    Item WaterLeakDetectedRainSensor changed to  OFF 
    then
   		logInfo( "irrigation:Rain_sensor_rain_deactivated","Rain sensor is dry")
    	EventHist.sendCommand("Rain sensor is dry")
end
    
// Sprinklers in auto 
rule "irrigation:Auto_ON" 
	when
		Item itmIrrigationAuto changed  to ON 
	then
		logInfo( "irrigation:auto_ON"," Automatic watering set")
		EventHist.sendCommand("Sprinklers system set to auto")
		itmIrrigationStartBtn.sendCommand(OFF)
		
end
	
// Sprinklers in manual 
rule "irrigation:auto_OFF" 
	when
		Item itmIrrigationAuto changed to OFF
	then
		logInfo( "irrigation:auto_ON"," Manual watering set")
		EventHist.sendCommand("Sprinklers system set to auto")
		itmIrrigationStartBtn.sendCommand(OFF)
		
end

// Manual watering 
rule "irrigation:Manual"
    when
	    Item itmIrrigationStartBtn received update 
    then
        logInfo( "irrigation:manual"," isWatering[" +isWatering+ "]" )
    	// if watering is on, it stops, otherwise it turns on watering
    	if (( isWatering == false )  &&  (itmIrrigationStartBtn.state	== ON) &&  (itmIrrigationAuto.state == OFF )) {
    		logInfo("irrigation:manual","Start watering, manual activation")
    		EventHist.sendCommand("Start watering, manual activation")
    		itmIrrigationNotification_Proxy.sendCommand("START")
    	} else if (( isWatering == true )  &&  (itmIrrigationStartBtn.state	 == OFF) &&  (itmIrrigationAuto.state	== OFF )) { 
    		logInfo("irrigation:manual","Stoping  watering, manual activation")
    		EventHist.sendCommand("Stoping  watering, manual activation")
    		itmIrrigationNotification_Proxy.sendCommand("STOP")
		}
    	if (itmIrrigationAuto.state	== ON ) { 
    		logInfo("irrigation:manual","System is in AUTO mode, manual opration not possible")
		}
end

// Controlling outputs
rule "irrigation:Commands"
	when 
		Item itmIrrigationNotification_Proxy received update
	then
		logInfo( "irrigation:Commands", "============== Irrigation commands ==========")
		var String msg = itmIrrigationNotification_Proxy.state.toString
    	
    	logInfo( "irrigation:Commands","Stoping watering if already started")
		logInfo( "irrigation:Commands","msg [" + msg + "]")

    	
    	// reset timers
		logInfo( "irrigation:Commands","WtrTimers")
		if(tmrIrrigationTerrace_Start !== null) tmrIrrigationTerrace_Start.cancel
		if(tmrIrrigationTerrace_Stop !== null) tmrIrrigationTerrace_Stop.cancel
		if(tmrIrrigationGardenHouse_Start !== null) tmrIrrigationGardenHouse_Start.cancel
		if(tmrIrrigationGardenHouse_Stop !== null) tmrIrrigationGardenHouse_Stop.cancel
		if(tmrIrrigationEntrance_Start !== null) tmrIrrigationEntrance_Start.cancel 
		if(tmrIrrigationEntrance_Stop !== null) tmrIrrigationEntrance_Stop.cancel 
		if(tmrIrrigationFront_Start !== null) tmrIrrigationFront_Start.cancel
		if(tmrIrrigationFront_Stop !== null) tmrIrrigationFront_Stop.cancel
		if(tmrIrrigationDripHose_Start !== null) tmrIrrigationDripHose_Start.cancel
		if(tmrIrrigationDripHose_Stop !== null) tmrIrrigationDripHose_Stop.cancel
		if(tmrIrrigation_Stop !== null) tmrIrrigation_Stop.cancel
		if(tmrIrrigationPump_Stop !== null) tmrIrrigationPump_Stop.cancel
		
		ON_R = ON
		OFF_R = OFF

		// Set last watering date
    	var String WaterNowTime = String::format( "%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:00.000+01:00[Europe/Brussels]", new Date() )
    	logInfo( "irrigation:Commands","WaterNowTime[" + WaterNowTime + "]")

		if (msg == "STOP") {
			logInfo( "irrigation:Commands","send OFF commands")
    		itmIrrigationSprinklersTerraceCmd.sendCommand(OFF_R)
    		itmIrrigationSprinklersGardenHouseCmd.sendCommand(OFF_R) 
    		itmIrrigationSprinklersEntranceCmd.sendCommand(OFF_R)
			itmIrrigationSprinklersFrontCmd.sendCommand(OFF_R)
    		itmIrrigationDripHoseCmd.sendCommand(OFF_R) 
    		itmIrrigationPumpCmd.sendCommand(OFF_R)
			itmIrrigationRainwaterFilterFlushCmd.sendCommand(OFF_R)

			// Idle (not watering)
    		isWatering = false
	    	sendNotification("xxxxx@gmail.com", "Garden watering stopped","rain","Info")
			itmIrrigationLastDate.sendCommand(now.toLocalDateTime().toString() + "+01:00[Europe/Brussels]")

		}

    	// Start watering
    	if (msg == "START") {
			    	
	    	logInfo( "irrigation:Commands","starting watering")
	    	sendNotification("xxxxx@gmail.com", "Garden watering started","rain","Info")
	    	
			// set watering flag
			isWatering = true
				    			
    		// Assign duration from items
    		var Number DurationSprinklersTerrace = itmIrrigationDurationSprinklersTerrace.state as DecimalType
    		var Number DurationSprinklersGardenHouse  = itmIrrigationDurationSprinklersGardenHouse.state as DecimalType
    		var Number DurationSprinklersEntrance  = itmIrrigationDurationSprinklersEntrance.state as DecimalType
    		var Number DurationSprinklersFront  = itmIrrigationDurationSprinklersFront.state as DecimalType
    		var Number DurationDripHose  = itmIrrigationDurationDripHose.state as DecimalType

    		var DateTimeType WateringStartTime = DateTimeType.valueOf(now.toLocalDateTime().toString())
    		var DateTimeType WateringEndTime = DateTimeType.valueOf(now.toLocalDateTime().toString())		
    
    	    // Set last watering date
			itmIrrigationLastDate.sendCommand(now.toLocalDateTime().toString() + "+01:00[Europe/Brussels]")
        
    		// Aplying correction factor
    		var Number scaleFactor = itmIrrigationScaleFactor.state as DecimalType
    		
    		var int wtrSprinklersTerraceTime = ((DurationSprinklersTerrace * scaleFactor) / 100).intValue
    		var int wtrSprinklersGardenHouseTime  = ((DurationSprinklersGardenHouse  * scaleFactor) / 100).intValue
    		var int wtrSprinklersEntranceTime  = ((DurationSprinklersEntrance  * scaleFactor) / 100).intValue
    		var int wtrSprinklersFrontTime  = ((DurationSprinklersFront  * scaleFactor) / 100).intValue
    		var int wtrDripHoseTime  = ((DurationDripHose  * scaleFactor) / 100).intValue

			//Calculate start delays in seconds
    		var int DelayedStartSprinklersGardenHouse = wtrSprinklersTerraceTime * 60
    		var int DelayedStartSprinklersEntrance = DelayedStartSprinklersGardenHouse + wtrSprinklersGardenHouseTime * 60
    		var int DelayedStartSprinklersFront = DelayedStartSprinklersEntrance + wtrSprinklersEntranceTime * 60
    		var int DelayedStartDripHose = DelayedStartSprinklersFront + wtrSprinklersFrontTime * 60
			
			//Check if the source is rain water tank
			if (itmIrrigationFromRainTank.state == ON) DelayedStartDripHose = 0
    		
			//Calculate stop delays in seconds
    		var int DelayedStopSprinklersTerrace = DelayedStartSprinklersGardenHouse + 2
    		var int DelayedStopSprinklersGardenHouse = DelayedStartSprinklersEntrance +2
    		var int DelayedStopSprinklersEntrance = DelayedStartSprinklersFront + 2
			var int DelayedStopSprinklersFront = DelayedStartDripHose + 2
			var int DelayedStopDripHose = DelayedStartDripHose + wtrDripHoseTime * 60
			var int DelayedStopPump = 0
			
			//Check if the source is rain water tank
			if (itmIrrigationFromRainTank.state == ON) {
				DelayedStopSprinklersFront = DelayedStartSprinklersFront + wtrSprinklersFrontTime * 60
				DelayedStopDripHose = DelayedStopSprinklersFront + wtrDripHoseTime * 60
				DelayedStopPump = DelayedStopSprinklersFront

				if (DelayedStopSprinklersFront == 0) {
					DelayedStopPump = DelayedStopDripHose - 120
				}
			}

    		logInfo( "irrigation:Commands","DurationSprinklersTerrace " + DurationSprinklersTerrace + " minutes")
    		logInfo( "irrigation:Commands","DurationSprinklersGardenHouse  " + DurationSprinklersGardenHouse+ " minutes")
    		logInfo( "irrigation:Commands","DurationSprinklersEntrance  " + DurationSprinklersEntrance + " minutes")
    		logInfo( "irrigation:Commands","DurationSprinklersFront  " + DurationSprinklersFront+ " minutes")
    		logInfo( "irrigation:Commands","DurationDripHose  " + DurationDripHose + " minutes")
			logInfo( "irrigation:Commands","scaleFactor   " + scaleFactor + " %")
			logInfo( "irrigation:Commands","wtrSprinklersTerraceTime  " + wtrSprinklersTerraceTime + " minutes")
			logInfo( "irrigation:Commands","wtrSprinklersGardenHouseTime   " + wtrSprinklersGardenHouseTime + " minutes")
			logInfo( "irrigation:Commands","wtrSprinklersEntranceTime   " + wtrSprinklersEntranceTime + " minutes")
			logInfo( "irrigation:Commands","wtrSprinklersFrontTime   " + wtrSprinklersFrontTime + " minutes")
			logInfo( "irrigation:Commands","wtrDripHoseTime   " + wtrDripHoseTime + " minutes")
			logInfo( "irrigation:Commands","Rain Sensor " + WaterLeakDetectedRainSensor.state )

			logInfo( "irrigation:Commands","DelayedStartSprinklersGardenHouse in " + DelayedStartSprinklersGardenHouse/60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStartSprinklersEntrance in " + DelayedStartSprinklersEntrance/60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStartSprinklersFront in " + DelayedStartSprinklersFront /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStartDripHose in " + DelayedStartDripHose /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopSprinklersTerrace in " + DelayedStopSprinklersTerrace /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopSprinklersGardenHouse in " + DelayedStopSprinklersGardenHouse /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopSprinklersEntrance in " + DelayedStopSprinklersEntrance /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopSprinklersFront in " + DelayedStopSprinklersFront /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopDripHose in " + DelayedStopDripHose /60 + " minutes")
    		logInfo( "irrigation:Commands","DelayedStopPump in " + DelayedStopPump /60 + " minutes")
			logInfo( "irrigation:Commands","Water source is rain tank :" + itmIrrigationFromRainTank.state )
			
			// Start sprinklers terrace
    		if (wtrSprinklersTerraceTime > 0) {
    			WateringEndTime = now.plusSeconds(DelayedStopSprinklersTerrace) 
				logInfo( "irrigation:Commands","Watering terrace starts " + WateringStartTime + ", finish " + WateringEndTime )
    			logInfo( "irrigation:Commands","itmIrrigationSprinklersTerraceCmd [ON_R]")
   				itmIrrigationSprinklersTerraceCmd.sendCommand(ON_R)
    			
    			tmrIrrigationTerrace_Stop= createTimer( now.plusSeconds(DelayedStopSprinklersTerrace)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersTerraceCmd[OFF_R]")
   					itmIrrigationSprinklersTerraceCmd.sendCommand(OFF_R)
    			]
    		}

			// Start sprinklers garden house
    		if (wtrSprinklersGardenHouseTime > 0) {
				WateringStartTime = now.plusSeconds(DelayedStartSprinklersGardenHouse)
    			WateringEndTime = now.plusSeconds(DelayedStopSprinklersGardenHouse)
    			logInfo( "irrigation:Commands","Watering garden house start " + WateringStartTime + ", finish " + WateringEndTime)
    			tmrIrrigationGardenHouse_Start= createTimer( now.plusSeconds(DelayedStartSprinklersGardenHouse)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersGardenHouseCmd[ON_R]")
   					itmIrrigationSprinklersGardenHouseCmd.sendCommand(ON_R)
    			]
    			
    			tmrIrrigationGardenHouse_Stop= createTimer( now.plusSeconds(DelayedStopSprinklersGardenHouse)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersGardenHouseCmd[OFF_R]")
   					itmIrrigationSprinklersGardenHouseCmd.sendCommand(OFF_R)
    			]
    		}

			// Start sprinklers entrance
    		if (wtrSprinklersEntranceTime > 0) {
				WateringStartTime = now.plusSeconds(DelayedStartSprinklersEntrance)
    			WateringEndTime = now.plusSeconds(DelayedStopSprinklersEntrance)
    			logInfo( "irrigation:Commands","Watering entrance start  " + WateringStartTime + ", finish " + WateringEndTime)
    			tmrIrrigationEntrance_Start= createTimer( now.plusSeconds(DelayedStartSprinklersEntrance)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersEntranceCmd[ON_R]")
   					itmIrrigationSprinklersEntranceCmd.sendCommand(ON_R)
    			]
    			
    			tmrIrrigationEntrance_Stop= createTimer( now.plusSeconds(DelayedStopSprinklersEntrance)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersEntranceCmd[OFF_R]")
   					itmIrrigationSprinklersEntranceCmd.sendCommand(OFF_R)
    			]
    		}

			// Start sprinklers front
    		if (wtrSprinklersFrontTime > 0) {
    			WateringStartTime = now.plusSeconds(DelayedStartSprinklersFront)
    			WateringEndTime = now.plusSeconds(DelayedStopSprinklersFront)
				logInfo( "irrigation:Commands","Watering entrance start  " + WateringStartTime + ", finish " + WateringEndTime)
    			tmrIrrigationFront_Start = createTimer( now.plusSeconds(DelayedStartSprinklersFront)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersFrontCmd[ON_R]")
   					itmIrrigationSprinklersFrontCmd.sendCommand(ON_R)
    			]
    			
    			tmrIrrigationFront_Stop = createTimer( now.plusSeconds(DelayedStopSprinklersFront)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationSprinklersFrontCmd[OFF_R]")
   					itmIrrigationSprinklersFrontCmd.sendCommand(OFF_R)
					//itmIrrigationPumpCmd.sendCommand(OFF_R)  
    			]
    		}

			//Start & stop pump
			if (DelayedStopPump > 0) {
				logInfo( "irrigation:Commands","itmIrrigationPumpCmd [ON_R]")
    			itmIrrigationPumpCmd.sendCommand(ON_R)
				tmrIrrigationPump_Stop = createTimer( now.plusSeconds(DelayedStopPump)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationPumpCmd[OFF_R]")
   					itmIrrigationPumpCmd.sendCommand(OFF_R)
				]
			}

			// Start drip hose (and depresurise pipe)
    		if (DelayedStopDripHose > 0) {
    			WateringStartTime = now.plusSeconds(DelayedStartDripHose)
    			WateringEndTime = now.plusSeconds(DelayedStopDripHose)
				logInfo( "irrigation:Commands","Watering drip hose start  " + WateringStartTime + ", finish " + WateringEndTime)
    			tmrIrrigationDripHose_Start = createTimer( now.plusSeconds(DelayedStartDripHose)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationDripHoseCmd[ON_R]")
   					itmIrrigationDripHoseCmd.sendCommand(ON_R)
    			]
    			
    			tmrIrrigationDripHose_Stop= createTimer( now.plusSeconds(DelayedStopDripHose)) [| 
    				logInfo( "irrigation:Commands","itmIrrigationDripHoseCmd[OFF_R]")
   					itmIrrigationDripHoseCmd.sendCommand(OFF_R)
    			]
    		}
  
			//sendPushoverMessage(pushoverBuilder("(2) Garden watering ended [" + WateringEndTime 
			//+ "]").withPriority(-2)) 
 
    		// End cyclus 
    		tmrIrrigation_Stop = createTimer(WateringEndTime) [| 
				itmIrrigationLastDate.sendCommand(now.toLocalDateTime().toString() + "+01:00[Europe/Brussels]")
    			logInfo( "irrigation:Commands","==== Watering ended  ====")
    			isWatering = false
    			EventHist.sendCommand("Garden watering ended")
				sendNotification("xxxxx@gmail.com", "Garden watering ended","rain","Info")
    		]

			 logDebug( "irrigation:Commands"," tmrIrrigation_Stop[" + tmrIrrigation_Stop + "]")
    	}
		
end 
	
// Main algorithm	
rule "irrigation:irrigation:Main_algorithm"
    when
	  Time cron "0 0 0/1 1/1 * ? *"   //Run every hour
//	  Time cron "0 0/5 * 1/1 * ? *"   // Test every 5 minutes
    then

	logInfo( "irrigation:Main_algorithm"," -START- ")

    // Check that the current time is the watering time and that the system is set to automatic watering
    // and whether to check the actual watering time (checkUserStartTime)

		if(itmIrrigationStartTime.state==NULL) {
			itmIrrigationStartTime.sendCommand(FallbackStartTime)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationStartTime SET TO 						" + FallbackStartTime )
		}	

		if(itmIrrigationDurationSprinklersTerrace.state==NULL) {
			itmIrrigationDurationSprinklersTerrace.sendCommand(FallbackDurationSprinklersTerrace)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationDurationSprinklersTerrace SET TO		" + FallbackDurationSprinklersTerrace + " min")
		}
		if(itmIrrigationDurationSprinklersGardenHouse.state==NULL) {
			itmIrrigationDurationSprinklersGardenHouse.sendCommand(FallbackDurationSprinklersGardenHouse)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationDurationSprinklersGardenHouse SET TO " + FallbackDurationSprinklersGardenHouse + " min")
		}
		if(itmIrrigationDurationSprinklersEntrance.state==NULL) {
			itmIrrigationDurationSprinklersEntrance.sendCommand(FallbackDurationSprinklersEntrance)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationDurationSprinklersEntrance SET TO 	" + FallbackDurationSprinklersEntrance  + " min")
		}
		if(itmIrrigationDurationSprinklersFront.state==NULL) {
			itmIrrigationDurationSprinklersFront.sendCommand(FallbackDurationSprinklersFront)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationDurationSprinklersFront SET TO 		"+ FallbackDurationSprinklersFront +" min")
		}
		if(itmIrrigationDurationDripHose.state==NULL) {
			itmIrrigationDurationDripHose.sendCommand(FallbackDurationDripHose)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationDurationDripHose SET TO 				" + FallbackDurationDripHose +" min")
		}	
		if(itmIrrigationDurationFilterFlush.state==NULL) {
			itmIrrigationDurationFilterFlush.sendCommand(FallbackDurationFilterFlush)
			logInfo( "FILE", "itmIrrigationDurationFilterFlush: itmIrrigationDurationDripHose SET TO 	" + FallbackDurationFilterFlush + " min")
		}
		if(itmIrrigationScaleFactor.state==NULL) {
			itmIrrigationScaleFactor.sendCommand(FallbackScaleFactor)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationScaleFactor SET TO 					" + FallbackScaleFactor + " %")
		}			
		if(itmIrrigationMinimumReqRainfallCfg.state==NULL) {
			itmIrrigationMinimumReqRainfallCfg.sendCommand(FallbackMinimumReqRainfallCfg)
			logInfo( "irrigation:Main_algorithm"," itmIrrigationMinimumReqRainfallCfg SET TO 		" + FallbackMinimumReqRainfallCfg + " mm")
		}			

	var NowMonth = now.getMonthValue()
	var NowDay = now.getDayOfMonth()

	if (NowMonth<10) {NowMonth = '0' + NowMonth}
	if (NowDay<10) {NowDay = '0' + NowDay}

	val userStartTime = parse(now.getYear() + "-" + NowMonth + "-" + NowDay + "T" + itmIrrigationStartTime.state + ":00.000+01:00[Europe/Brussels]").withZoneSameInstant(ZoneId.systemDefault())
	
	logInfo( "irrigation:Main_algorithm"," userStartTime             [" + userStartTime + "]")
	logInfo( "irrigation:Main_algorithm"," checkUserStartTime        [" + checkUserStartTime + "]")
	logInfo( "irrigation:Main_algorithm"," isWatering                [" + isWatering + "]")
	logInfo( "irrigation:Main_algorithm"," itmIrrigationAuto.state             [" + itmIrrigationAuto.state + "]")
	logInfo( "FILE", "irrigation:Main_algorithm: itmIrrigationLastDate.state             [" + itmIrrigationLastDate.state + "]")

    //Check the time hour by hour minute by minute, whether we are checking the set time. If the system is already watering, it does not check the conditions and does not water.
	if ( ( ( userStartTime.hour == now.getHour()  &&  userStartTime.minute == now.getMinute() ) || checkUserStartTime == false )
    	&& itmIrrigationAuto.state == ON && (isWatering == false)
    ) {
		if (itmIrrigationLastDate.state !== NULL) {
			lastWtrDate = parse(itmIrrigationLastDate.state.toString).withZoneSameInstant(ZoneId.systemDefault())
		} 
		if (itmIrrigationLastDate.state == NULL) {
			lastWtrDate = null
		}

		logInfo( "irrigation:Main_algorithm"," Rain Sensor state       	 [" + WaterLeakDetectedRainSensor.state + "]")
		logInfo( "irrigation:Main_algorithm"," Soil Moisture       		 [" + Miflora_Azalea_Moisture.state + "]")
		logInfo( "irrigation:Main_algorithm"," lastWtrDate               [" + lastWtrDate + "]")
		logInfo( "irrigation:Main_algorithm"," maxNoWtrDays              [" + maxNoWtrDays + "]")  
    	logInfo( "irrigation:Main_algorithm"," checkWtrRainSensor        [" + checkWtrRainSensor + "]")
    	logInfo( "irrigation:Main_algorithm"," checkUserStartTime        [" + checkUserStartTime + "]")
		//logInfo( "irrigation:Main_algorithm"," itmIrrigationMinimumReqRainfallCfg     [" + (itmIrrigationMinimumReqRainfallCfg.state as DecimalType).intValue + "]")
    	    	
	
		/*
		 *  Take the amount of water in mm that will potentially drop by the next morning in mm 
		 */

		rainfallMm = localTodayRainVolume.state  
		logInfo( "irrigation:Main_algorithm"," Getting wheather forecast [" + localTodayRainVolume.state + "]")
		

		if(  (rainfallMm >= 0 )) {
			//logInfo( "irrigation:Main_algorithm"," Getting wheather forecast [" + localTodayRainVolume.state + "]")
		} else {
			logInfo( "irrigation:Main_algorithm"," Cannot rain forecast - rainfallMm is 0 mm ")
			rainfallMm = 0
		} 		
				
		minimumReqRainfall = (itmIrrigationMinimumReqRainfallCfg.state as DecimalType).intValue

		logInfo( "irrigation:Main_algorithm","====================== Wheather forecast ============================ ")
		logInfo( "irrigation:Main_algorithm"," rainfallMm         [" + rainfallMm*1000 + "m]")
        logInfo( "irrigation:Main_algorithm"," minimumReqRainfall in mm [" + minimumReqRainfall + "]")
	
		// checking the condition of the rain sensor
		if ( WaterLeakDetectedRainSensor.state == OFF || checkWtrRainSensor==false ) {

			logInfo( "irrigation:Main_algorithm"," RainSensor is dry, check other conditions")
			
			//checking whether the expected amount of precipitation will be sufficient (divide by 1000 since the value from OpenWeatherMap is in meters)
			if (rainfallMm > minimumReqRainfall / 1000) {

			// rainfall in the next 24 hours should be sufficient
			// but I check how many days have not been watered, if more than maxNoWtrDays I water it
			
				if(lastWtrDate===null) {
					if (Miflora_Azalea_Moisture.state  < itmMinimumSoilMoisture.state){
						logInfo( "irrigation:Main_algorithm"," rainfall is sufficient but lastWtrDate is null, for safety starting watering")
						EventHist.sendCommand("Automatic watering has been activated ")
						itmIrrigationNotification_Proxy.sendCommand("START")
					}
				} else if(lastWtrDate.isBefore(now.minusDays(maxNoWtrDays))) {
					if (Miflora_Azalea_Moisture.state  < itmMinimumSoilMoisture.state){
						logInfo( "irrigation:Main_algorithm"," last watering date is more than [" +maxNoWtrDays+ "] days ago, starting watering")
						EventHist.sendCommand("Automatic watering has been activated ")
						itmIrrigationNotification_Proxy.sendCommand("START")
					}	
				} else {
					sendNotification("xxxxx@gmail.com", "No automatic watering, expected rainfall " + rainfallMm + "mm within the next 24 hours","rain","Info")
					logInfo( "irrigation:Main_algorithm","No automatic watering, expected rainfall " + rainfallMm + "mm within the next 24 hours")
				}
		
				
			} else {
				// the expected amount of precipitation within 24 hours is insufficient
				missingRainfall = minimumReqRainfall/1000 - rainfallMm 				//divide by 1000 since the value from OpenWeatherMap is in meters
				logInfo( "irrigation:Main_algorithm"," Missing [" + missingRainfall*1000 + "] mm rainfall")
				if(lastWtrDate===null) {
					if (Miflora_Azalea_Moisture.state  >= itmMinimumSoilMoisture.state){		
						logInfo( "irrigation:Main_algorithm"," lastWtrDate is null, for safety starting watering")
						EventHist.sendCommand("Automatic watering has been activated") 
						itmIrrigationNotification_Proxy.sendCommand("START")
					}	
				} else if(lastWtrDate.isAfter(now.minusHours(maxNoWtrDays*24-1))) {
					if (Miflora_Azalea_Moisture.state  >= itmMinimumSoilMoisture.state){		
						logInfo( "irrigation:Main_algorithm","last watering date is less than [" +maxNoWtrDays+ "] days ago and moisture is OK, postponing watering")
					} else {
						logInfo( "irrigation:Main_algorithm","last watering date is less than [" +maxNoWtrDays+ "] days ago but moisture is NOT OK, starting watering")
						EventHist.sendCommand("Automatic watering has been activated") 
						itmIrrigationNotification_Proxy.sendCommand("START")
					}
				} else {	
					logInfo( "irrigation:Main_algorithm"," last watering date is more than [" +maxNoWtrDays+ "] days ago, starting watering")
					EventHist.sendCommand("Automatic watering has been activated ")
					itmIrrigationNotification_Proxy.sendCommand("START")
				}	

			}	
			logInfo( "irrigation:Main_algorithm","======= End of Watering algorithm  ======= ")
		} else {
			// the sunroof sensor is on it's raining or raining
			itmIrrigationLastDate.sendCommand(now.toLocalDateTime().toString() + "+01:00[Europe/Brussels]") 	// set that there was rainfall / watering
			logInfo( "irrigation:Main_algorithm"," watering not started, RainSensor is wet - watering is not needed")
			sendNotification("xxxxx@gmail.com", "No automatic watering, rain sensor is wet","rain","Info")
			
		}	
	} else {
		logInfo( "irrigation:Main_algorithm"," not started. checkUserStartTime["  +checkUserStartTime+ "] itmIrrigationAuto.stat["
			+itmIrrigationAuto.state + "] isWatering[" +isWatering+ "] WaterLeakDetectedRainSensor.state[" + WaterLeakDetectedRainSensor.state + "]"
		)
	}
end

Hi @DarkoG ,

thanks for sharing. You are running OH3, correct?
I still get an error when using parts of your code:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'irrigation-6' failed: 'hour' is not a member of 'java.lang.String'; line 364, column 7, length 18 in irrigation

it relates to:

if ( ( ( userStartTime.hour == now.getHour()  &&  userStartTime.minute == now.getMinute() ) || checkUserStartTime == false )
    	&& itmIrrigationAuto.state == ON && (isWatering == false)

Any ideas why this?

EDIT: works with this line.

if ( ( ( userStartTime.hour == now.getHour()  &&  userStartTime.minute == now.getMinute() ) || checkUserStartTime == false )
    	&& WtrAuto.state == ON && (isWatering == false)
    )

Getting closer and closer… schedule is already running.
But as soon as it starts automatically based on scheduled time with the first line watering, it crashes:

2021-04-29 16:10:21.316 [INFO ] [org.openhab.core.model.script.FILE  ] - Wtr_starting_stoping: WtrValveLine[ON_R]

2021-04-29 16:10:21.318 [WARN ] [ore.internal.scheduler.SchedulerImpl] - Scheduled job failed and stopped

java.lang.reflect.UndeclaredThrowableException: null

	at com.sun.proxy.$Proxy279.apply(Unknown Source) ~[?:?]

	at org.openhab.core.model.script.actions.ScriptExecution.lambda$0(ScriptExecution.java:82) ~[?:?]

	at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$12(SchedulerImpl.java:166) ~[bundleFile:?]

	at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$1(SchedulerImpl.java:76) [bundleFile:?]

	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]

	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]

	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]

	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]

	at java.lang.Thread.run(Thread.java:834) [?:?]

Caused by: org.openhab.core.model.script.engine.ScriptExecutionException: The name '<unkown>' cannot be resolved to an item or type; line 0, column 0

	at org.openhab.core.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:141) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:992) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:955) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:236) ~[?:?]

	at org.openhab.core.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:216) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1206) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1136) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1082) ~[?:?]

	at org.openhab.core.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:862) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:232) ~[?:?]

	at org.openhab.core.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:216) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:459) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:240) ~[?:?]

	at org.openhab.core.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:216) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:202) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:47) ~[?:?]

	at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:30) ~[?:?]

	... 10 more

However manual activation works fine now.

Have you looked at the variable and item types? Maybe you have some type mismatch between your items and internal variables. I think I also had some problems with calculation of the timer start and stop and only conversion of the time in seconds worked back then. I didn’t change it since.

Hi @DarkoG ,
you mean between rules items and items created in items file?
I’ve read also that i could be the rules engine, loading too fast.
But the java error doenst really help much.

Sorry I can’t help.
Indeed, I referred to checking the data type definitions in your rule variables and items you might be using.
My rules are working but I know nothing about Java.
Good luck

Hi @DarkoG

thanks for the input. I might give your code also a try.

@Michal_Szymanski,
please find my current Version attached. It is still not finished, but maybe of use for you in case you want to migrate. Please note, that the rule engine in OH3 is a bit of a pain as it runs too fast and also the usage of “system started” is not supported anymore.
irrigation_oh3_v2.txt (28.0 KB)
I also noted, that persisatnce(mapdb) is not working in case the rule file has been loaded early.

1 Like

So you`ve got everything working on OH3? But what about mapdb persistence not available in OH3? Could you please post your entire setup (things, items, and so on)?

Mapdb is available in OH3 (just fell out of the online docs for unknown reasons).

Yes, everything is working on OH3. I didn’t have time to setup persistence yet so I do not know if it is working.
You can find my rules in the post above, I have 4 sprinkler zones, 1 drip hose, mi Flora humidity sensor and rain sensor. I can manually select the water source (drinking water or rain tank), this could be also automatic but I wanted to prevent the rain water polluting my drinking water so to switch the source I need to manually connect the right pipe/hose. My sprinkler valves are connected to rPi zero installed outside and talking to OH via MQTT. I don’t have any sitemaps or widgets (yet), I modify the things via the OH3 UI. What I still need to do i to create some fallback to the rPi that is connected to the sprinklers to close the valves and stop the pump if the communication to the OH is lost.

So the items files is (maybe some things are obsolete):

//Sprinkler system
    Switch                  itmIrrigationSprinklersTerraceCmd               "Sprinklers Terrace"                                        <rain>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationSprinklersTerraceCmd", expire="30m, command=OFF"}
    Switch                  itmIrrigationSprinklersGardenHouseCmd           "Sprinklers Garden House"                                   <rain>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationSprinklersGardenHouseCmd", expire="30m, command=OFF"}
    Switch                  itmIrrigationSprinklersEntranceCmd              "Sprinklers Entrance"                                       <rain>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationSprinklersEntranceCmd", expire="30m, command=OFF"}
    Switch                  itmIrrigationSprinklersFrontCmd                 "Sprinklers  Front"                                         <rain>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationSprinklersFrontCmd", expire="30m, command=OFF"}
    Switch                  itmIrrigationDripHoseCmd                        "Drip Hose"                                                 <rain>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationDripHoseCmd", expire="1h,command=OFF"}
    Switch                  itmIrrigationPumpCmd                            "Pump"                                                      <pump>          (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationPumpCmd",  expire="2h, command=OFF"}
    Switch                  itmIrrigationRainwaterFilterFlushCmd            "Filter Flush"                                              <softener>      (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationRainwaterFilterFlushCmd",  expire="5m, command=OFF"}
    Switch                  itmIrrigationPiRelay8Cmd                        "Relay 8"                                                   <switch>        (grpIrrigation)     ["Switch"]  {channel="mqtt:topic:sensor_reporter:chIrrigationPiRelay8Cmd"}
    Number                  itmIrrigationPiSensorReporterStatus             "Sensor Reporter Status"                                    <status>        (grpIrrigation)                 {channel="mqtt:topic:sensor_reporter:chIrrigationPiHealth"}


    String EventHist  // event history, used with Influxdb persistence 

    // Rain sensor - OPEN=wet, CLOSED=dry
    Switch                  itmIrrigationRainSensor                         "Rain sensor"                                               <rain>          (grpIrrigation)                 ["OpenState"]  
    Switch                  itmIrrigationStartBtn                           "Manual watering start"                                     <switch>        (grpIrrigation, grpSettings)    ["Switch"]   
    Switch                  itmIrrigationAuto                               "Watering automation"                                       <switch>        (grpIrrigation, grpSettings)    ["Switch"]
    Switch                  itmIrrigationFromRainTank                       "Water source is rain tank"                                 <switch>        (grpIrrigation, grpSettings)    ["Switch"]

    // Watering parameter
    String	                itmIrrigationStartTime     		                "Watering hour"	                 				            <calendar>  (grpIrrigation, grpSettings) 
    Number	                itmIrrigationDurationSprinklersTerrace 	    	"Watering duration - sprinklers terrace[%d min]"            <pressure>  (grpIrrigation, grpSettings) 
    Number          	    itmIrrigationDurationSprinklersGardenHouse 		"Watering duration - sprinklers garden house[%d min]"       <pressure>  (grpIrrigation, grpSettings) 
    Number	                itmIrrigationDurationSprinklersEntrance 		"Watering duration - sprinklers entrance[%d min]"           <pressure>  (grpIrrigation, grpSettings) 
    Number	                itmIrrigationDurationSprinklersFront		    "Watering duration - sprinklers front[%d min]"              <pressure>  (grpIrrigation, grpSettings) 
    Number          	    itmIrrigationDurationDripHose  		            "Watering duration - drip hose[%d min]"                     <pressure>  (grpIrrigation, grpSettings) 
    Number	                itmIrrigationDurationFilterFlush 		        "Filter flush duration [%d min]"                            <pressure>  (grpIrrigation, grpSettings) 

    Number	                itmIrrigationScaleFactor			            "Correction coefficient [%d %%]"  		                    <pressure>	                (grpIrrigation, grpSettings) 
    Number                  itmIrrigationMinimumReqRainfallCfg              "Minimum reqired rainfall [%d mm]"                          <pressure>	                (grpIrrigation, grpSettings) 
    String                  itmIrrigationLastDate                           "Last watering date [%s]"   			                    <humidity>                  (grpIrrigation) 
    String                  itmIrrigationNotification_Proxy                                                                                                         (grpIrrigation)     // START - start watering , STOP - stop watering 
    Number	                itmMinimumSoilMoisture			                "Minimum Soil moisture [%d %%]"  		                    <rain>	                (grpIrrigation, grpSettings) 

    //Health  "Sensor reporter Health"             
    Switch                  itmSprinklersPiSensorReporterHealth    "Sprinklers Pi Sensor reporter Health"   <status>        (grpIrrigation, grpHealth)  {expire="5m,command=OFF"}


//Mi Flora sensors
    Number:Illuminance      Miflora_Azalea_Light                            "Light Intensity [%d lx]"                                   <light>        (grpMiFloraAzalea)                   ["Measurement", "Light"]        { channel="mqtt:topic:AzaleaOutside:chLight" }
    Number:Dimensionless    Miflora_Azalea_Battery                          "Battery Charge [%d %%]"                                    <battery>      (grpMiFloraAzalea)                                                   { channel="mqtt:topic:AzaleaOutside:chBattery" }
    Number:Temperature      Miflora_Azalea_Temperature                      "Temperature [%.1f °C]"                                     <temperature>  (grpMiFloraAzalea, grpTemperature)   ["Measurement", "Temperature"]  { channel="mqtt:topic:AzaleaOutside:chTemperature" }
    Number                  Miflora_Azalea_Conductivity                     "Soil Fertility [%d µS/cm]"                                 <lawnmower>    (grpMiFloraAzalea)                   ["Measurement", "Point"]        { channel="mqtt:topic:AzaleaOutside:chConductivity" }
    Number:Dimensionless    Miflora_Azalea_Moisture                         "Soil Moisture [%d %%]"                                     <humidity>     (grpMiFloraAzalea)                   ["Measurement", "Humidity"]     { channel="mqtt:topic:AzaleaOutside:chMoisture" }

    //Mi Flora service health
    Switch  itmSprinklersPiMiFloraServiceHealth                             "Sprinklers Pi Mi Flora health"                             <status>        (grpMiFloraAzalea, grpHealth)  {expire="12h,command=OFF"}


Thanks for sharing, Darko. Will try to get your code working with my MegaD.

i still get
failed: Text ‘2021-7-25T14:00:00.000+01:00’ could not be parsed at index 5 in irriggation

val userStartTime = parse(now.getYear() + "-" + now.getMonthValue().toString() + "-" + now.getDayOfMonth() + "T" + WtrStartTime.state + ":00.000+01:00").withZoneSameInstant(ZoneId.systemDefault())