For Loop With Variable [Solved]

I am trying to control a Bionaire Fan with Openhab. To change the speed, I’m using this rule, which basically calculates how many times to send the IR code to get to the correct speed.

rule "Bionaire Speed"
    when
        Item BionaireSpeed changed
    then
        val prevstate=(BionaireSpeed.previousState.state as DecimalType)
        val currentstate=(BionaireSpeed.state as DecimalType)
        val reqclicks=currentstate-prevstate
        if (reqclicks < 0)
        {
        reqclicks=6+reqclicks
        }
        val i=1
        var boolean flag = true
        while(flag)
        {
        Bionaire_TransmitCommand.sendCommand("Speed")
        Thread::sleep(1000)
        if (i=>reqclicks)
        {
        flag=false
        }
end

It sends the code once, and then the log shows this:

19:03:26.085 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Bionaire Speed': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_doubleArrow(T,org.eclipse.xtext.xbase.lib.Procedures$Procedure1) on instance: null

Any ideas on how to do this properly, without the weird flag thing?
I tried using the tutorial here. Which doesn’t work, presumably because I have casted the wrong type.

There is a “}” missing at the end. I reformat it, then it is clear.

rule "Bionaire Speed"
    when
        Item BionaireSpeed changed
    then
        val prevstate=(BionaireSpeed.previousState.state as DecimalType)
        val currentstate=(BionaireSpeed.state as DecimalType)
        val reqclicks=currentstate-prevstate
        if (reqclicks < 0)
        {
              reqclicks=6+reqclicks
        }
        val i=1
        var boolean flag = true
        while(flag)
        {
             Bionaire_TransmitCommand.sendCommand("Speed")
             Thread::sleep(1000)
             if (i=>reqclicks)
             {
                   flag=false
             }
       } <==this one is missing!
end

Another hint. Maybe break; can end the while without the need of the flag check.

You need to increment i in the while loop or you will never get out of it.

Yeah, i had fixed the } after i posted; sorry. Also, this wasn’t the first try. I also used the openhab tutorial here, but it didn’t work for my variable, only when i put a number.

The while loop just breaks. It never executed.

See if this helps…

if (i >= reqclicks)

Also, you might want to try previousState(true). And be aware of this issue. I’m also not sure how the DSL reacts to the primitve boolean… you may want to use Boolean instead.

But if the rule was working, would it be retriggering itself? Does BionaireSpeed change after sending this?

Bionaire_TransmitCommand.sendCommand("Speed")

If you don’t increment the i in the loop, you will never get out of it!!

        while(flag) {
            Bionaire_TransmitCommand.sendCommand("Speed")
            Thread::sleep(1000)
            if (i=>reqclicks) {
                flag=false
            }
            i = i + 1 // <== YOU NEED THIS !!
         } // <==this one was missing!

Yes. However, the loop only executes until the if statement, then it crashes, even if i have the increment.

if (i >= reqclicks)

not =<

And change…

to…

var i = 1

Yes, missed that… :slight_smile:

After changing that, I get this in the log:

22:20:10.611 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Climate2.rules', using it anyway:
Assignment to final variable

I was also getting this before

To all: Is there another way than using the flag variable to exit the loop?
I.e. using a while loop like this (this doesn’t work either)

rule "Bionaire Speed"
    when
        Item BionaireSpeed changed
    then
        val int prevstate=(BionaireSpeed.previousState.state as DecimalType).$
        val int currentstate=(BionaireSpeed.state as DecimalType).intValue
        val int reqclicks=currentstate-prevstate
        if (reqclicks < 0)
        {
        reqclicks=6+reqclicks
        }
        val i=0
        while(i<reqclicks)
        {
        Bionaire_TransmitCommand.sendCommand("Speed")
        Thread::sleep(500)
        i=i+1
        }
end

The log shows this after using this code:

22:25:11.568 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Climate.rules', using it anyway:
Assignment to final variable
Assignment to final variable

This is because you didn’t change:

val i = 1

to

var i = 1

val defines a final variable, a bit like a constant, you CAN’T change it’s value
var defines a variable, you CAN change it’s value

Nope… didn’t work :frowning:

Log says this:

22:25:11.568 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Climate.rules', using it anyway:
Assignment to final variable

val is for a final variable (it’s not able to be changed). var is for a non-final variable (it can be changed). You will also need to change…

to…

var int reqclicks=currentstate-prevstate

rule "Bionaire Speed"
    when
        Item BionaireSpeed changed
    then
        val prevstate = BionaireSpeed.previousState.state as DecimalType
        val currentstate = BionaireSpeed.state as DecimalType
        var reqclicks = currentstate - prevstate
        if (reqclicks < 0) {
            reqclicks=6+reqclicks
        }
        var i = 1
        var boolean flag = true
        while(flag) {
            Bionaire_TransmitCommand.sendCommand("Speed")
            Thread::sleep(1000)
            if (i >= reqclicks) {
                flag=false
            }
            i = i + 1
        }
end

Thanks! That worked! :slight_smile:
Thanks on the really fast responses, everyone!

But now that it’s working, is it retriggering itself? Does BionaireSpeed change after sending this…

Bionaire_TransmitCommand.sendCommand(“Speed”)

… which would then trigger the rule again? If you’re not sure, you might want to add some logging. You could have 6 while loops running over themselves.

Now, did you understand your errors?
Difference between var and val?
Ending of while statement with }
And incrementing the test in the while loop?

This is the best way to learn is to make mistakes and correct them, but make sure that you understood what was wrong.

Good luck and happy coding