[SOLVED] Unexpected results with Val math operators

I have been a little confused for some time that maths in OH seems too hard. all the different rules around casting, double equals versus treble equals and whether the equals is before of after the less-than all make for a less than simple world.

So I figgured I would start with a basic rule and test out some Voperators using VAR’s and found some basic issues that I could not fathom out.

Here is my test rule

val Number TestA = 0
val Number TestB = 1.2
val Number TestC = 1.2
val Number TestD = 2.5

// test rule that logs received state
rule "test on rule"
when
	Item Test received command ON
then
	logInfo("Test", "Command was " + receivedCommand.toString)
    
	// Maths operators
	if (TestA < TestB) {logInfo("Test","TestA < TestB")}
	if (TestA = TestB) {logInfo("Test","TestA = TestB")}
	if (TestA > TestB) {logInfo("Test","TestA > TestB")}
	if (TestA <= TestB) {logInfo("Test","TestA <= TestB")}	
	if (TestA < TestC) {logInfo("Test","TestA < TestC")}
	if (TestA = TestC) {logInfo("Test","TestA = TestC")}
	if (TestA > TestC) {logInfo("Test","TestA > TestC")}
	if (TestA <= TestC) {logInfo("Test","TestA <= TestC")}		
	if (TestA < TestD) {logInfo("Test","TestA < TestD")}
	if (TestA = TestD) {logInfo("Test","TestA = TestD")}
	if (TestA > TestD) {logInfo("Test","TestA > TestD")}
	if (TestA <= TestD) {logInfo("Test","TestA <= TestD")}	
end

Running the command test provides this output:

2018-06-03 15:05:58.280 [INFO ] [.eclipse.smarthome.model.script.Test] - Command was ON

2018-06-03 15:05:58.286 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA < TestB

2018-06-03 15:05:58.295 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestB

2018-06-03 15:05:58.304 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestC

2018-06-03 15:05:58.310 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA < TestD

2018-06-03 15:05:58.318 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestD

Hang on, thats not correct; its missing TestA < TestC output
If I change it so TestB and TestC defined values are different rather than the same then the output is correct. - strange

Can some try the same test on their OH (mine is version 2.2 stable and running on a RPi3.
Can anyone suggest why the output is actually expected?

I have seen some other issues by changing the values defined but figured I would start with this one and see what people suggest.

Regards

Paul

I got the same when using = (assignment operator) versus == (equality operator)
You should use == or if (TestA.equals(TestB))

This:

val Number TestA = 0
val Number TestB = 1.2
val Number TestC = 1.2
val Number TestD = 2.5

// test rule that logs received state
rule "test on rule"
when
        Item P01_Presence received command ON
then
        logInfo("Test", "Command was " + receivedCommand.toString)

        // Maths operators
        if (TestA < TestB) {logInfo("Test","TestA < TestB")}
        if (TestA == TestB) {logInfo("Test","TestA = TestB")}
        if (TestA > TestB) {logInfo("Test","TestA > TestB")}
        if (TestA <= TestB) {logInfo("Test","TestA <= TestB")}
        if (TestA < TestC) {logInfo("Test","TestA < TestC")}
        if (TestA == TestC) {logInfo("Test","TestA = TestC")}
        if (TestA > TestC) {logInfo("Test","TestA > TestC")}
        if (TestA <= TestC) {logInfo("Test","TestA <= TestC")}
        if (TestA < TestD) {logInfo("Test","TestA < TestD")}
        if (TestA == TestD) {logInfo("Test","TestA = TestD")}
        if (TestA > TestD) {logInfo("Test","TestA > TestD")}
        if (TestA <= TestD) {logInfo("Test","TestA <= TestD")}
end

produces the proper results:

==> openhab.log <==
2018-06-03 08:58:50.909 [INFO ] [.eclipse.smarthome.model.script.Test] - Command was ON
2018-06-03 08:58:50.915 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA < TestB
2018-06-03 08:58:50.924 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestB
2018-06-03 08:58:50.928 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA < TestC
2018-06-03 08:58:50.934 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestC
2018-06-03 08:58:50.938 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA < TestD
2018-06-03 08:58:50.944 [INFO ] [.eclipse.smarthome.model.script.Test] - TestA <= TestD

more info on:
Java Language Specification 15.20.1 & 15.21.1

I had a log entry in openhab.log when using the assignment operator: Assignment to final field since val (not var) is being used. Did you receive the same “validation issues” log entry? (I am on OH2.3.0)

My incorrect use of assignment ‘=’ rather than comparison ‘==’ now makes sense of the outcome.
I did get the validation log entry although it not scream ‘you should use var’ to me.

Thanks

Paul

You are right, the java error reports can be verbosy and obscure. We all get used to them eventually. Read the error statement especially the first two or three lines. They normally will give you an indication of what is wrong if you can make sense of it.

Unfortunately, all of these conventions are universal across pretty much all C like programming languages. So it may seem weird but it is a standard.

Some rules for the logic behind them which might help you make sense of things:

  • A single = always means assignement. So TestA = TestB means Assign the value of TestB to TestA. You should pretty much never see a single = in an if statement.

  • All of the equals comparisons will have at least two characters. So to test for equality you would use ==. Any modifiers to the equals (<, >, !) will always go first. So you have not equals !=, less than equals <=, greater than equal >= and never =!, =>, or =<. NOTE, in some lanuages those may represent other operators.

  • There is one special case which is specific to the Rules DSL where if you have null as one of the operands, you must use three equal signs ===. <skip to the next buttlen unless you want to learn the details why> In the Rules DSL when you call TestA == TestB behind the scenes it is calling TestA.equals(TestB). However, when null is one of the operands, because null isn’t an Object, there is no .equals method to call. Therefore you need to call === which is the identity operator. This operator means “are the two operands pointing to the same place in memory” meaning not only are the two equivilent, they are the same Object.

  • All the other boolean comparison operators are one character: <, >, !.

  • Not ! is a little weird in that if it is not used with = then it goes before the comparison you are trying to negate. if(!(TestA < TestB)). ! is more useful when you have a boolean saved to a variable !myBoolean.

Again, I’ll emphasize that none of the above is specific to Java or the Rules DSL. The operators work like this almost universally across most programming languges to some degree or other with the most variation being the not operator.

2 Likes

Thanks Rich, that is a really use full summary.