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