How to create a simple loop?

Hey everyone,

I’m facing a small problem, when my alarm gets “triggered”. I’m trying to create a loop, where the sound keeps playing and my light keeps turning “ON” and "OFF - until the AlarmStatus.state == OFF

//Alarm

rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    if (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Gateway_SoundVolume, 20)
        sendCommand(Gateway_Sound, 1)
    } else {
        sendCommand(Gateway_Sound, 10000)
        sendCommand(Gateway_SoundVolume, 0)
    }
end

Currently I don’t have much, but the ITEM I use to turn the light ON and OFF is:

ITEM:
Garage_Spot

How do I set this Loop / While thing up correctly?

//Thanks

There are lots of options. Here is one approach, not the best but perhaps the simplist.

    while(AlarmStatus.state == ON && Hobbyroom_DoorSwitch.state == OPEN) {
        sendCommand(Gateway_SoundVolume, 20)
        sendCommand(Gateway_Sound, 1)
        Thread::sleep(10000) // ten seconds
    }
    sendCommand(Gateway_Sound, 10000)
    sendCommand(Gateway_SoundVolume, 0)

It is usually really bad to have sleeps so long but this is the simplest approach.

@rlkoshak

Thanks for the reply and sorry for my late response!

Yeah I read that you should only use sleep for a minimum of miliseconds.
The above while rule . if you had to make a spotlight turn on and off quickly, almost like a strobo, how would you then rewrite the rule (Just use “spot” as an example of the light)

Just use a shorter sleep and send command ON and OFF to your light Item.

@rlkoshak

Thanks man - much appreciated!

@rlkoshak

Hmm, have i missed anything here? Doesn’t seem to do what I was hoping for - nothing happens?

rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    while (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Garage_Spot(100)
        Thread::sleep(20)
    }
        sendCommand(Garage_Spot(0)
    }
end

That should turn on the light and then turn it off… quickly until I Disarm my Alarm Switch.

Also I will have to have the above in its own rule right? Because the rule with the Alarm Sound playing from my Xiaomi Gateway will be way longer that the sleep for the Light - otherwise it would just keep beeping shortly instead of playing the whole sound? Do you have any idea how I could rewrite it so it would be in only one rule?

rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Gateway_SoundVolume, 20)
        sendCommand(Gateway_Sound, 1)
    } else {
        sendCommand(Gateway_Sound, 10000)
        sendCommand(Gateway_SoundVolume, 0)
    }
end

Hello Yoinkz,

The sendCommand in “Hobbyroom Xiaomi Door Sensor” lines have some typos.

sendCommand(Garage_Spot(100)

Should be

sendCommand(Garage_Spot,100)

Same applies to “sendCommand(Garage_Spot(0)”. Additionally you have an extra closing curly brace (}) after the thread sleep command that should not be there.

Also it is worth mentioning that in OH 2.2 the thread sleep might cause some nasty issues (see more here).

PS: the sleep value is in milliseconds, which means for 1 second you should have a value of 1000.

@nepotu

Hi Nepotu,
Sorry about that - I was editing it from my Cell, so I didn’t write it correctly:

rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    while (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Garage_Spot,100)
        Thread::sleep(2000)
    }
        sendCommand(Garage_Spot,0)
    }
end

So far I haven’t had any issues with the Thread::sleep but thanks for the info. Do you have any other good ideas of how I could do it in another way?

Like I said above, there are lots of ways to implement this. Another approach would be to use Timers instead of the Thread sleep but that gets a little complicated:

Hey Guys,

I’m sorry I got away from this.
I tired changing whatever suggested, but I still can’t get it working.
Can someone take a quick look and tell me what I’ve done wrong?

//Alarm
rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    while (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Hobbyroom_LED1_switch,ON)
        //sendCommand(Gateway_SoundVolume, 20)
        //sendCommand(Gateway_Sound, 1)
        Thread::sleep(2000)
        sendCommand(Hobbyroom_LED1_switch,OFF)
    } else {
        sendCommand(Gateway_Sound, 10000)
        sendCommand(Gateway_SoundVolume, 0)
        sendCommand(Hobbyroom_LED1_switch,OFF)
    }
end

I just out-commented the part with the sound. Was playing with it last night and didn’t want to wake up the rest of the family :slight_smile:

Hi again Rich

Could you please explain why you are using thread sleep and not a timer like you normally recomend

Hey guys,

Please rewrite my above code with timers if that’s better. I want to implement with the best possible solution :slight_smile:

OP was asking for the simplest, not the best approach. Using Timers is significantly more complex. This was also written will over six months ago.

Were I to respond today I probably wouldn’t have even though it is simpler. And in this case the rule only waits when there is an alarm which will be rare and probably happen at times when not much else is going on in OH.

@Yoinkz, the problem is you can’t have an else without an if statement.

The loop continues while the condition is true then exits and the code starts executing after the closing curly bracket.

So I think all you need to do is drop the else part and you are good to go.

See Design Pattern: Looping Timers for how to convert this to a Timer based loop instead of a while loop.

1 Like

Thanks for the reply rich I was just wondering as I was thinking of trying too use a couple of loops if I can get the hang of them.

I had too edit the post I sent it too the wrong person

Once again - you are the man!

I don’t know why I didn’t catch that in the first post, but it now fires and I’m happy :slight_smile:.

Will try to look into the timer rule thing and see if I can get along with it.

Continuing the discussion from How to create a simple loop?:

Hi
Could you pls share the latest rule ?

@Infeus as mentioned by Rich just drop the else part.

rule "Hobbyroom Xiaomi Door Sensor"
when
    Item Hobbyroom_DoorSwitch_Status changed
then
    while (Hobbyroom_DoorSwitch_Status.state == OPEN && AlarmStatus.state == ON) {
        sendCommand(Hobbyroom_LED1_switch,ON)
        sendCommand(Gateway_SoundVolume, 20)
        sendCommand(Gateway_Sound, 1)
        Thread::sleep(2000)
        sendCommand(Hobbyroom_LED1_switch,OFF)
    } 
end

Thanks a lot