CreateTimer in Lambda

Hi,

I have a lambda and I want to create a Timer in it.
I have done this before and in different rules this works just fine.
However in this case I can’t get it to work and I get errors.

The Designer and openhab shows this as a Problem:

createTimer(now.plusMinutes(30)) [|
    val anz = countItem30min.state as DecimalType
    if( anz > 0) countItem30min.postUpdate( anz - 1)
]

This is the resulting Error:

2015-11-06 10:37:13.603 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Wohnzimmer Balkontür Counter': The name '<XFeatureCallImplCustom>.plusMinutes(<XNumberLiteralImpl>)' cannot be resolved to an item or type.

Where is this Error coming from?

// Imports
import org.yoda.time.*
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import java.util.regex.Matcher
import java.util.regex.Pattern

import java.util.Date
import java.text.SimpleDateFormat




val org.eclipse.xtext.xbase.lib.Functions$Function2 CounterHandler = [
    org.openhab.core.items.GenericItem countItem,
    org.openhab.core.items.GenericItem countItem30min|
    

    //Counter erhöhen
    countItem.postUpdate( countItem.state as DecimalType + 1)
    val DateTimeType now = new DateTimeType()


    //30min Counter
    countItem30min.postUpdate( countItem30min.state as DecimalType + 1)

    createTimer(now.plusMinutes(30)) [|
        val anz = countItem30min.state as DecimalType
        if( anz > 0) countItem30min.postUpdate( anz - 1)
    ]

    //Dynamischen Namen
    val String nameraw = countItem.name
    
    val Pattern pattern_name    = Pattern::compile( "^ctr_(\\w+)$" )
    var Matcher matcher_name    = pattern_name.matcher( nameraw)
    matcher_name.find()
    val int count_name            = matcher_name.groupCount()
    
    if( count_name != 1) {
        logError( "Counter", String::format( "%10s | Groupcount doesn't match 1! Name: '%s'", "Counter", nameraw))
        return false
    }
    val String itemname = matcher_name.group(1)

    
    //Timestamp-History
    val DateTimeType ts0    = gTimestamp.members.findFirst[ name.equals( "ts0_" + itemname)].state as DateTimeType
    val DateTimeType ts1    = gTimestamp.members.findFirst[ name.equals( "ts1_" + itemname)].state as DateTimeType
    val DateTimeType ts2    = gTimestamp.members.findFirst[ name.equals( "ts2_" + itemname)].state as DateTimeType

    postUpdate( "ts3_"    + itemname, ts2.toString())
    postUpdate( "ts2_"    + itemname, ts1.toString())
    postUpdate( "ts1_"    + itemname, ts0.toString())
    postUpdate( "ts0_"    + itemname, now.toString())
    return false
]

Crazy Thing:

If I change the rule like that, everything seems to work:

val org.eclipse.xtext.xbase.lib.Functions$Function2 CounterHandler = [
    org.openhab.core.items.GenericItem countItem,
    org.openhab.core.items.GenericItem countItem30min|

    
    //30min Counter
    countItem30min.postUpdate( countItem30min.state as DecimalType + 1)

    createTimer(now.plusMinutes(30)) [|
        val anz = countItem30min.state as DecimalType
        if( anz > 0) countItem30min.postUpdate( anz - 1)
    ]

    
    //Counter erhöhen
    countItem.postUpdate( countItem.state as DecimalType + 1)
    val DateTimeType now = new DateTimeType()

Can anybody help me out here?

don’t you need to use a variable as the timer?

e.g.

var Timer mytimer

...

mytimer = createTimer(now.plusMinutes(30)) [|
        val anz = countItem30min.state as DecimalType
        if( anz > 0) countItem30min.postUpdate( anz - 1)
]

Hi Dan,
thanks for you reply. The variable is only needed, if you want to reuse your timer later again.
This is not the case, so I just left it away. :wink:

I think the way you did it is valid, but I’ve used a slightly different syntax for my createTimer calls.

createTimer(now.plusMinutes(30), [|
    // timer code
])

Perhaps the lambda is sensitive to this difference.

The problem is that the plusMinutes-Method from now seems not to be known.
It is not with the timer.

I know, but the only difference between your createTimer call and my working createTimer calls, which use now.plusMinutes, is that minor difference in syntax.

I think you might have overlooked something in my second post.
If I move the exact call before
new DateTimeType()
everything works fine. This somehow breaks the method which is totally crazy!
I don’t even remotely understand how this could be possible.

OK, I did miss something.

You are redefining “now” in your first rule to an org.openhab.library.types.DateTimeType. But the “now” that you can refer to without defining it, the one with plusMinutes(), and the one that createTimer is expecting, is a org.joda.time.DateTime.

You don’t have to create a variable to hold “now”. The Rules engine already makes it available to you.

The error is because DateTimeType doesn’t have the plusMinute method and even if it did it would probably be of the wrong type.

As much as openHAB got right, dealing with time in the rules is a mess. There are at least three different packages you need to use depending on your context (e.g. joda when dealing with “now” and scheduling things, java.util.Date when needing to format a date String, and org.openhab.library.types.DateTimeType when dealing with your Items).

1 Like