If/Else in a rule does.. both?!

  • Platform information:
    • OS: Ubuntu Linux, 18.04.2 LTS
    • OpenJDK 10.0.2, runtime 10.0.2+13
    • OpenHAB 2

I’m a pretty experienced programmer (Python, BASH), so I’m either mixing languages or, having been coding for the last two days, might well have lost it… but here’s what I’m seeing and I’d sure be grateful for another pair of eyes…

I’ve written a Python program to telnet into an Ademco 20p and parse the stream for status. The switches it effects are in good shape and work consistently. The idea behind this code is that when it just detects presence - I’ve just arrived home, JustArrived.state == ON - there’s no point in telling me the front door is open because I will have just opened it. If however I’ve been home a while (JustArrived.state == OFF && groupPresence.state == ON) then if the front door opens let me know. If I’m not home and have been away for a while, send me a chat message via XMPP.


rule "alarm front door"
when
        Item AlarmFrontDoor changed from ON to OFF
then
        logInfo("AlarmStatus-arr-rule", "WTF.state="+JustArrived.state)

        if ((JustArrived.state == OFF) || (JustArrived.state == NULL)) {
                if (groupPresence.state == ON) {
                        say("The front door is open", "pollytts:Salli", "enhancedjavasound")
                } else {
                        sendXMPP("username1@email.com", "The front door has been opened!")
                        sendXMPP("username2@email.com", "The front door has been opened!")
                }
        } else {
                 logInfo("AlarmStatus-arr-rule", "justarrived home: "+JustArrived.state)
        }
end

What actually happens though, as you’ll see in the logs, is that it’ll do both: when I’ve just arrived home, it’ll tell me the door is open AND log “justarrived home” . The following logs show checkpoints showing status of the switches.

2019-02-24 13:45:22.619 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'User has arrived home' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]

2019-02-24 13:45:33.410 [INFO ] [me.model.script.AlarmStatus-arr-rule] - WTF.state=ON
2019-02-24 13:45:33.411 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Synthesize 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050
]
2019-02-24 13:45:33.412 [DEBUG] [ce.pollytts.internal.PollyTTSService] - voice UID: 'pollytts:Salli' voice label: 'Salli' voice Locale: en_US
2019-02-24 13:45:33.413 [INFO ] [me.model.script.AlarmStatus-arr-rule] - justarrived home: ON
2019-02-24 13:45:33.413 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]

As you see from the WTF.state, the switch is ON so ==OFF OR ==NULL should not be satisfied and it should only log “justarrived home:”, but it does both tell me the door is open AND log…? It does not, however, both tell me AND send an XMPP text… so ELSE works… sometimes.

I’ve refactored this code in three different ways… I don’t know what the deal is.
Anybody…? :expressionless:

That’s not the rule you have shown us, issuing that logInfo.

I’d suspect you may now have multiple versions of the rule in service. Editing a rule and changing its name (which the system uses as a key) can in some circumstances leave a ghost old version in place.
Try a reboot and see what problems are left.

See line five - that’s the log for that rule alright.

