Loop of flashing light inside a timer

Hello,i would like some help as a beginner at scripts.I want to make a loop for flashing a light for 30 sec and then stop.I want to use the code inside rules for signaling ,for example when my door bell rings i need my xiaomi gateway’s light to blink for 30 seconds.I have tried using the “while” in a timer option but cant make it work…

I once posted some code to blink a light with Morse code. Loop rule (in OH2)

That’s old OH 1.x style Rules though so here is an updated version with how I would write it today.

String BlinkMessage
import java.util.concurrent.ConcurrentLinkedQueue

val Queue<String> blink = new ConcurrentLinkedQueue()
var Timer timer = null

val dotTime = 500      // stay on for 500 msec for a dot
val dashTime = 1500    // stay on for 1500 msec for a dash
val betweenTime = 1500 // 500 msec between symbols

rule "BlinkMessage received a command, blink the lights with the message in Morse Code"
when
    Item BlinkMessage received command
then
    val message = receivedCommand.toString

    // Convert the message to Morse Code and add it to the queue
    if(blink.isEmpty) blink.append(",")

    var int charIndex = 0
    while(charIndex < message.toString.length){
        val encoding = transform("MAP", "morse.map", ""+message.charAt(charIndex))

        var int encodingIndex = 0
        while(encodingIndex < encoding.length){
            blink.add(""+encoding.charAt(encodingIndex))
        }
        blink.add(",")
    }

    // Create a looping timer to start blinking the lights if one doesn't already exist

    // If there is a timer then the Queue is already being processed
    if(timer === null) {

        // Create a looping timer to blink the light
        timer = createTimer(now, [ |

            // get the next symbol from the Queue
            val symbol = blink.poll
            if(symbol !== null) {

                // Initialize what we want to do to the dash case
                var lightState = ON
                var rescheduleTime = dotTime

                // Modify the states if the symbol is - or ,
                switch(symbol) {
                    //case ".": defaults have this covered
                    case "-": rescheduleTime = dashTime
                    case "," {
                        lightState = OFF
                        rescheduleTime = betweenTime
                    }
                }

                // Set the light to the proper state (ON for dot or dash, OFF for ,) and reschedule the Timer
                // to process the next symbol after the defined amount of time.
                Light.sendCommand(lightState)
                timer.reschedule(now.plusMillis(rescheduleTime))
            }

            // no more symbols, let the Timer loop end
            else { timer = null }
        ])
    }
end

rule "Blink lights with morse code"
when
    Item AlarmSystem changed
then
    BlinkMessage.sendCommand("This is the Morse Code Message")
end

Obviously this is more complicated then you need. So here is a simpler version.

var Timer timer = null

rule "Blink the light for 30 seconds"
when
    // some trigger
then
    if(timer !== null) return; // if already blinking ignore this event

    // Create a timer to blink the light for 30 seconds
    val timeStarted = now
    timer = createTimer(now, [ | 
        Light.sendCommand(if(Light.state == ON) OFF else ON)
        if(now.isBefore(timeStarted.plusSeconds(30) timer.reschedule(now.plusSeconds(1))
        else timer = null
    ])
end
4 Likes

thanx for the answer .I get "2018-10-26 23:36:29.179 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘blink_purple.rules’ has errors, therefore ignoring it: [14,53]: mismatched input ‘timer’ expecting ‘)’ "
error .here is my rule

var Timer timer = null

rule "Blink the light for 30 seconds"
when
    Item doorbell_switch changed from OFF to ON
then
    if(timer !== null) return; // if already blinking ignore this event

    // Create a timer to blink the light for 30 seconds
    val timeStarted = now
    timer = createTimer(now, [ | 
        mihome_gateway_7811dcb24452_brightness.sendCommand(if(mihome_gateway_7811dcb24452_brightness.state == ON) OFF else ON)
		mihome_gateway_7811dcb24452_color.sendCommand("300,100,100")
        if(now.isBefore(timeStarted.plusSeconds(30) timer.reschedule(now.plusSeconds(1))
        else timer = null
    ])
end

Missing brackets:

        if (now.isBefore(timeStarted.plusSeconds(30))) timer.reschedule(now.plusSeconds(1))
2 Likes

Expanding on this, how would one be able to keep the flashing running until a switch or something is turned off?

Test for the switch and reschedule or not