OH2: weird unhandled exception in rule (timer?)

Hello,

I tried to make a alarm script, but it throwas an unhandled exception:

2017-01-19 06:35:30.057 [ERROR] [org.quartz.core.JobRunShell ] - Job DEFAULT.2017-01-19T06:35:30.054+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | { logWarn(<XStringLiteralImpl>,<XStringLiteralImpl>) sendCommand(<XFeatureCallImplCustom>,<XNumberLiteralImpl>) <null>.timer15 = <XNullLiteralImplCustom> sendTelegram(<XStringLiteralImpl>,<XStringLiteralImpl>) } ] threw an unhandled Exception: java.lang.RuntimeException: The name '<unkown>' cannot be resolved to an item or type. at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:112)[130:org.eclipse.smarthome.model.script:0.9.0.201701140927] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1115)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1045)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:991)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:114)[130:org.eclipse.smarthome.model.script:0.9.0.201701140927] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:446)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:227)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29)[146:org.eclipse.xtext.xbase:2.9.2.v20160428-1452] at com.sun.proxy.$Proxy135.apply(Unknown Source)[:] at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:38)[130:org.eclipse.smarthome.model.script:0.9.0.201701140927] at org.quartz.core.JobRunShell.run(JobRunShell.java:202)[105:org.eclipse.smarthome.core.scheduler:0.9.0.201701140927] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)[105:org.eclipse.smarthome.core.scheduler:0.9.0.201701140927]

i think the relevant part in my rules is this:

//at +15 min timer15 = createTimer(now.plusMinutes(15), [| logWarn("Wecker","+15min") sendCommand(lichtwecker, 50) timer15 = null sendTelegram("daniel","Wecker +15min") ]) .

The complete .rules file:

[CODE]
import java.util.concurrent.locks.ReentrantLock
import org.eclipse.smarthome.core.library.types.DecimalType
import org.eclipse.smarthome.model.script.actions.Timer

var Timer timer1 = null
var ReentrantLock lock1 = new ReentrantLock()
var Timer timer10 = null
var Timer timer15 = null
var Timer timer20 = null
var Timer timer30 = null
var Timer timer35 = null

/rule "Initialization"
when
System started
then
postUpdate(weckerZeitStunde, 8)
postUpdate(weckerZeitMinute, 15)
postUpdate(weckerMontag, ON)
postUpdate(weckerDienstag, ON)
postUpdate(weckerMittwoch, ON)
postUpdate(weckerDonnerstag, ON)
postUpdate(weckerFreitag, ON)
postUpdate(weckerSamstag, OFF)
postUpdate(weckerSonntag, OFF)
end
/

rule "Weckzeit"
when
Item weckerZeitStunde changed or
Item weckerZeitMinute changed
then
// If the UI to change the Alarm time is clicked several times the code below
// is subject to race conditions. Therefore we make sure that all events
// are processed one after the other.
lock1.lock()
try {
var String msg = “”

// Copy the Alarm-Time from the UI to local variables
//var stunde = weckerZeitStunde.state as DecimalType
//var minute = weckerZeitMinute.state as DecimalType

// Combine the hour and minutes to one string to be displayed in the 
// user interface
if (weckerZeitStunde.state < 10) { msg = "0" } 
msg = msg + weckerZeitStunde.state.format("%d") + ":"

if (weckerZeitMinute.state < 10) { msg = msg + "0" }
msg = msg + weckerZeitMinute.state.format("%d")
postUpdate(weckerZeitMessage,msg)

// calculate the alarm time [min]
var int weckzeit1
weckzeit1 = (weckerZeitStunde.state as DecimalType).intValue * 60 + 
            (weckerZeitMinute.state as DecimalType).intValue
weckzeit1 = weckzeit1.intValue

// calculate current time [min]
var int jetzt1
jetzt1 = now.getMinuteOfDay
jetzt1 = jetzt1.intValue

// calculate the difference between the requested alarm time and 
// current time (again in minutes)  
var int delta1
delta1 = (weckzeit1 - jetzt1)
delta1 = delta1.intValue

// add one day (1440 minutes) if alarm time for today already passed
if (jetzt1 > weckzeit1) { delta1 = delta1 + 1440 }

// check if there is already an alarm timer; cancel it if present
if (timer1 != null) {
   timer1.cancel
   timer1 = null
}

// create a new timer using the calculated delta [min]
timer1 = createTimer(now.plusMinutes(delta1)) [|
    // This code will be executed if the timer triggers
    // ************************************************
    // check if alarm clock is armed for this weekday
    var Number day = now.getDayOfWeek
    if (((day == 1) && (weckerMontag.state == ON))     ||
        ((day == 2) && (weckerDienstag.state == ON))   ||
        ((day == 3) && (weckerMittwoch.state == ON))   ||
        ((day == 4) && (weckerDonnerstag.state == ON)) ||
        ((day == 5) && (weckerFreitag.state == ON))    ||
        ((day == 6) && (weckerSamstag.state == ON))    ||
        ((day == 7) && (weckerSonntag.state == ON))) {
            // The things to do if the alarm clock is enabled for this day of week: 
			logWarn("Wecker","Wecker triggered now")
			
			//at 0 min
			sendCommand(coffee, ON)
			sendTelegram("daniel","Wecker 0min")
			
			//at +10min 
			timer10 = createTimer(now.plusMinutes(10), [|
				logWarn("Wecker","+10min")
            	sendCommand(lichtwecker, 10)
            	timer10 = null
            	sendTelegram("daniel","Wecker +10min")
            ])            	
            
            //at +15 min	
            timer15 = createTimer(now.plusMinutes(15), [|
            	logWarn("Wecker","+15min")
            	sendCommand(lichtwecker, 50)
            	timer15 = null
            	sendTelegram("daniel","Wecker +15min")
			])
			
			//at +20 min	
            timer20 = createTimer(now.plusMinutes(20), [|
            	logWarn("Wecker","20min")
            	sendCommand(lichtwecker, 100)
            	timer20 = null
            	sendTelegram("daniel","Wecker 20min")
			])
			
			//at +30 min	
            timer30 = createTimer(now.plusMinutes(30), [|
            	logWarn("Wecker","+30min")
            	sendCommand(lichtwecker, 0)
            	timer30 = null
            	sendTelegram("daniel","Wecker +30min")
			])
			

			//at +35 min	
            timer35 = createTimer(now.plusMinutes(35), [|
            	logWarn("Wecker","+35min")
            	sendCommand(coffee, OFF)
            	timer35 = null
            	sendTelegram("daniel","Wecker +35min")
			])
			
       }
       // Re-Arm the timer to trigger again tomorrow (same time) 
       timer1.reschedule(now.plusHours(24))
    // ************************************************
    // Here the code ends that executes once the timer triggers 
    ]

} finally {
// release the lock - we are ready to process the next event
lock1.unlock()
}
end
[/CODE]

Each timer throwas an exception.
Any ideas?

thanks
Daniel

I’ve been working with timers (and recursive timers) quite a bit lately.

Most often when I encounter

   java.lang.RuntimeException: The name '<unkown>' cannot be resolved to an item or type.

the reason is that I have fed the rule a null or uninitialized value. OH leaves variables and undefined Items in an undefined state by default at startup. It looks like you do initialize various items at startup, be sure you haven’t missed anything, and check that your variables are also properly initialized if necessary.

Your code shows the OnStartup initialization section commented out – why is that?

because I added persistance, and the variables are restored on startup

Try using lichwecker.sendCommand(50)

Trying to have the timer do something after you have set it to null may have some odd effects also