I have written a rule for my Garage Door with two buttons, one for opening and one to close it, which openhab apparently cannot parse sucessfully, I do not receive any error it just takes forever and I have to restart openhab.
Using openhab 2.2 on raspian.
import java.util.concurrent.locks.ReentrantLock
var ReentrantLock lock = new ReentrantLock
val long Garagentor_TransitionTime = 15000
var DateTime Garagentor_TransitionStart = null
var Timer Garagentor_TransitionTimer = null
var long Garagentor_TransitionTime_adjusted = 15000 //If I use Garagentor_TransitionTime here the variable cannot be used later in the code, any suggestion why?
rule "Garagentor open"
when
Item Garagentor_open changed to ON
then
lock.lock
if(Garagentor_TransitionTimer !== null){
NS_Garage_4.sendCommand(ON)
//VITAL PART - AS SOON AS I ADD THIS THE WHOLE THING STOPS WORKING
Garagentor_TransitionTime_adjusted = Garagentor_TransitionTime - (Garagentor_TransitionTime_adjusted - (now.millis - Garagentor_TransitionStart.millis))
//################
if(CT_Garagentor == OPEN){
CT_Garagentor.postUpdate(CLOSED)
}else{
CT_Garagentor.postUpdate(OPEN)
}
}else if(CT_Garagentor == CLOSED){
NS_Garage_4.sendCommand(ON)
Garagentor_TransitionStart = now
Garagentor_TransitionTimer = createTimer(now.plus(Garagentor_TransitionTime_adjusted), [|
CT_Garagentor.postUpdate(OPEN)
])
}
Thread::sleep(1000)
lock.unlock
end
rule "Garagentor close"
when
Item Garagentor_close changed to ON
then
lock.lock
if(Garagentor_TransitionTimer !== null){
NS_Garage_4.sendCommand(ON)
//VITAL PART - AS SOON AS I ADD THIS THE WHOLE THING STOPS WORKING
Garagentor_TransitionTime_adjusted = Garagentor_TransitionTime - (Garagentor_TransitionTime_adjusted - (now.millis - Garagentor_TransitionStart.millis))
//################
if(CT_Garagentor == CLOSED)CT_Garagentor.postUpdate(OPEN)
else CT_Garagentor.postUpdate(CLOSED)
}else if(CT_Garagentor == OPEN){
NS_Garage_4.sendCommand(ON)
Garagentor_TransitionStart = now
Garagentor_TransitionTimer = createTimer(now.plus(Garagentor_TransitionTime_adjusted), [|
CT_Garagentor.postUpdate(CLOSED)
])
}
Thread::sleep(1000)
lock.unlock
end
rule "Garagentor Contact"
when
Item CT_Garagentor changed
then
Garagentor_TransitionStart = null
Garagentor_TransitionTimer?.cancel()
Garagentor_TransitionTimer = null
Garagentor_TransitionTime_adjusted = Garagentor_TransitionTime
end
rule "NS_Garage_4 off"
when
Item NS_Garage_4 changed to ON
then
Thread::sleep(1000)
NS_Garage_4.sendCommand(OFF)
end
I’m laboring on this for hour now but narrowing the error down to this particular line is all I could achieve.
Always put a lock inside try/catch/finally. If you have an error in the middle of the locked section, your Rule will never execute again until you restart OH because the lock never gets unlocked.
Post errors that appear in the logs
Using locks and Thread::sleeps is a recipe for problems as well. It increases the likelihood that you will run out of Rules execution threads.
What are you using Garagentor_TransitionTime for? What are you using CT_Garagentor for?
now.plus(Garagentor_TransitionTime_adjusted) should probably be now.plusMillis
It is really hard to tell but it seems to me you are trying to get the proper labels and icons on your sitemap based on the state of the garage door. You can do this much more simply. Here is how I do it:
Items
Switch aGarageOpener1 "Garage Door Opener 1"
String GarageOpener1_Cmd
Contact vGarageOpener1 "Garage Door Opener 1 is [MAP(en.map):%s]"
<garagedoor> (gDoorSensors,gDoorCounts)
aGarageOpener1 is a proxy Item that I use to trigger my Rule and to show on the sitemap. GarageOpener1_Cmd is the Item that actually sends the command to the opener. vGarageOpener1 is a reed sensor on the door that tells me when it is open.
Rules
val logName = "entry"
rule "A Garage Opener was triggered"
when
Item aGarageOpener1 received command
then
GarageOpener1_Cmd.sendCommand(ON)
logInfo(logName, "Garage Opener 1 was triggered.")
// send an alert if the garage controller is offline
if(vNetwork_Cerberos.state == OFF) {
aAlert.sendCommand("Attempting to trigger a garage opener but the controller is offline!")
}
end
Now clearly your setup will have to be a little different because you have two buttons, not just one, but again, I would ask why? It seems to add a bunch of extra complexity. Can you explain why you are approaching this like this?
First of all, thank you very much for your suggestions, especially for the sitemap.
By now I know I’ll have to rethink my rules for this door.
I just want to clarify why I felt it was necessary to add all that complexity
First, I don’t actually have a Door Contact (CT_Garagentor) so it is a virtual Contact that has to be updated after a predefined time and has to be recalculated whenever the action is stopped midway or (2/3 ways or whatever)
Second, I like explicit open/close buttons on my remote and I want that open-button to still be able to stop the door while it’s opening but not to trigger the subsequent close action.
Hope I’ve been more clear of my intentions this time.
I don’t know if I actually need all this but still it should be achievable.
That makes sense and is not clear from just the code posted.
Be aware though that based on what I’ve seen posted on this forum for roller shutters, this approach is not very reliable.
Does your opener actually support that?
Anyway, this is still easily achievable with a single Switch Item.
Item
Switch GarageOpener
Sitemap
rule "Garage triggered"
when
Item GarageOpener received command
then
// Garage OPEN pressed
if(receivedCommand == ON) {
// do open stuff
}
else {
// do close stuff
}
end
I don’t have time to help with the timing calculations but based on your descriptions of the problem, I’m all but positive was a combination of the locks and the Timers and not related to the calculations.