Counter with minutes and seconds

I try to realize a counter which displays the minutes and the seconds in the sitemap.
The counter runs but it displays the minutes with always 30 and the seconds with always 0.
I used a “while” cycle within a “while” cycle. Probably the mistake is within this. But I can’t find the failure.
Has anyone an idea whats going wrong?

rule "Heizung_Bad_ausschalten"
when
    Item heizung_1 received command ON 
then
var Number z
var Number x
var i = -1
var l = 0
  schleife_heizung_min.postUpdate(30) 
while ((i=i+1) < 31) {        // 30 Minuten
    while ((l=l+1) < 61) {    
        Thread::sleep(6000)  // 1 Minute:  1 x 60 x 1000
        if (heizung_1.state == OFF) {
            i = 30
            l = 60
            x=60-l
            schleife_heizung_sec.postUpdate(x)
            }
        }
 z=30-i        
  schleife_heizung_min.postUpdate(z) 
}
    sendCommand(heizung_1, OFF)    
end

This is the same as x = 0. Not sure what you try to do here?

First: Thread::sleep(6000) is 6 seconds. This may be a Typo in your rule.
Second: the if-clause is to reset the timer, right? You should set the curly bracket at the right place, so

if (heizung_1.state == OFF) {
    i = 30
    l = 60
}
x=60-l
schleife_heizung_sec.postUpdate(x)

but there is another problem, that has nothing to do with the rule itself. The UI won’t update every second :slight_smile:

So, simplest way would be to countdown only minutes, and don’t do it with a Thread::sleep, you would start the thread itself for 30 Minutes, better use timers:

var Timer myTimer = null
var int myMinutes = 30

rule "switch off bath heating"
when
    Item heizung_1 received command
then
    if (receivedCommand == ON) {
        if (myTimer==null || myTimer.hasTerminated)
            myTimer = createTimer(now.plusMinutes(1), [|
                myMinutes = myMinutes - 1
                if (myMinutes > 0) {
                    myTimer.reschedule(now.plusMinutes(1))
                    schleife_heizung_min.postUpdate(myMinutes)
                }
                else
                    heizung_1.sendCommand(OFF)
                ]
            )
    }
    else
        myTimer.cancel
        myTimer = null
        myMinutes = 30
        schleife_heizung_min.postUpdate(0)
end

This will create a timer, which will fire after 60 seconds. The timer will restart itself and count down to zero.

Hey Udo,

thank you for this rather great support.
I tried to avoid a timer as I had in the past exact with this rule some problems with the timer. But you are right, a time is much better and I will use your code.

Only for information. Here my complete code. It shows each minute and second in the UI. Sometimes a second is missing, but it runs.

rule "Heizung_Bad_ausschalten"
when
    Item heizung_1 received command ON 
then
var Number z
var Number x
var i = 0

  schleife_heizung_min.postUpdate(30) 
while ((i=i+1) < 31) {        // 30 Minuten
var l = 0
    while ((l=l+1) < 61) {    
        Thread::sleep(100)     // 1 Minute
        if (heizung_1.state == OFF) {
            i = 30
            l = 60
            }
            x=60-l
            schleife_heizung_sec.postUpdate(x)            
        }
 z=30-i        
  schleife_heizung_min.postUpdate(z)      
}
    sendCommand(heizung_1, OFF)    
end