That is because you didn’t use code fencing, you used quotes.
```
code goes here
```
One thing I will note is that any sleep of more than a few hundred milliseconds can cause problems in the long run because it ties up a Rule execution thread. This Thread ties up an execution thread for 11 seconds at a minimum, potentially and likely longer. If you have sleeps in other rules that are executing at this same time you can bring your OH to a halt as it runs out of Rule execution threads. Given this is an error case, that may not matter. But if it does, you would have to use Timers. Obviously, this makes it much more complex.
Note, I’m just typing this in, there are likely errors. Here is an attempt at a generic morse code set of rules and lambdas. I’m mainly doing this because of the challenge. I’m not sure I would recommend it as a valid approach.
import org.eclipse.xtext.xbase.lib.Functions
import org.eclipse.xtext.xbase.lib.Procedures
// Convert a String to Morse code with characters separated by commas
val Functions$Function1<String, String> toMorse = [message |
val StringBuilder morse = new StringBuilder()
var int charIndex = 0
while(charIndex < message.length){
morse.append(transform("MAP", "morse.map", ""+message.charAt(charIndex))
morse.append(",")
}
morse.toString
]
val Procedures$Procedure4<String, Map<SwitchItem, String, Integer, Procedures$Procedure3> blinkMorse = [ light, message, index, recurse |
// If the Alarm is OPEN, continue the message, otherwise the blinking will stop
if(AlarmSystem.state == OPEN) {
// reset the index to resend the message
if(index >= message.length) index = 0
// Initialize values for a dot
var int onTime = 500 // stay on 500 msec for a dot
var int offTime = 500 // stay off for 500 msec between morse symbols
var lightState = ON
switch(message.charAt[index]) {
// case '.': // do nothing, defaults are already set for dot
case '-': onTime = 1500 // stay on for 1500 for a dash
case ',': {
lightState = OFF
onTime = 500
offTime = 500 // 500 msec from sleep after turning off light + onTime + offTime means a rest of 1500
}
}
// Turn ON/OFF the light
light.sendCommand(lightState)
// Turn OFF the line after onTime msecs
createTimer(now.plusMillis(onTime), [|
light.sendCommand(OFF)
// sleep for half a second before processing the next character
createTimer(now.plusMillis(500), [| recurse.apply(light, message, index+1, recurse)]
])
}
]
rule "Blink lights with morse code"
when
Item AlarmSystem changed
then
// Blink morse code
if(AlarmSystem.state == OPEN) {
val morse = toMorse.apply("SOS")
blinkMorse.apply(Node3_CtrDiningRoom_Dimmer, morse, 0, blinkMorse)
}
end
morse.map
A=.-
a=.-
B=-...
b=-...
C=-.-.
c=-.-.
// and so on
Theory of operation:
We use morse.map to map the letters to their Morse code equivalent represented with . and -.
When the AlarmSystem changes to OPEN we convert the String “SOS” to Morse with a comma, separating the characters.
Then we kick off the recursive timer procedure to start blinking the light. Note that we pass blinkMorse to itself. This lets us recursively call the procedure.
In the procedure we see if the AlarmSystem is still OPEN. If it is not the recursion ends and the lights blinking stops. It should end with the light in the OFF state.
If the AlarmSystem is OPEN, then we process the next character in the morse message. We keep track of what symbol in the message we are on using the index variable. When we get to the end of the Morse message we reset the index to zero so we can send the message again. Next, we initialize some variables with the on and off times and whether to turn ON or OFF the light. Then we turn ON/OFF the light, set a Timer for as long as the light should stay ON, when the Timer executes we turn off the light and recursively call the procedure with an incremented index to process the next symbol.
Not bad for around 60 lines of code and 64 some lines in a map file. Assuming this works.