Variables in rules

Hi
I am quiet new to OH and I have some Shelly Things running, also a Doorswitch. My first rule should send me a message, when the door is opened longer than 30secs. In a second rule, I should get a message when the door is shut after it was opened longer than 30secs.
I am trying to save this information in Boolean variable “doorwasopen” after sending the first message.
The first rule works fine and I get the message. The second rule only works, when I remove this part: “&& doorwasopen == true”…so it seems something is wrong with this && syntax or with the variable…any ideas? Sorry I have no logs since I don’t know yet where to find them :confused:

It would be nice if someone had an idea.
Thanks
Michael

var Timer timer = null
var boolean doorwasopen

rule “Door EG open for 30s”
when
Item Switch_Door_EG changed to OPEN
then
timer = createTimer(now.plusSeconds(30)) [
if (Switch_Door_EG.state == OPEN) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre 30s offen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
}]
timer = null
doorwasopen = true
end

rule “Door EG closed for 10s”
when
Item Switch_Door_EG changed to CLOSED
then
timer = createTimer(now.plusSeconds(5)) [
if (Switch_Door_EG.state == CLOSED && doorwasopen == true) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre wurde geschlossen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
}]
timer = null
doorwasopen = false
end

Try using logging to help with your understanding of what is going on in each section of your code

So in this rule add

rule “Door EG closed for 10s”
when
Item Switch_Door_EG changed to CLOSED
then

  logInfo("BLAH" , doorwasopen)

timer = createTimer(now.plusSeconds(5)) [
if (Switch_Door_EG.state == OPEN && doorwasopen == true) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre wurde geschlossen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
}]
timer = null
doorwasopen = false
end

Then check that value in the logs

Thank you, I’ll try this and comment again here! Happy new year :partying_face:

17:07:47.261 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule ‘Door EG closed for 10s’: An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.LogAction.logInfo(java.lang.String,java.lang.String,java.lang.Object[]) on instance: null

this doesn’t mean so much to me…

Can you pleas post your whole rules file using code fences.

logInfo() requires two strings, your variable doorwasopen is a boolean, not a string.
I think this variant will work, never too sure with booleans
logInfo("test", "value {}", doorwasopen)
The {} should expand to text the object that you specify third.

I’ll try this, thanks!

let me try rossko57s hint…

Whilst your first rule sends the message after 30 seconds it sets doorwasopen=true no matter what period the door was open. If you want doorwasopen to be set true only if the door was open for at least 30 seconds then you need to move the doorwasopen=true to within the code block executed by the timer.

In your second rule “Door EG closed for 10s” the test if (Switch_Door_EG.state == OPEN && doorwasopen == true) will only ever evaluate true if the door has been re-opened before the timer expires and remains until it expires. This is because it requires Switch_Door_EG.state to be OPEN and doorwasopen to be true in order to evaluate as true and post the message. The only way this can happen is if the door is re-opened within 5 seconds of being closed and remains open until the timer expires, otherwise Switch_Door_EG.state will be CLOSED and doorwasopen false as you set doorwasopen to false as soon as the door is closed. To achieve what I beleive you require in the second rule you should move doorwasopen = false to within the code block invoked by the timer and remove Switch_Door_EG.state == OPEN && from the if statement. Although there is still a problem with this in so far as if the door is opened and closed before the 30 seconds are up (eg only open for 5 seconds) and then opened again just before the the timer expires it will still send the message that the door was open for 30 seconds, it will also set a second timer running.

Given the above I believe that in order to achive what I think you want your code should updated to the following:

var Timer dooropentimer = null
var boolean doorwasopen

rule “Door EG open for 30s”
when
Item Switch_Door_EG changed to OPEN
then
dooropentimer = createTimer(now.plusSeconds(30)) [
if (Switch_Door_EG.state == OPEN) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre 30s offen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = true
}]

end

