Timer Rule Problem

Hi There

I’m having some issues with my timer rule, hope someone can help me out.

import org.openhab.model.script.actions.Timer

rule "Nilan Humidity OFF Forseret"
	when
        	Item Nilan_Input_RH changed
	then
		delayTimer = Timer.createTimer(now.plusSeconds(30))
		 {
       	        sendCommand(Nilan_Control_VentSet,2)
		sendCommand(Smarthouse_Motorventil, OFF)
       	        delayTimer = null 
		}
		

end

I’m getting this error, and have been trying to search for what this means

14:20:47.551 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Nilan Humidity OFF Forseret': 'createTimer' is not a member of 'java.lang.Class'; line 70, column 16, length 38

14:20:47.551 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Nilan Humidity ON Forseret': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.lib.NumberExtensions.operator_plus(java.lang.Number,java.lang.Number) on instance: null

Look at this Example.

The code to be performed after the time has run-out has to be placed within “[ |” and “]” instead of the curly brackets .

1 Like

After code change it still gives me this error:

15:03:08.240 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Nilan Humidity OFF Forseret': 'createTimer' is not a member of 'java.lang.Class'; line 72, column 16, length 176

You seem to have more in the rule file (at least 72 lines!) and the createTimer is defined as something else before!

1 Like

Yes you are right I have, but I can’t see that createTimer is defined before.

import java.util.Random

val String logNamePresence = "presence"
var Timer presenceTimer = null
var Timer timer = null
val resList = newArrayList("640/480", "320/240", "480/360")
val urlList = newArrayList("http://www.fillmurray.com", "http://www.fillmurray.com/g",
                 "http://www.placecage.com", "http://www.placecage.com/c", "http://www.placecage.com/g")
val Random random = new Random()
var Timer delayTimer = null



rule "Humidity Average Nilan Inlet "
when
    Item Nilan_Input_RH received update
then
    Nilan_Input_RH_Avrg.postUpdate(Nilan_Input_RH.averageSince(now.minusHours(0.5)))
end



rule "Nilan Udluftning Max Speed Kl 06.00 & 18.00 hver Dag"
	when
	Time cron "0 00 06 * * ?"
	or
	Time cron "0 00 18 * * ?"
	then
	sendCommand(Nilan_Control_VentSet, 4)
	
end

rule "Nilan Udluftning Normal Speed Kl 07.30 & 20.00 hver Dag"
	when
	Time cron "0 30 07 * * ?"
	or
	Time cron "0 00 20 * * ?"
	then	
	sendCommand(Nilan_Control_VentSet, 2)
	
end







rule "Nilan Humidity ON Forseret"
	when
        	Item Nilan_Input_RH changed
	then
		var Number Humidity=(Nilan_Input_RH_Avrg.state)
		Humidity=Humidity+0.1
		Nilan_Input_RH_Trig.postUpdate (Humidity)
		if(Nilan_Input_RH.state >= Nilan_Input_RH_Trig.state){
		sendCommand(Nilan_Control_VentSet,4)
		sendCommand(Smarthouse_Motorventil, ON)
		}

end



rule "Nilan Humidity OFF Forseret"
	when
        	Item Nilan_Input_RH changed


	then
	    if(delayTimer == null) {
		delayTimer = Timer.createTimer(now.plusSeconds(30), [|
		   Nilan_Control_VentSet.sendCommand(2)
		   Smarthouse_Motorventil.sendCommand(OFF)
       	        delayTimer = null 
       		 ])

		 }
	else {
        delayTimer.reschedule(now.plusSeconds(timeoutMinutes))
    }
       	        
		
		

end
import org.openhab.model.script.actions.Timer

var Timer delayTimer = null


rule "Nilan Humidity OFF Forseret"
when
  Item Nilan_Input_RH changed
then
  delayTimer = createTimer(now.plusSeconds(30)) [|
  sendCommand(Nilan_Control_VentSet,2)
  sendCommand(Smarthouse_Motorventil, OFF)
  delayTimer = null 
  ]
end
1 Like

Fresh eyes :slight_smile:

Thanks so much, works perfect …

1 Like
import org.openhab.model.script.actions.Timer //this import is only needed in openHAB1

var Timer delayTimer = null
val int timeoutMinutes = 30  //timeoutMinutes wasn't defined yet!

rule "Nilan Humidity OFF Forseret"
when
    Item Nilan_Input_RH changed
then
    if(delayTimer == null) {
        delayTimer = createTimer(now.plusSeconds(30), [|
            Nilan_Control_VentSet.sendCommand(2)
            Smarthouse_Motorventil.sendCommand(OFF)
            delayTimer = null 
        ])
    }
    else {
        delayTimer.reschedule(now.plusSeconds(timeoutMinutes))
    }
end

should also work. In fact, it’s way better to use the methods [Item.sendCommand(value)] instead of actions [sendCommand(item,value)] (see sendCommand() Documentation and http://docs.openhab.org/configuration/rules-dsl.html#sendcommand-method-vs-action)
It’s always a good Idea to check if the timer is initialized.
I don’t understand the difference between createTimer(int) [| ] and createTimer(int,[| ]) but in the end both are ok.

The error in first place was the Timer. before createTimer, this is not allowed in the rules DSL.

1 Like

From the xtend docs:

When a method call’s last parameter is a lambda it can be passed right after the parameter list. For instance if you want to sort some strings by their length, you could write :

Collections.sort(someStrings) [ a, b |
  a.length - b.length
]

which is just the same as writing

Collections.sort(someStrings, [ a, b |
  a.length - b.length
])

Since you can leave out empty parentheses for methods which get a lambda as their only argument, you can reduce the code above further down to:

textField.addActionListener [
  textField.text = "Something happened!"
]

So ultimately both versions are the same. It is just a little bit of what is often called “syntactic sugar.” I personally prefer passing the lambda inside the parens as an argument rather than after because it makes it more explicit that the lambda is an argument to the function and nothing magic is going on.

2 Likes

Would there be a way to have a countdown timer shown on my site map?

In the below rule, I want to have the delayTimer remaining time shown - someone who can help me ?

rule "Nilan Humidity OFF Forseret"
	when
        	Item Nilan_Control_VentSet changed from 2 to 4 

	then
		
 		delayTimer = createTimer(now.plusMinutes(20)) [|
  		sendCommand(Nilan_Control_VentSet, 2)
  		sendCommand(Smarthouse_Motorventil, OFF)
 		delayTimer = null 
 	        ]
end

It’s not easy but others have posted examples on the forum.

The trick of it is you need to have a timer that only sleeps for a second, updates a Number Item with the total amount of time remaining, then gets recreated to sleep for another second.

1 Like

Thanks for your hint, I got it working :slight_smile:

Quite difficult to achieve this, but definitely worth it.

1 Like