I’ve actually deleted the surrounding rules and grepp’d strings via console out of the entire ./rules/* folder - not a dupe.

Given JustArrived is a switch, a simpler way would be

if(JustArrived.state != ON)  // could be OFF or NULL

but of course the boolean or should work.

Is there any other rule that switches JustArrived ON or OFF?

Hi there - that was in one of my refactors, I thought I’d specify OFF/NULL in the last try - same result I’m afraid.

Yes, JustArrived is on a timer, here’s what sets it (it’s in the same .rules file as the problematic code, above):

rule "home announce"
when
        Item Phone_Online changed from OFF to ON
then
        JustArrived.state = ON
        createTimer(now.plusMinutes(15)) [|sendCommand(JustArrived ,OFF)]
end

I tried the newer timer method but couldn’t get it to work, so I used this older one and it works more consistently.

You’re right. Doesn’t rule out the lingering ghost rule if you’ve edited a rule name.

Hang on … is JustArrived a variable or an Item?

1 Like

JustArrived.postUpdate(ON)

I’m sure grateful for the conversation everyone - great start.

@vzorglub - interesting distinction, I hadn’t tried postUpdate(ON), but unfortunately it has the same result : when I set the following:

JustArrived.postUpdate(ON)
createTimer(now.plusMinutes(15)) [|sendCommand(JustArrived ,OFF)]

I still get both responses:

2019-02-24 18:42:53.461 [INFO ] [me.model.script.AlarmStatus-arr-rule] - WTF.state=ON
2019-02-24 18:42:53.461 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Synthesize 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-24 18:42:53.461 [DEBUG] [ce.pollytts.internal.PollyTTSService] - voice UID: 'pollytts:Salli' voice label: 'Salli' voice Locale: en_US
2019-02-24 18:42:53.462 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-24 18:42:53.463 [INFO ] [me.model.script.AlarmStatus-arr-rule] - justarrived home: ON

@rossko57 - I’m not finding a ghost or overriding rule if I search /etc/openhab2/* .
Good thought, that isn’t a variable, it is an item; I’ve been calling it a variable because I’ve been effectively using it that way, sorry. I’ve defined it as:

Switch JustArrived

Whether a variable or an Item, isn’t ON… on?

Nope. A variable of any usual type won’t have a .state method, and if it did it’s probably not going to accept an OnOffType. However …

I’ve just had a play, and remarkably
someSwitch.state = ON
gives every appearance of working without error. Right down to state change getting logged in events.log, and subsequent postUpdate or sendCommand appear functional, the .state.toString method works, and the state evaluates as expected in if().
I do not think this is supposed to happen!!
I worry this has “damaged” the Item object in some way, but cannot identify any issue.

May we see events.log that goes with a run of your rule, in case the timer is somehow executing immediately.

My “ghost rule” is about having a rule called “fred”, editing it to rule “mary”, and system missing the ‘deletion’ of “fred” from memory. You wouldn’t find it with searching files.
I’m still recommending a reboot if you have fixed the postUpdate too.

The true test whether that worked or not would be to see if you can trigger a Rule on the event. What type of event gets logged in events.log?

And if you can trigger the Rule that way, does the Item reflect the correct state in the triggered Rule?

@rossko57 : Re: variable/item – okay, makes sense. Now that I research that, I now recall that the reason I made it an item is so that it would show up on the sitemap as a Switch, which I didn’t think I could do with a variable local to that .rules file.

Here are the contents from the events.log:

2019-02-24 22:38:54.838 [vent.ItemStateChangedEvent] - Phone_Online changed from OFF to ON

2019-02-24 22:38:54.838 [vent.ItemStateChangedEvent] - Phone_Latency changed from UNDEF to 0.0

2019-02-24 22:38:54.841 [vent.ItemStateChangedEvent] - JustArrived changed from OFF to ON

2019-02-24 22:39:17.896 [vent.ItemStateChangedEvent] - AlarmFrontDoor changed from ON to OFF

2019-02-24 22:39:21.555 [ome.event.ItemCommandEvent] - Item 'AlarmFrontDoor' received command ON

2019-02-24 22:39:21.556 [vent.ItemStateChangedEvent] - AlarmFrontDoor changed from OFF to ON

They’re not from the same time, I just generated them but it’s the same rule and results in openhab.log as well.

@rikoshak - yes, it’s very triggerable. I can twiddle it via Sitemap and it shows correctly when I turn the wireless on my phone on and off to simulate arrival; as soon as it sees it it switches ON (per the logs, they all line up) and the sitemap’s updated.

I’m glad I"m not the only one scratching my head of this one, thought I was loosing it.
I mean, I may be yet, but…

Could this be a bug in the rules interpreter?

Yes, but those will all be doing the “correct” thing with respect to the OH Item.
Rik and I were rambling about assignment myItem.state=ON, which is a bad thing to do and shouldn’t work really.
Providing you have fixed that in your rule by using the correct postUpdate form, this part has become a sideshow for you.
(I’m going to pick at this more and expect to raise an issue.)

I’m still recommending a openHAB reboot in case it has caused weirdness. After all, it is a bit of a coincidence to do something “wrong” to an Item - and then have trouble with same Item in another rule.

It won’t be a bug in if-else.
Try -

    rule "alarm front door"
    when
            Item AlarmFrontDoor changed from ON to OFF
    then
            logInfo("AlarmStatus-arr-rule", "WTF.state="+JustArrived.state)
               // individual diagnostic tests
            if (JustArrived.state == ON ) }
               logInfo("AlarmStatus-arr-rule", "test ON "+JustArrived.state.toString)
            } else {
               logInfo("AlarmStatus-arr-rule", "else-ON "+JustArrived.state.toString)
            }
            if (JustArrived.state != ON ) }
               logInfo("AlarmStatus-arr-rule", "test not-ON "+JustArrived.state.toString)
            } else {
               logInfo("AlarmStatus-arr-rule", "else not-ON "+JustArrived.state.toString)
            }

...   // rest of your rule

Sorry, I knew I missed something - I have rebooted a couple times after restarting the service after thinking that indeed there may be some artifact in memory. Everything shown here is well post-reboot.

I have updated the code to JustArrived.postUpdate(ON) - both that and JustArrived.state = ON work the same way (which I understand isn’t intended), and the if/else still doesn’t work, effectively else doesn’t exist.

If it’s not a bug in the if/else processing, why does it ignore else in this context? Please note, it’s repeatable across all my alarm zones, I’m just showing you the front door. They all (don’t) work the same way.

Check this out:

rule "alarm front door"
when
        Item AlarmFrontDoor changed from ON to OFF
then
        logInfo("AlarmStatus-arr-rule", "running...")

        if ((1 == 1) || (2 == 2)) {
                if ( 1 == 1) {
                        say("The front door is open", "pollytts:Salli", "enhancedjavasound")
                } else {
                        sendXMPP("email1@email.com", "The front door has been opened!")
                        sendXMPP("email2@email.com", "The front door has been opened!")
                }
        } else {
                 logInfo("AlarmStatus-arr-rule", "justarrived home: "+JustArrived.state)
        }
end

and this does NOT have the same behavior, showing it’s absolutely a matter of variable/Item type and use.

The logs are : Event.log :

2019-02-25 09:19:11.966 [ome.event.ItemCommandEvent] - Item 'AlarmFrontDoor' received command OFF
2019-02-25 09:19:11.967 [vent.ItemStateChangedEvent] - AlarmFrontDoor changed from ON to OFF

openhab.log:

2019-02-25 09:19:11.967 [INFO ] [me.model.script.AlarmStatus-arr-rule] - running...
2019-02-25 09:19:11.968 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Synthesize 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-25 09:19:11.968 [DEBUG] [ce.pollytts.internal.PollyTTSService] - voice UID: 'pollytts:Salli' voice label: 'Salli' voice Locale: en_US
2019-02-25 09:19:11.968 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Synthesize 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-25 09:19:11.968 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-25 09:19:11.968 [DEBUG] [ce.pollytts.internal.PollyTTSService] - voice UID: 'pollytts:Salli' voice label: 'Salli' voice Locale: en_US
2019-02-25 09:19:11.969 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]

So, else clearly works, there’s definitely something in the way JustArrived is set or used.

Okay… so where to from here?

  • It’s an item, not a variable (thank you for the clarification)
  • The item is on a timer,
  • I set it with JustArrived.state = ON and JustArrived.postUpdate(ON) , but they both have the same unintended effect.

Is it something local to the IF statement, should the item be used differently or should I use a variable? If I use a variable, can that be used as a Switch in the sitemap?

This is correct.

My comment was more directed at rossko57 dealing with the behavior he saw when he used = instead of postUpdate. This is new behavior I’ve not seen before and wanted some more details.

:+1 Though, if this were a deliberate change, the issue may be to the docs. :wink:

The problem is definitely inexplicable. The only way it can be executing the if and the else is if there are two copies of the Rule running somehow. But the logs do not indicated that.

openhab.log appears to show two (probably non-identical) copies of your rule running simultaneously now? The voice stuff is double logged.

Items may be created from xxx.items files or from PaperUI. It’s possible to attempt to create multiple Items with the same name; so far as I know it cannot actually do that and only one “wins”.
But we’ve had surprises already, maybe check.

Proof of pudding, change the name of your misbehaving Item, and the references to it in both rules. If there are mislaid references to it elsewhere, they’ll be stuck on the old name.

Off-topic now, but having discovered that stringItem.state = "xx" fails and contactItem.state = OPEN appears to work, obviously something is amiss. So I opened

1 Like

Time for me to take a business trip, I’ll be slow to respond with results. Still, thank you both for the help - I’ll keep looking for duplicate item names and rules.

I had to know, I’m messing with it before packing…

I’ve changed the item name - same results:

2019-02-25 21:48:11.704 [INFO ] [me.model.script.AlarmStatus-arr-rule] - WTF.state=ON
2019-02-25 21:48:11.705 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Synthesize 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-25 21:48:11.705 [DEBUG] [ce.pollytts.internal.PollyTTSService] - voice UID: 'pollytts:Salli' voice label: 'Salli' voice Locale: en_US
2019-02-25 21:48:11.706 [DEBUG] [ce.pollytts.internal.PollyTTSService] - Audio Stream for 'The front door is open' in format AudioFormat [codec=MP3, container=NONE, bitDepth=16, bitRate=64000, frequency=22050]
2019-02-25 21:48:11.706 [INFO ] [me.model.script.AlarmStatus-arr-rule] - justarrived home: ON

I can’t explain the duplicate in my previous logs, I theorize it went off twice, perhaps while testing I closed the door and reopened it in a short time window, I don’t know… it’s not like that in any of the other instances, that was unique.

It’s still showing executing both, logging “WTF.state” as well as “justarrived home:”.

Given that it’s an issue with how the item is set, called or referenced - how am I supposed to be doing it, how can I call it so that it works as expected?

Stuff like that certainly happens. And we all overlook how it might affect our rules.
It rang an alarm because that is one way to get parts of your overall weirdness - if the state changes during multiple runs of the rule.

For my curiosity; given the snappy rules response - you’re running on a box with more horsepower than a Pi ?

Going back to basics, and given an Item/variable debate … where have you defined , which file?
Switch JustArrived

Please can we try this variation on your rule, for elimination

// place at top of file
var Number diagcount = 0

rule "alarm front door"
when
        Item AlarmFrontDoor changed from ON to OFF
then
        diagcount = diagcount + 1
        logInfo("test", " rule entry " + diagcount.toString
        logInfo("AlarmStatus-arr-rule", "WTF item dump {}", JustArrived)

        if (JustArrived.state != ON) {
                if (groupPresence.state == ON) {
                        say("The front door is open", "pollytts:Salli", "enhancedjavasound")
                } else {
                        logInfo("AlarmStatus-arr-rule", "the XMPP else-stuff")
                        sendXMPP("username1@email.com", "The front door has been opened!")
                        sendXMPP("username2@email.com", "The front door has been opened!")
                }
        } else {
                 logInfo("AlarmStatus-arr-rule", "justarrived home: " + JustArrived.state.toString)
        }
        logInfo("test", " rule exit " + diagcount.toString
        diagcount = diagcount - 1
end