It might be useful to filter on those Items first and generate a warning if there is one or more Items with a null historic state. It would be a separate line before this one.
Hi, I’ve tried version 0.2.11 but still get a flood of exceptions:
2020-01-09 07:38:32.438 [ERROR] [org.quartz.core.JobRunShell ] - Job DEFAULT.Timer 189 2020-01-09T07:38:32.436+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@19ffc97 (conditionalExpression: false)
} ] threw an unhandled Exception:
java.lang.NullPointerException: null
at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:65) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:140) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:954) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:235) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:857) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1205) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1135) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:237) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:469) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:255) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy552.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [bundleFile:?]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
2020-01-09 07:38:32.438 [ERROR] [org.quartz.core.JobRunShell ] - Job DEFAULT.Timer 190 2020-01-09T07:38:32.438+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@19ffc97 (conditionalExpression: false)
} ] threw an unhandled Exception:
java.lang.NullPointerException: null
at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:65) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:140) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:954) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:235) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:857) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1205) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1135) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:237) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:469) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:255) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy552.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [bundleFile:?]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
2020-01-09 07:38:32.461 [ERROR] [org.quartz.core.ErrorLogger ] - Job (DEFAULT.Timer 189 2020-01-09T07:38:32.436+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@19ffc97 (conditionalExpression: false)
} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [bundleFile:?]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
Caused by: java.lang.NullPointerException
at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:65) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:140) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:954) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:235) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:857) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1205) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1135) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:237) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:469) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:255) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy552.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[?:?]
... 1 more
2020-01-09 07:38:32.488 [ERROR] [org.quartz.core.ErrorLogger ] - Job (DEFAULT.Timer 190 2020-01-09T07:38:32.438+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@19ffc97 (conditionalExpression: false)
} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [bundleFile:?]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
Caused by: java.lang.NullPointerException
at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:65) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:140) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:954) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:235) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:857) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1205) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1135) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:237) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:469) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:255) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy552.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[?:?]
... 1 more
If I can help you with adding some extra logging, just let me know and I’ll add
UPDATE 9 Jan 10:43 : After running for a few hours the exceptions seem to be gone now, only INFO statements are logged. I’ll monitor for a while to see how it behaves.
Thanks for your support already, much appreciated.
These null errors you can ignore. When you saved the rule file (I mean when openHAB reload the rule file), the existing timer items of the previous file still exists.
But when they run (timer went off) the environment in which they were created, doesn’t exist anymore.
With other word, they are ghost timers and thus creating errors of null.
If you look closely, the null expection is now at org.eclipse.smarthome.model.script.engine.ScriptError.<init>(ScriptError.java:65) ~[?:?]
instead of at org.eclipse.smarthome.model.persistence.extensions.PersistenceExtensions.historicState(PersistenceExtensions.java:163) ~[?:?]
Good idea!
This was for now a quick and dirty fix. If it is null
it wil convert to 0. VSCode will give you a warning if you do the follow:
val temp = (null as Number)?.doubleValue
The warning is:
Null-safe call of primitive-valued feature doubleValue, default value 0 will be used
But it’s nicer to catch the null ad generate a warning as you suggested.
I also get some warnings when saving:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
However it doesn’t help where are these variables but I assume that there are Strings mainly where the type is not referred. I will try to clean them up…
I also made some cosmetic changes to the code (I think it is easier to read now for someone who is not that familiar with the code) if you like that I can create a PR on GitHub…
That’s strange, I’ve never seen these warnings. When/Where do you get them?
Yes, great, I’m trying to make to code available and readable for everyone, so be my guest and create a PR.
I get these warnings when I save the file.
Basically it happens because it can’t refer the return type from lambdas (for example when filtering for Items). I have tried adding the type to some of them (hope I got it right), but it I couldn’t find which 3 statement causes these.
2020-01-09 19:26:10.633 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Thermostat.rules', using it anyway:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
2020-01-09 19:26:10.697 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'Thermostat.rules'
I only can find this part of code
Heating_Mode.allMembers.forEach[i|
logInfo("svt2","retrigger {} with {}",i.name,i.state)
i.sendCommand(i.state as Number)
]
Here i
is unkown. There is a discusion here that talks about the same problem.
But strange enough, I’ve used the Design Pattern: Working with Groups in Rules post to create them and there is no mention of this problem in the example.
You were right, this is one of the three. I have added Number (before i) and I get one less warning.
I think the other 2 is where 2 implicit variable is used like:
val lastTemp = Temperatures.allMembers.filter[name.contains(room)].map[(historicState(new DateTime(lastCalcItem.state.toString),DATABASE)?.state as Number).doubleValue].reduce[s, v | s + v ] / Temperatures.allMembers.filter[name.contains(room)].size //get average of room temperatures (group) at the last calc time
Here s and v are not referred with type…
Most of the time the Rules DSL is able to figure out what type i
needs to be in that context. Sometimes it fails. This appears to be one of those cases. As Kristof indicates, the solution is to just provide the type before the i
so the Rules DSL doesn’t have to try, and fail, to guess what type it is.
However, @rkrisi, the type of i
is not a Number
, it’s a NumberItem
. Your change probably made the parse time error go away but it will fail at runtime.
Thanks I already wanted to say that I’m not sure that the item type is correct, I just wanted to check this is what causes this…
After adding any type to these two (with a reduce where s, v is used) these warnings are gone. However I’m not sure what is the type of s and v there…
If you can help me out with the type I can include these fixes also in the PR (which I have created)
The result of the previous map
is a List of Doubles. It would be far better to leave it as a Number than force it to be a primitive only to have it reconverted back to a Double (which is a Number) behind the scenes because you can’t store primitives in Lists. So s and v can be either Number or Double or probably even double would work.
But you should avoid the use of primitives as much as is possible. It greatly slows down the .rules file parsing. A few primitive references can add minutes on an RPi.
And I thought that using primitives are better in terms of resources (primitive type vs a complete Object…).
I will give a Double for them I think.
In Rules DSL primitives are the worst. Really, in Rules DSL you should avoid defining types in general unless you have to. When you define the types you force the parser to do a whole lot more work than it would otherwise because it has to check to make sure all the types it can know about at parse time work with that type. And for some reason, using primitives causes the engine to do even more work.
Even on a very fast machine, there are some expressions that can take a couple of minutes to parse when you force it to use primitives and less than a second when you let the engine figure out the type on it’s own.
When you let the engine wait until runtime before it has to care about the types of the variables, it can skip all the type checking that takes places at parse time and at runtime it has a lot more information so the checks are really easy there too.
Good to know.
But I can’t find (or I’m not looking in the right docs) what I get with the doubleValue
method.
For example:
var lastSetpoint = (lastSetpointState as Number).doubleValue
Will lastSetPoint
become a double (primitive) or a Double (Object)?
A primitive double. Documentation is here.
Though in that case it might get converted back to a BigDecimal/Double/Number. But if you have
var double lastSetpoint = ...
it will be a primitive double.
As a general Rule, just don’t worry about type unless you have to. Let everything just be what it happens to be, or if you need to (e.g. like the state from a Number Item) cast it to Number, no more. Only call xValue
when you absolutely have to (e.g. like in now.plusSeconds(lastSetpointState as Number).doubleValue)
).
Edited the openingspost to reference to new versions of the files at GitHub.
In my Oppinion This idea is Great because it make devices independent from vendor.
What we Need is a value to Compare these rules against vendor bindings. I thought About valve Opening in %*seconds as sum for whole days. Let me think about it
Okay,
i think i have an idea now:
i made some rules, that measure the usage of the thermostats.Note: In the Rules i do not address groups, but i plan to realize it due to simplyfing my code. Stay tuned.
What we need:
thermostat.items
Group gTemperatur_Ventil "Ventilöffnungen alle Heizungen" (gFF)
Group gTemperatur_Ventil_Persistence
Group gTemperatur_Ventil_Counter "Counter für Ventilöffnungen" (gFF,gTemperatur_Ventil_Persistence)
Group:Number:SUM gTemperatur_Ventil_Hourly "Counter für Ventilöffnungen daily" (gFF,gTemperatur_Ventil_Persistence)
Group:Number:SUM gTemperatur_Ventil_Daily "Counter für Ventilöffnungen daily" (gFF,gTemperatur_Ventil_Persistence)
Group:Number:SUM gTemperatur_Ventil_Weekly "Counter für Ventilöffnungen daily" (gFF,gTemperatur_Ventil_Persistence)
Group:Number:SUM gTemperatur_Ventil_Monthly "Counter für Ventilöffnungen daily" (gFF,gTemperatur_Ventil_Persistence)
//Groups
Number Wohnzimmer_Heizung_Links_Ventil_Counter "Zählt die Sekunden multipliziert mit der Öffnung entsprechend der Ventilöffnung" (gTemperatur_Ventil_Counter)
Number Wohnzimmer_Heizung_Links_Ventil_Counter_Daily "Zählt die Sekunden multipliziert mit der Öffnung entsprechend der Ventilöffnung" (gTemperatur_Ventil_Counter_Daily)
Number Wohnzimmer_Heizung_Links_Ventil_Counter_Hourly "Zählt die Sekunden multipliziert mit der Öffnung entsprechend der Ventilöffnung" (gTemperatur_Ventil_Counter_Hourly)
Number Wohnzimmer_Heizung_Links_Ventil_Counter_Weekly "Zählt die Sekunden multipliziert mit der Öffnung entsprechend der Ventilöffnung" (gTemperatur_Ventil_Counter_Weekly)
Number Wohnzimmer_Heizung_Links_Ventil_Counter_Monthly "Zählt die Sekunden multipliziert mit der Öffnung entsprechend der Ventilöffnung" (gTemperatur_Ventil_Counter_Monthly)
thermostat.rules
rule "WZ Heizung links an"
when
Member of gTemperatur_Ventil changed
then
val devicename = triggeringItem.name.toString
val devicename_Counter = devicename + "_Counter"
val devicename_Counter_item = gTemperatur_Ventil_Counter.members.findFirst[ d | d.name == devicename_Counter ]
val lastOpen = triggeringItem.previousState(true).timestamp.time
if(triggeringItem.previousState(true).state!=0){
logInfo("Valve Opened", "Ventil letzter Change: " + lastOpen)
logInfo("Valve Opened", "Ventil now: " + now + " timestamp: " + now.millis)
val totalTime = now.millis - lastOpen
val totalTimeSec = totalTime / 1000
val ValveState = triggeringItem.previousState(true).state as DecimalType
val ValveStatePercent = ValveState * 0.01
val heatingCounter = ValveStatePercent * totalTimeSec
postUpdate(devicename_Counter_item,heatingCounter)
logInfo("Valve Opened", "Ventil war für X sekunden offen: " + triggeringItem.name + " Sekunden: " + totalTimeSec + " heatingcounter: " + heatingCounter +$
}
end
rule "Heizungen Verbraucherstatistik - hourly"
when
Time cron "0 0 0/1 1/1 * ? *"
then
logInfo("Valve Hourly", "Hourly Ventilstatus schreiben")
postUpdate(Wohnzimmer_Heizung_Links_Ventil_Counter_Hourly,Wohnzimmer_Heizung_Links_Ventil_Counter.sumSince(now.minusHours(1),"jdbc"))
postUpdate(Wohnzimmer_Heizung_Rechts_Ventil_Counter_Hourly,Wohnzimmer_Heizung_Rechts_Ventil_Counter.sumSince(now.minusHours(1),"jdbc"))
postUpdate(Kinderzimmer_Heizung_Ventil_Counter_Hourly,Kinderzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(1),"jdbc"))
postUpdate(Schlafzimmer_Heizung_Ventil_Counter_Hourly,Schlafzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(1),"jdbc"))
end
rule "Heizungen Verbraucherstatistik - daily"
when
Time cron "0 0 0 1/1 * ? *"
then
logInfo("Valve Hourly", "Daily Ventilstatus schreiben")
postUpdate(Wohnzimmer_Heizung_Links_Ventil_Counter_Daily,Wohnzimmer_Heizung_Links_Ventil_Counter.sumSince(now.minusHours(24),"jdbc"))
postUpdate(Wohnzimmer_Heizung_Rechts_Ventil_Counter_Daily,Wohnzimmer_Heizung_Rechts_Ventil_Counter.sumSince(now.minusHours(24),"jdbc"))
postUpdate(Kinderzimmer_Heizung_Ventil_Counter_Daily,Kinderzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(24),"jdbc"))
postUpdate(Schlafzimmer_Heizung_Ventil_Counter_Daily,Schlafzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(24),"jdbc"))
end
rule "Heizungen Verbraucherstatistik - weekly"
when
Time cron "0 0 0 ? * MON *"
then
logInfo("Valve Hourly", "Daily Ventilstatus schreiben")
postUpdate(Wohnzimmer_Heizung_Links_Ventil_Counter_Daily,Wohnzimmer_Heizung_Links_Ventil_Counter.sumSince(now.minusHours(168),"jdbc"))
postUpdate(Wohnzimmer_Heizung_Rechts_Ventil_Counter_Daily,Wohnzimmer_Heizung_Rechts_Ventil_Counter.sumSince(now.minusHours(168),"jdbc"))
postUpdate(Kinderzimmer_Heizung_Ventil_Counter_Daily,Kinderzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(168),"jdbc"))
postUpdate(Schlafzimmer_Heizung_Ventil_Counter_Daily,Schlafzimmer_Heizung_Ventil_Counter.sumSince(now.minusHours(168),"jdbc"))
end
thermostat.sitemap
Frame label="Heizungsverbrauch"
{
Text item=Wohnzimmer_Heizung_Links_Ventil_Counter_Hourly label="Hourly von WZ Heizung Links: [%s]"
Text item=Wohnzimmer_Heizung_Rechts_Ventil_Counter_Hourly label="Hourly von WZ Heizung Rechts: [%s]"
Text item=Kinderzimmer_Heizung_Ventil_Counter_Hourly label="Hourly von Kinderzimmerheizung: [%s]"
Text item=Schlafzimmer_Heizung_Ventil_Counter_Hourly label="Hourly von Schlafzimmerheizung: [%s]"
Text item=Wohnzimmer_Heizung_Links_Ventil_Counter_Daily label="Daily von WZ Heizung Links: [%s]"
Text item=Wohnzimmer_Heizung_Rechts_Ventil_Counter_Daily label="Daily von WZ Heizung Rechts: [%s]"
Text item=Kinderzimmer_Heizung_Ventil_Counter_Daily label="Daily von Kinderzimmerheizung: [%s]"
Text item=Schlafzimmer_Heizung_Ventil_Counter_Daily label="Daily von Schlafzimmerheizung: [%s]"
}
}```
How does it work?
the Rule calculates the seconds how long the valve did not stay at 0%. This value is multiplied with the percentage the value stood open. This way you get a rating that is updated to a counter. With the persistence rules you are able to display the usage for a period.
What can you do with all that values now? You can compare them to values that were generated from vendor solutions i.e. Homematic. Therefore you can see how many heating is needed to fulfill the requirements.
What is missing? I will implement a Method, that will measure the Delta over time to the Target temperature. This way you can measure the effectivity of your ruleset compared to other mechanisms.
For Example.
If you have a low valveusage and a low delta to target temperature , you can say that your method works pretty well. When a homematic solution has much worse values you can be glad
Best regards