rule “Door EG closed for 10s”
when
Item Switch_Door_EG changed to CLOSED
then
if(dooropentimer !== null){
dooropentimer.cancel()
dooropentimer = null
doorwasopen=false
}
if (doorwasopen == true) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre wurde geschlossen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = false
}

end

hope this helps

this I understand…(to be honest, I think I don’t really understand the timer thing here…I miss sleep(30) from Python :neutral_face:)

Oh my god here I had a typo…Switch_Door_EG.state == CLOSED && doorwasopen == true is right…was a copy-paste mistake during deleting my API und user account details, don’t ask :see_no_evil:

From this point of view…shouldn’t it work fine?

Anyway, I’ll try your code and come back, thank you!

createTimer initiates an asynchronus process which executes the required code after the specified time period. Meanwhile any code following the createTimer statement is executed immediately.

It might work fine most of the time, however as I pointed out if you have the situation:

Door opens and closes before 30 seconds up. So Switch_Door_EG.state from CLOSED to OPEN to CLOSED say within a 5 second period
Door opens again 2 seconds before door open timer expires so Switch_Door_EG.state goes from CLOSED to OPEN and closes 3 seconds later when Switch_Door_EG.state goes from OPEN to CLOSED

You will report the door as being open for 30 seconds even though in fact it opened twice each for 5 seconds each time.

This may of may not be acceptable to you

So I tried it, but the effect is the same; I only get the message that the door was open for more than 30secs, but when I close it then I don’t get a message…I controlled the typo, there’s everything ok…

Did you move the doorwasopen=false into the timer code block? If not it will always fail to send a message as the createTimer function creates an asynchronous process and the rest of your rule will be executed before the timer code is executed. Thus, because doorwasopen=false is currently outside the timer code block it will ensure that, unless the door is reopened, doorwasopen will always be false when the timer code block is executed.

now with code fences…

var Timer dooropentimer = null var boolean doorwasopen

rule “Door EG open for 30s”
when
Item Switch_Door_EG changed to OPEN
then
dooropentimer = createTimer(now.plusSeconds(3)) [
if (Switch_Door_EG.state == OPEN) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre 30s offen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = true
}]
end

rule “Door EG closed for 10s”
when
Item Switch_Door_EG changed to CLOSED
then
if (dooropentimer !== null){
dooropentimer.cancel()
dooropentimer = null
doorwasopen = false
}
if (doorwasopen == true) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre wurde geschlossen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = false
}
end

yes I did

Can you re-post your rules they now stand and I will take another look at them.

this is it:

var Timer dooropentimer = null var boolean doorwasopen

rule “Door EG open for 30s”
when
Item Switch_Door_EG changed to OPEN
then
dooropentimer = createTimer(now.plusSeconds(3)) [
if (Switch_Door_EG.state == OPEN) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre 30s offen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = true
}]
end

rule “Door EG closed for 10s”
when
Item Switch_Door_EG changed to CLOSED
then
if (dooropentimer !== null){
dooropentimer.cancel()
dooropentimer = null
doorwasopen = false
}
if (doorwasopen == true) {
sendPushoverMessage(pushoverBuilder(“Eingangstüre wurde geschlossen”).withApiKey(“abc”).withUser(“abc”).withDevice(“Michaels_iPhone”).withTitle(“Gerhards Home”))
doorwasopen = false
}
end

the LOG shows, that the switch is working properly:
20:32:39.587 [INFO ] [smarthome.event.ItemStateChangedEvent] - Switch_Door_EG changed from CLOSED to OPEN
20:33:03.338 [INFO ] [smarthome.event.ItemStateChangedEvent] - Switch_Door_EG changed from OPEN to CLOSED

you see I get only the open message, not the close one…and yes, at this cold we close the doors :wink:

Thank you for your kind help!

I think I’ve spotted what needs to be done.

In the rule 1 timer code block add the line:

doorsopentimer = null

Before/after the line:

doorwasopen = false

This will ensure that in rule 2 the 1st if test is false and allow the message to be posted

amazing, that was it! Thank you very much for your time and patience for and with me :blush:

No problem, glad to help

1 Like