Lambda in rule fails with 'Error during the execution of rule '{RuleName}': null'

Do you still see any potential problems with resource usage?

I don’t see anything that raises a red flag. This isn’t how I would implement it but I see nothing wrong with it. While it is good to keep track of your Timers so you can reference them later, I don’t see where you ever reference the timers though so you could probably eliminate doorRolloTimers.

There is no way to declare a void returning lambda, correct? I’d like to get rid of the boolean returns.

Use Procedures$Procedure6 instead of Functions$Function6.

Any chance to disable the warning regarding the recursive lambda parameter declaration

Not easily. You end up with an infinite recursion to do it normally. You can try to figure out a way to split the lambda into two and have one call the other but in this case I don’t really think that will work either.

This is one of those that you have to decide ho much it bothers you because fixing it will require a different approach.

For example, if I applied:

the rule could become:

var startedRollosLoop = now
val logName = "Rollos"

rule "Soor_Rollos_Night"
when
    Item vTimeOfDay changed
then
    // determine if we even need to do anything at all
    if(vTimeOfDay.state != "EVENING") return;
    if(Temperature_Today_Min.state >= 15 && Temperature_Tomorrow_Min.state >=15) return;

    logInfo(logName, "Forecast Temperature < 15°C, going to ANTI-CHILL mode (100) (Doors)")

    startedRollosLoop = now

    // Kick off the checking loop for each Rollershutter
    gRollos.members.forEach[ rollo |
        val timer = gTimers.members.findFirst[ t | t.name == rollo.name+"_Timer" ]
        timer.sendCommand(OFF) // kick off the retry loop
    ]
end

rule "Rollo Timer Expired"
when
    // Replace triggers with Member of gRollos received command OFF when running on 2.3+
    Item WZ_Terrassentuer_Rolladen_1_Level_Timer received command OFF or
    Item WSTerrassentuerRolladen_1_Level_Timer received command OFF
then
    val contact = gContacts.members.findFirst[ c | c.name == triggeringItem.name.replace("Timer", "Contact") ]

    // If contact is CLOSED, log and close the rollershutter    
    if(contact.state == CLOSE){
        val rolloName = triggeringItem.name.replace("_Timer", "")
        logInfo(logName, "Closing " + rolloName)
        sendCommand(rolloName, 100)
        return;
    }

    // contact is OPEN, have we been trying for 10 minutes?
    if(now.isAfter(startedRollosLoop.plusMinutes(10))) {
        logInfo(logName, contact.name + " was open after 10 minutes. Exiting")
        return;
    }

    // contact is OPEN and it has been less than 10 minutes, log and check again by resetting the Timer
    logInfo(logName, contact.name + " is still open, waiting before retrying ...")
    triggeringItem.sendCommand(ON)
end

Everything I did should be explained by the DP links above. If not let me know. Note that I just typed these in. There is likely to be a typo or two.

Theory of Operation:

When ever the time of day this rule runs.

We check to see if it is EVENING, if not we exit with nothing to do.

Then we check to see if today’s min and tomorrows min is greater equal to 15 and if so exit with nothing to do.

If we made it this far, we need to start the checking loop. Grab a timestamp for now and sendCommand(OFF) to the Expire Binding Timer Item associated with each rolloershutter Item. The Expire binding is set to expire="1m,command=OFF".

The OFF command immediately triggers the “Rollo Timer Expired” rule. This Rule implements the bulk of your old lambda.

Check to see if the contact associated with the Timer Item that triggered the Rule is CLOSED. If so log, close the rollershutter, and exit.

If the contact is OPEN and we have been trying for more than 10 minutes then log and exit.

If we made it this far, we need to try again in a minute, so start the Expire based Timer by sending command ON.