Getting error while trying to achieve simple timer

  • Platform information:
    • Hardware: raspberry pi
    • OS: OH2

i’m getting error while trying to achieve simple timer

items

Switch Timer01           "Timer 01"                    <time>          ["Switchable"]
Number Timer01RunFor     "Run For [%d]"                <time>
Number Timer01StopFor    "Stop For [%d]"               <time>

rules

rule "Timer01 Switch"
when
    Item Timer01 changed
then
    
    if(Timer01.state == ON){
        var Number RunFor = (Timer01RunFor.state as Number).intValue()
        if(RunFor<=0) RunFor = 20
        RunFor = RunFor * 1000

        var Number StopFor = (Timer01StopFor.state as Number).intValue()
        if(StopFor<=0) StopFor = 20
        StopFor = StopFor * 1000
        
        while(Timer01.state == ON){
            Timer01Group.members.forEach[ i | i.sendCommand(ON) ]
            logInfo("Timer01", "Timer01Group members Turned ON RunFor: " + RunFor.toString() + " min")
            Thread::sleep(RunFor);
            
            Timer01Group.members.forEach[ i | i.sendCommand(OFF) ]
            logInfo("Timer01","Timer01Group members Turned OFF StopFor: " + StopFor.toString() + " min")
            Thread::sleep(StopFor);
        }
    }
end

sitemap

Frame label="Light Timer" icon="light"{
				Switch item=Timer01 label="Light Timer"
				Setpoint item=Timer01RunFor minValue=1 maxValue=300 step=1
				Setpoint item=Timer01StopFor minValue=1 maxValue=600 step=1
			}

log

2019-11-19 10:49:26.338 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Timer01 Switch': An error occurred during the script execution: Could not invoke method: java.lang.Thread.sleep(long) on instance: null

2019-11-19 10:49:26.332 [INFO ] [lipse.smarthome.model.script.Timer01] - Timer01Group members Turned ON RunFor: 5000 min

2019-11-19 10:49:26.343 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Timer01 Switch': An error occurred during the script execution: Could not invoke method: java.lang.Thread.sleep(long) on instance: null

The Thread::sleep need an integer not a number:

        var int RunFor = (Timer01RunFor.state as Number).intValue()

What behaviour do you expect from this rule?
You will be potentially locking that thread for a long time and will run into problems

See: Why have my Rules stopped running? Why Thread::sleep is a bad idea

1 Like

This not solved
This is a very badly written timer
You will lock your rules out
You need to use timers not Thead::sleep
And certainly not a while loop

This should work. I hope… Just threw it rogether quickly

\\ At the TOP of the rules file
var timer myTimer = null
var myCommand = "ON"


\\In the rules file
rule "Timer01 Switch"
when
    Item Timer01 changed to ON
then
    var Number RunFor = (Timer01RunFor.state as Number).intValue()
    if(RunFor<=0) RunFor = 20
    var Number StopFor = (Timer01StopFor.state as Number).intValue()
    if(StopFor<=0) StopFor = 20
        
    if (myTimer === null) {
        myTimer = createTimer(now, [ |
            if (Timer01.state == ON) {
                if (myCommand == "ON") {
                    Timer01Group.members.forEach[ i | i.sendCommand(ON) ]
                    myCommand = "OFF"
                    myTimer.reschedule(now.plusSeconds(runFor)
                } else if (myCommand == "OFF") {
                    Timer01Group.members.forEach[ i | i.sendCommand(OFF) ]
                    myCommand = "ON"
                    myTimer.reschedule(now.plusSeconds(StopFor)
                }
            } else {
                myTimer.cancel()
                myTimer == null
            }
        ])
    }
end
3 Likes

thanks a lot :slight_smile: