Hello, I need to send sequences of IR commands using IRTrans binding.
Currently, I have only one item declared as: String IR_mRDC_Salon_command {irtrans="[192.168.0.2:21000:*:*:*]"}
Because of the asynchroneous nature of sendCommand(), how can I make sure that the IRTrans binding queues the commands in the right order?
I could use the item state update to manage my own command queue. But this would work if the state update occurs AFTER the command is processed by the hardware. Is this the case?
Hi, i have had a similar problem for my Media receiver with channel commands more than one digit…
I used Thread::Sleep to solve this
rule "T-Home Alexa Voice commands" when Item THOME_PRG_SELECT changed to 491 or Item THOME_ZDF_INFO received command ON then LR_THOME_DVR.sendCommand("4") Thread::sleep(2) LR_THOME_DVR.sendCommand("9") Thread::sleep(2) LR_THOME_DVR.sendCommand("1") Thread::sleep(2) LR_THOME_DVR.sendCommand("NumberEnter") end
Thread::sleeps are probably the way to go for this. If you are planning on issuing commands to your IR device from more than one Rule, I recommend Design Pattern: Gate Keeper to centralize the sending of the commands to the IR device so you only have one place where you need to add the Thread::sleeps or any other logic you may need to add.
import java.util.concurrent.locks.ReentrantLock
var lock = new ReentrantLock
rule "IR Controller"
when
Item IR_mRDC_Salon received command
then
lock.lock // Ensures only one instance of the Rule can run at a time
try {
val cmds = receivedCommand.split(" ")
cmds.forEach[cmd |
IR_mRDC_Salon_command.sendCommand(cmd)
Thread::sleep(10)
]
}
catch(Exception e) {
logError("IR", "Error handling IR command: " + e)
}
finally {
lock.unlock
}
end
By combining all the commands into one sendCommand it reduces the number of events in the system and guarantees that all those related commands get executed together and in order.
The lock prevents more than one instance of this Rule from running at a time. So if another command comes in while this on is running that new command has to wait until this one is done.
The Thread::sleep at the end of the for loop guarantees that there will always be that amount of time between commands to the IR device, even if the Rule gets triggered more than once at a time.
Great! Thank you!
I refined slightly the rule to allow providing repetition on IR codes: syntax is a space-separated string of
device,command[:repeat]
import java.util.concurrent.locks.ReentrantLock
var lock = new ReentrantLock
rule "IR Controller 2"
when
Item IR_mRDC_Salon_send received command
then
lock.lock // Ensures only one instance of the Rule can run at a time
try {
val String[] cmds_iters = receivedCommand.toString.split(" ")
cmds_iters.forEach[String cmd_it |
if(cmd_it.indexOf(":") == -1){
IR_mRDC_Salon_command.sendCommand(cmd_it)
Thread::sleep(5)
}
else{
val String[] strsplit = cmd_it.split(":")
val String cmd = strsplit.get(0)
val int nbiter = Integer.parseInt(strsplit.get(1))
for (var i = 1 ; i <= nbiter ; i++){
IR_mRDC_Salon_command.sendCommand(cmd)
Thread::sleep(5)
}
}
]
}
catch(Exception e) {
logError("IR", "Error handling IR command: " + e)
}
finally {
lock.unlock
}
end
That also made me discover the ‘Design pattern’ topics that will be helpful as I will migrate progressively all my automation scripts written in Python from Evenghost to openHAB.