Type problems with a simple expression

Hi All,

I’m working with the latest stable version of OH and I’m trying to setup a timer to turn off my sprinklers after a variable delay period.

The period is based on the current temperature (from the ‘Number Day1AirTemperature’ item in the BOM plugin). After lots of testing I’ve got to this point:

var int current_temp = 0
var int delay = 0

current_temp = Day1AirTemperature.state
delay = current_temp / 10

This gives an error on the last line of code above:
Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_divide(int,int) on instance: null

Now I’m not sure what object this is referring too since it’s an expression, so I’m not sure what is ‘null’.

This is all very odd because ‘current_temp’ and ‘10’ both appear to be integers, so I though I’d add this line to test the type the variable.

logInfo(“my.rules”, “Type of current_temp =’”, typeof(current_temp), “’”)

Running this rule gives the error:
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Test’: current_temp

So it seems that you can’t get the typeof a variable…

What am I missing?

Let the DSL do it’s job. Don’t cast unless you have to and stay away from primitives…

var current_temp = 0
var delay = 0

States are never integers…

current_temp = Day1AirTemperature.getStateAs(DecimalType).intValue
delay = current_temp / 10

This will also work if Day1AirTemperature is defined as Number:Temperature.

You might want to read up on logging…

typeOf?

logInfo("my.rules", "Type of current_temp = {}", current_temp.class)

Welcome to the forum! Code fences (see #12) will help others help you!

The rules DSL is very limited. If you are just starting out, you will probably do best using a real scripting language…

1 Like

Hi Stuart,

Thanks for taking the time to responsd - so I’ve taken your advice and taken the types of my var definitions. Same error: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_divide(int,int) on instance: null

Thinking about the problem, I decided to move the var declaration for my temporary variable outside of the code block to the top of the rule. When I did this I get a different error: Couldn’t invoke ‘assignValueTo’ for feature JvmVoid: (eProxyURI: thomashome.rules#|::0.2.1.2.0.4.1.0.0::0::/1)

So the error appears to be linked to the scope of the declaration:

Rule …
then
var Delay_Period = 180

 if (...)
 {
        var current_temp = 0
        current_temp = Day1AirTemperature.state
        Delay_Period = current_temp / 10
 }

– This gives the error operator_divide(int,int) on instance: null

Rule …
then
var Delay_Period = 180
var current_temp = 0

 if (...)
 {
        current_temp = Day1AirTemperature.state
        Delay_Period = current_temp / 10
 }

– This gives the error Couldn’t invoke ‘assignValueTo’ for feature JvmVoid

I’ll continue to simplify the code until I can narrow down the problem.
BTW: Thanks for the pointer on logging…

Narrowed things down a little more:

Rule
then
var Delay_Period = 180
if (. . .)
{
var current_temp = 0
current_temp = Day1AirTemperature.state
Delay_Period = current_temp / 10
}

generates error: operator_divide(int,int) on the expression 'current_temp / 10'

But this works just fine:
...
Rule
then
var Delay_Period = 180
if (. . .)
 {
        var current_temp = 0
        current_temp = Day1AirTemperature.getStateAs(DecimalType).intValue
        Delay_Period = current_temp / 10
 }

Sounds right. A state object is not an int object.

As you are using a primitive, you have to care yourself for type conversion. If using

So to summarise:

  • A ‘var’ declaration creates a typeless variable - it takes on the type of the attribute assigned to it
  • If you set the initial type of a ‘var’ with a something like ‘int’, then this only sets the type until the next assignment (so generally a pretty pointless modifier)
  • Strange errors can occur in expressions if the type of the arguments has shifted, in my case assign the ‘.state’ cause my variable to take on the type of a State (which isn’t an int)
  • RuleDSL is typeless until it isn’t…

Thanks, this was helpful. I always struggle with types in rules. It’s even more confounding when things will cast to string in a log message, but not to a number type in order to do math.

I don’t think so.

var int myInt
myInt = 5 // no error, as 5 is integer
myInt = 5.5 // either an error, as 5.5 is not integer, or myInt == 5 
myInt = (5.5).intValue // no error

I’m pretty sure that myInt = 5.5 will result in an error, as myInt is a primitive.

Now:

var Integer myInt
myInt = 5 // no error, as 5 is integer
myInt = 5.5 // either an error, as 5.5 is not integer, or myInt == 5 
myInt = (5.5).intValue // no error

I’m pretty sure that this time myInt = 5.5 will result in myInt == 5, as myInt now is an object. But I did not test this.