Nested if and else statement not working

Hi all, I’m trying to write an irrigation rule with a number of weather based conditions. I’m having trouble getting a nested if and else statement to work. In particular the 2 day delay and re-test. Where am I going wrong with my syntax? If I remove the if and else statements with the timer all is good. How do I nest this statement?

rule "Automatic orchard watering"
    when
        Time cron "0 55 5 ? * SUN *"
    then
        if (Skip_Next_Orchard_Irrigation.state != ON){

            if (BOM_Day1_CurrentRainfallMm.state < 6) {            

                if (BOM_Day1_CurrentRainfallMm.sumSince(now.minusDays(5)) < 12) {    
                    Orchard.sendCommand (ON)
                    sendPushoverMessage(pushoverBuilder("Orchard watered").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                }
                else 
                    sendPushoverMessage(pushoverBuilder("Orchard watering DELAYED 2 days due rain in last 5 days").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                    createTimer(now.plusDays(2), [ |
                    if (BOM_Day1_CurrentRainfallMm.sumSince(now.minusDays(5)) < 12 && BOM_Day1_CurrentRainfallMm.state < 6) {    
                        val mqttActions = getActions("mqtt","mqtt:broker:MyMQTTBroker")
        		  	    mqttActions.publishMQTT("BlueIris/admin", "camera=Cam6&trigger")
                        Orchard.sendCommand (ON)
                        sendPushoverMessage(pushoverBuilder("Orchard watered").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                        }
                        ])
                    }
                    else
                        sendPushoverMessage(pushoverBuilder("DELAYED Orchard watering CANCELED due to rain").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))

            }
            else
                sendPushoverMessage(pushoverBuilder("Orchard watering skipped due to rain since 9am").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
        }
        else
            sendPushoverMessage(pushoverBuilder("Orchard watering manually skipped").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
            Skip_Next_Orchard_Irrigation.postUpdate (OFF)
end

As it stands there is a mismatch in your { and } sections

your DAY1_CurrentRainfallmm also has tailing brackets.

Can you explain your logic you want or wish to create here?, I’m having a hard time following the if statements and not grasping your intent. This feels like a CASE statement tree would be more appropriate.

Note that a fully written if-else looks like

if (condition) {
   do stuff
} else {
   do something else
}

This structure -

if (condition) {
   do stuff
} else 
   do something else
   do a third thing

is the equivalent of

if (condition) {
   do stuff
} else {
   do something else
}
do a third thing

i.e. the third thing is not part of the if-else and gets executed regardless, which is not I think what you intended.

Personally I always use the { } so that it’s clear to me what I intended when reading back later.

I’m still learning as I go. I’m not aware of what a CASE statement is.

My intent is as follows:
*At the cron time check to see if I have chosen to skip next scheduled watering (a switch item), if not
*Check if there has been less than 6mm of rain since 9am, if yes
*Check if the sum of the rainfall for the past 5 days is less than 12mm, if yes, water Orchard.
*If no wait 2 days then check sum of rainfall in past 5 days is less than 12mm and rainfall since 9am is less than 6mm, if yes water, if not end rule.

The pushover notifications alert me if watering has taken place or not and why.
The MQTT sends a command to trigger security camera to record for audio visual confirmation of watering, effectively confirming there hasn’t been a hardware failure.

I’m sure there is a more elegant way of achieving this but as I’m slowly learning this was the only way I could come up with.

Hi Rossko. I did try using curly brackets in my else statements during my fault finding but this did seem to help. Could have been my error. I’ll try agin. Until now I haven’t used multiple else statements so this could be why I’ve not had an issue until now.

I’ve editing as you have suggested but still have mismatched else error as below.

rule "Automatic orchard watering"
    when
        Time cron "0 55 5 ? * SUN *"
    then
        if (Skip_Next_Orchard_Irrigation.state != ON){

            if (BOM_Day1_CurrentRainfallMm.state < 6) {            

                if (BOM_Day1_CurrentRainfallMm.sumSince(now.minusDays(5)) < 12) {    
                    val mqttActions = getActions("mqtt","mqtt:broker:MyMQTTBroker")
    		  	    mqttActions.publishMQTT("BlueIris/admin", "camera=Cam6&trigger")
                    Orchard.sendCommand (ON)
                    sendPushoverMessage(pushoverBuilder("Orchard watered").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                }
                else {
                    sendPushoverMessage(pushoverBuilder("Orchard watering DELAYED 2 days due rain in last 5 days").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                    createTimer(now.plusDays(2), [ |
                    if (BOM_Day1_CurrentRainfallMm.sumSince(now.minusDays(5)) < 12 && BOM_Day1_CurrentRainfallMm.state < 6) {    
                        val mqttActions = getActions("mqtt","mqtt:broker:MyMQTTBroker")
        		  	    mqttActions.publishMQTT("BlueIris/admin", "camera=Cam6&trigger")
                        Orchard.sendCommand (ON)
                        sendPushoverMessage(pushoverBuilder("Orchard watered").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                        }
                        ])
                    
                    else{
                        sendPushoverMessage(pushoverBuilder("DELAYED Orchard watering CANCELED due to rain").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
                    }}

            }
            else{
                sendPushoverMessage(pushoverBuilder("Orchard watering skipped due to rain since 9am").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
            }
        }
        else{
            sendPushoverMessage(pushoverBuilder("Orchard watering manually skipped").withTitle("Irrigation system").withDevice("james_iphone").withSound("none"))
            Skip_Next_Orchard_Irrigation.postUpdate (OFF)
        }
end
2020-10-02 10:41:50.639 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'irrigation.rules' has errors, therefore ignoring it: [28,21]: mismatched input 'else' expecting '}'
[32,13]: mismatched input '}' expecting 'end'

There’s no matching closing } for that one, and there seems to be a hanging else after the timer with no if().

Thank you Rossko. The problem was the hanging else should have been within the timer - it blows to that if statement. I was blind to it. The rules file is now loading and I can now test my logic. :+1: